Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/commands.py @ 607:94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
[PATCH] Parse and use header data from an hg export'ed changeset
From: Andrew Thompson <andrewkt@aktzero.com>
This should make it easier to import changesets that are hg export'ed
from other Mercurial users:
Add a routine to catch the user from an hg export'ed changeset.
Add user to commit call.
Add trap for changelog snippet, which is promoted to the beginning of
the commit text.
manifest hash: cf5b068f4cec411ff8b9fa3db324ab44ed012778
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
iD8DBQFCyMXAywK+sNU5EO8RAqk5AJ9rC4ZwzcpDfxrNqIBrrTj6eL2mzQCgmZ5O
wSkis2J9Xz2wOZAhjVcxIgQ=
=32D+
-----END PGP SIGNATURE-----
author | mpm@selenic.com |
---|---|
date | Sun, 03 Jul 2005 21:14:40 -0800 |
parents | 8e82fd763be2 |
children | 2acf1f5df2e6 |
rev | line source |
---|---|
249 | 1 # commands.py - command processing for mercurial |
2 # | |
3 # Copyright 2005 Matt Mackall <mpm@selenic.com> | |
4 # | |
5 # This software may be used and distributed according to the terms | |
6 # of the GNU General Public License, incorporated herein by reference. | |
7 | |
262 | 8 import os, re, sys, signal |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
417
diff
changeset
|
9 import fancyopts, ui, hg, util |
262 | 10 from demandload import * |
604 | 11 demandload(globals(), "mdiff time hgweb traceback random signal") |
12 demandload(globals(), "socket errno version") | |
209 | 13 |
14 class UnknownCommand(Exception): pass | |
15 | |
245 | 16 def filterfiles(filters, files): |
17 l = [ x for x in files if x in filters ] | |
213 | 18 |
245 | 19 for t in filters: |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
417
diff
changeset
|
20 if t and t[-1] != "/": t += "/" |
245 | 21 l += [ x for x in files if x.startswith(t) ] |
213 | 22 return l |
23 | |
245 | 24 def relfilter(repo, files): |
213 | 25 if os.getcwd() != repo.root: |
26 p = os.getcwd()[len(repo.root) + 1: ] | |
419
28511fc21073
[PATCH] file seperator handling for the other 'OS'
mpm@selenic.com
parents:
417
diff
changeset
|
27 return filterfiles([util.pconvert(p)], files) |
245 | 28 return files |
213 | 29 |
209 | 30 def relpath(repo, args): |
31 if os.getcwd() != repo.root: | |
32 p = os.getcwd()[len(repo.root) + 1: ] | |
554 | 33 return [ util.pconvert(os.path.normpath(os.path.join(p, x))) |
34 for x in args ] | |
209 | 35 return args |
245 | 36 |
580 | 37 revrangesep = ':' |
38 | |
39 def revrange(ui, repo, revs = [], revlog = None): | |
40 if revlog is None: | |
41 revlog = repo.changelog | |
42 revcount = revlog.count() | |
43 def fix(val, defval): | |
44 if not val: return defval | |
45 try: | |
46 num = int(val) | |
47 if str(num) != val: raise ValueError | |
48 if num < 0: num += revcount | |
49 if not (0 <= num < revcount): | |
50 raise ValueError | |
51 except ValueError: | |
52 try: | |
53 num = repo.changelog.rev(repo.lookup(val)) | |
54 except KeyError: | |
55 try: | |
56 num = revlog.rev(revlog.lookup(val)) | |
57 except KeyError: | |
58 ui.warn('abort: invalid revision identifier %s\n' % val) | |
59 sys.exit(1) | |
60 return num | |
61 for spec in revs: | |
62 if spec.find(revrangesep) >= 0: | |
63 start, end = spec.split(revrangesep, 1) | |
64 start = fix(start, 0) | |
65 end = fix(end, revcount - 1) | |
66 if end > start: | |
67 end += 1 | |
68 step = 1 | |
69 else: | |
70 end -= 1 | |
71 step = -1 | |
72 for rev in xrange(start, end, step): | |
73 yield str(rev) | |
74 else: | |
75 yield spec | |
76 | |
77 def dodiff(fp, ui, repo, files = None, node1 = None, node2 = None): | |
245 | 78 def date(c): |
79 return time.asctime(time.gmtime(float(c[2].split(' ')[0]))) | |
80 | |
561 | 81 (c, a, d, u) = repo.changes(node1, node2, files) |
537 | 82 if files: |
83 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d)) | |
84 | |
85 if not c and not a and not d: | |
86 return | |
87 | |
245 | 88 if node2: |
89 change = repo.changelog.read(node2) | |
90 mmap2 = repo.manifest.read(change[0]) | |
91 def read(f): return repo.file(f).read(mmap2[f]) | |
92 date2 = date(change) | |
93 else: | |
94 date2 = time.asctime() | |
95 if not node1: | |
96 node1 = repo.dirstate.parents()[0] | |
417 | 97 def read(f): return repo.wfile(f).read() |
245 | 98 |
396
8f8bb77d560e
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
395
diff
changeset
|
99 if ui.quiet: |
8f8bb77d560e
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
395
diff
changeset
|
100 r = None |
8f8bb77d560e
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
395
diff
changeset
|
101 else: |
8f8bb77d560e
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
395
diff
changeset
|
102 hexfunc = ui.verbose and hg.hex or hg.short |
8f8bb77d560e
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
395
diff
changeset
|
103 r = [hexfunc(node) for node in [node1, node2] if node] |
8f8bb77d560e
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
395
diff
changeset
|
104 |
245 | 105 change = repo.changelog.read(node1) |
106 mmap = repo.manifest.read(change[0]) | |
107 date1 = date(change) | |
108 | |
109 for f in c: | |
275 | 110 to = None |
111 if f in mmap: | |
112 to = repo.file(f).read(mmap[f]) | |
245 | 113 tn = read(f) |
580 | 114 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r)) |
245 | 115 for f in a: |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
262
diff
changeset
|
116 to = None |
245 | 117 tn = read(f) |
580 | 118 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r)) |
245 | 119 for f in d: |
120 to = repo.file(f).read(mmap[f]) | |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
262
diff
changeset
|
121 tn = None |
580 | 122 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r)) |
329
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
123 |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
124 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None): |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
125 """show a single changeset or file revision""" |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
126 changelog = repo.changelog |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
127 if filelog: |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
128 log = filelog |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
129 filerev = rev |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
130 node = filenode = filelog.node(filerev) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
131 changerev = filelog.linkrev(filenode) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
132 changenode = changenode or changelog.node(changerev) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
133 else: |
347
a0b2758edee7
Cleaned up show_changeset()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
330
diff
changeset
|
134 log = changelog |
329
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
135 changerev = rev |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
136 if changenode is None: |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
137 changenode = changelog.node(changerev) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
138 elif not changerev: |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
139 rev = changerev = changelog.rev(changenode) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
140 node = changenode |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
141 |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
142 if ui.quiet: |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
143 ui.write("%d:%s\n" % (rev, hg.hex(node))) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
144 return |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
145 |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
146 changes = changelog.read(changenode) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
147 |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
148 parents = [(log.rev(parent), hg.hex(parent)) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
149 for parent in log.parents(node) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
150 if ui.debugflag or parent != hg.nullid] |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
151 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1: |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
152 parents = [] |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
153 |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
154 if filelog: |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
155 ui.write("revision: %d:%s\n" % (filerev, hg.hex(filenode))) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
156 for parent in parents: |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
157 ui.write("parent: %d:%s\n" % parent) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
158 ui.status("changeset: %d:%s\n" % (changerev, hg.hex(changenode))) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
159 else: |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
160 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode))) |
387
c07c6fb2f0a8
Show tags in hg history etc.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
386
diff
changeset
|
161 for tag in repo.nodetags(changenode): |
c07c6fb2f0a8
Show tags in hg history etc.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
386
diff
changeset
|
162 ui.status("tag: %s\n" % tag) |
329
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
163 for parent in parents: |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
164 ui.write("parent: %d:%s\n" % parent) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
165 ui.note("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]), |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
166 hg.hex(changes[0]))) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
167 ui.status("user: %s\n" % changes[1]) |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
168 ui.status("date: %s\n" % time.asctime( |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
169 time.localtime(float(changes[2].split(' ')[0])))) |
493
30752b14f759
Make show_changeset show added/deleted files only in debug mode.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
490
diff
changeset
|
170 if ui.debugflag: |
536 | 171 files = repo.changes(changelog.parents(changenode)[0], changenode) |
490
df9b77f67998
Make show_changeset show added and deleted files in verbose mode.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
485
diff
changeset
|
172 for key, value in zip(["files:", "files+:", "files-:"], files): |
df9b77f67998
Make show_changeset show added and deleted files in verbose mode.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
485
diff
changeset
|
173 if value: |
df9b77f67998
Make show_changeset show added and deleted files in verbose mode.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
485
diff
changeset
|
174 ui.note("%-12s %s\n" % (key, " ".join(value))) |
493
30752b14f759
Make show_changeset show added/deleted files only in debug mode.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
490
diff
changeset
|
175 else: |
30752b14f759
Make show_changeset show added/deleted files only in debug mode.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
490
diff
changeset
|
176 ui.note("files: %s\n" % " ".join(changes[3])) |
347
a0b2758edee7
Cleaned up show_changeset()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
330
diff
changeset
|
177 description = changes[4].strip() |
329
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
178 if description: |
330 | 179 if ui.verbose: |
180 ui.status("description:\n") | |
347
a0b2758edee7
Cleaned up show_changeset()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
330
diff
changeset
|
181 ui.status(description) |
546
c8ae964109c1
Add an empty line after description in verbose mode of show_changeset.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
542
diff
changeset
|
182 ui.status("\n\n") |
330 | 183 else: |
347
a0b2758edee7
Cleaned up show_changeset()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
330
diff
changeset
|
184 ui.status("summary: %s\n" % description.splitlines()[0]) |
329
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
185 ui.status("\n") |
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
186 |
470
0ab093b473c5
Fix up version module name and command conflict
mpm@selenic.com
parents:
468
diff
changeset
|
187 def show_version(ui): |
423
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
188 """output version and copyright information""" |
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
189 ui.write("Mercurial version %s\n" % version.get_version()) |
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
190 ui.status( |
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
191 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n" |
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
192 "This is free software; see the source for copying conditions. " |
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
193 "There is NO\nwarranty; " |
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
194 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" |
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
195 ) |
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
196 |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
197 def help(ui, cmd=None): |
255 | 198 '''show help for a given command or all commands''' |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
199 if cmd: |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
200 try: |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
201 i = find(cmd) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
202 ui.write("%s\n\n" % i[2]) |
293 | 203 |
204 if i[1]: | |
205 for s, l, d, c in i[1]: | |
206 opt=' ' | |
207 if s: opt = opt + '-' + s + ' ' | |
208 if l: opt = opt + '--' + l + ' ' | |
209 if d: opt = opt + '(' + str(d) + ')' | |
210 ui.write(opt, "\n") | |
211 if c: ui.write(' %s\n' % c) | |
212 ui.write("\n") | |
213 | |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
214 ui.write(i[0].__doc__, "\n") |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
215 except UnknownCommand: |
268 | 216 ui.warn("hg: unknown command %s\n" % cmd) |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
217 sys.exit(0) |
255 | 218 else: |
593 | 219 if ui.verbose: |
470
0ab093b473c5
Fix up version module name and command conflict
mpm@selenic.com
parents:
468
diff
changeset
|
220 show_version(ui) |
423
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
221 ui.write('\n') |
593 | 222 if ui.verbose: |
223 ui.write('hg commands:\n\n') | |
224 else: | |
596 | 225 ui.write('basic hg commands (use "hg help -v" for more):\n\n') |
209 | 226 |
255 | 227 h = {} |
479
7293cb91bf2a
Cleaned up command alias handling in help.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
477
diff
changeset
|
228 for c, e in table.items(): |
7293cb91bf2a
Cleaned up command alias handling in help.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
477
diff
changeset
|
229 f = c.split("|")[0] |
593 | 230 if not ui.verbose and not f.startswith("^"): |
479
7293cb91bf2a
Cleaned up command alias handling in help.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
477
diff
changeset
|
231 continue |
593 | 232 if not ui.debugflag and f.startswith("debug"): |
233 continue | |
234 f = f.lstrip("^") | |
255 | 235 d = "" |
470
0ab093b473c5
Fix up version module name and command conflict
mpm@selenic.com
parents:
468
diff
changeset
|
236 if e[0].__doc__: |
0ab093b473c5
Fix up version module name and command conflict
mpm@selenic.com
parents:
468
diff
changeset
|
237 d = e[0].__doc__.splitlines(0)[0].rstrip() |
0ab093b473c5
Fix up version module name and command conflict
mpm@selenic.com
parents:
468
diff
changeset
|
238 h[f] = d |
255 | 239 |
240 fns = h.keys() | |
241 fns.sort() | |
242 m = max(map(len, fns)) | |
243 for f in fns: | |
423
25afb21d97ba
Support for 'hg --version'. setup.py stores version from hg repository.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
396
diff
changeset
|
244 ui.write(' %-*s %s\n' % (m, f, h[f])) |
255 | 245 |
246 # Commands start here, listed alphabetically | |
209 | 247 |
245 | 248 def add(ui, repo, file, *files): |
249 '''add the specified files on the next commit''' | |
250 repo.add(relpath(repo, (file,) + files)) | |
213 | 251 |
353 | 252 def addremove(ui, repo, *files): |
255 | 253 """add all new files, delete all missing files""" |
353 | 254 if files: |
255 files = relpath(repo, files) | |
256 d = [] | |
257 u = [] | |
258 for f in files: | |
259 p = repo.wjoin(f) | |
260 s = repo.dirstate.state(f) | |
261 isfile = os.path.isfile(p) | |
262 if s != 'r' and not isfile: | |
263 d.append(f) | |
264 elif s not in 'nmai' and isfile: | |
265 u.append(f) | |
266 else: | |
536 | 267 (c, a, d, u) = repo.changes(None, None) |
259 | 268 repo.add(u) |
245 | 269 repo.remove(d) |
219
8ff4532376a4
hg checkout: refuse to checkout if there are outstanding changes
mpm@selenic.com
parents:
214
diff
changeset
|
270 |
245 | 271 def annotate(u, repo, file, *files, **ops): |
255 | 272 """show changeset information per file line""" |
209 | 273 def getnode(rev): |
274 return hg.short(repo.changelog.node(rev)) | |
275 | |
276 def getname(rev): | |
277 try: | |
278 return bcache[rev] | |
279 except KeyError: | |
280 cl = repo.changelog.read(repo.changelog.node(rev)) | |
281 name = cl[1] | |
282 f = name.find('@') | |
283 if f >= 0: | |
284 name = name[:f] | |
534
ab0d1bfeee7c
[PATCH] Handle 'name firstname <email@server>' correctly in annotate
mpm@selenic.com
parents:
532
diff
changeset
|
285 f = name.find('<') |
ab0d1bfeee7c
[PATCH] Handle 'name firstname <email@server>' correctly in annotate
mpm@selenic.com
parents:
532
diff
changeset
|
286 if f >= 0: |
ab0d1bfeee7c
[PATCH] Handle 'name firstname <email@server>' correctly in annotate
mpm@selenic.com
parents:
532
diff
changeset
|
287 name = name[f+1:] |
209 | 288 bcache[rev] = name |
289 return name | |
500
ebc4714a7632
[PATCH] Clean up destination directory if a clone fails.
mpm@selenic.com
parents:
499
diff
changeset
|
290 |
209 | 291 bcache = {} |
292 opmap = [['user', getname], ['number', str], ['changeset', getnode]] | |
293 if not ops['user'] and not ops['changeset']: | |
294 ops['number'] = 1 | |
295 | |
227 | 296 node = repo.dirstate.parents()[0] |
209 | 297 if ops['revision']: |
298 node = repo.changelog.lookup(ops['revision']) | |
299 change = repo.changelog.read(node) | |
300 mmap = repo.manifest.read(change[0]) | |
245 | 301 for f in relpath(repo, (file,) + files): |
209 | 302 lines = repo.file(f).annotate(mmap[f]) |
303 pieces = [] | |
304 | |
305 for o, f in opmap: | |
306 if ops[o]: | |
307 l = [ f(n) for n,t in lines ] | |
308 m = max(map(len, l)) | |
309 pieces.append([ "%*s" % (m, x) for x in l]) | |
310 | |
311 for p,l in zip(zip(*pieces), lines): | |
312 u.write(" ".join(p) + ": " + l[1]) | |
313 | |
248 | 314 def cat(ui, repo, file, rev = []): |
255 | 315 """output the latest or given revision of a file""" |
281 | 316 r = repo.file(relpath(repo, [file])[0]) |
248 | 317 n = r.tip() |
318 if rev: n = r.lookup(rev) | |
319 sys.stdout.write(r.read(n)) | |
320 | |
485 | 321 def clone(ui, source, dest = None, **opts): |
322 """make a copy of an existing repository""" | |
506 | 323 source = ui.expandpath(source) |
485 | 324 |
325 if dest is None: | |
528 | 326 dest = os.path.basename(os.path.normpath(source)) |
532
2e9698a5c92c
clone: abort on pre-existing destination directory
mpm@selenic.com
parents:
528
diff
changeset
|
327 |
2e9698a5c92c
clone: abort on pre-existing destination directory
mpm@selenic.com
parents:
528
diff
changeset
|
328 if os.path.exists(dest): |
2e9698a5c92c
clone: abort on pre-existing destination directory
mpm@selenic.com
parents:
528
diff
changeset
|
329 ui.warn("abort: destination '%s' already exists\n" % dest) |
2e9698a5c92c
clone: abort on pre-existing destination directory
mpm@selenic.com
parents:
528
diff
changeset
|
330 return 1 |
523
003df62ae39f
[PATCH] Force "hg clone" to always create a new directory
mpm@selenic.com
parents:
522
diff
changeset
|
331 |
535
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
332 class dircleanup: |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
333 def __init__(self, dir): |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
334 self.dir = dir |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
335 os.mkdir(dir) |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
336 def close(self): |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
337 self.dir = None |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
338 def __del__(self): |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
339 if self.dir: |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
340 import shutil |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
341 shutil.rmtree(self.dir, True) |
485 | 342 |
535
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
343 d = dircleanup(dest) |
485 | 344 |
535
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
345 link = 0 |
562
be6233a2bfdd
hg clone: only use the absolute path for .hg/hgrc
mpm@selenic.com
parents:
561
diff
changeset
|
346 abspath = source |
542 | 347 if not (source.startswith("http://") or |
348 source.startswith("hg://") or | |
349 source.startswith("old-http://")): | |
562
be6233a2bfdd
hg clone: only use the absolute path for .hg/hgrc
mpm@selenic.com
parents:
561
diff
changeset
|
350 abspath = os.path.abspath(source) |
535
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
351 d1 = os.stat(dest).st_dev |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
352 d2 = os.stat(source).st_dev |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
353 if d1 == d2: link = 1 |
485 | 354 |
535
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
355 if link: |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
356 ui.note("copying by hardlink\n") |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
357 util.system("cp -al '%s'/.hg '%s'/.hg" % (source, dest)) |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
358 try: |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
359 os.remove(os.path.join(dest, ".hg", "dirstate")) |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
360 except: pass |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
361 |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
362 repo = hg.repository(ui, dest) |
485 | 363 |
535
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
364 else: |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
365 repo = hg.repository(ui, dest, create=1) |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
366 other = hg.repository(ui, source) |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
367 fetch = repo.findincoming(other) |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
368 if fetch: |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
369 cg = other.changegroup(fetch) |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
370 repo.addchangegroup(cg) |
503
c6a2e41c8c60
Fix troubles with clone and exception handling
mpm@selenic.com
parents:
500
diff
changeset
|
371 |
535
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
372 f = repo.opener("hgrc", "w") |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
373 f.write("[paths]\n") |
562
be6233a2bfdd
hg clone: only use the absolute path for .hg/hgrc
mpm@selenic.com
parents:
561
diff
changeset
|
374 f.write("default = %s\n" % abspath) |
515 | 375 |
535
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
376 if not opts['noupdate']: |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
377 update(ui, repo) |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
378 |
fba26990604a
Deal with failed clone/transaction interaction
mpm@selenic.com
parents:
534
diff
changeset
|
379 d.close() |
515 | 380 |
289 | 381 def commit(ui, repo, *files, **opts): |
245 | 382 """commit the specified files or all outstanding changes""" |
289 | 383 text = opts['text'] |
384 if not text and opts['logfile']: | |
385 try: text = open(opts['logfile']).read() | |
386 except IOError: pass | |
387 | |
354 | 388 if opts['addremove']: |
389 addremove(ui, repo, *files) | |
317 | 390 repo.commit(relpath(repo, files), text, opts['user'], opts['date']) |
245 | 391 |
363 | 392 def copy(ui, repo, source, dest): |
393 """mark a file as copied or renamed for the next commit""" | |
394 return repo.copy(*relpath(repo, (source, dest))) | |
395 | |
596 | 396 def debugcheckstate(ui, repo): |
397 """validate the correctness of the current dirstate""" | |
460 | 398 parent1, parent2 = repo.dirstate.parents() |
555 | 399 repo.dirstate.read() |
400 dc = repo.dirstate.map | |
460 | 401 keys = dc.keys() |
402 keys.sort() | |
403 m1n = repo.changelog.read(parent1)[0] | |
404 m2n = repo.changelog.read(parent2)[0] | |
405 m1 = repo.manifest.read(m1n) | |
406 m2 = repo.manifest.read(m2n) | |
407 errors = 0 | |
408 for f in dc: | |
409 state = repo.dirstate.state(f) | |
410 if state in "nr" and f not in m1: | |
582 | 411 ui.warn("%s in state %s, but not in manifest1\n" % (f, state)) |
460 | 412 errors += 1 |
413 if state in "a" and f in m1: | |
582 | 414 ui.warn("%s in state %s, but also in manifest1\n" % (f, state)) |
460 | 415 errors += 1 |
416 if state in "m" and f not in m1 and f not in m2: | |
582 | 417 ui.warn("%s in state %s, but not in either manifest\n" % |
418 (f, state)) | |
460 | 419 errors += 1 |
420 for f in m1: | |
421 state = repo.dirstate.state(f) | |
422 if state not in "nrm": | |
582 | 423 ui.warn("%s in manifest1, but listed as state %s" % (f, state)) |
460 | 424 errors += 1 |
425 if errors: | |
582 | 426 ui.warn(".hg/dirstate inconsistent with current parent's manifest\n") |
460 | 427 sys.exit(1) |
428 | |
596 | 429 def debugstate(ui, repo): |
430 """show the contents of the current dirstate""" | |
555 | 431 repo.dirstate.read() |
432 dc = repo.dirstate.map | |
460 | 433 keys = dc.keys() |
434 keys.sort() | |
435 for file in keys: | |
582 | 436 ui.write("%c %s\n" % (dc[file][0], file)) |
460 | 437 |
248 | 438 def debugindex(ui, file): |
596 | 439 """dump the contents of an index file""" |
417 | 440 r = hg.revlog(hg.opener(""), file, "") |
582 | 441 ui.write(" rev offset length base linkrev" + |
442 " p1 p2 nodeid\n") | |
248 | 443 for i in range(r.count()): |
444 e = r.index[i] | |
582 | 445 ui.write("% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s..\n" % ( |
446 i, e[0], e[1], e[2], e[3], | |
447 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))) | |
248 | 448 |
449 def debugindexdot(ui, file): | |
596 | 450 """dump an index DAG as a .dot file""" |
417 | 451 r = hg.revlog(hg.opener(""), file, "") |
582 | 452 ui.write("digraph G {\n") |
248 | 453 for i in range(r.count()): |
454 e = r.index[i] | |
582 | 455 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i)) |
248 | 456 if e[5] != hg.nullid: |
582 | 457 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i)) |
458 ui.write("}\n") | |
248 | 459 |
245 | 460 def diff(ui, repo, *files, **opts): |
255 | 461 """diff working directory (or selected files)""" |
245 | 462 revs = [] |
463 if opts['rev']: | |
464 revs = map(lambda x: repo.lookup(x), opts['rev']) | |
396
8f8bb77d560e
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
395
diff
changeset
|
465 |
245 | 466 if len(revs) > 2: |
480
430a10669928
Fixed call to ui.warn()
Thomas Arendsen Hein <thomas@intevation.de>
parents:
479
diff
changeset
|
467 ui.warn("too many revisions to diff\n") |
245 | 468 sys.exit(1) |
469 | |
470 if files: | |
471 files = relpath(repo, files) | |
472 else: | |
473 files = relpath(repo, [""]) | |
474 | |
580 | 475 dodiff(sys.stdout, ui, repo, files, *revs) |
245 | 476 |
580 | 477 def doexport(ui, repo, changeset, seqno, total, revwidth, opts): |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
478 node = repo.lookup(changeset) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
479 prev, other = repo.changelog.parents(node) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
480 change = repo.changelog.read(node) |
580 | 481 |
482 def expand(name): | |
483 expansions = { | |
484 '%': lambda: '%', | |
485 'H': lambda: hg.hex(node), | |
486 'N': lambda: str(total), | |
487 'R': lambda: str(repo.changelog.rev(node)), | |
488 'b': lambda: os.path.basename(repo.root), | |
489 'h': lambda: hg.short(node), | |
490 'n': lambda: str(seqno).zfill(len(str(total))), | |
491 'r': lambda: str(repo.changelog.rev(node)).zfill(revwidth), | |
492 } | |
493 newname = [] | |
494 namelen = len(name) | |
495 i = 0 | |
496 while i < namelen: | |
497 c = name[i] | |
498 if c == '%': | |
499 i += 1 | |
500 c = name[i] | |
501 c = expansions[c]() | |
502 newname.append(c) | |
503 i += 1 | |
504 return ''.join(newname) | |
505 | |
506 if opts['output'] and opts['output'] != '-': | |
507 try: | |
508 fp = open(expand(opts['output']), 'w') | |
509 except KeyError, inst: | |
510 ui.warn("error: invalid format spec '%%%s' in output file name\n" % | |
511 inst.args[0]) | |
512 sys.exit(1) | |
513 else: | |
514 fp = sys.stdout | |
515 | |
582 | 516 fp.write("# HG changeset patch\n") |
517 fp.write("# User %s\n" % change[1]) | |
518 fp.write("# Node ID %s\n" % hg.hex(node)) | |
519 fp.write("# Parent %s\n" % hg.hex(prev)) | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
520 if other != hg.nullid: |
582 | 521 fp.write("# Parent %s\n" % hg.hex(other)) |
522 fp.write(change[4].rstrip()) | |
523 fp.write("\n\n") | |
580 | 524 |
525 dodiff(fp, ui, repo, None, prev, node) | |
396
8f8bb77d560e
Show revisions in diffs like CVS, based on a patch from Goffredo Baroncelli.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
395
diff
changeset
|
526 |
580 | 527 def export(ui, repo, *changesets, **opts): |
528 """dump the header and diffs for one or more changesets""" | |
529 seqno = 0 | |
530 revs = list(revrange(ui, repo, changesets)) | |
531 total = len(revs) | |
532 revwidth = max(len(revs[0]), len(revs[-1])) | |
533 for cset in revs: | |
534 seqno += 1 | |
535 doexport(ui, repo, cset, seqno, total, revwidth, opts) | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
536 |
245 | 537 def forget(ui, repo, file, *files): |
538 """don't add the specified files on the next commit""" | |
539 repo.forget(relpath(repo, (file,) + files)) | |
540 | |
221 | 541 def heads(ui, repo): |
329
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
542 """show current repository heads""" |
221 | 543 for n in repo.changelog.heads(): |
329
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
544 show_changeset(ui, repo, changenode=n) |
221 | 545 |
339
a76fc9c4b67b
added hg identify|id (based on a patch from Andrew Thompson)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
338
diff
changeset
|
546 def identify(ui, repo): |
a76fc9c4b67b
added hg identify|id (based on a patch from Andrew Thompson)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
338
diff
changeset
|
547 """print information about the working copy""" |
343 | 548 parents = [p for p in repo.dirstate.parents() if p != hg.nullid] |
340
97a897d32dfc
Handle the case where the current working copy is not based on a checkout.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
339
diff
changeset
|
549 if not parents: |
343 | 550 ui.write("unknown\n") |
340
97a897d32dfc
Handle the case where the current working copy is not based on a checkout.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
339
diff
changeset
|
551 return |
97a897d32dfc
Handle the case where the current working copy is not based on a checkout.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
339
diff
changeset
|
552 |
386
494c8e3f47f3
Improvements for hg identify:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
371
diff
changeset
|
553 hexfunc = ui.verbose and hg.hex or hg.short |
536 | 554 (c, a, d, u) = repo.changes(None, None) |
386
494c8e3f47f3
Improvements for hg identify:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
371
diff
changeset
|
555 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]), |
494c8e3f47f3
Improvements for hg identify:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
371
diff
changeset
|
556 (c or a or d) and "+" or "")] |
494c8e3f47f3
Improvements for hg identify:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
371
diff
changeset
|
557 |
339
a76fc9c4b67b
added hg identify|id (based on a patch from Andrew Thompson)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
338
diff
changeset
|
558 if not ui.quiet: |
386
494c8e3f47f3
Improvements for hg identify:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
371
diff
changeset
|
559 # multiple tags for a single parent separated by '/' |
494c8e3f47f3
Improvements for hg identify:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
371
diff
changeset
|
560 parenttags = ['/'.join(tags) |
494c8e3f47f3
Improvements for hg identify:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
371
diff
changeset
|
561 for tags in map(repo.nodetags, parents) if tags] |
494c8e3f47f3
Improvements for hg identify:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
371
diff
changeset
|
562 # tags for multiple parents separated by ' + ' |
494c8e3f47f3
Improvements for hg identify:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
371
diff
changeset
|
563 output.append(' + '.join(parenttags)) |
339
a76fc9c4b67b
added hg identify|id (based on a patch from Andrew Thompson)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
338
diff
changeset
|
564 |
386
494c8e3f47f3
Improvements for hg identify:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
371
diff
changeset
|
565 ui.write("%s\n" % ' '.join(output)) |
339
a76fc9c4b67b
added hg identify|id (based on a patch from Andrew Thompson)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
338
diff
changeset
|
566 |
437 | 567 def import_(ui, repo, patch1, *patches, **opts): |
568 """import an ordered set of patches""" | |
569 try: | |
570 import psyco | |
571 psyco.full() | |
572 except: | |
573 pass | |
574 | |
575 patches = (patch1,) + patches | |
500
ebc4714a7632
[PATCH] Clean up destination directory if a clone fails.
mpm@selenic.com
parents:
499
diff
changeset
|
576 |
437 | 577 d = opts["base"] |
578 strip = opts["strip"] | |
579 | |
580 for patch in patches: | |
581 ui.status("applying %s\n" % patch) | |
582 pf = os.path.join(d, patch) | |
583 | |
584 text = "" | |
585 for l in file(pf): | |
586 if l[:4] == "--- ": break | |
587 text += l | |
588 | |
607
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
589 # parse values that exist when importing the result of an hg export |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
590 hgpatch = user = snippet = None |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
591 ui.debug('text:\n') |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
592 for t in text.splitlines(): |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
593 ui.debug(t,'\n') |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
594 if t == '# HG changeset patch' or hgpatch == True: |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
595 hgpatch = True |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
596 if t[:7] == "# User ": |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
597 user = t[7:] |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
598 ui.debug('User: %s\n' % user) |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
599 if t[:2] <> "# " and t.strip() and not snippet: snippet = t |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
600 if snippet: text = snippet + '\n' + text |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
601 ui.debug('text:\n%s\n' % text) |
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
602 |
437 | 603 # make sure text isn't empty |
604 if not text: text = "imported patch %s\n" % patch | |
605 | |
606 f = os.popen("patch -p%d < %s" % (strip, pf)) | |
607 files = [] | |
608 for l in f.read().splitlines(): | |
609 l.rstrip('\r\n'); | |
481
2705d20f77c9
hg import checking for quiet mode didn't work. Fixed using the ui module.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
480
diff
changeset
|
610 ui.status("%s\n" % l) |
437 | 611 if l[:14] == 'patching file ': |
443 | 612 pf = l[14:] |
613 if pf not in files: | |
614 files.append(pf) | |
615 patcherr = f.close() | |
616 if patcherr: | |
617 sys.stderr.write("patch failed") | |
618 sys.exit(1) | |
437 | 619 |
620 if len(files) > 0: | |
621 addremove(ui, repo, *files) | |
607
94744f6fe0e7
[PATCH] Parse and use header data from an hg export'ed changeset
mpm@selenic.com
parents:
605
diff
changeset
|
622 repo.commit(files, text, user) |
437 | 623 |
496 | 624 def init(ui, source=None): |
625 """create a new repository in the current directory""" | |
290 | 626 |
627 if source: | |
496 | 628 ui.warn("no longer supported: use \"hg clone\" instead\n") |
629 sys.exit(1) | |
630 repo = hg.repository(ui, ".", create=1) | |
338 | 631 |
552
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
632 def log(ui, repo, f=None, **opts): |
509 | 633 """show the revision history of the repository or a single file""" |
634 if f: | |
552
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
635 filelog = repo.file(relpath(repo, [f])[0]) |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
636 log = filelog |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
637 lookup = filelog.lookup |
509 | 638 else: |
552
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
639 filelog = None |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
640 log = repo.changelog |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
641 lookup = repo.lookup |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
642 revlist = [] |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
643 revs = [log.rev(lookup(rev)) for rev in opts['rev']] |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
644 while revs: |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
645 if len(revs) == 1: |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
646 revlist.append(revs.pop(0)) |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
647 else: |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
648 a = revs.pop(0) |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
649 b = revs.pop(0) |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
650 off = a > b and -1 or 1 |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
651 revlist.extend(range(a, b + off, off)) |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
652 for i in revlist or range(log.count() - 1, -1, -1): |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
653 show_changeset(ui, repo, filelog=filelog, rev=i) |
255 | 654 |
655 def manifest(ui, repo, rev = []): | |
656 """output the latest or given revision of the project manifest""" | |
657 n = repo.manifest.tip() | |
658 if rev: | |
659 n = repo.manifest.lookup(rev) | |
660 m = repo.manifest.read(n) | |
276 | 661 mf = repo.manifest.readflags(n) |
255 | 662 files = m.keys() |
663 files.sort() | |
664 | |
665 for f in files: | |
276 | 666 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f)) |
255 | 667 |
668 def parents(ui, repo, node = None): | |
669 '''show the parents of the current working dir''' | |
670 if node: | |
671 p = repo.changelog.parents(repo.lookup(hg.bin(node))) | |
672 else: | |
673 p = repo.dirstate.parents() | |
674 | |
675 for n in p: | |
676 if n != hg.nullid: | |
329
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
677 show_changeset(ui, repo, changenode=n) |
255 | 678 |
404 | 679 def pull(ui, repo, source="default", **opts): |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
680 """pull changes from the specified source""" |
506 | 681 source = ui.expandpath(source) |
404 | 682 |
683 ui.status('pulling from %s\n' % (source)) | |
500
ebc4714a7632
[PATCH] Clean up destination directory if a clone fails.
mpm@selenic.com
parents:
499
diff
changeset
|
684 |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
685 other = hg.repository(ui, source) |
516 | 686 fetch = repo.findincoming(other) |
522
2f1de824798a
Fix empty pull bug that appeared this morning
mpm@selenic.com
parents:
518
diff
changeset
|
687 if not fetch: |
2f1de824798a
Fix empty pull bug that appeared this morning
mpm@selenic.com
parents:
518
diff
changeset
|
688 ui.status("no changes found\n") |
2f1de824798a
Fix empty pull bug that appeared this morning
mpm@selenic.com
parents:
518
diff
changeset
|
689 return |
2f1de824798a
Fix empty pull bug that appeared this morning
mpm@selenic.com
parents:
518
diff
changeset
|
690 |
516 | 691 cg = other.changegroup(fetch) |
404 | 692 r = repo.addchangegroup(cg) |
693 if cg and not r: | |
694 if opts['update']: | |
695 return update(ui, repo) | |
580 | 696 else: |
404 | 697 ui.status("(run 'hg update' to get a working copy)\n") |
698 | |
699 return r | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
700 |
371
6e3436082697
hg push: "default-push" default target path
mpm@selenic.com
parents:
367
diff
changeset
|
701 def push(ui, repo, dest="default-push"): |
319 | 702 """push changes to the specified destination""" |
506 | 703 dest = ui.expandpath(dest) |
500
ebc4714a7632
[PATCH] Clean up destination directory if a clone fails.
mpm@selenic.com
parents:
499
diff
changeset
|
704 |
319 | 705 if not dest.startswith("ssh://"): |
706 ui.warn("abort: can only push to ssh:// destinations currently\n") | |
707 return 1 | |
708 | |
709 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest) | |
710 if not m: | |
711 ui.warn("abort: couldn't parse destination %s\n" % dest) | |
712 return 1 | |
713 | |
714 user, host, port, path = map(m.group, (2, 3, 5, 7)) | |
526 | 715 uhost = user and ("%s@%s" % (user, host)) or host |
319 | 716 port = port and (" -p %s") % port or "" |
717 path = path or "" | |
718 | |
719 sport = random.randrange(30000, 60000) | |
720 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'" | |
526 | 721 cmd = cmd % (uhost, port, sport+1, sport, path, sport+1) |
319 | 722 |
723 child = os.fork() | |
724 if not child: | |
725 sys.stdout = file("/dev/null", "w") | |
726 sys.stderr = sys.stdout | |
727 hgweb.server(repo.root, "pull", "", "localhost", sport) | |
728 else: | |
526 | 729 ui.status("connecting to %s\n" % host) |
319 | 730 r = os.system(cmd) |
731 os.kill(child, signal.SIGTERM) | |
320 | 732 return r |
319 | 733 |
403 | 734 def rawcommit(ui, repo, *flist, **rc): |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
735 "raw commit interface" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
736 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
737 text = rc['text'] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
738 if not text and rc['logfile']: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
739 try: text = open(rc['logfile']).read() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
740 except IOError: pass |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
741 if not text and not rc['logfile']: |
582 | 742 ui.warn("abort: missing commit text\n") |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
743 return 1 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
744 |
403 | 745 files = relpath(repo, list(flist)) |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
746 if rc['files']: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
747 files += open(rc['files']).read().splitlines() |
452
a1e91c24dab5
rawcommit: do lookup of parents at the appropriate layer
mpm@selenic.com
parents:
443
diff
changeset
|
748 |
a1e91c24dab5
rawcommit: do lookup of parents at the appropriate layer
mpm@selenic.com
parents:
443
diff
changeset
|
749 rc['parent'] = map(repo.lookup, rc['parent']) |
500
ebc4714a7632
[PATCH] Clean up destination directory if a clone fails.
mpm@selenic.com
parents:
499
diff
changeset
|
750 |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
751 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent']) |
500
ebc4714a7632
[PATCH] Clean up destination directory if a clone fails.
mpm@selenic.com
parents:
499
diff
changeset
|
752 |
245 | 753 def recover(ui, repo): |
255 | 754 """roll back an interrupted transaction""" |
245 | 755 repo.recover() |
756 | |
757 def remove(ui, repo, file, *files): | |
758 """remove the specified files on the next commit""" | |
759 repo.remove(relpath(repo, (file,) + files)) | |
760 | |
588 | 761 def revert(ui, repo, *names, **opts): |
762 """revert modified files or dirs back to their unmodified states""" | |
590
38d106db75bc
hg revert should revert to parent, not to tip
mpm@selenic.com
parents:
588
diff
changeset
|
763 node = opts['rev'] and repo.lookup(opts['rev']) or \ |
38d106db75bc
hg revert should revert to parent, not to tip
mpm@selenic.com
parents:
588
diff
changeset
|
764 repo.dirstate.parents()[0] |
588 | 765 root = os.path.realpath(repo.root) |
590
38d106db75bc
hg revert should revert to parent, not to tip
mpm@selenic.com
parents:
588
diff
changeset
|
766 |
588 | 767 def trimpath(p): |
768 p = os.path.realpath(p) | |
769 if p.startswith(root): | |
770 rest = p[len(root):] | |
771 if not rest: | |
772 return rest | |
773 if p.startswith(os.sep): | |
774 return rest[1:] | |
775 return p | |
590
38d106db75bc
hg revert should revert to parent, not to tip
mpm@selenic.com
parents:
588
diff
changeset
|
776 |
588 | 777 relnames = map(trimpath, names or [os.getcwd()]) |
778 chosen = {} | |
590
38d106db75bc
hg revert should revert to parent, not to tip
mpm@selenic.com
parents:
588
diff
changeset
|
779 |
588 | 780 def choose(name): |
781 def body(name): | |
782 for r in relnames: | |
783 if not name.startswith(r): continue | |
784 rest = name[len(r):] | |
785 if not rest: return r, True | |
786 depth = rest.count(os.sep) | |
787 if not r: | |
788 if depth == 0 or not opts['nonrecursive']: return r, True | |
789 elif rest[0] == os.sep: | |
790 if depth == 1 or not opts['nonrecursive']: return r, True | |
791 return None, False | |
792 relname, ret = body(name) | |
793 if ret: | |
794 chosen[relname] = 1 | |
795 return ret | |
796 | |
797 r = repo.update(node, False, True, choose, False) | |
798 for n in relnames: | |
799 if n not in chosen: | |
800 ui.warn('error: no matches for %s\n' % n) | |
801 r = 1 | |
802 sys.stdout.flush() | |
803 return r | |
804 | |
468 | 805 def root(ui, repo): |
806 """print the root (top) of the current working dir""" | |
807 ui.write(repo.root + "\n") | |
808 | |
245 | 809 def serve(ui, repo, **opts): |
255 | 810 """export the repository via HTTP""" |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
811 def openlog(opt, default): |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
812 if opts[opt] and opts[opt] != '-': return open(opts[opt], 'w') |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
813 else: return default |
603
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
814 httpd = hgweb.create_server(repo.root, opts["name"], opts["templates"], |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
815 opts["address"], opts["port"], |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
816 openlog('accesslog', sys.stdout), |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
817 openlog('errorlog', sys.stderr)) |
603
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
818 if ui.verbose: |
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
819 addr, port = httpd.socket.getsockname() |
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
820 if addr == '0.0.0.0': |
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
821 addr = socket.gethostname() |
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
822 else: |
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
823 try: |
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
824 addr = socket.gethostbyaddr(addr)[0] |
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
825 except: pass |
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
826 if port != 80: |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
827 ui.status('listening at http://%s:%d/\n' % (addr, port)) |
603
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
828 else: |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
829 ui.status('listening at http://%s/\n' % addr) |
603
bc5d058e65e9
[PATCH] Get "hg serve" to print the URL being served
mpm@selenic.com
parents:
596
diff
changeset
|
830 httpd.serve_forever() |
500
ebc4714a7632
[PATCH] Clean up destination directory if a clone fails.
mpm@selenic.com
parents:
499
diff
changeset
|
831 |
213 | 832 def status(ui, repo): |
833 '''show changed files in the working directory | |
834 | |
245 | 835 C = changed |
836 A = added | |
837 R = removed | |
838 ? = not tracked''' | |
312 | 839 |
537 | 840 (c, a, d, u) = repo.changes(None, None) |
220 | 841 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u)) |
213 | 842 |
582 | 843 for f in c: ui.write("C ", f, "\n") |
844 for f in a: ui.write("A ", f, "\n") | |
845 for f in d: ui.write("R ", f, "\n") | |
846 for f in u: ui.write("? ", f, "\n") | |
213 | 847 |
401
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
848 def tag(ui, repo, name, rev = None, **opts): |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
849 """add a tag for the current tip or a given revision""" |
500
ebc4714a7632
[PATCH] Clean up destination directory if a clone fails.
mpm@selenic.com
parents:
499
diff
changeset
|
850 |
401
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
851 if name == "tip": |
580 | 852 ui.warn("abort: 'tip' is a reserved name!\n") |
853 return -1 | |
854 if name.find(revrangesep) >= 0: | |
855 ui.warn("abort: '%s' cannot be used in a tag name\n" % revrangesep) | |
856 return -1 | |
401
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
857 |
536 | 858 (c, a, d, u) = repo.changes(None, None) |
401
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
859 for x in (c, a, d, u): |
580 | 860 if ".hgtags" in x: |
861 ui.warn("abort: working copy of .hgtags is changed!\n") | |
401
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
862 ui.status("(please commit .hgtags manually)\n") |
580 | 863 return -1 |
401
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
864 |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
865 if rev: |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
866 r = hg.hex(repo.lookup(rev)) |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
867 else: |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
868 r = hg.hex(repo.changelog.tip()) |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
869 |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
870 add = 0 |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
871 if not os.path.exists(repo.wjoin(".hgtags")): add = 1 |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
872 repo.wfile(".hgtags", "a").write("%s %s\n" % (r, name)) |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
873 if add: repo.add([".hgtags"]) |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
874 |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
875 if not opts['text']: |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
876 opts['text'] = "Added tag %s for changeset %s" % (name, r) |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
877 |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
878 repo.commit([".hgtags"], opts['text'], opts['user'], opts['date']) |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
879 |
248 | 880 def tags(ui, repo): |
255 | 881 """list repository tags""" |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
470
diff
changeset
|
882 |
343 | 883 l = repo.tagslist() |
884 l.reverse() | |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
470
diff
changeset
|
885 for t, n in l: |
248 | 886 try: |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
470
diff
changeset
|
887 r = "%5d:%s" % (repo.changelog.rev(n), hg.hex(n)) |
248 | 888 except KeyError: |
477
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
470
diff
changeset
|
889 r = " ?:?" |
520540fd6b64
Handle errors in .hgtags or hgrc [tags] section more gracefully.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
470
diff
changeset
|
890 ui.write("%-30s %s\n" % (t, r)) |
248 | 891 |
245 | 892 def tip(ui, repo): |
255 | 893 """show the tip revision""" |
245 | 894 n = repo.changelog.tip() |
329
67c19ad374a9
Use common output function show_changeset() for hg heads|history|log|tip.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
320
diff
changeset
|
895 show_changeset(ui, repo, changenode=n) |
245 | 896 |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
897 def undo(ui, repo): |
596 | 898 """undo the last commit or pull |
899 | |
900 Roll back the last pull or commit transaction on the | |
901 repository, restoring the project to its earlier state. | |
902 | |
903 This command should be used with care. There is only one level of | |
904 undo and there is no redo. | |
905 | |
906 This command is not intended for use on public repositories. Once | |
907 a change is visible for pull by other users, undoing it locally is | |
908 ineffective. | |
909 """ | |
210 | 910 repo.undo() |
911 | |
275 | 912 def update(ui, repo, node=None, merge=False, clean=False): |
254 | 913 '''update or merge working directory |
914 | |
915 If there are no outstanding changes in the working directory and | |
916 there is a linear relationship between the current version and the | |
917 requested version, the result is the requested version. | |
918 | |
919 Otherwise the result is a merge between the contents of the | |
920 current working directory and the requested version. Files that | |
921 changed between either parent are marked as changed for the next | |
922 commit and a commit must be performed before any further updates | |
923 are allowed. | |
924 ''' | |
925 node = node and repo.lookup(node) or repo.changelog.tip() | |
275 | 926 return repo.update(node, allow=merge, force=clean) |
254 | 927 |
247 | 928 def verify(ui, repo): |
929 """verify the integrity of the repository""" | |
930 return repo.verify() | |
931 | |
255 | 932 # Command options and aliases are listed here, alphabetically |
933 | |
209 | 934 table = { |
593 | 935 "^add": (add, [], "hg add [files]"), |
353 | 936 "addremove": (addremove, [], "hg addremove [files]"), |
596 | 937 "^annotate": (annotate, |
209 | 938 [('r', 'revision', '', 'revision'), |
939 ('u', 'user', None, 'show user'), | |
940 ('n', 'number', None, 'show revision number'), | |
941 ('c', 'changeset', None, 'show changeset')], | |
942 'hg annotate [-u] [-c] [-n] [-r id] [files]'), | |
437 | 943 "cat": (cat, [], 'hg cat <file> [rev]'), |
593 | 944 "^clone": (clone, [('U', 'noupdate', None, 'skip update after cloning')], |
485 | 945 'hg clone [options] <source> [dest]'), |
593 | 946 "^commit|ci": (commit, |
289 | 947 [('t', 'text', "", 'commit text'), |
354 | 948 ('A', 'addremove', None, 'run add/remove during commit'), |
317 | 949 ('l', 'logfile', "", 'commit text file'), |
591 | 950 ('d', 'date', "", 'date code'), |
317 | 951 ('u', 'user', "", 'user')], |
289 | 952 'hg commit [files]'), |
363 | 953 "copy": (copy, [], 'hg copy <source> <dest>'), |
596 | 954 "debugcheckstate": (debugcheckstate, [], 'debugcheckstate'), |
955 "debugstate": (debugstate, [], 'debugstate'), | |
248 | 956 "debugindex": (debugindex, [], 'debugindex <file>'), |
957 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'), | |
593 | 958 "^diff": (diff, [('r', 'rev', [], 'revision')], |
245 | 959 'hg diff [-r A] [-r B] [files]'), |
596 | 960 "^export": (export, [('o', 'output', "", 'output to file')], |
580 | 961 "hg export [-o file] <changeset> ..."), |
245 | 962 "forget": (forget, [], "hg forget [files]"), |
963 "heads": (heads, [], 'hg heads'), | |
964 "help": (help, [], 'hg help [command]'), | |
339
a76fc9c4b67b
added hg identify|id (based on a patch from Andrew Thompson)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
338
diff
changeset
|
965 "identify|id": (identify, [], 'hg identify'), |
437 | 966 "import|patch": (import_, |
967 [('p', 'strip', 1, 'path strip'), | |
968 ('b', 'base', "", 'base path')], | |
969 "hg import [options] <patches>"), | |
593 | 970 "^init": (init, [], 'hg init'), |
971 "^log|history": (log, | |
552
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
972 [('r', 'rev', [], 'revision')], |
2204311609a0
Allow specifying revisions in 'hg log' like with 'hg diff'.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
547
diff
changeset
|
973 'hg log [-r A] [-r B] [file]'), |
437 | 974 "manifest": (manifest, [], 'hg manifest [rev]'), |
227 | 975 "parents": (parents, [], 'hg parents [node]'), |
593 | 976 "^pull": (pull, |
404 | 977 [('u', 'update', None, 'update working directory')], |
580 | 978 'hg pull [options] [source]'), |
593 | 979 "^push": (push, [], 'hg push <destination>'), |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
980 "rawcommit": (rawcommit, |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
981 [('p', 'parent', [], 'parent'), |
591 | 982 ('d', 'date', "", 'date code'), |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
983 ('u', 'user', "", 'user'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
984 ('F', 'files', "", 'file list'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
985 ('t', 'text', "", 'commit text'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
986 ('l', 'logfile', "", 'commit text file')], |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
987 'hg rawcommit [options] [files]'), |
245 | 988 "recover": (recover, [], "hg recover"), |
593 | 989 "^remove|rm": (remove, [], "hg remove [files]"), |
596 | 990 "^revert": (revert, |
588 | 991 [("n", "nonrecursive", None, "don't recurse into subdirs"), |
992 ("r", "rev", "", "revision")], | |
993 "hg revert [files|dirs]"), | |
468 | 994 "root": (root, [], "hg root"), |
605
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
995 "^serve": (serve, [('A', 'accesslog', '', 'access log file'), |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
996 ('E', 'errorlog', '', 'error log file'), |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
997 ('p', 'port', 8000, 'listen port'), |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
998 ('a', 'address', '', 'interface address'), |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
999 ('n', 'name', os.getcwd(), 'repository name'), |
8e82fd763be2
[PATCH] Get "hg serve" to optionally log accesses and errors to files
mpm@selenic.com
parents:
604
diff
changeset
|
1000 ('t', 'templates', "", 'template map')], |
245 | 1001 "hg serve [options]"), |
593 | 1002 "^status": (status, [], 'hg status'), |
401
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
1003 "tag": (tag, [('t', 'text', "", 'commit text'), |
591 | 1004 ('d', 'date', "", 'date code'), |
401
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
1005 ('u', 'user', "", 'user')], |
af4848f83e68
From: Radoslaw Szkodzinski <astralstorm@gorzow.mm.pl>
mpm@selenic.com
parents:
396
diff
changeset
|
1006 'hg tag [options] <name> [rev]'), |
248 | 1007 "tags": (tags, [], 'hg tags'), |
245 | 1008 "tip": (tip, [], 'hg tip'), |
210 | 1009 "undo": (undo, [], 'hg undo'), |
593 | 1010 "^update|up|checkout|co": |
437 | 1011 (update, |
1012 [('m', 'merge', None, 'allow merging of conflicts'), | |
1013 ('C', 'clean', None, 'overwrite locally modified files')], | |
1014 'hg update [options] [node]'), | |
247 | 1015 "verify": (verify, [], 'hg verify'), |
470
0ab093b473c5
Fix up version module name and command conflict
mpm@selenic.com
parents:
468
diff
changeset
|
1016 "version": (show_version, [], 'hg version'), |
209 | 1017 } |
1018 | |
596 | 1019 globalopts = [('v', 'verbose', None, 'verbose'), |
1020 ('', 'debug', None, 'debug'), | |
1021 ('q', 'quiet', None, 'quiet'), | |
1022 ('', 'profile', None, 'profile'), | |
1023 ('R', 'repository', "", 'repository root directory'), | |
1024 ('', 'traceback', None, 'print traceback on exception'), | |
1025 ('y', 'noninteractive', None, 'run non-interactively'), | |
1026 ('', 'version', None, 'output version information and exit'), | |
1027 ] | |
1028 | |
485 | 1029 norepo = "clone init version help debugindex debugindexdot" |
209 | 1030 |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1031 def find(cmd): |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1032 for e in table.keys(): |
335 | 1033 if re.match("(%s)$" % e, cmd): |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1034 return table[e] |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1035 |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1036 raise UnknownCommand(cmd) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1037 |
214 | 1038 class SignalInterrupt(Exception): pass |
1039 | |
1040 def catchterm(*args): | |
1041 raise SignalInterrupt | |
1042 | |
249 | 1043 def run(): |
1044 sys.exit(dispatch(sys.argv[1:])) | |
1045 | |
596 | 1046 class ParseError(Exception): pass |
592 | 1047 |
596 | 1048 def parse(args): |
209 | 1049 options = {} |
596 | 1050 cmdoptions = {} |
209 | 1051 |
592 | 1052 try: |
596 | 1053 args = fancyopts.fancyopts(args, globalopts, options) |
592 | 1054 except fancyopts.getopt.GetoptError, inst: |
596 | 1055 raise ParseError(cmd, inst) |
209 | 1056 |
596 | 1057 if options["version"]: |
1058 return ("version", show_version, [], options, cmdoptions) | |
1059 elif not args: | |
1060 return ("help", help, [], options, cmdoptions) | |
209 | 1061 else: |
1062 cmd, args = args[0], args[1:] | |
1063 | |
596 | 1064 i = find(cmd) |
209 | 1065 |
592 | 1066 # combine global options into local |
1067 c = list(i[1]) | |
1068 l = len(c) | |
596 | 1069 for o in globalopts: |
592 | 1070 c.append((o[0], o[1], options[o[1]], o[3])) |
214 | 1071 |
293 | 1072 try: |
596 | 1073 args = fancyopts.fancyopts(args, c, cmdoptions) |
293 | 1074 except fancyopts.getopt.GetoptError, inst: |
596 | 1075 raise ParseError(cmd, inst) |
209 | 1076 |
592 | 1077 # separate global options back out |
596 | 1078 for o in globalopts: |
592 | 1079 n = o[1] |
1080 options[n] = cmdoptions[n] | |
1081 del cmdoptions[n] | |
1082 | |
596 | 1083 return (cmd, i[0], args, options, cmdoptions) |
1084 | |
1085 def dispatch(args): | |
1086 signal.signal(signal.SIGTERM, catchterm) | |
1087 | |
1088 try: | |
1089 cmd, func, args, options, cmdoptions = parse(args) | |
1090 except ParseError, inst: | |
1091 u = ui.ui() | |
1092 if inst.args[0]: | |
1093 u.warn("hg %s: %s\n" % (inst.args[0], inst.args[1])) | |
1094 help(u, inst.args[0]) | |
1095 else: | |
1096 u.warn("hg: %s\n" % inst.args[1]) | |
1097 help(u) | |
1098 sys.exit(-1) | |
1099 except UnknownCommand, inst: | |
1100 u = ui.ui() | |
1101 u.warn("hg: unknown command '%s'\n" % inst.args[0]) | |
1102 help(u) | |
1103 sys.exit(1) | |
1104 | |
1105 u = ui.ui(options["verbose"], options["debug"], options["quiet"], | |
1106 not options["noninteractive"]) | |
592 | 1107 |
499 | 1108 try: |
527 | 1109 try: |
1110 if cmd not in norepo.split(): | |
1111 path = options["repository"] or "" | |
1112 repo = hg.repository(ui=u, path=path) | |
596 | 1113 d = lambda: func(u, repo, *args, **cmdoptions) |
527 | 1114 else: |
596 | 1115 d = lambda: func(u, *args, **cmdoptions) |
209 | 1116 |
527 | 1117 if options['profile']: |
1118 import hotshot, hotshot.stats | |
1119 prof = hotshot.Profile("hg.prof") | |
1120 r = prof.runcall(d) | |
1121 prof.close() | |
1122 stats = hotshot.stats.load("hg.prof") | |
1123 stats.strip_dirs() | |
1124 stats.sort_stats('time', 'calls') | |
1125 stats.print_stats(40) | |
1126 return r | |
1127 else: | |
1128 return d() | |
1129 except: | |
1130 if options['traceback']: | |
1131 traceback.print_exc() | |
1132 raise | |
508 | 1133 except util.CommandError, inst: |
1134 u.warn("abort: %s\n" % inst.args) | |
499 | 1135 except hg.RepoError, inst: |
1136 u.warn("abort: ", inst, "!\n") | |
214 | 1137 except SignalInterrupt: |
1138 u.warn("killed!\n") | |
209 | 1139 except KeyboardInterrupt: |
1140 u.warn("interrupted!\n") | |
250 | 1141 except IOError, inst: |
395 | 1142 if hasattr(inst, "code"): |
1143 u.warn("abort: %s\n" % inst) | |
1144 elif hasattr(inst, "reason"): | |
1145 u.warn("abort: error %d: %s\n" % (inst.reason[0], inst.reason[1])) | |
1146 elif hasattr(inst, "args") and inst[0] == errno.EPIPE: | |
250 | 1147 u.warn("broken pipe\n") |
1148 else: | |
1149 raise | |
549 | 1150 except OSError, inst: |
1151 if hasattr(inst, "filename"): | |
1152 u.warn("abort: %s: %s\n" % (inst.strerror, inst.filename)) | |
1153 else: | |
1154 u.warn("abort: %s\n" % inst.strerror) | |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1155 except TypeError, inst: |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1156 # was this an argument error? |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1157 tb = traceback.extract_tb(sys.exc_info()[2]) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1158 if len(tb) > 2: # no |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
1159 raise |
293 | 1160 u.debug(inst, "\n") |
596 | 1161 u.warn("%s: invalid arguments\n" % cmd) |
293 | 1162 help(u, cmd) |
1163 | |
503
c6a2e41c8c60
Fix troubles with clone and exception handling
mpm@selenic.com
parents:
500
diff
changeset
|
1164 sys.exit(-1) |