Mercurial > hg
view hgext/convert/git.py @ 6858:8f256bf98219
Add support for multiple possible bisect results (issue1228, issue1182)
The real reason for both issue is that bisect can not handle cases where there
are multiple possibilities for the result.
Example (from issue1228):
rev 0 -> good
rev 1 -> skipped
rev 2 -> skipped
rev 3 -> skipped
rev 4 -> bad
Note that this patch does not only fix the reported Assertion Error but also
the problem of a non converging bisect:
hg init
for i in `seq 3`; do echo $i > $i; hg add $i; hg ci -m$i; done
hg bisect -b 2
hg bisect -g 0
hg bisect -s
From this state on, you can:
a) mark as bad forever (non converging!)
b) mark as good to get an inconsistent state
c) skip for the Assertion Error
Minor description and code edits by pmezard.
author | Bernhard Leiner <bleiner@gmail.com> |
---|---|
date | Sat, 02 Aug 2008 22:10:10 +0200 |
parents | e30c56f337b1 |
children | c1dc903dc7b6 |
line wrap: on
line source
# git support for the convert extension import os from mercurial import util from common import NoRepo, commit, converter_source, checktool class convert_git(converter_source): # Windows does not support GIT_DIR= construct while other systems # cannot remove environment variable. Just assume none have # both issues. if hasattr(os, 'unsetenv'): def gitcmd(self, s): prevgitdir = os.environ.get('GIT_DIR') os.environ['GIT_DIR'] = self.path try: return util.popen(s) finally: if prevgitdir is None: del os.environ['GIT_DIR'] else: os.environ['GIT_DIR'] = prevgitdir else: def gitcmd(self, s): return util.popen('GIT_DIR=%s %s' % (self.path, s)) def __init__(self, ui, path, rev=None): super(convert_git, self).__init__(ui, path, rev=rev) if os.path.isdir(path + "/.git"): path += "/.git" if not os.path.exists(path + "/objects"): raise NoRepo("%s does not look like a Git repo" % path) checktool('git', 'git') self.path = path def getheads(self): if not self.rev: return self.gitcmd('git rev-parse --branches').read().splitlines() else: fh = self.gitcmd("git rev-parse --verify %s" % self.rev) return [fh.read()[:-1]] def catfile(self, rev, type): if rev == "0" * 40: raise IOError() fh = self.gitcmd("git cat-file %s %s" % (type, rev)) return fh.read() def getfile(self, name, rev): return self.catfile(rev, "blob") def getmode(self, name, rev): return self.modecache[(name, rev)] def getchanges(self, version): self.modecache = {} fh = self.gitcmd("git diff-tree --root -m -r %s" % version) changes = [] seen = {} for l in fh: if "\t" not in l: continue m, f = l[:-1].split("\t") if f in seen: continue seen[f] = 1 m = m.split() h = m[3] p = (m[1] == "100755") s = (m[1] == "120000") self.modecache[(f, h)] = (p and "x") or (s and "l") or "" changes.append((f, h)) return (changes, {}) def getcommit(self, version): c = self.catfile(version, "commit") # read the commit hash end = c.find("\n\n") message = c[end+2:] message = self.recode(message) l = c[:end].splitlines() manifest = l[0].split()[1] parents = [] 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] author = self.recode(author) if n == "committer": p = v.split() tm, tz = p[-2:] committer = " ".join(p[:-2]) if committer[0] == "<": committer = committer[1:-1] committer = self.recode(committer) message += "\ncommitter: %s\n" % committer if n == "parent": parents.append(v) tzs, tzh, tzm = tz[-5:-4] + "1", tz[-4:-2], tz[-2:] tz = -int(tzs) * (int(tzh) * 3600 + int(tzm)) date = tm + " " + str(tz) c = commit(parents=parents, date=date, author=author, desc=message, rev=version) return c def gettags(self): tags = {} fh = self.gitcmd('git ls-remote --tags "%s"' % self.path) prefix = 'refs/tags/' for line in fh: line = line.strip() if not line.endswith("^{}"): continue node, tag = line.split(None, 1) if not tag.startswith(prefix): continue tag = tag[len(prefix):-3] tags[tag] = node return tags def getchangedfiles(self, version, i): changes = [] if i is None: fh = self.gitcmd("git diff-tree --root -m -r %s" % version) for l in fh: if "\t" not in l: continue m, f = l[:-1].split("\t") changes.append(f) fh.close() else: fh = self.gitcmd('git diff-tree --name-only --root -r %s "%s^%s" --' % (version, version, i+1)) changes = [f.rstrip('\n') for f in fh] fh.close() return changes