##// END OF EJS Templates
Reverted change 51f26e856f3d: Reading changelogs is too slow.
Reverted change 51f26e856f3d: Reading changelogs is too slow.

File last commit:

r740:d2422f10 merge default
r1139:916bb284 default
Show More
hgit
255 lines | 7.9 KiB | text/plain | TextLexer
mpm@selenic.com
Initial import of hgit and hgk...
r267 #!/usr/bin/env python
#
# Minimal support for git commands on an hg repository
#
# Copyright 2005 Chris Mason <mason@suse.com>
#
# This software may be used and distributed according to the terms
# of the GNU General Public License, incorporated herein by reference.
import time, sys, signal
from mercurial import hg, mdiff, fancyopts, commands, ui
Thomas Arendsen Hein
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli....
r396 def difftree(args, ui, repo):
mpm@selenic.com
Initial import of hgit and hgk...
r267 def __difftree(repo, files = None, node1 = None, node2 = None):
mpm@selenic.com
hgit: remove tabs...
r334 def date(c):
return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
mpm@selenic.com
Initial import of hgit and hgk...
r267
mpm@selenic.com
hgit: remove tabs...
r334 if node2:
change = repo.changelog.read(node2)
mmap2 = repo.manifest.read(change[0])
mason@suse.com
Fix hgit usage of repo.changes and fancyopts to reflect current hg api
r719 (c, a, d, u) = repo.changes(node1, node2)
mpm@selenic.com
hgit: remove tabs...
r334 def read(f): return repo.file(f).read(mmap2[f])
date2 = date(change)
else:
date2 = time.asctime()
(c, a, d, u) = repo.diffdir(repo.root, node1)
if not node1:
node1 = repo.dirstate.parents()[0]
def read(f): return file(os.path.join(repo.root, f)).read()
mpm@selenic.com
Initial import of hgit and hgk...
r267
mpm@selenic.com
hgit: remove tabs...
r334 change = repo.changelog.read(node1)
mmap = repo.manifest.read(change[0])
date1 = date(change)
empty = "0" * 40;
mpm@selenic.com
Initial import of hgit and hgk...
r267
mpm@selenic.com
hgit: remove tabs...
r334 if files:
c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
mpm@selenic.com
Initial import of hgit and hgk...
r267
mpm@selenic.com
hgit: remove tabs...
r334 for f in c:
# TODO get file permissions
mpm@selenic.com
[PATCH] Using monotone-viz/git-viz with mercurial...
r406 print ":100664 100664 %s %s M\t%s\t%s" % (hg.hex(mmap[f]),
mpm@selenic.com
hgit: remove tabs...
r334 hg.hex(mmap2[f]), f, f)
for f in a:
mpm@selenic.com
[PATCH] Using monotone-viz/git-viz with mercurial...
r406 print ":000000 100664 %s %s N\t%s\t%s" % (empty, hg.hex(mmap2[f]), f, f)
mpm@selenic.com
hgit: remove tabs...
r334 for f in d:
mpm@selenic.com
[PATCH] Using monotone-viz/git-viz with mercurial...
r406 print ":100664 000000 %s %s D\t%s\t%s" % (hg.hex(mmap[f]), empty, f, f)
mpm@selenic.com
Initial import of hgit and hgk...
r267 ##
revs = []
if args:
mpm@selenic.com
hgit: remove tabs...
r334 doptions = {}
opts = [('p', 'patch', None, 'patch'),
('r', 'recursive', None, 'recursive')]
mason@suse.com
Fix hgit usage of repo.changes and fancyopts to reflect current hg api
r719 args = fancyopts.fancyopts(args, opts, doptions)
mpm@selenic.com
Initial import of hgit and hgk...
r267
if len(args) < 2:
mpm@selenic.com
hgit: remove tabs...
r334 help()
mpm@selenic.com
Initial import of hgit and hgk...
r267 sys.exit(1)
revs.append(repo.lookup(args[0]))
revs.append(repo.lookup(args[1]))
args = args[2:]
if doptions['patch']:
mason@suse.com
Fix hgit usage of repo.changes and fancyopts to reflect current hg api
r719 commands.dodiff(sys.stdout, ui, repo, args, *revs)
mpm@selenic.com
Initial import of hgit and hgk...
r267 else:
mpm@selenic.com
hgit: remove tabs...
r334 __difftree(repo, args, *revs)
mpm@selenic.com
Initial import of hgit and hgk...
r267
def catcommit(repo, n, prefix):
nlprefix = '\n' + prefix;
changes = repo.changelog.read(n)
(p1, p2) = repo.changelog.parents(n)
(h, h1, h2) = map(hg.hex, (n, p1, p2))
(i1, i2) = map(repo.changelog.rev, (p1, p2))
print "tree %s" % (h)
if i1 != -1: print "%sparent %s" % (prefix, h1)
if i2 != -1: print "%sparent %s" % (prefix, h2)
date_ar = changes[2].split(' ')
date = int(float(date_ar[0]))
print "%sauthor <%s> %s %s" % (prefix, changes[1], date, date_ar[1])
print "%scommitter <%s> %s %s" % (prefix, changes[1], date, date_ar[1])
print prefix
if prefix != "":
mpm@selenic.com
hgit: remove tabs...
r334 print "%s%s" % (prefix, changes[4].replace('\n', nlprefix).strip())
mpm@selenic.com
Initial import of hgit and hgk...
r267 else:
mpm@selenic.com
hgit: remove tabs...
r334 print changes[4]
mpm@selenic.com
Initial import of hgit and hgk...
r267
def catfile(args, ui, repo):
doptions = {}
opts = [('s', 'stdin', None, 'stdin')]
mason@suse.com
Fix hgit usage of repo.changes and fancyopts to reflect current hg api
r719 args = fancyopts.fancyopts(args, opts, doptions)
mpm@selenic.com
Initial import of hgit and hgk...
r267
# in stdin mode, every line except the commit is prefixed with two
# spaces. This way the our caller can find the commit without magic
# strings
#
prefix = ""
if doptions['stdin']:
mpm@selenic.com
hgit: remove tabs...
r334 try:
(type, r) = raw_input().split(' ');
prefix = " "
except EOFError:
return
mpm@selenic.com
Initial import of hgit and hgk...
r267
else:
mpm@selenic.com
hgit: remove tabs...
r334 if len(args) < 2:
help()
sys.exit(1)
mpm@selenic.com
Initial import of hgit and hgk...
r267 type = args[0]
mpm@selenic.com
hgit: remove tabs...
r334 r = args[1]
mpm@selenic.com
Initial import of hgit and hgk...
r267
while r:
mpm@selenic.com
hgit: remove tabs...
r334 if type != "commit":
sys.stderr.write("aborting hg cat-file only understands commits\n")
sys.exit(1);
mason@suse.com
Change hgit revision lookup to use repo.lookup
r720 n = repo.lookup(r)
mpm@selenic.com
hgit: remove tabs...
r334 catcommit(repo, n, prefix)
if doptions['stdin']:
try:
(type, r) = raw_input().split(' ');
except EOFError:
break
else:
break
mpm@selenic.com
Initial import of hgit and hgk...
r267
# git rev-tree is a confusing thing. You can supply a number of
# commit sha1s on the command line, and it walks the commit history
# telling you which commits are reachable from the supplied ones via
# a bitmask based on arg position.
# you can specify a commit to stop at by starting the sha1 with ^
mpm@selenic.com
hgit rev-list support...
r356 def revtree(args, repo, full="tree", maxnr=0):
mpm@selenic.com
Initial import of hgit and hgk...
r267 # calculate and return the reachability bitmask for sha
def is_reachable(ar, reachable, sha):
mpm@selenic.com
hgit: remove tabs...
r334 if len(ar) == 0:
return 1
mask = 0
for i in range(len(ar)):
if sha in reachable[i]:
mask |= 1 << i
mpm@selenic.com
Initial import of hgit and hgk...
r267
mpm@selenic.com
hgit: remove tabs...
r334 return mask
mpm@selenic.com
Initial import of hgit and hgk...
r267
reachable = []
stop_sha1 = []
want_sha1 = []
mpm@selenic.com
hgit rev-list support...
r356 count = 0
mpm@selenic.com
Initial import of hgit and hgk...
r267
# figure out which commits they are asking for and which ones they
# want us to stop on
for i in range(len(args)):
mason@suse.com
Change hgit revision lookup to use repo.lookup
r720 if args[i].startswith('^'):
s = repo.lookup(args[i][1:])
stop_sha1.append(s)
mpm@selenic.com
hgit: remove tabs...
r334 want_sha1.append(s)
elif args[i] != 'HEAD':
mason@suse.com
Change hgit revision lookup to use repo.lookup
r720 want_sha1.append(repo.lookup(args[i]))
mpm@selenic.com
hgit rev-list support...
r356
mpm@selenic.com
Initial import of hgit and hgk...
r267 # calculate the graph for the supplied commits
for i in range(len(want_sha1)):
mpm@selenic.com
hgit: remove tabs...
r334 reachable.append({});
mason@suse.com
Change hgit revision lookup to use repo.lookup
r720 n = want_sha1[i];
mpm@selenic.com
hgit: remove tabs...
r334 visit = [n];
reachable[i][n] = 1
while visit:
n = visit.pop(0)
if n in stop_sha1:
break
for p in repo.changelog.parents(n):
if p not in reachable[i]:
reachable[i][p] = 1
visit.append(p)
if p in stop_sha1:
break
mpm@selenic.com
hgit rev-list support...
r356
mpm@selenic.com
Initial import of hgit and hgk...
r267 # walk the repository looking for commits that are in our
# reachability graph
mpm@selenic.com
hgit rev-list support...
r356 for i in range(repo.changelog.count()-1, -1, -1):
mpm@selenic.com
hgit: remove tabs...
r334 n = repo.changelog.node(i)
mask = is_reachable(want_sha1, reachable, n)
if mask:
mpm@selenic.com
hgit rev-list support...
r356 if not full:
print hg.hex(n)
elif full is "commit":
print hg.hex(n)
catcommit(repo, n, ' ')
else:
changes = repo.changelog.read(n)
(p1, p2) = repo.changelog.parents(n)
(h, h1, h2) = map(hg.hex, (n, p1, p2))
(i1, i2) = map(repo.changelog.rev, (p1, p2))
mpm@selenic.com
Initial import of hgit and hgk...
r267
mpm@selenic.com
hgit rev-list support...
r356 date = changes[2].split(' ')[0]
print "%s %s:%s" % (date, h, mask),
mask = is_reachable(want_sha1, reachable, p1)
if i1 != -1 and mask > 0:
print "%s:%s " % (h1, mask),
mask = is_reachable(want_sha1, reachable, p2)
if i2 != -1 and mask > 0:
print "%s:%s " % (h2, mask),
print ""
if maxnr and count >= maxnr:
break
count += 1
mpm@selenic.com
Initial import of hgit and hgk...
r267
# git rev-list tries to order things by date, and has the ability to stop
# at a given commit without walking the whole repo. TODO add the stop
# parameter
def revlist(args, repo):
doptions = {}
mpm@selenic.com
hgit rev-list support...
r356 opts = [('c', 'commit', None, 'commit'),
('n', 'max-nr', 0, 'max-nr')]
mason@suse.com
Fix hgit usage of repo.changes and fancyopts to reflect current hg api
r719 args = fancyopts.fancyopts(args, opts, doptions)
mpm@selenic.com
hgit rev-list support...
r356 if doptions['commit']:
full = "commit"
else:
full = None
for i in range(1, len(args)):
args[i] = '^' + args[i]
revtree(args, repo, full, doptions['max-nr'])
mpm@selenic.com
Initial import of hgit and hgk...
r267
def catchterm(*args):
raise SignalInterrupt
def help():
sys.stderr.write("commands:\n")
sys.stderr.write(" hgit cat-file [type] sha1\n")
sys.stderr.write(" hgit diff-tree [-p] [-r] sha1 sha1\n")
sys.stderr.write(" hgit rev-tree [sha1 ... [^stop sha1]]\n")
mason@suse.com
Change hgit revision lookup to use repo.lookup
r720 sys.stderr.write(" hgit rev-list [-c] [sha1 [stop sha1]\n")
mpm@selenic.com
Initial import of hgit and hgk...
r267
cmd = sys.argv[1]
args = sys.argv[2:]
u = ui.ui()
signal.signal(signal.SIGTERM, catchterm)
repo = hg.repository(ui = u)
if cmd == "diff-tree":
Thomas Arendsen Hein
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli....
r396 difftree(args, u, repo)
mpm@selenic.com
Initial import of hgit and hgk...
r267
elif cmd == "cat-file":
Thomas Arendsen Hein
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli....
r396 catfile(args, u, repo)
mpm@selenic.com
Initial import of hgit and hgk...
r267
elif cmd == "rev-tree":
revtree(args, repo)
elif cmd == "rev-list":
revlist(args, repo)
elif cmd == "help":
help()
else:
if cmd: sys.stderr.write("unknown command\n\n")
help()
sys.exit(1)
sys.exit(0)