##// END OF EJS Templates
Turn hgit into an extension, and add commands supporting the latest gitk
mason@suse.com -
r1239:29f17e08 default
parent child Browse files
Show More
@@ -8,10 +8,61 b''
8 # of the GNU General Public License, incorporated herein by reference.
8 # of the GNU General Public License, incorporated herein by reference.
9
9
10 import time, sys, signal
10 import time, sys, signal
11 from mercurial import hg, mdiff, fancyopts, commands, ui
11 from mercurial import hg, mdiff, fancyopts, commands, ui, util
12
12
13 def difftree(args, ui, repo):
13 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
14 def __difftree(repo, files = None, node1 = None, node2 = None):
14 changes=None, text=False):
15 def date(c):
16 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
17
18 if not changes:
19 (c, a, d, u) = repo.changes(node1, node2, files, match=match)
20 else:
21 (c, a, d, u) = changes
22 if files:
23 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
24
25 if not c and not a and not d:
26 return
27
28 if node2:
29 change = repo.changelog.read(node2)
30 mmap2 = repo.manifest.read(change[0])
31 date2 = date(change)
32 def read(f):
33 return repo.file(f).read(mmap2[f])
34 else:
35 date2 = time.asctime()
36 if not node1:
37 node1 = repo.dirstate.parents()[0]
38 def read(f):
39 return repo.wfile(f).read()
40
41 change = repo.changelog.read(node1)
42 mmap = repo.manifest.read(change[0])
43 date1 = date(change)
44
45 for f in c:
46 to = None
47 if f in mmap:
48 to = repo.file(f).read(mmap[f])
49 tn = read(f)
50 fp.write("diff --git a/%s b/%s\n" % (f, f))
51 fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, text=text))
52 for f in a:
53 to = None
54 tn = read(f)
55 fp.write("diff --git /dev/null b/%s\n" % (f))
56 fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, text=text))
57 for f in d:
58 to = repo.file(f).read(mmap[f])
59 tn = None
60 fp.write("diff --git a/%s /dev/null\n" % (f))
61 fp.write(mdiff.unidiff(to, date1, tn, date2, f, None, text=text))
62
63 def difftree(ui, repo, node1=None, node2=None, **opts):
64 """diff trees from two commits"""
65 def __difftree(repo, node1, node2):
15 def date(c):
66 def date(c):
16 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
67 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
17
68
@@ -23,7 +74,7 b' def difftree(args, ui, repo):'
23 date2 = date(change)
74 date2 = date(change)
24 else:
75 else:
25 date2 = time.asctime()
76 date2 = time.asctime()
26 (c, a, d, u) = repo.diffdir(repo.root, node1)
77 (c, a, d, u) = repo.changes(node1, None)
27 if not node1:
78 if not node1:
28 node1 = repo.dirstate.parents()[0]
79 node1 = repo.dirstate.parents()[0]
29 def read(f): return file(os.path.join(repo.root, f)).read()
80 def read(f): return file(os.path.join(repo.root, f)).read()
@@ -33,9 +84,6 b' def difftree(args, ui, repo):'
33 date1 = date(change)
84 date1 = date(change)
34 empty = "0" * 40;
85 empty = "0" * 40;
35
86
36 if files:
37 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
38
39 for f in c:
87 for f in c:
40 # TODO get file permissions
88 # TODO get file permissions
41 print ":100664 100664 %s %s M\t%s\t%s" % (hg.hex(mmap[f]),
89 print ":100664 100664 %s %s M\t%s\t%s" % (hg.hex(mmap[f]),
@@ -46,66 +94,85 b' def difftree(args, ui, repo):'
46 print ":100664 000000 %s %s D\t%s\t%s" % (hg.hex(mmap[f]), empty, f, f)
94 print ":100664 000000 %s %s D\t%s\t%s" % (hg.hex(mmap[f]), empty, f, f)
47 ##
95 ##
48
96
49 revs = []
97 while True:
50 if args:
98 if opts['stdin']:
51 doptions = {}
99 try:
52 opts = [('p', 'patch', None, 'patch'),
100 line = raw_input().split(' ')
53 ('r', 'recursive', None, 'recursive')]
101 node1 = line[0]
54 args = fancyopts.fancyopts(args, opts, doptions)
102 if len(line) > 1:
103 node2 = line[1]
104 else:
105 node2 = None
106 except EOFError:
107 break
108 node1 = repo.lookup(node1)
109 if node2:
110 node2 = repo.lookup(node2)
111 else:
112 node2 = node1
113 node1 = repo.changelog.parents(node1)[0]
114 if opts['patch']:
115 if opts['pretty']:
116 catcommit(repo, node2, "")
117 dodiff(sys.stdout, ui, repo, node1, node2)
118 else:
119 __difftree(repo, node1, node2)
120 if not opts['stdin']:
121 break
55
122
56 if len(args) < 2:
123 def catcommit(repo, n, prefix, changes=None):
57 help()
58 sys.exit(1)
59 revs.append(repo.lookup(args[0]))
60 revs.append(repo.lookup(args[1]))
61 args = args[2:]
62 if doptions['patch']:
63 commands.dodiff(sys.stdout, ui, repo, args, *revs)
64 else:
65 __difftree(repo, args, *revs)
66
67 def catcommit(repo, n, prefix):
68 nlprefix = '\n' + prefix;
124 nlprefix = '\n' + prefix;
69 changes = repo.changelog.read(n)
70 (p1, p2) = repo.changelog.parents(n)
125 (p1, p2) = repo.changelog.parents(n)
71 (h, h1, h2) = map(hg.hex, (n, p1, p2))
126 (h, h1, h2) = map(hg.hex, (n, p1, p2))
72 (i1, i2) = map(repo.changelog.rev, (p1, p2))
127 (i1, i2) = map(repo.changelog.rev, (p1, p2))
73 print "tree %s" % (h)
128 if not changes:
74 if i1 != -1: print "%sparent %s" % (prefix, h1)
129 changes = repo.changelog.read(n)
75 if i2 != -1: print "%sparent %s" % (prefix, h2)
130 print "tree %s" % (hg.hex(changes[0]))
131 if i1 != -1: print "parent %s" % (h1)
132 if i2 != -1: print "parent %s" % (h2)
76 date_ar = changes[2].split(' ')
133 date_ar = changes[2].split(' ')
77 date = int(float(date_ar[0]))
134 date = int(float(date_ar[0]))
78 print "%sauthor <%s> %s %s" % (prefix, changes[1], date, date_ar[1])
135 lines = changes[4].splitlines()
79 print "%scommitter <%s> %s %s" % (prefix, changes[1], date, date_ar[1])
136 if lines[-1].startswith('committer:'):
80 print prefix
137 committer = lines[-1].split(': ')[1].rstrip()
138 else:
139 committer = "%s %s %s" % (changes[1], date, date_ar[1])
140
141 print "author %s %s %s" % (changes[1], date, date_ar[1])
142 print "committer %s" % (committer)
143 print ""
81 if prefix != "":
144 if prefix != "":
82 print "%s%s" % (prefix, changes[4].replace('\n', nlprefix).strip())
145 print "%s%s" % (prefix, changes[4].replace('\n', nlprefix).strip())
83 else:
146 else:
84 print changes[4]
147 print changes[4]
148 if prefix:
149 sys.stdout.write('\0')
85
150
86 def catfile(args, ui, repo):
151 def base(ui, repo, node1, node2):
87 doptions = {}
152 """Output common ancestor information"""
88 opts = [('s', 'stdin', None, 'stdin')]
153 node1 = repo.lookup(node1)
89 args = fancyopts.fancyopts(args, opts, doptions)
154 node2 = repo.lookup(node2)
155 n = repo.changelog.ancestor(node1, node2)
156 print hg.hex(n)
90
157
158 def catfile(ui, repo, type=None, r=None, **opts):
159 """cat a specific revision"""
91 # in stdin mode, every line except the commit is prefixed with two
160 # in stdin mode, every line except the commit is prefixed with two
92 # spaces. This way the our caller can find the commit without magic
161 # spaces. This way the our caller can find the commit without magic
93 # strings
162 # strings
94 #
163 #
95 prefix = ""
164 prefix = ""
96 if doptions['stdin']:
165 if opts['stdin']:
97 try:
166 try:
98 (type, r) = raw_input().split(' ');
167 (type, r) = raw_input().split(' ');
99 prefix = " "
168 prefix = " "
100 except EOFError:
169 except EOFError:
101 return
170 return
102
171
103 else:
172 else:
104 if len(args) < 2:
173 if not type or not r:
105 help()
174 ui.warn("cat-file: type or revision not supplied\n")
106 sys.exit(1)
175 commands.help_(ui, 'cat-file')
107 type = args[0]
108 r = args[1]
109
176
110 while r:
177 while r:
111 if type != "commit":
178 if type != "commit":
@@ -113,7 +180,7 b' def catfile(args, ui, repo):'
113 sys.exit(1);
180 sys.exit(1);
114 n = repo.lookup(r)
181 n = repo.lookup(r)
115 catcommit(repo, n, prefix)
182 catcommit(repo, n, prefix)
116 if doptions['stdin']:
183 if opts['stdin']:
117 try:
184 try:
118 (type, r) = raw_input().split(' ');
185 (type, r) = raw_input().split(' ');
119 except EOFError:
186 except EOFError:
@@ -126,7 +193,34 b' def catfile(args, ui, repo):'
126 # telling you which commits are reachable from the supplied ones via
193 # telling you which commits are reachable from the supplied ones via
127 # a bitmask based on arg position.
194 # a bitmask based on arg position.
128 # you can specify a commit to stop at by starting the sha1 with ^
195 # you can specify a commit to stop at by starting the sha1 with ^
129 def revtree(args, repo, full="tree", maxnr=0):
196 def revtree(args, repo, full="tree", maxnr=0, parents=False):
197 def chlogwalk():
198 ch = repo.changelog
199 count = ch.count()
200 i = count
201 l = [0] * 100
202 chunk = 100
203 while True:
204 if chunk > i:
205 chunk = i
206 i = 0
207 else:
208 i -= chunk
209
210 for x in xrange(0, chunk):
211 if i + x >= count:
212 l[chunk - x:] = [0] * (chunk - x)
213 break
214 if full != None:
215 l[x] = ch.read(ch.node(i + x))
216 else:
217 l[x] = 1
218 for x in xrange(chunk-1, -1, -1):
219 if l[x] != 0:
220 yield (i + x, full != None and l[x] or None)
221 if i == 0:
222 break
223
130 # calculate and return the reachability bitmask for sha
224 # calculate and return the reachability bitmask for sha
131 def is_reachable(ar, reachable, sha):
225 def is_reachable(ar, reachable, sha):
132 if len(ar) == 0:
226 if len(ar) == 0:
@@ -172,17 +266,24 b' def revtree(args, repo, full="tree", max'
172
266
173 # walk the repository looking for commits that are in our
267 # walk the repository looking for commits that are in our
174 # reachability graph
268 # reachability graph
175 for i in range(repo.changelog.count()-1, -1, -1):
269 #for i in range(repo.changelog.count()-1, -1, -1):
270 for i, changes in chlogwalk():
176 n = repo.changelog.node(i)
271 n = repo.changelog.node(i)
177 mask = is_reachable(want_sha1, reachable, n)
272 mask = is_reachable(want_sha1, reachable, n)
178 if mask:
273 if mask:
274 parentstr = ""
275 if parents:
276 pp = repo.changelog.parents(n)
277 if pp[0] != hg.nullid:
278 parentstr += " " + hg.hex(pp[0])
279 if pp[1] != hg.nullid:
280 parentstr += " " + hg.hex(pp[1])
179 if not full:
281 if not full:
180 print hg.hex(n)
282 print hg.hex(n) + parentstr
181 elif full is "commit":
283 elif full is "commit":
182 print hg.hex(n)
284 print hg.hex(n) + parentstr
183 catcommit(repo, n, ' ')
285 catcommit(repo, n, ' ', changes)
184 else:
286 else:
185 changes = repo.changelog.read(n)
186 (p1, p2) = repo.changelog.parents(n)
287 (p1, p2) = repo.changelog.parents(n)
187 (h, h1, h2) = map(hg.hex, (n, p1, p2))
288 (h, h1, h2) = map(hg.hex, (n, p1, p2))
188 (i1, i2) = map(repo.changelog.rev, (p1, p2))
289 (i1, i2) = map(repo.changelog.rev, (p1, p2))
@@ -203,53 +304,32 b' def revtree(args, repo, full="tree", max'
203 # git rev-list tries to order things by date, and has the ability to stop
304 # git rev-list tries to order things by date, and has the ability to stop
204 # at a given commit without walking the whole repo. TODO add the stop
305 # at a given commit without walking the whole repo. TODO add the stop
205 # parameter
306 # parameter
206 def revlist(args, repo):
307 def revlist(ui, repo, *revs, **opts):
207 doptions = {}
308 """print revisions"""
208 opts = [('c', 'commit', None, 'commit'),
309 if opts['header']:
209 ('n', 'max-nr', 0, 'max-nr')]
210 args = fancyopts.fancyopts(args, opts, doptions)
211 if doptions['commit']:
212 full = "commit"
310 full = "commit"
213 else:
311 else:
214 full = None
312 full = None
215 for i in range(1, len(args)):
313 copy = [x for x in revs]
216 args[i] = '^' + args[i]
314 revtree(copy, repo, full, opts['max_count'], opts['parents'])
217 revtree(args, repo, full, doptions['max-nr'])
218
219 def catchterm(*args):
220 raise SignalInterrupt
221
222 def help():
223 sys.stderr.write("commands:\n")
224 sys.stderr.write(" hgit cat-file [type] sha1\n")
225 sys.stderr.write(" hgit diff-tree [-p] [-r] sha1 sha1\n")
226 sys.stderr.write(" hgit rev-tree [sha1 ... [^stop sha1]]\n")
227 sys.stderr.write(" hgit rev-list [-c] [sha1 [stop sha1]\n")
228
229 cmd = sys.argv[1]
230 args = sys.argv[2:]
231 u = ui.ui()
232 signal.signal(signal.SIGTERM, catchterm)
233 repo = hg.repository(ui = u)
234
315
235 if cmd == "diff-tree":
316 cmdtable = {
236 difftree(args, u, repo)
317 "git-diff-tree": (difftree, [('p', 'patch', None, 'generate patch'),
237
318 ('r', 'recursive', None, 'recursive'),
238 elif cmd == "cat-file":
319 ('P', 'pretty', None, 'pretty'),
239 catfile(args, u, repo)
320 ('s', 'stdin', None, 'stdin'),
240
321 ('C', 'copy', None, 'detect copies'),
241 elif cmd == "rev-tree":
322 ('S', 'search', "", 'search')],
242 revtree(args, repo)
323 "hg git-diff-tree [options] node1 node2"),
324 "git-cat-file": (catfile, [('s', 'stdin', None, 'stdin')],
325 "hg cat-file [options] type file"),
326 "git-merge-base": (base, [], "hg git-merge-base node node"),
327 "git-rev-list": (revlist, [('H', 'header', None, 'header'),
328 ('t', 'topo-order', None, 'topo-order'),
329 ('p', 'parents', None, 'parents'),
330 ('n', 'max-count', 0, 'max-count')],
331 "hg git-rev-list [options] revs"),
332 }
243
333
244 elif cmd == "rev-list":
334 def reposetup(ui, repo):
245 revlist(args, repo)
335 pass
246
247 elif cmd == "help":
248 help()
249
250 else:
251 if cmd: sys.stderr.write("unknown command\n\n")
252 help()
253 sys.exit(1)
254
255 sys.exit(0)
General Comments 0
You need to be logged in to leave comments. Login now