|
|
1f5a365 |
# HG changeset patch
|
|
|
1f5a365 |
# User Mateusz Kwapich <mitrandir@fb.com>
|
|
|
1f5a365 |
# Date 1458691511 25200
|
|
|
1f5a365 |
# Tue Mar 22 17:05:11 2016 -0700
|
|
|
1f5a365 |
# Branch stable
|
|
|
1f5a365 |
# Node ID cdda7b96afff3433eafdeeb83ded83a5b25b7a5b
|
|
|
1f5a365 |
# Parent a47006d8d01537c6a765ac77b66bf1c73b4cf7db
|
|
|
1f5a365 |
convert: rewrite calls to Git to use the new shelling mechanism (SEC)
|
|
|
1f5a365 |
|
|
|
1f5a365 |
CVE-2016-3069 (2/5)
|
|
|
1f5a365 |
|
|
|
1f5a365 |
One test output changed because we were ignoring git return code in numcommits
|
|
|
1f5a365 |
before.
|
|
|
1f5a365 |
|
|
|
1f5a365 |
diff --git a/hgext/convert/git.py b/hgext/convert/git.py
|
|
|
1f5a365 |
--- a/hgext/convert/git.py
|
|
|
1f5a365 |
+++ b/hgext/convert/git.py
|
|
|
1f5a365 |
@@ -115,13 +115,13 @@ class convert_git(converter_source, comm
|
|
|
1f5a365 |
if similarity < 0 or similarity > 100:
|
|
|
1f5a365 |
raise util.Abort(_('similarity must be between 0 and 100'))
|
|
|
1f5a365 |
if similarity > 0:
|
|
|
1f5a365 |
- self.simopt = '-C%d%%' % similarity
|
|
|
1f5a365 |
+ self.simopt = ['-C%d%%' % similarity]
|
|
|
1f5a365 |
findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
|
|
|
1f5a365 |
False)
|
|
|
1f5a365 |
if findcopiesharder:
|
|
|
1f5a365 |
- self.simopt += ' --find-copies-harder'
|
|
|
1f5a365 |
+ self.simopt.append('--find-copies-harder')
|
|
|
1f5a365 |
else:
|
|
|
1f5a365 |
- self.simopt = ''
|
|
|
1f5a365 |
+ self.simopt = []
|
|
|
1f5a365 |
|
|
|
1f5a365 |
checktool('git', 'git')
|
|
|
1f5a365 |
|
|
|
1f5a365 |
@@ -136,14 +136,14 @@ class convert_git(converter_source, comm
|
|
|
1f5a365 |
|
|
|
1f5a365 |
def getheads(self):
|
|
|
1f5a365 |
if not self.revs:
|
|
|
1f5a365 |
- heads, ret = self.gitread('git rev-parse --branches --remotes')
|
|
|
1f5a365 |
- heads = heads.splitlines()
|
|
|
1f5a365 |
- if ret:
|
|
|
1f5a365 |
+ output, status = self.gitrun('rev-parse', '--branches', '--remotes')
|
|
|
1f5a365 |
+ heads = output.splitlines()
|
|
|
1f5a365 |
+ if status:
|
|
|
1f5a365 |
raise util.Abort(_('cannot retrieve git heads'))
|
|
|
1f5a365 |
else:
|
|
|
1f5a365 |
heads = []
|
|
|
1f5a365 |
for rev in self.revs:
|
|
|
1f5a365 |
- rawhead, ret = self.gitread("git rev-parse --verify %s" % rev)
|
|
|
1f5a365 |
+ rawhead, ret = self.gitrun('rev-parse', '--verify', rev)
|
|
|
1f5a365 |
heads.append(rawhead[:-1])
|
|
|
1f5a365 |
if ret:
|
|
|
1f5a365 |
raise util.Abort(_('cannot retrieve git head "%s"') % rev)
|
|
|
1f5a365 |
@@ -203,7 +203,7 @@ class convert_git(converter_source, comm
|
|
|
1f5a365 |
self.submodules.append(submodule(s['path'], '', s['url']))
|
|
|
1f5a365 |
|
|
|
1f5a365 |
def retrievegitmodules(self, version):
|
|
|
1f5a365 |
- modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
|
|
|
1f5a365 |
+ modules, ret = self.gitrun('show', '%s:%s' % (version, '.gitmodules'))
|
|
|
1f5a365 |
if ret:
|
|
|
1f5a365 |
# This can happen if a file is in the repo that has permissions
|
|
|
1f5a365 |
# 160000, but there is no .gitmodules file.
|
|
|
1f5a365 |
@@ -219,7 +219,7 @@ class convert_git(converter_source, comm
|
|
|
1f5a365 |
return
|
|
|
1f5a365 |
|
|
|
1f5a365 |
for m in self.submodules:
|
|
|
1f5a365 |
- node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path))
|
|
|
1f5a365 |
+ node, ret = self.gitrun('rev-parse', '%s:%s' % (version, m.path))
|
|
|
1f5a365 |
if ret:
|
|
|
1f5a365 |
continue
|
|
|
1f5a365 |
m.node = node.strip()
|
|
|
1f5a365 |
@@ -228,15 +228,17 @@ class convert_git(converter_source, comm
|
|
|
1f5a365 |
if full:
|
|
|
1f5a365 |
raise util.Abort(_("convert from git do not support --full"))
|
|
|
1f5a365 |
self.modecache = {}
|
|
|
1f5a365 |
- fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % (
|
|
|
1f5a365 |
- self.simopt, version))
|
|
|
1f5a365 |
+ cmd = ['diff-tree','-z', '--root', '-m', '-r'] + self.simopt + [version]
|
|
|
1f5a365 |
+ output, status = self.gitrun(*cmd)
|
|
|
1f5a365 |
+ if status:
|
|
|
1f5a365 |
+ raise util.Abort(_('cannot read changes in %s') % version)
|
|
|
1f5a365 |
changes = []
|
|
|
1f5a365 |
copies = {}
|
|
|
1f5a365 |
seen = set()
|
|
|
1f5a365 |
entry = None
|
|
|
1f5a365 |
subexists = [False]
|
|
|
1f5a365 |
subdeleted = [False]
|
|
|
1f5a365 |
- difftree = fh.read().split('\x00')
|
|
|
1f5a365 |
+ difftree = output.split('\x00')
|
|
|
1f5a365 |
lcount = len(difftree)
|
|
|
1f5a365 |
i = 0
|
|
|
1f5a365 |
|
|
|
1f5a365 |
@@ -292,8 +294,6 @@ class convert_git(converter_source, comm
|
|
|
1f5a365 |
if f != '.gitmodules' and fdest != '.gitmodules':
|
|
|
1f5a365 |
copies[fdest] = f
|
|
|
1f5a365 |
entry = None
|
|
|
1f5a365 |
- if fh.close():
|
|
|
1f5a365 |
- raise util.Abort(_('cannot read changes in %s') % version)
|
|
|
1f5a365 |
|
|
|
1f5a365 |
if subexists[0]:
|
|
|
1f5a365 |
if subdeleted[0]:
|
|
|
1f5a365 |
@@ -339,17 +339,23 @@ class convert_git(converter_source, comm
|
|
|
1f5a365 |
return c
|
|
|
1f5a365 |
|
|
|
1f5a365 |
def numcommits(self):
|
|
|
1f5a365 |
- return len([None for _ in self.gitopen('git rev-list --all')])
|
|
|
1f5a365 |
+ output, ret = self.gitrunlines('rev-list', '--all')
|
|
|
1f5a365 |
+ if ret:
|
|
|
1f5a365 |
+ raise util.Abort(_('cannot retrieve number of commits in %s') \
|
|
|
1f5a365 |
+ % self.path)
|
|
|
1f5a365 |
+ return len(output)
|
|
|
1f5a365 |
|
|
|
1f5a365 |
def gettags(self):
|
|
|
1f5a365 |
tags = {}
|
|
|
1f5a365 |
alltags = {}
|
|
|
1f5a365 |
- fh = self.gitopen('git ls-remote --tags "%s"' % self.path,
|
|
|
1f5a365 |
- err=subprocess.STDOUT)
|
|
|
1f5a365 |
+ output, status = self.gitrunlines('ls-remote', '--tags', self.path)
|
|
|
1f5a365 |
+
|
|
|
1f5a365 |
+ if status:
|
|
|
1f5a365 |
+ raise util.Abort(_('cannot read tags from %s') % self.path)
|
|
|
1f5a365 |
prefix = 'refs/tags/'
|
|
|
1f5a365 |
|
|
|
1f5a365 |
# Build complete list of tags, both annotated and bare ones
|
|
|
1f5a365 |
- for line in fh:
|
|
|
1f5a365 |
+ for line in output:
|
|
|
1f5a365 |
line = line.strip()
|
|
|
1f5a365 |
if line.startswith("error:") or line.startswith("fatal:"):
|
|
|
1f5a365 |
raise util.Abort(_('cannot read tags from %s') % self.path)
|
|
|
1f5a365 |
@@ -357,8 +363,6 @@ class convert_git(converter_source, comm
|
|
|
1f5a365 |
if not tag.startswith(prefix):
|
|
|
1f5a365 |
continue
|
|
|
1f5a365 |
alltags[tag[len(prefix):]] = node
|
|
|
1f5a365 |
- if fh.close():
|
|
|
1f5a365 |
- raise util.Abort(_('cannot read tags from %s') % self.path)
|
|
|
1f5a365 |
|
|
|
1f5a365 |
# Filter out tag objects for annotated tag refs
|
|
|
1f5a365 |
for tag in alltags:
|
|
|
1f5a365 |
@@ -375,18 +379,20 @@ class convert_git(converter_source, comm
|
|
|
1f5a365 |
def getchangedfiles(self, version, i):
|
|
|
1f5a365 |
changes = []
|
|
|
1f5a365 |
if i is None:
|
|
|
1f5a365 |
- fh = self.gitopen("git diff-tree --root -m -r %s" % version)
|
|
|
1f5a365 |
- for l in fh:
|
|
|
1f5a365 |
+ output, status = self.gitrunlines('diff-tree', '--root', '-m',
|
|
|
1f5a365 |
+ '-r', version)
|
|
|
1f5a365 |
+ if status:
|
|
|
1f5a365 |
+ raise util.Abort(_('cannot read changes in %s') % version)
|
|
|
1f5a365 |
+ for l in output:
|
|
|
1f5a365 |
if "\t" not in l:
|
|
|
1f5a365 |
continue
|
|
|
1f5a365 |
m, f = l[:-1].split("\t")
|
|
|
1f5a365 |
changes.append(f)
|
|
|
1f5a365 |
else:
|
|
|
1f5a365 |
- fh = self.gitopen('git diff-tree --name-only --root -r %s '
|
|
|
1f5a365 |
- '"%s^%s" --' % (version, version, i + 1))
|
|
|
1f5a365 |
- changes = [f.rstrip('\n') for f in fh]
|
|
|
1f5a365 |
- if fh.close():
|
|
|
1f5a365 |
- raise util.Abort(_('cannot read changes in %s') % version)
|
|
|
1f5a365 |
+ output, status = self.gitrunlines('diff-tree', '--name-only',
|
|
|
1f5a365 |
+ '--root', '-r', version,
|
|
|
1f5a365 |
+ '%s^%s' % (version, i + 1), '--')
|
|
|
1f5a365 |
+ changes = [f.rstrip('\n') for f in output]
|
|
|
1f5a365 |
|
|
|
1f5a365 |
return changes
|
|
|
1f5a365 |
|
|
|
1f5a365 |
@@ -399,14 +405,14 @@ class convert_git(converter_source, comm
|
|
|
1f5a365 |
|
|
|
1f5a365 |
# factor two commands
|
|
|
1f5a365 |
remoteprefix = self.ui.config('convert', 'git.remoteprefix', 'remote')
|
|
|
1f5a365 |
- gitcmd = { remoteprefix + '/': 'git ls-remote --heads origin',
|
|
|
1f5a365 |
- '': 'git show-ref'}
|
|
|
1f5a365 |
+ gitcmd = { remoteprefix + '/': ['ls-remote', '--heads', 'origin'],
|
|
|
1f5a365 |
+ '': ['show-ref']}
|
|
|
1f5a365 |
|
|
|
1f5a365 |
# Origin heads
|
|
|
1f5a365 |
for reftype in gitcmd:
|
|
|
1f5a365 |
try:
|
|
|
1f5a365 |
- fh = self.gitopen(gitcmd[reftype], err=subprocess.PIPE)
|
|
|
1f5a365 |
- for line in fh:
|
|
|
1f5a365 |
+ output, status = self.gitrunlines(*gitcmd[reftype])
|
|
|
1f5a365 |
+ for line in output:
|
|
|
1f5a365 |
line = line.strip()
|
|
|
1f5a365 |
rev, name = line.split(None, 1)
|
|
|
1f5a365 |
if not name.startswith(prefix):
|
|
|
1f5a365 |
diff --git a/tests/test-convert-git.t b/tests/test-convert-git.t
|
|
|
1f5a365 |
--- a/tests/test-convert-git.t
|
|
|
1f5a365 |
+++ b/tests/test-convert-git.t
|
|
|
1f5a365 |
@@ -534,7 +534,6 @@ test missing .gitmodules
|
|
|
1f5a365 |
$ git commit -q -m "missing .gitmodules"
|
|
|
1f5a365 |
$ cd ..
|
|
|
1f5a365 |
$ hg convert git-repo6 hg-repo6 --traceback
|
|
|
1f5a365 |
- fatal: Path '.gitmodules' does not exist in '*' (glob)
|
|
|
1f5a365 |
initializing destination hg-repo6 repository
|
|
|
1f5a365 |
scanning source...
|
|
|
1f5a365 |
sorting...
|
|
|
1f5a365 |
@@ -689,7 +688,7 @@ damage git repository by renaming a comm
|
|
|
1f5a365 |
$ COMMIT_OBJ=1c/0ce3c5886f83a1d78a7b517cdff5cf9ca17bdd
|
|
|
1f5a365 |
$ mv git-repo4/.git/objects/$COMMIT_OBJ git-repo4/.git/objects/$COMMIT_OBJ.tmp
|
|
|
1f5a365 |
$ hg convert git-repo4 git-repo4-broken-hg 2>&1 | grep 'abort:'
|
|
|
1f5a365 |
- abort: cannot read tags from git-repo4/.git
|
|
|
1f5a365 |
+ abort: cannot retrieve number of commits in git-repo4/.git
|
|
|
1f5a365 |
$ mv git-repo4/.git/objects/$COMMIT_OBJ.tmp git-repo4/.git/objects/$COMMIT_OBJ
|
|
|
1f5a365 |
damage git repository by renaming a blob object
|
|
|
1f5a365 |
|