Mercurial > hg
diff hgext/convert/git.py @ 28670:ff0d3b6b287f
merge with stable
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Tue, 29 Mar 2016 12:29:00 -0500 |
parents | cd599bc179fb 80cac1de6aea |
children | 96ed01f6514b |
line wrap: on
line diff
--- a/hgext/convert/git.py Fri Mar 25 23:05:32 2016 -0700 +++ b/hgext/convert/git.py Tue Mar 29 12:29:00 2016 -0500 @@ -32,61 +32,28 @@ def hgsubstate(self): return "%s %s" % (self.node, self.path) -class convert_git(common.converter_source): +class convert_git(common.converter_source, common.commandline): # Windows does not support GIT_DIR= construct while other systems # cannot remove environment variable. Just assume none have # both issues. - if util.safehasattr(os, 'unsetenv'): - def gitopen(self, s, err=None): - prevgitdir = os.environ.get('GIT_DIR') - os.environ['GIT_DIR'] = self.path - try: - if err == subprocess.PIPE: - (stdin, stdout, stderr) = util.popen3(s) - return stdout - elif err == subprocess.STDOUT: - return self.popen_with_stderr(s) - else: - return util.popen(s, 'rb') - finally: - if prevgitdir is None: - del os.environ['GIT_DIR'] - else: - os.environ['GIT_DIR'] = prevgitdir + + def _gitcmd(self, cmd, *args, **kwargs): + return cmd('--git-dir=%s' % self.path, *args, **kwargs) + + def gitrun0(self, *args, **kwargs): + return self._gitcmd(self.run0, *args, **kwargs) - def gitpipe(self, s): - prevgitdir = os.environ.get('GIT_DIR') - os.environ['GIT_DIR'] = self.path - try: - return util.popen3(s) - finally: - if prevgitdir is None: - del os.environ['GIT_DIR'] - else: - os.environ['GIT_DIR'] = prevgitdir + def gitrun(self, *args, **kwargs): + return self._gitcmd(self.run, *args, **kwargs) + + def gitrunlines0(self, *args, **kwargs): + return self._gitcmd(self.runlines0, *args, **kwargs) - else: - def gitopen(self, s, err=None): - if err == subprocess.PIPE: - (sin, so, se) = util.popen3('GIT_DIR=%s %s' % (self.path, s)) - return so - elif err == subprocess.STDOUT: - return self.popen_with_stderr(s) - else: - return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb') + def gitrunlines(self, *args, **kwargs): + return self._gitcmd(self.runlines, *args, **kwargs) - def gitpipe(self, s): - return util.popen3('GIT_DIR=%s %s' % (self.path, s)) - - def popen_with_stderr(self, s): - p = subprocess.Popen(s, shell=True, bufsize=-1, - close_fds=util.closefds, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - universal_newlines=False, - env=None) - return p.stdout + def gitpipe(self, *args, **kwargs): + return self._gitcmd(self._run3, *args, **kwargs) def gitread(self, s): fh = self.gitopen(s) @@ -95,6 +62,7 @@ def __init__(self, ui, path, revs=None): super(convert_git, self).__init__(ui, path, revs=revs) + common.commandline.__init__(self, ui, 'git') if os.path.isdir(path + "/.git"): path += "/.git" @@ -107,20 +75,20 @@ if similarity < 0 or similarity > 100: raise error.Abort(_('similarity must be between 0 and 100')) if similarity > 0: - self.simopt = '-C%d%%' % similarity + self.simopt = ['-C%d%%' % similarity] findcopiesharder = ui.configbool('convert', 'git.findcopiesharder', False) if findcopiesharder: - self.simopt += ' --find-copies-harder' + self.simopt.append('--find-copies-harder') else: - self.simopt = '' + self.simopt = [] common.checktool('git', 'git') self.path = path self.submodules = [] - self.catfilepipe = self.gitpipe('git cat-file --batch') + self.catfilepipe = self.gitpipe('cat-file', '--batch') def after(self): for f in self.catfilepipe: @@ -128,14 +96,14 @@ def getheads(self): if not self.revs: - heads, ret = self.gitread('git rev-parse --branches --remotes') - heads = heads.splitlines() - if ret: + output, status = self.gitrun('rev-parse', '--branches', '--remotes') + heads = output.splitlines() + if status: raise error.Abort(_('cannot retrieve git heads')) else: heads = [] for rev in self.revs: - rawhead, ret = self.gitread("git rev-parse --verify %s" % rev) + rawhead, ret = self.gitrun('rev-parse', '--verify', rev) heads.append(rawhead[:-1]) if ret: raise error.Abort(_('cannot retrieve git head "%s"') % rev) @@ -195,7 +163,7 @@ self.submodules.append(submodule(s['path'], '', s['url'])) def retrievegitmodules(self, version): - modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules')) + modules, ret = self.gitrun('show', '%s:%s' % (version, '.gitmodules')) if ret: # This can happen if a file is in the repo that has permissions # 160000, but there is no .gitmodules file. @@ -211,7 +179,7 @@ return for m in self.submodules: - node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path)) + node, ret = self.gitrun('rev-parse', '%s:%s' % (version, m.path)) if ret: continue m.node = node.strip() @@ -220,15 +188,17 @@ if full: raise error.Abort(_("convert from git does not support --full")) self.modecache = {} - fh = self.gitopen("git diff-tree -z --root -m -r %s %s" % ( - self.simopt, version)) + cmd = ['diff-tree','-z', '--root', '-m', '-r'] + self.simopt + [version] + output, status = self.gitrun(*cmd) + if status: + raise error.Abort(_('cannot read changes in %s') % version) changes = [] copies = {} seen = set() entry = None subexists = [False] subdeleted = [False] - difftree = fh.read().split('\x00') + difftree = output.split('\x00') lcount = len(difftree) i = 0 @@ -290,8 +260,6 @@ if f != '.gitmodules' and fdest != '.gitmodules': copies[fdest] = f entry = None - if fh.close(): - raise error.Abort(_('cannot read changes in %s') % version) if subexists[0]: if subdeleted[0]: @@ -338,17 +306,23 @@ return c def numcommits(self): - return len([None for _ in self.gitopen('git rev-list --all')]) + output, ret = self.gitrunlines('rev-list', '--all') + if ret: + raise error.Abort(_('cannot retrieve number of commits in %s') \ + % self.path) + return len(output) def gettags(self): tags = {} alltags = {} - fh = self.gitopen('git ls-remote --tags "%s"' % self.path, - err=subprocess.STDOUT) + output, status = self.gitrunlines('ls-remote', '--tags', self.path) + + if status: + raise error.Abort(_('cannot read tags from %s') % self.path) prefix = 'refs/tags/' # Build complete list of tags, both annotated and bare ones - for line in fh: + for line in output: line = line.strip() if line.startswith("error:") or line.startswith("fatal:"): raise error.Abort(_('cannot read tags from %s') % self.path) @@ -356,8 +330,6 @@ if not tag.startswith(prefix): continue alltags[tag[len(prefix):]] = node - if fh.close(): - raise error.Abort(_('cannot read tags from %s') % self.path) # Filter out tag objects for annotated tag refs for tag in alltags: @@ -374,18 +346,20 @@ def getchangedfiles(self, version, i): changes = [] if i is None: - fh = self.gitopen("git diff-tree --root -m -r %s" % version) - for l in fh: + output, status = self.gitrunlines('diff-tree', '--root', '-m', + '-r', version) + if status: + raise error.Abort(_('cannot read changes in %s') % version) + for l in output: if "\t" not in l: continue m, f = l[:-1].split("\t") changes.append(f) else: - fh = self.gitopen('git diff-tree --name-only --root -r %s ' - '"%s^%s" --' % (version, version, i + 1)) - changes = [f.rstrip('\n') for f in fh] - if fh.close(): - raise error.Abort(_('cannot read changes in %s') % version) + output, status = self.gitrunlines('diff-tree', '--name-only', + '--root', '-r', version, + '%s^%s' % (version, i + 1), '--') + changes = [f.rstrip('\n') for f in output] return changes @@ -405,8 +379,8 @@ ]) try: - fh = self.gitopen('git show-ref', err=subprocess.PIPE) - for line in fh: + output, status = self.gitrunlines('show-ref') + for line in output: line = line.strip() rev, name = line.split(None, 1) # Process each type of branch