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. |
|
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 |
|
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 |
|
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( |
|
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