##// END OF EJS Templates
Migrate rawcommit, import, export, history, and merge...
mpm@selenic.com -
r246:96cde50a default
parent child Browse files
Show More
@@ -1,411 +1,244 b''
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2 #
2 #
3 # mercurial - a minimal scalable distributed SCM
3 # mercurial - a minimal scalable distributed SCM
4 # v0.5b "katje"
4 # v0.5b "katje"
5 #
5 #
6 # Copyright 2005 Matt Mackall <mpm@selenic.com>
6 # Copyright 2005 Matt Mackall <mpm@selenic.com>
7 #
7 #
8 # This software may be used and distributed according to the terms
8 # This software may be used and distributed according to the terms
9 # of the GNU General Public License, incorporated herein by reference.
9 # of the GNU General Public License, incorporated herein by reference.
10
10
11 # the psyco compiler makes commits a bit faster
11 # the psyco compiler makes commits a bit faster
12 # and makes changegroup merge about 20 times slower!
12 # and makes changegroup merge about 20 times slower!
13 # try:
13 # try:
14 # import psyco
14 # import psyco
15 # psyco.full()
15 # psyco.full()
16 # except:
16 # except:
17 # pass
17 # pass
18
18
19 import sys, os, time
19 import sys
20 from mercurial import hg, mdiff, fancyopts, ui, commands
20 from mercurial import hg, mdiff, fancyopts, ui, commands
21
21
22 def filterfiles(list, files):
23 l = [ x for x in list if x in files ]
24
25 for f in files:
26 if f[-1] != os.sep: f += os.sep
27 l += [ x for x in list if x.startswith(f) ]
28 return l
29
30 def diff(files = None, node1 = None, node2 = None):
31 def date(c):
32 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
33
34 if node2:
35 change = repo.changelog.read(node2)
36 mmap2 = repo.manifest.read(change[0])
37 (c, a, d) = repo.diffrevs(node1, node2)
38 def read(f): return repo.file(f).read(mmap2[f])
39 date2 = date(change)
40 else:
41 date2 = time.asctime()
42 if not node1:
43 node1 = repo.dirstate.parents()[0]
44 (c, a, d, u) = repo.diffdir(repo.root, node1)
45 def read(f): return file(os.path.join(repo.root, f)).read()
46
47 change = repo.changelog.read(node1)
48 mmap = repo.manifest.read(change[0])
49 date1 = date(change)
50
51 if files:
52 c, a, d = map(lambda x: filterfiles(x, files), (c, a, d))
53
54 for f in c:
55 to = repo.file(f).read(mmap[f])
56 tn = read(f)
57 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
58 for f in a:
59 to = ""
60 tn = read(f)
61 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
62 for f in d:
63 to = repo.file(f).read(mmap[f])
64 tn = ""
65 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
66
67
68 try:
22 try:
69 sys.exit(commands.dispatch(sys.argv[1:]))
23 sys.exit(commands.dispatch(sys.argv[1:]))
70 except commands.UnknownCommand:
24 except commands.UnknownCommand:
71 # fall through
25 # fall through
72 pass
26 pass
73
27
74 options = {}
28 options = {}
75 opts = [('v', 'verbose', None, 'verbose'),
29 opts = [('v', 'verbose', None, 'verbose'),
76 ('d', 'debug', None, 'debug'),
30 ('d', 'debug', None, 'debug'),
77 ('q', 'quiet', None, 'quiet'),
31 ('q', 'quiet', None, 'quiet'),
78 ('y', 'noninteractive', None, 'run non-interactively'),
32 ('y', 'noninteractive', None, 'run non-interactively'),
79 ]
33 ]
80
34
81 args = fancyopts.fancyopts(sys.argv[1:], opts, options,
35 args = fancyopts.fancyopts(sys.argv[1:], opts, options,
82 'hg [options] <command> [command options] [files]')
36 'hg [options] <command> [command options] [files]')
83
37
84 try:
38 try:
85 cmd = args[0]
39 cmd = args[0]
86 args = args[1:]
40 args = args[1:]
87 except:
41 except:
88 cmd = "help"
42 cmd = "help"
89
43
90 ui = ui.ui(options["verbose"], options["debug"], options["quiet"],
44 ui = ui.ui(options["verbose"], options["debug"], options["quiet"],
91 not options["noninteractive"])
45 not options["noninteractive"])
92
46
93 try:
47 try:
94 repo = hg.repository(ui=ui)
48 repo = hg.repository(ui=ui)
95 except IOError:
49 except IOError:
96 ui.warn("Unable to open repository\n")
50 ui.warn("Unable to open repository\n")
97 sys.exit(0)
51 sys.exit(0)
98
52
99 relpath = None
53 if cmd == "debugchangegroup":
100 if os.getcwd() != repo.root:
101 relpath = os.getcwd()[len(repo.root) + 1: ]
102
103 elif cmd == "rawcommit":
104 "raw commit interface"
105 rc = {}
106 opts = [('p', 'parent', [], 'parent'),
107 ('d', 'date', "", 'data'),
108 ('u', 'user', "", 'user'),
109 ('F', 'files', "", 'file list'),
110 ('t', 'text', "", 'commit text'),
111 ('l', 'logfile', "", 'commit text file')
112 ]
113 args = fancyopts.fancyopts(args, opts, rc,
114 "hg rawcommit [options] files")
115 text = rc['text']
116 if not text and rc['logfile']:
117 try: text = open(rc['logfile']).read()
118 except IOError: pass
119 if not text and not rc['logfile']:
120 print "missing commit text"
121 sys.exit(0)
122 if rc['files']:
123 files = open(rc['files']).read().splitlines()
124 else:
125 files = args
126
127 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
128
129
130 elif cmd == "import" or cmd == "patch":
131 try:
132 import psyco
133 psyco.full()
134 except:
135 pass
136
137 ioptions = {}
138 opts = [('p', 'strip', 1, 'path strip'),
139 ('b', 'base', "", 'base path'),
140 ('q', 'quiet', "", 'silence diff')
141 ]
142
143 args = fancyopts.fancyopts(args, opts, ioptions,
144 'hg import [options] <patch names>')
145 d = ioptions["base"]
146 strip = ioptions["strip"]
147 quiet = ioptions["quiet"] and "> /dev/null" or ""
148
149 for patch in args:
150 ui.status("applying %s\n" % patch)
151 pf = os.path.join(d, patch)
152
153 text = ""
154 for l in file(pf):
155 if l[:4] == "--- ": break
156 text += l
157
158 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
159 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
160 f.close()
161
162 if files:
163 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
164 raise "patch failed!"
165 repo.commit(files, text)
166
167 elif cmd == "export":
168 node = repo.lookup(args[0])
169 prev, other = repo.changelog.parents(node)
170 change = repo.changelog.read(node)
171 print "# HG changeset patch"
172 print "# User %s" % change[1]
173 print "# Node ID %s" % hg.hex(node)
174 print "# Parent %s" % hg.hex(prev)
175 print
176 if other != hg.nullid:
177 print "# Parent %s" % hg.hex(other)
178 print change[4]
179
180 diff(None, prev, node)
181
182 elif cmd == "debugchangegroup":
183 newer = repo.newer(map(repo.lookup, args))
54 newer = repo.newer(map(repo.lookup, args))
184 for chunk in repo.changegroup(newer):
55 for chunk in repo.changegroup(newer):
185 sys.stdout.write(chunk)
56 sys.stdout.write(chunk)
186
57
187 elif cmd == "debugaddchangegroup":
58 elif cmd == "debugaddchangegroup":
188 data = sys.stdin.read()
59 data = sys.stdin.read()
189 repo.addchangegroup(data)
60 repo.addchangegroup(data)
190
61
191 elif cmd == "history":
192 for i in range(repo.changelog.count()):
193 n = repo.changelog.node(i)
194 changes = repo.changelog.read(n)
195 (p1, p2) = repo.changelog.parents(n)
196 (h, h1, h2) = map(hg.hex, (n, p1, p2))
197 (i1, i2) = map(repo.changelog.rev, (p1, p2))
198 print "rev: %4d:%s" % (i, h)
199 print "parents: %4d:%s" % (i1, h1)
200 if i2: print " %4d:%s" % (i2, h2)
201 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
202 hg.hex(changes[0]))
203 print "user:", changes[1]
204 print "date:", time.asctime(
205 time.localtime(float(changes[2].split(' ')[0])))
206 if ui.verbose: print "files:", " ".join(changes[3])
207 print "description:"
208 print changes[4]
209
210 elif cmd == "dump":
62 elif cmd == "dump":
211 if args:
63 if args:
212 r = repo.file(args[0])
64 r = repo.file(args[0])
213 n = r.tip()
65 n = r.tip()
214 if len(args) > 1: n = r.lookup(args[1])
66 if len(args) > 1: n = r.lookup(args[1])
215 sys.stdout.write(r.read(n))
67 sys.stdout.write(r.read(n))
216 else:
68 else:
217 print "missing filename"
69 print "missing filename"
218
70
219 elif cmd == "dumpmanifest":
71 elif cmd == "dumpmanifest":
220 n = repo.manifest.tip()
72 n = repo.manifest.tip()
221 if len(args) > 0:
73 if len(args) > 0:
222 n = repo.manifest.lookup(args[0])
74 n = repo.manifest.lookup(args[0])
223 m = repo.manifest.read(n)
75 m = repo.manifest.read(n)
224 files = m.keys()
76 files = m.keys()
225 files.sort()
77 files.sort()
226
78
227 for f in files:
79 for f in files:
228 print hg.hex(m[f]), f
80 print hg.hex(m[f]), f
229
81
230 elif cmd == "debugindex":
82 elif cmd == "debugindex":
231 if ".hg" not in args[0]:
83 if ".hg" not in args[0]:
232 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
84 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
233
85
234 r = hg.revlog(open, args[0], "")
86 r = hg.revlog(open, args[0], "")
235 print " rev offset length base linkrev"+\
87 print " rev offset length base linkrev"+\
236 " p1 p2 nodeid"
88 " p1 p2 nodeid"
237 for i in range(r.count()):
89 for i in range(r.count()):
238 e = r.index[i]
90 e = r.index[i]
239 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
91 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
240 i, e[0], e[1], e[2], e[3],
92 i, e[0], e[1], e[2], e[3],
241 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
93 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
242
94
243 elif cmd == "debugindexdot":
95 elif cmd == "debugindexdot":
244 if ".hg" not in args[0]:
96 if ".hg" not in args[0]:
245 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
97 args[0] = ".hg/data/" + repo.file(args[0]).encodepath(args[0]) + "i"
246
98
247 r = hg.revlog(open, args[0], "")
99 r = hg.revlog(open, args[0], "")
248 print "digraph G {"
100 print "digraph G {"
249 for i in range(r.count()):
101 for i in range(r.count()):
250 e = r.index[i]
102 e = r.index[i]
251 print "\t%d -> %d" % (r.rev(e[4]), i)
103 print "\t%d -> %d" % (r.rev(e[4]), i)
252 if e[5] != hg.nullid:
104 if e[5] != hg.nullid:
253 print "\t%d -> %d" % (r.rev(e[5]), i)
105 print "\t%d -> %d" % (r.rev(e[5]), i)
254 print "}"
106 print "}"
255
107
256 elif cmd == "merge":
257 if args:
258 paths = {}
259 try:
260 pf = os.path.join(os.environ["HOME"], ".hgpaths")
261 for l in file(pf):
262 name, path = l.split()
263 paths[name] = path
264 except:
265 pass
266
267 if args[0] in paths: args[0] = paths[args[0]]
268
269 other = hg.repository(ui, args[0])
270 cg = repo.getchangegroup(other)
271 repo.addchangegroup(cg)
272 else:
273 print "missing source repository"
274
275 elif cmd == "tags":
108 elif cmd == "tags":
276 repo.lookup(0) # prime the cache
109 repo.lookup(0) # prime the cache
277 i = repo.tags.items()
110 i = repo.tags.items()
278 i.sort()
111 i.sort()
279 for k, n in i:
112 for k, n in i:
280 try:
113 try:
281 r = repo.changelog.rev(n)
114 r = repo.changelog.rev(n)
282 except KeyError:
115 except KeyError:
283 r = "?"
116 r = "?"
284 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
117 print "%-30s %5d:%s" % (k, repo.changelog.rev(n), hg.hex(n))
285
118
286 elif cmd == "verify":
119 elif cmd == "verify":
287 filelinkrevs = {}
120 filelinkrevs = {}
288 filenodes = {}
121 filenodes = {}
289 manifestchangeset = {}
122 manifestchangeset = {}
290 changesets = revisions = files = 0
123 changesets = revisions = files = 0
291 errors = 0
124 errors = 0
292
125
293 ui.status("checking changesets\n")
126 ui.status("checking changesets\n")
294 for i in range(repo.changelog.count()):
127 for i in range(repo.changelog.count()):
295 changesets += 1
128 changesets += 1
296 n = repo.changelog.node(i)
129 n = repo.changelog.node(i)
297 for p in repo.changelog.parents(n):
130 for p in repo.changelog.parents(n):
298 if p not in repo.changelog.nodemap:
131 if p not in repo.changelog.nodemap:
299 ui.warn("changeset %s has unknown parent %s\n" %
132 ui.warn("changeset %s has unknown parent %s\n" %
300 (hg.short(n), hg.short(p)))
133 (hg.short(n), hg.short(p)))
301 errors += 1
134 errors += 1
302 try:
135 try:
303 changes = repo.changelog.read(n)
136 changes = repo.changelog.read(n)
304 except Exception, inst:
137 except Exception, inst:
305 ui.warn("unpacking changeset %s: %s\n" % (short(n), inst))
138 ui.warn("unpacking changeset %s: %s\n" % (short(n), inst))
306 errors += 1
139 errors += 1
307
140
308 manifestchangeset[changes[0]] = n
141 manifestchangeset[changes[0]] = n
309 for f in changes[3]:
142 for f in changes[3]:
310 filelinkrevs.setdefault(f, []).append(i)
143 filelinkrevs.setdefault(f, []).append(i)
311
144
312 ui.status("checking manifests\n")
145 ui.status("checking manifests\n")
313 for i in range(repo.manifest.count()):
146 for i in range(repo.manifest.count()):
314 n = repo.manifest.node(i)
147 n = repo.manifest.node(i)
315 for p in repo.manifest.parents(n):
148 for p in repo.manifest.parents(n):
316 if p not in repo.manifest.nodemap:
149 if p not in repo.manifest.nodemap:
317 ui.warn("manifest %s has unknown parent %s\n" %
150 ui.warn("manifest %s has unknown parent %s\n" %
318 (hg.short(n), hg.short(p)))
151 (hg.short(n), hg.short(p)))
319 errors += 1
152 errors += 1
320 ca = repo.changelog.node(repo.manifest.linkrev(n))
153 ca = repo.changelog.node(repo.manifest.linkrev(n))
321 cc = manifestchangeset[n]
154 cc = manifestchangeset[n]
322 if ca != cc:
155 if ca != cc:
323 ui.warn("manifest %s points to %s, not %s\n" %
156 ui.warn("manifest %s points to %s, not %s\n" %
324 (hg.hex(n), hg.hex(ca), hg.hex(cc)))
157 (hg.hex(n), hg.hex(ca), hg.hex(cc)))
325 errors += 1
158 errors += 1
326
159
327 try:
160 try:
328 delta = mdiff.patchtext(repo.manifest.delta(n))
161 delta = mdiff.patchtext(repo.manifest.delta(n))
329 except KeyboardInterrupt:
162 except KeyboardInterrupt:
330 print "aborted"
163 print "aborted"
331 sys.exit(0)
164 sys.exit(0)
332 except Exception, inst:
165 except Exception, inst:
333 ui.warn("unpacking manifest %s: %s\n" % (hg.short(n), inst))
166 ui.warn("unpacking manifest %s: %s\n" % (hg.short(n), inst))
334 errors += 1
167 errors += 1
335
168
336 ff = [ l.split('\0') for l in delta.splitlines() ]
169 ff = [ l.split('\0') for l in delta.splitlines() ]
337 for f, fn in ff:
170 for f, fn in ff:
338 filenodes.setdefault(f, {})[hg.bin(fn)] = 1
171 filenodes.setdefault(f, {})[hg.bin(fn)] = 1
339
172
340 ui.status("crosschecking files in changesets and manifests\n")
173 ui.status("crosschecking files in changesets and manifests\n")
341 for f in filenodes:
174 for f in filenodes:
342 if f not in filelinkrevs:
175 if f not in filelinkrevs:
343 ui.warn("file %s in manifest but not in changesets\n" % f)
176 ui.warn("file %s in manifest but not in changesets\n" % f)
344 errors += 1
177 errors += 1
345
178
346 for f in filelinkrevs:
179 for f in filelinkrevs:
347 if f not in filenodes:
180 if f not in filenodes:
348 ui.warn("file %s in changeset but not in manifest\n" % f)
181 ui.warn("file %s in changeset but not in manifest\n" % f)
349 errors += 1
182 errors += 1
350
183
351 ui.status("checking files\n")
184 ui.status("checking files\n")
352 ff = filenodes.keys()
185 ff = filenodes.keys()
353 ff.sort()
186 ff.sort()
354 for f in ff:
187 for f in ff:
355 if f == "/dev/null": continue
188 if f == "/dev/null": continue
356 files += 1
189 files += 1
357 fl = repo.file(f)
190 fl = repo.file(f)
358 nodes = { hg.nullid: 1 }
191 nodes = { hg.nullid: 1 }
359 for i in range(fl.count()):
192 for i in range(fl.count()):
360 revisions += 1
193 revisions += 1
361 n = fl.node(i)
194 n = fl.node(i)
362
195
363 if n not in filenodes[f]:
196 if n not in filenodes[f]:
364 ui.warn("%s: %d:%s not in manifests\n" % (f, i, hg.short(n)))
197 ui.warn("%s: %d:%s not in manifests\n" % (f, i, hg.short(n)))
365 print len(filenodes[f].keys()), fl.count(), f
198 print len(filenodes[f].keys()), fl.count(), f
366 errors += 1
199 errors += 1
367 else:
200 else:
368 del filenodes[f][n]
201 del filenodes[f][n]
369
202
370 flr = fl.linkrev(n)
203 flr = fl.linkrev(n)
371 if flr not in filelinkrevs[f]:
204 if flr not in filelinkrevs[f]:
372 ui.warn("%s:%s points to unexpected changeset rev %d\n"
205 ui.warn("%s:%s points to unexpected changeset rev %d\n"
373 % (f, hg.short(n), fl.linkrev(n)))
206 % (f, hg.short(n), fl.linkrev(n)))
374 errors += 1
207 errors += 1
375 else:
208 else:
376 filelinkrevs[f].remove(flr)
209 filelinkrevs[f].remove(flr)
377
210
378 # verify contents
211 # verify contents
379 try:
212 try:
380 t = fl.read(n)
213 t = fl.read(n)
381 except Exception, inst:
214 except Exception, inst:
382 ui.warn("unpacking file %s %s: %s\n" % (f, hg.short(n), inst))
215 ui.warn("unpacking file %s %s: %s\n" % (f, hg.short(n), inst))
383 errors += 1
216 errors += 1
384
217
385 # verify parents
218 # verify parents
386 (p1, p2) = fl.parents(n)
219 (p1, p2) = fl.parents(n)
387 if p1 not in nodes:
220 if p1 not in nodes:
388 ui.warn("file %s:%s unknown parent 1 %s" %
221 ui.warn("file %s:%s unknown parent 1 %s" %
389 (f, hg.short(n), hg.short(p1)))
222 (f, hg.short(n), hg.short(p1)))
390 errors += 1
223 errors += 1
391 if p2 not in nodes:
224 if p2 not in nodes:
392 ui.warn("file %s:%s unknown parent 2 %s" %
225 ui.warn("file %s:%s unknown parent 2 %s" %
393 (f, hg.short(n), hg.short(p1)))
226 (f, hg.short(n), hg.short(p1)))
394 errors += 1
227 errors += 1
395 nodes[n] = 1
228 nodes[n] = 1
396
229
397 # cross-check
230 # cross-check
398 for node in filenodes[f]:
231 for node in filenodes[f]:
399 ui.warn("node %s in manifests not in %s\n" % (hg.hex(n), f))
232 ui.warn("node %s in manifests not in %s\n" % (hg.hex(n), f))
400 errors += 1
233 errors += 1
401
234
402 ui.status("%d files, %d changesets, %d total revisions\n" %
235 ui.status("%d files, %d changesets, %d total revisions\n" %
403 (files, changesets, revisions))
236 (files, changesets, revisions))
404
237
405 if errors:
238 if errors:
406 ui.warn("%d integrity errors encountered!\n" % errors)
239 ui.warn("%d integrity errors encountered!\n" % errors)
407 sys.exit(1)
240 sys.exit(1)
408
241
409 else:
242 else:
410 if cmd: ui.warn("unknown command\n\n")
243 if cmd: ui.warn("unknown command\n\n")
411 sys.exit(1)
244 sys.exit(1)
@@ -1,386 +1,502 b''
1 import os, re, traceback, sys, signal, time, mdiff
1 import os, re, traceback, sys, signal, time, mdiff
2 from mercurial import fancyopts, ui, hg
2 from mercurial import fancyopts, ui, hg
3
3
4 class UnknownCommand(Exception): pass
4 class UnknownCommand(Exception): pass
5
5
6 def filterfiles(filters, files):
6 def filterfiles(filters, files):
7 l = [ x for x in files if x in filters ]
7 l = [ x for x in files if x in filters ]
8
8
9 for t in filters:
9 for t in filters:
10 if t and t[-1] != os.sep: t += os.sep
10 if t and t[-1] != os.sep: t += os.sep
11 l += [ x for x in files if x.startswith(t) ]
11 l += [ x for x in files if x.startswith(t) ]
12 return l
12 return l
13
13
14 def relfilter(repo, files):
14 def relfilter(repo, files):
15 if os.getcwd() != repo.root:
15 if os.getcwd() != repo.root:
16 p = os.getcwd()[len(repo.root) + 1: ]
16 p = os.getcwd()[len(repo.root) + 1: ]
17 return filterfiles(p, files)
17 return filterfiles(p, files)
18 return files
18 return files
19
19
20 def relpath(repo, args):
20 def relpath(repo, args):
21 if os.getcwd() != repo.root:
21 if os.getcwd() != repo.root:
22 p = os.getcwd()[len(repo.root) + 1: ]
22 p = os.getcwd()[len(repo.root) + 1: ]
23 return [ os.path.normpath(os.path.join(p, x)) for x in args ]
23 return [ os.path.normpath(os.path.join(p, x)) for x in args ]
24 return args
24 return args
25
25
26 def dodiff(repo, files = None, node1 = None, node2 = None):
26 def dodiff(repo, files = None, node1 = None, node2 = None):
27 def date(c):
27 def date(c):
28 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
28 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
29
29
30 if node2:
30 if node2:
31 change = repo.changelog.read(node2)
31 change = repo.changelog.read(node2)
32 mmap2 = repo.manifest.read(change[0])
32 mmap2 = repo.manifest.read(change[0])
33 (c, a, d) = repo.diffrevs(node1, node2)
33 (c, a, d) = repo.diffrevs(node1, node2)
34 def read(f): return repo.file(f).read(mmap2[f])
34 def read(f): return repo.file(f).read(mmap2[f])
35 date2 = date(change)
35 date2 = date(change)
36 else:
36 else:
37 date2 = time.asctime()
37 date2 = time.asctime()
38 (c, a, d, u) = repo.diffdir(repo.root, node1)
38 (c, a, d, u) = repo.diffdir(repo.root, node1)
39 if not node1:
39 if not node1:
40 node1 = repo.dirstate.parents()[0]
40 node1 = repo.dirstate.parents()[0]
41 def read(f): return file(os.path.join(repo.root, f)).read()
41 def read(f): return file(os.path.join(repo.root, f)).read()
42
42
43 change = repo.changelog.read(node1)
43 change = repo.changelog.read(node1)
44 mmap = repo.manifest.read(change[0])
44 mmap = repo.manifest.read(change[0])
45 date1 = date(change)
45 date1 = date(change)
46
46
47 if files:
47 if files:
48 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
48 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
49
49
50 for f in c:
50 for f in c:
51 to = repo.file(f).read(mmap[f])
51 to = repo.file(f).read(mmap[f])
52 tn = read(f)
52 tn = read(f)
53 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
53 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
54 for f in a:
54 for f in a:
55 to = ""
55 to = ""
56 tn = read(f)
56 tn = read(f)
57 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
57 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
58 for f in d:
58 for f in d:
59 to = repo.file(f).read(mmap[f])
59 to = repo.file(f).read(mmap[f])
60 tn = ""
60 tn = ""
61 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
61 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f))
62
62
63 def help(ui, cmd=None):
63 def help(ui, cmd=None):
64 '''show help'''
64 '''show help'''
65 if cmd:
65 if cmd:
66 try:
66 try:
67 i = find(cmd)
67 i = find(cmd)
68 ui.write("%s\n\n" % i[2])
68 ui.write("%s\n\n" % i[2])
69 ui.write(i[0].__doc__, "\n")
69 ui.write(i[0].__doc__, "\n")
70 except UnknownCommand:
70 except UnknownCommand:
71 ui.warn("unknown command %s", cmd)
71 ui.warn("unknown command %s", cmd)
72 sys.exit(0)
72 sys.exit(0)
73
73
74 ui.status("""\
74 ui.status("""\
75 hg commands:
75 hg commands:
76
76
77 add [files...] add the given files in the next commit
77 add [files...] add the given files in the next commit
78 addremove add all new files, delete all missing files
78 addremove add all new files, delete all missing files
79 annotate [files...] show changeset number per file line
79 annotate [files...] show changeset number per file line
80 branch <path> create a branch of <path> in this directory
80 branch <path> create a branch of <path> in this directory
81 checkout [changeset] checkout the latest or given changeset
81 checkout [changeset] checkout the latest or given changeset
82 commit commit all changes to the repository
82 commit commit all changes to the repository
83 diff [files...] diff working directory (or selected files)
83 diff [files...] diff working directory (or selected files)
84 dump <file> [rev] dump the latest or given revision of a file
84 dump <file> [rev] dump the latest or given revision of a file
85 dumpmanifest [rev] dump the latest or given revision of the manifest
85 dumpmanifest [rev] dump the latest or given revision of the manifest
86 export <rev> dump the changeset header and diffs for a revision
86 export <rev> dump the changeset header and diffs for a revision
87 history show changeset history
87 history show changeset history
88 init create a new repository in this directory
88 init create a new repository in this directory
89 log <file> show revision history of a single file
89 log <file> show revision history of a single file
90 merge <path> merge changes from <path> into local repository
90 merge <path> merge changes from <path> into local repository
91 recover rollback an interrupted transaction
91 recover rollback an interrupted transaction
92 remove [files...] remove the given files in the next commit
92 remove [files...] remove the given files in the next commit
93 serve export the repository via HTTP
93 serve export the repository via HTTP
94 status show new, missing, and changed files in working dir
94 status show new, missing, and changed files in working dir
95 tags show current changeset tags
95 tags show current changeset tags
96 undo undo the last transaction
96 undo undo the last transaction
97 """)
97 """)
98
98
99 def add(ui, repo, file, *files):
99 def add(ui, repo, file, *files):
100 '''add the specified files on the next commit'''
100 '''add the specified files on the next commit'''
101 repo.add(relpath(repo, (file,) + files))
101 repo.add(relpath(repo, (file,) + files))
102
102
103 def addremove(ui, repo):
103 def addremove(ui, repo):
104 (c, a, d, u) = repo.diffdir(repo.root)
104 (c, a, d, u) = repo.diffdir(repo.root)
105 repo.add(a)
105 repo.add(a)
106 repo.remove(d)
106 repo.remove(d)
107
107
108 def annotate(u, repo, file, *files, **ops):
108 def annotate(u, repo, file, *files, **ops):
109 def getnode(rev):
109 def getnode(rev):
110 return hg.short(repo.changelog.node(rev))
110 return hg.short(repo.changelog.node(rev))
111
111
112 def getname(rev):
112 def getname(rev):
113 try:
113 try:
114 return bcache[rev]
114 return bcache[rev]
115 except KeyError:
115 except KeyError:
116 cl = repo.changelog.read(repo.changelog.node(rev))
116 cl = repo.changelog.read(repo.changelog.node(rev))
117 name = cl[1]
117 name = cl[1]
118 f = name.find('@')
118 f = name.find('@')
119 if f >= 0:
119 if f >= 0:
120 name = name[:f]
120 name = name[:f]
121 bcache[rev] = name
121 bcache[rev] = name
122 return name
122 return name
123
123
124 bcache = {}
124 bcache = {}
125 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
125 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
126 if not ops['user'] and not ops['changeset']:
126 if not ops['user'] and not ops['changeset']:
127 ops['number'] = 1
127 ops['number'] = 1
128
128
129 node = repo.dirstate.parents()[0]
129 node = repo.dirstate.parents()[0]
130 if ops['revision']:
130 if ops['revision']:
131 node = repo.changelog.lookup(ops['revision'])
131 node = repo.changelog.lookup(ops['revision'])
132 change = repo.changelog.read(node)
132 change = repo.changelog.read(node)
133 mmap = repo.manifest.read(change[0])
133 mmap = repo.manifest.read(change[0])
134 maxuserlen = 0
134 maxuserlen = 0
135 maxchangelen = 0
135 maxchangelen = 0
136 for f in relpath(repo, (file,) + files):
136 for f in relpath(repo, (file,) + files):
137 lines = repo.file(f).annotate(mmap[f])
137 lines = repo.file(f).annotate(mmap[f])
138 pieces = []
138 pieces = []
139
139
140 for o, f in opmap:
140 for o, f in opmap:
141 if ops[o]:
141 if ops[o]:
142 l = [ f(n) for n,t in lines ]
142 l = [ f(n) for n,t in lines ]
143 m = max(map(len, l))
143 m = max(map(len, l))
144 pieces.append([ "%*s" % (m, x) for x in l])
144 pieces.append([ "%*s" % (m, x) for x in l])
145
145
146 for p,l in zip(zip(*pieces), lines):
146 for p,l in zip(zip(*pieces), lines):
147 u.write(" ".join(p) + ": " + l[1])
147 u.write(" ".join(p) + ": " + l[1])
148
148
149 def branch(ui, path):
149 def branch(ui, path):
150 '''branch from a local repository'''
150 '''branch from a local repository'''
151 # this should eventually support remote repos
151 # this should eventually support remote repos
152 os.system("cp -al %s/.hg .hg" % path)
152 os.system("cp -al %s/.hg .hg" % path)
153
153
154 def checkout(ui, repo, changeset=None):
154 def checkout(ui, repo, changeset=None):
155 '''checkout a given changeset or the current tip'''
155 '''checkout a given changeset or the current tip'''
156 (c, a, d, u) = repo.diffdir(repo.root)
156 (c, a, d, u) = repo.diffdir(repo.root)
157 if c or a or d:
157 if c or a or d:
158 ui.warn("aborting (outstanding changes in working directory)\n")
158 ui.warn("aborting (outstanding changes in working directory)\n")
159 sys.exit(1)
159 sys.exit(1)
160
160
161 node = repo.changelog.tip()
161 node = repo.changelog.tip()
162 if changeset:
162 if changeset:
163 node = repo.lookup(changeset)
163 node = repo.lookup(changeset)
164 repo.checkout(node)
164 repo.checkout(node)
165
165
166 def commit(ui, repo, *files):
166 def commit(ui, repo, *files):
167 """commit the specified files or all outstanding changes"""
167 """commit the specified files or all outstanding changes"""
168 repo.commit(relpath(repo, files))
168 repo.commit(relpath(repo, files))
169
169
170 def diff(ui, repo, *files, **opts):
170 def diff(ui, repo, *files, **opts):
171 revs = []
171 revs = []
172 if opts['rev']:
172 if opts['rev']:
173 revs = map(lambda x: repo.lookup(x), opts['rev'])
173 revs = map(lambda x: repo.lookup(x), opts['rev'])
174
174
175 if len(revs) > 2:
175 if len(revs) > 2:
176 self.ui.warn("too many revisions to diff\n")
176 self.ui.warn("too many revisions to diff\n")
177 sys.exit(1)
177 sys.exit(1)
178
178
179 if files:
179 if files:
180 files = relpath(repo, files)
180 files = relpath(repo, files)
181 else:
181 else:
182 files = relpath(repo, [""])
182 files = relpath(repo, [""])
183
183
184 dodiff(repo, files, *revs)
184 dodiff(repo, files, *revs)
185
185
186 def export(ui, repo, changeset):
187 node = repo.lookup(changeset)
188 prev, other = repo.changelog.parents(node)
189 change = repo.changelog.read(node)
190 print "# HG changeset patch"
191 print "# User %s" % change[1]
192 print "# Node ID %s" % hg.hex(node)
193 print "# Parent %s" % hg.hex(prev)
194 print
195 if other != hg.nullid:
196 print "# Parent %s" % hg.hex(other)
197 print change[4].rstrip()
198 print
199
200 dodiff(repo, None, prev, node)
201
186 def forget(ui, repo, file, *files):
202 def forget(ui, repo, file, *files):
187 """don't add the specified files on the next commit"""
203 """don't add the specified files on the next commit"""
188 repo.forget(relpath(repo, (file,) + files))
204 repo.forget(relpath(repo, (file,) + files))
189
205
190 def heads(ui, repo):
206 def heads(ui, repo):
191 '''show current repository heads'''
207 '''show current repository heads'''
192 for n in repo.changelog.heads():
208 for n in repo.changelog.heads():
193 i = repo.changelog.rev(n)
209 i = repo.changelog.rev(n)
194 changes = repo.changelog.read(n)
210 changes = repo.changelog.read(n)
195 (p1, p2) = repo.changelog.parents(n)
211 (p1, p2) = repo.changelog.parents(n)
196 (h, h1, h2) = map(hg.hex, (n, p1, p2))
212 (h, h1, h2) = map(hg.hex, (n, p1, p2))
197 (i1, i2) = map(repo.changelog.rev, (p1, p2))
213 (i1, i2) = map(repo.changelog.rev, (p1, p2))
198 print "rev: %4d:%s" % (i, h)
214 print "rev: %4d:%s" % (i, h)
199 print "parents: %4d:%s" % (i1, h1)
215 print "parents: %4d:%s" % (i1, h1)
200 if i2: print " %4d:%s" % (i2, h2)
216 if i2: print " %4d:%s" % (i2, h2)
201 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
217 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
202 hg.hex(changes[0]))
218 hg.hex(changes[0]))
203 print "user:", changes[1]
219 print "user:", changes[1]
204 print "date:", time.asctime(
220 print "date:", time.asctime(
205 time.localtime(float(changes[2].split(' ')[0])))
221 time.localtime(float(changes[2].split(' ')[0])))
206 if ui.verbose: print "files:", " ".join(changes[3])
222 if ui.verbose: print "files:", " ".join(changes[3])
207 print "description:"
223 print "description:"
208 print changes[4]
224 print changes[4]
209
225
226 def history(ui, repo):
227 """show the changelog history"""
228 for i in range(repo.changelog.count()):
229 n = repo.changelog.node(i)
230 changes = repo.changelog.read(n)
231 (p1, p2) = repo.changelog.parents(n)
232 (h, h1, h2) = map(hg.hex, (n, p1, p2))
233 (i1, i2) = map(repo.changelog.rev, (p1, p2))
234 print "rev: %4d:%s" % (i, h)
235 print "parents: %4d:%s" % (i1, h1)
236 if i2: print " %4d:%s" % (i2, h2)
237 print "manifest: %4d:%s" % (repo.manifest.rev(changes[0]),
238 hg.hex(changes[0]))
239 print "user:", changes[1]
240 print "date:", time.asctime(
241 time.localtime(float(changes[2].split(' ')[0])))
242 if ui.verbose: print "files:", " ".join(changes[3])
243 print "description:"
244 print changes[4]
245
246 def patch(ui, repo, patches, opts):
247 """import an ordered set of patches"""
248 try:
249 import psyco
250 psyco.full()
251 except:
252 pass
253
254 d = opts["base"]
255 strip = opts["strip"]
256 quiet = opts["quiet"] and "> /dev/null" or ""
257
258 for patch in patches:
259 ui.status("applying %s\n" % patch)
260 pf = os.path.join(d, patch)
261
262 text = ""
263 for l in file(pf):
264 if l[:4] == "--- ": break
265 text += l
266
267 f = os.popen("lsdiff --strip %d %s" % (strip, pf))
268 files = filter(None, map(lambda x: x.rstrip(), f.read().splitlines()))
269 f.close()
270
271 if files:
272 if os.system("patch -p%d < %s %s" % (strip, pf, quiet)):
273 raise "patch failed!"
274 repo.commit(files, text)
275
210 def init(ui):
276 def init(ui):
211 """create a repository"""
277 """create a repository"""
212 hg.repository(ui, ".", create=1)
278 hg.repository(ui, ".", create=1)
213
279
214 def log(ui, repo, f):
280 def log(ui, repo, f):
215 f = relpath(repo, [f])[0]
281 f = relpath(repo, [f])[0]
216
282
217 r = repo.file(f)
283 r = repo.file(f)
218 for i in range(r.count()):
284 for i in range(r.count()):
219 n = r.node(i)
285 n = r.node(i)
220 (p1, p2) = r.parents(n)
286 (p1, p2) = r.parents(n)
221 (h, h1, h2) = map(hg.hex, (n, p1, p2))
287 (h, h1, h2) = map(hg.hex, (n, p1, p2))
222 (i1, i2) = map(r.rev, (p1, p2))
288 (i1, i2) = map(r.rev, (p1, p2))
223 cr = r.linkrev(n)
289 cr = r.linkrev(n)
224 cn = hg.hex(repo.changelog.node(cr))
290 cn = hg.hex(repo.changelog.node(cr))
225 print "rev: %4d:%s" % (i, h)
291 print "rev: %4d:%s" % (i, h)
226 print "changeset: %4d:%s" % (cr, cn)
292 print "changeset: %4d:%s" % (cr, cn)
227 print "parents: %4d:%s" % (i1, h1)
293 print "parents: %4d:%s" % (i1, h1)
228 if i2: print " %4d:%s" % (i2, h2)
294 if i2: print " %4d:%s" % (i2, h2)
229 changes = repo.changelog.read(repo.changelog.node(cr))
295 changes = repo.changelog.read(repo.changelog.node(cr))
230 print "user: %s" % changes[1]
296 print "user: %s" % changes[1]
231 print "date: %s" % time.asctime(
297 print "date: %s" % time.asctime(
232 time.localtime(float(changes[2].split(' ')[0])))
298 time.localtime(float(changes[2].split(' ')[0])))
233 print "description:"
299 print "description:"
234 print changes[4].rstrip()
300 print changes[4].rstrip()
235 print
301 print
236
302
237 def parents(ui, repo, node = None):
303 def parents(ui, repo, node = None):
238 '''show the parents of the current working dir'''
304 '''show the parents of the current working dir'''
239 if node:
305 if node:
240 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
306 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
241 else:
307 else:
242 p = repo.dirstate.parents()
308 p = repo.dirstate.parents()
243
309
244 for n in p:
310 for n in p:
245 if n != hg.nullid:
311 if n != hg.nullid:
246 ui.write("%d:%s\n" % (repo.changelog.rev(n), hg.hex(n)))
312 ui.write("%d:%s\n" % (repo.changelog.rev(n), hg.hex(n)))
247
313
314 def pull(ui, repo, source):
315 """pull changes from the specified source"""
316 paths = {}
317 try:
318 pf = os.path.expanduser("~/.hgpaths")
319 for l in file(pf):
320 name, path = l.split()
321 paths[name] = path
322 except IOError:
323 pass
324
325 if source in paths: source = paths[source]
326
327 other = hg.repository(ui, source)
328 cg = repo.getchangegroup(other)
329 repo.addchangegroup(cg)
330
331 def rawcommit(ui, repo, files, rc):
332 "raw commit interface"
333
334 text = rc['text']
335 if not text and rc['logfile']:
336 try: text = open(rc['logfile']).read()
337 except IOError: pass
338 if not text and not rc['logfile']:
339 print "missing commit text"
340 return 1
341
342 files = relpath(repo, files)
343 if rc['files']:
344 files += open(rc['files']).read().splitlines()
345
346 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
347
248 def recover(ui, repo):
348 def recover(ui, repo):
249 repo.recover()
349 repo.recover()
250
350
251 def remove(ui, repo, file, *files):
351 def remove(ui, repo, file, *files):
252 """remove the specified files on the next commit"""
352 """remove the specified files on the next commit"""
253 repo.remove(relpath(repo, (file,) + files))
353 repo.remove(relpath(repo, (file,) + files))
254
354
255 def resolve(ui, repo, node=None):
355 def resolve(ui, repo, node=None):
256 '''merge a given node or the current tip into the working dir'''
356 '''merge a given node or the current tip into the working dir'''
257 if not node:
357 if not node:
258 node = repo.changelog.tip()
358 node = repo.changelog.tip()
259 else:
359 else:
260 node = repo.lookup(node)
360 node = repo.lookup(node)
261 repo.resolve(node)
361 repo.resolve(node)
262
362
263 def serve(ui, repo, **opts):
363 def serve(ui, repo, **opts):
264 from mercurial import hgweb
364 from mercurial import hgweb
265 hgweb.server(repo.root, opts["name"], opts["templates"],
365 hgweb.server(repo.root, opts["name"], opts["templates"],
266 opts["address"], opts["port"])
366 opts["address"], opts["port"])
267
367
268 def status(ui, repo):
368 def status(ui, repo):
269 '''show changed files in the working directory
369 '''show changed files in the working directory
270
370
271 C = changed
371 C = changed
272 A = added
372 A = added
273 R = removed
373 R = removed
274 ? = not tracked'''
374 ? = not tracked'''
275
375
276 (c, a, d, u) = repo.diffdir(repo.root)
376 (c, a, d, u) = repo.diffdir(repo.root)
277 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
377 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
278
378
279 for f in c: print "C", f
379 for f in c: print "C", f
280 for f in a: print "A", f
380 for f in a: print "A", f
281 for f in d: print "R", f
381 for f in d: print "R", f
282 for f in u: print "?", f
382 for f in u: print "?", f
283
383
284 def tip(ui, repo):
384 def tip(ui, repo):
285 n = repo.changelog.tip()
385 n = repo.changelog.tip()
286 t = repo.changelog.rev(n)
386 t = repo.changelog.rev(n)
287 ui.status("%d:%s\n" % (t, hg.hex(n)))
387 ui.status("%d:%s\n" % (t, hg.hex(n)))
288
388
289 def undo(ui, repo):
389 def undo(ui, repo):
290 repo.undo()
390 repo.undo()
291
391
292 table = {
392 table = {
293 "add": (add, [], "hg add [files]"),
393 "add": (add, [], "hg add [files]"),
294 "addremove": (addremove, [], "hg addremove"),
394 "addremove": (addremove, [], "hg addremove"),
295 "ann|annotate": (annotate,
395 "ann|annotate": (annotate,
296 [('r', 'revision', '', 'revision'),
396 [('r', 'revision', '', 'revision'),
297 ('u', 'user', None, 'show user'),
397 ('u', 'user', None, 'show user'),
298 ('n', 'number', None, 'show revision number'),
398 ('n', 'number', None, 'show revision number'),
299 ('c', 'changeset', None, 'show changeset')],
399 ('c', 'changeset', None, 'show changeset')],
300 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
400 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
301 "branch|clone": (branch, [], 'hg branch [path]'),
401 "branch|clone": (branch, [], 'hg branch [path]'),
302 "checkout|co": (checkout, [], 'hg checkout [changeset]'),
402 "checkout|co": (checkout, [], 'hg checkout [changeset]'),
303 "commit|ci": (commit, [], 'hg commit [files]'),
403 "commit|ci": (commit, [], 'hg commit [files]'),
304 "diff": (diff, [('r', 'rev', [], 'revision')],
404 "diff": (diff, [('r', 'rev', [], 'revision')],
305 'hg diff [-r A] [-r B] [files]'),
405 'hg diff [-r A] [-r B] [files]'),
406 "export": (export, [], "hg export <changeset>"),
306 "forget": (forget, [], "hg forget [files]"),
407 "forget": (forget, [], "hg forget [files]"),
307 "heads": (heads, [], 'hg heads'),
408 "heads": (heads, [], 'hg heads'),
409 "history": (history, [], 'hg history'),
308 "help": (help, [], 'hg help [command]'),
410 "help": (help, [], 'hg help [command]'),
309 "init": (init, [], 'hg init'),
411 "init": (init, [], 'hg init'),
310 "log": (log, [], 'hg log <file>'),
412 "log": (log, [], 'hg log <file>'),
311 "parents": (parents, [], 'hg parents [node]'),
413 "parents": (parents, [], 'hg parents [node]'),
414 "patch|import": (patch,
415 [('p', 'strip', 1, 'path strip'),
416 ('b', 'base', "", 'base path'),
417 ('q', 'quiet', "", 'silence diff')],
418 "hg import [options] patches"),
419 "pull|merge": (pull, [], 'hg pull [source]'),
420 "rawcommit": (rawcommit,
421 [('p', 'parent', [], 'parent'),
422 ('d', 'date', "", 'data'),
423 ('u', 'user', "", 'user'),
424 ('F', 'files', "", 'file list'),
425 ('t', 'text', "", 'commit text'),
426 ('l', 'logfile', "", 'commit text file')],
427 'hg rawcommit [options] [files]'),
312 "recover": (recover, [], "hg recover"),
428 "recover": (recover, [], "hg recover"),
313 "remove": (remove, [], "hg remove [files]"),
429 "remove": (remove, [], "hg remove [files]"),
314 "resolve": (resolve, [], 'hg resolve [node]'),
430 "resolve": (resolve, [], 'hg resolve [node]'),
315 "serve": (serve, [('p', 'port', 8000, 'listen port'),
431 "serve": (serve, [('p', 'port', 8000, 'listen port'),
316 ('a', 'address', '', 'interface address'),
432 ('a', 'address', '', 'interface address'),
317 ('n', 'name', os.getcwd(), 'repository name'),
433 ('n', 'name', os.getcwd(), 'repository name'),
318 ('t', 'templates', "", 'template map')],
434 ('t', 'templates', "", 'template map')],
319 "hg serve [options]"),
435 "hg serve [options]"),
320 "status": (status, [], 'hg status'),
436 "status": (status, [], 'hg status'),
321 "tip": (tip, [], 'hg tip'),
437 "tip": (tip, [], 'hg tip'),
322 "undo": (undo, [], 'hg undo'),
438 "undo": (undo, [], 'hg undo'),
323 }
439 }
324
440
325 norepo = "init branch help"
441 norepo = "init branch help"
326
442
327 def find(cmd):
443 def find(cmd):
328 i = None
444 i = None
329 for e in table.keys():
445 for e in table.keys():
330 if re.match(e + "$", cmd):
446 if re.match(e + "$", cmd):
331 return table[e]
447 return table[e]
332
448
333 raise UnknownCommand(cmd)
449 raise UnknownCommand(cmd)
334
450
335 class SignalInterrupt(Exception): pass
451 class SignalInterrupt(Exception): pass
336
452
337 def catchterm(*args):
453 def catchterm(*args):
338 raise SignalInterrupt
454 raise SignalInterrupt
339
455
340 def dispatch(args):
456 def dispatch(args):
341 options = {}
457 options = {}
342 opts = [('v', 'verbose', None, 'verbose'),
458 opts = [('v', 'verbose', None, 'verbose'),
343 ('d', 'debug', None, 'debug'),
459 ('d', 'debug', None, 'debug'),
344 ('q', 'quiet', None, 'quiet'),
460 ('q', 'quiet', None, 'quiet'),
345 ('y', 'noninteractive', None, 'run non-interactively'),
461 ('y', 'noninteractive', None, 'run non-interactively'),
346 ]
462 ]
347
463
348 args = fancyopts.fancyopts(args, opts, options,
464 args = fancyopts.fancyopts(args, opts, options,
349 'hg [options] <command> [options] [files]')
465 'hg [options] <command> [options] [files]')
350
466
351 if not args:
467 if not args:
352 cmd = "help"
468 cmd = "help"
353 else:
469 else:
354 cmd, args = args[0], args[1:]
470 cmd, args = args[0], args[1:]
355
471
356 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
472 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
357 not options["noninteractive"])
473 not options["noninteractive"])
358
474
359 # deal with unfound commands later
475 # deal with unfound commands later
360 i = find(cmd)
476 i = find(cmd)
361
477
362 signal.signal(signal.SIGTERM, catchterm)
478 signal.signal(signal.SIGTERM, catchterm)
363
479
364 cmdoptions = {}
480 cmdoptions = {}
365 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
481 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
366
482
367 if cmd not in norepo.split():
483 if cmd not in norepo.split():
368 repo = hg.repository(ui = u)
484 repo = hg.repository(ui = u)
369 d = lambda: i[0](u, repo, *args, **cmdoptions)
485 d = lambda: i[0](u, repo, *args, **cmdoptions)
370 else:
486 else:
371 d = lambda: i[0](u, *args, **cmdoptions)
487 d = lambda: i[0](u, *args, **cmdoptions)
372
488
373 try:
489 try:
374 d()
490 return d()
375 except SignalInterrupt:
491 except SignalInterrupt:
376 u.warn("killed!\n")
492 u.warn("killed!\n")
377 except KeyboardInterrupt:
493 except KeyboardInterrupt:
378 u.warn("interrupted!\n")
494 u.warn("interrupted!\n")
379 except TypeError, inst:
495 except TypeError, inst:
380 # was this an argument error?
496 # was this an argument error?
381 tb = traceback.extract_tb(sys.exc_info()[2])
497 tb = traceback.extract_tb(sys.exc_info()[2])
382 if len(tb) > 2: # no
498 if len(tb) > 2: # no
383 raise
499 raise
384 u.warn("%s: invalid arguments\n" % i[0].__name__)
500 u.warn("%s: invalid arguments\n" % i[0].__name__)
385 u.warn("syntax: %s\n" % i[2])
501 u.warn("syntax: %s\n" % i[2])
386 sys.exit(-1)
502 sys.exit(-1)
General Comments 0
You need to be logged in to leave comments. Login now