Mercurial > hg > mercurial-crew-with-dirclash
annotate mercurial/commands.py @ 276:10e325db7347
add tracking of execute permissions
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
add tracking of execute permissions
Changes to executable permissions are now tracked. We only track one
bit here as the others tends to be problematic. "hg manifest" now
shows file permissions.
manifest hash: b76b85d12a9550fdc9fbc4f9446a812f3a2bbe88
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.0 (GNU/Linux)
iD8DBQFCpzYBywK+sNU5EO8RAgkMAJ48l2ac12E20EFS24/i8ScwOtG4HwCgkbaE
ue6l1RJroqzNA7vNeqwCwK4=
=sEmJ
-----END PGP SIGNATURE-----
author | mpm@selenic.com |
---|---|
date | Wed, 08 Jun 2005 10:16:33 -0800 |
parents | 61d45b0ba8fb |
children | 574420507d8c |
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 |
9 import fancyopts, ui, hg | |
10 from demandload import * | |
11 demandload(globals(), "mdiff time hgweb traceback") | |
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: |
19 if t and t[-1] != os.sep: t += os.sep | |
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: ] | |
245 | 26 return filterfiles(p, files) |
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: ] | |
245 | 32 return [ os.path.normpath(os.path.join(p, x)) for x in args ] |
209 | 33 return args |
245 | 34 |
35 def dodiff(repo, files = None, node1 = None, node2 = None): | |
36 def date(c): | |
37 return time.asctime(time.gmtime(float(c[2].split(' ')[0]))) | |
38 | |
39 if node2: | |
40 change = repo.changelog.read(node2) | |
41 mmap2 = repo.manifest.read(change[0]) | |
42 (c, a, d) = repo.diffrevs(node1, node2) | |
43 def read(f): return repo.file(f).read(mmap2[f]) | |
44 date2 = date(change) | |
45 else: | |
46 date2 = time.asctime() | |
47 (c, a, d, u) = repo.diffdir(repo.root, node1) | |
48 if not node1: | |
49 node1 = repo.dirstate.parents()[0] | |
50 def read(f): return file(os.path.join(repo.root, f)).read() | |
51 | |
52 change = repo.changelog.read(node1) | |
53 mmap = repo.manifest.read(change[0]) | |
54 date1 = date(change) | |
55 | |
56 if files: | |
57 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d)) | |
58 | |
59 for f in c: | |
275 | 60 to = None |
61 if f in mmap: | |
62 to = repo.file(f).read(mmap[f]) | |
245 | 63 tn = read(f) |
64 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f)) | |
65 for f in a: | |
264
4c1d7072d5cd
Attempt to make diff deal with null sources properly
mpm@selenic.com
parents:
262
diff
changeset
|
66 to = None |
245 | 67 tn = read(f) |
68 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f)) | |
69 for f in d: | |
70 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
|
71 tn = None |
245 | 72 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f)) |
209 | 73 |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
74 def help(ui, cmd=None): |
255 | 75 '''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
|
76 if cmd: |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
77 try: |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
78 i = find(cmd) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
79 ui.write("%s\n\n" % i[2]) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
80 ui.write(i[0].__doc__, "\n") |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
81 except UnknownCommand: |
268 | 82 ui.warn("hg: unknown command %s\n" % cmd) |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
83 sys.exit(0) |
255 | 84 else: |
85 ui.status('hg commands:\n\n') | |
209 | 86 |
255 | 87 h = {} |
88 for e in table.values(): | |
89 f = e[0] | |
90 if f.__name__.startswith("debug"): continue | |
91 d = "" | |
92 if f.__doc__: | |
93 d = f.__doc__.splitlines(0)[0].rstrip() | |
94 h[f.__name__] = d | |
95 | |
96 fns = h.keys() | |
97 fns.sort() | |
98 m = max(map(len, fns)) | |
99 for f in fns: | |
100 ui.status(' %-*s %s\n' % (m, f, h[f])) | |
101 | |
102 # Commands start here, listed alphabetically | |
209 | 103 |
245 | 104 def add(ui, repo, file, *files): |
105 '''add the specified files on the next commit''' | |
106 repo.add(relpath(repo, (file,) + files)) | |
213 | 107 |
245 | 108 def addremove(ui, repo): |
255 | 109 """add all new files, delete all missing files""" |
230 | 110 (c, a, d, u) = repo.diffdir(repo.root) |
259 | 111 repo.add(u) |
245 | 112 repo.remove(d) |
219
8ff4532376a4
hg checkout: refuse to checkout if there are outstanding changes
mpm@selenic.com
parents:
214
diff
changeset
|
113 |
245 | 114 def annotate(u, repo, file, *files, **ops): |
255 | 115 """show changeset information per file line""" |
209 | 116 def getnode(rev): |
117 return hg.short(repo.changelog.node(rev)) | |
118 | |
119 def getname(rev): | |
120 try: | |
121 return bcache[rev] | |
122 except KeyError: | |
123 cl = repo.changelog.read(repo.changelog.node(rev)) | |
124 name = cl[1] | |
125 f = name.find('@') | |
126 if f >= 0: | |
127 name = name[:f] | |
128 bcache[rev] = name | |
129 return name | |
130 | |
131 bcache = {} | |
132 opmap = [['user', getname], ['number', str], ['changeset', getnode]] | |
133 if not ops['user'] and not ops['changeset']: | |
134 ops['number'] = 1 | |
135 | |
227 | 136 node = repo.dirstate.parents()[0] |
209 | 137 if ops['revision']: |
138 node = repo.changelog.lookup(ops['revision']) | |
139 change = repo.changelog.read(node) | |
140 mmap = repo.manifest.read(change[0]) | |
141 maxuserlen = 0 | |
142 maxchangelen = 0 | |
245 | 143 for f in relpath(repo, (file,) + files): |
209 | 144 lines = repo.file(f).annotate(mmap[f]) |
145 pieces = [] | |
146 | |
147 for o, f in opmap: | |
148 if ops[o]: | |
149 l = [ f(n) for n,t in lines ] | |
150 m = max(map(len, l)) | |
151 pieces.append([ "%*s" % (m, x) for x in l]) | |
152 | |
153 for p,l in zip(zip(*pieces), lines): | |
154 u.write(" ".join(p) + ": " + l[1]) | |
155 | |
245 | 156 def branch(ui, path): |
157 '''branch from a local repository''' | |
158 # this should eventually support remote repos | |
159 os.system("cp -al %s/.hg .hg" % path) | |
160 | |
248 | 161 def cat(ui, repo, file, rev = []): |
255 | 162 """output the latest or given revision of a file""" |
248 | 163 r = repo.file(file) |
164 n = r.tip() | |
165 if rev: n = r.lookup(rev) | |
166 sys.stdout.write(r.read(n)) | |
167 | |
245 | 168 def commit(ui, repo, *files): |
169 """commit the specified files or all outstanding changes""" | |
170 repo.commit(relpath(repo, files)) | |
171 | |
248 | 172 def debugaddchangegroup(ui, repo): |
173 data = sys.stdin.read() | |
174 repo.addchangegroup(data) | |
175 | |
176 def debugchangegroup(ui, repo, roots): | |
177 newer = repo.newer(map(repo.lookup, roots)) | |
178 for chunk in repo.changegroup(newer): | |
179 sys.stdout.write(chunk) | |
180 | |
181 def debugindex(ui, file): | |
182 r = hg.revlog(open, file, "") | |
183 print " rev offset length base linkrev"+\ | |
184 " p1 p2 nodeid" | |
185 for i in range(r.count()): | |
186 e = r.index[i] | |
187 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % ( | |
188 i, e[0], e[1], e[2], e[3], | |
189 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5])) | |
190 | |
191 def debugindexdot(ui, file): | |
192 r = hg.revlog(open, file, "") | |
193 print "digraph G {" | |
194 for i in range(r.count()): | |
195 e = r.index[i] | |
196 print "\t%d -> %d" % (r.rev(e[4]), i) | |
197 if e[5] != hg.nullid: | |
198 print "\t%d -> %d" % (r.rev(e[5]), i) | |
199 print "}" | |
200 | |
245 | 201 def diff(ui, repo, *files, **opts): |
255 | 202 """diff working directory (or selected files)""" |
245 | 203 revs = [] |
204 if opts['rev']: | |
205 revs = map(lambda x: repo.lookup(x), opts['rev']) | |
206 | |
207 if len(revs) > 2: | |
208 self.ui.warn("too many revisions to diff\n") | |
209 sys.exit(1) | |
210 | |
211 if files: | |
212 files = relpath(repo, files) | |
213 else: | |
214 files = relpath(repo, [""]) | |
215 | |
216 dodiff(repo, files, *revs) | |
217 | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
218 def export(ui, repo, changeset): |
255 | 219 """dump the changeset header and diffs for a revision""" |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
220 node = repo.lookup(changeset) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
221 prev, other = repo.changelog.parents(node) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
222 change = repo.changelog.read(node) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
223 print "# HG changeset patch" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
224 print "# User %s" % change[1] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
225 print "# Node ID %s" % hg.hex(node) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
226 print "# Parent %s" % hg.hex(prev) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
227 print |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
228 if other != hg.nullid: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
229 print "# Parent %s" % hg.hex(other) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
230 print change[4].rstrip() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
231 print |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
232 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
233 dodiff(repo, None, prev, node) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
234 |
245 | 235 def forget(ui, repo, file, *files): |
236 """don't add the specified files on the next commit""" | |
237 repo.forget(relpath(repo, (file,) + files)) | |
238 | |
221 | 239 def heads(ui, repo): |
240 '''show current repository heads''' | |
241 for n in repo.changelog.heads(): | |
242 i = repo.changelog.rev(n) | |
243 changes = repo.changelog.read(n) | |
244 (p1, p2) = repo.changelog.parents(n) | |
245 (h, h1, h2) = map(hg.hex, (n, p1, p2)) | |
246 (i1, i2) = map(repo.changelog.rev, (p1, p2)) | |
247 print "rev: %4d:%s" % (i, h) | |
248 print "parents: %4d:%s" % (i1, h1) | |
249 if i2: print " %4d:%s" % (i2, h2) | |
250 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]), | |
251 hg.hex(changes[0])) | |
252 print "user:", changes[1] | |
253 print "date:", time.asctime( | |
254 time.localtime(float(changes[2].split(' ')[0]))) | |
255 if ui.verbose: print "files:", " ".join(changes[3]) | |
256 print "description:" | |
257 print changes[4] | |
258 | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
259 def history(ui, repo): |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
260 """show the changelog history""" |
270
5a80ed2158c8
Reverse order of hg log and hg history lists
mpm@selenic.com
parents:
268
diff
changeset
|
261 for i in range(repo.changelog.count() - 1, -1, -1): |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
262 n = repo.changelog.node(i) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
263 changes = repo.changelog.read(n) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
264 (p1, p2) = repo.changelog.parents(n) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
265 (h, h1, h2) = map(hg.hex, (n, p1, p2)) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
266 (i1, i2) = map(repo.changelog.rev, (p1, p2)) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
267 print "rev: %4d:%s" % (i, h) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
268 print "parents: %4d:%s" % (i1, h1) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
269 if i2: print " %4d:%s" % (i2, h2) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
270 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
271 hg.hex(changes[0])) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
272 print "user:", changes[1] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
273 print "date:", time.asctime( |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
274 time.localtime(float(changes[2].split(' ')[0]))) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
275 if ui.verbose: print "files:", " ".join(changes[3]) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
276 print "description:" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
277 print changes[4] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
278 |
255 | 279 def init(ui): |
280 """create a repository""" | |
281 hg.repository(ui, ".", create=1) | |
282 | |
283 def log(ui, repo, f): | |
284 """show the revision history of a single file""" | |
285 f = relpath(repo, [f])[0] | |
286 | |
287 r = repo.file(f) | |
270
5a80ed2158c8
Reverse order of hg log and hg history lists
mpm@selenic.com
parents:
268
diff
changeset
|
288 for i in range(r.count() - 1, -1, -1): |
255 | 289 n = r.node(i) |
290 (p1, p2) = r.parents(n) | |
291 (h, h1, h2) = map(hg.hex, (n, p1, p2)) | |
292 (i1, i2) = map(r.rev, (p1, p2)) | |
293 cr = r.linkrev(n) | |
294 cn = hg.hex(repo.changelog.node(cr)) | |
295 print "rev: %4d:%s" % (i, h) | |
296 print "changeset: %4d:%s" % (cr, cn) | |
297 print "parents: %4d:%s" % (i1, h1) | |
298 if i2: print " %4d:%s" % (i2, h2) | |
299 changes = repo.changelog.read(repo.changelog.node(cr)) | |
300 print "user: %s" % changes[1] | |
301 print "date: %s" % time.asctime( | |
302 time.localtime(float(changes[2].split(' ')[0]))) | |
303 print "description:" | |
304 print changes[4].rstrip() | |
305 print | |
306 | |
307 def manifest(ui, repo, rev = []): | |
308 """output the latest or given revision of the project manifest""" | |
309 n = repo.manifest.tip() | |
310 if rev: | |
311 n = repo.manifest.lookup(rev) | |
312 m = repo.manifest.read(n) | |
276 | 313 mf = repo.manifest.readflags(n) |
255 | 314 files = m.keys() |
315 files.sort() | |
316 | |
317 for f in files: | |
276 | 318 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f)) |
255 | 319 |
320 def parents(ui, repo, node = None): | |
321 '''show the parents of the current working dir''' | |
322 if node: | |
323 p = repo.changelog.parents(repo.lookup(hg.bin(node))) | |
324 else: | |
325 p = repo.dirstate.parents() | |
326 | |
327 for n in p: | |
328 if n != hg.nullid: | |
329 ui.write("%d:%s\n" % (repo.changelog.rev(n), hg.hex(n))) | |
330 | |
266
4af7677de4a9
Fix argument processing for patch and rawcommit
mpm@selenic.com
parents:
264
diff
changeset
|
331 def patch(ui, repo, patches, **opts): |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
332 """import an ordered set of patches""" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
333 try: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
334 import psyco |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
335 psyco.full() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
336 except: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
337 pass |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
338 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
339 d = opts["base"] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
340 strip = opts["strip"] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
341 quiet = opts["quiet"] and "> /dev/null" or "" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
342 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
343 for patch in patches: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
344 ui.status("applying %s\n" % patch) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
345 pf = os.path.join(d, patch) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
346 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
347 text = "" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
348 for l in file(pf): |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
349 if l[:4] == "--- ": break |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
350 text += l |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
351 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
352 f = os.popen("lsdiff --strip %d %s" % (strip, pf)) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
353 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines())) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
354 f.close() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
355 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
356 if files: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
357 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)): |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
358 raise "patch failed!" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
359 repo.commit(files, text) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
360 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
361 def pull(ui, repo, source): |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
362 """pull changes from the specified source""" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
363 paths = {} |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
364 try: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
365 pf = os.path.expanduser("~/.hgpaths") |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
366 for l in file(pf): |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
367 name, path = l.split() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
368 paths[name] = path |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
369 except IOError: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
370 pass |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
371 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
372 if source in paths: source = paths[source] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
373 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
374 other = hg.repository(ui, source) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
375 cg = repo.getchangegroup(other) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
376 repo.addchangegroup(cg) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
377 |
266
4af7677de4a9
Fix argument processing for patch and rawcommit
mpm@selenic.com
parents:
264
diff
changeset
|
378 def rawcommit(ui, repo, files, **rc): |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
379 "raw commit interface" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
380 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
381 text = rc['text'] |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
382 if not text and rc['logfile']: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
383 try: text = open(rc['logfile']).read() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
384 except IOError: pass |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
385 if not text and not rc['logfile']: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
386 print "missing commit text" |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
387 return 1 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
388 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
389 files = relpath(repo, files) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
390 if rc['files']: |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
391 files += open(rc['files']).read().splitlines() |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
392 |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
393 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent']) |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
394 |
245 | 395 def recover(ui, repo): |
255 | 396 """roll back an interrupted transaction""" |
245 | 397 repo.recover() |
398 | |
399 def remove(ui, repo, file, *files): | |
400 """remove the specified files on the next commit""" | |
401 repo.remove(relpath(repo, (file,) + files)) | |
402 | |
403 def serve(ui, repo, **opts): | |
255 | 404 """export the repository via HTTP""" |
245 | 405 hgweb.server(repo.root, opts["name"], opts["templates"], |
406 opts["address"], opts["port"]) | |
407 | |
213 | 408 def status(ui, repo): |
409 '''show changed files in the working directory | |
410 | |
245 | 411 C = changed |
412 A = added | |
413 R = removed | |
414 ? = not tracked''' | |
415 | |
230 | 416 (c, a, d, u) = repo.diffdir(repo.root) |
220 | 417 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u)) |
213 | 418 |
419 for f in c: print "C", f | |
220 | 420 for f in a: print "A", f |
213 | 421 for f in d: print "R", f |
220 | 422 for f in u: print "?", f |
213 | 423 |
248 | 424 def tags(ui, repo): |
255 | 425 """list repository tags""" |
248 | 426 repo.lookup(0) # prime the cache |
427 i = repo.tags.items() | |
257 | 428 n = [] |
429 for e in i: | |
430 try: | |
431 l = repo.changelog.rev(e[1]) | |
432 except KeyError: | |
433 l = -2 | |
434 n.append((l, e)) | |
435 | |
436 n.sort() | |
437 n.reverse() | |
438 i = [ e[1] for e in n ] | |
248 | 439 for k, n in i: |
440 try: | |
441 r = repo.changelog.rev(n) | |
442 except KeyError: | |
443 r = "?" | |
444 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n)) | |
445 | |
245 | 446 def tip(ui, repo): |
255 | 447 """show the tip revision""" |
245 | 448 n = repo.changelog.tip() |
449 t = repo.changelog.rev(n) | |
450 ui.status("%d:%s\n" % (t, hg.hex(n))) | |
451 | |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
452 def undo(ui, repo): |
255 | 453 """undo the last transaction""" |
210 | 454 repo.undo() |
455 | |
275 | 456 def update(ui, repo, node=None, merge=False, clean=False): |
254 | 457 '''update or merge working directory |
458 | |
459 If there are no outstanding changes in the working directory and | |
460 there is a linear relationship between the current version and the | |
461 requested version, the result is the requested version. | |
462 | |
463 Otherwise the result is a merge between the contents of the | |
464 current working directory and the requested version. Files that | |
465 changed between either parent are marked as changed for the next | |
466 commit and a commit must be performed before any further updates | |
467 are allowed. | |
468 ''' | |
469 node = node and repo.lookup(node) or repo.changelog.tip() | |
275 | 470 return repo.update(node, allow=merge, force=clean) |
254 | 471 |
247 | 472 def verify(ui, repo): |
473 """verify the integrity of the repository""" | |
474 return repo.verify() | |
475 | |
255 | 476 # Command options and aliases are listed here, alphabetically |
477 | |
209 | 478 table = { |
245 | 479 "add": (add, [], "hg add [files]"), |
480 "addremove": (addremove, [], "hg addremove"), | |
209 | 481 "ann|annotate": (annotate, |
482 [('r', 'revision', '', 'revision'), | |
483 ('u', 'user', None, 'show user'), | |
484 ('n', 'number', None, 'show revision number'), | |
485 ('c', 'changeset', None, 'show changeset')], | |
486 'hg annotate [-u] [-c] [-n] [-r id] [files]'), | |
245 | 487 "branch|clone": (branch, [], 'hg branch [path]'), |
248 | 488 "cat|dump": (cat, [], 'hg cat <file> [rev]'), |
245 | 489 "commit|ci": (commit, [], 'hg commit [files]'), |
248 | 490 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'), |
491 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'), | |
492 "debugindex": (debugindex, [], 'debugindex <file>'), | |
493 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'), | |
245 | 494 "diff": (diff, [('r', 'rev', [], 'revision')], |
495 'hg diff [-r A] [-r B] [files]'), | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
496 "export": (export, [], "hg export <changeset>"), |
245 | 497 "forget": (forget, [], "hg forget [files]"), |
498 "heads": (heads, [], 'hg heads'), | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
499 "history": (history, [], 'hg history'), |
245 | 500 "help": (help, [], 'hg help [command]'), |
501 "init": (init, [], 'hg init'), | |
502 "log": (log, [], 'hg log <file>'), | |
248 | 503 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'), |
227 | 504 "parents": (parents, [], 'hg parents [node]'), |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
505 "patch|import": (patch, |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
506 [('p', 'strip', 1, 'path strip'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
507 ('b', 'base', "", 'base path'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
508 ('q', 'quiet', "", 'silence diff')], |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
509 "hg import [options] patches"), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
510 "pull|merge": (pull, [], 'hg pull [source]'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
511 "rawcommit": (rawcommit, |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
512 [('p', 'parent', [], 'parent'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
513 ('d', 'date', "", 'data'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
514 ('u', 'user', "", 'user'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
515 ('F', 'files', "", 'file list'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
516 ('t', 'text', "", 'commit text'), |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
517 ('l', 'logfile', "", 'commit text file')], |
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
518 'hg rawcommit [options] [files]'), |
245 | 519 "recover": (recover, [], "hg recover"), |
520 "remove": (remove, [], "hg remove [files]"), | |
521 "serve": (serve, [('p', 'port', 8000, 'listen port'), | |
522 ('a', 'address', '', 'interface address'), | |
523 ('n', 'name', os.getcwd(), 'repository name'), | |
524 ('t', 'templates', "", 'template map')], | |
525 "hg serve [options]"), | |
213 | 526 "status": (status, [], 'hg status'), |
248 | 527 "tags": (tags, [], 'hg tags'), |
245 | 528 "tip": (tip, [], 'hg tip'), |
210 | 529 "undo": (undo, [], 'hg undo'), |
275 | 530 "update|up|checkout|co|resolve": (update, |
531 [('m', 'merge', None, | |
532 'allow merging of conflicts'), | |
533 ('C', 'clean', None, | |
534 'overwrite locally modified files')], | |
535 'hg update [options] [node]'), | |
247 | 536 "verify": (verify, [], 'hg verify'), |
209 | 537 } |
538 | |
248 | 539 norepo = "init branch help debugindex debugindexdot" |
209 | 540 |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
541 def find(cmd): |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
542 i = None |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
543 for e in table.keys(): |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
544 if re.match(e + "$", cmd): |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
545 return table[e] |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
546 |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
547 raise UnknownCommand(cmd) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
548 |
214 | 549 class SignalInterrupt(Exception): pass |
550 | |
551 def catchterm(*args): | |
552 raise SignalInterrupt | |
553 | |
249 | 554 def run(): |
555 sys.exit(dispatch(sys.argv[1:])) | |
556 | |
209 | 557 def dispatch(args): |
558 options = {} | |
559 opts = [('v', 'verbose', None, 'verbose'), | |
560 ('d', 'debug', None, 'debug'), | |
561 ('q', 'quiet', None, 'quiet'), | |
562 ('y', 'noninteractive', None, 'run non-interactively'), | |
563 ] | |
564 | |
565 args = fancyopts.fancyopts(args, opts, options, | |
566 'hg [options] <command> [options] [files]') | |
567 | |
568 if not args: | |
569 cmd = "help" | |
570 else: | |
571 cmd, args = args[0], args[1:] | |
572 | |
573 u = ui.ui(options["verbose"], options["debug"], options["quiet"], | |
574 not options["noninteractive"]) | |
575 | |
252 | 576 try: |
577 i = find(cmd) | |
578 except UnknownCommand: | |
268 | 579 u.warn("hg: unknown command '%s'\n" % cmd) |
252 | 580 help(u) |
581 sys.exit(1) | |
209 | 582 |
214 | 583 signal.signal(signal.SIGTERM, catchterm) |
584 | |
209 | 585 cmdoptions = {} |
586 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2]) | |
587 | |
588 if cmd not in norepo.split(): | |
589 repo = hg.repository(ui = u) | |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
590 d = lambda: i[0](u, repo, *args, **cmdoptions) |
209 | 591 else: |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
592 d = lambda: i[0](u, *args, **cmdoptions) |
209 | 593 |
594 try: | |
246
96cde50a746f
Migrate rawcommit, import, export, history, and merge
mpm@selenic.com
parents:
245
diff
changeset
|
595 return d() |
214 | 596 except SignalInterrupt: |
597 u.warn("killed!\n") | |
209 | 598 except KeyboardInterrupt: |
599 u.warn("interrupted!\n") | |
250 | 600 except IOError, inst: |
601 if inst.errno == 32: | |
602 u.warn("broken pipe\n") | |
603 else: | |
604 raise | |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
605 except TypeError, inst: |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
606 # was this an argument error? |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
607 tb = traceback.extract_tb(sys.exc_info()[2]) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
608 if len(tb) > 2: # no |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
609 raise |
275 | 610 raise |
212
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
611 u.warn("%s: invalid arguments\n" % i[0].__name__) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
612 u.warn("syntax: %s\n" % i[2]) |
48398a5353e3
commands: better argument processing, per-command help
mpm@selenic.com
parents:
211
diff
changeset
|
613 sys.exit(-1) |