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