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