##// END OF EJS Templates
Cleaned up show_changeset()...
Thomas Arendsen Hein -
r347:a0b2758e default
parent child Browse files
Show More
@@ -1,717 +1,717 b''
1 1 # commands.py - command processing for mercurial
2 2 #
3 3 # Copyright 2005 Matt Mackall <mpm@selenic.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 import os, re, sys, signal
9 9 import fancyopts, ui, hg
10 10 from demandload import *
11 11 demandload(globals(), "mdiff time hgweb traceback random signal")
12 12
13 13 class UnknownCommand(Exception): pass
14 14
15 15 def filterfiles(filters, files):
16 16 l = [ x for x in files if x in filters ]
17 17
18 18 for t in filters:
19 19 if t and t[-1] != os.sep: t += os.sep
20 20 l += [ x for x in files if x.startswith(t) ]
21 21 return l
22 22
23 23 def relfilter(repo, files):
24 24 if os.getcwd() != repo.root:
25 25 p = os.getcwd()[len(repo.root) + 1: ]
26 26 return filterfiles([p], files)
27 27 return files
28 28
29 29 def relpath(repo, args):
30 30 if os.getcwd() != repo.root:
31 31 p = os.getcwd()[len(repo.root) + 1: ]
32 32 return [ os.path.normpath(os.path.join(p, x)) for x in args ]
33 33 return args
34 34
35 35 def dodiff(repo, path, files = None, node1 = None, node2 = None):
36 36 def date(c):
37 37 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
38 38
39 39 if node2:
40 40 change = repo.changelog.read(node2)
41 41 mmap2 = repo.manifest.read(change[0])
42 42 (c, a, d) = repo.diffrevs(node1, node2)
43 43 def read(f): return repo.file(f).read(mmap2[f])
44 44 date2 = date(change)
45 45 else:
46 46 date2 = time.asctime()
47 47 (c, a, d, u) = repo.diffdir(path, node1)
48 48 if not node1:
49 49 node1 = repo.dirstate.parents()[0]
50 50 def read(f): return file(os.path.join(repo.root, f)).read()
51 51
52 52 change = repo.changelog.read(node1)
53 53 mmap = repo.manifest.read(change[0])
54 54 date1 = date(change)
55 55
56 56 if files:
57 57 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
58 58
59 59 for f in c:
60 60 to = None
61 61 if f in mmap:
62 62 to = repo.file(f).read(mmap[f])
63 63 tn = read(f)
64 64 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
65 65 for f in a:
66 66 to = None
67 67 tn = read(f)
68 68 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
69 69 for f in d:
70 70 to = repo.file(f).read(mmap[f])
71 71 tn = None
72 72 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
73 73
74 74 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
75 75 """show a single changeset or file revision"""
76 76 changelog = repo.changelog
77 77 if filelog:
78 78 log = filelog
79 79 filerev = rev
80 80 node = filenode = filelog.node(filerev)
81 81 changerev = filelog.linkrev(filenode)
82 82 changenode = changenode or changelog.node(changerev)
83 83 else:
84 log = changelog
84 85 changerev = rev
85 log = changelog
86 86 if changenode is None:
87 87 changenode = changelog.node(changerev)
88 88 elif not changerev:
89 89 rev = changerev = changelog.rev(changenode)
90 90 node = changenode
91 91
92 92 if ui.quiet:
93 93 ui.write("%d:%s\n" % (rev, hg.hex(node)))
94 94 return
95 95
96 96 changes = changelog.read(changenode)
97 description = changes[4].strip().splitlines()
98 97
99 98 parents = [(log.rev(parent), hg.hex(parent))
100 99 for parent in log.parents(node)
101 100 if ui.debugflag or parent != hg.nullid]
102 101 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
103 102 parents = []
104 103
105 104 if filelog:
106 105 ui.write("revision: %d:%s\n" % (filerev, hg.hex(filenode)))
107 106 for parent in parents:
108 107 ui.write("parent: %d:%s\n" % parent)
109 108 ui.status("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
110 109 else:
111 110 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
112 111 for parent in parents:
113 112 ui.write("parent: %d:%s\n" % parent)
114 113 ui.note("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
115 114 hg.hex(changes[0])))
116 115 ui.status("user: %s\n" % changes[1])
117 116 ui.status("date: %s\n" % time.asctime(
118 117 time.localtime(float(changes[2].split(' ')[0]))))
119 118 ui.note("files: %s\n" % " ".join(changes[3]))
119 description = changes[4].strip()
120 120 if description:
121 121 if ui.verbose:
122 122 ui.status("description:\n")
123 ui.status(changes[4].strip())
124 ui.status("\n")
123 ui.status(description)
124 ui.status("\n\n")
125 125 else:
126 ui.status("summary: %s\n" % description[0])
126 ui.status("summary: %s\n" % description.splitlines()[0])
127 127 ui.status("\n")
128 128
129 129 def help(ui, cmd=None):
130 130 '''show help for a given command or all commands'''
131 131 if cmd:
132 132 try:
133 133 i = find(cmd)
134 134 ui.write("%s\n\n" % i[2])
135 135
136 136 if i[1]:
137 137 for s, l, d, c in i[1]:
138 138 opt=' '
139 139 if s: opt = opt + '-' + s + ' '
140 140 if l: opt = opt + '--' + l + ' '
141 141 if d: opt = opt + '(' + str(d) + ')'
142 142 ui.write(opt, "\n")
143 143 if c: ui.write(' %s\n' % c)
144 144 ui.write("\n")
145 145
146 146 ui.write(i[0].__doc__, "\n")
147 147 except UnknownCommand:
148 148 ui.warn("hg: unknown command %s\n" % cmd)
149 149 sys.exit(0)
150 150 else:
151 151 ui.status('hg commands:\n\n')
152 152
153 153 h = {}
154 154 for e in table.values():
155 155 f = e[0]
156 156 if f.__name__.startswith("debug"): continue
157 157 d = ""
158 158 if f.__doc__:
159 159 d = f.__doc__.splitlines(0)[0].rstrip()
160 160 h[f.__name__] = d
161 161
162 162 fns = h.keys()
163 163 fns.sort()
164 164 m = max(map(len, fns))
165 165 for f in fns:
166 166 ui.status(' %-*s %s\n' % (m, f, h[f]))
167 167
168 168 # Commands start here, listed alphabetically
169 169
170 170 def add(ui, repo, file, *files):
171 171 '''add the specified files on the next commit'''
172 172 repo.add(relpath(repo, (file,) + files))
173 173
174 174 def addremove(ui, repo):
175 175 """add all new files, delete all missing files"""
176 176 (c, a, d, u) = repo.diffdir(repo.root)
177 177 repo.add(u)
178 178 repo.remove(d)
179 179
180 180 def annotate(u, repo, file, *files, **ops):
181 181 """show changeset information per file line"""
182 182 def getnode(rev):
183 183 return hg.short(repo.changelog.node(rev))
184 184
185 185 def getname(rev):
186 186 try:
187 187 return bcache[rev]
188 188 except KeyError:
189 189 cl = repo.changelog.read(repo.changelog.node(rev))
190 190 name = cl[1]
191 191 f = name.find('@')
192 192 if f >= 0:
193 193 name = name[:f]
194 194 bcache[rev] = name
195 195 return name
196 196
197 197 bcache = {}
198 198 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
199 199 if not ops['user'] and not ops['changeset']:
200 200 ops['number'] = 1
201 201
202 202 node = repo.dirstate.parents()[0]
203 203 if ops['revision']:
204 204 node = repo.changelog.lookup(ops['revision'])
205 205 change = repo.changelog.read(node)
206 206 mmap = repo.manifest.read(change[0])
207 207 maxuserlen = 0
208 208 maxchangelen = 0
209 209 for f in relpath(repo, (file,) + files):
210 210 lines = repo.file(f).annotate(mmap[f])
211 211 pieces = []
212 212
213 213 for o, f in opmap:
214 214 if ops[o]:
215 215 l = [ f(n) for n,t in lines ]
216 216 m = max(map(len, l))
217 217 pieces.append([ "%*s" % (m, x) for x in l])
218 218
219 219 for p,l in zip(zip(*pieces), lines):
220 220 u.write(" ".join(p) + ": " + l[1])
221 221
222 222 def cat(ui, repo, file, rev = []):
223 223 """output the latest or given revision of a file"""
224 224 r = repo.file(relpath(repo, [file])[0])
225 225 n = r.tip()
226 226 if rev: n = r.lookup(rev)
227 227 sys.stdout.write(r.read(n))
228 228
229 229 def commit(ui, repo, *files, **opts):
230 230 """commit the specified files or all outstanding changes"""
231 231 text = opts['text']
232 232 if not text and opts['logfile']:
233 233 try: text = open(opts['logfile']).read()
234 234 except IOError: pass
235 235
236 236 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
237 237
238 238 def debugaddchangegroup(ui, repo):
239 239 data = sys.stdin.read()
240 240 repo.addchangegroup(data)
241 241
242 242 def debugchangegroup(ui, repo, roots):
243 243 newer = repo.newer(map(repo.lookup, roots))
244 244 for chunk in repo.changegroup(newer):
245 245 sys.stdout.write(chunk)
246 246
247 247 def debugindex(ui, file):
248 248 r = hg.revlog(open, file, "")
249 249 print " rev offset length base linkrev"+\
250 250 " p1 p2 nodeid"
251 251 for i in range(r.count()):
252 252 e = r.index[i]
253 253 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
254 254 i, e[0], e[1], e[2], e[3],
255 255 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
256 256
257 257 def debugindexdot(ui, file):
258 258 r = hg.revlog(open, file, "")
259 259 print "digraph G {"
260 260 for i in range(r.count()):
261 261 e = r.index[i]
262 262 print "\t%d -> %d" % (r.rev(e[4]), i)
263 263 if e[5] != hg.nullid:
264 264 print "\t%d -> %d" % (r.rev(e[5]), i)
265 265 print "}"
266 266
267 267 def diff(ui, repo, *files, **opts):
268 268 """diff working directory (or selected files)"""
269 269 revs = []
270 270 if opts['rev']:
271 271 revs = map(lambda x: repo.lookup(x), opts['rev'])
272 272
273 273 if len(revs) > 2:
274 274 self.ui.warn("too many revisions to diff\n")
275 275 sys.exit(1)
276 276
277 277 if files:
278 278 files = relpath(repo, files)
279 279 else:
280 280 files = relpath(repo, [""])
281 281
282 282 dodiff(repo, os.getcwd(), files, *revs)
283 283
284 284 def export(ui, repo, changeset):
285 285 """dump the changeset header and diffs for a revision"""
286 286 node = repo.lookup(changeset)
287 287 prev, other = repo.changelog.parents(node)
288 288 change = repo.changelog.read(node)
289 289 print "# HG changeset patch"
290 290 print "# User %s" % change[1]
291 291 print "# Node ID %s" % hg.hex(node)
292 292 print "# Parent %s" % hg.hex(prev)
293 293 print
294 294 if other != hg.nullid:
295 295 print "# Parent %s" % hg.hex(other)
296 296 print change[4].rstrip()
297 297 print
298 298
299 299 dodiff(repo, "", None, prev, node)
300 300
301 301 def forget(ui, repo, file, *files):
302 302 """don't add the specified files on the next commit"""
303 303 repo.forget(relpath(repo, (file,) + files))
304 304
305 305 def heads(ui, repo):
306 306 """show current repository heads"""
307 307 for n in repo.changelog.heads():
308 308 show_changeset(ui, repo, changenode=n)
309 309
310 310 def history(ui, repo):
311 311 """show the changelog history"""
312 312 for i in range(repo.changelog.count() - 1, -1, -1):
313 313 show_changeset(ui, repo, rev=i)
314 314
315 315 def init(ui, source=None):
316 316 """create a new repository or copy an existing one"""
317 317
318 318 if source:
319 319 paths = {}
320 320 for name, path in ui.configitems("paths"):
321 321 paths[name] = path
322 322
323 323 if source in paths: source = paths[source]
324 324
325 325 link = 0
326 326 if not source.startswith("http://"):
327 327 d1 = os.stat(os.getcwd()).st_dev
328 328 d2 = os.stat(source).st_dev
329 329 if d1 == d2: link = 1
330 330
331 331 if link:
332 332 ui.debug("copying by hardlink\n")
333 333 os.system("cp -al %s/.hg .hg" % source)
334 334 try:
335 335 os.remove(".hg/dirstate")
336 336 except: pass
337 337 else:
338 338 repo = hg.repository(ui, ".", create=1)
339 339 other = hg.repository(ui, source)
340 340 cg = repo.getchangegroup(other)
341 341 repo.addchangegroup(cg)
342 342 else:
343 343 hg.repository(ui, ".", create=1)
344 344
345 345 def log(ui, repo, f):
346 346 """show the revision history of a single file"""
347 347 f = relpath(repo, [f])[0]
348 348
349 349 r = repo.file(f)
350 350 for i in range(r.count() - 1, -1, -1):
351 351 show_changeset(ui, repo, filelog=r, rev=i)
352 352
353 353 def manifest(ui, repo, rev = []):
354 354 """output the latest or given revision of the project manifest"""
355 355 n = repo.manifest.tip()
356 356 if rev:
357 357 n = repo.manifest.lookup(rev)
358 358 m = repo.manifest.read(n)
359 359 mf = repo.manifest.readflags(n)
360 360 files = m.keys()
361 361 files.sort()
362 362
363 363 for f in files:
364 364 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
365 365
366 366 def parents(ui, repo, node = None):
367 367 '''show the parents of the current working dir'''
368 368 if node:
369 369 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
370 370 else:
371 371 p = repo.dirstate.parents()
372 372
373 373 for n in p:
374 374 if n != hg.nullid:
375 375 show_changeset(ui, repo, changenode=n)
376 376
377 377 def patch(ui, repo, patch1, *patches, **opts):
378 378 """import an ordered set of patches"""
379 379 try:
380 380 import psyco
381 381 psyco.full()
382 382 except:
383 383 pass
384 384
385 385 patches = (patch1,) + patches
386 386
387 387 d = opts["base"]
388 388 strip = opts["strip"]
389 389 quiet = opts["quiet"] and "> /dev/null" or ""
390 390
391 391 for patch in patches:
392 392 ui.status("applying %s\n" % patch)
393 393 pf = os.path.join(d, patch)
394 394
395 395 text = ""
396 396 for l in file(pf):
397 397 if l[:4] == "--- ": break
398 398 text += l
399 399
400 400 # make sure text isn't empty
401 401 if not text: text = "imported patch %s\n" % patch
402 402
403 403 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
404 404 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
405 405 f.close()
406 406
407 407 if files:
408 408 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
409 409 raise "patch failed!"
410 410 repo.commit(files, text)
411 411
412 412 def pull(ui, repo, source):
413 413 """pull changes from the specified source"""
414 414 paths = {}
415 415 for name, path in ui.configitems("paths"):
416 416 paths[name] = path
417 417
418 418 if source in paths: source = paths[source]
419 419
420 420 other = hg.repository(ui, source)
421 421 cg = repo.getchangegroup(other)
422 422 repo.addchangegroup(cg)
423 423
424 424 def push(ui, repo, dest):
425 425 """push changes to the specified destination"""
426 426 paths = {}
427 427 for name, path in ui.configitems("paths"):
428 428 paths[name] = path
429 429
430 430 if dest in paths: dest = paths[dest]
431 431
432 432 if not dest.startswith("ssh://"):
433 433 ui.warn("abort: can only push to ssh:// destinations currently\n")
434 434 return 1
435 435
436 436 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
437 437 if not m:
438 438 ui.warn("abort: couldn't parse destination %s\n" % dest)
439 439 return 1
440 440
441 441 user, host, port, path = map(m.group, (2, 3, 5, 7))
442 442 host = user and ("%s@%s" % (user, host)) or host
443 443 port = port and (" -p %s") % port or ""
444 444 path = path or ""
445 445
446 446 sport = random.randrange(30000, 60000)
447 447 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
448 448 cmd = cmd % (host, port, sport+1, sport, path, sport+1)
449 449
450 450 child = os.fork()
451 451 if not child:
452 452 sys.stdout = file("/dev/null", "w")
453 453 sys.stderr = sys.stdout
454 454 hgweb.server(repo.root, "pull", "", "localhost", sport)
455 455 else:
456 456 r = os.system(cmd)
457 457 os.kill(child, signal.SIGTERM)
458 458 return r
459 459
460 460 def rawcommit(ui, repo, files, **rc):
461 461 "raw commit interface"
462 462
463 463 text = rc['text']
464 464 if not text and rc['logfile']:
465 465 try: text = open(rc['logfile']).read()
466 466 except IOError: pass
467 467 if not text and not rc['logfile']:
468 468 print "missing commit text"
469 469 return 1
470 470
471 471 files = relpath(repo, files)
472 472 if rc['files']:
473 473 files += open(rc['files']).read().splitlines()
474 474
475 475 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
476 476
477 477 def recover(ui, repo):
478 478 """roll back an interrupted transaction"""
479 479 repo.recover()
480 480
481 481 def remove(ui, repo, file, *files):
482 482 """remove the specified files on the next commit"""
483 483 repo.remove(relpath(repo, (file,) + files))
484 484
485 485 def serve(ui, repo, **opts):
486 486 """export the repository via HTTP"""
487 487 hgweb.server(repo.root, opts["name"], opts["templates"],
488 488 opts["address"], opts["port"])
489 489
490 490 def status(ui, repo):
491 491 '''show changed files in the working directory
492 492
493 493 C = changed
494 494 A = added
495 495 R = removed
496 496 ? = not tracked'''
497 497
498 498 (c, a, d, u) = repo.diffdir(os.getcwd())
499 499 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
500 500
501 501 for f in c: print "C", f
502 502 for f in a: print "A", f
503 503 for f in d: print "R", f
504 504 for f in u: print "?", f
505 505
506 506 def tags(ui, repo):
507 507 """list repository tags"""
508 508 repo.lookup(0) # prime the cache
509 509 i = repo.tags.items()
510 510 n = []
511 511 for e in i:
512 512 try:
513 513 l = repo.changelog.rev(e[1])
514 514 except KeyError:
515 515 l = -2
516 516 n.append((l, e))
517 517
518 518 n.sort()
519 519 n.reverse()
520 520 i = [ e[1] for e in n ]
521 521 for k, n in i:
522 522 try:
523 523 r = repo.changelog.rev(n)
524 524 except KeyError:
525 525 r = "?"
526 526 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
527 527
528 528 def tip(ui, repo):
529 529 """show the tip revision"""
530 530 n = repo.changelog.tip()
531 531 show_changeset(ui, repo, changenode=n)
532 532
533 533 def undo(ui, repo):
534 534 """undo the last transaction"""
535 535 repo.undo()
536 536
537 537 def update(ui, repo, node=None, merge=False, clean=False):
538 538 '''update or merge working directory
539 539
540 540 If there are no outstanding changes in the working directory and
541 541 there is a linear relationship between the current version and the
542 542 requested version, the result is the requested version.
543 543
544 544 Otherwise the result is a merge between the contents of the
545 545 current working directory and the requested version. Files that
546 546 changed between either parent are marked as changed for the next
547 547 commit and a commit must be performed before any further updates
548 548 are allowed.
549 549 '''
550 550 node = node and repo.lookup(node) or repo.changelog.tip()
551 551 return repo.update(node, allow=merge, force=clean)
552 552
553 553 def verify(ui, repo):
554 554 """verify the integrity of the repository"""
555 555 return repo.verify()
556 556
557 557 # Command options and aliases are listed here, alphabetically
558 558
559 559 table = {
560 560 "add": (add, [], "hg add [files]"),
561 561 "addremove": (addremove, [], "hg addremove"),
562 562 "ann|annotate": (annotate,
563 563 [('r', 'revision', '', 'revision'),
564 564 ('u', 'user', None, 'show user'),
565 565 ('n', 'number', None, 'show revision number'),
566 566 ('c', 'changeset', None, 'show changeset')],
567 567 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
568 568 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
569 569 "commit|ci": (commit,
570 570 [('t', 'text', "", 'commit text'),
571 571 ('l', 'logfile', "", 'commit text file'),
572 572 ('d', 'date', "", 'data'),
573 573 ('u', 'user', "", 'user')],
574 574 'hg commit [files]'),
575 575 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
576 576 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
577 577 "debugindex": (debugindex, [], 'debugindex <file>'),
578 578 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
579 579 "diff": (diff, [('r', 'rev', [], 'revision')],
580 580 'hg diff [-r A] [-r B] [files]'),
581 581 "export": (export, [], "hg export <changeset>"),
582 582 "forget": (forget, [], "hg forget [files]"),
583 583 "heads": (heads, [], 'hg heads'),
584 584 "history": (history, [], 'hg history'),
585 585 "help": (help, [], 'hg help [command]'),
586 586 "init": (init, [], 'hg init [url]'),
587 587 "log": (log, [], 'hg log <file>'),
588 588 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'),
589 589 "parents": (parents, [], 'hg parents [node]'),
590 590 "patch|import": (patch,
591 591 [('p', 'strip', 1, 'path strip'),
592 592 ('b', 'base', "", 'base path'),
593 593 ('q', 'quiet', "", 'silence diff')],
594 594 "hg import [options] patches"),
595 595 "pull|merge": (pull, [], 'hg pull [source]'),
596 596 "push": (push, [], 'hg push <destination>'),
597 597 "rawcommit": (rawcommit,
598 598 [('p', 'parent', [], 'parent'),
599 599 ('d', 'date', "", 'data'),
600 600 ('u', 'user', "", 'user'),
601 601 ('F', 'files', "", 'file list'),
602 602 ('t', 'text', "", 'commit text'),
603 603 ('l', 'logfile', "", 'commit text file')],
604 604 'hg rawcommit [options] [files]'),
605 605 "recover": (recover, [], "hg recover"),
606 606 "remove": (remove, [], "hg remove [files]"),
607 607 "serve": (serve, [('p', 'port', 8000, 'listen port'),
608 608 ('a', 'address', '', 'interface address'),
609 609 ('n', 'name', os.getcwd(), 'repository name'),
610 610 ('t', 'templates', "", 'template map')],
611 611 "hg serve [options]"),
612 612 "status": (status, [], 'hg status'),
613 613 "tags": (tags, [], 'hg tags'),
614 614 "tip": (tip, [], 'hg tip'),
615 615 "undo": (undo, [], 'hg undo'),
616 616 "update|up|checkout|co|resolve": (update,
617 617 [('m', 'merge', None,
618 618 'allow merging of conflicts'),
619 619 ('C', 'clean', None,
620 620 'overwrite locally modified files')],
621 621 'hg update [options] [node]'),
622 622 "verify": (verify, [], 'hg verify'),
623 623 }
624 624
625 625 norepo = "init branch help debugindex debugindexdot"
626 626
627 627 def find(cmd):
628 628 i = None
629 629 for e in table.keys():
630 630 if re.match(e + "$", cmd):
631 631 return table[e]
632 632
633 633 raise UnknownCommand(cmd)
634 634
635 635 class SignalInterrupt(Exception): pass
636 636
637 637 def catchterm(*args):
638 638 raise SignalInterrupt
639 639
640 640 def run():
641 641 sys.exit(dispatch(sys.argv[1:]))
642 642
643 643 def dispatch(args):
644 644 options = {}
645 645 opts = [('v', 'verbose', None, 'verbose'),
646 646 ('d', 'debug', None, 'debug'),
647 647 ('q', 'quiet', None, 'quiet'),
648 648 ('p', 'profile', None, 'profile'),
649 649 ('y', 'noninteractive', None, 'run non-interactively'),
650 650 ]
651 651
652 652 args = fancyopts.fancyopts(args, opts, options,
653 653 'hg [options] <command> [options] [files]')
654 654
655 655 if not args:
656 656 cmd = "help"
657 657 else:
658 658 cmd, args = args[0], args[1:]
659 659
660 660 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
661 661 not options["noninteractive"])
662 662
663 663 try:
664 664 i = find(cmd)
665 665 except UnknownCommand:
666 666 u.warn("hg: unknown command '%s'\n" % cmd)
667 667 help(u)
668 668 sys.exit(1)
669 669
670 670 signal.signal(signal.SIGTERM, catchterm)
671 671
672 672 cmdoptions = {}
673 673 try:
674 674 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
675 675 except fancyopts.getopt.GetoptError, inst:
676 676 u.warn("hg %s: %s\n" % (cmd, inst))
677 677 help(u, cmd)
678 678 sys.exit(-1)
679 679
680 680 if cmd not in norepo.split():
681 681 repo = hg.repository(ui = u)
682 682 d = lambda: i[0](u, repo, *args, **cmdoptions)
683 683 else:
684 684 d = lambda: i[0](u, *args, **cmdoptions)
685 685
686 686 try:
687 687 if options['profile']:
688 688 import hotshot, hotshot.stats
689 689 prof = hotshot.Profile("hg.prof")
690 690 r = prof.runcall(d)
691 691 prof.close()
692 692 stats = hotshot.stats.load("hg.prof")
693 693 stats.strip_dirs()
694 694 stats.sort_stats('time', 'calls')
695 695 stats.print_stats(40)
696 696 return r
697 697 else:
698 698 return d()
699 699 except SignalInterrupt:
700 700 u.warn("killed!\n")
701 701 except KeyboardInterrupt:
702 702 u.warn("interrupted!\n")
703 703 except IOError, inst:
704 704 if inst.errno == 32:
705 705 u.warn("broken pipe\n")
706 706 else:
707 707 raise
708 708 except TypeError, inst:
709 709 # was this an argument error?
710 710 tb = traceback.extract_tb(sys.exc_info()[2])
711 711 if len(tb) > 2: # no
712 712 raise
713 713 u.debug(inst, "\n")
714 714 u.warn("%s: invalid arguments\n" % i[0].__name__)
715 715 help(u, cmd)
716 716 sys.exit(-1)
717 717
General Comments 0
You need to be logged in to leave comments. Login now