##// END OF EJS Templates
reset mergestate after commit
Martin Geisler -
r7734:9f73bddb default
parent child Browse files
Show More
@@ -0,0 +1,27 b''
1 #!/bin/sh
2
3 # test that a commit clears the merge state.
4
5 hg init repo
6 cd repo
7
8 echo foo > file
9 hg commit -Am 'add file' -d '0 0'
10
11 echo bar >> file
12 hg commit -Am 'append bar' -d '0 0'
13
14 echo % create a second head
15 hg up -C 0
16 echo baz >> file
17 hg commit -Am 'append baz' -d '0 0'
18
19 echo % failing merge
20 HGMERGE=internal:fail hg merge
21
22 echo resolved > file
23 hg resolve -m file
24 hg commit -m 'resolved' -d '0 0'
25
26 echo % resolve -l, should be empty
27 hg resolve -l
@@ -0,0 +1,8 b''
1 adding file
2 % create a second head
3 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 created new head
5 % failing merge
6 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
7 use 'hg resolve' to retry unresolved file merges
8 % resolve -l, should be empty
@@ -1,3406 +1,3409 b''
1 1 # commands.py - command processing for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms
6 6 # of the GNU General Public License, incorporated herein by reference.
7 7
8 8 from node import hex, nullid, nullrev, short
9 9 from i18n import _, gettext
10 10 import os, re, sys
11 11 import hg, util, revlog, bundlerepo, extensions, copies, context, error
12 12 import difflib, patch, time, help, mdiff, tempfile, url
13 13 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
14 14 import merge as merge_
15 15
16 16 # Commands start here, listed alphabetically
17 17
18 18 def add(ui, repo, *pats, **opts):
19 19 """add the specified files on the next commit
20 20
21 21 Schedule files to be version controlled and added to the repository.
22 22
23 23 The files will be added to the repository at the next commit. To
24 24 undo an add before that, see hg revert.
25 25
26 26 If no names are given, add all files in the repository.
27 27 """
28 28
29 29 rejected = None
30 30 exacts = {}
31 31 names = []
32 32 m = cmdutil.match(repo, pats, opts)
33 33 m.bad = lambda x,y: True
34 34 for abs in repo.walk(m):
35 35 if m.exact(abs):
36 36 if ui.verbose:
37 37 ui.status(_('adding %s\n') % m.rel(abs))
38 38 names.append(abs)
39 39 exacts[abs] = 1
40 40 elif abs not in repo.dirstate:
41 41 ui.status(_('adding %s\n') % m.rel(abs))
42 42 names.append(abs)
43 43 if not opts.get('dry_run'):
44 44 rejected = repo.add(names)
45 45 rejected = [p for p in rejected if p in exacts]
46 46 return rejected and 1 or 0
47 47
48 48 def addremove(ui, repo, *pats, **opts):
49 49 """add all new files, delete all missing files
50 50
51 51 Add all new files and remove all missing files from the repository.
52 52
53 53 New files are ignored if they match any of the patterns in .hgignore. As
54 54 with add, these changes take effect at the next commit.
55 55
56 56 Use the -s option to detect renamed files. With a parameter > 0,
57 57 this compares every removed file with every added file and records
58 58 those similar enough as renames. This option takes a percentage
59 59 between 0 (disabled) and 100 (files must be identical) as its
60 60 parameter. Detecting renamed files this way can be expensive.
61 61 """
62 62 try:
63 63 sim = float(opts.get('similarity') or 0)
64 64 except ValueError:
65 65 raise util.Abort(_('similarity must be a number'))
66 66 if sim < 0 or sim > 100:
67 67 raise util.Abort(_('similarity must be between 0 and 100'))
68 68 return cmdutil.addremove(repo, pats, opts, similarity=sim/100.)
69 69
70 70 def annotate(ui, repo, *pats, **opts):
71 71 """show changeset information per file line
72 72
73 73 List changes in files, showing the revision id responsible for each line
74 74
75 75 This command is useful to discover who did a change or when a change took
76 76 place.
77 77
78 78 Without the -a option, annotate will avoid processing files it
79 79 detects as binary. With -a, annotate will generate an annotation
80 80 anyway, probably with undesirable results.
81 81 """
82 82 datefunc = ui.quiet and util.shortdate or util.datestr
83 83 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
84 84
85 85 if not pats:
86 86 raise util.Abort(_('at least one file name or pattern required'))
87 87
88 88 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
89 89 ('number', lambda x: str(x[0].rev())),
90 90 ('changeset', lambda x: short(x[0].node())),
91 91 ('date', getdate),
92 92 ('follow', lambda x: x[0].path()),
93 93 ]
94 94
95 95 if (not opts.get('user') and not opts.get('changeset') and not opts.get('date')
96 96 and not opts.get('follow')):
97 97 opts['number'] = 1
98 98
99 99 linenumber = opts.get('line_number') is not None
100 100 if (linenumber and (not opts.get('changeset')) and (not opts.get('number'))):
101 101 raise util.Abort(_('at least one of -n/-c is required for -l'))
102 102
103 103 funcmap = [func for op, func in opmap if opts.get(op)]
104 104 if linenumber:
105 105 lastfunc = funcmap[-1]
106 106 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
107 107
108 108 ctx = repo[opts.get('rev')]
109 109
110 110 m = cmdutil.match(repo, pats, opts)
111 111 for abs in ctx.walk(m):
112 112 fctx = ctx[abs]
113 113 if not opts.get('text') and util.binary(fctx.data()):
114 114 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
115 115 continue
116 116
117 117 lines = fctx.annotate(follow=opts.get('follow'),
118 118 linenumber=linenumber)
119 119 pieces = []
120 120
121 121 for f in funcmap:
122 122 l = [f(n) for n, dummy in lines]
123 123 if l:
124 124 ml = max(map(len, l))
125 125 pieces.append(["%*s" % (ml, x) for x in l])
126 126
127 127 if pieces:
128 128 for p, l in zip(zip(*pieces), lines):
129 129 ui.write("%s: %s" % (" ".join(p), l[1]))
130 130
131 131 def archive(ui, repo, dest, **opts):
132 132 '''create unversioned archive of a repository revision
133 133
134 134 By default, the revision used is the parent of the working
135 135 directory; use "-r" to specify a different revision.
136 136
137 137 To specify the type of archive to create, use "-t". Valid
138 138 types are:
139 139
140 140 "files" (default): a directory full of files
141 141 "tar": tar archive, uncompressed
142 142 "tbz2": tar archive, compressed using bzip2
143 143 "tgz": tar archive, compressed using gzip
144 144 "uzip": zip archive, uncompressed
145 145 "zip": zip archive, compressed using deflate
146 146
147 147 The exact name of the destination archive or directory is given
148 148 using a format string; see "hg help export" for details.
149 149
150 150 Each member added to an archive file has a directory prefix
151 151 prepended. Use "-p" to specify a format string for the prefix.
152 152 The default is the basename of the archive, with suffixes removed.
153 153 '''
154 154
155 155 ctx = repo[opts.get('rev')]
156 156 if not ctx:
157 157 raise util.Abort(_('no working directory: please specify a revision'))
158 158 node = ctx.node()
159 159 dest = cmdutil.make_filename(repo, dest, node)
160 160 if os.path.realpath(dest) == repo.root:
161 161 raise util.Abort(_('repository root cannot be destination'))
162 162 matchfn = cmdutil.match(repo, [], opts)
163 163 kind = opts.get('type') or 'files'
164 164 prefix = opts.get('prefix')
165 165 if dest == '-':
166 166 if kind == 'files':
167 167 raise util.Abort(_('cannot archive plain files to stdout'))
168 168 dest = sys.stdout
169 169 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
170 170 prefix = cmdutil.make_filename(repo, prefix, node)
171 171 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
172 172 matchfn, prefix)
173 173
174 174 def backout(ui, repo, node=None, rev=None, **opts):
175 175 '''reverse effect of earlier changeset
176 176
177 177 Commit the backed out changes as a new changeset. The new
178 178 changeset is a child of the backed out changeset.
179 179
180 180 If you back out a changeset other than the tip, a new head is
181 181 created. This head will be the new tip and you should merge this
182 182 backout changeset with another head (current one by default).
183 183
184 184 The --merge option remembers the parent of the working directory
185 185 before starting the backout, then merges the new head with that
186 186 changeset afterwards. This saves you from doing the merge by
187 187 hand. The result of this merge is not committed, as for a normal
188 188 merge.
189 189
190 190 See \'hg help dates\' for a list of formats valid for -d/--date.
191 191 '''
192 192 if rev and node:
193 193 raise util.Abort(_("please specify just one revision"))
194 194
195 195 if not rev:
196 196 rev = node
197 197
198 198 if not rev:
199 199 raise util.Abort(_("please specify a revision to backout"))
200 200
201 201 date = opts.get('date')
202 202 if date:
203 203 opts['date'] = util.parsedate(date)
204 204
205 205 cmdutil.bail_if_changed(repo)
206 206 node = repo.lookup(rev)
207 207
208 208 op1, op2 = repo.dirstate.parents()
209 209 a = repo.changelog.ancestor(op1, node)
210 210 if a != node:
211 211 raise util.Abort(_('cannot back out change on a different branch'))
212 212
213 213 p1, p2 = repo.changelog.parents(node)
214 214 if p1 == nullid:
215 215 raise util.Abort(_('cannot back out a change with no parents'))
216 216 if p2 != nullid:
217 217 if not opts.get('parent'):
218 218 raise util.Abort(_('cannot back out a merge changeset without '
219 219 '--parent'))
220 220 p = repo.lookup(opts['parent'])
221 221 if p not in (p1, p2):
222 222 raise util.Abort(_('%s is not a parent of %s') %
223 223 (short(p), short(node)))
224 224 parent = p
225 225 else:
226 226 if opts.get('parent'):
227 227 raise util.Abort(_('cannot use --parent on non-merge changeset'))
228 228 parent = p1
229 229
230 230 # the backout should appear on the same branch
231 231 branch = repo.dirstate.branch()
232 232 hg.clean(repo, node, show_stats=False)
233 233 repo.dirstate.setbranch(branch)
234 234 revert_opts = opts.copy()
235 235 revert_opts['date'] = None
236 236 revert_opts['all'] = True
237 237 revert_opts['rev'] = hex(parent)
238 238 revert_opts['no_backup'] = None
239 239 revert(ui, repo, **revert_opts)
240 240 commit_opts = opts.copy()
241 241 commit_opts['addremove'] = False
242 242 if not commit_opts['message'] and not commit_opts['logfile']:
243 243 commit_opts['message'] = _("Backed out changeset %s") % (short(node))
244 244 commit_opts['force_editor'] = True
245 245 commit(ui, repo, **commit_opts)
246 246 def nice(node):
247 247 return '%d:%s' % (repo.changelog.rev(node), short(node))
248 248 ui.status(_('changeset %s backs out changeset %s\n') %
249 249 (nice(repo.changelog.tip()), nice(node)))
250 250 if op1 != node:
251 251 hg.clean(repo, op1, show_stats=False)
252 252 if opts.get('merge'):
253 253 ui.status(_('merging with changeset %s\n') % nice(repo.changelog.tip()))
254 254 hg.merge(repo, hex(repo.changelog.tip()))
255 255 else:
256 256 ui.status(_('the backout changeset is a new head - '
257 257 'do not forget to merge\n'))
258 258 ui.status(_('(use "backout --merge" '
259 259 'if you want to auto-merge)\n'))
260 260
261 261 def bisect(ui, repo, rev=None, extra=None, command=None,
262 262 reset=None, good=None, bad=None, skip=None, noupdate=None):
263 263 """subdivision search of changesets
264 264
265 265 This command helps to find changesets which introduce problems.
266 266 To use, mark the earliest changeset you know exhibits the problem
267 267 as bad, then mark the latest changeset which is free from the
268 268 problem as good. Bisect will update your working directory to a
269 269 revision for testing (unless the --noupdate option is specified).
270 270 Once you have performed tests, mark the working directory as bad
271 271 or good and bisect will either update to another candidate changeset
272 272 or announce that it has found the bad revision.
273 273
274 274 As a shortcut, you can also use the revision argument to mark a
275 275 revision as good or bad without checking it out first.
276 276
277 277 If you supply a command it will be used for automatic bisection. Its exit
278 278 status will be used as flag to mark revision as bad or good. In case exit
279 279 status is 0 the revision is marked as good, 125 - skipped, 127 (command not
280 280 found) - bisection will be aborted and any other status bigger than 0 will
281 281 mark revision as bad.
282 282 """
283 283 def print_result(nodes, good):
284 284 displayer = cmdutil.show_changeset(ui, repo, {})
285 285 transition = (good and "good" or "bad")
286 286 if len(nodes) == 1:
287 287 # narrowed it down to a single revision
288 288 ui.write(_("The first %s revision is:\n") % transition)
289 289 displayer.show(repo[nodes[0]])
290 290 else:
291 291 # multiple possible revisions
292 292 ui.write(_("Due to skipped revisions, the first "
293 293 "%s revision could be any of:\n") % transition)
294 294 for n in nodes:
295 295 displayer.show(repo[n])
296 296
297 297 def check_state(state, interactive=True):
298 298 if not state['good'] or not state['bad']:
299 299 if (good or bad or skip or reset) and interactive:
300 300 return
301 301 if not state['good']:
302 302 raise util.Abort(_('cannot bisect (no known good revisions)'))
303 303 else:
304 304 raise util.Abort(_('cannot bisect (no known bad revisions)'))
305 305 return True
306 306
307 307 # backward compatibility
308 308 if rev in "good bad reset init".split():
309 309 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
310 310 cmd, rev, extra = rev, extra, None
311 311 if cmd == "good":
312 312 good = True
313 313 elif cmd == "bad":
314 314 bad = True
315 315 else:
316 316 reset = True
317 317 elif extra or good + bad + skip + reset + bool(command) > 1:
318 318 raise util.Abort(_('incompatible arguments'))
319 319
320 320 if reset:
321 321 p = repo.join("bisect.state")
322 322 if os.path.exists(p):
323 323 os.unlink(p)
324 324 return
325 325
326 326 state = hbisect.load_state(repo)
327 327
328 328 if command:
329 329 commandpath = util.find_exe(command)
330 330 changesets = 1
331 331 try:
332 332 while changesets:
333 333 # update state
334 334 status = os.spawnl(os.P_WAIT, commandpath)
335 335 if status == 125:
336 336 transition = "skip"
337 337 elif status == 0:
338 338 transition = "good"
339 339 # status < 0 means process was killed
340 340 elif status == 127:
341 341 raise util.Abort(_("failed to execute %s") % command)
342 342 elif status < 0:
343 343 raise util.Abort(_("%s killed") % command)
344 344 else:
345 345 transition = "bad"
346 346 node = repo.lookup(rev or '.')
347 347 state[transition].append(node)
348 348 ui.note(_('Changeset %s: %s\n') % (short(node), transition))
349 349 check_state(state, interactive=False)
350 350 # bisect
351 351 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
352 352 # update to next check
353 353 cmdutil.bail_if_changed(repo)
354 354 hg.clean(repo, nodes[0], show_stats=False)
355 355 finally:
356 356 hbisect.save_state(repo, state)
357 357 return print_result(nodes, not status)
358 358
359 359 # update state
360 360 node = repo.lookup(rev or '.')
361 361 if good:
362 362 state['good'].append(node)
363 363 elif bad:
364 364 state['bad'].append(node)
365 365 elif skip:
366 366 state['skip'].append(node)
367 367
368 368 hbisect.save_state(repo, state)
369 369
370 370 if not check_state(state):
371 371 return
372 372
373 373 # actually bisect
374 374 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
375 375 if changesets == 0:
376 376 print_result(nodes, good)
377 377 else:
378 378 assert len(nodes) == 1 # only a single node can be tested next
379 379 node = nodes[0]
380 380 # compute the approximate number of remaining tests
381 381 tests, size = 0, 2
382 382 while size <= changesets:
383 383 tests, size = tests + 1, size * 2
384 384 rev = repo.changelog.rev(node)
385 385 ui.write(_("Testing changeset %s:%s "
386 386 "(%s changesets remaining, ~%s tests)\n")
387 387 % (rev, short(node), changesets, tests))
388 388 if not noupdate:
389 389 cmdutil.bail_if_changed(repo)
390 390 return hg.clean(repo, node)
391 391
392 392 def branch(ui, repo, label=None, **opts):
393 393 """set or show the current branch name
394 394
395 395 With no argument, show the current branch name. With one argument,
396 396 set the working directory branch name (the branch does not exist in
397 397 the repository until the next commit).
398 398
399 399 Unless --force is specified, branch will not let you set a
400 400 branch name that shadows an existing branch.
401 401
402 402 Use --clean to reset the working directory branch to that of the
403 403 parent of the working directory, negating a previous branch change.
404 404
405 405 Use the command 'hg update' to switch to an existing branch.
406 406 """
407 407
408 408 if opts.get('clean'):
409 409 label = repo[None].parents()[0].branch()
410 410 repo.dirstate.setbranch(label)
411 411 ui.status(_('reset working directory to branch %s\n') % label)
412 412 elif label:
413 413 if not opts.get('force') and label in repo.branchtags():
414 414 if label not in [p.branch() for p in repo.parents()]:
415 415 raise util.Abort(_('a branch of the same name already exists'
416 416 ' (use --force to override)'))
417 417 repo.dirstate.setbranch(util.fromlocal(label))
418 418 ui.status(_('marked working directory as branch %s\n') % label)
419 419 else:
420 420 ui.write("%s\n" % util.tolocal(repo.dirstate.branch()))
421 421
422 422 def branches(ui, repo, active=False):
423 423 """list repository named branches
424 424
425 425 List the repository's named branches, indicating which ones are
426 426 inactive. If active is specified, only show active branches.
427 427
428 428 A branch is considered active if it contains repository heads.
429 429
430 430 Use the command 'hg update' to switch to an existing branch.
431 431 """
432 432 hexfunc = ui.debugflag and hex or short
433 433 activebranches = [util.tolocal(repo[n].branch())
434 434 for n in repo.heads(closed=False)]
435 435 branches = util.sort([(tag in activebranches, repo.changelog.rev(node), tag)
436 436 for tag, node in repo.branchtags().items()])
437 437 branches.reverse()
438 438
439 439 for isactive, node, tag in branches:
440 440 if (not active) or isactive:
441 441 if ui.quiet:
442 442 ui.write("%s\n" % tag)
443 443 else:
444 444 hn = repo.lookup(node)
445 445 if isactive:
446 446 notice = ''
447 447 elif hn not in repo.branchheads(tag, closed=False):
448 448 notice = ' (closed)'
449 449 else:
450 450 notice = ' (inactive)'
451 451 rev = str(node).rjust(31 - util.colwidth(tag))
452 452 data = tag, rev, hexfunc(hn), notice
453 453 ui.write("%s %s:%s%s\n" % data)
454 454
455 455 def bundle(ui, repo, fname, dest=None, **opts):
456 456 """create a changegroup file
457 457
458 458 Generate a compressed changegroup file collecting changesets not
459 459 found in the other repository.
460 460
461 461 If no destination repository is specified the destination is
462 462 assumed to have all the nodes specified by one or more --base
463 463 parameters. To create a bundle containing all changesets, use
464 464 --all (or --base null). To change the compression method applied,
465 465 use the -t option (by default, bundles are compressed using bz2).
466 466
467 467 The bundle file can then be transferred using conventional means and
468 468 applied to another repository with the unbundle or pull command.
469 469 This is useful when direct push and pull are not available or when
470 470 exporting an entire repository is undesirable.
471 471
472 472 Applying bundles preserves all changeset contents including
473 473 permissions, copy/rename information, and revision history.
474 474 """
475 475 revs = opts.get('rev') or None
476 476 if revs:
477 477 revs = [repo.lookup(rev) for rev in revs]
478 478 if opts.get('all'):
479 479 base = ['null']
480 480 else:
481 481 base = opts.get('base')
482 482 if base:
483 483 if dest:
484 484 raise util.Abort(_("--base is incompatible with specifiying "
485 485 "a destination"))
486 486 base = [repo.lookup(rev) for rev in base]
487 487 # create the right base
488 488 # XXX: nodesbetween / changegroup* should be "fixed" instead
489 489 o = []
490 490 has = {nullid: None}
491 491 for n in base:
492 492 has.update(repo.changelog.reachable(n))
493 493 if revs:
494 494 visit = list(revs)
495 495 else:
496 496 visit = repo.changelog.heads()
497 497 seen = {}
498 498 while visit:
499 499 n = visit.pop(0)
500 500 parents = [p for p in repo.changelog.parents(n) if p not in has]
501 501 if len(parents) == 0:
502 502 o.insert(0, n)
503 503 else:
504 504 for p in parents:
505 505 if p not in seen:
506 506 seen[p] = 1
507 507 visit.append(p)
508 508 else:
509 509 cmdutil.setremoteconfig(ui, opts)
510 510 dest, revs, checkout = hg.parseurl(
511 511 ui.expandpath(dest or 'default-push', dest or 'default'), revs)
512 512 other = hg.repository(ui, dest)
513 513 o = repo.findoutgoing(other, force=opts.get('force'))
514 514
515 515 if revs:
516 516 cg = repo.changegroupsubset(o, revs, 'bundle')
517 517 else:
518 518 cg = repo.changegroup(o, 'bundle')
519 519
520 520 bundletype = opts.get('type', 'bzip2').lower()
521 521 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
522 522 bundletype = btypes.get(bundletype)
523 523 if bundletype not in changegroup.bundletypes:
524 524 raise util.Abort(_('unknown bundle type specified with --type'))
525 525
526 526 changegroup.writebundle(cg, fname, bundletype)
527 527
528 528 def cat(ui, repo, file1, *pats, **opts):
529 529 """output the current or given revision of files
530 530
531 531 Print the specified files as they were at the given revision.
532 532 If no revision is given, the parent of the working directory is used,
533 533 or tip if no revision is checked out.
534 534
535 535 Output may be to a file, in which case the name of the file is
536 536 given using a format string. The formatting rules are the same as
537 537 for the export command, with the following additions:
538 538
539 539 %s basename of file being printed
540 540 %d dirname of file being printed, or '.' if in repo root
541 541 %p root-relative path name of file being printed
542 542 """
543 543 ctx = repo[opts.get('rev')]
544 544 err = 1
545 545 m = cmdutil.match(repo, (file1,) + pats, opts)
546 546 for abs in ctx.walk(m):
547 547 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
548 548 data = ctx[abs].data()
549 549 if opts.get('decode'):
550 550 data = repo.wwritedata(abs, data)
551 551 fp.write(data)
552 552 err = 0
553 553 return err
554 554
555 555 def clone(ui, source, dest=None, **opts):
556 556 """make a copy of an existing repository
557 557
558 558 Create a copy of an existing repository in a new directory.
559 559
560 560 If no destination directory name is specified, it defaults to the
561 561 basename of the source.
562 562
563 563 The location of the source is added to the new repository's
564 564 .hg/hgrc file, as the default to be used for future pulls.
565 565
566 566 For efficiency, hardlinks are used for cloning whenever the source
567 567 and destination are on the same filesystem (note this applies only
568 568 to the repository data, not to the checked out files). Some
569 569 filesystems, such as AFS, implement hardlinking incorrectly, but
570 570 do not report errors. In these cases, use the --pull option to
571 571 avoid hardlinking.
572 572
573 573 In some cases, you can clone repositories and checked out files
574 574 using full hardlinks with
575 575
576 576 $ cp -al REPO REPOCLONE
577 577
578 578 This is the fastest way to clone, but it is not always safe. The
579 579 operation is not atomic (making sure REPO is not modified during
580 580 the operation is up to you) and you have to make sure your editor
581 581 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
582 582 this is not compatible with certain extensions that place their
583 583 metadata under the .hg directory, such as mq.
584 584
585 585 If you use the -r option to clone up to a specific revision, no
586 586 subsequent revisions will be present in the cloned repository.
587 587 This option implies --pull, even on local repositories.
588 588
589 589 If the -U option is used, the new clone will contain only a repository
590 590 (.hg) and no working copy (the working copy parent is the null revision).
591 591
592 592 See 'hg help urls' for valid source format details.
593 593
594 594 It is possible to specify an ssh:// URL as the destination, but no
595 595 .hg/hgrc and working directory will be created on the remote side.
596 596 Look at the help text for urls for important details about ssh:// URLs.
597 597 """
598 598 cmdutil.setremoteconfig(ui, opts)
599 599 hg.clone(ui, source, dest,
600 600 pull=opts.get('pull'),
601 601 stream=opts.get('uncompressed'),
602 602 rev=opts.get('rev'),
603 603 update=not opts.get('noupdate'))
604 604
605 605 def commit(ui, repo, *pats, **opts):
606 606 """commit the specified files or all outstanding changes
607 607
608 608 Commit changes to the given files into the repository.
609 609
610 610 If a list of files is omitted, all changes reported by "hg status"
611 611 will be committed.
612 612
613 613 If you are committing the result of a merge, do not provide any
614 614 file names or -I/-X filters.
615 615
616 616 If no commit message is specified, the configured editor is started to
617 617 enter a message.
618 618
619 619 See 'hg help dates' for a list of formats valid for -d/--date.
620 620 """
621 621 extra = {}
622 622 if opts.get('close_branch'):
623 623 extra['close'] = 1
624 624 def commitfunc(ui, repo, message, match, opts):
625 625 return repo.commit(match.files(), message, opts.get('user'),
626 626 opts.get('date'), match, force_editor=opts.get('force_editor'),
627 627 extra=extra)
628 628
629 629 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
630 630 if not node:
631 631 return
632 632 cl = repo.changelog
633 633 rev = cl.rev(node)
634 634 parents = cl.parentrevs(rev)
635 635 if rev - 1 in parents:
636 636 # one of the parents was the old tip
637 637 pass
638 638 elif (parents == (nullrev, nullrev) or
639 639 len(cl.heads(cl.node(parents[0]))) > 1 and
640 640 (parents[1] == nullrev or len(cl.heads(cl.node(parents[1]))) > 1)):
641 641 ui.status(_('created new head\n'))
642 642
643 643 if ui.debugflag:
644 644 ui.write(_('committed changeset %d:%s\n') % (rev,hex(node)))
645 645 elif ui.verbose:
646 646 ui.write(_('committed changeset %d:%s\n') % (rev,short(node)))
647 647
648 ms = merge_.mergestate(repo)
649 ms.reset(node)
650
648 651 def copy(ui, repo, *pats, **opts):
649 652 """mark files as copied for the next commit
650 653
651 654 Mark dest as having copies of source files. If dest is a
652 655 directory, copies are put in that directory. If dest is a file,
653 656 there can only be one source.
654 657
655 658 By default, this command copies the contents of files as they
656 659 stand in the working directory. If invoked with --after, the
657 660 operation is recorded, but no copying is performed.
658 661
659 662 This command takes effect in the next commit. To undo a copy
660 663 before that, see hg revert.
661 664 """
662 665 wlock = repo.wlock(False)
663 666 try:
664 667 return cmdutil.copy(ui, repo, pats, opts)
665 668 finally:
666 669 del wlock
667 670
668 671 def debugancestor(ui, repo, *args):
669 672 """find the ancestor revision of two revisions in a given index"""
670 673 if len(args) == 3:
671 674 index, rev1, rev2 = args
672 675 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
673 676 lookup = r.lookup
674 677 elif len(args) == 2:
675 678 if not repo:
676 679 raise util.Abort(_("There is no Mercurial repository here "
677 680 "(.hg not found)"))
678 681 rev1, rev2 = args
679 682 r = repo.changelog
680 683 lookup = repo.lookup
681 684 else:
682 685 raise util.Abort(_('either two or three arguments required'))
683 686 a = r.ancestor(lookup(rev1), lookup(rev2))
684 687 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
685 688
686 689 def debugcomplete(ui, cmd='', **opts):
687 690 """returns the completion list associated with the given command"""
688 691
689 692 if opts.get('options'):
690 693 options = []
691 694 otables = [globalopts]
692 695 if cmd:
693 696 aliases, entry = cmdutil.findcmd(cmd, table, False)
694 697 otables.append(entry[1])
695 698 for t in otables:
696 699 for o in t:
697 700 if o[0]:
698 701 options.append('-%s' % o[0])
699 702 options.append('--%s' % o[1])
700 703 ui.write("%s\n" % "\n".join(options))
701 704 return
702 705
703 706 cmdlist = cmdutil.findpossible(cmd, table)
704 707 if ui.verbose:
705 708 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
706 709 ui.write("%s\n" % "\n".join(util.sort(cmdlist)))
707 710
708 711 def debugfsinfo(ui, path = "."):
709 712 file('.debugfsinfo', 'w').write('')
710 713 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
711 714 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
712 715 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
713 716 and 'yes' or 'no'))
714 717 os.unlink('.debugfsinfo')
715 718
716 719 def debugrebuildstate(ui, repo, rev="tip"):
717 720 """rebuild the dirstate as it would look like for the given revision"""
718 721 ctx = repo[rev]
719 722 wlock = repo.wlock()
720 723 try:
721 724 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
722 725 finally:
723 726 del wlock
724 727
725 728 def debugcheckstate(ui, repo):
726 729 """validate the correctness of the current dirstate"""
727 730 parent1, parent2 = repo.dirstate.parents()
728 731 m1 = repo[parent1].manifest()
729 732 m2 = repo[parent2].manifest()
730 733 errors = 0
731 734 for f in repo.dirstate:
732 735 state = repo.dirstate[f]
733 736 if state in "nr" and f not in m1:
734 737 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
735 738 errors += 1
736 739 if state in "a" and f in m1:
737 740 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
738 741 errors += 1
739 742 if state in "m" and f not in m1 and f not in m2:
740 743 ui.warn(_("%s in state %s, but not in either manifest\n") %
741 744 (f, state))
742 745 errors += 1
743 746 for f in m1:
744 747 state = repo.dirstate[f]
745 748 if state not in "nrm":
746 749 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
747 750 errors += 1
748 751 if errors:
749 752 error = _(".hg/dirstate inconsistent with current parent's manifest")
750 753 raise util.Abort(error)
751 754
752 755 def showconfig(ui, repo, *values, **opts):
753 756 """show combined config settings from all hgrc files
754 757
755 758 With no args, print names and values of all config items.
756 759
757 760 With one arg of the form section.name, print just the value of
758 761 that config item.
759 762
760 763 With multiple args, print names and values of all config items
761 764 with matching section names."""
762 765
763 766 untrusted = bool(opts.get('untrusted'))
764 767 if values:
765 768 if len([v for v in values if '.' in v]) > 1:
766 769 raise util.Abort(_('only one config item permitted'))
767 770 for section, name, value in ui.walkconfig(untrusted=untrusted):
768 771 sectname = section + '.' + name
769 772 if values:
770 773 for v in values:
771 774 if v == section:
772 775 ui.write('%s=%s\n' % (sectname, value))
773 776 elif v == sectname:
774 777 ui.write(value, '\n')
775 778 else:
776 779 ui.write('%s=%s\n' % (sectname, value))
777 780
778 781 def debugsetparents(ui, repo, rev1, rev2=None):
779 782 """manually set the parents of the current working directory
780 783
781 784 This is useful for writing repository conversion tools, but should
782 785 be used with care.
783 786 """
784 787
785 788 if not rev2:
786 789 rev2 = hex(nullid)
787 790
788 791 wlock = repo.wlock()
789 792 try:
790 793 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
791 794 finally:
792 795 del wlock
793 796
794 797 def debugstate(ui, repo, nodates=None):
795 798 """show the contents of the current dirstate"""
796 799 timestr = ""
797 800 showdate = not nodates
798 801 for file_, ent in util.sort(repo.dirstate._map.iteritems()):
799 802 if showdate:
800 803 if ent[3] == -1:
801 804 # Pad or slice to locale representation
802 805 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(0)))
803 806 timestr = 'unset'
804 807 timestr = timestr[:locale_len] + ' '*(locale_len - len(timestr))
805 808 else:
806 809 timestr = time.strftime("%Y-%m-%d %H:%M:%S ", time.localtime(ent[3]))
807 810 if ent[1] & 020000:
808 811 mode = 'lnk'
809 812 else:
810 813 mode = '%3o' % (ent[1] & 0777)
811 814 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
812 815 for f in repo.dirstate.copies():
813 816 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
814 817
815 818 def debugdata(ui, file_, rev):
816 819 """dump the contents of a data file revision"""
817 820 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
818 821 try:
819 822 ui.write(r.revision(r.lookup(rev)))
820 823 except KeyError:
821 824 raise util.Abort(_('invalid revision identifier %s') % rev)
822 825
823 826 def debugdate(ui, date, range=None, **opts):
824 827 """parse and display a date"""
825 828 if opts["extended"]:
826 829 d = util.parsedate(date, util.extendeddateformats)
827 830 else:
828 831 d = util.parsedate(date)
829 832 ui.write("internal: %s %s\n" % d)
830 833 ui.write("standard: %s\n" % util.datestr(d))
831 834 if range:
832 835 m = util.matchdate(range)
833 836 ui.write("match: %s\n" % m(d[0]))
834 837
835 838 def debugindex(ui, file_):
836 839 """dump the contents of an index file"""
837 840 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
838 841 ui.write(" rev offset length base linkrev" +
839 842 " nodeid p1 p2\n")
840 843 for i in r:
841 844 node = r.node(i)
842 845 try:
843 846 pp = r.parents(node)
844 847 except:
845 848 pp = [nullid, nullid]
846 849 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
847 850 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
848 851 short(node), short(pp[0]), short(pp[1])))
849 852
850 853 def debugindexdot(ui, file_):
851 854 """dump an index DAG as a .dot file"""
852 855 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
853 856 ui.write("digraph G {\n")
854 857 for i in r:
855 858 node = r.node(i)
856 859 pp = r.parents(node)
857 860 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
858 861 if pp[1] != nullid:
859 862 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
860 863 ui.write("}\n")
861 864
862 865 def debuginstall(ui):
863 866 '''test Mercurial installation'''
864 867
865 868 def writetemp(contents):
866 869 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
867 870 f = os.fdopen(fd, "wb")
868 871 f.write(contents)
869 872 f.close()
870 873 return name
871 874
872 875 problems = 0
873 876
874 877 # encoding
875 878 ui.status(_("Checking encoding (%s)...\n") % util._encoding)
876 879 try:
877 880 util.fromlocal("test")
878 881 except util.Abort, inst:
879 882 ui.write(" %s\n" % inst)
880 883 ui.write(_(" (check that your locale is properly set)\n"))
881 884 problems += 1
882 885
883 886 # compiled modules
884 887 ui.status(_("Checking extensions...\n"))
885 888 try:
886 889 import bdiff, mpatch, base85
887 890 except Exception, inst:
888 891 ui.write(" %s\n" % inst)
889 892 ui.write(_(" One or more extensions could not be found"))
890 893 ui.write(_(" (check that you compiled the extensions)\n"))
891 894 problems += 1
892 895
893 896 # templates
894 897 ui.status(_("Checking templates...\n"))
895 898 try:
896 899 import templater
897 900 t = templater.templater(templater.templatepath("map-cmdline.default"))
898 901 except Exception, inst:
899 902 ui.write(" %s\n" % inst)
900 903 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
901 904 problems += 1
902 905
903 906 # patch
904 907 ui.status(_("Checking patch...\n"))
905 908 patchproblems = 0
906 909 a = "1\n2\n3\n4\n"
907 910 b = "1\n2\n3\ninsert\n4\n"
908 911 fa = writetemp(a)
909 912 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
910 913 os.path.basename(fa))
911 914 fd = writetemp(d)
912 915
913 916 files = {}
914 917 try:
915 918 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
916 919 except util.Abort, e:
917 920 ui.write(_(" patch call failed:\n"))
918 921 ui.write(" " + str(e) + "\n")
919 922 patchproblems += 1
920 923 else:
921 924 if list(files) != [os.path.basename(fa)]:
922 925 ui.write(_(" unexpected patch output!\n"))
923 926 patchproblems += 1
924 927 a = file(fa).read()
925 928 if a != b:
926 929 ui.write(_(" patch test failed!\n"))
927 930 patchproblems += 1
928 931
929 932 if patchproblems:
930 933 if ui.config('ui', 'patch'):
931 934 ui.write(_(" (Current patch tool may be incompatible with patch,"
932 935 " or misconfigured. Please check your .hgrc file)\n"))
933 936 else:
934 937 ui.write(_(" Internal patcher failure, please report this error"
935 938 " to http://www.selenic.com/mercurial/bts\n"))
936 939 problems += patchproblems
937 940
938 941 os.unlink(fa)
939 942 os.unlink(fd)
940 943
941 944 # editor
942 945 ui.status(_("Checking commit editor...\n"))
943 946 editor = ui.geteditor()
944 947 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
945 948 if not cmdpath:
946 949 if editor == 'vi':
947 950 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
948 951 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
949 952 else:
950 953 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
951 954 ui.write(_(" (specify a commit editor in your .hgrc file)\n"))
952 955 problems += 1
953 956
954 957 # check username
955 958 ui.status(_("Checking username...\n"))
956 959 user = os.environ.get("HGUSER")
957 960 if user is None:
958 961 user = ui.config("ui", "username")
959 962 if user is None:
960 963 user = os.environ.get("EMAIL")
961 964 if not user:
962 965 ui.warn(" ")
963 966 ui.username()
964 967 ui.write(_(" (specify a username in your .hgrc file)\n"))
965 968
966 969 if not problems:
967 970 ui.status(_("No problems detected\n"))
968 971 else:
969 972 ui.write(_("%s problems detected,"
970 973 " please check your install!\n") % problems)
971 974
972 975 return problems
973 976
974 977 def debugrename(ui, repo, file1, *pats, **opts):
975 978 """dump rename information"""
976 979
977 980 ctx = repo[opts.get('rev')]
978 981 m = cmdutil.match(repo, (file1,) + pats, opts)
979 982 for abs in ctx.walk(m):
980 983 fctx = ctx[abs]
981 984 o = fctx.filelog().renamed(fctx.filenode())
982 985 rel = m.rel(abs)
983 986 if o:
984 987 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
985 988 else:
986 989 ui.write(_("%s not renamed\n") % rel)
987 990
988 991 def debugwalk(ui, repo, *pats, **opts):
989 992 """show how files match on given patterns"""
990 993 m = cmdutil.match(repo, pats, opts)
991 994 items = list(repo.walk(m))
992 995 if not items:
993 996 return
994 997 fmt = 'f %%-%ds %%-%ds %%s' % (
995 998 max([len(abs) for abs in items]),
996 999 max([len(m.rel(abs)) for abs in items]))
997 1000 for abs in items:
998 1001 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
999 1002 ui.write("%s\n" % line.rstrip())
1000 1003
1001 1004 def diff(ui, repo, *pats, **opts):
1002 1005 """diff repository (or selected files)
1003 1006
1004 1007 Show differences between revisions for the specified files.
1005 1008
1006 1009 Differences between files are shown using the unified diff format.
1007 1010
1008 1011 NOTE: diff may generate unexpected results for merges, as it will
1009 1012 default to comparing against the working directory's first parent
1010 1013 changeset if no revisions are specified.
1011 1014
1012 1015 When two revision arguments are given, then changes are shown
1013 1016 between those revisions. If only one revision is specified then
1014 1017 that revision is compared to the working directory, and, when no
1015 1018 revisions are specified, the working directory files are compared
1016 1019 to its parent.
1017 1020
1018 1021 Without the -a option, diff will avoid generating diffs of files
1019 1022 it detects as binary. With -a, diff will generate a diff anyway,
1020 1023 probably with undesirable results.
1021 1024
1022 1025 Use the --git option to generate diffs in the git extended diff
1023 1026 format. Read the diffs help topic for more information.
1024 1027 """
1025 1028
1026 1029 revs = opts.get('rev')
1027 1030 change = opts.get('change')
1028 1031
1029 1032 if revs and change:
1030 1033 msg = _('cannot specify --rev and --change at the same time')
1031 1034 raise util.Abort(msg)
1032 1035 elif change:
1033 1036 node2 = repo.lookup(change)
1034 1037 node1 = repo[node2].parents()[0].node()
1035 1038 else:
1036 1039 node1, node2 = cmdutil.revpair(repo, revs)
1037 1040
1038 1041 m = cmdutil.match(repo, pats, opts)
1039 1042 it = patch.diff(repo, node1, node2, match=m, opts=patch.diffopts(ui, opts))
1040 1043 for chunk in it:
1041 1044 repo.ui.write(chunk)
1042 1045
1043 1046 def export(ui, repo, *changesets, **opts):
1044 1047 """dump the header and diffs for one or more changesets
1045 1048
1046 1049 Print the changeset header and diffs for one or more revisions.
1047 1050
1048 1051 The information shown in the changeset header is: author,
1049 1052 changeset hash, parent(s) and commit comment.
1050 1053
1051 1054 NOTE: export may generate unexpected diff output for merge changesets,
1052 1055 as it will compare the merge changeset against its first parent only.
1053 1056
1054 1057 Output may be to a file, in which case the name of the file is
1055 1058 given using a format string. The formatting rules are as follows:
1056 1059
1057 1060 %% literal "%" character
1058 1061 %H changeset hash (40 bytes of hexadecimal)
1059 1062 %N number of patches being generated
1060 1063 %R changeset revision number
1061 1064 %b basename of the exporting repository
1062 1065 %h short-form changeset hash (12 bytes of hexadecimal)
1063 1066 %n zero-padded sequence number, starting at 1
1064 1067 %r zero-padded changeset revision number
1065 1068
1066 1069 Without the -a option, export will avoid generating diffs of files
1067 1070 it detects as binary. With -a, export will generate a diff anyway,
1068 1071 probably with undesirable results.
1069 1072
1070 1073 Use the --git option to generate diffs in the git extended diff
1071 1074 format. Read the diffs help topic for more information.
1072 1075
1073 1076 With the --switch-parent option, the diff will be against the second
1074 1077 parent. It can be useful to review a merge.
1075 1078 """
1076 1079 if not changesets:
1077 1080 raise util.Abort(_("export requires at least one changeset"))
1078 1081 revs = cmdutil.revrange(repo, changesets)
1079 1082 if len(revs) > 1:
1080 1083 ui.note(_('exporting patches:\n'))
1081 1084 else:
1082 1085 ui.note(_('exporting patch:\n'))
1083 1086 patch.export(repo, revs, template=opts.get('output'),
1084 1087 switch_parent=opts.get('switch_parent'),
1085 1088 opts=patch.diffopts(ui, opts))
1086 1089
1087 1090 def grep(ui, repo, pattern, *pats, **opts):
1088 1091 """search for a pattern in specified files and revisions
1089 1092
1090 1093 Search revisions of files for a regular expression.
1091 1094
1092 1095 This command behaves differently than Unix grep. It only accepts
1093 1096 Python/Perl regexps. It searches repository history, not the
1094 1097 working directory. It always prints the revision number in which
1095 1098 a match appears.
1096 1099
1097 1100 By default, grep only prints output for the first revision of a
1098 1101 file in which it finds a match. To get it to print every revision
1099 1102 that contains a change in match status ("-" for a match that
1100 1103 becomes a non-match, or "+" for a non-match that becomes a match),
1101 1104 use the --all flag.
1102 1105 """
1103 1106 reflags = 0
1104 1107 if opts.get('ignore_case'):
1105 1108 reflags |= re.I
1106 1109 try:
1107 1110 regexp = re.compile(pattern, reflags)
1108 1111 except Exception, inst:
1109 1112 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1110 1113 return None
1111 1114 sep, eol = ':', '\n'
1112 1115 if opts.get('print0'):
1113 1116 sep = eol = '\0'
1114 1117
1115 1118 fcache = {}
1116 1119 def getfile(fn):
1117 1120 if fn not in fcache:
1118 1121 fcache[fn] = repo.file(fn)
1119 1122 return fcache[fn]
1120 1123
1121 1124 def matchlines(body):
1122 1125 begin = 0
1123 1126 linenum = 0
1124 1127 while True:
1125 1128 match = regexp.search(body, begin)
1126 1129 if not match:
1127 1130 break
1128 1131 mstart, mend = match.span()
1129 1132 linenum += body.count('\n', begin, mstart) + 1
1130 1133 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1131 1134 begin = body.find('\n', mend) + 1 or len(body)
1132 1135 lend = begin - 1
1133 1136 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1134 1137
1135 1138 class linestate(object):
1136 1139 def __init__(self, line, linenum, colstart, colend):
1137 1140 self.line = line
1138 1141 self.linenum = linenum
1139 1142 self.colstart = colstart
1140 1143 self.colend = colend
1141 1144
1142 1145 def __hash__(self):
1143 1146 return hash((self.linenum, self.line))
1144 1147
1145 1148 def __eq__(self, other):
1146 1149 return self.line == other.line
1147 1150
1148 1151 matches = {}
1149 1152 copies = {}
1150 1153 def grepbody(fn, rev, body):
1151 1154 matches[rev].setdefault(fn, [])
1152 1155 m = matches[rev][fn]
1153 1156 for lnum, cstart, cend, line in matchlines(body):
1154 1157 s = linestate(line, lnum, cstart, cend)
1155 1158 m.append(s)
1156 1159
1157 1160 def difflinestates(a, b):
1158 1161 sm = difflib.SequenceMatcher(None, a, b)
1159 1162 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1160 1163 if tag == 'insert':
1161 1164 for i in xrange(blo, bhi):
1162 1165 yield ('+', b[i])
1163 1166 elif tag == 'delete':
1164 1167 for i in xrange(alo, ahi):
1165 1168 yield ('-', a[i])
1166 1169 elif tag == 'replace':
1167 1170 for i in xrange(alo, ahi):
1168 1171 yield ('-', a[i])
1169 1172 for i in xrange(blo, bhi):
1170 1173 yield ('+', b[i])
1171 1174
1172 1175 prev = {}
1173 1176 def display(fn, rev, states, prevstates):
1174 1177 datefunc = ui.quiet and util.shortdate or util.datestr
1175 1178 found = False
1176 1179 filerevmatches = {}
1177 1180 r = prev.get(fn, -1)
1178 1181 if opts.get('all'):
1179 1182 iter = difflinestates(states, prevstates)
1180 1183 else:
1181 1184 iter = [('', l) for l in prevstates]
1182 1185 for change, l in iter:
1183 1186 cols = [fn, str(r)]
1184 1187 if opts.get('line_number'):
1185 1188 cols.append(str(l.linenum))
1186 1189 if opts.get('all'):
1187 1190 cols.append(change)
1188 1191 if opts.get('user'):
1189 1192 cols.append(ui.shortuser(get(r)[1]))
1190 1193 if opts.get('date'):
1191 1194 cols.append(datefunc(get(r)[2]))
1192 1195 if opts.get('files_with_matches'):
1193 1196 c = (fn, r)
1194 1197 if c in filerevmatches:
1195 1198 continue
1196 1199 filerevmatches[c] = 1
1197 1200 else:
1198 1201 cols.append(l.line)
1199 1202 ui.write(sep.join(cols), eol)
1200 1203 found = True
1201 1204 return found
1202 1205
1203 1206 fstate = {}
1204 1207 skip = {}
1205 1208 get = util.cachefunc(lambda r: repo[r].changeset())
1206 1209 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1207 1210 found = False
1208 1211 follow = opts.get('follow')
1209 1212 for st, rev, fns in changeiter:
1210 1213 if st == 'window':
1211 1214 matches.clear()
1212 1215 elif st == 'add':
1213 1216 ctx = repo[rev]
1214 1217 matches[rev] = {}
1215 1218 for fn in fns:
1216 1219 if fn in skip:
1217 1220 continue
1218 1221 try:
1219 1222 grepbody(fn, rev, getfile(fn).read(ctx.filenode(fn)))
1220 1223 fstate.setdefault(fn, [])
1221 1224 if follow:
1222 1225 copied = getfile(fn).renamed(ctx.filenode(fn))
1223 1226 if copied:
1224 1227 copies.setdefault(rev, {})[fn] = copied[0]
1225 1228 except error.LookupError:
1226 1229 pass
1227 1230 elif st == 'iter':
1228 1231 for fn, m in util.sort(matches[rev].items()):
1229 1232 copy = copies.get(rev, {}).get(fn)
1230 1233 if fn in skip:
1231 1234 if copy:
1232 1235 skip[copy] = True
1233 1236 continue
1234 1237 if fn in prev or fstate[fn]:
1235 1238 r = display(fn, rev, m, fstate[fn])
1236 1239 found = found or r
1237 1240 if r and not opts.get('all'):
1238 1241 skip[fn] = True
1239 1242 if copy:
1240 1243 skip[copy] = True
1241 1244 fstate[fn] = m
1242 1245 if copy:
1243 1246 fstate[copy] = m
1244 1247 prev[fn] = rev
1245 1248
1246 1249 for fn, state in util.sort(fstate.items()):
1247 1250 if fn in skip:
1248 1251 continue
1249 1252 if fn not in copies.get(prev[fn], {}):
1250 1253 found = display(fn, rev, {}, state) or found
1251 1254 return (not found and 1) or 0
1252 1255
1253 1256 def heads(ui, repo, *branchrevs, **opts):
1254 1257 """show current repository heads or show branch heads
1255 1258
1256 1259 With no arguments, show all repository head changesets.
1257 1260
1258 1261 If branch or revisions names are given this will show the heads of
1259 1262 the specified branches or the branches those revisions are tagged
1260 1263 with.
1261 1264
1262 1265 Repository "heads" are changesets that don't have child
1263 1266 changesets. They are where development generally takes place and
1264 1267 are the usual targets for update and merge operations.
1265 1268
1266 1269 Branch heads are changesets that have a given branch tag, but have
1267 1270 no child changesets with that tag. They are usually where
1268 1271 development on the given branch takes place.
1269 1272 """
1270 1273 if opts.get('rev'):
1271 1274 start = repo.lookup(opts['rev'])
1272 1275 else:
1273 1276 start = None
1274 1277 closed = not opts.get('active')
1275 1278 if not branchrevs:
1276 1279 # Assume we're looking repo-wide heads if no revs were specified.
1277 1280 heads = repo.heads(start, closed=closed)
1278 1281 else:
1279 1282 heads = []
1280 1283 visitedset = util.set()
1281 1284 for branchrev in branchrevs:
1282 1285 branch = repo[branchrev].branch()
1283 1286 if branch in visitedset:
1284 1287 continue
1285 1288 visitedset.add(branch)
1286 1289 bheads = repo.branchheads(branch, start, closed=closed)
1287 1290 if not bheads:
1288 1291 if branch != branchrev:
1289 1292 ui.warn(_("no changes on branch %s containing %s are "
1290 1293 "reachable from %s\n")
1291 1294 % (branch, branchrev, opts.get('rev')))
1292 1295 else:
1293 1296 ui.warn(_("no changes on branch %s are reachable from %s\n")
1294 1297 % (branch, opts.get('rev')))
1295 1298 heads.extend(bheads)
1296 1299 if not heads:
1297 1300 return 1
1298 1301 displayer = cmdutil.show_changeset(ui, repo, opts)
1299 1302 for n in heads:
1300 1303 displayer.show(repo[n])
1301 1304
1302 1305 def help_(ui, name=None, with_version=False):
1303 1306 """show help for a given topic or a help overview
1304 1307
1305 1308 With no arguments, print a list of commands and short help.
1306 1309
1307 1310 Given a topic, extension, or command name, print help for that topic."""
1308 1311 option_lists = []
1309 1312
1310 1313 def addglobalopts(aliases):
1311 1314 if ui.verbose:
1312 1315 option_lists.append((_("global options:"), globalopts))
1313 1316 if name == 'shortlist':
1314 1317 option_lists.append((_('use "hg help" for the full list '
1315 1318 'of commands'), ()))
1316 1319 else:
1317 1320 if name == 'shortlist':
1318 1321 msg = _('use "hg help" for the full list of commands '
1319 1322 'or "hg -v" for details')
1320 1323 elif aliases:
1321 1324 msg = _('use "hg -v help%s" to show aliases and '
1322 1325 'global options') % (name and " " + name or "")
1323 1326 else:
1324 1327 msg = _('use "hg -v help %s" to show global options') % name
1325 1328 option_lists.append((msg, ()))
1326 1329
1327 1330 def helpcmd(name):
1328 1331 if with_version:
1329 1332 version_(ui)
1330 1333 ui.write('\n')
1331 1334
1332 1335 try:
1333 1336 aliases, i = cmdutil.findcmd(name, table, False)
1334 1337 except error.AmbiguousCommand, inst:
1335 1338 select = lambda c: c.lstrip('^').startswith(inst.args[0])
1336 1339 helplist(_('list of commands:\n\n'), select)
1337 1340 return
1338 1341
1339 1342 # synopsis
1340 1343 if len(i) > 2:
1341 1344 if i[2].startswith('hg'):
1342 1345 ui.write("%s\n" % i[2])
1343 1346 else:
1344 1347 ui.write('hg %s %s\n' % (aliases[0], i[2]))
1345 1348 else:
1346 1349 ui.write('hg %s\n' % aliases[0])
1347 1350
1348 1351 # aliases
1349 1352 if not ui.quiet and len(aliases) > 1:
1350 1353 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1351 1354
1352 1355 # description
1353 1356 doc = gettext(i[0].__doc__)
1354 1357 if not doc:
1355 1358 doc = _("(no help text available)")
1356 1359 if ui.quiet:
1357 1360 doc = doc.splitlines(0)[0]
1358 1361 ui.write("\n%s\n" % doc.rstrip())
1359 1362
1360 1363 if not ui.quiet:
1361 1364 # options
1362 1365 if i[1]:
1363 1366 option_lists.append((_("options:\n"), i[1]))
1364 1367
1365 1368 addglobalopts(False)
1366 1369
1367 1370 def helplist(header, select=None):
1368 1371 h = {}
1369 1372 cmds = {}
1370 1373 for c, e in table.iteritems():
1371 1374 f = c.split("|", 1)[0]
1372 1375 if select and not select(f):
1373 1376 continue
1374 1377 if (not select and name != 'shortlist' and
1375 1378 e[0].__module__ != __name__):
1376 1379 continue
1377 1380 if name == "shortlist" and not f.startswith("^"):
1378 1381 continue
1379 1382 f = f.lstrip("^")
1380 1383 if not ui.debugflag and f.startswith("debug"):
1381 1384 continue
1382 1385 doc = gettext(e[0].__doc__)
1383 1386 if not doc:
1384 1387 doc = _("(no help text available)")
1385 1388 h[f] = doc.splitlines(0)[0].rstrip()
1386 1389 cmds[f] = c.lstrip("^")
1387 1390
1388 1391 if not h:
1389 1392 ui.status(_('no commands defined\n'))
1390 1393 return
1391 1394
1392 1395 ui.status(header)
1393 1396 fns = util.sort(h)
1394 1397 m = max(map(len, fns))
1395 1398 for f in fns:
1396 1399 if ui.verbose:
1397 1400 commands = cmds[f].replace("|",", ")
1398 1401 ui.write(" %s:\n %s\n"%(commands, h[f]))
1399 1402 else:
1400 1403 ui.write(' %-*s %s\n' % (m, f, h[f]))
1401 1404
1402 1405 exts = list(extensions.extensions())
1403 1406 if exts and name != 'shortlist':
1404 1407 ui.write(_('\nenabled extensions:\n\n'))
1405 1408 maxlength = 0
1406 1409 exthelps = []
1407 1410 for ename, ext in exts:
1408 1411 doc = (ext.__doc__ or _('(no help text available)'))
1409 1412 ename = ename.split('.')[-1]
1410 1413 maxlength = max(len(ename), maxlength)
1411 1414 exthelps.append((ename, doc.splitlines(0)[0].strip()))
1412 1415 for ename, text in exthelps:
1413 1416 ui.write(_(' %s %s\n') % (ename.ljust(maxlength), text))
1414 1417
1415 1418 if not ui.quiet:
1416 1419 addglobalopts(True)
1417 1420
1418 1421 def helptopic(name):
1419 1422 for names, header, doc in help.helptable:
1420 1423 if name in names:
1421 1424 break
1422 1425 else:
1423 1426 raise error.UnknownCommand(name)
1424 1427
1425 1428 # description
1426 1429 if not doc:
1427 1430 doc = _("(no help text available)")
1428 1431 if callable(doc):
1429 1432 doc = doc()
1430 1433
1431 1434 ui.write("%s\n" % header)
1432 1435 ui.write("%s\n" % doc.rstrip())
1433 1436
1434 1437 def helpext(name):
1435 1438 try:
1436 1439 mod = extensions.find(name)
1437 1440 except KeyError:
1438 1441 raise error.UnknownCommand(name)
1439 1442
1440 1443 doc = gettext(mod.__doc__) or _('no help text available')
1441 1444 doc = doc.splitlines(0)
1442 1445 ui.write(_('%s extension - %s\n') % (name.split('.')[-1], doc[0]))
1443 1446 for d in doc[1:]:
1444 1447 ui.write(d, '\n')
1445 1448
1446 1449 ui.status('\n')
1447 1450
1448 1451 try:
1449 1452 ct = mod.cmdtable
1450 1453 except AttributeError:
1451 1454 ct = {}
1452 1455
1453 1456 modcmds = dict.fromkeys([c.split('|', 1)[0] for c in ct])
1454 1457 helplist(_('list of commands:\n\n'), modcmds.has_key)
1455 1458
1456 1459 if name and name != 'shortlist':
1457 1460 i = None
1458 1461 for f in (helptopic, helpcmd, helpext):
1459 1462 try:
1460 1463 f(name)
1461 1464 i = None
1462 1465 break
1463 1466 except error.UnknownCommand, inst:
1464 1467 i = inst
1465 1468 if i:
1466 1469 raise i
1467 1470
1468 1471 else:
1469 1472 # program name
1470 1473 if ui.verbose or with_version:
1471 1474 version_(ui)
1472 1475 else:
1473 1476 ui.status(_("Mercurial Distributed SCM\n"))
1474 1477 ui.status('\n')
1475 1478
1476 1479 # list of commands
1477 1480 if name == "shortlist":
1478 1481 header = _('basic commands:\n\n')
1479 1482 else:
1480 1483 header = _('list of commands:\n\n')
1481 1484
1482 1485 helplist(header)
1483 1486
1484 1487 # list all option lists
1485 1488 opt_output = []
1486 1489 for title, options in option_lists:
1487 1490 opt_output.append(("\n%s" % title, None))
1488 1491 for shortopt, longopt, default, desc in options:
1489 1492 if "DEPRECATED" in desc and not ui.verbose: continue
1490 1493 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
1491 1494 longopt and " --%s" % longopt),
1492 1495 "%s%s" % (desc,
1493 1496 default
1494 1497 and _(" (default: %s)") % default
1495 1498 or "")))
1496 1499
1497 1500 if not name:
1498 1501 ui.write(_("\nadditional help topics:\n\n"))
1499 1502 topics = []
1500 1503 for names, header, doc in help.helptable:
1501 1504 names = [(-len(name), name) for name in names]
1502 1505 names.sort()
1503 1506 topics.append((names[0][1], header))
1504 1507 topics_len = max([len(s[0]) for s in topics])
1505 1508 for t, desc in topics:
1506 1509 ui.write(" %-*s %s\n" % (topics_len, t, desc))
1507 1510
1508 1511 if opt_output:
1509 1512 opts_len = max([len(line[0]) for line in opt_output if line[1]] or [0])
1510 1513 for first, second in opt_output:
1511 1514 if second:
1512 1515 ui.write(" %-*s %s\n" % (opts_len, first, second))
1513 1516 else:
1514 1517 ui.write("%s\n" % first)
1515 1518
1516 1519 def identify(ui, repo, source=None,
1517 1520 rev=None, num=None, id=None, branch=None, tags=None):
1518 1521 """identify the working copy or specified revision
1519 1522
1520 1523 With no revision, print a summary of the current state of the repo.
1521 1524
1522 1525 With a path, do a lookup in another repository.
1523 1526
1524 1527 This summary identifies the repository state using one or two parent
1525 1528 hash identifiers, followed by a "+" if there are uncommitted changes
1526 1529 in the working directory, a list of tags for this revision and a branch
1527 1530 name for non-default branches.
1528 1531 """
1529 1532
1530 1533 if not repo and not source:
1531 1534 raise util.Abort(_("There is no Mercurial repository here "
1532 1535 "(.hg not found)"))
1533 1536
1534 1537 hexfunc = ui.debugflag and hex or short
1535 1538 default = not (num or id or branch or tags)
1536 1539 output = []
1537 1540
1538 1541 if source:
1539 1542 source, revs, checkout = hg.parseurl(ui.expandpath(source), [])
1540 1543 srepo = hg.repository(ui, source)
1541 1544 if not rev and revs:
1542 1545 rev = revs[0]
1543 1546 if not rev:
1544 1547 rev = "tip"
1545 1548 if num or branch or tags:
1546 1549 raise util.Abort(
1547 1550 "can't query remote revision number, branch, or tags")
1548 1551 output = [hexfunc(srepo.lookup(rev))]
1549 1552 elif not rev:
1550 1553 ctx = repo[None]
1551 1554 parents = ctx.parents()
1552 1555 changed = False
1553 1556 if default or id or num:
1554 1557 changed = ctx.files() + ctx.deleted()
1555 1558 if default or id:
1556 1559 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
1557 1560 (changed) and "+" or "")]
1558 1561 if num:
1559 1562 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
1560 1563 (changed) and "+" or ""))
1561 1564 else:
1562 1565 ctx = repo[rev]
1563 1566 if default or id:
1564 1567 output = [hexfunc(ctx.node())]
1565 1568 if num:
1566 1569 output.append(str(ctx.rev()))
1567 1570
1568 1571 if not source and default and not ui.quiet:
1569 1572 b = util.tolocal(ctx.branch())
1570 1573 if b != 'default':
1571 1574 output.append("(%s)" % b)
1572 1575
1573 1576 # multiple tags for a single parent separated by '/'
1574 1577 t = "/".join(ctx.tags())
1575 1578 if t:
1576 1579 output.append(t)
1577 1580
1578 1581 if branch:
1579 1582 output.append(util.tolocal(ctx.branch()))
1580 1583
1581 1584 if tags:
1582 1585 output.extend(ctx.tags())
1583 1586
1584 1587 ui.write("%s\n" % ' '.join(output))
1585 1588
1586 1589 def import_(ui, repo, patch1, *patches, **opts):
1587 1590 """import an ordered set of patches
1588 1591
1589 1592 Import a list of patches and commit them individually.
1590 1593
1591 1594 If there are outstanding changes in the working directory, import
1592 1595 will abort unless given the -f flag.
1593 1596
1594 1597 You can import a patch straight from a mail message. Even patches
1595 1598 as attachments work (body part must be type text/plain or
1596 1599 text/x-patch to be used). From and Subject headers of email
1597 1600 message are used as default committer and commit message. All
1598 1601 text/plain body parts before first diff are added to commit
1599 1602 message.
1600 1603
1601 1604 If the imported patch was generated by hg export, user and description
1602 1605 from patch override values from message headers and body. Values
1603 1606 given on command line with -m and -u override these.
1604 1607
1605 1608 If --exact is specified, import will set the working directory
1606 1609 to the parent of each patch before applying it, and will abort
1607 1610 if the resulting changeset has a different ID than the one
1608 1611 recorded in the patch. This may happen due to character set
1609 1612 problems or other deficiencies in the text patch format.
1610 1613
1611 1614 With --similarity, hg will attempt to discover renames and copies
1612 1615 in the patch in the same way as 'addremove'.
1613 1616
1614 1617 To read a patch from standard input, use patch name "-".
1615 1618 See 'hg help dates' for a list of formats valid for -d/--date.
1616 1619 """
1617 1620 patches = (patch1,) + patches
1618 1621
1619 1622 date = opts.get('date')
1620 1623 if date:
1621 1624 opts['date'] = util.parsedate(date)
1622 1625
1623 1626 try:
1624 1627 sim = float(opts.get('similarity') or 0)
1625 1628 except ValueError:
1626 1629 raise util.Abort(_('similarity must be a number'))
1627 1630 if sim < 0 or sim > 100:
1628 1631 raise util.Abort(_('similarity must be between 0 and 100'))
1629 1632
1630 1633 if opts.get('exact') or not opts.get('force'):
1631 1634 cmdutil.bail_if_changed(repo)
1632 1635
1633 1636 d = opts["base"]
1634 1637 strip = opts["strip"]
1635 1638 wlock = lock = None
1636 1639 try:
1637 1640 wlock = repo.wlock()
1638 1641 lock = repo.lock()
1639 1642 for p in patches:
1640 1643 pf = os.path.join(d, p)
1641 1644
1642 1645 if pf == '-':
1643 1646 ui.status(_("applying patch from stdin\n"))
1644 1647 pf = sys.stdin
1645 1648 else:
1646 1649 ui.status(_("applying %s\n") % p)
1647 1650 pf = url.open(ui, pf)
1648 1651 data = patch.extract(ui, pf)
1649 1652 tmpname, message, user, date, branch, nodeid, p1, p2 = data
1650 1653
1651 1654 if tmpname is None:
1652 1655 raise util.Abort(_('no diffs found'))
1653 1656
1654 1657 try:
1655 1658 cmdline_message = cmdutil.logmessage(opts)
1656 1659 if cmdline_message:
1657 1660 # pickup the cmdline msg
1658 1661 message = cmdline_message
1659 1662 elif message:
1660 1663 # pickup the patch msg
1661 1664 message = message.strip()
1662 1665 else:
1663 1666 # launch the editor
1664 1667 message = None
1665 1668 ui.debug(_('message:\n%s\n') % message)
1666 1669
1667 1670 wp = repo.parents()
1668 1671 if opts.get('exact'):
1669 1672 if not nodeid or not p1:
1670 1673 raise util.Abort(_('not a mercurial patch'))
1671 1674 p1 = repo.lookup(p1)
1672 1675 p2 = repo.lookup(p2 or hex(nullid))
1673 1676
1674 1677 if p1 != wp[0].node():
1675 1678 hg.clean(repo, p1)
1676 1679 repo.dirstate.setparents(p1, p2)
1677 1680 elif p2:
1678 1681 try:
1679 1682 p1 = repo.lookup(p1)
1680 1683 p2 = repo.lookup(p2)
1681 1684 if p1 == wp[0].node():
1682 1685 repo.dirstate.setparents(p1, p2)
1683 1686 except error.RepoError:
1684 1687 pass
1685 1688 if opts.get('exact') or opts.get('import_branch'):
1686 1689 repo.dirstate.setbranch(branch or 'default')
1687 1690
1688 1691 files = {}
1689 1692 try:
1690 1693 fuzz = patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
1691 1694 files=files)
1692 1695 finally:
1693 1696 files = patch.updatedir(ui, repo, files, similarity=sim/100.)
1694 1697 if not opts.get('no_commit'):
1695 1698 n = repo.commit(files, message, opts.get('user') or user,
1696 1699 opts.get('date') or date)
1697 1700 if opts.get('exact'):
1698 1701 if hex(n) != nodeid:
1699 1702 repo.rollback()
1700 1703 raise util.Abort(_('patch is damaged'
1701 1704 ' or loses information'))
1702 1705 # Force a dirstate write so that the next transaction
1703 1706 # backups an up-do-date file.
1704 1707 repo.dirstate.write()
1705 1708 finally:
1706 1709 os.unlink(tmpname)
1707 1710 finally:
1708 1711 del lock, wlock
1709 1712
1710 1713 def incoming(ui, repo, source="default", **opts):
1711 1714 """show new changesets found in source
1712 1715
1713 1716 Show new changesets found in the specified path/URL or the default
1714 1717 pull location. These are the changesets that would be pulled if a pull
1715 1718 was requested.
1716 1719
1717 1720 For remote repository, using --bundle avoids downloading the changesets
1718 1721 twice if the incoming is followed by a pull.
1719 1722
1720 1723 See pull for valid source format details.
1721 1724 """
1722 1725 limit = cmdutil.loglimit(opts)
1723 1726 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
1724 1727 cmdutil.setremoteconfig(ui, opts)
1725 1728
1726 1729 other = hg.repository(ui, source)
1727 1730 ui.status(_('comparing with %s\n') % url.hidepassword(source))
1728 1731 if revs:
1729 1732 revs = [other.lookup(rev) for rev in revs]
1730 1733 common, incoming, rheads = repo.findcommonincoming(other, heads=revs,
1731 1734 force=opts["force"])
1732 1735 if not incoming:
1733 1736 try:
1734 1737 os.unlink(opts["bundle"])
1735 1738 except:
1736 1739 pass
1737 1740 ui.status(_("no changes found\n"))
1738 1741 return 1
1739 1742
1740 1743 cleanup = None
1741 1744 try:
1742 1745 fname = opts["bundle"]
1743 1746 if fname or not other.local():
1744 1747 # create a bundle (uncompressed if other repo is not local)
1745 1748
1746 1749 if revs is None and other.capable('changegroupsubset'):
1747 1750 revs = rheads
1748 1751
1749 1752 if revs is None:
1750 1753 cg = other.changegroup(incoming, "incoming")
1751 1754 else:
1752 1755 cg = other.changegroupsubset(incoming, revs, 'incoming')
1753 1756 bundletype = other.local() and "HG10BZ" or "HG10UN"
1754 1757 fname = cleanup = changegroup.writebundle(cg, fname, bundletype)
1755 1758 # keep written bundle?
1756 1759 if opts["bundle"]:
1757 1760 cleanup = None
1758 1761 if not other.local():
1759 1762 # use the created uncompressed bundlerepo
1760 1763 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1761 1764
1762 1765 o = other.changelog.nodesbetween(incoming, revs)[0]
1763 1766 if opts.get('newest_first'):
1764 1767 o.reverse()
1765 1768 displayer = cmdutil.show_changeset(ui, other, opts)
1766 1769 count = 0
1767 1770 for n in o:
1768 1771 if count >= limit:
1769 1772 break
1770 1773 parents = [p for p in other.changelog.parents(n) if p != nullid]
1771 1774 if opts.get('no_merges') and len(parents) == 2:
1772 1775 continue
1773 1776 count += 1
1774 1777 displayer.show(other[n])
1775 1778 finally:
1776 1779 if hasattr(other, 'close'):
1777 1780 other.close()
1778 1781 if cleanup:
1779 1782 os.unlink(cleanup)
1780 1783
1781 1784 def init(ui, dest=".", **opts):
1782 1785 """create a new repository in the given directory
1783 1786
1784 1787 Initialize a new repository in the given directory. If the given
1785 1788 directory does not exist, it is created.
1786 1789
1787 1790 If no directory is given, the current directory is used.
1788 1791
1789 1792 It is possible to specify an ssh:// URL as the destination.
1790 1793 See 'hg help urls' for more information.
1791 1794 """
1792 1795 cmdutil.setremoteconfig(ui, opts)
1793 1796 hg.repository(ui, dest, create=1)
1794 1797
1795 1798 def locate(ui, repo, *pats, **opts):
1796 1799 """locate files matching specific patterns
1797 1800
1798 1801 Print all files under Mercurial control whose names match the
1799 1802 given patterns.
1800 1803
1801 1804 This command searches the entire repository by default. To search
1802 1805 just the current directory and its subdirectories, use
1803 1806 "--include .".
1804 1807
1805 1808 If no patterns are given to match, this command prints all file
1806 1809 names.
1807 1810
1808 1811 If you want to feed the output of this command into the "xargs"
1809 1812 command, use the "-0" option to both this command and "xargs".
1810 1813 This will avoid the problem of "xargs" treating single filenames
1811 1814 that contain white space as multiple filenames.
1812 1815 """
1813 1816 end = opts.get('print0') and '\0' or '\n'
1814 1817 rev = opts.get('rev') or None
1815 1818
1816 1819 ret = 1
1817 1820 m = cmdutil.match(repo, pats, opts, default='relglob')
1818 1821 m.bad = lambda x,y: False
1819 1822 for abs in repo[rev].walk(m):
1820 1823 if not rev and abs not in repo.dirstate:
1821 1824 continue
1822 1825 if opts.get('fullpath'):
1823 1826 ui.write(repo.wjoin(abs), end)
1824 1827 else:
1825 1828 ui.write(((pats and m.rel(abs)) or abs), end)
1826 1829 ret = 0
1827 1830
1828 1831 return ret
1829 1832
1830 1833 def log(ui, repo, *pats, **opts):
1831 1834 """show revision history of entire repository or files
1832 1835
1833 1836 Print the revision history of the specified files or the entire
1834 1837 project.
1835 1838
1836 1839 File history is shown without following rename or copy history of
1837 1840 files. Use -f/--follow with a file name to follow history across
1838 1841 renames and copies. --follow without a file name will only show
1839 1842 ancestors or descendants of the starting revision. --follow-first
1840 1843 only follows the first parent of merge revisions.
1841 1844
1842 1845 If no revision range is specified, the default is tip:0 unless
1843 1846 --follow is set, in which case the working directory parent is
1844 1847 used as the starting revision.
1845 1848
1846 1849 See 'hg help dates' for a list of formats valid for -d/--date.
1847 1850
1848 1851 By default this command outputs: changeset id and hash, tags,
1849 1852 non-trivial parents, user, date and time, and a summary for each
1850 1853 commit. When the -v/--verbose switch is used, the list of changed
1851 1854 files and full commit message is shown.
1852 1855
1853 1856 NOTE: log -p may generate unexpected diff output for merge
1854 1857 changesets, as it will compare the merge changeset against its
1855 1858 first parent only. Also, the files: list will only reflect files
1856 1859 that are different from BOTH parents.
1857 1860
1858 1861 """
1859 1862
1860 1863 get = util.cachefunc(lambda r: repo[r].changeset())
1861 1864 changeiter, matchfn = cmdutil.walkchangerevs(ui, repo, pats, get, opts)
1862 1865
1863 1866 limit = cmdutil.loglimit(opts)
1864 1867 count = 0
1865 1868
1866 1869 if opts.get('copies') and opts.get('rev'):
1867 1870 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
1868 1871 else:
1869 1872 endrev = len(repo)
1870 1873 rcache = {}
1871 1874 ncache = {}
1872 1875 def getrenamed(fn, rev):
1873 1876 '''looks up all renames for a file (up to endrev) the first
1874 1877 time the file is given. It indexes on the changerev and only
1875 1878 parses the manifest if linkrev != changerev.
1876 1879 Returns rename info for fn at changerev rev.'''
1877 1880 if fn not in rcache:
1878 1881 rcache[fn] = {}
1879 1882 ncache[fn] = {}
1880 1883 fl = repo.file(fn)
1881 1884 for i in fl:
1882 1885 node = fl.node(i)
1883 1886 lr = fl.linkrev(i)
1884 1887 renamed = fl.renamed(node)
1885 1888 rcache[fn][lr] = renamed
1886 1889 if renamed:
1887 1890 ncache[fn][node] = renamed
1888 1891 if lr >= endrev:
1889 1892 break
1890 1893 if rev in rcache[fn]:
1891 1894 return rcache[fn][rev]
1892 1895
1893 1896 # If linkrev != rev (i.e. rev not found in rcache) fallback to
1894 1897 # filectx logic.
1895 1898
1896 1899 try:
1897 1900 return repo[rev][fn].renamed()
1898 1901 except error.LookupError:
1899 1902 pass
1900 1903 return None
1901 1904
1902 1905 df = False
1903 1906 if opts["date"]:
1904 1907 df = util.matchdate(opts["date"])
1905 1908
1906 1909 only_branches = opts.get('only_branch')
1907 1910
1908 1911 displayer = cmdutil.show_changeset(ui, repo, opts, True, matchfn)
1909 1912 for st, rev, fns in changeiter:
1910 1913 if st == 'add':
1911 1914 parents = [p for p in repo.changelog.parentrevs(rev)
1912 1915 if p != nullrev]
1913 1916 if opts.get('no_merges') and len(parents) == 2:
1914 1917 continue
1915 1918 if opts.get('only_merges') and len(parents) != 2:
1916 1919 continue
1917 1920
1918 1921 if only_branches:
1919 1922 revbranch = get(rev)[5]['branch']
1920 1923 if revbranch not in only_branches:
1921 1924 continue
1922 1925
1923 1926 if df:
1924 1927 changes = get(rev)
1925 1928 if not df(changes[2][0]):
1926 1929 continue
1927 1930
1928 1931 if opts.get('keyword'):
1929 1932 changes = get(rev)
1930 1933 miss = 0
1931 1934 for k in [kw.lower() for kw in opts['keyword']]:
1932 1935 if not (k in changes[1].lower() or
1933 1936 k in changes[4].lower() or
1934 1937 k in " ".join(changes[3]).lower()):
1935 1938 miss = 1
1936 1939 break
1937 1940 if miss:
1938 1941 continue
1939 1942
1940 1943 if opts['user']:
1941 1944 changes = get(rev)
1942 1945 miss = 0
1943 1946 for k in opts['user']:
1944 1947 if k != changes[1]:
1945 1948 miss = 1
1946 1949 break
1947 1950 if miss:
1948 1951 continue
1949 1952
1950 1953 copies = []
1951 1954 if opts.get('copies') and rev:
1952 1955 for fn in get(rev)[3]:
1953 1956 rename = getrenamed(fn, rev)
1954 1957 if rename:
1955 1958 copies.append((fn, rename[0]))
1956 1959 displayer.show(context.changectx(repo, rev), copies=copies)
1957 1960 elif st == 'iter':
1958 1961 if count == limit: break
1959 1962 if displayer.flush(rev):
1960 1963 count += 1
1961 1964
1962 1965 def manifest(ui, repo, node=None, rev=None):
1963 1966 """output the current or given revision of the project manifest
1964 1967
1965 1968 Print a list of version controlled files for the given revision.
1966 1969 If no revision is given, the parent of the working directory is used,
1967 1970 or tip if no revision is checked out.
1968 1971
1969 1972 The manifest is the list of files being version controlled. If no revision
1970 1973 is given then the first parent of the working directory is used.
1971 1974
1972 1975 With -v flag, print file permissions, symlink and executable bits. With
1973 1976 --debug flag, print file revision hashes.
1974 1977 """
1975 1978
1976 1979 if rev and node:
1977 1980 raise util.Abort(_("please specify just one revision"))
1978 1981
1979 1982 if not node:
1980 1983 node = rev
1981 1984
1982 1985 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
1983 1986 ctx = repo[node]
1984 1987 for f in ctx:
1985 1988 if ui.debugflag:
1986 1989 ui.write("%40s " % hex(ctx.manifest()[f]))
1987 1990 if ui.verbose:
1988 1991 ui.write(decor[ctx.flags(f)])
1989 1992 ui.write("%s\n" % f)
1990 1993
1991 1994 def merge(ui, repo, node=None, force=None, rev=None):
1992 1995 """merge working directory with another revision
1993 1996
1994 1997 Merge the contents of the current working directory and the
1995 1998 requested revision. Files that changed between either parent are
1996 1999 marked as changed for the next commit and a commit must be
1997 2000 performed before any further updates are allowed.
1998 2001
1999 2002 If no revision is specified, the working directory's parent is a
2000 2003 head revision, and the current branch contains exactly one other head,
2001 2004 the other head is merged with by default. Otherwise, an explicit
2002 2005 revision to merge with must be provided.
2003 2006 """
2004 2007
2005 2008 if rev and node:
2006 2009 raise util.Abort(_("please specify just one revision"))
2007 2010 if not node:
2008 2011 node = rev
2009 2012
2010 2013 if not node:
2011 2014 branch = repo.changectx(None).branch()
2012 2015 bheads = repo.branchheads(branch)
2013 2016 if len(bheads) > 2:
2014 2017 raise util.Abort(_("branch '%s' has %d heads - "
2015 2018 "please merge with an explicit rev") %
2016 2019 (branch, len(bheads)))
2017 2020
2018 2021 parent = repo.dirstate.parents()[0]
2019 2022 if len(bheads) == 1:
2020 2023 if len(repo.heads()) > 1:
2021 2024 raise util.Abort(_("branch '%s' has one head - "
2022 2025 "please merge with an explicit rev") %
2023 2026 branch)
2024 2027 msg = _('there is nothing to merge')
2025 2028 if parent != repo.lookup(repo[None].branch()):
2026 2029 msg = _('%s - use "hg update" instead') % msg
2027 2030 raise util.Abort(msg)
2028 2031
2029 2032 if parent not in bheads:
2030 2033 raise util.Abort(_('working dir not at a head rev - '
2031 2034 'use "hg update" or merge with an explicit rev'))
2032 2035 node = parent == bheads[0] and bheads[-1] or bheads[0]
2033 2036 return hg.merge(repo, node, force=force)
2034 2037
2035 2038 def outgoing(ui, repo, dest=None, **opts):
2036 2039 """show changesets not found in destination
2037 2040
2038 2041 Show changesets not found in the specified destination repository or
2039 2042 the default push location. These are the changesets that would be pushed
2040 2043 if a push was requested.
2041 2044
2042 2045 See pull for valid destination format details.
2043 2046 """
2044 2047 limit = cmdutil.loglimit(opts)
2045 2048 dest, revs, checkout = hg.parseurl(
2046 2049 ui.expandpath(dest or 'default-push', dest or 'default'), opts.get('rev'))
2047 2050 cmdutil.setremoteconfig(ui, opts)
2048 2051 if revs:
2049 2052 revs = [repo.lookup(rev) for rev in revs]
2050 2053
2051 2054 other = hg.repository(ui, dest)
2052 2055 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2053 2056 o = repo.findoutgoing(other, force=opts.get('force'))
2054 2057 if not o:
2055 2058 ui.status(_("no changes found\n"))
2056 2059 return 1
2057 2060 o = repo.changelog.nodesbetween(o, revs)[0]
2058 2061 if opts.get('newest_first'):
2059 2062 o.reverse()
2060 2063 displayer = cmdutil.show_changeset(ui, repo, opts)
2061 2064 count = 0
2062 2065 for n in o:
2063 2066 if count >= limit:
2064 2067 break
2065 2068 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2066 2069 if opts.get('no_merges') and len(parents) == 2:
2067 2070 continue
2068 2071 count += 1
2069 2072 displayer.show(repo[n])
2070 2073
2071 2074 def parents(ui, repo, file_=None, **opts):
2072 2075 """show the parents of the working dir or revision
2073 2076
2074 2077 Print the working directory's parent revisions. If a
2075 2078 revision is given via --rev, the parent of that revision
2076 2079 will be printed. If a file argument is given, revision in
2077 2080 which the file was last changed (before the working directory
2078 2081 revision or the argument to --rev if given) is printed.
2079 2082 """
2080 2083 rev = opts.get('rev')
2081 2084 if rev:
2082 2085 ctx = repo[rev]
2083 2086 else:
2084 2087 ctx = repo[None]
2085 2088
2086 2089 if file_:
2087 2090 m = cmdutil.match(repo, (file_,), opts)
2088 2091 if m.anypats() or len(m.files()) != 1:
2089 2092 raise util.Abort(_('can only specify an explicit file name'))
2090 2093 file_ = m.files()[0]
2091 2094 filenodes = []
2092 2095 for cp in ctx.parents():
2093 2096 if not cp:
2094 2097 continue
2095 2098 try:
2096 2099 filenodes.append(cp.filenode(file_))
2097 2100 except error.LookupError:
2098 2101 pass
2099 2102 if not filenodes:
2100 2103 raise util.Abort(_("'%s' not found in manifest!") % file_)
2101 2104 fl = repo.file(file_)
2102 2105 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2103 2106 else:
2104 2107 p = [cp.node() for cp in ctx.parents()]
2105 2108
2106 2109 displayer = cmdutil.show_changeset(ui, repo, opts)
2107 2110 for n in p:
2108 2111 if n != nullid:
2109 2112 displayer.show(repo[n])
2110 2113
2111 2114 def paths(ui, repo, search=None):
2112 2115 """show aliases for remote repositories
2113 2116
2114 2117 Show definition of symbolic path name NAME. If no name is given, show
2115 2118 definition of available names.
2116 2119 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2117 2120 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2118 2121
2119 2122 See 'hg help urls' for more information.
2120 2123 """
2121 2124 if search:
2122 2125 for name, path in ui.configitems("paths"):
2123 2126 if name == search:
2124 2127 ui.write("%s\n" % url.hidepassword(path))
2125 2128 return
2126 2129 ui.warn(_("not found!\n"))
2127 2130 return 1
2128 2131 else:
2129 2132 for name, path in ui.configitems("paths"):
2130 2133 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2131 2134
2132 2135 def postincoming(ui, repo, modheads, optupdate, checkout):
2133 2136 if modheads == 0:
2134 2137 return
2135 2138 if optupdate:
2136 2139 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2137 2140 return hg.update(repo, checkout)
2138 2141 else:
2139 2142 ui.status(_("not updating, since new heads added\n"))
2140 2143 if modheads > 1:
2141 2144 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2142 2145 else:
2143 2146 ui.status(_("(run 'hg update' to get a working copy)\n"))
2144 2147
2145 2148 def pull(ui, repo, source="default", **opts):
2146 2149 """pull changes from the specified source
2147 2150
2148 2151 Pull changes from a remote repository to a local one.
2149 2152
2150 2153 This finds all changes from the repository at the specified path
2151 2154 or URL and adds them to the local repository. By default, this
2152 2155 does not update the copy of the project in the working directory.
2153 2156
2154 2157 If SOURCE is omitted, the 'default' path will be used.
2155 2158 See 'hg help urls' for more information.
2156 2159 """
2157 2160 source, revs, checkout = hg.parseurl(ui.expandpath(source), opts.get('rev'))
2158 2161 cmdutil.setremoteconfig(ui, opts)
2159 2162
2160 2163 other = hg.repository(ui, source)
2161 2164 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2162 2165 if revs:
2163 2166 try:
2164 2167 revs = [other.lookup(rev) for rev in revs]
2165 2168 except error.CapabilityError:
2166 2169 err = _("Other repository doesn't support revision lookup, "
2167 2170 "so a rev cannot be specified.")
2168 2171 raise util.Abort(err)
2169 2172
2170 2173 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2171 2174 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2172 2175
2173 2176 def push(ui, repo, dest=None, **opts):
2174 2177 """push changes to the specified destination
2175 2178
2176 2179 Push changes from the local repository to the given destination.
2177 2180
2178 2181 This is the symmetrical operation for pull. It helps to move
2179 2182 changes from the current repository to a different one. If the
2180 2183 destination is local this is identical to a pull in that directory
2181 2184 from the current one.
2182 2185
2183 2186 By default, push will refuse to run if it detects the result would
2184 2187 increase the number of remote heads. This generally indicates the
2185 2188 the client has forgotten to pull and merge before pushing.
2186 2189
2187 2190 If -r is used, the named changeset and all its ancestors will be pushed
2188 2191 to the remote repository.
2189 2192
2190 2193 Look at the help text for urls for important details about ssh:// URLs.
2191 2194 If DESTINATION is omitted, a default path will be used.
2192 2195 See 'hg help urls' for more information.
2193 2196 """
2194 2197 dest, revs, checkout = hg.parseurl(
2195 2198 ui.expandpath(dest or 'default-push', dest or 'default'), opts.get('rev'))
2196 2199 cmdutil.setremoteconfig(ui, opts)
2197 2200
2198 2201 other = hg.repository(ui, dest)
2199 2202 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2200 2203 if revs:
2201 2204 revs = [repo.lookup(rev) for rev in revs]
2202 2205 r = repo.push(other, opts.get('force'), revs=revs)
2203 2206 return r == 0
2204 2207
2205 2208 def rawcommit(ui, repo, *pats, **opts):
2206 2209 """raw commit interface (DEPRECATED)
2207 2210
2208 2211 (DEPRECATED)
2209 2212 Lowlevel commit, for use in helper scripts.
2210 2213
2211 2214 This command is not intended to be used by normal users, as it is
2212 2215 primarily useful for importing from other SCMs.
2213 2216
2214 2217 This command is now deprecated and will be removed in a future
2215 2218 release, please use debugsetparents and commit instead.
2216 2219 """
2217 2220
2218 2221 ui.warn(_("(the rawcommit command is deprecated)\n"))
2219 2222
2220 2223 message = cmdutil.logmessage(opts)
2221 2224
2222 2225 files = cmdutil.match(repo, pats, opts).files()
2223 2226 if opts.get('files'):
2224 2227 files += open(opts['files']).read().splitlines()
2225 2228
2226 2229 parents = [repo.lookup(p) for p in opts['parent']]
2227 2230
2228 2231 try:
2229 2232 repo.rawcommit(files, message, opts['user'], opts['date'], *parents)
2230 2233 except ValueError, inst:
2231 2234 raise util.Abort(str(inst))
2232 2235
2233 2236 def recover(ui, repo):
2234 2237 """roll back an interrupted transaction
2235 2238
2236 2239 Recover from an interrupted commit or pull.
2237 2240
2238 2241 This command tries to fix the repository status after an interrupted
2239 2242 operation. It should only be necessary when Mercurial suggests it.
2240 2243 """
2241 2244 if repo.recover():
2242 2245 return hg.verify(repo)
2243 2246 return 1
2244 2247
2245 2248 def remove(ui, repo, *pats, **opts):
2246 2249 """remove the specified files on the next commit
2247 2250
2248 2251 Schedule the indicated files for removal from the repository.
2249 2252
2250 2253 This only removes files from the current branch, not from the entire
2251 2254 project history. -A can be used to remove only files that have already
2252 2255 been deleted, -f can be used to force deletion, and -Af can be used
2253 2256 to remove files from the next revision without deleting them.
2254 2257
2255 2258 The following table details the behavior of remove for different file
2256 2259 states (columns) and option combinations (rows). The file states are
2257 2260 Added, Clean, Modified and Missing (as reported by hg status). The
2258 2261 actions are Warn, Remove (from branch) and Delete (from disk).
2259 2262
2260 2263 A C M !
2261 2264 none W RD W R
2262 2265 -f R RD RD R
2263 2266 -A W W W R
2264 2267 -Af R R R R
2265 2268
2266 2269 This command schedules the files to be removed at the next commit.
2267 2270 To undo a remove before that, see hg revert.
2268 2271 """
2269 2272
2270 2273 after, force = opts.get('after'), opts.get('force')
2271 2274 if not pats and not after:
2272 2275 raise util.Abort(_('no files specified'))
2273 2276
2274 2277 m = cmdutil.match(repo, pats, opts)
2275 2278 s = repo.status(match=m, clean=True)
2276 2279 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2277 2280
2278 2281 def warn(files, reason):
2279 2282 for f in files:
2280 2283 ui.warn(_('not removing %s: file %s (use -f to force removal)\n')
2281 2284 % (m.rel(f), reason))
2282 2285
2283 2286 if force:
2284 2287 remove, forget = modified + deleted + clean, added
2285 2288 elif after:
2286 2289 remove, forget = deleted, []
2287 2290 warn(modified + added + clean, _('still exists'))
2288 2291 else:
2289 2292 remove, forget = deleted + clean, []
2290 2293 warn(modified, _('is modified'))
2291 2294 warn(added, _('has been marked for add'))
2292 2295
2293 2296 for f in util.sort(remove + forget):
2294 2297 if ui.verbose or not m.exact(f):
2295 2298 ui.status(_('removing %s\n') % m.rel(f))
2296 2299
2297 2300 repo.forget(forget)
2298 2301 repo.remove(remove, unlink=not after)
2299 2302
2300 2303 def rename(ui, repo, *pats, **opts):
2301 2304 """rename files; equivalent of copy + remove
2302 2305
2303 2306 Mark dest as copies of sources; mark sources for deletion. If
2304 2307 dest is a directory, copies are put in that directory. If dest is
2305 2308 a file, there can only be one source.
2306 2309
2307 2310 By default, this command copies the contents of files as they
2308 2311 stand in the working directory. If invoked with --after, the
2309 2312 operation is recorded, but no copying is performed.
2310 2313
2311 2314 This command takes effect in the next commit. To undo a rename
2312 2315 before that, see hg revert.
2313 2316 """
2314 2317 wlock = repo.wlock(False)
2315 2318 try:
2316 2319 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2317 2320 finally:
2318 2321 del wlock
2319 2322
2320 2323 def resolve(ui, repo, *pats, **opts):
2321 2324 """retry file merges from a merge or update
2322 2325
2323 2326 This command will cleanly retry unresolved file merges using file
2324 2327 revisions preserved from the last update or merge. To attempt to
2325 2328 resolve all unresolved files, use the -a switch.
2326 2329
2327 2330 This command will also allow listing resolved files and manually
2328 2331 marking and unmarking files as resolved.
2329 2332
2330 2333 The codes used to show the status of files are:
2331 2334 U = unresolved
2332 2335 R = resolved
2333 2336 """
2334 2337
2335 2338 all, mark, unmark, show = [opts.get(o) for o in 'all mark unmark list'.split()]
2336 2339
2337 2340 if (show and (mark or unmark)) or (mark and unmark):
2338 2341 raise util.Abort(_("too many options specified"))
2339 2342 if pats and all:
2340 2343 raise util.Abort(_("can't specify --all and patterns"))
2341 2344 if not (all or pats or show or mark or unmark):
2342 2345 raise util.Abort(_('no files or directories specified; '
2343 2346 'use --all to remerge all files'))
2344 2347
2345 2348 ms = merge_.mergestate(repo)
2346 2349 m = cmdutil.match(repo, pats, opts)
2347 2350
2348 2351 for f in ms:
2349 2352 if m(f):
2350 2353 if show:
2351 2354 ui.write("%s %s\n" % (ms[f].upper(), f))
2352 2355 elif mark:
2353 2356 ms.mark(f, "r")
2354 2357 elif unmark:
2355 2358 ms.mark(f, "u")
2356 2359 else:
2357 2360 wctx = repo[None]
2358 2361 mctx = wctx.parents()[-1]
2359 2362 ms.resolve(f, wctx, mctx)
2360 2363
2361 2364 def revert(ui, repo, *pats, **opts):
2362 2365 """restore individual files or dirs to an earlier state
2363 2366
2364 2367 (use update -r to check out earlier revisions, revert does not
2365 2368 change the working dir parents)
2366 2369
2367 2370 With no revision specified, revert the named files or directories
2368 2371 to the contents they had in the parent of the working directory.
2369 2372 This restores the contents of the affected files to an unmodified
2370 2373 state and unschedules adds, removes, copies, and renames. If the
2371 2374 working directory has two parents, you must explicitly specify the
2372 2375 revision to revert to.
2373 2376
2374 2377 Using the -r option, revert the given files or directories to their
2375 2378 contents as of a specific revision. This can be helpful to "roll
2376 2379 back" some or all of an earlier change.
2377 2380 See 'hg help dates' for a list of formats valid for -d/--date.
2378 2381
2379 2382 Revert modifies the working directory. It does not commit any
2380 2383 changes, or change the parent of the working directory. If you
2381 2384 revert to a revision other than the parent of the working
2382 2385 directory, the reverted files will thus appear modified
2383 2386 afterwards.
2384 2387
2385 2388 If a file has been deleted, it is restored. If the executable
2386 2389 mode of a file was changed, it is reset.
2387 2390
2388 2391 If names are given, all files matching the names are reverted.
2389 2392 If no arguments are given, no files are reverted.
2390 2393
2391 2394 Modified files are saved with a .orig suffix before reverting.
2392 2395 To disable these backups, use --no-backup.
2393 2396 """
2394 2397
2395 2398 if opts["date"]:
2396 2399 if opts["rev"]:
2397 2400 raise util.Abort(_("you can't specify a revision and a date"))
2398 2401 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
2399 2402
2400 2403 if not pats and not opts.get('all'):
2401 2404 raise util.Abort(_('no files or directories specified; '
2402 2405 'use --all to revert the whole repo'))
2403 2406
2404 2407 parent, p2 = repo.dirstate.parents()
2405 2408 if not opts.get('rev') and p2 != nullid:
2406 2409 raise util.Abort(_('uncommitted merge - please provide a '
2407 2410 'specific revision'))
2408 2411 ctx = repo[opts.get('rev')]
2409 2412 node = ctx.node()
2410 2413 mf = ctx.manifest()
2411 2414 if node == parent:
2412 2415 pmf = mf
2413 2416 else:
2414 2417 pmf = None
2415 2418
2416 2419 # need all matching names in dirstate and manifest of target rev,
2417 2420 # so have to walk both. do not print errors if files exist in one
2418 2421 # but not other.
2419 2422
2420 2423 names = {}
2421 2424
2422 2425 wlock = repo.wlock()
2423 2426 try:
2424 2427 # walk dirstate.
2425 2428 files = []
2426 2429
2427 2430 m = cmdutil.match(repo, pats, opts)
2428 2431 m.bad = lambda x,y: False
2429 2432 for abs in repo.walk(m):
2430 2433 names[abs] = m.rel(abs), m.exact(abs)
2431 2434
2432 2435 # walk target manifest.
2433 2436
2434 2437 def badfn(path, msg):
2435 2438 if path in names:
2436 2439 return False
2437 2440 path_ = path + '/'
2438 2441 for f in names:
2439 2442 if f.startswith(path_):
2440 2443 return False
2441 2444 repo.ui.warn("%s: %s\n" % (m.rel(path), msg))
2442 2445 return False
2443 2446
2444 2447 m = cmdutil.match(repo, pats, opts)
2445 2448 m.bad = badfn
2446 2449 for abs in repo[node].walk(m):
2447 2450 if abs not in names:
2448 2451 names[abs] = m.rel(abs), m.exact(abs)
2449 2452
2450 2453 m = cmdutil.matchfiles(repo, names)
2451 2454 changes = repo.status(match=m)[:4]
2452 2455 modified, added, removed, deleted = map(dict.fromkeys, changes)
2453 2456
2454 2457 # if f is a rename, also revert the source
2455 2458 cwd = repo.getcwd()
2456 2459 for f in added:
2457 2460 src = repo.dirstate.copied(f)
2458 2461 if src and src not in names and repo.dirstate[src] == 'r':
2459 2462 removed[src] = None
2460 2463 names[src] = (repo.pathto(src, cwd), True)
2461 2464
2462 2465 def removeforget(abs):
2463 2466 if repo.dirstate[abs] == 'a':
2464 2467 return _('forgetting %s\n')
2465 2468 return _('removing %s\n')
2466 2469
2467 2470 revert = ([], _('reverting %s\n'))
2468 2471 add = ([], _('adding %s\n'))
2469 2472 remove = ([], removeforget)
2470 2473 undelete = ([], _('undeleting %s\n'))
2471 2474
2472 2475 disptable = (
2473 2476 # dispatch table:
2474 2477 # file state
2475 2478 # action if in target manifest
2476 2479 # action if not in target manifest
2477 2480 # make backup if in target manifest
2478 2481 # make backup if not in target manifest
2479 2482 (modified, revert, remove, True, True),
2480 2483 (added, revert, remove, True, False),
2481 2484 (removed, undelete, None, False, False),
2482 2485 (deleted, revert, remove, False, False),
2483 2486 )
2484 2487
2485 2488 for abs, (rel, exact) in util.sort(names.items()):
2486 2489 mfentry = mf.get(abs)
2487 2490 target = repo.wjoin(abs)
2488 2491 def handle(xlist, dobackup):
2489 2492 xlist[0].append(abs)
2490 2493 if dobackup and not opts.get('no_backup') and util.lexists(target):
2491 2494 bakname = "%s.orig" % rel
2492 2495 ui.note(_('saving current version of %s as %s\n') %
2493 2496 (rel, bakname))
2494 2497 if not opts.get('dry_run'):
2495 2498 util.copyfile(target, bakname)
2496 2499 if ui.verbose or not exact:
2497 2500 msg = xlist[1]
2498 2501 if not isinstance(msg, basestring):
2499 2502 msg = msg(abs)
2500 2503 ui.status(msg % rel)
2501 2504 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2502 2505 if abs not in table: continue
2503 2506 # file has changed in dirstate
2504 2507 if mfentry:
2505 2508 handle(hitlist, backuphit)
2506 2509 elif misslist is not None:
2507 2510 handle(misslist, backupmiss)
2508 2511 break
2509 2512 else:
2510 2513 if abs not in repo.dirstate:
2511 2514 if mfentry:
2512 2515 handle(add, True)
2513 2516 elif exact:
2514 2517 ui.warn(_('file not managed: %s\n') % rel)
2515 2518 continue
2516 2519 # file has not changed in dirstate
2517 2520 if node == parent:
2518 2521 if exact: ui.warn(_('no changes needed to %s\n') % rel)
2519 2522 continue
2520 2523 if pmf is None:
2521 2524 # only need parent manifest in this unlikely case,
2522 2525 # so do not read by default
2523 2526 pmf = repo[parent].manifest()
2524 2527 if abs in pmf:
2525 2528 if mfentry:
2526 2529 # if version of file is same in parent and target
2527 2530 # manifests, do nothing
2528 2531 if (pmf[abs] != mfentry or
2529 2532 pmf.flags(abs) != mf.flags(abs)):
2530 2533 handle(revert, False)
2531 2534 else:
2532 2535 handle(remove, False)
2533 2536
2534 2537 if not opts.get('dry_run'):
2535 2538 def checkout(f):
2536 2539 fc = ctx[f]
2537 2540 repo.wwrite(f, fc.data(), fc.flags())
2538 2541
2539 2542 audit_path = util.path_auditor(repo.root)
2540 2543 for f in remove[0]:
2541 2544 if repo.dirstate[f] == 'a':
2542 2545 repo.dirstate.forget(f)
2543 2546 continue
2544 2547 audit_path(f)
2545 2548 try:
2546 2549 util.unlink(repo.wjoin(f))
2547 2550 except OSError:
2548 2551 pass
2549 2552 repo.dirstate.remove(f)
2550 2553
2551 2554 normal = None
2552 2555 if node == parent:
2553 2556 # We're reverting to our parent. If possible, we'd like status
2554 2557 # to report the file as clean. We have to use normallookup for
2555 2558 # merges to avoid losing information about merged/dirty files.
2556 2559 if p2 != nullid:
2557 2560 normal = repo.dirstate.normallookup
2558 2561 else:
2559 2562 normal = repo.dirstate.normal
2560 2563 for f in revert[0]:
2561 2564 checkout(f)
2562 2565 if normal:
2563 2566 normal(f)
2564 2567
2565 2568 for f in add[0]:
2566 2569 checkout(f)
2567 2570 repo.dirstate.add(f)
2568 2571
2569 2572 normal = repo.dirstate.normallookup
2570 2573 if node == parent and p2 == nullid:
2571 2574 normal = repo.dirstate.normal
2572 2575 for f in undelete[0]:
2573 2576 checkout(f)
2574 2577 normal(f)
2575 2578
2576 2579 finally:
2577 2580 del wlock
2578 2581
2579 2582 def rollback(ui, repo):
2580 2583 """roll back the last transaction
2581 2584
2582 2585 This command should be used with care. There is only one level of
2583 2586 rollback, and there is no way to undo a rollback. It will also
2584 2587 restore the dirstate at the time of the last transaction, losing
2585 2588 any dirstate changes since that time.
2586 2589
2587 2590 Transactions are used to encapsulate the effects of all commands
2588 2591 that create new changesets or propagate existing changesets into a
2589 2592 repository. For example, the following commands are transactional,
2590 2593 and their effects can be rolled back:
2591 2594
2592 2595 commit
2593 2596 import
2594 2597 pull
2595 2598 push (with this repository as destination)
2596 2599 unbundle
2597 2600
2598 2601 This command is not intended for use on public repositories. Once
2599 2602 changes are visible for pull by other users, rolling a transaction
2600 2603 back locally is ineffective (someone else may already have pulled
2601 2604 the changes). Furthermore, a race is possible with readers of the
2602 2605 repository; for example an in-progress pull from the repository
2603 2606 may fail if a rollback is performed.
2604 2607 """
2605 2608 repo.rollback()
2606 2609
2607 2610 def root(ui, repo):
2608 2611 """print the root (top) of the current working dir
2609 2612
2610 2613 Print the root directory of the current repository.
2611 2614 """
2612 2615 ui.write(repo.root + "\n")
2613 2616
2614 2617 def serve(ui, repo, **opts):
2615 2618 """export the repository via HTTP
2616 2619
2617 2620 Start a local HTTP repository browser and pull server.
2618 2621
2619 2622 By default, the server logs accesses to stdout and errors to
2620 2623 stderr. Use the "-A" and "-E" options to log to files.
2621 2624 """
2622 2625
2623 2626 if opts["stdio"]:
2624 2627 if repo is None:
2625 2628 raise error.RepoError(_("There is no Mercurial repository here"
2626 2629 " (.hg not found)"))
2627 2630 s = sshserver.sshserver(ui, repo)
2628 2631 s.serve_forever()
2629 2632
2630 2633 parentui = ui.parentui or ui
2631 2634 optlist = ("name templates style address port prefix ipv6"
2632 2635 " accesslog errorlog webdir_conf certificate")
2633 2636 for o in optlist.split():
2634 2637 if opts[o]:
2635 2638 parentui.setconfig("web", o, str(opts[o]))
2636 2639 if (repo is not None) and (repo.ui != parentui):
2637 2640 repo.ui.setconfig("web", o, str(opts[o]))
2638 2641
2639 2642 if repo is None and not ui.config("web", "webdir_conf"):
2640 2643 raise error.RepoError(_("There is no Mercurial repository here"
2641 2644 " (.hg not found)"))
2642 2645
2643 2646 class service:
2644 2647 def init(self):
2645 2648 util.set_signal_handler()
2646 2649 self.httpd = hgweb.server.create_server(parentui, repo)
2647 2650
2648 2651 if not ui.verbose: return
2649 2652
2650 2653 if self.httpd.prefix:
2651 2654 prefix = self.httpd.prefix.strip('/') + '/'
2652 2655 else:
2653 2656 prefix = ''
2654 2657
2655 2658 port = ':%d' % self.httpd.port
2656 2659 if port == ':80':
2657 2660 port = ''
2658 2661
2659 2662 bindaddr = self.httpd.addr
2660 2663 if bindaddr == '0.0.0.0':
2661 2664 bindaddr = '*'
2662 2665 elif ':' in bindaddr: # IPv6
2663 2666 bindaddr = '[%s]' % bindaddr
2664 2667
2665 2668 fqaddr = self.httpd.fqaddr
2666 2669 if ':' in fqaddr:
2667 2670 fqaddr = '[%s]' % fqaddr
2668 2671 ui.status(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
2669 2672 (fqaddr, port, prefix, bindaddr, self.httpd.port))
2670 2673
2671 2674 def run(self):
2672 2675 self.httpd.serve_forever()
2673 2676
2674 2677 service = service()
2675 2678
2676 2679 cmdutil.service(opts, initfn=service.init, runfn=service.run)
2677 2680
2678 2681 def status(ui, repo, *pats, **opts):
2679 2682 """show changed files in the working directory
2680 2683
2681 2684 Show status of files in the repository. If names are given, only
2682 2685 files that match are shown. Files that are clean or ignored or
2683 2686 source of a copy/move operation, are not listed unless -c (clean),
2684 2687 -i (ignored), -C (copies) or -A is given. Unless options described
2685 2688 with "show only ..." are given, the options -mardu are used.
2686 2689
2687 2690 Option -q/--quiet hides untracked (unknown and ignored) files
2688 2691 unless explicitly requested with -u/--unknown or -i/-ignored.
2689 2692
2690 2693 NOTE: status may appear to disagree with diff if permissions have
2691 2694 changed or a merge has occurred. The standard diff format does not
2692 2695 report permission changes and diff only reports changes relative
2693 2696 to one merge parent.
2694 2697
2695 2698 If one revision is given, it is used as the base revision.
2696 2699 If two revisions are given, the difference between them is shown.
2697 2700
2698 2701 The codes used to show the status of files are:
2699 2702 M = modified
2700 2703 A = added
2701 2704 R = removed
2702 2705 C = clean
2703 2706 ! = deleted, but still tracked
2704 2707 ? = not tracked
2705 2708 I = ignored
2706 2709 = the previous added file was copied from here
2707 2710 """
2708 2711
2709 2712 node1, node2 = cmdutil.revpair(repo, opts.get('rev'))
2710 2713 cwd = (pats and repo.getcwd()) or ''
2711 2714 end = opts.get('print0') and '\0' or '\n'
2712 2715 copy = {}
2713 2716 states = 'modified added removed deleted unknown ignored clean'.split()
2714 2717 show = [k for k in states if opts.get(k)]
2715 2718 if opts.get('all'):
2716 2719 show += ui.quiet and (states[:4] + ['clean']) or states
2717 2720 if not show:
2718 2721 show = ui.quiet and states[:4] or states[:5]
2719 2722
2720 2723 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
2721 2724 'ignored' in show, 'clean' in show, 'unknown' in show)
2722 2725 changestates = zip(states, 'MAR!?IC', stat)
2723 2726
2724 2727 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
2725 2728 ctxn = repo[nullid]
2726 2729 ctx1 = repo[node1]
2727 2730 ctx2 = repo[node2]
2728 2731 added = stat[1]
2729 2732 if node2 is None:
2730 2733 added = stat[0] + stat[1] # merged?
2731 2734
2732 2735 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
2733 2736 if k in added:
2734 2737 copy[k] = v
2735 2738 elif v in added:
2736 2739 copy[v] = k
2737 2740
2738 2741 for state, char, files in changestates:
2739 2742 if state in show:
2740 2743 format = "%s %%s%s" % (char, end)
2741 2744 if opts.get('no_status'):
2742 2745 format = "%%s%s" % end
2743 2746
2744 2747 for f in files:
2745 2748 ui.write(format % repo.pathto(f, cwd))
2746 2749 if f in copy:
2747 2750 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end))
2748 2751
2749 2752 def tag(ui, repo, name1, *names, **opts):
2750 2753 """add one or more tags for the current or given revision
2751 2754
2752 2755 Name a particular revision using <name>.
2753 2756
2754 2757 Tags are used to name particular revisions of the repository and are
2755 2758 very useful to compare different revisions, to go back to significant
2756 2759 earlier versions or to mark branch points as releases, etc.
2757 2760
2758 2761 If no revision is given, the parent of the working directory is used,
2759 2762 or tip if no revision is checked out.
2760 2763
2761 2764 To facilitate version control, distribution, and merging of tags,
2762 2765 they are stored as a file named ".hgtags" which is managed
2763 2766 similarly to other project files and can be hand-edited if
2764 2767 necessary. The file '.hg/localtags' is used for local tags (not
2765 2768 shared among repositories).
2766 2769
2767 2770 See 'hg help dates' for a list of formats valid for -d/--date.
2768 2771 """
2769 2772
2770 2773 rev_ = "."
2771 2774 names = (name1,) + names
2772 2775 if len(names) != len(dict.fromkeys(names)):
2773 2776 raise util.Abort(_('tag names must be unique'))
2774 2777 for n in names:
2775 2778 if n in ['tip', '.', 'null']:
2776 2779 raise util.Abort(_('the name \'%s\' is reserved') % n)
2777 2780 if opts.get('rev') and opts.get('remove'):
2778 2781 raise util.Abort(_("--rev and --remove are incompatible"))
2779 2782 if opts.get('rev'):
2780 2783 rev_ = opts['rev']
2781 2784 message = opts.get('message')
2782 2785 if opts.get('remove'):
2783 2786 expectedtype = opts.get('local') and 'local' or 'global'
2784 2787 for n in names:
2785 2788 if not repo.tagtype(n):
2786 2789 raise util.Abort(_('tag \'%s\' does not exist') % n)
2787 2790 if repo.tagtype(n) != expectedtype:
2788 2791 raise util.Abort(_('tag \'%s\' is not a %s tag') %
2789 2792 (n, expectedtype))
2790 2793 rev_ = nullid
2791 2794 if not message:
2792 2795 message = _('Removed tag %s') % ', '.join(names)
2793 2796 elif not opts.get('force'):
2794 2797 for n in names:
2795 2798 if n in repo.tags():
2796 2799 raise util.Abort(_('tag \'%s\' already exists '
2797 2800 '(use -f to force)') % n)
2798 2801 if not rev_ and repo.dirstate.parents()[1] != nullid:
2799 2802 raise util.Abort(_('uncommitted merge - please provide a '
2800 2803 'specific revision'))
2801 2804 r = repo[rev_].node()
2802 2805
2803 2806 if not message:
2804 2807 message = (_('Added tag %s for changeset %s') %
2805 2808 (', '.join(names), short(r)))
2806 2809
2807 2810 date = opts.get('date')
2808 2811 if date:
2809 2812 date = util.parsedate(date)
2810 2813
2811 2814 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
2812 2815
2813 2816 def tags(ui, repo):
2814 2817 """list repository tags
2815 2818
2816 2819 This lists both regular and local tags. When the -v/--verbose switch
2817 2820 is used, a third column "local" is printed for local tags.
2818 2821 """
2819 2822
2820 2823 l = repo.tagslist()
2821 2824 l.reverse()
2822 2825 hexfunc = ui.debugflag and hex or short
2823 2826 tagtype = ""
2824 2827
2825 2828 for t, n in l:
2826 2829 if ui.quiet:
2827 2830 ui.write("%s\n" % t)
2828 2831 continue
2829 2832
2830 2833 try:
2831 2834 hn = hexfunc(n)
2832 2835 r = "%5d:%s" % (repo.changelog.rev(n), hn)
2833 2836 except error.LookupError:
2834 2837 r = " ?:%s" % hn
2835 2838 else:
2836 2839 spaces = " " * (30 - util.colwidth(t))
2837 2840 if ui.verbose:
2838 2841 if repo.tagtype(t) == 'local':
2839 2842 tagtype = " local"
2840 2843 else:
2841 2844 tagtype = ""
2842 2845 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
2843 2846
2844 2847 def tip(ui, repo, **opts):
2845 2848 """show the tip revision
2846 2849
2847 2850 The tip revision (usually just called the tip) is the most
2848 2851 recently added changeset in the repository, the most recently
2849 2852 changed head.
2850 2853
2851 2854 If you have just made a commit, that commit will be the tip. If
2852 2855 you have just pulled changes from another repository, the tip of
2853 2856 that repository becomes the current tip. The "tip" tag is special
2854 2857 and cannot be renamed or assigned to a different changeset.
2855 2858 """
2856 2859 cmdutil.show_changeset(ui, repo, opts).show(repo[len(repo) - 1])
2857 2860
2858 2861 def unbundle(ui, repo, fname1, *fnames, **opts):
2859 2862 """apply one or more changegroup files
2860 2863
2861 2864 Apply one or more compressed changegroup files generated by the
2862 2865 bundle command.
2863 2866 """
2864 2867 fnames = (fname1,) + fnames
2865 2868
2866 2869 lock = None
2867 2870 try:
2868 2871 lock = repo.lock()
2869 2872 for fname in fnames:
2870 2873 f = url.open(ui, fname)
2871 2874 gen = changegroup.readbundle(f, fname)
2872 2875 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
2873 2876 finally:
2874 2877 del lock
2875 2878
2876 2879 return postincoming(ui, repo, modheads, opts.get('update'), None)
2877 2880
2878 2881 def update(ui, repo, node=None, rev=None, clean=False, date=None):
2879 2882 """update working directory
2880 2883
2881 2884 Update the repository's working directory to the specified revision,
2882 2885 or the tip of the current branch if none is specified. Use null as
2883 2886 the revision to remove the working copy (like 'hg clone -U').
2884 2887
2885 2888 When the working dir contains no uncommitted changes, it will be
2886 2889 replaced by the state of the requested revision from the repo. When
2887 2890 the requested revision is on a different branch, the working dir
2888 2891 will additionally be switched to that branch.
2889 2892
2890 2893 When there are uncommitted changes, use option -C to discard them,
2891 2894 forcibly replacing the state of the working dir with the requested
2892 2895 revision.
2893 2896
2894 2897 When there are uncommitted changes and option -C is not used, and
2895 2898 the parent revision and requested revision are on the same branch,
2896 2899 and one of them is an ancestor of the other, then the new working
2897 2900 directory will contain the requested revision merged with the
2898 2901 uncommitted changes. Otherwise, the update will fail with a
2899 2902 suggestion to use 'merge' or 'update -C' instead.
2900 2903
2901 2904 If you want to update just one file to an older revision, use revert.
2902 2905
2903 2906 See 'hg help dates' for a list of formats valid for --date.
2904 2907 """
2905 2908 if rev and node:
2906 2909 raise util.Abort(_("please specify just one revision"))
2907 2910
2908 2911 if not rev:
2909 2912 rev = node
2910 2913
2911 2914 if date:
2912 2915 if rev:
2913 2916 raise util.Abort(_("you can't specify a revision and a date"))
2914 2917 rev = cmdutil.finddate(ui, repo, date)
2915 2918
2916 2919 if clean:
2917 2920 return hg.clean(repo, rev)
2918 2921 else:
2919 2922 return hg.update(repo, rev)
2920 2923
2921 2924 def verify(ui, repo):
2922 2925 """verify the integrity of the repository
2923 2926
2924 2927 Verify the integrity of the current repository.
2925 2928
2926 2929 This will perform an extensive check of the repository's
2927 2930 integrity, validating the hashes and checksums of each entry in
2928 2931 the changelog, manifest, and tracked files, as well as the
2929 2932 integrity of their crosslinks and indices.
2930 2933 """
2931 2934 return hg.verify(repo)
2932 2935
2933 2936 def version_(ui):
2934 2937 """output version and copyright information"""
2935 2938 ui.write(_("Mercurial Distributed SCM (version %s)\n")
2936 2939 % util.version())
2937 2940 ui.status(_(
2938 2941 "\nCopyright (C) 2005-2008 Matt Mackall <mpm@selenic.com> and others\n"
2939 2942 "This is free software; see the source for copying conditions. "
2940 2943 "There is NO\nwarranty; "
2941 2944 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
2942 2945 ))
2943 2946
2944 2947 # Command options and aliases are listed here, alphabetically
2945 2948
2946 2949 globalopts = [
2947 2950 ('R', 'repository', '',
2948 2951 _('repository root directory or symbolic path name')),
2949 2952 ('', 'cwd', '', _('change working directory')),
2950 2953 ('y', 'noninteractive', None,
2951 2954 _('do not prompt, assume \'yes\' for any required answers')),
2952 2955 ('q', 'quiet', None, _('suppress output')),
2953 2956 ('v', 'verbose', None, _('enable additional output')),
2954 2957 ('', 'config', [], _('set/override config option')),
2955 2958 ('', 'debug', None, _('enable debugging output')),
2956 2959 ('', 'debugger', None, _('start debugger')),
2957 2960 ('', 'encoding', util._encoding, _('set the charset encoding')),
2958 2961 ('', 'encodingmode', util._encodingmode, _('set the charset encoding mode')),
2959 2962 ('', 'lsprof', None, _('print improved command execution profile')),
2960 2963 ('', 'traceback', None, _('print traceback on exception')),
2961 2964 ('', 'time', None, _('time how long the command takes')),
2962 2965 ('', 'profile', None, _('print command execution profile')),
2963 2966 ('', 'version', None, _('output version information and exit')),
2964 2967 ('h', 'help', None, _('display help and exit')),
2965 2968 ]
2966 2969
2967 2970 dryrunopts = [('n', 'dry-run', None,
2968 2971 _('do not perform actions, just print output'))]
2969 2972
2970 2973 remoteopts = [
2971 2974 ('e', 'ssh', '', _('specify ssh command to use')),
2972 2975 ('', 'remotecmd', '', _('specify hg command to run on the remote side')),
2973 2976 ]
2974 2977
2975 2978 walkopts = [
2976 2979 ('I', 'include', [], _('include names matching the given patterns')),
2977 2980 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2978 2981 ]
2979 2982
2980 2983 commitopts = [
2981 2984 ('m', 'message', '', _('use <text> as commit message')),
2982 2985 ('l', 'logfile', '', _('read commit message from <file>')),
2983 2986 ]
2984 2987
2985 2988 commitopts2 = [
2986 2989 ('d', 'date', '', _('record datecode as commit date')),
2987 2990 ('u', 'user', '', _('record user as committer')),
2988 2991 ]
2989 2992
2990 2993 templateopts = [
2991 2994 ('', 'style', '', _('display using template map file')),
2992 2995 ('', 'template', '', _('display with template')),
2993 2996 ]
2994 2997
2995 2998 logopts = [
2996 2999 ('p', 'patch', None, _('show patch')),
2997 3000 ('l', 'limit', '', _('limit number of changes displayed')),
2998 3001 ('M', 'no-merges', None, _('do not show merges')),
2999 3002 ] + templateopts
3000 3003
3001 3004 diffopts = [
3002 3005 ('a', 'text', None, _('treat all files as text')),
3003 3006 ('g', 'git', None, _('use git extended diff format')),
3004 3007 ('', 'nodates', None, _("don't include dates in diff headers"))
3005 3008 ]
3006 3009
3007 3010 diffopts2 = [
3008 3011 ('p', 'show-function', None, _('show which function each change is in')),
3009 3012 ('w', 'ignore-all-space', None,
3010 3013 _('ignore white space when comparing lines')),
3011 3014 ('b', 'ignore-space-change', None,
3012 3015 _('ignore changes in the amount of white space')),
3013 3016 ('B', 'ignore-blank-lines', None,
3014 3017 _('ignore changes whose lines are all blank')),
3015 3018 ('U', 'unified', '', _('number of lines of context to show'))
3016 3019 ]
3017 3020
3018 3021 similarityopts = [
3019 3022 ('s', 'similarity', '',
3020 3023 _('guess renamed files by similarity (0<=s<=100)'))
3021 3024 ]
3022 3025
3023 3026 table = {
3024 3027 "^add": (add, walkopts + dryrunopts, _('[OPTION]... [FILE]...')),
3025 3028 "addremove":
3026 3029 (addremove, similarityopts + walkopts + dryrunopts,
3027 3030 _('[OPTION]... [FILE]...')),
3028 3031 "^annotate|blame":
3029 3032 (annotate,
3030 3033 [('r', 'rev', '', _('annotate the specified revision')),
3031 3034 ('f', 'follow', None, _('follow file copies and renames')),
3032 3035 ('a', 'text', None, _('treat all files as text')),
3033 3036 ('u', 'user', None, _('list the author (long with -v)')),
3034 3037 ('d', 'date', None, _('list the date (short with -q)')),
3035 3038 ('n', 'number', None, _('list the revision number (default)')),
3036 3039 ('c', 'changeset', None, _('list the changeset')),
3037 3040 ('l', 'line-number', None,
3038 3041 _('show line number at the first appearance'))
3039 3042 ] + walkopts,
3040 3043 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
3041 3044 "archive":
3042 3045 (archive,
3043 3046 [('', 'no-decode', None, _('do not pass files through decoders')),
3044 3047 ('p', 'prefix', '', _('directory prefix for files in archive')),
3045 3048 ('r', 'rev', '', _('revision to distribute')),
3046 3049 ('t', 'type', '', _('type of distribution to create')),
3047 3050 ] + walkopts,
3048 3051 _('[OPTION]... DEST')),
3049 3052 "backout":
3050 3053 (backout,
3051 3054 [('', 'merge', None,
3052 3055 _('merge with old dirstate parent after backout')),
3053 3056 ('', 'parent', '', _('parent to choose when backing out merge')),
3054 3057 ('r', 'rev', '', _('revision to backout')),
3055 3058 ] + walkopts + commitopts + commitopts2,
3056 3059 _('[OPTION]... [-r] REV')),
3057 3060 "bisect":
3058 3061 (bisect,
3059 3062 [('r', 'reset', False, _('reset bisect state')),
3060 3063 ('g', 'good', False, _('mark changeset good')),
3061 3064 ('b', 'bad', False, _('mark changeset bad')),
3062 3065 ('s', 'skip', False, _('skip testing changeset')),
3063 3066 ('c', 'command', '', _('use command to check changeset state')),
3064 3067 ('U', 'noupdate', False, _('do not update to target'))],
3065 3068 _("[-gbsr] [-c CMD] [REV]")),
3066 3069 "branch":
3067 3070 (branch,
3068 3071 [('f', 'force', None,
3069 3072 _('set branch name even if it shadows an existing branch')),
3070 3073 ('C', 'clean', None, _('reset branch name to parent branch name'))],
3071 3074 _('[-fC] [NAME]')),
3072 3075 "branches":
3073 3076 (branches,
3074 3077 [('a', 'active', False,
3075 3078 _('show only branches that have unmerged heads'))],
3076 3079 _('[-a]')),
3077 3080 "bundle":
3078 3081 (bundle,
3079 3082 [('f', 'force', None,
3080 3083 _('run even when remote repository is unrelated')),
3081 3084 ('r', 'rev', [],
3082 3085 _('a changeset up to which you would like to bundle')),
3083 3086 ('', 'base', [],
3084 3087 _('a base changeset to specify instead of a destination')),
3085 3088 ('a', 'all', None, _('bundle all changesets in the repository')),
3086 3089 ('t', 'type', 'bzip2', _('bundle compression type to use')),
3087 3090 ] + remoteopts,
3088 3091 _('[-f] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
3089 3092 "cat":
3090 3093 (cat,
3091 3094 [('o', 'output', '', _('print output to file with formatted name')),
3092 3095 ('r', 'rev', '', _('print the given revision')),
3093 3096 ('', 'decode', None, _('apply any matching decode filter')),
3094 3097 ] + walkopts,
3095 3098 _('[OPTION]... FILE...')),
3096 3099 "^clone":
3097 3100 (clone,
3098 3101 [('U', 'noupdate', None,
3099 3102 _('the clone will only contain a repository (no working copy)')),
3100 3103 ('r', 'rev', [],
3101 3104 _('a changeset you would like to have after cloning')),
3102 3105 ('', 'pull', None, _('use pull protocol to copy metadata')),
3103 3106 ('', 'uncompressed', None,
3104 3107 _('use uncompressed transfer (fast over LAN)')),
3105 3108 ] + remoteopts,
3106 3109 _('[OPTION]... SOURCE [DEST]')),
3107 3110 "^commit|ci":
3108 3111 (commit,
3109 3112 [('A', 'addremove', None,
3110 3113 _('mark new/missing files as added/removed before committing')),
3111 3114 ('', 'close-branch', None,
3112 3115 _('mark a branch as closed, hiding it from the branch list')),
3113 3116 ] + walkopts + commitopts + commitopts2,
3114 3117 _('[OPTION]... [FILE]...')),
3115 3118 "copy|cp":
3116 3119 (copy,
3117 3120 [('A', 'after', None, _('record a copy that has already occurred')),
3118 3121 ('f', 'force', None,
3119 3122 _('forcibly copy over an existing managed file')),
3120 3123 ] + walkopts + dryrunopts,
3121 3124 _('[OPTION]... [SOURCE]... DEST')),
3122 3125 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
3123 3126 "debugcheckstate": (debugcheckstate, []),
3124 3127 "debugcomplete":
3125 3128 (debugcomplete,
3126 3129 [('o', 'options', None, _('show the command options'))],
3127 3130 _('[-o] CMD')),
3128 3131 "debugdate":
3129 3132 (debugdate,
3130 3133 [('e', 'extended', None, _('try extended date formats'))],
3131 3134 _('[-e] DATE [RANGE]')),
3132 3135 "debugdata": (debugdata, [], _('FILE REV')),
3133 3136 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
3134 3137 "debugindex": (debugindex, [], _('FILE')),
3135 3138 "debugindexdot": (debugindexdot, [], _('FILE')),
3136 3139 "debuginstall": (debuginstall, []),
3137 3140 "debugrawcommit|rawcommit":
3138 3141 (rawcommit,
3139 3142 [('p', 'parent', [], _('parent')),
3140 3143 ('F', 'files', '', _('file list'))
3141 3144 ] + commitopts + commitopts2,
3142 3145 _('[OPTION]... [FILE]...')),
3143 3146 "debugrebuildstate":
3144 3147 (debugrebuildstate,
3145 3148 [('r', 'rev', '', _('revision to rebuild to'))],
3146 3149 _('[-r REV] [REV]')),
3147 3150 "debugrename":
3148 3151 (debugrename,
3149 3152 [('r', 'rev', '', _('revision to debug'))],
3150 3153 _('[-r REV] FILE')),
3151 3154 "debugsetparents":
3152 3155 (debugsetparents, [], _('REV1 [REV2]')),
3153 3156 "debugstate":
3154 3157 (debugstate,
3155 3158 [('', 'nodates', None, _('do not display the saved mtime'))],
3156 3159 _('[OPTION]...')),
3157 3160 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
3158 3161 "^diff":
3159 3162 (diff,
3160 3163 [('r', 'rev', [], _('revision')),
3161 3164 ('c', 'change', '', _('change made by revision'))
3162 3165 ] + diffopts + diffopts2 + walkopts,
3163 3166 _('[OPTION]... [-r REV1 [-r REV2]] [FILE]...')),
3164 3167 "^export":
3165 3168 (export,
3166 3169 [('o', 'output', '', _('print output to file with formatted name')),
3167 3170 ('', 'switch-parent', None, _('diff against the second parent'))
3168 3171 ] + diffopts,
3169 3172 _('[OPTION]... [-o OUTFILESPEC] REV...')),
3170 3173 "grep":
3171 3174 (grep,
3172 3175 [('0', 'print0', None, _('end fields with NUL')),
3173 3176 ('', 'all', None, _('print all revisions that match')),
3174 3177 ('f', 'follow', None,
3175 3178 _('follow changeset history, or file history across copies and renames')),
3176 3179 ('i', 'ignore-case', None, _('ignore case when matching')),
3177 3180 ('l', 'files-with-matches', None,
3178 3181 _('print only filenames and revs that match')),
3179 3182 ('n', 'line-number', None, _('print matching line numbers')),
3180 3183 ('r', 'rev', [], _('search in given revision range')),
3181 3184 ('u', 'user', None, _('list the author (long with -v)')),
3182 3185 ('d', 'date', None, _('list the date (short with -q)')),
3183 3186 ] + walkopts,
3184 3187 _('[OPTION]... PATTERN [FILE]...')),
3185 3188 "heads":
3186 3189 (heads,
3187 3190 [('r', 'rev', '', _('show only heads which are descendants of rev')),
3188 3191 ('a', 'active', False,
3189 3192 _('show only the active heads from open branches')),
3190 3193 ] + templateopts,
3191 3194 _('[-r REV] [REV]...')),
3192 3195 "help": (help_, [], _('[TOPIC]')),
3193 3196 "identify|id":
3194 3197 (identify,
3195 3198 [('r', 'rev', '', _('identify the specified rev')),
3196 3199 ('n', 'num', None, _('show local revision number')),
3197 3200 ('i', 'id', None, _('show global revision id')),
3198 3201 ('b', 'branch', None, _('show branch')),
3199 3202 ('t', 'tags', None, _('show tags'))],
3200 3203 _('[-nibt] [-r REV] [SOURCE]')),
3201 3204 "import|patch":
3202 3205 (import_,
3203 3206 [('p', 'strip', 1,
3204 3207 _('directory strip option for patch. This has the same\n'
3205 3208 'meaning as the corresponding patch option')),
3206 3209 ('b', 'base', '', _('base path')),
3207 3210 ('f', 'force', None,
3208 3211 _('skip check for outstanding uncommitted changes')),
3209 3212 ('', 'no-commit', None, _("don't commit, just update the working directory")),
3210 3213 ('', 'exact', None,
3211 3214 _('apply patch to the nodes from which it was generated')),
3212 3215 ('', 'import-branch', None,
3213 3216 _('Use any branch information in patch (implied by --exact)'))] +
3214 3217 commitopts + commitopts2 + similarityopts,
3215 3218 _('[OPTION]... PATCH...')),
3216 3219 "incoming|in":
3217 3220 (incoming,
3218 3221 [('f', 'force', None,
3219 3222 _('run even when remote repository is unrelated')),
3220 3223 ('n', 'newest-first', None, _('show newest record first')),
3221 3224 ('', 'bundle', '', _('file to store the bundles into')),
3222 3225 ('r', 'rev', [],
3223 3226 _('a specific revision up to which you would like to pull')),
3224 3227 ] + logopts + remoteopts,
3225 3228 _('[-p] [-n] [-M] [-f] [-r REV]...'
3226 3229 ' [--bundle FILENAME] [SOURCE]')),
3227 3230 "^init":
3228 3231 (init,
3229 3232 remoteopts,
3230 3233 _('[-e CMD] [--remotecmd CMD] [DEST]')),
3231 3234 "locate":
3232 3235 (locate,
3233 3236 [('r', 'rev', '', _('search the repository as it stood at rev')),
3234 3237 ('0', 'print0', None,
3235 3238 _('end filenames with NUL, for use with xargs')),
3236 3239 ('f', 'fullpath', None,
3237 3240 _('print complete paths from the filesystem root')),
3238 3241 ] + walkopts,
3239 3242 _('[OPTION]... [PATTERN]...')),
3240 3243 "^log|history":
3241 3244 (log,
3242 3245 [('f', 'follow', None,
3243 3246 _('follow changeset history, or file history across copies and renames')),
3244 3247 ('', 'follow-first', None,
3245 3248 _('only follow the first parent of merge changesets')),
3246 3249 ('d', 'date', '', _('show revs matching date spec')),
3247 3250 ('C', 'copies', None, _('show copied files')),
3248 3251 ('k', 'keyword', [], _('do case-insensitive search for a keyword')),
3249 3252 ('r', 'rev', [], _('show the specified revision or range')),
3250 3253 ('', 'removed', None, _('include revs where files were removed')),
3251 3254 ('m', 'only-merges', None, _('show only merges')),
3252 3255 ('u', 'user', [], _('revs committed by user')),
3253 3256 ('b', 'only-branch', [],
3254 3257 _('show only changesets within the given named branch')),
3255 3258 ('P', 'prune', [], _('do not display revision or any of its ancestors')),
3256 3259 ] + logopts + walkopts,
3257 3260 _('[OPTION]... [FILE]')),
3258 3261 "manifest":
3259 3262 (manifest,
3260 3263 [('r', 'rev', '', _('revision to display'))],
3261 3264 _('[-r REV]')),
3262 3265 "^merge":
3263 3266 (merge,
3264 3267 [('f', 'force', None, _('force a merge with outstanding changes')),
3265 3268 ('r', 'rev', '', _('revision to merge')),
3266 3269 ],
3267 3270 _('[-f] [[-r] REV]')),
3268 3271 "outgoing|out":
3269 3272 (outgoing,
3270 3273 [('f', 'force', None,
3271 3274 _('run even when remote repository is unrelated')),
3272 3275 ('r', 'rev', [],
3273 3276 _('a specific revision up to which you would like to push')),
3274 3277 ('n', 'newest-first', None, _('show newest record first')),
3275 3278 ] + logopts + remoteopts,
3276 3279 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
3277 3280 "^parents":
3278 3281 (parents,
3279 3282 [('r', 'rev', '', _('show parents from the specified rev')),
3280 3283 ] + templateopts,
3281 3284 _('hg parents [-r REV] [FILE]')),
3282 3285 "paths": (paths, [], _('[NAME]')),
3283 3286 "^pull":
3284 3287 (pull,
3285 3288 [('u', 'update', None,
3286 3289 _('update to new tip if changesets were pulled')),
3287 3290 ('f', 'force', None,
3288 3291 _('run even when remote repository is unrelated')),
3289 3292 ('r', 'rev', [],
3290 3293 _('a specific revision up to which you would like to pull')),
3291 3294 ] + remoteopts,
3292 3295 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
3293 3296 "^push":
3294 3297 (push,
3295 3298 [('f', 'force', None, _('force push')),
3296 3299 ('r', 'rev', [],
3297 3300 _('a specific revision up to which you would like to push')),
3298 3301 ] + remoteopts,
3299 3302 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
3300 3303 "recover": (recover, []),
3301 3304 "^remove|rm":
3302 3305 (remove,
3303 3306 [('A', 'after', None, _('record delete for missing files')),
3304 3307 ('f', 'force', None,
3305 3308 _('remove (and delete) file even if added or modified')),
3306 3309 ] + walkopts,
3307 3310 _('[OPTION]... FILE...')),
3308 3311 "rename|mv":
3309 3312 (rename,
3310 3313 [('A', 'after', None, _('record a rename that has already occurred')),
3311 3314 ('f', 'force', None,
3312 3315 _('forcibly copy over an existing managed file')),
3313 3316 ] + walkopts + dryrunopts,
3314 3317 _('[OPTION]... SOURCE... DEST')),
3315 3318 "resolve":
3316 3319 (resolve,
3317 3320 [('a', 'all', None, _('remerge all unresolved files')),
3318 3321 ('l', 'list', None, _('list state of files needing merge')),
3319 3322 ('m', 'mark', None, _('mark files as resolved')),
3320 3323 ('u', 'unmark', None, _('unmark files as resolved'))],
3321 3324 _('[OPTION]... [FILE]...')),
3322 3325 "revert":
3323 3326 (revert,
3324 3327 [('a', 'all', None, _('revert all changes when no arguments given')),
3325 3328 ('d', 'date', '', _('tipmost revision matching date')),
3326 3329 ('r', 'rev', '', _('revision to revert to')),
3327 3330 ('', 'no-backup', None, _('do not save backup copies of files')),
3328 3331 ] + walkopts + dryrunopts,
3329 3332 _('[OPTION]... [-r REV] [NAME]...')),
3330 3333 "rollback": (rollback, []),
3331 3334 "root": (root, []),
3332 3335 "^serve":
3333 3336 (serve,
3334 3337 [('A', 'accesslog', '', _('name of access log file to write to')),
3335 3338 ('d', 'daemon', None, _('run server in background')),
3336 3339 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3337 3340 ('E', 'errorlog', '', _('name of error log file to write to')),
3338 3341 ('p', 'port', 0, _('port to listen on (default: 8000)')),
3339 3342 ('a', 'address', '', _('address to listen on (default: all interfaces)')),
3340 3343 ('', 'prefix', '', _('prefix path to serve from (default: server root)')),
3341 3344 ('n', 'name', '',
3342 3345 _('name to show in web pages (default: working dir)')),
3343 3346 ('', 'webdir-conf', '', _('name of the webdir config file'
3344 3347 ' (serve more than one repo)')),
3345 3348 ('', 'pid-file', '', _('name of file to write process ID to')),
3346 3349 ('', 'stdio', None, _('for remote clients')),
3347 3350 ('t', 'templates', '', _('web templates to use')),
3348 3351 ('', 'style', '', _('template style to use')),
3349 3352 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
3350 3353 ('', 'certificate', '', _('SSL certificate file'))],
3351 3354 _('[OPTION]...')),
3352 3355 "showconfig|debugconfig":
3353 3356 (showconfig,
3354 3357 [('u', 'untrusted', None, _('show untrusted configuration options'))],
3355 3358 _('[-u] [NAME]...')),
3356 3359 "^status|st":
3357 3360 (status,
3358 3361 [('A', 'all', None, _('show status of all files')),
3359 3362 ('m', 'modified', None, _('show only modified files')),
3360 3363 ('a', 'added', None, _('show only added files')),
3361 3364 ('r', 'removed', None, _('show only removed files')),
3362 3365 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3363 3366 ('c', 'clean', None, _('show only files without changes')),
3364 3367 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3365 3368 ('i', 'ignored', None, _('show only ignored files')),
3366 3369 ('n', 'no-status', None, _('hide status prefix')),
3367 3370 ('C', 'copies', None, _('show source of copied files')),
3368 3371 ('0', 'print0', None,
3369 3372 _('end filenames with NUL, for use with xargs')),
3370 3373 ('', 'rev', [], _('show difference from revision')),
3371 3374 ] + walkopts,
3372 3375 _('[OPTION]... [FILE]...')),
3373 3376 "tag":
3374 3377 (tag,
3375 3378 [('f', 'force', None, _('replace existing tag')),
3376 3379 ('l', 'local', None, _('make the tag local')),
3377 3380 ('r', 'rev', '', _('revision to tag')),
3378 3381 ('', 'remove', None, _('remove a tag')),
3379 3382 # -l/--local is already there, commitopts cannot be used
3380 3383 ('m', 'message', '', _('use <text> as commit message')),
3381 3384 ] + commitopts2,
3382 3385 _('[-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
3383 3386 "tags": (tags, []),
3384 3387 "tip":
3385 3388 (tip,
3386 3389 [('p', 'patch', None, _('show patch')),
3387 3390 ] + templateopts,
3388 3391 _('[-p]')),
3389 3392 "unbundle":
3390 3393 (unbundle,
3391 3394 [('u', 'update', None,
3392 3395 _('update to new tip if changesets were unbundled'))],
3393 3396 _('[-u] FILE...')),
3394 3397 "^update|up|checkout|co":
3395 3398 (update,
3396 3399 [('C', 'clean', None, _('overwrite locally modified files (no backup)')),
3397 3400 ('d', 'date', '', _('tipmost revision matching date')),
3398 3401 ('r', 'rev', '', _('revision'))],
3399 3402 _('[-C] [-d DATE] [[-r] REV]')),
3400 3403 "verify": (verify, []),
3401 3404 "version": (version_, []),
3402 3405 }
3403 3406
3404 3407 norepo = ("clone init version help debugcomplete debugdata"
3405 3408 " debugindex debugindexdot debugdate debuginstall debugfsinfo")
3406 3409 optionalrepo = ("identify paths serve showconfig debugancestor")
General Comments 0
You need to be logged in to leave comments. Login now