##// END OF EJS Templates
py3: replace os.name with pycompat.osname (part 1 of 2)...
py3: replace os.name with pycompat.osname (part 1 of 2) os.name returns unicodes on py3 and we have pycompat.osname which returns bytes. This series of 2 patches will change every ocurrence of os.name with pycompat.osname.

File last commit:

r29205:a0939666 default
r30639:d524c885 default
Show More
git.py
399 lines | 13.7 KiB | text/x-python | PythonLexer
Martin Geisler
convert: add copyright and license headers to back-ends
r8250 # git.py - git support for the convert extension
#
# Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others
#
# This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
timeless
convert: git use absolute_import
r28365 from __future__ import absolute_import
Brendan Cully
Split convert extension into common and repository type modules
r4536
import os
Yuya Nishihara
py3: move up symbol imports to enforce import-checker rules...
r29205
from mercurial.i18n import _
timeless
convert: git use absolute_import
r28365 from mercurial import (
config,
error,
node as nodemod,
)
Brendan Cully
Split convert extension into common and repository type modules
r4536
timeless
convert: git use absolute_import
r28365 from . import (
common,
)
Brendan Cully
Split convert extension into common and repository type modules
r4536
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 class submodule(object):
def __init__(self, path, node, url):
self.path = path
self.node = node
self.url = url
def hgsub(self):
return "%s = [git]%s" % (self.path, self.url)
def hgsubstate(self):
return "%s %s" % (self.node, self.path)
Matt Mackall
merge with stable
r28670 class convert_git(common.converter_source, common.commandline):
Patrick Mezard
convert: fix issue702 about GIT_DIR= construct unsupported under Windows.
r5217 # Windows does not support GIT_DIR= construct while other systems
# cannot remove environment variable. Just assume none have
# both issues.
David Schleimer
convert: drastically speed up git conversions...
r21630
Mateusz Kwapich
convert: add new, non-clowny interface for shelling out to git (SEC)...
r28659 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 gitrun(self, *args, **kwargs):
return self._gitcmd(self.run, *args, **kwargs)
def gitrunlines0(self, *args, **kwargs):
return self._gitcmd(self.runlines0, *args, **kwargs)
def gitrunlines(self, *args, **kwargs):
return self._gitcmd(self.runlines, *args, **kwargs)
Mateusz Kwapich
convert: rewrite gitpipe to use common.commandline (SEC)...
r28662 def gitpipe(self, *args, **kwargs):
return self._gitcmd(self._run3, *args, **kwargs)
Durham Goode
convert: add support for specifying multiple revs...
r25748 def __init__(self, ui, path, revs=None):
super(convert_git, self).__init__(ui, path, revs=revs)
Matt Mackall
merge with stable
r28670 common.commandline.__init__(self, ui, 'git')
Durham Goode
convert: add support for specifying multiple revs...
r25748
Blake Burkhart
convert: pass absolute paths to git (SEC)...
r29051 # Pass an absolute path to git to prevent from ever being interpreted
# as a URL
path = os.path.abspath(path)
Brendan Cully
Split convert extension into common and repository type modules
r4536 if os.path.isdir(path + "/.git"):
path += "/.git"
if not os.path.exists(path + "/objects"):
timeless
convert: git use absolute_import
r28365 raise common.NoRepo(_("%s does not look like a Git repository") %
path)
Patrick Mezard
convert: fail if an external required tool is not found
r5497
Siddharth Agarwal
convert: change default for git rename detection to 50%...
r22512 # The default value (50) is based on the default for 'git diff'.
similarity = ui.configint('convert', 'git.similarity', default=50)
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470 if similarity < 0 or similarity > 100:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('similarity must be between 0 and 100'))
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470 if similarity > 0:
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 self.simopt = ['-C%d%%' % similarity]
Siddharth Agarwal
convert: add support to find git copies from all files in the working copy...
r22471 findcopiesharder = ui.configbool('convert', 'git.findcopiesharder',
False)
if findcopiesharder:
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 self.simopt.append('--find-copies-harder')
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470 else:
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 self.simopt = []
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470
timeless
convert: git use absolute_import
r28365 common.checktool('git', 'git')
Patrick Mezard
convert: fail if an external required tool is not found
r5497
Brendan Cully
Split convert extension into common and repository type modules
r4536 self.path = path
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 self.submodules = []
Brendan Cully
Split convert extension into common and repository type modules
r4536
Mateusz Kwapich
convert: rewrite gitpipe to use common.commandline (SEC)...
r28662 self.catfilepipe = self.gitpipe('cat-file', '--batch')
David Schleimer
convert: drastically speed up git conversions...
r21630
def after(self):
for f in self.catfilepipe:
f.close()
Brendan Cully
Split convert extension into common and repository type modules
r4536 def getheads(self):
Durham Goode
convert: add support for specifying multiple revs...
r25748 if not self.revs:
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 output, status = self.gitrun('rev-parse', '--branches', '--remotes')
heads = output.splitlines()
if status:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot retrieve git heads'))
Brendan Cully
convert: import all branches from git repositories
r4768 else:
Durham Goode
convert: support multiple specifed revs in git source...
r25749 heads = []
for rev in self.revs:
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 rawhead, ret = self.gitrun('rev-parse', '--verify', rev)
Durham Goode
convert: support multiple specifed revs in git source...
r25749 heads.append(rawhead[:-1])
if ret:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot retrieve git head "%s"') % rev)
Patrick Mezard
convert/git: check status when reading the whole output
r10986 return heads
Brendan Cully
Split convert extension into common and repository type modules
r4536
def catfile(self, rev, type):
timeless
convert: git use absolute_import
r28365 if rev == nodemod.nullhex:
Brodie Rao
cleanup: "raise SomeException()" -> "raise SomeException"
r16687 raise IOError
David Schleimer
convert: drastically speed up git conversions...
r21630 self.catfilepipe[0].write(rev+'\n')
self.catfilepipe[0].flush()
info = self.catfilepipe[1].readline().split()
if info[1] != type:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot read %r object at %s') % (type, rev))
David Schleimer
convert: drastically speed up git conversions...
r21630 size = int(info[2])
data = self.catfilepipe[1].read(size)
if len(data) < size:
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot read %r object at %s: unexpected size')
FUJIWARA Katsunori
convert: fix argument mismatch at formatting the abort message...
r21958 % (type, rev))
David Schleimer
convert: drastically speed up git conversions...
r21630 # read the trailing newline
self.catfilepipe[1].read(1)
Patrick Mezard
convert/git: check status when reading the whole output
r10986 return data
Brendan Cully
Split convert extension into common and repository type modules
r4536
def getfile(self, name, rev):
timeless
convert: git use absolute_import
r28365 if rev == nodemod.nullhex:
Mads Kiilerich
convert: use None value for missing files instead of overloading IOError...
r22296 return None, None
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 if name == '.hgsub':
data = '\n'.join([m.hgsub() for m in self.submoditer()])
mode = ''
elif name == '.hgsubstate':
data = '\n'.join([m.hgsubstate() for m in self.submoditer()])
mode = ''
else:
data = self.catfile(rev, "blob")
mode = self.modecache[(name, rev)]
Patrick Mezard
convert: merge sources getmode() into getfile()
r11134 return data, mode
Brendan Cully
Split convert extension into common and repository type modules
r4536
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 def submoditer(self):
timeless
convert: git use absolute_import
r28365 null = nodemod.nullhex
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 for m in sorted(self.submodules, key=lambda p: p.path):
if m.node != null:
yield m
def parsegitmodules(self, content):
"""Parse the formatted .gitmodules file, example file format:
[submodule "sub"]\n
\tpath = sub\n
\turl = git://giturl\n
"""
self.submodules = []
c = config.config()
Durham Goode
convert: handle .gitmodules with non-tab whitespaces...
r25698 # Each item in .gitmodules starts with whitespace that cant be parsed
c.parse('.gitmodules', '\n'.join(line.strip() for line in
content.split('\n')))
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 for sec in c.sections():
s = c[sec]
if 'url' in s and 'path' in s:
self.submodules.append(submodule(s['path'], '', s['url']))
def retrievegitmodules(self, version):
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 modules, ret = self.gitrun('show', '%s:%s' % (version, '.gitmodules'))
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 if ret:
Durham Goode
convert: improve support for unusual .gitmodules...
r25699 # This can happen if a file is in the repo that has permissions
# 160000, but there is no .gitmodules file.
self.ui.warn(_("warning: cannot read submodules config file in "
"%s\n") % version)
return
try:
self.parsegitmodules(modules)
except error.ParseError:
self.ui.warn(_("warning: unable to parse .gitmodules in %s\n")
% version)
return
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 for m in self.submodules:
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 node, ret = self.gitrun('rev-parse', '%s:%s' % (version, m.path))
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 if ret:
continue
m.node = node.strip()
Mads Kiilerich
convert: introduce --full for converting all files...
r22300 def getchanges(self, version, full):
if full:
timeless@mozdev.org
grammar: use does instead of do where appropriate
r26779 raise error.Abort(_("convert from git does not support --full"))
Brendan Cully
Split convert extension into common and repository type modules
r4536 self.modecache = {}
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 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)
Brendan Cully
Split convert extension into common and repository type modules
r4536 changes = []
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470 copies = {}
Benoit Boissinot
convert: use set instead of dict
r8456 seen = set()
Patrick Mezard
convert: fix non-ASCII filenames retrieval from git sources (issue 1360)
r7242 entry = None
Siddharth Agarwal
convert: for git, factor out code to add entries to a separate function...
r22469 subexists = [False]
subdeleted = [False]
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 difftree = output.split('\x00')
Siddharth Agarwal
convert: for git's getchanges, use explicit index for iteration...
r22467 lcount = len(difftree)
i = 0
Siddharth Agarwal
convert: for git, factor out code to add entries to a separate function...
r22469
Durham Goode
convert: add convert.git.skipsubmodules option...
r26077 skipsubmodules = self.ui.configbool('convert', 'git.skipsubmodules',
False)
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470 def add(entry, f, isdest):
Siddharth Agarwal
convert: for git, factor out code to add entries to a separate function...
r22469 seen.add(f)
h = entry[3]
p = (entry[1] == "100755")
s = (entry[1] == "120000")
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470 renamesource = (not isdest and entry[4][0] == 'R')
Siddharth Agarwal
convert: for git, factor out code to add entries to a separate function...
r22469
if f == '.gitmodules':
Durham Goode
convert: add convert.git.skipsubmodules option...
r26077 if skipsubmodules:
return
Siddharth Agarwal
convert: for git, factor out code to add entries to a separate function...
r22469 subexists[0] = True
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470 if entry[4] == 'D' or renamesource:
Siddharth Agarwal
convert: for git, factor out code to add entries to a separate function...
r22469 subdeleted[0] = True
timeless
convert: git use absolute_import
r28365 changes.append(('.hgsub', nodemod.nullhex))
Siddharth Agarwal
convert: for git, factor out code to add entries to a separate function...
r22469 else:
changes.append(('.hgsub', ''))
elif entry[1] == '160000' or entry[0] == ':160000':
Durham Goode
convert: add convert.git.skipsubmodules option...
r26077 if not skipsubmodules:
subexists[0] = True
Siddharth Agarwal
convert: for git, factor out code to add entries to a separate function...
r22469 else:
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470 if renamesource:
timeless
convert: git use absolute_import
r28365 h = nodemod.nullhex
Siddharth Agarwal
convert: for git, factor out code to add entries to a separate function...
r22469 self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
changes.append((f, h))
Siddharth Agarwal
convert: for git's getchanges, use explicit index for iteration...
r22467 while i < lcount:
l = difftree[i]
i += 1
Patrick Mezard
convert: fix non-ASCII filenames retrieval from git sources (issue 1360)
r7242 if not entry:
if not l.startswith(':'):
continue
Siddharth Agarwal
convert: for git's getchanges, always split entry line into components...
r22468 entry = l.split()
Alexis S. L. Carvalho
convert_git: avoid returning two entries for the same file in getchanges...
r5335 continue
Patrick Mezard
convert: fix non-ASCII filenames retrieval from git sources (issue 1360)
r7242 f = l
Durham Goode
convert: fix git copy file content conversions...
r25997 if entry[4][0] == 'C':
copysrc = f
copydest = difftree[i]
i += 1
f = copydest
copies[copydest] = copysrc
Patrick Mezard
convert: fix non-ASCII filenames retrieval from git sources (issue 1360)
r7242 if f not in seen:
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470 add(entry, f, False)
# A file can be copied multiple times, or modified and copied
# simultaneously. So f can be repeated even if fdest isn't.
Durham Goode
convert: fix git copy file content conversions...
r25997 if entry[4][0] == 'R':
# rename: next line is the destination
Siddharth Agarwal
convert: add support to detect git renames and copies...
r22470 fdest = difftree[i]
i += 1
if fdest not in seen:
add(entry, fdest, True)
# .gitmodules isn't imported at all, so it being copied to
# and fro doesn't really make sense
if f != '.gitmodules' and fdest != '.gitmodules':
copies[fdest] = f
Patrick Mezard
convert: fix non-ASCII filenames retrieval from git sources (issue 1360)
r7242 entry = None
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929
Siddharth Agarwal
convert: for git, factor out code to add entries to a separate function...
r22469 if subexists[0]:
if subdeleted[0]:
timeless
convert: git use absolute_import
r28365 changes.append(('.hgsubstate', nodemod.nullhex))
FUJIWARA Katsunori
convert: detect removal of ".gitmodules" at git source revisions correctly...
r21868 else:
self.retrievegitmodules(version)
changes.append(('.hgsubstate', ''))
Mads Kiilerich
convert: optimize convert of files that are unmodified from p2 in merges...
r24395 return (changes, copies, set())
Brendan Cully
Split convert extension into common and repository type modules
r4536
def getcommit(self, version):
c = self.catfile(version, "commit") # read the commit hash
end = c.find("\n\n")
Matt Mackall
many, many trivial check-code fixups
r10282 message = c[end + 2:]
Brendan Cully
convert: ove recode method into converter_source
r4759 message = self.recode(message)
Brendan Cully
Split convert extension into common and repository type modules
r4536 l = c[:end].splitlines()
parents = []
Richard Quirk
Add committer tag only when needed in git conversion...
r8271 author = committer = None
Brendan Cully
Split convert extension into common and repository type modules
r4536 for e in l[1:]:
n, v = e.split(" ", 1)
if n == "author":
p = v.split()
tm, tz = p[-2:]
author = " ".join(p[:-2])
if author[0] == "<": author = author[1:-1]
Brendan Cully
convert: ove recode method into converter_source
r4759 author = self.recode(author)
Brendan Cully
Split convert extension into common and repository type modules
r4536 if n == "committer":
p = v.split()
tm, tz = p[-2:]
committer = " ".join(p[:-2])
if committer[0] == "<": committer = committer[1:-1]
Brendan Cully
convert: ove recode method into converter_source
r4759 committer = self.recode(committer)
Matt Mackall
many, many trivial check-code fixups
r10282 if n == "parent":
parents.append(v)
Brendan Cully
Split convert extension into common and repository type modules
r4536
Richard Quirk
Add committer tag only when needed in git conversion...
r8271 if committer and committer != author:
message += "\ncommitter: %s\n" % committer
Brendan Cully
Split convert extension into common and repository type modules
r4536 tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:]
tz = -int(tzs) * (int(tzh) * 3600 + int(tzm))
date = tm + " " + str(tz)
timeless
convert: git use absolute_import
r28365 c = common.commit(parents=parents, date=date, author=author,
desc=message,
rev=version)
Brendan Cully
Split convert extension into common and repository type modules
r4536 return c
Augie Fackler
convert: enable deterministic conversion progress bar for git
r22413 def numcommits(self):
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 output, ret = self.gitrunlines('rev-list', '--all')
if ret:
raise error.Abort(_('cannot retrieve number of commits in %s') \
% self.path)
return len(output)
Augie Fackler
convert: enable deterministic conversion progress bar for git
r22413
Brendan Cully
Split convert extension into common and repository type modules
r4536 def gettags(self):
tags = {}
Edouard Gomez
convert: support non annotated tags in git backend...
r16259 alltags = {}
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 output, status = self.gitrunlines('ls-remote', '--tags', self.path)
if status:
raise error.Abort(_('cannot read tags from %s') % self.path)
Brendan Cully
Split convert extension into common and repository type modules
r4536 prefix = 'refs/tags/'
Edouard Gomez
convert: support non annotated tags in git backend...
r16259
# Build complete list of tags, both annotated and bare ones
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 for line in output:
Brendan Cully
Split convert extension into common and repository type modules
r4536 line = line.strip()
Augie Fackler
git convert: some versions of git use fatal: instead of error:...
r18572 if line.startswith("error:") or line.startswith("fatal:"):
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(_('cannot read tags from %s') % self.path)
Brendan Cully
Split convert extension into common and repository type modules
r4536 node, tag = line.split(None, 1)
if not tag.startswith(prefix):
continue
Edouard Gomez
convert: support non annotated tags in git backend...
r16259 alltags[tag[len(prefix):]] = node
Brendan Cully
Split convert extension into common and repository type modules
r4536
Edouard Gomez
convert: support non annotated tags in git backend...
r16259 # Filter out tag objects for annotated tag refs
for tag in alltags:
if tag.endswith('^{}'):
tags[tag[:-3]] = alltags[tag]
else:
if tag + '^{}' in alltags:
continue
else:
tags[tag] = alltags[tag]
Brendan Cully
Split convert extension into common and repository type modules
r4536 return tags
Alexis S. L. Carvalho
convert_git: add --filemap support
r5380
def getchangedfiles(self, version, i):
changes = []
if i is None:
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 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:
Alexis S. L. Carvalho
convert_git: add --filemap support
r5380 if "\t" not in l:
continue
m, f = l[:-1].split("\t")
changes.append(f)
else:
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 output, status = self.gitrunlines('diff-tree', '--name-only',
'--root', '-r', version,
'%s^%s' % (version, i + 1), '--')
Julien Cristau
convert: don't ignore errors from git diff-tree
r28816 if status:
raise error.Abort(_('cannot read changes in %s') % version)
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 changes = [f.rstrip('\n') for f in output]
Alexis S. L. Carvalho
convert_git: add --filemap support
r5380
return changes
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756
def getbookmarks(self):
bookmarks = {}
Durham Goode
convert: fix git convert using servers branches...
r25905 # Handle local and remote branches
remoteprefix = self.ui.config('convert', 'git.remoteprefix', 'remote')
reftypes = [
# (git prefix, hg prefix)
('refs/remotes/origin/', remoteprefix + '/'),
('refs/heads/', '')
]
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756
Durham Goode
convert: fix git convert using servers branches...
r25905 exclude = set([
'refs/remotes/origin/HEAD',
])
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756
Durham Goode
convert: fix git convert using servers branches...
r25905 try:
Mateusz Kwapich
convert: rewrite calls to Git to use the new shelling mechanism (SEC)...
r28660 output, status = self.gitrunlines('show-ref')
for line in output:
Durham Goode
convert: fix git convert using servers branches...
r25905 line = line.strip()
rev, name = line.split(None, 1)
# Process each type of branch
for gitprefix, hgprefix in reftypes:
if not name.startswith(gitprefix) or name in exclude:
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756 continue
Durham Goode
convert: fix git convert using servers branches...
r25905 name = '%s%s' % (hgprefix, name[len(gitprefix):])
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756 bookmarks[name] = rev
Durham Goode
convert: fix git convert using servers branches...
r25905 except Exception:
pass
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756
return bookmarks
Ben Goswami
splicemap: improve error handling when source is git (issue2084)...
r19121
Sean Farley
convert: add mapname parameter to checkrevformat...
r20373 def checkrevformat(self, revstr, mapname='splicemap'):
Ben Goswami
splicemap: improve error handling when source is git (issue2084)...
r19121 """ git revision string is a 40 byte hex """
Sean Farley
convert: add mapname parameter to checkrevformat...
r20373 self.checkhexformat(revstr, mapname)