##// END OF EJS Templates
hgk: remove repetitious (and wrong) command syntax descriptions
Andrew Shadura -
r24511:0ecc1e42 default
parent child Browse files
Show More
@@ -1,354 +1,354 b''
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 of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 '''browse the repository in a graphical way
9 9
10 10 The hgk extension allows browsing the history of a repository in a
11 11 graphical way. It requires Tcl/Tk version 8.4 or later. (Tcl/Tk is not
12 12 distributed with Mercurial.)
13 13
14 14 hgk consists of two parts: a Tcl script that does the displaying and
15 15 querying of information, and an extension to Mercurial named hgk.py,
16 16 which provides hooks for hgk to get information. hgk can be found in
17 17 the contrib directory, and the extension is shipped in the hgext
18 18 repository, and needs to be enabled.
19 19
20 20 The :hg:`view` command will launch the hgk Tcl script. For this command
21 21 to work, hgk must be in your search path. Alternately, you can specify
22 22 the path to hgk in your configuration file::
23 23
24 24 [hgk]
25 25 path=/location/of/hgk
26 26
27 27 hgk can make use of the extdiff extension to visualize revisions.
28 28 Assuming you had already configured extdiff vdiff command, just add::
29 29
30 30 [hgk]
31 31 vdiff=vdiff
32 32
33 33 Revisions context menu will now display additional entries to fire
34 34 vdiff on hovered and selected revisions.
35 35 '''
36 36
37 37 import os
38 38 from mercurial import cmdutil, commands, patch, revlog, scmutil
39 39 from mercurial.node import nullid, nullrev, short
40 40 from mercurial.i18n import _
41 41
42 42 cmdtable = {}
43 43 command = cmdutil.command(cmdtable)
44 44 testedwith = 'internal'
45 45
46 46 @command('debug-diff-tree',
47 47 [('p', 'patch', None, _('generate patch')),
48 48 ('r', 'recursive', None, _('recursive')),
49 49 ('P', 'pretty', None, _('pretty')),
50 50 ('s', 'stdin', None, _('stdin')),
51 51 ('C', 'copy', None, _('detect copies')),
52 52 ('S', 'search', "", _('search'))],
53 ('hg git-diff-tree [OPTION]... NODE1 NODE2 [FILE]...'),
53 ('[OPTION]... NODE1 NODE2 [FILE]...'),
54 54 inferrepo=True)
55 55 def difftree(ui, repo, node1=None, node2=None, *files, **opts):
56 56 """diff trees from two commits"""
57 57 def __difftree(repo, node1, node2, files=[]):
58 58 assert node2 is not None
59 59 mmap = repo[node1].manifest()
60 60 mmap2 = repo[node2].manifest()
61 61 m = scmutil.match(repo[node1], files)
62 62 modified, added, removed = repo.status(node1, node2, m)[:3]
63 63 empty = short(nullid)
64 64
65 65 for f in modified:
66 66 # TODO get file permissions
67 67 ui.write(":100664 100664 %s %s M\t%s\t%s\n" %
68 68 (short(mmap[f]), short(mmap2[f]), f, f))
69 69 for f in added:
70 70 ui.write(":000000 100664 %s %s N\t%s\t%s\n" %
71 71 (empty, short(mmap2[f]), f, f))
72 72 for f in removed:
73 73 ui.write(":100664 000000 %s %s D\t%s\t%s\n" %
74 74 (short(mmap[f]), empty, f, f))
75 75 ##
76 76
77 77 while True:
78 78 if opts['stdin']:
79 79 try:
80 80 line = raw_input().split(' ')
81 81 node1 = line[0]
82 82 if len(line) > 1:
83 83 node2 = line[1]
84 84 else:
85 85 node2 = None
86 86 except EOFError:
87 87 break
88 88 node1 = repo.lookup(node1)
89 89 if node2:
90 90 node2 = repo.lookup(node2)
91 91 else:
92 92 node2 = node1
93 93 node1 = repo.changelog.parents(node1)[0]
94 94 if opts['patch']:
95 95 if opts['pretty']:
96 96 catcommit(ui, repo, node2, "")
97 97 m = scmutil.match(repo[node1], files)
98 98 diffopts = patch.difffeatureopts(ui)
99 99 diffopts.git = True
100 100 chunks = patch.diff(repo, node1, node2, match=m,
101 101 opts=diffopts)
102 102 for chunk in chunks:
103 103 ui.write(chunk)
104 104 else:
105 105 __difftree(repo, node1, node2, files=files)
106 106 if not opts['stdin']:
107 107 break
108 108
109 109 def catcommit(ui, repo, n, prefix, ctx=None):
110 110 nlprefix = '\n' + prefix
111 111 if ctx is None:
112 112 ctx = repo[n]
113 113 # use ctx.node() instead ??
114 114 ui.write(("tree %s\n" % short(ctx.changeset()[0])))
115 115 for p in ctx.parents():
116 116 ui.write(("parent %s\n" % p))
117 117
118 118 date = ctx.date()
119 119 description = ctx.description().replace("\0", "")
120 120 lines = description.splitlines()
121 121 if lines and lines[-1].startswith('committer:'):
122 122 committer = lines[-1].split(': ')[1].rstrip()
123 123 else:
124 124 committer = ""
125 125
126 126 ui.write(("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1])))
127 127 if committer != '':
128 128 ui.write(("committer %s %s %s\n" % (committer, int(date[0]), date[1])))
129 129 ui.write(("revision %d\n" % ctx.rev()))
130 130 ui.write(("branch %s\n" % ctx.branch()))
131 131 ui.write(("phase %s\n\n" % ctx.phasestr()))
132 132
133 133 if prefix != "":
134 134 ui.write("%s%s\n" % (prefix,
135 135 description.replace('\n', nlprefix).strip()))
136 136 else:
137 137 ui.write(description + "\n")
138 138 if prefix:
139 139 ui.write('\0')
140 140
141 @command('debug-merge-base', [], _('hg debug-merge-base REV REV'))
141 @command('debug-merge-base', [], _('REV REV'))
142 142 def base(ui, repo, node1, node2):
143 143 """output common ancestor information"""
144 144 node1 = repo.lookup(node1)
145 145 node2 = repo.lookup(node2)
146 146 n = repo.changelog.ancestor(node1, node2)
147 147 ui.write(short(n) + "\n")
148 148
149 149 @command('debug-cat-file',
150 150 [('s', 'stdin', None, _('stdin'))],
151 _('hg debug-cat-file [OPTION]... TYPE FILE'),
151 _('[OPTION]... TYPE FILE'),
152 152 inferrepo=True)
153 153 def catfile(ui, repo, type=None, r=None, **opts):
154 154 """cat a specific revision"""
155 155 # in stdin mode, every line except the commit is prefixed with two
156 156 # spaces. This way the our caller can find the commit without magic
157 157 # strings
158 158 #
159 159 prefix = ""
160 160 if opts['stdin']:
161 161 try:
162 162 (type, r) = raw_input().split(' ')
163 163 prefix = " "
164 164 except EOFError:
165 165 return
166 166
167 167 else:
168 168 if not type or not r:
169 169 ui.warn(_("cat-file: type or revision not supplied\n"))
170 170 commands.help_(ui, 'cat-file')
171 171
172 172 while r:
173 173 if type != "commit":
174 174 ui.warn(_("aborting hg cat-file only understands commits\n"))
175 175 return 1
176 176 n = repo.lookup(r)
177 177 catcommit(ui, repo, n, prefix)
178 178 if opts['stdin']:
179 179 try:
180 180 (type, r) = raw_input().split(' ')
181 181 except EOFError:
182 182 break
183 183 else:
184 184 break
185 185
186 186 # git rev-tree is a confusing thing. You can supply a number of
187 187 # commit sha1s on the command line, and it walks the commit history
188 188 # telling you which commits are reachable from the supplied ones via
189 189 # a bitmask based on arg position.
190 190 # you can specify a commit to stop at by starting the sha1 with ^
191 191 def revtree(ui, args, repo, full="tree", maxnr=0, parents=False):
192 192 def chlogwalk():
193 193 count = len(repo)
194 194 i = count
195 195 l = [0] * 100
196 196 chunk = 100
197 197 while True:
198 198 if chunk > i:
199 199 chunk = i
200 200 i = 0
201 201 else:
202 202 i -= chunk
203 203
204 204 for x in xrange(chunk):
205 205 if i + x >= count:
206 206 l[chunk - x:] = [0] * (chunk - x)
207 207 break
208 208 if full is not None:
209 209 if (i + x) in repo:
210 210 l[x] = repo[i + x]
211 211 l[x].changeset() # force reading
212 212 else:
213 213 if (i + x) in repo:
214 214 l[x] = 1
215 215 for x in xrange(chunk - 1, -1, -1):
216 216 if l[x] != 0:
217 217 yield (i + x, full is not None and l[x] or None)
218 218 if i == 0:
219 219 break
220 220
221 221 # calculate and return the reachability bitmask for sha
222 222 def is_reachable(ar, reachable, sha):
223 223 if len(ar) == 0:
224 224 return 1
225 225 mask = 0
226 226 for i in xrange(len(ar)):
227 227 if sha in reachable[i]:
228 228 mask |= 1 << i
229 229
230 230 return mask
231 231
232 232 reachable = []
233 233 stop_sha1 = []
234 234 want_sha1 = []
235 235 count = 0
236 236
237 237 # figure out which commits they are asking for and which ones they
238 238 # want us to stop on
239 239 for i, arg in enumerate(args):
240 240 if arg.startswith('^'):
241 241 s = repo.lookup(arg[1:])
242 242 stop_sha1.append(s)
243 243 want_sha1.append(s)
244 244 elif arg != 'HEAD':
245 245 want_sha1.append(repo.lookup(arg))
246 246
247 247 # calculate the graph for the supplied commits
248 248 for i, n in enumerate(want_sha1):
249 249 reachable.append(set())
250 250 visit = [n]
251 251 reachable[i].add(n)
252 252 while visit:
253 253 n = visit.pop(0)
254 254 if n in stop_sha1:
255 255 continue
256 256 for p in repo.changelog.parents(n):
257 257 if p not in reachable[i]:
258 258 reachable[i].add(p)
259 259 visit.append(p)
260 260 if p in stop_sha1:
261 261 continue
262 262
263 263 # walk the repository looking for commits that are in our
264 264 # reachability graph
265 265 for i, ctx in chlogwalk():
266 266 if i not in repo:
267 267 continue
268 268 n = repo.changelog.node(i)
269 269 mask = is_reachable(want_sha1, reachable, n)
270 270 if mask:
271 271 parentstr = ""
272 272 if parents:
273 273 pp = repo.changelog.parents(n)
274 274 if pp[0] != nullid:
275 275 parentstr += " " + short(pp[0])
276 276 if pp[1] != nullid:
277 277 parentstr += " " + short(pp[1])
278 278 if not full:
279 279 ui.write("%s%s\n" % (short(n), parentstr))
280 280 elif full == "commit":
281 281 ui.write("%s%s\n" % (short(n), parentstr))
282 282 catcommit(ui, repo, n, ' ', ctx)
283 283 else:
284 284 (p1, p2) = repo.changelog.parents(n)
285 285 (h, h1, h2) = map(short, (n, p1, p2))
286 286 (i1, i2) = map(repo.changelog.rev, (p1, p2))
287 287
288 288 date = ctx.date()[0]
289 289 ui.write("%s %s:%s" % (date, h, mask))
290 290 mask = is_reachable(want_sha1, reachable, p1)
291 291 if i1 != nullrev and mask > 0:
292 292 ui.write("%s:%s " % (h1, mask)),
293 293 mask = is_reachable(want_sha1, reachable, p2)
294 294 if i2 != nullrev and mask > 0:
295 295 ui.write("%s:%s " % (h2, mask))
296 296 ui.write("\n")
297 297 if maxnr and count >= maxnr:
298 298 break
299 299 count += 1
300 300
301 301 @command('debug-rev-parse',
302 302 [('', 'default', '', _('ignored'))],
303 _('hg debug-rev-parse REV'))
303 _('REV'))
304 304 def revparse(ui, repo, *revs, **opts):
305 305 """parse given revisions"""
306 306 def revstr(rev):
307 307 if rev == 'HEAD':
308 308 rev = 'tip'
309 309 return revlog.hex(repo.lookup(rev))
310 310
311 311 for r in revs:
312 312 revrange = r.split(':', 1)
313 313 ui.write('%s\n' % revstr(revrange[0]))
314 314 if len(revrange) == 2:
315 315 ui.write('^%s\n' % revstr(revrange[1]))
316 316
317 317 # git rev-list tries to order things by date, and has the ability to stop
318 318 # at a given commit without walking the whole repo. TODO add the stop
319 319 # parameter
320 320 @command('debug-rev-list',
321 321 [('H', 'header', None, _('header')),
322 322 ('t', 'topo-order', None, _('topo-order')),
323 323 ('p', 'parents', None, _('parents')),
324 324 ('n', 'max-count', 0, _('max-count'))],
325 ('hg debug-rev-list [OPTION]... REV...'))
325 ('[OPTION]... REV...'))
326 326 def revlist(ui, repo, *revs, **opts):
327 327 """print revisions"""
328 328 if opts['header']:
329 329 full = "commit"
330 330 else:
331 331 full = None
332 332 copy = [x for x in revs]
333 333 revtree(ui, copy, repo, full, opts['max_count'], opts['parents'])
334 334
335 335 @command('debug-config', [], _('hg debug-config'))
336 336 def config(ui, repo, **opts):
337 337 """print extension options"""
338 338 def writeopt(name, value):
339 339 ui.write(('k=%s\nv=%s\n' % (name, value)))
340 340
341 341 writeopt('vdiff', ui.config('hgk', 'vdiff', ''))
342 342
343 343
344 344 @command('view',
345 345 [('l', 'limit', '',
346 346 _('limit number of changes displayed'), _('NUM'))],
347 _('hg view [-l LIMIT] [REVRANGE]'))
347 _('[-l LIMIT] [REVRANGE]'))
348 348 def view(ui, repo, *etc, **opts):
349 349 "start interactive history viewer"
350 350 os.chdir(repo.root)
351 351 optstr = ' '.join(['--%s %s' % (k, v) for k, v in opts.iteritems() if v])
352 352 cmd = ui.config("hgk", "path", "hgk") + " %s %s" % (optstr, " ".join(etc))
353 353 ui.debug("running %s\n" % cmd)
354 354 ui.system(cmd)
General Comments 0
You need to be logged in to leave comments. Login now