comparison mercurial/commands.py @ 580:353a2ce50423

[PATCH] New export patch -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 [PATCH] New export patch From: Bryan O'Sullivan <bos@serpentine.com> Modify export command to accept rev ranges and output file spec. It can now export a range of revisions, and print exported patches to files whose names are generated using format strings. manifest hash: e0085c205cdc31a168bcd25c85772ef00d53031d -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.0 (GNU/Linux) iD8DBQFCx02iywK+sNU5EO8RAtCKAJ0V2K9+i1OGa27KyC5/nq3m+OdvtgCgpnav 3vfEODMzJVOZoJt9wzI1UCg= =YAdI -----END PGP SIGNATURE-----
author mpm@selenic.com
date Sat, 02 Jul 2005 18:29:54 -0800
parents 5291a16324c0
children df8a5a0098d4
comparison
equal deleted inserted replaced
579:ffeb2c3a1966 580:353a2ce50423
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
583 cg = other.changegroup(fetch) 667 cg = other.changegroup(fetch)
584 r = repo.addchangegroup(cg) 668 r = repo.addchangegroup(cg)
585 if cg and not r: 669 if cg and not r:
586 if opts['update']: 670 if opts['update']:
587 return update(ui, repo) 671 return update(ui, repo)
588 else: 672 else:
589 ui.status("(run 'hg update' to get a working copy)\n") 673 ui.status("(run 'hg update' to get a working copy)\n")
590 674
591 return r 675 return r
592 676
593 def push(ui, repo, dest="default-push"): 677 def push(ui, repo, dest="default-push"):
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'),
941 u.debug(inst, "\n") 1029 u.debug(inst, "\n")
942 u.warn("%s: invalid arguments\n" % i[0].__name__) 1030 u.warn("%s: invalid arguments\n" % i[0].__name__)
943 help(u, cmd) 1031 help(u, cmd)
944 1032
945 sys.exit(-1) 1033 sys.exit(-1)
946