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