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