31 p = os.getcwd()[len(repo.root) + 1: ] |
31 p = os.getcwd()[len(repo.root) + 1: ] |
32 return [ util.pconvert(os.path.normpath(os.path.join(p, x))) |
32 return [ util.pconvert(os.path.normpath(os.path.join(p, x))) |
33 for x in args ] |
33 for x in args ] |
34 return args |
34 return args |
35 |
35 |
36 def dodiff(ui, repo, files = None, node1 = None, node2 = None): |
36 revrangesep = ':' |
|
37 |
|
38 def revrange(ui, repo, revs = [], revlog = None): |
|
39 if revlog is None: |
|
40 revlog = repo.changelog |
|
41 revcount = revlog.count() |
|
42 def fix(val, defval): |
|
43 if not val: return defval |
|
44 try: |
|
45 num = int(val) |
|
46 if str(num) != val: raise ValueError |
|
47 if num < 0: num += revcount |
|
48 if not (0 <= num < revcount): |
|
49 raise ValueError |
|
50 except ValueError: |
|
51 try: |
|
52 num = repo.changelog.rev(repo.lookup(val)) |
|
53 except KeyError: |
|
54 try: |
|
55 num = revlog.rev(revlog.lookup(val)) |
|
56 except KeyError: |
|
57 ui.warn('abort: invalid revision identifier %s\n' % val) |
|
58 sys.exit(1) |
|
59 return num |
|
60 for spec in revs: |
|
61 if spec.find(revrangesep) >= 0: |
|
62 start, end = spec.split(revrangesep, 1) |
|
63 start = fix(start, 0) |
|
64 end = fix(end, revcount - 1) |
|
65 if end > start: |
|
66 end += 1 |
|
67 step = 1 |
|
68 else: |
|
69 end -= 1 |
|
70 step = -1 |
|
71 for rev in xrange(start, end, step): |
|
72 yield str(rev) |
|
73 else: |
|
74 yield spec |
|
75 |
|
76 def dodiff(fp, ui, repo, files = None, node1 = None, node2 = None): |
37 def date(c): |
77 def date(c): |
38 return time.asctime(time.gmtime(float(c[2].split(' ')[0]))) |
78 return time.asctime(time.gmtime(float(c[2].split(' ')[0]))) |
39 |
79 |
40 (c, a, d, u) = repo.changes(node1, node2, files) |
80 (c, a, d, u) = repo.changes(node1, node2, files) |
41 if files: |
81 if files: |
68 for f in c: |
108 for f in c: |
69 to = None |
109 to = None |
70 if f in mmap: |
110 if f in mmap: |
71 to = repo.file(f).read(mmap[f]) |
111 to = repo.file(f).read(mmap[f]) |
72 tn = read(f) |
112 tn = read(f) |
73 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r)) |
113 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r)) |
74 for f in a: |
114 for f in a: |
75 to = None |
115 to = None |
76 tn = read(f) |
116 tn = read(f) |
77 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r)) |
117 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r)) |
78 for f in d: |
118 for f in d: |
79 to = repo.file(f).read(mmap[f]) |
119 to = repo.file(f).read(mmap[f]) |
80 tn = None |
120 tn = None |
81 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r)) |
121 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r)) |
82 |
122 |
83 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None): |
123 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None): |
84 """show a single changeset or file revision""" |
124 """show a single changeset or file revision""" |
85 changelog = repo.changelog |
125 changelog = repo.changelog |
86 if filelog: |
126 if filelog: |
419 if files: |
459 if files: |
420 files = relpath(repo, files) |
460 files = relpath(repo, files) |
421 else: |
461 else: |
422 files = relpath(repo, [""]) |
462 files = relpath(repo, [""]) |
423 |
463 |
424 dodiff(ui, repo, files, *revs) |
464 dodiff(sys.stdout, ui, repo, files, *revs) |
425 |
465 |
426 def export(ui, repo, changeset): |
466 def doexport(ui, repo, changeset, seqno, total, revwidth, opts): |
427 """dump the changeset header and diffs for a revision""" |
|
428 node = repo.lookup(changeset) |
467 node = repo.lookup(changeset) |
429 prev, other = repo.changelog.parents(node) |
468 prev, other = repo.changelog.parents(node) |
430 change = repo.changelog.read(node) |
469 change = repo.changelog.read(node) |
431 print "# HG changeset patch" |
470 |
432 print "# User %s" % change[1] |
471 def expand(name): |
433 print "# Node ID %s" % hg.hex(node) |
472 expansions = { |
434 print "# Parent %s" % hg.hex(prev) |
473 '%': lambda: '%', |
435 print |
474 'H': lambda: hg.hex(node), |
|
475 'N': lambda: str(total), |
|
476 'R': lambda: str(repo.changelog.rev(node)), |
|
477 'b': lambda: os.path.basename(repo.root), |
|
478 'h': lambda: hg.short(node), |
|
479 'n': lambda: str(seqno).zfill(len(str(total))), |
|
480 'r': lambda: str(repo.changelog.rev(node)).zfill(revwidth), |
|
481 } |
|
482 newname = [] |
|
483 namelen = len(name) |
|
484 i = 0 |
|
485 while i < namelen: |
|
486 c = name[i] |
|
487 if c == '%': |
|
488 i += 1 |
|
489 c = name[i] |
|
490 c = expansions[c]() |
|
491 newname.append(c) |
|
492 i += 1 |
|
493 return ''.join(newname) |
|
494 |
|
495 if opts['output'] and opts['output'] != '-': |
|
496 try: |
|
497 fp = open(expand(opts['output']), 'w') |
|
498 except KeyError, inst: |
|
499 ui.warn("error: invalid format spec '%%%s' in output file name\n" % |
|
500 inst.args[0]) |
|
501 sys.exit(1) |
|
502 else: |
|
503 fp = sys.stdout |
|
504 |
|
505 print >> fp, "# HG changeset patch" |
|
506 print >> fp, "# User %s" % change[1] |
|
507 print >> fp, "# Node ID %s" % hg.hex(node) |
|
508 print >> fp, "# Parent %s" % hg.hex(prev) |
|
509 print >> fp |
436 if other != hg.nullid: |
510 if other != hg.nullid: |
437 print "# Parent %s" % hg.hex(other) |
511 print >> fp, "# Parent %s" % hg.hex(other) |
438 print change[4].rstrip() |
512 print >> fp, change[4].rstrip() |
439 print |
513 print >> fp |
440 |
514 |
441 dodiff(ui, repo, None, prev, node) |
515 dodiff(fp, ui, repo, None, prev, node) |
|
516 |
|
517 def export(ui, repo, *changesets, **opts): |
|
518 """dump the header and diffs for one or more changesets""" |
|
519 seqno = 0 |
|
520 revs = list(revrange(ui, repo, changesets)) |
|
521 total = len(revs) |
|
522 revwidth = max(len(revs[0]), len(revs[-1])) |
|
523 for cset in revs: |
|
524 seqno += 1 |
|
525 doexport(ui, repo, cset, seqno, total, revwidth, opts) |
442 |
526 |
443 def forget(ui, repo, file, *files): |
527 def forget(ui, repo, file, *files): |
444 """don't add the specified files on the next commit""" |
528 """don't add the specified files on the next commit""" |
445 repo.forget(relpath(repo, (file,) + files)) |
529 repo.forget(relpath(repo, (file,) + files)) |
446 |
530 |
677 |
761 |
678 def tag(ui, repo, name, rev = None, **opts): |
762 def tag(ui, repo, name, rev = None, **opts): |
679 """add a tag for the current tip or a given revision""" |
763 """add a tag for the current tip or a given revision""" |
680 |
764 |
681 if name == "tip": |
765 if name == "tip": |
682 ui.warn("abort: 'tip' is a reserved name!\n") |
766 ui.warn("abort: 'tip' is a reserved name!\n") |
683 return -1 |
767 return -1 |
|
768 if name.find(revrangesep) >= 0: |
|
769 ui.warn("abort: '%s' cannot be used in a tag name\n" % revrangesep) |
|
770 return -1 |
684 |
771 |
685 (c, a, d, u) = repo.changes(None, None) |
772 (c, a, d, u) = repo.changes(None, None) |
686 for x in (c, a, d, u): |
773 for x in (c, a, d, u): |
687 if ".hgtags" in x: |
774 if ".hgtags" in x: |
688 ui.warn("abort: working copy of .hgtags is changed!\n") |
775 ui.warn("abort: working copy of .hgtags is changed!\n") |
689 ui.status("(please commit .hgtags manually)\n") |
776 ui.status("(please commit .hgtags manually)\n") |
690 return -1 |
777 return -1 |
691 |
778 |
692 if rev: |
779 if rev: |
693 r = hg.hex(repo.lookup(rev)) |
780 r = hg.hex(repo.lookup(rev)) |
694 else: |
781 else: |
695 r = hg.hex(repo.changelog.tip()) |
782 r = hg.hex(repo.changelog.tip()) |
771 "debugdumpdirstate": (debugdumpdirstate, [], 'debugdumpdirstate'), |
858 "debugdumpdirstate": (debugdumpdirstate, [], 'debugdumpdirstate'), |
772 "debugindex": (debugindex, [], 'debugindex <file>'), |
859 "debugindex": (debugindex, [], 'debugindex <file>'), |
773 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'), |
860 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'), |
774 "diff": (diff, [('r', 'rev', [], 'revision')], |
861 "diff": (diff, [('r', 'rev', [], 'revision')], |
775 'hg diff [-r A] [-r B] [files]'), |
862 'hg diff [-r A] [-r B] [files]'), |
776 "export": (export, [], "hg export <changeset>"), |
863 "export": (export, [('o', 'output', "", 'output to file')], |
|
864 "hg export [-o file] <changeset> ..."), |
777 "forget": (forget, [], "hg forget [files]"), |
865 "forget": (forget, [], "hg forget [files]"), |
778 "heads": (heads, [], 'hg heads'), |
866 "heads": (heads, [], 'hg heads'), |
779 "help": (help, [], 'hg help [command]'), |
867 "help": (help, [], 'hg help [command]'), |
780 "identify|id": (identify, [], 'hg identify'), |
868 "identify|id": (identify, [], 'hg identify'), |
781 "import|patch": (import_, |
869 "import|patch": (import_, |
788 'hg log [-r A] [-r B] [file]'), |
876 'hg log [-r A] [-r B] [file]'), |
789 "manifest": (manifest, [], 'hg manifest [rev]'), |
877 "manifest": (manifest, [], 'hg manifest [rev]'), |
790 "parents": (parents, [], 'hg parents [node]'), |
878 "parents": (parents, [], 'hg parents [node]'), |
791 "pull": (pull, |
879 "pull": (pull, |
792 [('u', 'update', None, 'update working directory')], |
880 [('u', 'update', None, 'update working directory')], |
793 'hg pull [options] [source]'), |
881 'hg pull [options] [source]'), |
794 "push": (push, [], 'hg push <destination>'), |
882 "push": (push, [], 'hg push <destination>'), |
795 "rawcommit": (rawcommit, |
883 "rawcommit": (rawcommit, |
796 [('p', 'parent', [], 'parent'), |
884 [('p', 'parent', [], 'parent'), |
797 ('d', 'date', "", 'data'), |
885 ('d', 'date', "", 'data'), |
798 ('u', 'user', "", 'user'), |
886 ('u', 'user', "", 'user'), |