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