##// END OF EJS Templates
[PATCH] New export patch...
mpm@selenic.com -
r580:353a2ce5 default
parent child Browse files
Show More
@@ -129,11 +129,27 b' diff [-r revision] [-r revision] [files '
129 revisions are specified, the working directory files are compared
129 revisions are specified, the working directory files are compared
130 to its parent.
130 to its parent.
131
131
132 export [revision]::
132 export [-o filespec] [revision] ...::
133 Print the changeset header and diffs for a particular revision.
133 Print the changeset header and diffs for one or more revisions.
134
135 The information shown in the changeset header is: author,
136 changeset hash, parent and commit comment.
137
138 Output may be to a file, in which case the name of the file is
139 given using a format string. The formatting rules are as follows:
134
140
135 The information shown in the changeset header is: author, changeset hash,
141 %% literal "%" character
136 parent and commit comment.
142 %H changeset hash (40 bytes of hexadecimal)
143 %N number of patches being generated
144 %R changeset revision number
145 %b basename of the exporting repository
146 %h short-form changeset hash (12 bytes of hexadecimal)
147 %n zero-padded sequence number, starting at 1
148 %r zero-padded changeset revision number
149
150 Options:
151
152 -o, --output <filespec> print output to file with formatted named
137
153
138 forget [files]::
154 forget [files]::
139 Undo an 'hg add' scheduled for the next commit.
155 Undo an 'hg add' scheduled for the next commit.
@@ -317,6 +333,49 b' verify::'
317 the changelog, manifest, and tracked files, as well as the
333 the changelog, manifest, and tracked files, as well as the
318 integrity of their crosslinks and indices.
334 integrity of their crosslinks and indices.
319
335
336 SPECIFYING SINGLE REVISIONS
337 ---------------------------
338
339 Mercurial accepts several notations for identifying individual
340 revisions.
341
342 A plain integer is treated as a revision number. Negative
343 integers are treated as offsets from the tip, with -1 denoting the
344 tip.
345
346 A 40-digit hexadecimal string is treated as a unique revision
347 identifier.
348
349 A hexadecimal string less than 40 characters long is treated as a
350 unique revision identifier, and referred to as a short-form
351 identifier. A short-form identifier is only valid if it is the
352 prefix of one full-length identifier.
353
354 Any other string is treated as a tag name, which is a symbolic
355 name associated with a revision identifier. Tag names may not
356 contain the ":" character.
357
358 The reserved name "tip" is a special tag that always identifies
359 the most recent revision.
360
361 SPECIFYING MULTIPLE REVISIONS
362 -----------------------------
363
364 When Mercurial accepts more than one revision, they may be
365 specified individually, or provided as a continuous range,
366 separated by the ":" character.
367
368 The syntax of range notation is [BEGIN]:[END], where BEGIN and END
369 are revision identifiers. Both BEGIN and END are optional. If
370 BEGIN is not specified, it defaults to revision number 0. If END
371 is not specified, it defaults to the tip. The range ":" thus
372 means "all revisions".
373
374 If BEGIN is greater than END, revisions are treated in reverse
375 order.
376
377 A range acts as an open interval. This means that a range of 3:5
378 gives 3, 4 and 5. Similarly, a range of 4:2 gives 4, 3, and 2.
320
379
321 ENVIRONMENT VARIABLES
380 ENVIRONMENT VARIABLES
322 ---------------------
381 ---------------------
@@ -33,7 +33,47 b' def relpath(repo, args):'
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
@@ -70,15 +110,15 b' def dodiff(ui, repo, files = None, node1'
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"""
@@ -421,24 +461,68 b' def diff(ui, repo, *files, **opts):'
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
514
515 dodiff(fp, ui, repo, None, prev, node)
440
516
441 dodiff(ui, repo, None, prev, node)
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"""
@@ -585,7 +669,7 b' def pull(ui, repo, source="default", **o'
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
@@ -679,15 +763,18 b' def tag(ui, repo, name, rev = None, **op'
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))
@@ -773,7 +860,8 b' table = {'
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]'),
@@ -790,7 +878,7 b' table = {'
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'),
@@ -943,4 +1031,3 b' def dispatch(args):'
943 help(u, cmd)
1031 help(u, cmd)
944
1032
945 sys.exit(-1)
1033 sys.exit(-1)
946
General Comments 0
You need to be logged in to leave comments. Login now