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