##// END OF EJS Templates
hgk: fix mixup of --limit and REVRANGE in hgk call
TK Soh -
r3180:eb0906eb default
parent child Browse files
Show More
@@ -1,307 +1,309
1 # Minimal support for git commands on an hg repository
1 # Minimal support for git commands on an hg repository
2 #
2 #
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from mercurial.demandload import *
8 from mercurial.demandload import *
9 demandload(globals(), 'time sys signal os')
9 demandload(globals(), 'time sys signal os')
10 demandload(globals(), 'mercurial:hg,fancyopts,commands,ui,util,patch,revlog')
10 demandload(globals(), 'mercurial:hg,fancyopts,commands,ui,util,patch,revlog')
11
11
12 def difftree(ui, repo, node1=None, node2=None, *files, **opts):
12 def difftree(ui, repo, node1=None, node2=None, *files, **opts):
13 """diff trees from two commits"""
13 """diff trees from two commits"""
14 def __difftree(repo, node1, node2, files=[]):
14 def __difftree(repo, node1, node2, files=[]):
15 if node2:
15 if node2:
16 change = repo.changelog.read(node2)
16 change = repo.changelog.read(node2)
17 mmap2 = repo.manifest.read(change[0])
17 mmap2 = repo.manifest.read(change[0])
18 status = repo.status(node1, node2, files=files)[:5]
18 status = repo.status(node1, node2, files=files)[:5]
19 modified, added, removed, deleted, unknown = status
19 modified, added, removed, deleted, unknown = status
20 else:
20 else:
21 status = repo.status(node1, files=files)[:5]
21 status = repo.status(node1, files=files)[:5]
22 modified, added, removed, deleted, unknown = status
22 modified, added, removed, deleted, unknown = status
23 if not node1:
23 if not node1:
24 node1 = repo.dirstate.parents()[0]
24 node1 = repo.dirstate.parents()[0]
25
25
26 change = repo.changelog.read(node1)
26 change = repo.changelog.read(node1)
27 mmap = repo.manifest.read(change[0])
27 mmap = repo.manifest.read(change[0])
28 empty = hg.short(hg.nullid)
28 empty = hg.short(hg.nullid)
29
29
30 for f in modified:
30 for f in modified:
31 # TODO get file permissions
31 # TODO get file permissions
32 print ":100664 100664 %s %s M\t%s\t%s" % (hg.short(mmap[f]),
32 print ":100664 100664 %s %s M\t%s\t%s" % (hg.short(mmap[f]),
33 hg.short(mmap2[f]),
33 hg.short(mmap2[f]),
34 f, f)
34 f, f)
35 for f in added:
35 for f in added:
36 print ":000000 100664 %s %s N\t%s\t%s" % (empty,
36 print ":000000 100664 %s %s N\t%s\t%s" % (empty,
37 hg.short(mmap2[f]),
37 hg.short(mmap2[f]),
38 f, f)
38 f, f)
39 for f in removed:
39 for f in removed:
40 print ":100664 000000 %s %s D\t%s\t%s" % (hg.short(mmap[f]),
40 print ":100664 000000 %s %s D\t%s\t%s" % (hg.short(mmap[f]),
41 empty,
41 empty,
42 f, f)
42 f, f)
43 ##
43 ##
44
44
45 while True:
45 while True:
46 if opts['stdin']:
46 if opts['stdin']:
47 try:
47 try:
48 line = raw_input().split(' ')
48 line = raw_input().split(' ')
49 node1 = line[0]
49 node1 = line[0]
50 if len(line) > 1:
50 if len(line) > 1:
51 node2 = line[1]
51 node2 = line[1]
52 else:
52 else:
53 node2 = None
53 node2 = None
54 except EOFError:
54 except EOFError:
55 break
55 break
56 node1 = repo.lookup(node1)
56 node1 = repo.lookup(node1)
57 if node2:
57 if node2:
58 node2 = repo.lookup(node2)
58 node2 = repo.lookup(node2)
59 else:
59 else:
60 node2 = node1
60 node2 = node1
61 node1 = repo.changelog.parents(node1)[0]
61 node1 = repo.changelog.parents(node1)[0]
62 if opts['patch']:
62 if opts['patch']:
63 if opts['pretty']:
63 if opts['pretty']:
64 catcommit(repo, node2, "")
64 catcommit(repo, node2, "")
65 patch.diff(repo, node1, node2,
65 patch.diff(repo, node1, node2,
66 files=files,
66 files=files,
67 opts=patch.diffopts(ui, {'git': True}))
67 opts=patch.diffopts(ui, {'git': True}))
68 else:
68 else:
69 __difftree(repo, node1, node2, files=files)
69 __difftree(repo, node1, node2, files=files)
70 if not opts['stdin']:
70 if not opts['stdin']:
71 break
71 break
72
72
73 def catcommit(repo, n, prefix, changes=None):
73 def catcommit(repo, n, prefix, changes=None):
74 nlprefix = '\n' + prefix;
74 nlprefix = '\n' + prefix;
75 (p1, p2) = repo.changelog.parents(n)
75 (p1, p2) = repo.changelog.parents(n)
76 (h, h1, h2) = map(hg.short, (n, p1, p2))
76 (h, h1, h2) = map(hg.short, (n, p1, p2))
77 (i1, i2) = map(repo.changelog.rev, (p1, p2))
77 (i1, i2) = map(repo.changelog.rev, (p1, p2))
78 if not changes:
78 if not changes:
79 changes = repo.changelog.read(n)
79 changes = repo.changelog.read(n)
80 print "tree %s" % (hg.short(changes[0]))
80 print "tree %s" % (hg.short(changes[0]))
81 if i1 != -1: print "parent %s" % (h1)
81 if i1 != -1: print "parent %s" % (h1)
82 if i2 != -1: print "parent %s" % (h2)
82 if i2 != -1: print "parent %s" % (h2)
83 date_ar = changes[2]
83 date_ar = changes[2]
84 date = int(float(date_ar[0]))
84 date = int(float(date_ar[0]))
85 lines = changes[4].splitlines()
85 lines = changes[4].splitlines()
86 if lines and lines[-1].startswith('committer:'):
86 if lines and lines[-1].startswith('committer:'):
87 committer = lines[-1].split(': ')[1].rstrip()
87 committer = lines[-1].split(': ')[1].rstrip()
88 else:
88 else:
89 committer = changes[1]
89 committer = changes[1]
90
90
91 print "author %s %s %s" % (changes[1], date, date_ar[1])
91 print "author %s %s %s" % (changes[1], date, date_ar[1])
92 print "committer %s %s %s" % (committer, date, date_ar[1])
92 print "committer %s %s %s" % (committer, date, date_ar[1])
93 print "revision %d" % repo.changelog.rev(n)
93 print "revision %d" % repo.changelog.rev(n)
94 print ""
94 print ""
95 if prefix != "":
95 if prefix != "":
96 print "%s%s" % (prefix, changes[4].replace('\n', nlprefix).strip())
96 print "%s%s" % (prefix, changes[4].replace('\n', nlprefix).strip())
97 else:
97 else:
98 print changes[4]
98 print changes[4]
99 if prefix:
99 if prefix:
100 sys.stdout.write('\0')
100 sys.stdout.write('\0')
101
101
102 def base(ui, repo, node1, node2):
102 def base(ui, repo, node1, node2):
103 """Output common ancestor information"""
103 """Output common ancestor information"""
104 node1 = repo.lookup(node1)
104 node1 = repo.lookup(node1)
105 node2 = repo.lookup(node2)
105 node2 = repo.lookup(node2)
106 n = repo.changelog.ancestor(node1, node2)
106 n = repo.changelog.ancestor(node1, node2)
107 print hg.short(n)
107 print hg.short(n)
108
108
109 def catfile(ui, repo, type=None, r=None, **opts):
109 def catfile(ui, repo, type=None, r=None, **opts):
110 """cat a specific revision"""
110 """cat a specific revision"""
111 # in stdin mode, every line except the commit is prefixed with two
111 # in stdin mode, every line except the commit is prefixed with two
112 # spaces. This way the our caller can find the commit without magic
112 # spaces. This way the our caller can find the commit without magic
113 # strings
113 # strings
114 #
114 #
115 prefix = ""
115 prefix = ""
116 if opts['stdin']:
116 if opts['stdin']:
117 try:
117 try:
118 (type, r) = raw_input().split(' ');
118 (type, r) = raw_input().split(' ');
119 prefix = " "
119 prefix = " "
120 except EOFError:
120 except EOFError:
121 return
121 return
122
122
123 else:
123 else:
124 if not type or not r:
124 if not type or not r:
125 ui.warn("cat-file: type or revision not supplied\n")
125 ui.warn("cat-file: type or revision not supplied\n")
126 commands.help_(ui, 'cat-file')
126 commands.help_(ui, 'cat-file')
127
127
128 while r:
128 while r:
129 if type != "commit":
129 if type != "commit":
130 sys.stderr.write("aborting hg cat-file only understands commits\n")
130 sys.stderr.write("aborting hg cat-file only understands commits\n")
131 sys.exit(1);
131 sys.exit(1);
132 n = repo.lookup(r)
132 n = repo.lookup(r)
133 catcommit(repo, n, prefix)
133 catcommit(repo, n, prefix)
134 if opts['stdin']:
134 if opts['stdin']:
135 try:
135 try:
136 (type, r) = raw_input().split(' ');
136 (type, r) = raw_input().split(' ');
137 except EOFError:
137 except EOFError:
138 break
138 break
139 else:
139 else:
140 break
140 break
141
141
142 # git rev-tree is a confusing thing. You can supply a number of
142 # git rev-tree is a confusing thing. You can supply a number of
143 # commit sha1s on the command line, and it walks the commit history
143 # commit sha1s on the command line, and it walks the commit history
144 # telling you which commits are reachable from the supplied ones via
144 # telling you which commits are reachable from the supplied ones via
145 # a bitmask based on arg position.
145 # a bitmask based on arg position.
146 # you can specify a commit to stop at by starting the sha1 with ^
146 # you can specify a commit to stop at by starting the sha1 with ^
147 def revtree(args, repo, full="tree", maxnr=0, parents=False):
147 def revtree(args, repo, full="tree", maxnr=0, parents=False):
148 def chlogwalk():
148 def chlogwalk():
149 ch = repo.changelog
149 ch = repo.changelog
150 count = ch.count()
150 count = ch.count()
151 i = count
151 i = count
152 l = [0] * 100
152 l = [0] * 100
153 chunk = 100
153 chunk = 100
154 while True:
154 while True:
155 if chunk > i:
155 if chunk > i:
156 chunk = i
156 chunk = i
157 i = 0
157 i = 0
158 else:
158 else:
159 i -= chunk
159 i -= chunk
160
160
161 for x in xrange(0, chunk):
161 for x in xrange(0, chunk):
162 if i + x >= count:
162 if i + x >= count:
163 l[chunk - x:] = [0] * (chunk - x)
163 l[chunk - x:] = [0] * (chunk - x)
164 break
164 break
165 if full != None:
165 if full != None:
166 l[x] = ch.read(ch.node(i + x))
166 l[x] = ch.read(ch.node(i + x))
167 else:
167 else:
168 l[x] = 1
168 l[x] = 1
169 for x in xrange(chunk-1, -1, -1):
169 for x in xrange(chunk-1, -1, -1):
170 if l[x] != 0:
170 if l[x] != 0:
171 yield (i + x, full != None and l[x] or None)
171 yield (i + x, full != None and l[x] or None)
172 if i == 0:
172 if i == 0:
173 break
173 break
174
174
175 # calculate and return the reachability bitmask for sha
175 # calculate and return the reachability bitmask for sha
176 def is_reachable(ar, reachable, sha):
176 def is_reachable(ar, reachable, sha):
177 if len(ar) == 0:
177 if len(ar) == 0:
178 return 1
178 return 1
179 mask = 0
179 mask = 0
180 for i in range(len(ar)):
180 for i in range(len(ar)):
181 if sha in reachable[i]:
181 if sha in reachable[i]:
182 mask |= 1 << i
182 mask |= 1 << i
183
183
184 return mask
184 return mask
185
185
186 reachable = []
186 reachable = []
187 stop_sha1 = []
187 stop_sha1 = []
188 want_sha1 = []
188 want_sha1 = []
189 count = 0
189 count = 0
190
190
191 # figure out which commits they are asking for and which ones they
191 # figure out which commits they are asking for and which ones they
192 # want us to stop on
192 # want us to stop on
193 for i in range(len(args)):
193 for i in range(len(args)):
194 if args[i].startswith('^'):
194 if args[i].startswith('^'):
195 s = repo.lookup(args[i][1:])
195 s = repo.lookup(args[i][1:])
196 stop_sha1.append(s)
196 stop_sha1.append(s)
197 want_sha1.append(s)
197 want_sha1.append(s)
198 elif args[i] != 'HEAD':
198 elif args[i] != 'HEAD':
199 want_sha1.append(repo.lookup(args[i]))
199 want_sha1.append(repo.lookup(args[i]))
200
200
201 # calculate the graph for the supplied commits
201 # calculate the graph for the supplied commits
202 for i in range(len(want_sha1)):
202 for i in range(len(want_sha1)):
203 reachable.append({});
203 reachable.append({});
204 n = want_sha1[i];
204 n = want_sha1[i];
205 visit = [n];
205 visit = [n];
206 reachable[i][n] = 1
206 reachable[i][n] = 1
207 while visit:
207 while visit:
208 n = visit.pop(0)
208 n = visit.pop(0)
209 if n in stop_sha1:
209 if n in stop_sha1:
210 continue
210 continue
211 for p in repo.changelog.parents(n):
211 for p in repo.changelog.parents(n):
212 if p not in reachable[i]:
212 if p not in reachable[i]:
213 reachable[i][p] = 1
213 reachable[i][p] = 1
214 visit.append(p)
214 visit.append(p)
215 if p in stop_sha1:
215 if p in stop_sha1:
216 continue
216 continue
217
217
218 # walk the repository looking for commits that are in our
218 # walk the repository looking for commits that are in our
219 # reachability graph
219 # reachability graph
220 for i, changes in chlogwalk():
220 for i, changes in chlogwalk():
221 n = repo.changelog.node(i)
221 n = repo.changelog.node(i)
222 mask = is_reachable(want_sha1, reachable, n)
222 mask = is_reachable(want_sha1, reachable, n)
223 if mask:
223 if mask:
224 parentstr = ""
224 parentstr = ""
225 if parents:
225 if parents:
226 pp = repo.changelog.parents(n)
226 pp = repo.changelog.parents(n)
227 if pp[0] != hg.nullid:
227 if pp[0] != hg.nullid:
228 parentstr += " " + hg.short(pp[0])
228 parentstr += " " + hg.short(pp[0])
229 if pp[1] != hg.nullid:
229 if pp[1] != hg.nullid:
230 parentstr += " " + hg.short(pp[1])
230 parentstr += " " + hg.short(pp[1])
231 if not full:
231 if not full:
232 print hg.short(n) + parentstr
232 print hg.short(n) + parentstr
233 elif full == "commit":
233 elif full == "commit":
234 print hg.short(n) + parentstr
234 print hg.short(n) + parentstr
235 catcommit(repo, n, ' ', changes)
235 catcommit(repo, n, ' ', changes)
236 else:
236 else:
237 (p1, p2) = repo.changelog.parents(n)
237 (p1, p2) = repo.changelog.parents(n)
238 (h, h1, h2) = map(hg.short, (n, p1, p2))
238 (h, h1, h2) = map(hg.short, (n, p1, p2))
239 (i1, i2) = map(repo.changelog.rev, (p1, p2))
239 (i1, i2) = map(repo.changelog.rev, (p1, p2))
240
240
241 date = changes[2][0]
241 date = changes[2][0]
242 print "%s %s:%s" % (date, h, mask),
242 print "%s %s:%s" % (date, h, mask),
243 mask = is_reachable(want_sha1, reachable, p1)
243 mask = is_reachable(want_sha1, reachable, p1)
244 if i1 != -1 and mask > 0:
244 if i1 != -1 and mask > 0:
245 print "%s:%s " % (h1, mask),
245 print "%s:%s " % (h1, mask),
246 mask = is_reachable(want_sha1, reachable, p2)
246 mask = is_reachable(want_sha1, reachable, p2)
247 if i2 != -1 and mask > 0:
247 if i2 != -1 and mask > 0:
248 print "%s:%s " % (h2, mask),
248 print "%s:%s " % (h2, mask),
249 print ""
249 print ""
250 if maxnr and count >= maxnr:
250 if maxnr and count >= maxnr:
251 break
251 break
252 count += 1
252 count += 1
253
253
254 def revparse(ui, repo, *revs, **opts):
254 def revparse(ui, repo, *revs, **opts):
255 """Parse given revisions"""
255 """Parse given revisions"""
256 def revstr(rev):
256 def revstr(rev):
257 if rev == 'HEAD':
257 if rev == 'HEAD':
258 rev = 'tip'
258 rev = 'tip'
259 return revlog.hex(repo.lookup(rev))
259 return revlog.hex(repo.lookup(rev))
260
260
261 for r in revs:
261 for r in revs:
262 revrange = r.split(':', 1)
262 revrange = r.split(':', 1)
263 ui.write('%s\n' % revstr(revrange[0]))
263 ui.write('%s\n' % revstr(revrange[0]))
264 if len(revrange) == 2:
264 if len(revrange) == 2:
265 ui.write('^%s\n' % revstr(revrange[1]))
265 ui.write('^%s\n' % revstr(revrange[1]))
266
266
267 # git rev-list tries to order things by date, and has the ability to stop
267 # git rev-list tries to order things by date, and has the ability to stop
268 # at a given commit without walking the whole repo. TODO add the stop
268 # at a given commit without walking the whole repo. TODO add the stop
269 # parameter
269 # parameter
270 def revlist(ui, repo, *revs, **opts):
270 def revlist(ui, repo, *revs, **opts):
271 """print revisions"""
271 """print revisions"""
272 if opts['header']:
272 if opts['header']:
273 full = "commit"
273 full = "commit"
274 else:
274 else:
275 full = None
275 full = None
276 copy = [x for x in revs]
276 copy = [x for x in revs]
277 revtree(copy, repo, full, opts['max_count'], opts['parents'])
277 revtree(copy, repo, full, opts['max_count'], opts['parents'])
278
278
279 def view(ui, repo, *etc, **opts):
279 def view(ui, repo, *etc, **opts):
280 "start interactive history viewer"
280 "start interactive history viewer"
281 os.chdir(repo.root)
281 os.chdir(repo.root)
282 optstr = ' '.join(['--%s %s' % (k, v) for k, v in opts.iteritems()])
282 optstr = ' '.join(['--%s %s' % (k, v) for k, v in opts.iteritems() if v])
283 os.system(ui.config("hgk", "path", "hgk") + " %s %s" % (optstr, " ".join(etc)))
283 cmd = ui.config("hgk", "path", "hgk") + " %s %s" % (optstr, " ".join(etc))
284 ui.debug("running %s\n" % cmd)
285 os.system(cmd)
284
286
285 cmdtable = {
287 cmdtable = {
286 "view": (view,
288 "view": (view,
287 [('l', 'limit', '', 'limit number of changes displayed')],
289 [('l', 'limit', '', 'limit number of changes displayed')],
288 'hg view [-l LIMIT] [REVRANGE]'),
290 'hg view [-l LIMIT] [REVRANGE]'),
289 "debug-diff-tree": (difftree, [('p', 'patch', None, 'generate patch'),
291 "debug-diff-tree": (difftree, [('p', 'patch', None, 'generate patch'),
290 ('r', 'recursive', None, 'recursive'),
292 ('r', 'recursive', None, 'recursive'),
291 ('P', 'pretty', None, 'pretty'),
293 ('P', 'pretty', None, 'pretty'),
292 ('s', 'stdin', None, 'stdin'),
294 ('s', 'stdin', None, 'stdin'),
293 ('C', 'copy', None, 'detect copies'),
295 ('C', 'copy', None, 'detect copies'),
294 ('S', 'search', "", 'search')],
296 ('S', 'search', "", 'search')],
295 "hg git-diff-tree [options] node1 node2 [files...]"),
297 "hg git-diff-tree [options] node1 node2 [files...]"),
296 "debug-cat-file": (catfile, [('s', 'stdin', None, 'stdin')],
298 "debug-cat-file": (catfile, [('s', 'stdin', None, 'stdin')],
297 "hg debug-cat-file [options] type file"),
299 "hg debug-cat-file [options] type file"),
298 "debug-merge-base": (base, [], "hg debug-merge-base node node"),
300 "debug-merge-base": (base, [], "hg debug-merge-base node node"),
299 'debug-rev-parse': (revparse,
301 'debug-rev-parse': (revparse,
300 [('', 'default', '', 'ignored')],
302 [('', 'default', '', 'ignored')],
301 "hg debug-rev-parse rev"),
303 "hg debug-rev-parse rev"),
302 "debug-rev-list": (revlist, [('H', 'header', None, 'header'),
304 "debug-rev-list": (revlist, [('H', 'header', None, 'header'),
303 ('t', 'topo-order', None, 'topo-order'),
305 ('t', 'topo-order', None, 'topo-order'),
304 ('p', 'parents', None, 'parents'),
306 ('p', 'parents', None, 'parents'),
305 ('n', 'max-count', 0, 'max-count')],
307 ('n', 'max-count', 0, 'max-count')],
306 "hg debug-rev-list [options] revs"),
308 "hg debug-rev-list [options] revs"),
307 }
309 }
General Comments 0
You need to be logged in to leave comments. Login now