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