##// END OF EJS Templates
cvsps: use commitids (when present) to detect changesets...
cvsps: use commitids (when present) to detect changesets Simplify core logic by no longer attempting to work around missing class attributes. Instead always generate the attributes and ignore the cache if the attributes are missing

File last commit:

r17930:7788b5e7 default
r18261:1b7b5975 default
Show More
git.py
280 lines | 9.3 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.
Brendan Cully
Split convert extension into common and repository type modules
r4536
import os
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 from mercurial import util, config
Martin Geisler
clone, patch, convert: use hex(nullid) instead of '0'*40
r12144 from mercurial.node import hex, nullid
Martin Geisler
convert: mark strings for translation
r10939 from mercurial.i18n import _
Brendan Cully
Split convert extension into common and repository type modules
r4536
Patrick Mezard
convert: fail if an external required tool is not found
r5497 from common import NoRepo, commit, converter_source, checktool
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)
Brendan Cully
Split convert extension into common and repository type modules
r4536 class convert_git(converter_source):
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.
Augie Fackler
hgext: replace uses of hasattr with util.safehasattr
r14945 if util.safehasattr(os, 'unsetenv'):
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756 def gitopen(self, s, noerr=False):
Patrick Mezard
convert: fix issue702 about GIT_DIR= construct unsupported under Windows.
r5217 prevgitdir = os.environ.get('GIT_DIR')
os.environ['GIT_DIR'] = self.path
try:
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756 if noerr:
(stdin, stdout, stderr) = util.popen3(s)
return stdout
else:
return util.popen(s, 'rb')
Patrick Mezard
convert: fix issue702 about GIT_DIR= construct unsupported under Windows.
r5217 finally:
if prevgitdir is None:
del os.environ['GIT_DIR']
else:
os.environ['GIT_DIR'] = prevgitdir
else:
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756 def gitopen(self, s, noerr=False):
if noerr:
(sin, so, se) = util.popen3('GIT_DIR=%s %s' % (self.path, s))
timeless
convert: fix error in git solaris code
r14177 return so
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756 else:
Mads Kiilerich
convert: fix git convert on solaris - it cannot remove environment variables
r14735 return util.popen('GIT_DIR=%s %s' % (self.path, s), 'rb')
Brendan Cully
convert: gitcmd wrapper for os.popen
r4767
Patrick Mezard
convert/git: check status when reading the whole output
r10986 def gitread(self, s):
fh = self.gitopen(s)
data = fh.read()
return data, fh.close()
Brendan Cully
convert: add -r argument specifying latest revision to convert
r4760 def __init__(self, ui, path, rev=None):
Brendan Cully
convert: call superclass init from engine init functions
r4807 super(convert_git, self).__init__(ui, path, rev=rev)
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"):
Martin Geisler
convert: mark strings for translation
r10939 raise NoRepo(_("%s does not look like a Git repository") % path)
Patrick Mezard
convert: fail if an external required tool is not found
r5497
Dhruva Krishnamurthy
convert: use git executable only, with subcommands...
r6837 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
def getheads(self):
Brendan Cully
convert: import all branches from git repositories
r4768 if not self.rev:
Patrick Mezard
convert/git: check status when reading the whole output
r10986 heads, ret = self.gitread('git rev-parse --branches --remotes')
heads = heads.splitlines()
Brendan Cully
convert: import all branches from git repositories
r4768 else:
Patrick Mezard
convert/git: check status when reading the whole output
r10986 heads, ret = self.gitread("git rev-parse --verify %s" % self.rev)
heads = [heads[:-1]]
if ret:
raise util.Abort(_('cannot retrieve git heads'))
return heads
Brendan Cully
Split convert extension into common and repository type modules
r4536
def catfile(self, rev, type):
Martin Geisler
clone, patch, convert: use hex(nullid) instead of '0'*40
r12144 if rev == hex(nullid):
Brodie Rao
cleanup: "raise SomeException()" -> "raise SomeException"
r16687 raise IOError
Patrick Mezard
convert/git: check status when reading the whole output
r10986 data, ret = self.gitread("git cat-file %s %s" % (type, rev))
if ret:
raise util.Abort(_('cannot read %r object at %s') % (type, rev))
return data
Brendan Cully
Split convert extension into common and repository type modules
r4536
def getfile(self, name, rev):
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):
null = hex(nullid)
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()
# Each item in .gitmodules starts with \t that cant be parsed
c.parse('.gitmodules', content.replace('\t',''))
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):
modules, ret = self.gitread("git show %s:%s" % (version, '.gitmodules'))
if ret:
Bryan O'Sullivan
convert: fix a too-long line nag
r17930 raise util.Abort(_('cannot read submodules config file in %s') %
version)
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 self.parsegitmodules(modules)
for m in self.submodules:
node, ret = self.gitread("git rev-parse %s:%s" % (version, m.path))
if ret:
continue
m.node = node.strip()
Brendan Cully
Split convert extension into common and repository type modules
r4536 def getchanges(self, version):
self.modecache = {}
Patrick Mezard
convert/git: rename gitcmd() into gitopen() for readability
r10985 fh = self.gitopen("git diff-tree -z --root -m -r %s" % version)
Brendan Cully
Split convert extension into common and repository type modules
r4536 changes = []
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
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929 subexists = False
Patrick Mezard
convert: fix non-ASCII filenames retrieval from git sources (issue 1360)
r7242 for l in fh.read().split('\x00'):
if not entry:
if not l.startswith(':'):
continue
entry = l
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
if f not in seen:
Benoit Boissinot
convert: use set instead of dict
r8456 seen.add(f)
Patrick Mezard
convert: fix non-ASCII filenames retrieval from git sources (issue 1360)
r7242 entry = entry.split()
h = entry[3]
p = (entry[1] == "100755")
s = (entry[1] == "120000")
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929
if f == '.gitmodules':
subexists = True
changes.append(('.hgsub', ''))
elif entry[1] == '160000' or entry[0] == ':160000':
subexists = True
else:
self.modecache[(f, h)] = (p and "x") or (s and "l") or ""
changes.append((f, h))
Patrick Mezard
convert: fix non-ASCII filenames retrieval from git sources (issue 1360)
r7242 entry = None
Patrick Mezard
convert/git: check status when reading output stream
r10987 if fh.close():
raise util.Abort(_('cannot read changes in %s') % version)
YaNan Xu
convert: add support for converting git submodule (issue3528)...
r17929
if subexists:
self.retrievegitmodules(version)
changes.append(('.hgsubstate', ''))
Brendan Cully
convert: look up copies in getchanges instead of getcommit...
r5121 return (changes, {})
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)
Brendan Cully
convert: record the source revision in the changelog
r4873 c = 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
def gettags(self):
tags = {}
Edouard Gomez
convert: support non annotated tags in git backend...
r16259 alltags = {}
Patrick Mezard
convert/git: rename gitcmd() into gitopen() for readability
r10985 fh = self.gitopen('git ls-remote --tags "%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
Brendan Cully
Split convert extension into common and repository type modules
r4536 for line in fh:
line = line.strip()
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
Patrick Mezard
convert/git: check status when reading output stream
r10987 if fh.close():
raise util.Abort(_('cannot read tags from %s') % self.path)
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:
Patrick Mezard
convert/git: rename gitcmd() into gitopen() for readability
r10985 fh = self.gitopen("git diff-tree --root -m -r %s" % version)
Alexis S. L. Carvalho
convert_git: add --filemap support
r5380 for l in fh:
if "\t" not in l:
continue
m, f = l[:-1].split("\t")
changes.append(f)
else:
Brodie Rao
cleanup: eradicate long lines
r16683 fh = self.gitopen('git diff-tree --name-only --root -r %s '
'"%s^%s" --' % (version, version, i + 1))
Alexis S. L. Carvalho
convert_git: add --filemap support
r5380 changes = [f.rstrip('\n') for f in fh]
Patrick Mezard
convert/git: check status when reading output stream
r10987 if fh.close():
raise util.Abort(_('cannot read changes in %s') % version)
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 = {}
# Interesting references in git are prefixed
prefix = 'refs/heads/'
prefixlen = len(prefix)
# factor two commands
gitcmd = { 'remote/': 'git ls-remote --heads origin',
'': 'git show-ref'}
# Origin heads
for reftype in gitcmd:
try:
fh = self.gitopen(gitcmd[reftype], noerr=True)
for line in fh:
line = line.strip()
rev, name = line.split(None, 1)
if not name.startswith(prefix):
continue
name = '%s%s' % (reftype, name[prefixlen:])
bookmarks[name] = rev
Brodie Rao
cleanup: replace naked excepts with except Exception: ...
r16689 except Exception:
Edouard Gomez
convert: add bookmarks reading support to git backend
r13756 pass
return bookmarks