##// END OF EJS Templates
graft: add initial implementation
Matt Mackall -
r15238:2d710c12 default
parent child Browse files
Show More
@@ -1,5475 +1,5544 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 or any later version.
7 7
8 8 from node import hex, bin, nullid, nullrev, short
9 9 from lock import release
10 10 from i18n import _, gettext
11 11 import os, re, difflib, time, tempfile, errno
12 12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 13 import patch, help, url, encoding, templatekw, discovery
14 14 import archival, changegroup, cmdutil, hbisect
15 15 import sshserver, hgweb, hgweb.server, commandserver
16 16 import merge as mergemod
17 17 import minirst, revset, fileset
18 18 import dagparser, context, simplemerge
19 19 import random, setdiscovery, treediscovery, dagutil
20 20
21 21 table = {}
22 22
23 23 command = cmdutil.command(table)
24 24
25 25 # common command options
26 26
27 27 globalopts = [
28 28 ('R', 'repository', '',
29 29 _('repository root directory or name of overlay bundle file'),
30 30 _('REPO')),
31 31 ('', 'cwd', '',
32 32 _('change working directory'), _('DIR')),
33 33 ('y', 'noninteractive', None,
34 34 _('do not prompt, automatically pick the first choice for all prompts')),
35 35 ('q', 'quiet', None, _('suppress output')),
36 36 ('v', 'verbose', None, _('enable additional output')),
37 37 ('', 'config', [],
38 38 _('set/override config option (use \'section.name=value\')'),
39 39 _('CONFIG')),
40 40 ('', 'debug', None, _('enable debugging output')),
41 41 ('', 'debugger', None, _('start debugger')),
42 42 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 43 _('ENCODE')),
44 44 ('', 'encodingmode', encoding.encodingmode,
45 45 _('set the charset encoding mode'), _('MODE')),
46 46 ('', 'traceback', None, _('always print a traceback on exception')),
47 47 ('', 'time', None, _('time how long the command takes')),
48 48 ('', 'profile', None, _('print command execution profile')),
49 49 ('', 'version', None, _('output version information and exit')),
50 50 ('h', 'help', None, _('display help and exit')),
51 51 ]
52 52
53 53 dryrunopts = [('n', 'dry-run', None,
54 54 _('do not perform actions, just print output'))]
55 55
56 56 remoteopts = [
57 57 ('e', 'ssh', '',
58 58 _('specify ssh command to use'), _('CMD')),
59 59 ('', 'remotecmd', '',
60 60 _('specify hg command to run on the remote side'), _('CMD')),
61 61 ('', 'insecure', None,
62 62 _('do not verify server certificate (ignoring web.cacerts config)')),
63 63 ]
64 64
65 65 walkopts = [
66 66 ('I', 'include', [],
67 67 _('include names matching the given patterns'), _('PATTERN')),
68 68 ('X', 'exclude', [],
69 69 _('exclude names matching the given patterns'), _('PATTERN')),
70 70 ]
71 71
72 72 commitopts = [
73 73 ('m', 'message', '',
74 74 _('use text as commit message'), _('TEXT')),
75 75 ('l', 'logfile', '',
76 76 _('read commit message from file'), _('FILE')),
77 77 ]
78 78
79 79 commitopts2 = [
80 80 ('d', 'date', '',
81 81 _('record the specified date as commit date'), _('DATE')),
82 82 ('u', 'user', '',
83 83 _('record the specified user as committer'), _('USER')),
84 84 ]
85 85
86 86 templateopts = [
87 87 ('', 'style', '',
88 88 _('display using template map file'), _('STYLE')),
89 89 ('', 'template', '',
90 90 _('display with template'), _('TEMPLATE')),
91 91 ]
92 92
93 93 logopts = [
94 94 ('p', 'patch', None, _('show patch')),
95 95 ('g', 'git', None, _('use git extended diff format')),
96 96 ('l', 'limit', '',
97 97 _('limit number of changes displayed'), _('NUM')),
98 98 ('M', 'no-merges', None, _('do not show merges')),
99 99 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 100 ] + templateopts
101 101
102 102 diffopts = [
103 103 ('a', 'text', None, _('treat all files as text')),
104 104 ('g', 'git', None, _('use git extended diff format')),
105 105 ('', 'nodates', None, _('omit dates from diff headers'))
106 106 ]
107 107
108 108 diffopts2 = [
109 109 ('p', 'show-function', None, _('show which function each change is in')),
110 110 ('', 'reverse', None, _('produce a diff that undoes the changes')),
111 111 ('w', 'ignore-all-space', None,
112 112 _('ignore white space when comparing lines')),
113 113 ('b', 'ignore-space-change', None,
114 114 _('ignore changes in the amount of white space')),
115 115 ('B', 'ignore-blank-lines', None,
116 116 _('ignore changes whose lines are all blank')),
117 117 ('U', 'unified', '',
118 118 _('number of lines of context to show'), _('NUM')),
119 119 ('', 'stat', None, _('output diffstat-style summary of changes')),
120 120 ]
121 121
122 122 mergetoolopts = [
123 123 ('t', 'tool', '', _('specify merge tool')),
124 124 ]
125 125
126 126 similarityopts = [
127 127 ('s', 'similarity', '',
128 128 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
129 129 ]
130 130
131 131 subrepoopts = [
132 132 ('S', 'subrepos', None,
133 133 _('recurse into subrepositories'))
134 134 ]
135 135
136 136 # Commands start here, listed alphabetically
137 137
138 138 @command('^add',
139 139 walkopts + subrepoopts + dryrunopts,
140 140 _('[OPTION]... [FILE]...'))
141 141 def add(ui, repo, *pats, **opts):
142 142 """add the specified files on the next commit
143 143
144 144 Schedule files to be version controlled and added to the
145 145 repository.
146 146
147 147 The files will be added to the repository at the next commit. To
148 148 undo an add before that, see :hg:`forget`.
149 149
150 150 If no names are given, add all files to the repository.
151 151
152 152 .. container:: verbose
153 153
154 154 An example showing how new (unknown) files are added
155 155 automatically by :hg:`add`::
156 156
157 157 $ ls
158 158 foo.c
159 159 $ hg status
160 160 ? foo.c
161 161 $ hg add
162 162 adding foo.c
163 163 $ hg status
164 164 A foo.c
165 165
166 166 Returns 0 if all files are successfully added.
167 167 """
168 168
169 169 m = scmutil.match(repo[None], pats, opts)
170 170 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
171 171 opts.get('subrepos'), prefix="")
172 172 return rejected and 1 or 0
173 173
174 174 @command('addremove',
175 175 similarityopts + walkopts + dryrunopts,
176 176 _('[OPTION]... [FILE]...'))
177 177 def addremove(ui, repo, *pats, **opts):
178 178 """add all new files, delete all missing files
179 179
180 180 Add all new files and remove all missing files from the
181 181 repository.
182 182
183 183 New files are ignored if they match any of the patterns in
184 184 ``.hgignore``. As with add, these changes take effect at the next
185 185 commit.
186 186
187 187 Use the -s/--similarity option to detect renamed files. With a
188 188 parameter greater than 0, this compares every removed file with
189 189 every added file and records those similar enough as renames. This
190 190 option takes a percentage between 0 (disabled) and 100 (files must
191 191 be identical) as its parameter. Detecting renamed files this way
192 192 can be expensive. After using this option, :hg:`status -C` can be
193 193 used to check which files were identified as moved or renamed.
194 194
195 195 Returns 0 if all files are successfully added.
196 196 """
197 197 try:
198 198 sim = float(opts.get('similarity') or 100)
199 199 except ValueError:
200 200 raise util.Abort(_('similarity must be a number'))
201 201 if sim < 0 or sim > 100:
202 202 raise util.Abort(_('similarity must be between 0 and 100'))
203 203 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
204 204
205 205 @command('^annotate|blame',
206 206 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
207 207 ('', 'follow', None,
208 208 _('follow copies/renames and list the filename (DEPRECATED)')),
209 209 ('', 'no-follow', None, _("don't follow copies and renames")),
210 210 ('a', 'text', None, _('treat all files as text')),
211 211 ('u', 'user', None, _('list the author (long with -v)')),
212 212 ('f', 'file', None, _('list the filename')),
213 213 ('d', 'date', None, _('list the date (short with -q)')),
214 214 ('n', 'number', None, _('list the revision number (default)')),
215 215 ('c', 'changeset', None, _('list the changeset')),
216 216 ('l', 'line-number', None, _('show line number at the first appearance'))
217 217 ] + walkopts,
218 218 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
219 219 def annotate(ui, repo, *pats, **opts):
220 220 """show changeset information by line for each file
221 221
222 222 List changes in files, showing the revision id responsible for
223 223 each line
224 224
225 225 This command is useful for discovering when a change was made and
226 226 by whom.
227 227
228 228 Without the -a/--text option, annotate will avoid processing files
229 229 it detects as binary. With -a, annotate will annotate the file
230 230 anyway, although the results will probably be neither useful
231 231 nor desirable.
232 232
233 233 Returns 0 on success.
234 234 """
235 235 if opts.get('follow'):
236 236 # --follow is deprecated and now just an alias for -f/--file
237 237 # to mimic the behavior of Mercurial before version 1.5
238 238 opts['file'] = True
239 239
240 240 datefunc = ui.quiet and util.shortdate or util.datestr
241 241 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
242 242
243 243 if not pats:
244 244 raise util.Abort(_('at least one filename or pattern is required'))
245 245
246 246 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
247 247 ('number', ' ', lambda x: str(x[0].rev())),
248 248 ('changeset', ' ', lambda x: short(x[0].node())),
249 249 ('date', ' ', getdate),
250 250 ('file', ' ', lambda x: x[0].path()),
251 251 ('line_number', ':', lambda x: str(x[1])),
252 252 ]
253 253
254 254 if (not opts.get('user') and not opts.get('changeset')
255 255 and not opts.get('date') and not opts.get('file')):
256 256 opts['number'] = True
257 257
258 258 linenumber = opts.get('line_number') is not None
259 259 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
260 260 raise util.Abort(_('at least one of -n/-c is required for -l'))
261 261
262 262 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
263 263 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
264 264
265 265 def bad(x, y):
266 266 raise util.Abort("%s: %s" % (x, y))
267 267
268 268 ctx = scmutil.revsingle(repo, opts.get('rev'))
269 269 m = scmutil.match(ctx, pats, opts)
270 270 m.bad = bad
271 271 follow = not opts.get('no_follow')
272 272 for abs in ctx.walk(m):
273 273 fctx = ctx[abs]
274 274 if not opts.get('text') and util.binary(fctx.data()):
275 275 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
276 276 continue
277 277
278 278 lines = fctx.annotate(follow=follow, linenumber=linenumber)
279 279 pieces = []
280 280
281 281 for f, sep in funcmap:
282 282 l = [f(n) for n, dummy in lines]
283 283 if l:
284 284 sized = [(x, encoding.colwidth(x)) for x in l]
285 285 ml = max([w for x, w in sized])
286 286 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
287 287 for x, w in sized])
288 288
289 289 if pieces:
290 290 for p, l in zip(zip(*pieces), lines):
291 291 ui.write("%s: %s" % ("".join(p), l[1]))
292 292
293 293 @command('archive',
294 294 [('', 'no-decode', None, _('do not pass files through decoders')),
295 295 ('p', 'prefix', '', _('directory prefix for files in archive'),
296 296 _('PREFIX')),
297 297 ('r', 'rev', '', _('revision to distribute'), _('REV')),
298 298 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
299 299 ] + subrepoopts + walkopts,
300 300 _('[OPTION]... DEST'))
301 301 def archive(ui, repo, dest, **opts):
302 302 '''create an unversioned archive of a repository revision
303 303
304 304 By default, the revision used is the parent of the working
305 305 directory; use -r/--rev to specify a different revision.
306 306
307 307 The archive type is automatically detected based on file
308 308 extension (or override using -t/--type).
309 309
310 310 .. container:: verbose
311 311
312 312 Examples:
313 313
314 314 - create a zip file containing the 1.0 release::
315 315
316 316 hg archive -r 1.0 project-1.0.zip
317 317
318 318 - create a tarball excluding .hg files::
319 319
320 320 hg archive project.tar.gz -X ".hg*"
321 321
322 322 Valid types are:
323 323
324 324 :``files``: a directory full of files (default)
325 325 :``tar``: tar archive, uncompressed
326 326 :``tbz2``: tar archive, compressed using bzip2
327 327 :``tgz``: tar archive, compressed using gzip
328 328 :``uzip``: zip archive, uncompressed
329 329 :``zip``: zip archive, compressed using deflate
330 330
331 331 The exact name of the destination archive or directory is given
332 332 using a format string; see :hg:`help export` for details.
333 333
334 334 Each member added to an archive file has a directory prefix
335 335 prepended. Use -p/--prefix to specify a format string for the
336 336 prefix. The default is the basename of the archive, with suffixes
337 337 removed.
338 338
339 339 Returns 0 on success.
340 340 '''
341 341
342 342 ctx = scmutil.revsingle(repo, opts.get('rev'))
343 343 if not ctx:
344 344 raise util.Abort(_('no working directory: please specify a revision'))
345 345 node = ctx.node()
346 346 dest = cmdutil.makefilename(repo, dest, node)
347 347 if os.path.realpath(dest) == repo.root:
348 348 raise util.Abort(_('repository root cannot be destination'))
349 349
350 350 kind = opts.get('type') or archival.guesskind(dest) or 'files'
351 351 prefix = opts.get('prefix')
352 352
353 353 if dest == '-':
354 354 if kind == 'files':
355 355 raise util.Abort(_('cannot archive plain files to stdout'))
356 356 dest = cmdutil.makefileobj(repo, dest)
357 357 if not prefix:
358 358 prefix = os.path.basename(repo.root) + '-%h'
359 359
360 360 prefix = cmdutil.makefilename(repo, prefix, node)
361 361 matchfn = scmutil.match(ctx, [], opts)
362 362 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
363 363 matchfn, prefix, subrepos=opts.get('subrepos'))
364 364
365 365 @command('backout',
366 366 [('', 'merge', None, _('merge with old dirstate parent after backout')),
367 367 ('', 'parent', '',
368 368 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
369 369 ('r', 'rev', '', _('revision to backout'), _('REV')),
370 370 ] + mergetoolopts + walkopts + commitopts + commitopts2,
371 371 _('[OPTION]... [-r] REV'))
372 372 def backout(ui, repo, node=None, rev=None, **opts):
373 373 '''reverse effect of earlier changeset
374 374
375 375 Prepare a new changeset with the effect of REV undone in the
376 376 current working directory.
377 377
378 378 If REV is the parent of the working directory, then this new changeset
379 379 is committed automatically. Otherwise, hg needs to merge the
380 380 changes and the merged result is left uncommitted.
381 381
382 382 .. note::
383 383 backout cannot be used to fix either an unwanted or
384 384 incorrect merge.
385 385
386 386 .. container:: verbose
387 387
388 388 By default, the pending changeset will have one parent,
389 389 maintaining a linear history. With --merge, the pending
390 390 changeset will instead have two parents: the old parent of the
391 391 working directory and a new child of REV that simply undoes REV.
392 392
393 393 Before version 1.7, the behavior without --merge was equivalent
394 394 to specifying --merge followed by :hg:`update --clean .` to
395 395 cancel the merge and leave the child of REV as a head to be
396 396 merged separately.
397 397
398 398 See :hg:`help dates` for a list of formats valid for -d/--date.
399 399
400 400 Returns 0 on success.
401 401 '''
402 402 if rev and node:
403 403 raise util.Abort(_("please specify just one revision"))
404 404
405 405 if not rev:
406 406 rev = node
407 407
408 408 if not rev:
409 409 raise util.Abort(_("please specify a revision to backout"))
410 410
411 411 date = opts.get('date')
412 412 if date:
413 413 opts['date'] = util.parsedate(date)
414 414
415 415 cmdutil.bailifchanged(repo)
416 416 node = scmutil.revsingle(repo, rev).node()
417 417
418 418 op1, op2 = repo.dirstate.parents()
419 419 a = repo.changelog.ancestor(op1, node)
420 420 if a != node:
421 421 raise util.Abort(_('cannot backout change on a different branch'))
422 422
423 423 p1, p2 = repo.changelog.parents(node)
424 424 if p1 == nullid:
425 425 raise util.Abort(_('cannot backout a change with no parents'))
426 426 if p2 != nullid:
427 427 if not opts.get('parent'):
428 428 raise util.Abort(_('cannot backout a merge changeset'))
429 429 p = repo.lookup(opts['parent'])
430 430 if p not in (p1, p2):
431 431 raise util.Abort(_('%s is not a parent of %s') %
432 432 (short(p), short(node)))
433 433 parent = p
434 434 else:
435 435 if opts.get('parent'):
436 436 raise util.Abort(_('cannot use --parent on non-merge changeset'))
437 437 parent = p1
438 438
439 439 # the backout should appear on the same branch
440 440 branch = repo.dirstate.branch()
441 441 hg.clean(repo, node, show_stats=False)
442 442 repo.dirstate.setbranch(branch)
443 443 revert_opts = opts.copy()
444 444 revert_opts['date'] = None
445 445 revert_opts['all'] = True
446 446 revert_opts['rev'] = hex(parent)
447 447 revert_opts['no_backup'] = None
448 448 revert(ui, repo, **revert_opts)
449 449 if not opts.get('merge') and op1 != node:
450 450 try:
451 451 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
452 452 return hg.update(repo, op1)
453 453 finally:
454 454 ui.setconfig('ui', 'forcemerge', '')
455 455
456 456 commit_opts = opts.copy()
457 457 commit_opts['addremove'] = False
458 458 if not commit_opts['message'] and not commit_opts['logfile']:
459 459 # we don't translate commit messages
460 460 commit_opts['message'] = "Backed out changeset %s" % short(node)
461 461 commit_opts['force_editor'] = True
462 462 commit(ui, repo, **commit_opts)
463 463 def nice(node):
464 464 return '%d:%s' % (repo.changelog.rev(node), short(node))
465 465 ui.status(_('changeset %s backs out changeset %s\n') %
466 466 (nice(repo.changelog.tip()), nice(node)))
467 467 if opts.get('merge') and op1 != node:
468 468 hg.clean(repo, op1, show_stats=False)
469 469 ui.status(_('merging with changeset %s\n')
470 470 % nice(repo.changelog.tip()))
471 471 try:
472 472 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
473 473 return hg.merge(repo, hex(repo.changelog.tip()))
474 474 finally:
475 475 ui.setconfig('ui', 'forcemerge', '')
476 476 return 0
477 477
478 478 @command('bisect',
479 479 [('r', 'reset', False, _('reset bisect state')),
480 480 ('g', 'good', False, _('mark changeset good')),
481 481 ('b', 'bad', False, _('mark changeset bad')),
482 482 ('s', 'skip', False, _('skip testing changeset')),
483 483 ('e', 'extend', False, _('extend the bisect range')),
484 484 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
485 485 ('U', 'noupdate', False, _('do not update to target'))],
486 486 _("[-gbsr] [-U] [-c CMD] [REV]"))
487 487 def bisect(ui, repo, rev=None, extra=None, command=None,
488 488 reset=None, good=None, bad=None, skip=None, extend=None,
489 489 noupdate=None):
490 490 """subdivision search of changesets
491 491
492 492 This command helps to find changesets which introduce problems. To
493 493 use, mark the earliest changeset you know exhibits the problem as
494 494 bad, then mark the latest changeset which is free from the problem
495 495 as good. Bisect will update your working directory to a revision
496 496 for testing (unless the -U/--noupdate option is specified). Once
497 497 you have performed tests, mark the working directory as good or
498 498 bad, and bisect will either update to another candidate changeset
499 499 or announce that it has found the bad revision.
500 500
501 501 As a shortcut, you can also use the revision argument to mark a
502 502 revision as good or bad without checking it out first.
503 503
504 504 If you supply a command, it will be used for automatic bisection.
505 505 Its exit status will be used to mark revisions as good or bad:
506 506 status 0 means good, 125 means to skip the revision, 127
507 507 (command not found) will abort the bisection, and any other
508 508 non-zero exit status means the revision is bad.
509 509
510 510 .. container:: verbose
511 511
512 512 Some examples:
513 513
514 514 - start a bisection with known bad revision 12, and good revision 34::
515 515
516 516 hg bisect --bad 34
517 517 hg bisect --good 12
518 518
519 519 - advance the current bisection by marking current revision as good or
520 520 bad::
521 521
522 522 hg bisect --good
523 523 hg bisect --bad
524 524
525 525 - mark the current revision, or a known revision, to be skipped (eg. if
526 526 that revision is not usable because of another issue)::
527 527
528 528 hg bisect --skip
529 529 hg bisect --skip 23
530 530
531 531 - forget the current bisection::
532 532
533 533 hg bisect --reset
534 534
535 535 - use 'make && make tests' to automatically find the first broken
536 536 revision::
537 537
538 538 hg bisect --reset
539 539 hg bisect --bad 34
540 540 hg bisect --good 12
541 541 hg bisect --command 'make && make tests'
542 542
543 543 - see all changesets whose states are already known in the current
544 544 bisection::
545 545
546 546 hg log -r "bisect(pruned)"
547 547
548 548 - see all changesets that took part in the current bisection::
549 549
550 550 hg log -r "bisect(range)"
551 551
552 552 - with the graphlog extension, you can even get a nice graph::
553 553
554 554 hg log --graph -r "bisect(range)"
555 555
556 556 See :hg:`help revsets` for more about the `bisect()` keyword.
557 557
558 558 Returns 0 on success.
559 559 """
560 560 def extendbisectrange(nodes, good):
561 561 # bisect is incomplete when it ends on a merge node and
562 562 # one of the parent was not checked.
563 563 parents = repo[nodes[0]].parents()
564 564 if len(parents) > 1:
565 565 side = good and state['bad'] or state['good']
566 566 num = len(set(i.node() for i in parents) & set(side))
567 567 if num == 1:
568 568 return parents[0].ancestor(parents[1])
569 569 return None
570 570
571 571 def print_result(nodes, good):
572 572 displayer = cmdutil.show_changeset(ui, repo, {})
573 573 if len(nodes) == 1:
574 574 # narrowed it down to a single revision
575 575 if good:
576 576 ui.write(_("The first good revision is:\n"))
577 577 else:
578 578 ui.write(_("The first bad revision is:\n"))
579 579 displayer.show(repo[nodes[0]])
580 580 extendnode = extendbisectrange(nodes, good)
581 581 if extendnode is not None:
582 582 ui.write(_('Not all ancestors of this changeset have been'
583 583 ' checked.\nUse bisect --extend to continue the '
584 584 'bisection from\nthe common ancestor, %s.\n')
585 585 % extendnode)
586 586 else:
587 587 # multiple possible revisions
588 588 if good:
589 589 ui.write(_("Due to skipped revisions, the first "
590 590 "good revision could be any of:\n"))
591 591 else:
592 592 ui.write(_("Due to skipped revisions, the first "
593 593 "bad revision could be any of:\n"))
594 594 for n in nodes:
595 595 displayer.show(repo[n])
596 596 displayer.close()
597 597
598 598 def check_state(state, interactive=True):
599 599 if not state['good'] or not state['bad']:
600 600 if (good or bad or skip or reset) and interactive:
601 601 return
602 602 if not state['good']:
603 603 raise util.Abort(_('cannot bisect (no known good revisions)'))
604 604 else:
605 605 raise util.Abort(_('cannot bisect (no known bad revisions)'))
606 606 return True
607 607
608 608 # backward compatibility
609 609 if rev in "good bad reset init".split():
610 610 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
611 611 cmd, rev, extra = rev, extra, None
612 612 if cmd == "good":
613 613 good = True
614 614 elif cmd == "bad":
615 615 bad = True
616 616 else:
617 617 reset = True
618 618 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
619 619 raise util.Abort(_('incompatible arguments'))
620 620
621 621 if reset:
622 622 p = repo.join("bisect.state")
623 623 if os.path.exists(p):
624 624 os.unlink(p)
625 625 return
626 626
627 627 state = hbisect.load_state(repo)
628 628
629 629 if command:
630 630 changesets = 1
631 631 try:
632 632 while changesets:
633 633 # update state
634 634 status = util.system(command, out=ui.fout)
635 635 if status == 125:
636 636 transition = "skip"
637 637 elif status == 0:
638 638 transition = "good"
639 639 # status < 0 means process was killed
640 640 elif status == 127:
641 641 raise util.Abort(_("failed to execute %s") % command)
642 642 elif status < 0:
643 643 raise util.Abort(_("%s killed") % command)
644 644 else:
645 645 transition = "bad"
646 646 ctx = scmutil.revsingle(repo, rev)
647 647 rev = None # clear for future iterations
648 648 state[transition].append(ctx.node())
649 649 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
650 650 check_state(state, interactive=False)
651 651 # bisect
652 652 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
653 653 # update to next check
654 654 cmdutil.bailifchanged(repo)
655 655 hg.clean(repo, nodes[0], show_stats=False)
656 656 finally:
657 657 hbisect.save_state(repo, state)
658 658 print_result(nodes, good)
659 659 return
660 660
661 661 # update state
662 662
663 663 if rev:
664 664 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
665 665 else:
666 666 nodes = [repo.lookup('.')]
667 667
668 668 if good or bad or skip:
669 669 if good:
670 670 state['good'] += nodes
671 671 elif bad:
672 672 state['bad'] += nodes
673 673 elif skip:
674 674 state['skip'] += nodes
675 675 hbisect.save_state(repo, state)
676 676
677 677 if not check_state(state):
678 678 return
679 679
680 680 # actually bisect
681 681 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
682 682 if extend:
683 683 if not changesets:
684 684 extendnode = extendbisectrange(nodes, good)
685 685 if extendnode is not None:
686 686 ui.write(_("Extending search to changeset %d:%s\n"
687 687 % (extendnode.rev(), extendnode)))
688 688 if noupdate:
689 689 return
690 690 cmdutil.bailifchanged(repo)
691 691 return hg.clean(repo, extendnode.node())
692 692 raise util.Abort(_("nothing to extend"))
693 693
694 694 if changesets == 0:
695 695 print_result(nodes, good)
696 696 else:
697 697 assert len(nodes) == 1 # only a single node can be tested next
698 698 node = nodes[0]
699 699 # compute the approximate number of remaining tests
700 700 tests, size = 0, 2
701 701 while size <= changesets:
702 702 tests, size = tests + 1, size * 2
703 703 rev = repo.changelog.rev(node)
704 704 ui.write(_("Testing changeset %d:%s "
705 705 "(%d changesets remaining, ~%d tests)\n")
706 706 % (rev, short(node), changesets, tests))
707 707 if not noupdate:
708 708 cmdutil.bailifchanged(repo)
709 709 return hg.clean(repo, node)
710 710
711 711 @command('bookmarks',
712 712 [('f', 'force', False, _('force')),
713 713 ('r', 'rev', '', _('revision'), _('REV')),
714 714 ('d', 'delete', False, _('delete a given bookmark')),
715 715 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
716 716 ('i', 'inactive', False, _('do not mark a new bookmark active'))],
717 717 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
718 718 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
719 719 rename=None, inactive=False):
720 720 '''track a line of development with movable markers
721 721
722 722 Bookmarks are pointers to certain commits that move when
723 723 committing. Bookmarks are local. They can be renamed, copied and
724 724 deleted. It is possible to use bookmark names in :hg:`merge` and
725 725 :hg:`update` to merge and update respectively to a given bookmark.
726 726
727 727 You can use :hg:`bookmark NAME` to set a bookmark on the working
728 728 directory's parent revision with the given name. If you specify
729 729 a revision using -r REV (where REV may be an existing bookmark),
730 730 the bookmark is assigned to that revision.
731 731
732 732 Bookmarks can be pushed and pulled between repositories (see :hg:`help
733 733 push` and :hg:`help pull`). This requires both the local and remote
734 734 repositories to support bookmarks. For versions prior to 1.8, this means
735 735 the bookmarks extension must be enabled.
736 736 '''
737 737 hexfn = ui.debugflag and hex or short
738 738 marks = repo._bookmarks
739 739 cur = repo.changectx('.').node()
740 740
741 741 if rename:
742 742 if rename not in marks:
743 743 raise util.Abort(_("bookmark '%s' does not exist") % rename)
744 744 if mark in marks and not force:
745 745 raise util.Abort(_("bookmark '%s' already exists "
746 746 "(use -f to force)") % mark)
747 747 if mark is None:
748 748 raise util.Abort(_("new bookmark name required"))
749 749 marks[mark] = marks[rename]
750 750 if repo._bookmarkcurrent == rename and not inactive:
751 751 bookmarks.setcurrent(repo, mark)
752 752 del marks[rename]
753 753 bookmarks.write(repo)
754 754 return
755 755
756 756 if delete:
757 757 if mark is None:
758 758 raise util.Abort(_("bookmark name required"))
759 759 if mark not in marks:
760 760 raise util.Abort(_("bookmark '%s' does not exist") % mark)
761 761 if mark == repo._bookmarkcurrent:
762 762 bookmarks.setcurrent(repo, None)
763 763 del marks[mark]
764 764 bookmarks.write(repo)
765 765 return
766 766
767 767 if mark is not None:
768 768 if "\n" in mark:
769 769 raise util.Abort(_("bookmark name cannot contain newlines"))
770 770 mark = mark.strip()
771 771 if not mark:
772 772 raise util.Abort(_("bookmark names cannot consist entirely of "
773 773 "whitespace"))
774 774 if inactive and mark == repo._bookmarkcurrent:
775 775 bookmarks.setcurrent(repo, None)
776 776 return
777 777 if mark in marks and not force:
778 778 raise util.Abort(_("bookmark '%s' already exists "
779 779 "(use -f to force)") % mark)
780 780 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
781 781 and not force):
782 782 raise util.Abort(
783 783 _("a bookmark cannot have the name of an existing branch"))
784 784 if rev:
785 785 marks[mark] = repo.lookup(rev)
786 786 else:
787 787 marks[mark] = repo.changectx('.').node()
788 788 if not inactive and repo.changectx('.').node() == marks[mark]:
789 789 bookmarks.setcurrent(repo, mark)
790 790 bookmarks.write(repo)
791 791 return
792 792
793 793 if mark is None:
794 794 if rev:
795 795 raise util.Abort(_("bookmark name required"))
796 796 if len(marks) == 0:
797 797 ui.status(_("no bookmarks set\n"))
798 798 else:
799 799 for bmark, n in sorted(marks.iteritems()):
800 800 current = repo._bookmarkcurrent
801 801 if bmark == current and n == cur:
802 802 prefix, label = '*', 'bookmarks.current'
803 803 else:
804 804 prefix, label = ' ', ''
805 805
806 806 if ui.quiet:
807 807 ui.write("%s\n" % bmark, label=label)
808 808 else:
809 809 ui.write(" %s %-25s %d:%s\n" % (
810 810 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
811 811 label=label)
812 812 return
813 813
814 814 @command('branch',
815 815 [('f', 'force', None,
816 816 _('set branch name even if it shadows an existing branch')),
817 817 ('C', 'clean', None, _('reset branch name to parent branch name'))],
818 818 _('[-fC] [NAME]'))
819 819 def branch(ui, repo, label=None, **opts):
820 820 """set or show the current branch name
821 821
822 822 With no argument, show the current branch name. With one argument,
823 823 set the working directory branch name (the branch will not exist
824 824 in the repository until the next commit). Standard practice
825 825 recommends that primary development take place on the 'default'
826 826 branch.
827 827
828 828 Unless -f/--force is specified, branch will not let you set a
829 829 branch name that already exists, even if it's inactive.
830 830
831 831 Use -C/--clean to reset the working directory branch to that of
832 832 the parent of the working directory, negating a previous branch
833 833 change.
834 834
835 835 Use the command :hg:`update` to switch to an existing branch. Use
836 836 :hg:`commit --close-branch` to mark this branch as closed.
837 837
838 838 .. note::
839 839 Branch names are permanent. Use :hg:`bookmark` to create a
840 840 light-weight bookmark instead. See :hg:`help glossary` for more
841 841 information about named branches and bookmarks.
842 842
843 843 Returns 0 on success.
844 844 """
845 845
846 846 if opts.get('clean'):
847 847 label = repo[None].p1().branch()
848 848 repo.dirstate.setbranch(label)
849 849 ui.status(_('reset working directory to branch %s\n') % label)
850 850 elif label:
851 851 if not opts.get('force') and label in repo.branchtags():
852 852 if label not in [p.branch() for p in repo.parents()]:
853 853 raise util.Abort(_('a branch of the same name already exists'),
854 854 # i18n: "it" refers to an existing branch
855 855 hint=_("use 'hg update' to switch to it"))
856 856 repo.dirstate.setbranch(label)
857 857 ui.status(_('marked working directory as branch %s\n') % label)
858 858 else:
859 859 ui.write("%s\n" % repo.dirstate.branch())
860 860
861 861 @command('branches',
862 862 [('a', 'active', False, _('show only branches that have unmerged heads')),
863 863 ('c', 'closed', False, _('show normal and closed branches'))],
864 864 _('[-ac]'))
865 865 def branches(ui, repo, active=False, closed=False):
866 866 """list repository named branches
867 867
868 868 List the repository's named branches, indicating which ones are
869 869 inactive. If -c/--closed is specified, also list branches which have
870 870 been marked closed (see :hg:`commit --close-branch`).
871 871
872 872 If -a/--active is specified, only show active branches. A branch
873 873 is considered active if it contains repository heads.
874 874
875 875 Use the command :hg:`update` to switch to an existing branch.
876 876
877 877 Returns 0.
878 878 """
879 879
880 880 hexfunc = ui.debugflag and hex or short
881 881 activebranches = [repo[n].branch() for n in repo.heads()]
882 882 def testactive(tag, node):
883 883 realhead = tag in activebranches
884 884 open = node in repo.branchheads(tag, closed=False)
885 885 return realhead and open
886 886 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
887 887 for tag, node in repo.branchtags().items()],
888 888 reverse=True)
889 889
890 890 for isactive, node, tag in branches:
891 891 if (not active) or isactive:
892 892 if ui.quiet:
893 893 ui.write("%s\n" % tag)
894 894 else:
895 895 hn = repo.lookup(node)
896 896 if isactive:
897 897 label = 'branches.active'
898 898 notice = ''
899 899 elif hn not in repo.branchheads(tag, closed=False):
900 900 if not closed:
901 901 continue
902 902 label = 'branches.closed'
903 903 notice = _(' (closed)')
904 904 else:
905 905 label = 'branches.inactive'
906 906 notice = _(' (inactive)')
907 907 if tag == repo.dirstate.branch():
908 908 label = 'branches.current'
909 909 rev = str(node).rjust(31 - encoding.colwidth(tag))
910 910 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
911 911 tag = ui.label(tag, label)
912 912 ui.write("%s %s%s\n" % (tag, rev, notice))
913 913
914 914 @command('bundle',
915 915 [('f', 'force', None, _('run even when the destination is unrelated')),
916 916 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
917 917 _('REV')),
918 918 ('b', 'branch', [], _('a specific branch you would like to bundle'),
919 919 _('BRANCH')),
920 920 ('', 'base', [],
921 921 _('a base changeset assumed to be available at the destination'),
922 922 _('REV')),
923 923 ('a', 'all', None, _('bundle all changesets in the repository')),
924 924 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
925 925 ] + remoteopts,
926 926 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
927 927 def bundle(ui, repo, fname, dest=None, **opts):
928 928 """create a changegroup file
929 929
930 930 Generate a compressed changegroup file collecting changesets not
931 931 known to be in another repository.
932 932
933 933 If you omit the destination repository, then hg assumes the
934 934 destination will have all the nodes you specify with --base
935 935 parameters. To create a bundle containing all changesets, use
936 936 -a/--all (or --base null).
937 937
938 938 You can change compression method with the -t/--type option.
939 939 The available compression methods are: none, bzip2, and
940 940 gzip (by default, bundles are compressed using bzip2).
941 941
942 942 The bundle file can then be transferred using conventional means
943 943 and applied to another repository with the unbundle or pull
944 944 command. This is useful when direct push and pull are not
945 945 available or when exporting an entire repository is undesirable.
946 946
947 947 Applying bundles preserves all changeset contents including
948 948 permissions, copy/rename information, and revision history.
949 949
950 950 Returns 0 on success, 1 if no changes found.
951 951 """
952 952 revs = None
953 953 if 'rev' in opts:
954 954 revs = scmutil.revrange(repo, opts['rev'])
955 955
956 956 if opts.get('all'):
957 957 base = ['null']
958 958 else:
959 959 base = scmutil.revrange(repo, opts.get('base'))
960 960 if base:
961 961 if dest:
962 962 raise util.Abort(_("--base is incompatible with specifying "
963 963 "a destination"))
964 964 common = [repo.lookup(rev) for rev in base]
965 965 heads = revs and map(repo.lookup, revs) or revs
966 966 else:
967 967 dest = ui.expandpath(dest or 'default-push', dest or 'default')
968 968 dest, branches = hg.parseurl(dest, opts.get('branch'))
969 969 other = hg.peer(repo, opts, dest)
970 970 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
971 971 heads = revs and map(repo.lookup, revs) or revs
972 972 common, outheads = discovery.findcommonoutgoing(repo, other,
973 973 onlyheads=heads,
974 974 force=opts.get('force'))
975 975
976 976 cg = repo.getbundle('bundle', common=common, heads=heads)
977 977 if not cg:
978 978 ui.status(_("no changes found\n"))
979 979 return 1
980 980
981 981 bundletype = opts.get('type', 'bzip2').lower()
982 982 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
983 983 bundletype = btypes.get(bundletype)
984 984 if bundletype not in changegroup.bundletypes:
985 985 raise util.Abort(_('unknown bundle type specified with --type'))
986 986
987 987 changegroup.writebundle(cg, fname, bundletype)
988 988
989 989 @command('cat',
990 990 [('o', 'output', '',
991 991 _('print output to file with formatted name'), _('FORMAT')),
992 992 ('r', 'rev', '', _('print the given revision'), _('REV')),
993 993 ('', 'decode', None, _('apply any matching decode filter')),
994 994 ] + walkopts,
995 995 _('[OPTION]... FILE...'))
996 996 def cat(ui, repo, file1, *pats, **opts):
997 997 """output the current or given revision of files
998 998
999 999 Print the specified files as they were at the given revision. If
1000 1000 no revision is given, the parent of the working directory is used,
1001 1001 or tip if no revision is checked out.
1002 1002
1003 1003 Output may be to a file, in which case the name of the file is
1004 1004 given using a format string. The formatting rules are the same as
1005 1005 for the export command, with the following additions:
1006 1006
1007 1007 :``%s``: basename of file being printed
1008 1008 :``%d``: dirname of file being printed, or '.' if in repository root
1009 1009 :``%p``: root-relative path name of file being printed
1010 1010
1011 1011 Returns 0 on success.
1012 1012 """
1013 1013 ctx = scmutil.revsingle(repo, opts.get('rev'))
1014 1014 err = 1
1015 1015 m = scmutil.match(ctx, (file1,) + pats, opts)
1016 1016 for abs in ctx.walk(m):
1017 1017 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1018 1018 pathname=abs)
1019 1019 data = ctx[abs].data()
1020 1020 if opts.get('decode'):
1021 1021 data = repo.wwritedata(abs, data)
1022 1022 fp.write(data)
1023 1023 fp.close()
1024 1024 err = 0
1025 1025 return err
1026 1026
1027 1027 @command('^clone',
1028 1028 [('U', 'noupdate', None,
1029 1029 _('the clone will include an empty working copy (only a repository)')),
1030 1030 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1031 1031 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1032 1032 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1033 1033 ('', 'pull', None, _('use pull protocol to copy metadata')),
1034 1034 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1035 1035 ] + remoteopts,
1036 1036 _('[OPTION]... SOURCE [DEST]'))
1037 1037 def clone(ui, source, dest=None, **opts):
1038 1038 """make a copy of an existing repository
1039 1039
1040 1040 Create a copy of an existing repository in a new directory.
1041 1041
1042 1042 If no destination directory name is specified, it defaults to the
1043 1043 basename of the source.
1044 1044
1045 1045 The location of the source is added to the new repository's
1046 1046 ``.hg/hgrc`` file, as the default to be used for future pulls.
1047 1047
1048 1048 Only local paths and ``ssh://`` URLs are supported as
1049 1049 destinations. For ``ssh://`` destinations, no working directory or
1050 1050 ``.hg/hgrc`` will be created on the remote side.
1051 1051
1052 1052 To pull only a subset of changesets, specify one or more revisions
1053 1053 identifiers with -r/--rev or branches with -b/--branch. The
1054 1054 resulting clone will contain only the specified changesets and
1055 1055 their ancestors. These options (or 'clone src#rev dest') imply
1056 1056 --pull, even for local source repositories. Note that specifying a
1057 1057 tag will include the tagged changeset but not the changeset
1058 1058 containing the tag.
1059 1059
1060 1060 To check out a particular version, use -u/--update, or
1061 1061 -U/--noupdate to create a clone with no working directory.
1062 1062
1063 1063 .. container:: verbose
1064 1064
1065 1065 For efficiency, hardlinks are used for cloning whenever the
1066 1066 source and destination are on the same filesystem (note this
1067 1067 applies only to the repository data, not to the working
1068 1068 directory). Some filesystems, such as AFS, implement hardlinking
1069 1069 incorrectly, but do not report errors. In these cases, use the
1070 1070 --pull option to avoid hardlinking.
1071 1071
1072 1072 In some cases, you can clone repositories and the working
1073 1073 directory using full hardlinks with ::
1074 1074
1075 1075 $ cp -al REPO REPOCLONE
1076 1076
1077 1077 This is the fastest way to clone, but it is not always safe. The
1078 1078 operation is not atomic (making sure REPO is not modified during
1079 1079 the operation is up to you) and you have to make sure your
1080 1080 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1081 1081 so). Also, this is not compatible with certain extensions that
1082 1082 place their metadata under the .hg directory, such as mq.
1083 1083
1084 1084 Mercurial will update the working directory to the first applicable
1085 1085 revision from this list:
1086 1086
1087 1087 a) null if -U or the source repository has no changesets
1088 1088 b) if -u . and the source repository is local, the first parent of
1089 1089 the source repository's working directory
1090 1090 c) the changeset specified with -u (if a branch name, this means the
1091 1091 latest head of that branch)
1092 1092 d) the changeset specified with -r
1093 1093 e) the tipmost head specified with -b
1094 1094 f) the tipmost head specified with the url#branch source syntax
1095 1095 g) the tipmost head of the default branch
1096 1096 h) tip
1097 1097
1098 1098 Examples:
1099 1099
1100 1100 - clone a remote repository to a new directory named hg/::
1101 1101
1102 1102 hg clone http://selenic.com/hg
1103 1103
1104 1104 - create a lightweight local clone::
1105 1105
1106 1106 hg clone project/ project-feature/
1107 1107
1108 1108 - clone from an absolute path on an ssh server (note double-slash)::
1109 1109
1110 1110 hg clone ssh://user@server//home/projects/alpha/
1111 1111
1112 1112 - do a high-speed clone over a LAN while checking out a
1113 1113 specified version::
1114 1114
1115 1115 hg clone --uncompressed http://server/repo -u 1.5
1116 1116
1117 1117 - create a repository without changesets after a particular revision::
1118 1118
1119 1119 hg clone -r 04e544 experimental/ good/
1120 1120
1121 1121 - clone (and track) a particular named branch::
1122 1122
1123 1123 hg clone http://selenic.com/hg#stable
1124 1124
1125 1125 See :hg:`help urls` for details on specifying URLs.
1126 1126
1127 1127 Returns 0 on success.
1128 1128 """
1129 1129 if opts.get('noupdate') and opts.get('updaterev'):
1130 1130 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1131 1131
1132 1132 r = hg.clone(ui, opts, source, dest,
1133 1133 pull=opts.get('pull'),
1134 1134 stream=opts.get('uncompressed'),
1135 1135 rev=opts.get('rev'),
1136 1136 update=opts.get('updaterev') or not opts.get('noupdate'),
1137 1137 branch=opts.get('branch'))
1138 1138
1139 1139 return r is None
1140 1140
1141 1141 @command('^commit|ci',
1142 1142 [('A', 'addremove', None,
1143 1143 _('mark new/missing files as added/removed before committing')),
1144 1144 ('', 'close-branch', None,
1145 1145 _('mark a branch as closed, hiding it from the branch list')),
1146 1146 ] + walkopts + commitopts + commitopts2,
1147 1147 _('[OPTION]... [FILE]...'))
1148 1148 def commit(ui, repo, *pats, **opts):
1149 1149 """commit the specified files or all outstanding changes
1150 1150
1151 1151 Commit changes to the given files into the repository. Unlike a
1152 1152 centralized SCM, this operation is a local operation. See
1153 1153 :hg:`push` for a way to actively distribute your changes.
1154 1154
1155 1155 If a list of files is omitted, all changes reported by :hg:`status`
1156 1156 will be committed.
1157 1157
1158 1158 If you are committing the result of a merge, do not provide any
1159 1159 filenames or -I/-X filters.
1160 1160
1161 1161 If no commit message is specified, Mercurial starts your
1162 1162 configured editor where you can enter a message. In case your
1163 1163 commit fails, you will find a backup of your message in
1164 1164 ``.hg/last-message.txt``.
1165 1165
1166 1166 See :hg:`help dates` for a list of formats valid for -d/--date.
1167 1167
1168 1168 Returns 0 on success, 1 if nothing changed.
1169 1169 """
1170 1170 extra = {}
1171 1171 if opts.get('close_branch'):
1172 1172 if repo['.'].node() not in repo.branchheads():
1173 1173 # The topo heads set is included in the branch heads set of the
1174 1174 # current branch, so it's sufficient to test branchheads
1175 1175 raise util.Abort(_('can only close branch heads'))
1176 1176 extra['close'] = 1
1177 1177 e = cmdutil.commiteditor
1178 1178 if opts.get('force_editor'):
1179 1179 e = cmdutil.commitforceeditor
1180 1180
1181 1181 def commitfunc(ui, repo, message, match, opts):
1182 1182 return repo.commit(message, opts.get('user'), opts.get('date'), match,
1183 1183 editor=e, extra=extra)
1184 1184
1185 1185 branch = repo[None].branch()
1186 1186 bheads = repo.branchheads(branch)
1187 1187
1188 1188 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1189 1189 if not node:
1190 1190 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1191 1191 if stat[3]:
1192 1192 ui.status(_("nothing changed (%d missing files, see 'hg status')\n")
1193 1193 % len(stat[3]))
1194 1194 else:
1195 1195 ui.status(_("nothing changed\n"))
1196 1196 return 1
1197 1197
1198 1198 ctx = repo[node]
1199 1199 parents = ctx.parents()
1200 1200
1201 1201 if (bheads and node not in bheads and not
1202 1202 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1203 1203 ui.status(_('created new head\n'))
1204 1204 # The message is not printed for initial roots. For the other
1205 1205 # changesets, it is printed in the following situations:
1206 1206 #
1207 1207 # Par column: for the 2 parents with ...
1208 1208 # N: null or no parent
1209 1209 # B: parent is on another named branch
1210 1210 # C: parent is a regular non head changeset
1211 1211 # H: parent was a branch head of the current branch
1212 1212 # Msg column: whether we print "created new head" message
1213 1213 # In the following, it is assumed that there already exists some
1214 1214 # initial branch heads of the current branch, otherwise nothing is
1215 1215 # printed anyway.
1216 1216 #
1217 1217 # Par Msg Comment
1218 1218 # NN y additional topo root
1219 1219 #
1220 1220 # BN y additional branch root
1221 1221 # CN y additional topo head
1222 1222 # HN n usual case
1223 1223 #
1224 1224 # BB y weird additional branch root
1225 1225 # CB y branch merge
1226 1226 # HB n merge with named branch
1227 1227 #
1228 1228 # CC y additional head from merge
1229 1229 # CH n merge with a head
1230 1230 #
1231 1231 # HH n head merge: head count decreases
1232 1232
1233 1233 if not opts.get('close_branch'):
1234 1234 for r in parents:
1235 1235 if r.extra().get('close') and r.branch() == branch:
1236 1236 ui.status(_('reopening closed branch head %d\n') % r)
1237 1237
1238 1238 if ui.debugflag:
1239 1239 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1240 1240 elif ui.verbose:
1241 1241 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1242 1242
1243 1243 @command('copy|cp',
1244 1244 [('A', 'after', None, _('record a copy that has already occurred')),
1245 1245 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1246 1246 ] + walkopts + dryrunopts,
1247 1247 _('[OPTION]... [SOURCE]... DEST'))
1248 1248 def copy(ui, repo, *pats, **opts):
1249 1249 """mark files as copied for the next commit
1250 1250
1251 1251 Mark dest as having copies of source files. If dest is a
1252 1252 directory, copies are put in that directory. If dest is a file,
1253 1253 the source must be a single file.
1254 1254
1255 1255 By default, this command copies the contents of files as they
1256 1256 exist in the working directory. If invoked with -A/--after, the
1257 1257 operation is recorded, but no copying is performed.
1258 1258
1259 1259 This command takes effect with the next commit. To undo a copy
1260 1260 before that, see :hg:`revert`.
1261 1261
1262 1262 Returns 0 on success, 1 if errors are encountered.
1263 1263 """
1264 1264 wlock = repo.wlock(False)
1265 1265 try:
1266 1266 return cmdutil.copy(ui, repo, pats, opts)
1267 1267 finally:
1268 1268 wlock.release()
1269 1269
1270 1270 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1271 1271 def debugancestor(ui, repo, *args):
1272 1272 """find the ancestor revision of two revisions in a given index"""
1273 1273 if len(args) == 3:
1274 1274 index, rev1, rev2 = args
1275 1275 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1276 1276 lookup = r.lookup
1277 1277 elif len(args) == 2:
1278 1278 if not repo:
1279 1279 raise util.Abort(_("there is no Mercurial repository here "
1280 1280 "(.hg not found)"))
1281 1281 rev1, rev2 = args
1282 1282 r = repo.changelog
1283 1283 lookup = repo.lookup
1284 1284 else:
1285 1285 raise util.Abort(_('either two or three arguments required'))
1286 1286 a = r.ancestor(lookup(rev1), lookup(rev2))
1287 1287 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1288 1288
1289 1289 @command('debugbuilddag',
1290 1290 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1291 1291 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1292 1292 ('n', 'new-file', None, _('add new file at each rev'))],
1293 1293 _('[OPTION]... [TEXT]'))
1294 1294 def debugbuilddag(ui, repo, text=None,
1295 1295 mergeable_file=False,
1296 1296 overwritten_file=False,
1297 1297 new_file=False):
1298 1298 """builds a repo with a given DAG from scratch in the current empty repo
1299 1299
1300 1300 The description of the DAG is read from stdin if not given on the
1301 1301 command line.
1302 1302
1303 1303 Elements:
1304 1304
1305 1305 - "+n" is a linear run of n nodes based on the current default parent
1306 1306 - "." is a single node based on the current default parent
1307 1307 - "$" resets the default parent to null (implied at the start);
1308 1308 otherwise the default parent is always the last node created
1309 1309 - "<p" sets the default parent to the backref p
1310 1310 - "*p" is a fork at parent p, which is a backref
1311 1311 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1312 1312 - "/p2" is a merge of the preceding node and p2
1313 1313 - ":tag" defines a local tag for the preceding node
1314 1314 - "@branch" sets the named branch for subsequent nodes
1315 1315 - "#...\\n" is a comment up to the end of the line
1316 1316
1317 1317 Whitespace between the above elements is ignored.
1318 1318
1319 1319 A backref is either
1320 1320
1321 1321 - a number n, which references the node curr-n, where curr is the current
1322 1322 node, or
1323 1323 - the name of a local tag you placed earlier using ":tag", or
1324 1324 - empty to denote the default parent.
1325 1325
1326 1326 All string valued-elements are either strictly alphanumeric, or must
1327 1327 be enclosed in double quotes ("..."), with "\\" as escape character.
1328 1328 """
1329 1329
1330 1330 if text is None:
1331 1331 ui.status(_("reading DAG from stdin\n"))
1332 1332 text = ui.fin.read()
1333 1333
1334 1334 cl = repo.changelog
1335 1335 if len(cl) > 0:
1336 1336 raise util.Abort(_('repository is not empty'))
1337 1337
1338 1338 # determine number of revs in DAG
1339 1339 total = 0
1340 1340 for type, data in dagparser.parsedag(text):
1341 1341 if type == 'n':
1342 1342 total += 1
1343 1343
1344 1344 if mergeable_file:
1345 1345 linesperrev = 2
1346 1346 # make a file with k lines per rev
1347 1347 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1348 1348 initialmergedlines.append("")
1349 1349
1350 1350 tags = []
1351 1351
1352 1352 tr = repo.transaction("builddag")
1353 1353 try:
1354 1354
1355 1355 at = -1
1356 1356 atbranch = 'default'
1357 1357 nodeids = []
1358 1358 ui.progress(_('building'), 0, unit=_('revisions'), total=total)
1359 1359 for type, data in dagparser.parsedag(text):
1360 1360 if type == 'n':
1361 1361 ui.note('node %s\n' % str(data))
1362 1362 id, ps = data
1363 1363
1364 1364 files = []
1365 1365 fctxs = {}
1366 1366
1367 1367 p2 = None
1368 1368 if mergeable_file:
1369 1369 fn = "mf"
1370 1370 p1 = repo[ps[0]]
1371 1371 if len(ps) > 1:
1372 1372 p2 = repo[ps[1]]
1373 1373 pa = p1.ancestor(p2)
1374 1374 base, local, other = [x[fn].data() for x in pa, p1, p2]
1375 1375 m3 = simplemerge.Merge3Text(base, local, other)
1376 1376 ml = [l.strip() for l in m3.merge_lines()]
1377 1377 ml.append("")
1378 1378 elif at > 0:
1379 1379 ml = p1[fn].data().split("\n")
1380 1380 else:
1381 1381 ml = initialmergedlines
1382 1382 ml[id * linesperrev] += " r%i" % id
1383 1383 mergedtext = "\n".join(ml)
1384 1384 files.append(fn)
1385 1385 fctxs[fn] = context.memfilectx(fn, mergedtext)
1386 1386
1387 1387 if overwritten_file:
1388 1388 fn = "of"
1389 1389 files.append(fn)
1390 1390 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1391 1391
1392 1392 if new_file:
1393 1393 fn = "nf%i" % id
1394 1394 files.append(fn)
1395 1395 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1396 1396 if len(ps) > 1:
1397 1397 if not p2:
1398 1398 p2 = repo[ps[1]]
1399 1399 for fn in p2:
1400 1400 if fn.startswith("nf"):
1401 1401 files.append(fn)
1402 1402 fctxs[fn] = p2[fn]
1403 1403
1404 1404 def fctxfn(repo, cx, path):
1405 1405 return fctxs.get(path)
1406 1406
1407 1407 if len(ps) == 0 or ps[0] < 0:
1408 1408 pars = [None, None]
1409 1409 elif len(ps) == 1:
1410 1410 pars = [nodeids[ps[0]], None]
1411 1411 else:
1412 1412 pars = [nodeids[p] for p in ps]
1413 1413 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1414 1414 date=(id, 0),
1415 1415 user="debugbuilddag",
1416 1416 extra={'branch': atbranch})
1417 1417 nodeid = repo.commitctx(cx)
1418 1418 nodeids.append(nodeid)
1419 1419 at = id
1420 1420 elif type == 'l':
1421 1421 id, name = data
1422 1422 ui.note('tag %s\n' % name)
1423 1423 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1424 1424 elif type == 'a':
1425 1425 ui.note('branch %s\n' % data)
1426 1426 atbranch = data
1427 1427 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1428 1428 tr.close()
1429 1429 finally:
1430 1430 ui.progress(_('building'), None)
1431 1431 tr.release()
1432 1432
1433 1433 if tags:
1434 1434 repo.opener.write("localtags", "".join(tags))
1435 1435
1436 1436 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1437 1437 def debugbundle(ui, bundlepath, all=None, **opts):
1438 1438 """lists the contents of a bundle"""
1439 1439 f = url.open(ui, bundlepath)
1440 1440 try:
1441 1441 gen = changegroup.readbundle(f, bundlepath)
1442 1442 if all:
1443 1443 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1444 1444
1445 1445 def showchunks(named):
1446 1446 ui.write("\n%s\n" % named)
1447 1447 chain = None
1448 1448 while True:
1449 1449 chunkdata = gen.deltachunk(chain)
1450 1450 if not chunkdata:
1451 1451 break
1452 1452 node = chunkdata['node']
1453 1453 p1 = chunkdata['p1']
1454 1454 p2 = chunkdata['p2']
1455 1455 cs = chunkdata['cs']
1456 1456 deltabase = chunkdata['deltabase']
1457 1457 delta = chunkdata['delta']
1458 1458 ui.write("%s %s %s %s %s %s\n" %
1459 1459 (hex(node), hex(p1), hex(p2),
1460 1460 hex(cs), hex(deltabase), len(delta)))
1461 1461 chain = node
1462 1462
1463 1463 chunkdata = gen.changelogheader()
1464 1464 showchunks("changelog")
1465 1465 chunkdata = gen.manifestheader()
1466 1466 showchunks("manifest")
1467 1467 while True:
1468 1468 chunkdata = gen.filelogheader()
1469 1469 if not chunkdata:
1470 1470 break
1471 1471 fname = chunkdata['filename']
1472 1472 showchunks(fname)
1473 1473 else:
1474 1474 chunkdata = gen.changelogheader()
1475 1475 chain = None
1476 1476 while True:
1477 1477 chunkdata = gen.deltachunk(chain)
1478 1478 if not chunkdata:
1479 1479 break
1480 1480 node = chunkdata['node']
1481 1481 ui.write("%s\n" % hex(node))
1482 1482 chain = node
1483 1483 finally:
1484 1484 f.close()
1485 1485
1486 1486 @command('debugcheckstate', [], '')
1487 1487 def debugcheckstate(ui, repo):
1488 1488 """validate the correctness of the current dirstate"""
1489 1489 parent1, parent2 = repo.dirstate.parents()
1490 1490 m1 = repo[parent1].manifest()
1491 1491 m2 = repo[parent2].manifest()
1492 1492 errors = 0
1493 1493 for f in repo.dirstate:
1494 1494 state = repo.dirstate[f]
1495 1495 if state in "nr" and f not in m1:
1496 1496 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1497 1497 errors += 1
1498 1498 if state in "a" and f in m1:
1499 1499 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1500 1500 errors += 1
1501 1501 if state in "m" and f not in m1 and f not in m2:
1502 1502 ui.warn(_("%s in state %s, but not in either manifest\n") %
1503 1503 (f, state))
1504 1504 errors += 1
1505 1505 for f in m1:
1506 1506 state = repo.dirstate[f]
1507 1507 if state not in "nrm":
1508 1508 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1509 1509 errors += 1
1510 1510 if errors:
1511 1511 error = _(".hg/dirstate inconsistent with current parent's manifest")
1512 1512 raise util.Abort(error)
1513 1513
1514 1514 @command('debugcommands', [], _('[COMMAND]'))
1515 1515 def debugcommands(ui, cmd='', *args):
1516 1516 """list all available commands and options"""
1517 1517 for cmd, vals in sorted(table.iteritems()):
1518 1518 cmd = cmd.split('|')[0].strip('^')
1519 1519 opts = ', '.join([i[1] for i in vals[1]])
1520 1520 ui.write('%s: %s\n' % (cmd, opts))
1521 1521
1522 1522 @command('debugcomplete',
1523 1523 [('o', 'options', None, _('show the command options'))],
1524 1524 _('[-o] CMD'))
1525 1525 def debugcomplete(ui, cmd='', **opts):
1526 1526 """returns the completion list associated with the given command"""
1527 1527
1528 1528 if opts.get('options'):
1529 1529 options = []
1530 1530 otables = [globalopts]
1531 1531 if cmd:
1532 1532 aliases, entry = cmdutil.findcmd(cmd, table, False)
1533 1533 otables.append(entry[1])
1534 1534 for t in otables:
1535 1535 for o in t:
1536 1536 if "(DEPRECATED)" in o[3]:
1537 1537 continue
1538 1538 if o[0]:
1539 1539 options.append('-%s' % o[0])
1540 1540 options.append('--%s' % o[1])
1541 1541 ui.write("%s\n" % "\n".join(options))
1542 1542 return
1543 1543
1544 1544 cmdlist = cmdutil.findpossible(cmd, table)
1545 1545 if ui.verbose:
1546 1546 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1547 1547 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1548 1548
1549 1549 @command('debugdag',
1550 1550 [('t', 'tags', None, _('use tags as labels')),
1551 1551 ('b', 'branches', None, _('annotate with branch names')),
1552 1552 ('', 'dots', None, _('use dots for runs')),
1553 1553 ('s', 'spaces', None, _('separate elements by spaces'))],
1554 1554 _('[OPTION]... [FILE [REV]...]'))
1555 1555 def debugdag(ui, repo, file_=None, *revs, **opts):
1556 1556 """format the changelog or an index DAG as a concise textual description
1557 1557
1558 1558 If you pass a revlog index, the revlog's DAG is emitted. If you list
1559 1559 revision numbers, they get labelled in the output as rN.
1560 1560
1561 1561 Otherwise, the changelog DAG of the current repo is emitted.
1562 1562 """
1563 1563 spaces = opts.get('spaces')
1564 1564 dots = opts.get('dots')
1565 1565 if file_:
1566 1566 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1567 1567 revs = set((int(r) for r in revs))
1568 1568 def events():
1569 1569 for r in rlog:
1570 1570 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1571 1571 if r in revs:
1572 1572 yield 'l', (r, "r%i" % r)
1573 1573 elif repo:
1574 1574 cl = repo.changelog
1575 1575 tags = opts.get('tags')
1576 1576 branches = opts.get('branches')
1577 1577 if tags:
1578 1578 labels = {}
1579 1579 for l, n in repo.tags().items():
1580 1580 labels.setdefault(cl.rev(n), []).append(l)
1581 1581 def events():
1582 1582 b = "default"
1583 1583 for r in cl:
1584 1584 if branches:
1585 1585 newb = cl.read(cl.node(r))[5]['branch']
1586 1586 if newb != b:
1587 1587 yield 'a', newb
1588 1588 b = newb
1589 1589 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1590 1590 if tags:
1591 1591 ls = labels.get(r)
1592 1592 if ls:
1593 1593 for l in ls:
1594 1594 yield 'l', (r, l)
1595 1595 else:
1596 1596 raise util.Abort(_('need repo for changelog dag'))
1597 1597
1598 1598 for line in dagparser.dagtextlines(events(),
1599 1599 addspaces=spaces,
1600 1600 wraplabels=True,
1601 1601 wrapannotations=True,
1602 1602 wrapnonlinear=dots,
1603 1603 usedots=dots,
1604 1604 maxlinewidth=70):
1605 1605 ui.write(line)
1606 1606 ui.write("\n")
1607 1607
1608 1608 @command('debugdata',
1609 1609 [('c', 'changelog', False, _('open changelog')),
1610 1610 ('m', 'manifest', False, _('open manifest'))],
1611 1611 _('-c|-m|FILE REV'))
1612 1612 def debugdata(ui, repo, file_, rev = None, **opts):
1613 1613 """dump the contents of a data file revision"""
1614 1614 if opts.get('changelog') or opts.get('manifest'):
1615 1615 file_, rev = None, file_
1616 1616 elif rev is None:
1617 1617 raise error.CommandError('debugdata', _('invalid arguments'))
1618 1618 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1619 1619 try:
1620 1620 ui.write(r.revision(r.lookup(rev)))
1621 1621 except KeyError:
1622 1622 raise util.Abort(_('invalid revision identifier %s') % rev)
1623 1623
1624 1624 @command('debugdate',
1625 1625 [('e', 'extended', None, _('try extended date formats'))],
1626 1626 _('[-e] DATE [RANGE]'))
1627 1627 def debugdate(ui, date, range=None, **opts):
1628 1628 """parse and display a date"""
1629 1629 if opts["extended"]:
1630 1630 d = util.parsedate(date, util.extendeddateformats)
1631 1631 else:
1632 1632 d = util.parsedate(date)
1633 1633 ui.write("internal: %s %s\n" % d)
1634 1634 ui.write("standard: %s\n" % util.datestr(d))
1635 1635 if range:
1636 1636 m = util.matchdate(range)
1637 1637 ui.write("match: %s\n" % m(d[0]))
1638 1638
1639 1639 @command('debugdiscovery',
1640 1640 [('', 'old', None, _('use old-style discovery')),
1641 1641 ('', 'nonheads', None,
1642 1642 _('use old-style discovery with non-heads included')),
1643 1643 ] + remoteopts,
1644 1644 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1645 1645 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1646 1646 """runs the changeset discovery protocol in isolation"""
1647 1647 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl), opts.get('branch'))
1648 1648 remote = hg.peer(repo, opts, remoteurl)
1649 1649 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1650 1650
1651 1651 # make sure tests are repeatable
1652 1652 random.seed(12323)
1653 1653
1654 1654 def doit(localheads, remoteheads):
1655 1655 if opts.get('old'):
1656 1656 if localheads:
1657 1657 raise util.Abort('cannot use localheads with old style discovery')
1658 1658 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1659 1659 force=True)
1660 1660 common = set(common)
1661 1661 if not opts.get('nonheads'):
1662 1662 ui.write("unpruned common: %s\n" % " ".join([short(n)
1663 1663 for n in common]))
1664 1664 dag = dagutil.revlogdag(repo.changelog)
1665 1665 all = dag.ancestorset(dag.internalizeall(common))
1666 1666 common = dag.externalizeall(dag.headsetofconnecteds(all))
1667 1667 else:
1668 1668 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1669 1669 common = set(common)
1670 1670 rheads = set(hds)
1671 1671 lheads = set(repo.heads())
1672 1672 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1673 1673 if lheads <= common:
1674 1674 ui.write("local is subset\n")
1675 1675 elif rheads <= common:
1676 1676 ui.write("remote is subset\n")
1677 1677
1678 1678 serverlogs = opts.get('serverlog')
1679 1679 if serverlogs:
1680 1680 for filename in serverlogs:
1681 1681 logfile = open(filename, 'r')
1682 1682 try:
1683 1683 line = logfile.readline()
1684 1684 while line:
1685 1685 parts = line.strip().split(';')
1686 1686 op = parts[1]
1687 1687 if op == 'cg':
1688 1688 pass
1689 1689 elif op == 'cgss':
1690 1690 doit(parts[2].split(' '), parts[3].split(' '))
1691 1691 elif op == 'unb':
1692 1692 doit(parts[3].split(' '), parts[2].split(' '))
1693 1693 line = logfile.readline()
1694 1694 finally:
1695 1695 logfile.close()
1696 1696
1697 1697 else:
1698 1698 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1699 1699 opts.get('remote_head'))
1700 1700 localrevs = opts.get('local_head')
1701 1701 doit(localrevs, remoterevs)
1702 1702
1703 1703 @command('debugfileset', [], ('REVSPEC'))
1704 1704 def debugfileset(ui, repo, expr):
1705 1705 '''parse and apply a fileset specification'''
1706 1706 if ui.verbose:
1707 1707 tree = fileset.parse(expr)[0]
1708 1708 ui.note(tree, "\n")
1709 1709
1710 1710 for f in fileset.getfileset(repo[None], expr):
1711 1711 ui.write("%s\n" % f)
1712 1712
1713 1713 @command('debugfsinfo', [], _('[PATH]'))
1714 1714 def debugfsinfo(ui, path = "."):
1715 1715 """show information detected about current filesystem"""
1716 1716 util.writefile('.debugfsinfo', '')
1717 1717 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1718 1718 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1719 1719 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1720 1720 and 'yes' or 'no'))
1721 1721 os.unlink('.debugfsinfo')
1722 1722
1723 1723 @command('debuggetbundle',
1724 1724 [('H', 'head', [], _('id of head node'), _('ID')),
1725 1725 ('C', 'common', [], _('id of common node'), _('ID')),
1726 1726 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1727 1727 _('REPO FILE [-H|-C ID]...'))
1728 1728 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1729 1729 """retrieves a bundle from a repo
1730 1730
1731 1731 Every ID must be a full-length hex node id string. Saves the bundle to the
1732 1732 given file.
1733 1733 """
1734 1734 repo = hg.peer(ui, opts, repopath)
1735 1735 if not repo.capable('getbundle'):
1736 1736 raise util.Abort("getbundle() not supported by target repository")
1737 1737 args = {}
1738 1738 if common:
1739 1739 args['common'] = [bin(s) for s in common]
1740 1740 if head:
1741 1741 args['heads'] = [bin(s) for s in head]
1742 1742 bundle = repo.getbundle('debug', **args)
1743 1743
1744 1744 bundletype = opts.get('type', 'bzip2').lower()
1745 1745 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1746 1746 bundletype = btypes.get(bundletype)
1747 1747 if bundletype not in changegroup.bundletypes:
1748 1748 raise util.Abort(_('unknown bundle type specified with --type'))
1749 1749 changegroup.writebundle(bundle, bundlepath, bundletype)
1750 1750
1751 1751 @command('debugignore', [], '')
1752 1752 def debugignore(ui, repo, *values, **opts):
1753 1753 """display the combined ignore pattern"""
1754 1754 ignore = repo.dirstate._ignore
1755 1755 includepat = getattr(ignore, 'includepat', None)
1756 1756 if includepat is not None:
1757 1757 ui.write("%s\n" % includepat)
1758 1758 else:
1759 1759 raise util.Abort(_("no ignore patterns found"))
1760 1760
1761 1761 @command('debugindex',
1762 1762 [('c', 'changelog', False, _('open changelog')),
1763 1763 ('m', 'manifest', False, _('open manifest')),
1764 1764 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1765 1765 _('[-f FORMAT] -c|-m|FILE'))
1766 1766 def debugindex(ui, repo, file_ = None, **opts):
1767 1767 """dump the contents of an index file"""
1768 1768 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1769 1769 format = opts.get('format', 0)
1770 1770 if format not in (0, 1):
1771 1771 raise util.Abort(_("unknown format %d") % format)
1772 1772
1773 1773 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1774 1774 if generaldelta:
1775 1775 basehdr = ' delta'
1776 1776 else:
1777 1777 basehdr = ' base'
1778 1778
1779 1779 if format == 0:
1780 1780 ui.write(" rev offset length " + basehdr + " linkrev"
1781 1781 " nodeid p1 p2\n")
1782 1782 elif format == 1:
1783 1783 ui.write(" rev flag offset length"
1784 1784 " size " + basehdr + " link p1 p2 nodeid\n")
1785 1785
1786 1786 for i in r:
1787 1787 node = r.node(i)
1788 1788 if generaldelta:
1789 1789 base = r.deltaparent(i)
1790 1790 else:
1791 1791 base = r.chainbase(i)
1792 1792 if format == 0:
1793 1793 try:
1794 1794 pp = r.parents(node)
1795 1795 except:
1796 1796 pp = [nullid, nullid]
1797 1797 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1798 1798 i, r.start(i), r.length(i), base, r.linkrev(i),
1799 1799 short(node), short(pp[0]), short(pp[1])))
1800 1800 elif format == 1:
1801 1801 pr = r.parentrevs(i)
1802 1802 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1803 1803 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1804 1804 base, r.linkrev(i), pr[0], pr[1], short(node)))
1805 1805
1806 1806 @command('debugindexdot', [], _('FILE'))
1807 1807 def debugindexdot(ui, repo, file_):
1808 1808 """dump an index DAG as a graphviz dot file"""
1809 1809 r = None
1810 1810 if repo:
1811 1811 filelog = repo.file(file_)
1812 1812 if len(filelog):
1813 1813 r = filelog
1814 1814 if not r:
1815 1815 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1816 1816 ui.write("digraph G {\n")
1817 1817 for i in r:
1818 1818 node = r.node(i)
1819 1819 pp = r.parents(node)
1820 1820 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1821 1821 if pp[1] != nullid:
1822 1822 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1823 1823 ui.write("}\n")
1824 1824
1825 1825 @command('debuginstall', [], '')
1826 1826 def debuginstall(ui):
1827 1827 '''test Mercurial installation
1828 1828
1829 1829 Returns 0 on success.
1830 1830 '''
1831 1831
1832 1832 def writetemp(contents):
1833 1833 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1834 1834 f = os.fdopen(fd, "wb")
1835 1835 f.write(contents)
1836 1836 f.close()
1837 1837 return name
1838 1838
1839 1839 problems = 0
1840 1840
1841 1841 # encoding
1842 1842 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1843 1843 try:
1844 1844 encoding.fromlocal("test")
1845 1845 except util.Abort, inst:
1846 1846 ui.write(" %s\n" % inst)
1847 1847 ui.write(_(" (check that your locale is properly set)\n"))
1848 1848 problems += 1
1849 1849
1850 1850 # compiled modules
1851 1851 ui.status(_("Checking installed modules (%s)...\n")
1852 1852 % os.path.dirname(__file__))
1853 1853 try:
1854 1854 import bdiff, mpatch, base85, osutil
1855 1855 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1856 1856 except Exception, inst:
1857 1857 ui.write(" %s\n" % inst)
1858 1858 ui.write(_(" One or more extensions could not be found"))
1859 1859 ui.write(_(" (check that you compiled the extensions)\n"))
1860 1860 problems += 1
1861 1861
1862 1862 # templates
1863 1863 import templater
1864 1864 p = templater.templatepath()
1865 1865 ui.status(_("Checking templates (%s)...\n") % ' '.join(p))
1866 1866 try:
1867 1867 templater.templater(templater.templatepath("map-cmdline.default"))
1868 1868 except Exception, inst:
1869 1869 ui.write(" %s\n" % inst)
1870 1870 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1871 1871 problems += 1
1872 1872
1873 1873 # editor
1874 1874 ui.status(_("Checking commit editor...\n"))
1875 1875 editor = ui.geteditor()
1876 1876 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
1877 1877 if not cmdpath:
1878 1878 if editor == 'vi':
1879 1879 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1880 1880 ui.write(_(" (specify a commit editor in your configuration"
1881 1881 " file)\n"))
1882 1882 else:
1883 1883 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1884 1884 ui.write(_(" (specify a commit editor in your configuration"
1885 1885 " file)\n"))
1886 1886 problems += 1
1887 1887
1888 1888 # check username
1889 1889 ui.status(_("Checking username...\n"))
1890 1890 try:
1891 1891 ui.username()
1892 1892 except util.Abort, e:
1893 1893 ui.write(" %s\n" % e)
1894 1894 ui.write(_(" (specify a username in your configuration file)\n"))
1895 1895 problems += 1
1896 1896
1897 1897 if not problems:
1898 1898 ui.status(_("No problems detected\n"))
1899 1899 else:
1900 1900 ui.write(_("%s problems detected,"
1901 1901 " please check your install!\n") % problems)
1902 1902
1903 1903 return problems
1904 1904
1905 1905 @command('debugknown', [], _('REPO ID...'))
1906 1906 def debugknown(ui, repopath, *ids, **opts):
1907 1907 """test whether node ids are known to a repo
1908 1908
1909 1909 Every ID must be a full-length hex node id string. Returns a list of 0s and 1s
1910 1910 indicating unknown/known.
1911 1911 """
1912 1912 repo = hg.peer(ui, opts, repopath)
1913 1913 if not repo.capable('known'):
1914 1914 raise util.Abort("known() not supported by target repository")
1915 1915 flags = repo.known([bin(s) for s in ids])
1916 1916 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
1917 1917
1918 1918 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
1919 1919 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
1920 1920 '''access the pushkey key/value protocol
1921 1921
1922 1922 With two args, list the keys in the given namespace.
1923 1923
1924 1924 With five args, set a key to new if it currently is set to old.
1925 1925 Reports success or failure.
1926 1926 '''
1927 1927
1928 1928 target = hg.peer(ui, {}, repopath)
1929 1929 if keyinfo:
1930 1930 key, old, new = keyinfo
1931 1931 r = target.pushkey(namespace, key, old, new)
1932 1932 ui.status(str(r) + '\n')
1933 1933 return not r
1934 1934 else:
1935 1935 for k, v in target.listkeys(namespace).iteritems():
1936 1936 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1937 1937 v.encode('string-escape')))
1938 1938
1939 1939 @command('debugrebuildstate',
1940 1940 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
1941 1941 _('[-r REV] [REV]'))
1942 1942 def debugrebuildstate(ui, repo, rev="tip"):
1943 1943 """rebuild the dirstate as it would look like for the given revision"""
1944 1944 ctx = scmutil.revsingle(repo, rev)
1945 1945 wlock = repo.wlock()
1946 1946 try:
1947 1947 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1948 1948 finally:
1949 1949 wlock.release()
1950 1950
1951 1951 @command('debugrename',
1952 1952 [('r', 'rev', '', _('revision to debug'), _('REV'))],
1953 1953 _('[-r REV] FILE'))
1954 1954 def debugrename(ui, repo, file1, *pats, **opts):
1955 1955 """dump rename information"""
1956 1956
1957 1957 ctx = scmutil.revsingle(repo, opts.get('rev'))
1958 1958 m = scmutil.match(ctx, (file1,) + pats, opts)
1959 1959 for abs in ctx.walk(m):
1960 1960 fctx = ctx[abs]
1961 1961 o = fctx.filelog().renamed(fctx.filenode())
1962 1962 rel = m.rel(abs)
1963 1963 if o:
1964 1964 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1965 1965 else:
1966 1966 ui.write(_("%s not renamed\n") % rel)
1967 1967
1968 1968 @command('debugrevlog',
1969 1969 [('c', 'changelog', False, _('open changelog')),
1970 1970 ('m', 'manifest', False, _('open manifest')),
1971 1971 ('d', 'dump', False, _('dump index data'))],
1972 1972 _('-c|-m|FILE'))
1973 1973 def debugrevlog(ui, repo, file_ = None, **opts):
1974 1974 """show data and statistics about a revlog"""
1975 1975 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
1976 1976
1977 1977 if opts.get("dump"):
1978 1978 numrevs = len(r)
1979 1979 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
1980 1980 " rawsize totalsize compression heads\n")
1981 1981 ts = 0
1982 1982 heads = set()
1983 1983 for rev in xrange(numrevs):
1984 1984 dbase = r.deltaparent(rev)
1985 1985 if dbase == -1:
1986 1986 dbase = rev
1987 1987 cbase = r.chainbase(rev)
1988 1988 p1, p2 = r.parentrevs(rev)
1989 1989 rs = r.rawsize(rev)
1990 1990 ts = ts + rs
1991 1991 heads -= set(r.parentrevs(rev))
1992 1992 heads.add(rev)
1993 1993 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
1994 1994 (rev, p1, p2, r.start(rev), r.end(rev),
1995 1995 r.start(dbase), r.start(cbase),
1996 1996 r.start(p1), r.start(p2),
1997 1997 rs, ts, ts / r.end(rev), len(heads)))
1998 1998 return 0
1999 1999
2000 2000 v = r.version
2001 2001 format = v & 0xFFFF
2002 2002 flags = []
2003 2003 gdelta = False
2004 2004 if v & revlog.REVLOGNGINLINEDATA:
2005 2005 flags.append('inline')
2006 2006 if v & revlog.REVLOGGENERALDELTA:
2007 2007 gdelta = True
2008 2008 flags.append('generaldelta')
2009 2009 if not flags:
2010 2010 flags = ['(none)']
2011 2011
2012 2012 nummerges = 0
2013 2013 numfull = 0
2014 2014 numprev = 0
2015 2015 nump1 = 0
2016 2016 nump2 = 0
2017 2017 numother = 0
2018 2018 nump1prev = 0
2019 2019 nump2prev = 0
2020 2020 chainlengths = []
2021 2021
2022 2022 datasize = [None, 0, 0L]
2023 2023 fullsize = [None, 0, 0L]
2024 2024 deltasize = [None, 0, 0L]
2025 2025
2026 2026 def addsize(size, l):
2027 2027 if l[0] is None or size < l[0]:
2028 2028 l[0] = size
2029 2029 if size > l[1]:
2030 2030 l[1] = size
2031 2031 l[2] += size
2032 2032
2033 2033 numrevs = len(r)
2034 2034 for rev in xrange(numrevs):
2035 2035 p1, p2 = r.parentrevs(rev)
2036 2036 delta = r.deltaparent(rev)
2037 2037 if format > 0:
2038 2038 addsize(r.rawsize(rev), datasize)
2039 2039 if p2 != nullrev:
2040 2040 nummerges += 1
2041 2041 size = r.length(rev)
2042 2042 if delta == nullrev:
2043 2043 chainlengths.append(0)
2044 2044 numfull += 1
2045 2045 addsize(size, fullsize)
2046 2046 else:
2047 2047 chainlengths.append(chainlengths[delta] + 1)
2048 2048 addsize(size, deltasize)
2049 2049 if delta == rev - 1:
2050 2050 numprev += 1
2051 2051 if delta == p1:
2052 2052 nump1prev += 1
2053 2053 elif delta == p2:
2054 2054 nump2prev += 1
2055 2055 elif delta == p1:
2056 2056 nump1 += 1
2057 2057 elif delta == p2:
2058 2058 nump2 += 1
2059 2059 elif delta != nullrev:
2060 2060 numother += 1
2061 2061
2062 2062 numdeltas = numrevs - numfull
2063 2063 numoprev = numprev - nump1prev - nump2prev
2064 2064 totalrawsize = datasize[2]
2065 2065 datasize[2] /= numrevs
2066 2066 fulltotal = fullsize[2]
2067 2067 fullsize[2] /= numfull
2068 2068 deltatotal = deltasize[2]
2069 2069 deltasize[2] /= numrevs - numfull
2070 2070 totalsize = fulltotal + deltatotal
2071 2071 avgchainlen = sum(chainlengths) / numrevs
2072 2072 compratio = totalrawsize / totalsize
2073 2073
2074 2074 basedfmtstr = '%%%dd\n'
2075 2075 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2076 2076
2077 2077 def dfmtstr(max):
2078 2078 return basedfmtstr % len(str(max))
2079 2079 def pcfmtstr(max, padding=0):
2080 2080 return basepcfmtstr % (len(str(max)), ' ' * padding)
2081 2081
2082 2082 def pcfmt(value, total):
2083 2083 return (value, 100 * float(value) / total)
2084 2084
2085 2085 ui.write('format : %d\n' % format)
2086 2086 ui.write('flags : %s\n' % ', '.join(flags))
2087 2087
2088 2088 ui.write('\n')
2089 2089 fmt = pcfmtstr(totalsize)
2090 2090 fmt2 = dfmtstr(totalsize)
2091 2091 ui.write('revisions : ' + fmt2 % numrevs)
2092 2092 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2093 2093 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2094 2094 ui.write('revisions : ' + fmt2 % numrevs)
2095 2095 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2096 2096 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2097 2097 ui.write('revision size : ' + fmt2 % totalsize)
2098 2098 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2099 2099 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2100 2100
2101 2101 ui.write('\n')
2102 2102 fmt = dfmtstr(max(avgchainlen, compratio))
2103 2103 ui.write('avg chain length : ' + fmt % avgchainlen)
2104 2104 ui.write('compression ratio : ' + fmt % compratio)
2105 2105
2106 2106 if format > 0:
2107 2107 ui.write('\n')
2108 2108 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2109 2109 % tuple(datasize))
2110 2110 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2111 2111 % tuple(fullsize))
2112 2112 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2113 2113 % tuple(deltasize))
2114 2114
2115 2115 if numdeltas > 0:
2116 2116 ui.write('\n')
2117 2117 fmt = pcfmtstr(numdeltas)
2118 2118 fmt2 = pcfmtstr(numdeltas, 4)
2119 2119 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2120 2120 if numprev > 0:
2121 2121 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev, numprev))
2122 2122 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev, numprev))
2123 2123 ui.write(' other : ' + fmt2 % pcfmt(numoprev, numprev))
2124 2124 if gdelta:
2125 2125 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2126 2126 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2127 2127 ui.write('deltas against other : ' + fmt % pcfmt(numother, numdeltas))
2128 2128
2129 2129 @command('debugrevspec', [], ('REVSPEC'))
2130 2130 def debugrevspec(ui, repo, expr):
2131 2131 '''parse and apply a revision specification'''
2132 2132 if ui.verbose:
2133 2133 tree = revset.parse(expr)[0]
2134 2134 ui.note(tree, "\n")
2135 2135 newtree = revset.findaliases(ui, tree)
2136 2136 if newtree != tree:
2137 2137 ui.note(newtree, "\n")
2138 2138 func = revset.match(ui, expr)
2139 2139 for c in func(repo, range(len(repo))):
2140 2140 ui.write("%s\n" % c)
2141 2141
2142 2142 @command('debugsetparents', [], _('REV1 [REV2]'))
2143 2143 def debugsetparents(ui, repo, rev1, rev2=None):
2144 2144 """manually set the parents of the current working directory
2145 2145
2146 2146 This is useful for writing repository conversion tools, but should
2147 2147 be used with care.
2148 2148
2149 2149 Returns 0 on success.
2150 2150 """
2151 2151
2152 2152 r1 = scmutil.revsingle(repo, rev1).node()
2153 2153 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2154 2154
2155 2155 wlock = repo.wlock()
2156 2156 try:
2157 2157 repo.dirstate.setparents(r1, r2)
2158 2158 finally:
2159 2159 wlock.release()
2160 2160
2161 2161 @command('debugstate',
2162 2162 [('', 'nodates', None, _('do not display the saved mtime')),
2163 2163 ('', 'datesort', None, _('sort by saved mtime'))],
2164 2164 _('[OPTION]...'))
2165 2165 def debugstate(ui, repo, nodates=None, datesort=None):
2166 2166 """show the contents of the current dirstate"""
2167 2167 timestr = ""
2168 2168 showdate = not nodates
2169 2169 if datesort:
2170 2170 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2171 2171 else:
2172 2172 keyfunc = None # sort by filename
2173 2173 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2174 2174 if showdate:
2175 2175 if ent[3] == -1:
2176 2176 # Pad or slice to locale representation
2177 2177 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2178 2178 time.localtime(0)))
2179 2179 timestr = 'unset'
2180 2180 timestr = (timestr[:locale_len] +
2181 2181 ' ' * (locale_len - len(timestr)))
2182 2182 else:
2183 2183 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2184 2184 time.localtime(ent[3]))
2185 2185 if ent[1] & 020000:
2186 2186 mode = 'lnk'
2187 2187 else:
2188 2188 mode = '%3o' % (ent[1] & 0777)
2189 2189 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2190 2190 for f in repo.dirstate.copies():
2191 2191 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2192 2192
2193 2193 @command('debugsub',
2194 2194 [('r', 'rev', '',
2195 2195 _('revision to check'), _('REV'))],
2196 2196 _('[-r REV] [REV]'))
2197 2197 def debugsub(ui, repo, rev=None):
2198 2198 ctx = scmutil.revsingle(repo, rev, None)
2199 2199 for k, v in sorted(ctx.substate.items()):
2200 2200 ui.write('path %s\n' % k)
2201 2201 ui.write(' source %s\n' % v[0])
2202 2202 ui.write(' revision %s\n' % v[1])
2203 2203
2204 2204 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2205 2205 def debugwalk(ui, repo, *pats, **opts):
2206 2206 """show how files match on given patterns"""
2207 2207 m = scmutil.match(repo[None], pats, opts)
2208 2208 items = list(repo.walk(m))
2209 2209 if not items:
2210 2210 return
2211 2211 fmt = 'f %%-%ds %%-%ds %%s' % (
2212 2212 max([len(abs) for abs in items]),
2213 2213 max([len(m.rel(abs)) for abs in items]))
2214 2214 for abs in items:
2215 2215 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
2216 2216 ui.write("%s\n" % line.rstrip())
2217 2217
2218 2218 @command('debugwireargs',
2219 2219 [('', 'three', '', 'three'),
2220 2220 ('', 'four', '', 'four'),
2221 2221 ('', 'five', '', 'five'),
2222 2222 ] + remoteopts,
2223 2223 _('REPO [OPTIONS]... [ONE [TWO]]'))
2224 2224 def debugwireargs(ui, repopath, *vals, **opts):
2225 2225 repo = hg.peer(ui, opts, repopath)
2226 2226 for opt in remoteopts:
2227 2227 del opts[opt[1]]
2228 2228 args = {}
2229 2229 for k, v in opts.iteritems():
2230 2230 if v:
2231 2231 args[k] = v
2232 2232 # run twice to check that we don't mess up the stream for the next command
2233 2233 res1 = repo.debugwireargs(*vals, **args)
2234 2234 res2 = repo.debugwireargs(*vals, **args)
2235 2235 ui.write("%s\n" % res1)
2236 2236 if res1 != res2:
2237 2237 ui.warn("%s\n" % res2)
2238 2238
2239 2239 @command('^diff',
2240 2240 [('r', 'rev', [], _('revision'), _('REV')),
2241 2241 ('c', 'change', '', _('change made by revision'), _('REV'))
2242 2242 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2243 2243 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2244 2244 def diff(ui, repo, *pats, **opts):
2245 2245 """diff repository (or selected files)
2246 2246
2247 2247 Show differences between revisions for the specified files.
2248 2248
2249 2249 Differences between files are shown using the unified diff format.
2250 2250
2251 2251 .. note::
2252 2252 diff may generate unexpected results for merges, as it will
2253 2253 default to comparing against the working directory's first
2254 2254 parent changeset if no revisions are specified.
2255 2255
2256 2256 When two revision arguments are given, then changes are shown
2257 2257 between those revisions. If only one revision is specified then
2258 2258 that revision is compared to the working directory, and, when no
2259 2259 revisions are specified, the working directory files are compared
2260 2260 to its parent.
2261 2261
2262 2262 Alternatively you can specify -c/--change with a revision to see
2263 2263 the changes in that changeset relative to its first parent.
2264 2264
2265 2265 Without the -a/--text option, diff will avoid generating diffs of
2266 2266 files it detects as binary. With -a, diff will generate a diff
2267 2267 anyway, probably with undesirable results.
2268 2268
2269 2269 Use the -g/--git option to generate diffs in the git extended diff
2270 2270 format. For more information, read :hg:`help diffs`.
2271 2271
2272 2272 .. container:: verbose
2273 2273
2274 2274 Examples:
2275 2275
2276 2276 - compare a file in the current working directory to its parent::
2277 2277
2278 2278 hg diff foo.c
2279 2279
2280 2280 - compare two historical versions of a directory, with rename info::
2281 2281
2282 2282 hg diff --git -r 1.0:1.2 lib/
2283 2283
2284 2284 - get change stats relative to the last change on some date::
2285 2285
2286 2286 hg diff --stat -r "date('may 2')"
2287 2287
2288 2288 - diff all newly-added files that contain a keyword::
2289 2289
2290 2290 hg diff "set:added() and grep(GNU)"
2291 2291
2292 2292 - compare a revision and its parents::
2293 2293
2294 2294 hg diff -c 9353 # compare against first parent
2295 2295 hg diff -r 9353^:9353 # same using revset syntax
2296 2296 hg diff -r 9353^2:9353 # compare against the second parent
2297 2297
2298 2298 Returns 0 on success.
2299 2299 """
2300 2300
2301 2301 revs = opts.get('rev')
2302 2302 change = opts.get('change')
2303 2303 stat = opts.get('stat')
2304 2304 reverse = opts.get('reverse')
2305 2305
2306 2306 if revs and change:
2307 2307 msg = _('cannot specify --rev and --change at the same time')
2308 2308 raise util.Abort(msg)
2309 2309 elif change:
2310 2310 node2 = scmutil.revsingle(repo, change, None).node()
2311 2311 node1 = repo[node2].p1().node()
2312 2312 else:
2313 2313 node1, node2 = scmutil.revpair(repo, revs)
2314 2314
2315 2315 if reverse:
2316 2316 node1, node2 = node2, node1
2317 2317
2318 2318 diffopts = patch.diffopts(ui, opts)
2319 2319 m = scmutil.match(repo[node2], pats, opts)
2320 2320 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2321 2321 listsubrepos=opts.get('subrepos'))
2322 2322
2323 2323 @command('^export',
2324 2324 [('o', 'output', '',
2325 2325 _('print output to file with formatted name'), _('FORMAT')),
2326 2326 ('', 'switch-parent', None, _('diff against the second parent')),
2327 2327 ('r', 'rev', [], _('revisions to export'), _('REV')),
2328 2328 ] + diffopts,
2329 2329 _('[OPTION]... [-o OUTFILESPEC] REV...'))
2330 2330 def export(ui, repo, *changesets, **opts):
2331 2331 """dump the header and diffs for one or more changesets
2332 2332
2333 2333 Print the changeset header and diffs for one or more revisions.
2334 2334
2335 2335 The information shown in the changeset header is: author, date,
2336 2336 branch name (if non-default), changeset hash, parent(s) and commit
2337 2337 comment.
2338 2338
2339 2339 .. note::
2340 2340 export may generate unexpected diff output for merge
2341 2341 changesets, as it will compare the merge changeset against its
2342 2342 first parent only.
2343 2343
2344 2344 Output may be to a file, in which case the name of the file is
2345 2345 given using a format string. The formatting rules are as follows:
2346 2346
2347 2347 :``%%``: literal "%" character
2348 2348 :``%H``: changeset hash (40 hexadecimal digits)
2349 2349 :``%N``: number of patches being generated
2350 2350 :``%R``: changeset revision number
2351 2351 :``%b``: basename of the exporting repository
2352 2352 :``%h``: short-form changeset hash (12 hexadecimal digits)
2353 2353 :``%m``: first line of the commit message (only alphanumeric characters)
2354 2354 :``%n``: zero-padded sequence number, starting at 1
2355 2355 :``%r``: zero-padded changeset revision number
2356 2356
2357 2357 Without the -a/--text option, export will avoid generating diffs
2358 2358 of files it detects as binary. With -a, export will generate a
2359 2359 diff anyway, probably with undesirable results.
2360 2360
2361 2361 Use the -g/--git option to generate diffs in the git extended diff
2362 2362 format. See :hg:`help diffs` for more information.
2363 2363
2364 2364 With the --switch-parent option, the diff will be against the
2365 2365 second parent. It can be useful to review a merge.
2366 2366
2367 2367 .. container:: verbose
2368 2368
2369 2369 Examples:
2370 2370
2371 2371 - use export and import to transplant a bugfix to the current
2372 2372 branch::
2373 2373
2374 2374 hg export -r 9353 | hg import -
2375 2375
2376 2376 - export all the changesets between two revisions to a file with
2377 2377 rename information::
2378 2378
2379 2379 hg export --git -r 123:150 > changes.txt
2380 2380
2381 2381 - split outgoing changes into a series of patches with
2382 2382 descriptive names::
2383 2383
2384 2384 hg export -r "outgoing()" -o "%n-%m.patch"
2385 2385
2386 2386 Returns 0 on success.
2387 2387 """
2388 2388 changesets += tuple(opts.get('rev', []))
2389 2389 if not changesets:
2390 2390 raise util.Abort(_("export requires at least one changeset"))
2391 2391 revs = scmutil.revrange(repo, changesets)
2392 2392 if len(revs) > 1:
2393 2393 ui.note(_('exporting patches:\n'))
2394 2394 else:
2395 2395 ui.note(_('exporting patch:\n'))
2396 2396 cmdutil.export(repo, revs, template=opts.get('output'),
2397 2397 switch_parent=opts.get('switch_parent'),
2398 2398 opts=patch.diffopts(ui, opts))
2399 2399
2400 2400 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2401 2401 def forget(ui, repo, *pats, **opts):
2402 2402 """forget the specified files on the next commit
2403 2403
2404 2404 Mark the specified files so they will no longer be tracked
2405 2405 after the next commit.
2406 2406
2407 2407 This only removes files from the current branch, not from the
2408 2408 entire project history, and it does not delete them from the
2409 2409 working directory.
2410 2410
2411 2411 To undo a forget before the next commit, see :hg:`add`.
2412 2412
2413 2413 .. container:: verbose
2414 2414
2415 2415 Examples:
2416 2416
2417 2417 - forget newly-added binary files::
2418 2418
2419 2419 hg forget "set:added() and binary()"
2420 2420
2421 2421 - forget files that would be excluded by .hgignore::
2422 2422
2423 2423 hg forget "set:hgignore()"
2424 2424
2425 2425 Returns 0 on success.
2426 2426 """
2427 2427
2428 2428 if not pats:
2429 2429 raise util.Abort(_('no files specified'))
2430 2430
2431 2431 m = scmutil.match(repo[None], pats, opts)
2432 2432 s = repo.status(match=m, clean=True)
2433 2433 forget = sorted(s[0] + s[1] + s[3] + s[6])
2434 2434 errs = 0
2435 2435
2436 2436 for f in m.files():
2437 2437 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2438 2438 if os.path.exists(m.rel(f)):
2439 2439 ui.warn(_('not removing %s: file is already untracked\n')
2440 2440 % m.rel(f))
2441 2441 errs = 1
2442 2442
2443 2443 for f in forget:
2444 2444 if ui.verbose or not m.exact(f):
2445 2445 ui.status(_('removing %s\n') % m.rel(f))
2446 2446
2447 2447 repo[None].forget(forget)
2448 2448 return errs
2449 2449
2450 @command('graft',
2451 [],
2452 _('[OPTION]... REVISION...'))
2453 def graft(ui, repo, rev, *revs, **opts):
2454 '''copy changes from other branches onto the current branch
2455
2456 This command uses Mercurial's merge logic to copy individual
2457 changes from other branches without merging branches in the
2458 history graph. This is sometimes known as 'backporting' or
2459 'cherry-picking'.
2460
2461 Changesets that are ancestors of the current revision, that have
2462 already been grafted, or that are merges will be skipped.
2463
2464 Returns 0 on successful completion.
2465 '''
2466
2467 cmdutil.bailifchanged(repo)
2468
2469 revs = [rev] + list(revs)
2470 revs = scmutil.revrange(repo, revs)
2471
2472 # check for merges
2473 for ctx in repo.set('%ld and merge()', revs):
2474 ui.warn(_('skipping ungraftable merge revision %s\n') % ctx.rev())
2475 revs.remove(ctx.rev())
2476 if not revs:
2477 return -1
2478
2479 # check for ancestors of dest branch
2480 for ctx in repo.set('::. and %ld', revs):
2481 ui.warn(_('skipping ancestor revision %s\n') % ctx.rev())
2482 revs.remove(ctx.rev())
2483 if not revs:
2484 return -1
2485
2486 # check ancestors for earlier grafts
2487 ui.debug('scanning for existing transplants')
2488 for ctx in repo.set("::. - ::%ld", revs):
2489 n = ctx.extra().get('source')
2490 if n and n in repo:
2491 r = repo[n].rev()
2492 ui.warn(_('skipping already grafted revision %s\n') % r)
2493 revs.remove(r)
2494 if not revs:
2495 return -1
2496
2497 for ctx in repo.set("%ld", revs):
2498 current = repo['.']
2499 ui.debug('grafting revision %s', ctx.rev())
2500 # perform the graft merge with p1(rev) as 'ancestor'
2501 stats = mergemod.update(repo, ctx.node(), True, True, False,
2502 ctx.p1().node())
2503 # drop the second merge parent
2504 repo.dirstate.setparents(current.node(), nullid)
2505 repo.dirstate.write()
2506 # fix up dirstate for copies and renames
2507 cmdutil.duplicatecopies(repo, ctx.rev(), current.node(), nullid)
2508 # report any conflicts
2509 if stats and stats[3] > 0:
2510 raise util.Abort(_("unresolved conflicts, can't continue"),
2511 hint=_('use hg resolve and hg graft --continue'))
2512 # commit
2513 extra = {'source': ctx.hex()}
2514 repo.commit(text=ctx.description(), user=ctx.user(),
2515 date=ctx.date(), extra=extra)
2516
2517 return 0
2518
2450 2519 @command('grep',
2451 2520 [('0', 'print0', None, _('end fields with NUL')),
2452 2521 ('', 'all', None, _('print all revisions that match')),
2453 2522 ('a', 'text', None, _('treat all files as text')),
2454 2523 ('f', 'follow', None,
2455 2524 _('follow changeset history,'
2456 2525 ' or file history across copies and renames')),
2457 2526 ('i', 'ignore-case', None, _('ignore case when matching')),
2458 2527 ('l', 'files-with-matches', None,
2459 2528 _('print only filenames and revisions that match')),
2460 2529 ('n', 'line-number', None, _('print matching line numbers')),
2461 2530 ('r', 'rev', [],
2462 2531 _('only search files changed within revision range'), _('REV')),
2463 2532 ('u', 'user', None, _('list the author (long with -v)')),
2464 2533 ('d', 'date', None, _('list the date (short with -q)')),
2465 2534 ] + walkopts,
2466 2535 _('[OPTION]... PATTERN [FILE]...'))
2467 2536 def grep(ui, repo, pattern, *pats, **opts):
2468 2537 """search for a pattern in specified files and revisions
2469 2538
2470 2539 Search revisions of files for a regular expression.
2471 2540
2472 2541 This command behaves differently than Unix grep. It only accepts
2473 2542 Python/Perl regexps. It searches repository history, not the
2474 2543 working directory. It always prints the revision number in which a
2475 2544 match appears.
2476 2545
2477 2546 By default, grep only prints output for the first revision of a
2478 2547 file in which it finds a match. To get it to print every revision
2479 2548 that contains a change in match status ("-" for a match that
2480 2549 becomes a non-match, or "+" for a non-match that becomes a match),
2481 2550 use the --all flag.
2482 2551
2483 2552 Returns 0 if a match is found, 1 otherwise.
2484 2553 """
2485 2554 reflags = 0
2486 2555 if opts.get('ignore_case'):
2487 2556 reflags |= re.I
2488 2557 try:
2489 2558 regexp = re.compile(pattern, reflags)
2490 2559 except re.error, inst:
2491 2560 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2492 2561 return 1
2493 2562 sep, eol = ':', '\n'
2494 2563 if opts.get('print0'):
2495 2564 sep = eol = '\0'
2496 2565
2497 2566 getfile = util.lrucachefunc(repo.file)
2498 2567
2499 2568 def matchlines(body):
2500 2569 begin = 0
2501 2570 linenum = 0
2502 2571 while True:
2503 2572 match = regexp.search(body, begin)
2504 2573 if not match:
2505 2574 break
2506 2575 mstart, mend = match.span()
2507 2576 linenum += body.count('\n', begin, mstart) + 1
2508 2577 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2509 2578 begin = body.find('\n', mend) + 1 or len(body)
2510 2579 lend = begin - 1
2511 2580 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2512 2581
2513 2582 class linestate(object):
2514 2583 def __init__(self, line, linenum, colstart, colend):
2515 2584 self.line = line
2516 2585 self.linenum = linenum
2517 2586 self.colstart = colstart
2518 2587 self.colend = colend
2519 2588
2520 2589 def __hash__(self):
2521 2590 return hash((self.linenum, self.line))
2522 2591
2523 2592 def __eq__(self, other):
2524 2593 return self.line == other.line
2525 2594
2526 2595 matches = {}
2527 2596 copies = {}
2528 2597 def grepbody(fn, rev, body):
2529 2598 matches[rev].setdefault(fn, [])
2530 2599 m = matches[rev][fn]
2531 2600 for lnum, cstart, cend, line in matchlines(body):
2532 2601 s = linestate(line, lnum, cstart, cend)
2533 2602 m.append(s)
2534 2603
2535 2604 def difflinestates(a, b):
2536 2605 sm = difflib.SequenceMatcher(None, a, b)
2537 2606 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2538 2607 if tag == 'insert':
2539 2608 for i in xrange(blo, bhi):
2540 2609 yield ('+', b[i])
2541 2610 elif tag == 'delete':
2542 2611 for i in xrange(alo, ahi):
2543 2612 yield ('-', a[i])
2544 2613 elif tag == 'replace':
2545 2614 for i in xrange(alo, ahi):
2546 2615 yield ('-', a[i])
2547 2616 for i in xrange(blo, bhi):
2548 2617 yield ('+', b[i])
2549 2618
2550 2619 def display(fn, ctx, pstates, states):
2551 2620 rev = ctx.rev()
2552 2621 datefunc = ui.quiet and util.shortdate or util.datestr
2553 2622 found = False
2554 2623 filerevmatches = {}
2555 2624 def binary():
2556 2625 flog = getfile(fn)
2557 2626 return util.binary(flog.read(ctx.filenode(fn)))
2558 2627
2559 2628 if opts.get('all'):
2560 2629 iter = difflinestates(pstates, states)
2561 2630 else:
2562 2631 iter = [('', l) for l in states]
2563 2632 for change, l in iter:
2564 2633 cols = [fn, str(rev)]
2565 2634 before, match, after = None, None, None
2566 2635 if opts.get('line_number'):
2567 2636 cols.append(str(l.linenum))
2568 2637 if opts.get('all'):
2569 2638 cols.append(change)
2570 2639 if opts.get('user'):
2571 2640 cols.append(ui.shortuser(ctx.user()))
2572 2641 if opts.get('date'):
2573 2642 cols.append(datefunc(ctx.date()))
2574 2643 if opts.get('files_with_matches'):
2575 2644 c = (fn, rev)
2576 2645 if c in filerevmatches:
2577 2646 continue
2578 2647 filerevmatches[c] = 1
2579 2648 else:
2580 2649 before = l.line[:l.colstart]
2581 2650 match = l.line[l.colstart:l.colend]
2582 2651 after = l.line[l.colend:]
2583 2652 ui.write(sep.join(cols))
2584 2653 if before is not None:
2585 2654 if not opts.get('text') and binary():
2586 2655 ui.write(sep + " Binary file matches")
2587 2656 else:
2588 2657 ui.write(sep + before)
2589 2658 ui.write(match, label='grep.match')
2590 2659 ui.write(after)
2591 2660 ui.write(eol)
2592 2661 found = True
2593 2662 return found
2594 2663
2595 2664 skip = {}
2596 2665 revfiles = {}
2597 2666 matchfn = scmutil.match(repo[None], pats, opts)
2598 2667 found = False
2599 2668 follow = opts.get('follow')
2600 2669
2601 2670 def prep(ctx, fns):
2602 2671 rev = ctx.rev()
2603 2672 pctx = ctx.p1()
2604 2673 parent = pctx.rev()
2605 2674 matches.setdefault(rev, {})
2606 2675 matches.setdefault(parent, {})
2607 2676 files = revfiles.setdefault(rev, [])
2608 2677 for fn in fns:
2609 2678 flog = getfile(fn)
2610 2679 try:
2611 2680 fnode = ctx.filenode(fn)
2612 2681 except error.LookupError:
2613 2682 continue
2614 2683
2615 2684 copied = flog.renamed(fnode)
2616 2685 copy = follow and copied and copied[0]
2617 2686 if copy:
2618 2687 copies.setdefault(rev, {})[fn] = copy
2619 2688 if fn in skip:
2620 2689 if copy:
2621 2690 skip[copy] = True
2622 2691 continue
2623 2692 files.append(fn)
2624 2693
2625 2694 if fn not in matches[rev]:
2626 2695 grepbody(fn, rev, flog.read(fnode))
2627 2696
2628 2697 pfn = copy or fn
2629 2698 if pfn not in matches[parent]:
2630 2699 try:
2631 2700 fnode = pctx.filenode(pfn)
2632 2701 grepbody(pfn, parent, flog.read(fnode))
2633 2702 except error.LookupError:
2634 2703 pass
2635 2704
2636 2705 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2637 2706 rev = ctx.rev()
2638 2707 parent = ctx.p1().rev()
2639 2708 for fn in sorted(revfiles.get(rev, [])):
2640 2709 states = matches[rev][fn]
2641 2710 copy = copies.get(rev, {}).get(fn)
2642 2711 if fn in skip:
2643 2712 if copy:
2644 2713 skip[copy] = True
2645 2714 continue
2646 2715 pstates = matches.get(parent, {}).get(copy or fn, [])
2647 2716 if pstates or states:
2648 2717 r = display(fn, ctx, pstates, states)
2649 2718 found = found or r
2650 2719 if r and not opts.get('all'):
2651 2720 skip[fn] = True
2652 2721 if copy:
2653 2722 skip[copy] = True
2654 2723 del matches[rev]
2655 2724 del revfiles[rev]
2656 2725
2657 2726 return not found
2658 2727
2659 2728 @command('heads',
2660 2729 [('r', 'rev', '',
2661 2730 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2662 2731 ('t', 'topo', False, _('show topological heads only')),
2663 2732 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2664 2733 ('c', 'closed', False, _('show normal and closed branch heads')),
2665 2734 ] + templateopts,
2666 2735 _('[-ac] [-r STARTREV] [REV]...'))
2667 2736 def heads(ui, repo, *branchrevs, **opts):
2668 2737 """show current repository heads or show branch heads
2669 2738
2670 2739 With no arguments, show all repository branch heads.
2671 2740
2672 2741 Repository "heads" are changesets with no child changesets. They are
2673 2742 where development generally takes place and are the usual targets
2674 2743 for update and merge operations. Branch heads are changesets that have
2675 2744 no child changeset on the same branch.
2676 2745
2677 2746 If one or more REVs are given, only branch heads on the branches
2678 2747 associated with the specified changesets are shown. This means
2679 2748 that you can use :hg:`heads foo` to see the heads on a branch
2680 2749 named ``foo``.
2681 2750
2682 2751 If -c/--closed is specified, also show branch heads marked closed
2683 2752 (see :hg:`commit --close-branch`).
2684 2753
2685 2754 If STARTREV is specified, only those heads that are descendants of
2686 2755 STARTREV will be displayed.
2687 2756
2688 2757 If -t/--topo is specified, named branch mechanics will be ignored and only
2689 2758 changesets without children will be shown.
2690 2759
2691 2760 Returns 0 if matching heads are found, 1 if not.
2692 2761 """
2693 2762
2694 2763 start = None
2695 2764 if 'rev' in opts:
2696 2765 start = scmutil.revsingle(repo, opts['rev'], None).node()
2697 2766
2698 2767 if opts.get('topo'):
2699 2768 heads = [repo[h] for h in repo.heads(start)]
2700 2769 else:
2701 2770 heads = []
2702 2771 for branch in repo.branchmap():
2703 2772 heads += repo.branchheads(branch, start, opts.get('closed'))
2704 2773 heads = [repo[h] for h in heads]
2705 2774
2706 2775 if branchrevs:
2707 2776 branches = set(repo[br].branch() for br in branchrevs)
2708 2777 heads = [h for h in heads if h.branch() in branches]
2709 2778
2710 2779 if opts.get('active') and branchrevs:
2711 2780 dagheads = repo.heads(start)
2712 2781 heads = [h for h in heads if h.node() in dagheads]
2713 2782
2714 2783 if branchrevs:
2715 2784 haveheads = set(h.branch() for h in heads)
2716 2785 if branches - haveheads:
2717 2786 headless = ', '.join(b for b in branches - haveheads)
2718 2787 msg = _('no open branch heads found on branches %s')
2719 2788 if opts.get('rev'):
2720 2789 msg += _(' (started at %s)' % opts['rev'])
2721 2790 ui.warn((msg + '\n') % headless)
2722 2791
2723 2792 if not heads:
2724 2793 return 1
2725 2794
2726 2795 heads = sorted(heads, key=lambda x: -x.rev())
2727 2796 displayer = cmdutil.show_changeset(ui, repo, opts)
2728 2797 for ctx in heads:
2729 2798 displayer.show(ctx)
2730 2799 displayer.close()
2731 2800
2732 2801 @command('help',
2733 2802 [('e', 'extension', None, _('show only help for extensions')),
2734 2803 ('c', 'command', None, _('show only help for commands'))],
2735 2804 _('[-ec] [TOPIC]'))
2736 2805 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
2737 2806 """show help for a given topic or a help overview
2738 2807
2739 2808 With no arguments, print a list of commands with short help messages.
2740 2809
2741 2810 Given a topic, extension, or command name, print help for that
2742 2811 topic.
2743 2812
2744 2813 Returns 0 if successful.
2745 2814 """
2746 2815
2747 2816 textwidth = min(ui.termwidth(), 80) - 2
2748 2817
2749 2818 def optrst(options):
2750 2819 data = []
2751 2820 multioccur = False
2752 2821 for option in options:
2753 2822 if len(option) == 5:
2754 2823 shortopt, longopt, default, desc, optlabel = option
2755 2824 else:
2756 2825 shortopt, longopt, default, desc = option
2757 2826 optlabel = _("VALUE") # default label
2758 2827
2759 2828 if _("DEPRECATED") in desc and not ui.verbose:
2760 2829 continue
2761 2830
2762 2831 so = ''
2763 2832 if shortopt:
2764 2833 so = '-' + shortopt
2765 2834 lo = '--' + longopt
2766 2835 if default:
2767 2836 desc += _(" (default: %s)") % default
2768 2837
2769 2838 if isinstance(default, list):
2770 2839 lo += " %s [+]" % optlabel
2771 2840 multioccur = True
2772 2841 elif (default is not None) and not isinstance(default, bool):
2773 2842 lo += " %s" % optlabel
2774 2843
2775 2844 data.append((so, lo, desc))
2776 2845
2777 2846 rst = minirst.maketable(data, 1)
2778 2847
2779 2848 if multioccur:
2780 2849 rst += _("\n[+] marked option can be specified multiple times\n")
2781 2850
2782 2851 return rst
2783 2852
2784 2853 # list all option lists
2785 2854 def opttext(optlist, width):
2786 2855 rst = ''
2787 2856 if not optlist:
2788 2857 return ''
2789 2858
2790 2859 for title, options in optlist:
2791 2860 rst += '\n%s\n' % title
2792 2861 if options:
2793 2862 rst += "\n"
2794 2863 rst += optrst(options)
2795 2864 rst += '\n'
2796 2865
2797 2866 return '\n' + minirst.format(rst, width)
2798 2867
2799 2868 def addglobalopts(optlist, aliases):
2800 2869 if ui.quiet:
2801 2870 return []
2802 2871
2803 2872 if ui.verbose:
2804 2873 optlist.append((_("global options:"), globalopts))
2805 2874 if name == 'shortlist':
2806 2875 optlist.append((_('use "hg help" for the full list '
2807 2876 'of commands'), ()))
2808 2877 else:
2809 2878 if name == 'shortlist':
2810 2879 msg = _('use "hg help" for the full list of commands '
2811 2880 'or "hg -v" for details')
2812 2881 elif name and not full:
2813 2882 msg = _('use "hg help %s" to show the full help text' % name)
2814 2883 elif aliases:
2815 2884 msg = _('use "hg -v help%s" to show builtin aliases and '
2816 2885 'global options') % (name and " " + name or "")
2817 2886 else:
2818 2887 msg = _('use "hg -v help %s" to show more info') % name
2819 2888 optlist.append((msg, ()))
2820 2889
2821 2890 def helpcmd(name):
2822 2891 try:
2823 2892 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
2824 2893 except error.AmbiguousCommand, inst:
2825 2894 # py3k fix: except vars can't be used outside the scope of the
2826 2895 # except block, nor can be used inside a lambda. python issue4617
2827 2896 prefix = inst.args[0]
2828 2897 select = lambda c: c.lstrip('^').startswith(prefix)
2829 2898 helplist(select)
2830 2899 return
2831 2900
2832 2901 # check if it's an invalid alias and display its error if it is
2833 2902 if getattr(entry[0], 'badalias', False):
2834 2903 if not unknowncmd:
2835 2904 entry[0](ui)
2836 2905 return
2837 2906
2838 2907 rst = ""
2839 2908
2840 2909 # synopsis
2841 2910 if len(entry) > 2:
2842 2911 if entry[2].startswith('hg'):
2843 2912 rst += "%s\n" % entry[2]
2844 2913 else:
2845 2914 rst += 'hg %s %s\n' % (aliases[0], entry[2])
2846 2915 else:
2847 2916 rst += 'hg %s\n' % aliases[0]
2848 2917
2849 2918 # aliases
2850 2919 if full and not ui.quiet and len(aliases) > 1:
2851 2920 rst += _("\naliases: %s\n") % ', '.join(aliases[1:])
2852 2921
2853 2922 # description
2854 2923 doc = gettext(entry[0].__doc__)
2855 2924 if not doc:
2856 2925 doc = _("(no help text available)")
2857 2926 if util.safehasattr(entry[0], 'definition'): # aliased command
2858 2927 if entry[0].definition.startswith('!'): # shell alias
2859 2928 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2860 2929 else:
2861 2930 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2862 2931 if ui.quiet or not full:
2863 2932 doc = doc.splitlines()[0]
2864 2933 rst += "\n" + doc + "\n"
2865 2934
2866 2935 # check if this command shadows a non-trivial (multi-line)
2867 2936 # extension help text
2868 2937 try:
2869 2938 mod = extensions.find(name)
2870 2939 doc = gettext(mod.__doc__) or ''
2871 2940 if '\n' in doc.strip():
2872 2941 msg = _('use "hg help -e %s" to show help for '
2873 2942 'the %s extension') % (name, name)
2874 2943 rst += '\n%s\n' % msg
2875 2944 except KeyError:
2876 2945 pass
2877 2946
2878 2947 # options
2879 2948 if not ui.quiet and entry[1]:
2880 2949 rst += '\noptions:\n\n'
2881 2950 rst += optrst(entry[1])
2882 2951
2883 2952 if ui.verbose:
2884 2953 rst += '\nglobal options:\n\n'
2885 2954 rst += optrst(globalopts)
2886 2955
2887 2956 keep = ui.verbose and ['verbose'] or []
2888 2957 formatted, pruned = minirst.format(rst, textwidth, keep=keep)
2889 2958 ui.write(formatted)
2890 2959
2891 2960 if not ui.verbose:
2892 2961 if not full:
2893 2962 ui.write(_('\nuse "hg help %s" to show the full help text\n')
2894 2963 % name)
2895 2964 elif not ui.quiet:
2896 2965 ui.write(_('\nuse "hg -v help %s" to show more info\n') % name)
2897 2966
2898 2967
2899 2968 def helplist(select=None):
2900 2969 # list of commands
2901 2970 if name == "shortlist":
2902 2971 header = _('basic commands:\n\n')
2903 2972 else:
2904 2973 header = _('list of commands:\n\n')
2905 2974
2906 2975 h = {}
2907 2976 cmds = {}
2908 2977 for c, e in table.iteritems():
2909 2978 f = c.split("|", 1)[0]
2910 2979 if select and not select(f):
2911 2980 continue
2912 2981 if (not select and name != 'shortlist' and
2913 2982 e[0].__module__ != __name__):
2914 2983 continue
2915 2984 if name == "shortlist" and not f.startswith("^"):
2916 2985 continue
2917 2986 f = f.lstrip("^")
2918 2987 if not ui.debugflag and f.startswith("debug"):
2919 2988 continue
2920 2989 doc = e[0].__doc__
2921 2990 if doc and 'DEPRECATED' in doc and not ui.verbose:
2922 2991 continue
2923 2992 doc = gettext(doc)
2924 2993 if not doc:
2925 2994 doc = _("(no help text available)")
2926 2995 h[f] = doc.splitlines()[0].rstrip()
2927 2996 cmds[f] = c.lstrip("^")
2928 2997
2929 2998 if not h:
2930 2999 ui.status(_('no commands defined\n'))
2931 3000 return
2932 3001
2933 3002 ui.status(header)
2934 3003 fns = sorted(h)
2935 3004 m = max(map(len, fns))
2936 3005 for f in fns:
2937 3006 if ui.verbose:
2938 3007 commands = cmds[f].replace("|",", ")
2939 3008 ui.write(" %s:\n %s\n"%(commands, h[f]))
2940 3009 else:
2941 3010 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2942 3011 initindent=' %-*s ' % (m, f),
2943 3012 hangindent=' ' * (m + 4))))
2944 3013
2945 3014 if not name:
2946 3015 text = help.listexts(_('enabled extensions:'), extensions.enabled())
2947 3016 if text:
2948 3017 ui.write("\n%s" % minirst.format(text, textwidth))
2949 3018
2950 3019 ui.write(_("\nadditional help topics:\n\n"))
2951 3020 topics = []
2952 3021 for names, header, doc in help.helptable:
2953 3022 topics.append((sorted(names, key=len, reverse=True)[0], header))
2954 3023 topics_len = max([len(s[0]) for s in topics])
2955 3024 for t, desc in topics:
2956 3025 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2957 3026
2958 3027 optlist = []
2959 3028 addglobalopts(optlist, True)
2960 3029 ui.write(opttext(optlist, textwidth))
2961 3030
2962 3031 def helptopic(name):
2963 3032 for names, header, doc in help.helptable:
2964 3033 if name in names:
2965 3034 break
2966 3035 else:
2967 3036 raise error.UnknownCommand(name)
2968 3037
2969 3038 # description
2970 3039 if not doc:
2971 3040 doc = _("(no help text available)")
2972 3041 if util.safehasattr(doc, '__call__'):
2973 3042 doc = doc()
2974 3043
2975 3044 ui.write("%s\n\n" % header)
2976 3045 ui.write("%s" % minirst.format(doc, textwidth, indent=4))
2977 3046 try:
2978 3047 cmdutil.findcmd(name, table)
2979 3048 ui.write(_('\nuse "hg help -c %s" to see help for '
2980 3049 'the %s command\n') % (name, name))
2981 3050 except error.UnknownCommand:
2982 3051 pass
2983 3052
2984 3053 def helpext(name):
2985 3054 try:
2986 3055 mod = extensions.find(name)
2987 3056 doc = gettext(mod.__doc__) or _('no help text available')
2988 3057 except KeyError:
2989 3058 mod = None
2990 3059 doc = extensions.disabledext(name)
2991 3060 if not doc:
2992 3061 raise error.UnknownCommand(name)
2993 3062
2994 3063 if '\n' not in doc:
2995 3064 head, tail = doc, ""
2996 3065 else:
2997 3066 head, tail = doc.split('\n', 1)
2998 3067 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2999 3068 if tail:
3000 3069 ui.write(minirst.format(tail, textwidth))
3001 3070 ui.status('\n')
3002 3071
3003 3072 if mod:
3004 3073 try:
3005 3074 ct = mod.cmdtable
3006 3075 except AttributeError:
3007 3076 ct = {}
3008 3077 modcmds = set([c.split('|', 1)[0] for c in ct])
3009 3078 helplist(modcmds.__contains__)
3010 3079 else:
3011 3080 ui.write(_('use "hg help extensions" for information on enabling '
3012 3081 'extensions\n'))
3013 3082
3014 3083 def helpextcmd(name):
3015 3084 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
3016 3085 doc = gettext(mod.__doc__).splitlines()[0]
3017 3086
3018 3087 msg = help.listexts(_("'%s' is provided by the following "
3019 3088 "extension:") % cmd, {ext: doc}, indent=4)
3020 3089 ui.write(minirst.format(msg, textwidth))
3021 3090 ui.write('\n')
3022 3091 ui.write(_('use "hg help extensions" for information on enabling '
3023 3092 'extensions\n'))
3024 3093
3025 3094 if name and name != 'shortlist':
3026 3095 i = None
3027 3096 if unknowncmd:
3028 3097 queries = (helpextcmd,)
3029 3098 elif opts.get('extension'):
3030 3099 queries = (helpext,)
3031 3100 elif opts.get('command'):
3032 3101 queries = (helpcmd,)
3033 3102 else:
3034 3103 queries = (helptopic, helpcmd, helpext, helpextcmd)
3035 3104 for f in queries:
3036 3105 try:
3037 3106 f(name)
3038 3107 i = None
3039 3108 break
3040 3109 except error.UnknownCommand, inst:
3041 3110 i = inst
3042 3111 if i:
3043 3112 raise i
3044 3113 else:
3045 3114 # program name
3046 3115 ui.status(_("Mercurial Distributed SCM\n"))
3047 3116 ui.status('\n')
3048 3117 helplist()
3049 3118
3050 3119
3051 3120 @command('identify|id',
3052 3121 [('r', 'rev', '',
3053 3122 _('identify the specified revision'), _('REV')),
3054 3123 ('n', 'num', None, _('show local revision number')),
3055 3124 ('i', 'id', None, _('show global revision id')),
3056 3125 ('b', 'branch', None, _('show branch')),
3057 3126 ('t', 'tags', None, _('show tags')),
3058 3127 ('B', 'bookmarks', None, _('show bookmarks'))],
3059 3128 _('[-nibtB] [-r REV] [SOURCE]'))
3060 3129 def identify(ui, repo, source=None, rev=None,
3061 3130 num=None, id=None, branch=None, tags=None, bookmarks=None):
3062 3131 """identify the working copy or specified revision
3063 3132
3064 3133 Print a summary identifying the repository state at REV using one or
3065 3134 two parent hash identifiers, followed by a "+" if the working
3066 3135 directory has uncommitted changes, the branch name (if not default),
3067 3136 a list of tags, and a list of bookmarks.
3068 3137
3069 3138 When REV is not given, print a summary of the current state of the
3070 3139 repository.
3071 3140
3072 3141 Specifying a path to a repository root or Mercurial bundle will
3073 3142 cause lookup to operate on that repository/bundle.
3074 3143
3075 3144 .. container:: verbose
3076 3145
3077 3146 Examples:
3078 3147
3079 3148 - generate a build identifier for the working directory::
3080 3149
3081 3150 hg id --id > build-id.dat
3082 3151
3083 3152 - find the revision corresponding to a tag::
3084 3153
3085 3154 hg id -n -r 1.3
3086 3155
3087 3156 - check the most recent revision of a remote repository::
3088 3157
3089 3158 hg id -r tip http://selenic.com/hg/
3090 3159
3091 3160 Returns 0 if successful.
3092 3161 """
3093 3162
3094 3163 if not repo and not source:
3095 3164 raise util.Abort(_("there is no Mercurial repository here "
3096 3165 "(.hg not found)"))
3097 3166
3098 3167 hexfunc = ui.debugflag and hex or short
3099 3168 default = not (num or id or branch or tags or bookmarks)
3100 3169 output = []
3101 3170 revs = []
3102 3171
3103 3172 if source:
3104 3173 source, branches = hg.parseurl(ui.expandpath(source))
3105 3174 repo = hg.peer(ui, {}, source)
3106 3175 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3107 3176
3108 3177 if not repo.local():
3109 3178 if num or branch or tags:
3110 3179 raise util.Abort(
3111 3180 _("can't query remote revision number, branch, or tags"))
3112 3181 if not rev and revs:
3113 3182 rev = revs[0]
3114 3183 if not rev:
3115 3184 rev = "tip"
3116 3185
3117 3186 remoterev = repo.lookup(rev)
3118 3187 if default or id:
3119 3188 output = [hexfunc(remoterev)]
3120 3189
3121 3190 def getbms():
3122 3191 bms = []
3123 3192
3124 3193 if 'bookmarks' in repo.listkeys('namespaces'):
3125 3194 hexremoterev = hex(remoterev)
3126 3195 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3127 3196 if bmr == hexremoterev]
3128 3197
3129 3198 return bms
3130 3199
3131 3200 if bookmarks:
3132 3201 output.extend(getbms())
3133 3202 elif default and not ui.quiet:
3134 3203 # multiple bookmarks for a single parent separated by '/'
3135 3204 bm = '/'.join(getbms())
3136 3205 if bm:
3137 3206 output.append(bm)
3138 3207 else:
3139 3208 if not rev:
3140 3209 ctx = repo[None]
3141 3210 parents = ctx.parents()
3142 3211 changed = ""
3143 3212 if default or id or num:
3144 3213 changed = util.any(repo.status()) and "+" or ""
3145 3214 if default or id:
3146 3215 output = ["%s%s" %
3147 3216 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3148 3217 if num:
3149 3218 output.append("%s%s" %
3150 3219 ('+'.join([str(p.rev()) for p in parents]), changed))
3151 3220 else:
3152 3221 ctx = scmutil.revsingle(repo, rev)
3153 3222 if default or id:
3154 3223 output = [hexfunc(ctx.node())]
3155 3224 if num:
3156 3225 output.append(str(ctx.rev()))
3157 3226
3158 3227 if default and not ui.quiet:
3159 3228 b = ctx.branch()
3160 3229 if b != 'default':
3161 3230 output.append("(%s)" % b)
3162 3231
3163 3232 # multiple tags for a single parent separated by '/'
3164 3233 t = '/'.join(ctx.tags())
3165 3234 if t:
3166 3235 output.append(t)
3167 3236
3168 3237 # multiple bookmarks for a single parent separated by '/'
3169 3238 bm = '/'.join(ctx.bookmarks())
3170 3239 if bm:
3171 3240 output.append(bm)
3172 3241 else:
3173 3242 if branch:
3174 3243 output.append(ctx.branch())
3175 3244
3176 3245 if tags:
3177 3246 output.extend(ctx.tags())
3178 3247
3179 3248 if bookmarks:
3180 3249 output.extend(ctx.bookmarks())
3181 3250
3182 3251 ui.write("%s\n" % ' '.join(output))
3183 3252
3184 3253 @command('import|patch',
3185 3254 [('p', 'strip', 1,
3186 3255 _('directory strip option for patch. This has the same '
3187 3256 'meaning as the corresponding patch option'), _('NUM')),
3188 3257 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3189 3258 ('e', 'edit', False, _('invoke editor on commit messages')),
3190 3259 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3191 3260 ('', 'no-commit', None,
3192 3261 _("don't commit, just update the working directory")),
3193 3262 ('', 'bypass', None,
3194 3263 _("apply patch without touching the working directory")),
3195 3264 ('', 'exact', None,
3196 3265 _('apply patch to the nodes from which it was generated')),
3197 3266 ('', 'import-branch', None,
3198 3267 _('use any branch information in patch (implied by --exact)'))] +
3199 3268 commitopts + commitopts2 + similarityopts,
3200 3269 _('[OPTION]... PATCH...'))
3201 3270 def import_(ui, repo, patch1, *patches, **opts):
3202 3271 """import an ordered set of patches
3203 3272
3204 3273 Import a list of patches and commit them individually (unless
3205 3274 --no-commit is specified).
3206 3275
3207 3276 If there are outstanding changes in the working directory, import
3208 3277 will abort unless given the -f/--force flag.
3209 3278
3210 3279 You can import a patch straight from a mail message. Even patches
3211 3280 as attachments work (to use the body part, it must have type
3212 3281 text/plain or text/x-patch). From and Subject headers of email
3213 3282 message are used as default committer and commit message. All
3214 3283 text/plain body parts before first diff are added to commit
3215 3284 message.
3216 3285
3217 3286 If the imported patch was generated by :hg:`export`, user and
3218 3287 description from patch override values from message headers and
3219 3288 body. Values given on command line with -m/--message and -u/--user
3220 3289 override these.
3221 3290
3222 3291 If --exact is specified, import will set the working directory to
3223 3292 the parent of each patch before applying it, and will abort if the
3224 3293 resulting changeset has a different ID than the one recorded in
3225 3294 the patch. This may happen due to character set problems or other
3226 3295 deficiencies in the text patch format.
3227 3296
3228 3297 Use --bypass to apply and commit patches directly to the
3229 3298 repository, not touching the working directory. Without --exact,
3230 3299 patches will be applied on top of the working directory parent
3231 3300 revision.
3232 3301
3233 3302 With -s/--similarity, hg will attempt to discover renames and
3234 3303 copies in the patch in the same way as 'addremove'.
3235 3304
3236 3305 To read a patch from standard input, use "-" as the patch name. If
3237 3306 a URL is specified, the patch will be downloaded from it.
3238 3307 See :hg:`help dates` for a list of formats valid for -d/--date.
3239 3308
3240 3309 .. container:: verbose
3241 3310
3242 3311 Examples:
3243 3312
3244 3313 - import a traditional patch from a website and detect renames::
3245 3314
3246 3315 hg import -s 80 http://example.com/bugfix.patch
3247 3316
3248 3317 - import a changeset from an hgweb server::
3249 3318
3250 3319 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3251 3320
3252 3321 - import all the patches in an Unix-style mbox::
3253 3322
3254 3323 hg import incoming-patches.mbox
3255 3324
3256 3325 - attempt to exactly restore an exported changeset (not always
3257 3326 possible)::
3258 3327
3259 3328 hg import --exact proposed-fix.patch
3260 3329
3261 3330 Returns 0 on success.
3262 3331 """
3263 3332 patches = (patch1,) + patches
3264 3333
3265 3334 date = opts.get('date')
3266 3335 if date:
3267 3336 opts['date'] = util.parsedate(date)
3268 3337
3269 3338 editor = cmdutil.commiteditor
3270 3339 if opts.get('edit'):
3271 3340 editor = cmdutil.commitforceeditor
3272 3341
3273 3342 update = not opts.get('bypass')
3274 3343 if not update and opts.get('no_commit'):
3275 3344 raise util.Abort(_('cannot use --no-commit with --bypass'))
3276 3345 try:
3277 3346 sim = float(opts.get('similarity') or 0)
3278 3347 except ValueError:
3279 3348 raise util.Abort(_('similarity must be a number'))
3280 3349 if sim < 0 or sim > 100:
3281 3350 raise util.Abort(_('similarity must be between 0 and 100'))
3282 3351 if sim and not update:
3283 3352 raise util.Abort(_('cannot use --similarity with --bypass'))
3284 3353
3285 3354 if (opts.get('exact') or not opts.get('force')) and update:
3286 3355 cmdutil.bailifchanged(repo)
3287 3356
3288 3357 base = opts["base"]
3289 3358 strip = opts["strip"]
3290 3359 wlock = lock = tr = None
3291 3360 msgs = []
3292 3361
3293 3362 def checkexact(repo, n, nodeid):
3294 3363 if opts.get('exact') and hex(n) != nodeid:
3295 3364 repo.rollback()
3296 3365 raise util.Abort(_('patch is damaged or loses information'))
3297 3366
3298 3367 def tryone(ui, hunk, parents):
3299 3368 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3300 3369 patch.extract(ui, hunk)
3301 3370
3302 3371 if not tmpname:
3303 3372 return (None, None)
3304 3373 msg = _('applied to working directory')
3305 3374
3306 3375 try:
3307 3376 cmdline_message = cmdutil.logmessage(ui, opts)
3308 3377 if cmdline_message:
3309 3378 # pickup the cmdline msg
3310 3379 message = cmdline_message
3311 3380 elif message:
3312 3381 # pickup the patch msg
3313 3382 message = message.strip()
3314 3383 else:
3315 3384 # launch the editor
3316 3385 message = None
3317 3386 ui.debug('message:\n%s\n' % message)
3318 3387
3319 3388 if len(parents) == 1:
3320 3389 parents.append(repo[nullid])
3321 3390 if opts.get('exact'):
3322 3391 if not nodeid or not p1:
3323 3392 raise util.Abort(_('not a Mercurial patch'))
3324 3393 p1 = repo[p1]
3325 3394 p2 = repo[p2 or nullid]
3326 3395 elif p2:
3327 3396 try:
3328 3397 p1 = repo[p1]
3329 3398 p2 = repo[p2]
3330 3399 except error.RepoError:
3331 3400 p1, p2 = parents
3332 3401 else:
3333 3402 p1, p2 = parents
3334 3403
3335 3404 n = None
3336 3405 if update:
3337 3406 if opts.get('exact') and p1 != parents[0]:
3338 3407 hg.clean(repo, p1.node())
3339 3408 if p1 != parents[0] and p2 != parents[1]:
3340 3409 repo.dirstate.setparents(p1.node(), p2.node())
3341 3410
3342 3411 if opts.get('exact') or opts.get('import_branch'):
3343 3412 repo.dirstate.setbranch(branch or 'default')
3344 3413
3345 3414 files = set()
3346 3415 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3347 3416 eolmode=None, similarity=sim / 100.0)
3348 3417 files = list(files)
3349 3418 if opts.get('no_commit'):
3350 3419 if message:
3351 3420 msgs.append(message)
3352 3421 else:
3353 3422 if opts.get('exact'):
3354 3423 m = None
3355 3424 else:
3356 3425 m = scmutil.matchfiles(repo, files or [])
3357 3426 n = repo.commit(message, opts.get('user') or user,
3358 3427 opts.get('date') or date, match=m,
3359 3428 editor=editor)
3360 3429 checkexact(repo, n, nodeid)
3361 3430 else:
3362 3431 if opts.get('exact') or opts.get('import_branch'):
3363 3432 branch = branch or 'default'
3364 3433 else:
3365 3434 branch = p1.branch()
3366 3435 store = patch.filestore()
3367 3436 try:
3368 3437 files = set()
3369 3438 try:
3370 3439 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3371 3440 files, eolmode=None)
3372 3441 except patch.PatchError, e:
3373 3442 raise util.Abort(str(e))
3374 3443 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3375 3444 message,
3376 3445 opts.get('user') or user,
3377 3446 opts.get('date') or date,
3378 3447 branch, files, store,
3379 3448 editor=cmdutil.commiteditor)
3380 3449 repo.savecommitmessage(memctx.description())
3381 3450 n = memctx.commit()
3382 3451 checkexact(repo, n, nodeid)
3383 3452 finally:
3384 3453 store.close()
3385 3454 if n:
3386 3455 msg = _('created %s') % short(n)
3387 3456 return (msg, n)
3388 3457 finally:
3389 3458 os.unlink(tmpname)
3390 3459
3391 3460 try:
3392 3461 wlock = repo.wlock()
3393 3462 lock = repo.lock()
3394 3463 tr = repo.transaction('import')
3395 3464 parents = repo.parents()
3396 3465 for patchurl in patches:
3397 3466 if patchurl == '-':
3398 3467 ui.status(_('applying patch from stdin\n'))
3399 3468 patchfile = ui.fin
3400 3469 patchurl = 'stdin' # for error message
3401 3470 else:
3402 3471 patchurl = os.path.join(base, patchurl)
3403 3472 ui.status(_('applying %s\n') % patchurl)
3404 3473 patchfile = url.open(ui, patchurl)
3405 3474
3406 3475 haspatch = False
3407 3476 for hunk in patch.split(patchfile):
3408 3477 (msg, node) = tryone(ui, hunk, parents)
3409 3478 if msg:
3410 3479 haspatch = True
3411 3480 ui.note(msg + '\n')
3412 3481 if update or opts.get('exact'):
3413 3482 parents = repo.parents()
3414 3483 else:
3415 3484 parents = [repo[node]]
3416 3485
3417 3486 if not haspatch:
3418 3487 raise util.Abort(_('%s: no diffs found') % patchurl)
3419 3488
3420 3489 tr.close()
3421 3490 if msgs:
3422 3491 repo.savecommitmessage('\n* * *\n'.join(msgs))
3423 3492 except:
3424 3493 # wlock.release() indirectly calls dirstate.write(): since
3425 3494 # we're crashing, we do not want to change the working dir
3426 3495 # parent after all, so make sure it writes nothing
3427 3496 repo.dirstate.invalidate()
3428 3497 raise
3429 3498 finally:
3430 3499 if tr:
3431 3500 tr.release()
3432 3501 release(lock, wlock)
3433 3502
3434 3503 @command('incoming|in',
3435 3504 [('f', 'force', None,
3436 3505 _('run even if remote repository is unrelated')),
3437 3506 ('n', 'newest-first', None, _('show newest record first')),
3438 3507 ('', 'bundle', '',
3439 3508 _('file to store the bundles into'), _('FILE')),
3440 3509 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3441 3510 ('B', 'bookmarks', False, _("compare bookmarks")),
3442 3511 ('b', 'branch', [],
3443 3512 _('a specific branch you would like to pull'), _('BRANCH')),
3444 3513 ] + logopts + remoteopts + subrepoopts,
3445 3514 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3446 3515 def incoming(ui, repo, source="default", **opts):
3447 3516 """show new changesets found in source
3448 3517
3449 3518 Show new changesets found in the specified path/URL or the default
3450 3519 pull location. These are the changesets that would have been pulled
3451 3520 if a pull at the time you issued this command.
3452 3521
3453 3522 For remote repository, using --bundle avoids downloading the
3454 3523 changesets twice if the incoming is followed by a pull.
3455 3524
3456 3525 See pull for valid source format details.
3457 3526
3458 3527 Returns 0 if there are incoming changes, 1 otherwise.
3459 3528 """
3460 3529 if opts.get('bundle') and opts.get('subrepos'):
3461 3530 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3462 3531
3463 3532 if opts.get('bookmarks'):
3464 3533 source, branches = hg.parseurl(ui.expandpath(source),
3465 3534 opts.get('branch'))
3466 3535 other = hg.peer(repo, opts, source)
3467 3536 if 'bookmarks' not in other.listkeys('namespaces'):
3468 3537 ui.warn(_("remote doesn't support bookmarks\n"))
3469 3538 return 0
3470 3539 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3471 3540 return bookmarks.diff(ui, repo, other)
3472 3541
3473 3542 repo._subtoppath = ui.expandpath(source)
3474 3543 try:
3475 3544 return hg.incoming(ui, repo, source, opts)
3476 3545 finally:
3477 3546 del repo._subtoppath
3478 3547
3479 3548
3480 3549 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3481 3550 def init(ui, dest=".", **opts):
3482 3551 """create a new repository in the given directory
3483 3552
3484 3553 Initialize a new repository in the given directory. If the given
3485 3554 directory does not exist, it will be created.
3486 3555
3487 3556 If no directory is given, the current directory is used.
3488 3557
3489 3558 It is possible to specify an ``ssh://`` URL as the destination.
3490 3559 See :hg:`help urls` for more information.
3491 3560
3492 3561 Returns 0 on success.
3493 3562 """
3494 3563 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3495 3564
3496 3565 @command('locate',
3497 3566 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3498 3567 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3499 3568 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3500 3569 ] + walkopts,
3501 3570 _('[OPTION]... [PATTERN]...'))
3502 3571 def locate(ui, repo, *pats, **opts):
3503 3572 """locate files matching specific patterns
3504 3573
3505 3574 Print files under Mercurial control in the working directory whose
3506 3575 names match the given patterns.
3507 3576
3508 3577 By default, this command searches all directories in the working
3509 3578 directory. To search just the current directory and its
3510 3579 subdirectories, use "--include .".
3511 3580
3512 3581 If no patterns are given to match, this command prints the names
3513 3582 of all files under Mercurial control in the working directory.
3514 3583
3515 3584 If you want to feed the output of this command into the "xargs"
3516 3585 command, use the -0 option to both this command and "xargs". This
3517 3586 will avoid the problem of "xargs" treating single filenames that
3518 3587 contain whitespace as multiple filenames.
3519 3588
3520 3589 Returns 0 if a match is found, 1 otherwise.
3521 3590 """
3522 3591 end = opts.get('print0') and '\0' or '\n'
3523 3592 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3524 3593
3525 3594 ret = 1
3526 3595 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3527 3596 m.bad = lambda x, y: False
3528 3597 for abs in repo[rev].walk(m):
3529 3598 if not rev and abs not in repo.dirstate:
3530 3599 continue
3531 3600 if opts.get('fullpath'):
3532 3601 ui.write(repo.wjoin(abs), end)
3533 3602 else:
3534 3603 ui.write(((pats and m.rel(abs)) or abs), end)
3535 3604 ret = 0
3536 3605
3537 3606 return ret
3538 3607
3539 3608 @command('^log|history',
3540 3609 [('f', 'follow', None,
3541 3610 _('follow changeset history, or file history across copies and renames')),
3542 3611 ('', 'follow-first', None,
3543 3612 _('only follow the first parent of merge changesets')),
3544 3613 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3545 3614 ('C', 'copies', None, _('show copied files')),
3546 3615 ('k', 'keyword', [],
3547 3616 _('do case-insensitive search for a given text'), _('TEXT')),
3548 3617 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3549 3618 ('', 'removed', None, _('include revisions where files were removed')),
3550 3619 ('m', 'only-merges', None, _('show only merges')),
3551 3620 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3552 3621 ('', 'only-branch', [],
3553 3622 _('show only changesets within the given named branch (DEPRECATED)'),
3554 3623 _('BRANCH')),
3555 3624 ('b', 'branch', [],
3556 3625 _('show changesets within the given named branch'), _('BRANCH')),
3557 3626 ('P', 'prune', [],
3558 3627 _('do not display revision or any of its ancestors'), _('REV')),
3559 3628 ('', 'hidden', False, _('show hidden changesets')),
3560 3629 ] + logopts + walkopts,
3561 3630 _('[OPTION]... [FILE]'))
3562 3631 def log(ui, repo, *pats, **opts):
3563 3632 """show revision history of entire repository or files
3564 3633
3565 3634 Print the revision history of the specified files or the entire
3566 3635 project.
3567 3636
3568 3637 If no revision range is specified, the default is ``tip:0`` unless
3569 3638 --follow is set, in which case the working directory parent is
3570 3639 used as the starting revision.
3571 3640
3572 3641 File history is shown without following rename or copy history of
3573 3642 files. Use -f/--follow with a filename to follow history across
3574 3643 renames and copies. --follow without a filename will only show
3575 3644 ancestors or descendants of the starting revision.
3576 3645
3577 3646 By default this command prints revision number and changeset id,
3578 3647 tags, non-trivial parents, user, date and time, and a summary for
3579 3648 each commit. When the -v/--verbose switch is used, the list of
3580 3649 changed files and full commit message are shown.
3581 3650
3582 3651 .. note::
3583 3652 log -p/--patch may generate unexpected diff output for merge
3584 3653 changesets, as it will only compare the merge changeset against
3585 3654 its first parent. Also, only files different from BOTH parents
3586 3655 will appear in files:.
3587 3656
3588 3657 .. note::
3589 3658 for performance reasons, log FILE may omit duplicate changes
3590 3659 made on branches and will not show deletions. To see all
3591 3660 changes including duplicates and deletions, use the --removed
3592 3661 switch.
3593 3662
3594 3663 .. container:: verbose
3595 3664
3596 3665 Some examples:
3597 3666
3598 3667 - changesets with full descriptions and file lists::
3599 3668
3600 3669 hg log -v
3601 3670
3602 3671 - changesets ancestral to the working directory::
3603 3672
3604 3673 hg log -f
3605 3674
3606 3675 - last 10 commits on the current branch::
3607 3676
3608 3677 hg log -l 10 -b .
3609 3678
3610 3679 - changesets showing all modifications of a file, including removals::
3611 3680
3612 3681 hg log --removed file.c
3613 3682
3614 3683 - all changesets that touch a directory, with diffs, excluding merges::
3615 3684
3616 3685 hg log -Mp lib/
3617 3686
3618 3687 - all revision numbers that match a keyword::
3619 3688
3620 3689 hg log -k bug --template "{rev}\\n"
3621 3690
3622 3691 - check if a given changeset is included is a tagged release::
3623 3692
3624 3693 hg log -r "a21ccf and ancestor(1.9)"
3625 3694
3626 3695 - find all changesets by some user in a date range::
3627 3696
3628 3697 hg log -k alice -d "may 2008 to jul 2008"
3629 3698
3630 3699 - summary of all changesets after the last tag::
3631 3700
3632 3701 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3633 3702
3634 3703 See :hg:`help dates` for a list of formats valid for -d/--date.
3635 3704
3636 3705 See :hg:`help revisions` and :hg:`help revsets` for more about
3637 3706 specifying revisions.
3638 3707
3639 3708 Returns 0 on success.
3640 3709 """
3641 3710
3642 3711 matchfn = scmutil.match(repo[None], pats, opts)
3643 3712 limit = cmdutil.loglimit(opts)
3644 3713 count = 0
3645 3714
3646 3715 endrev = None
3647 3716 if opts.get('copies') and opts.get('rev'):
3648 3717 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3649 3718
3650 3719 df = False
3651 3720 if opts["date"]:
3652 3721 df = util.matchdate(opts["date"])
3653 3722
3654 3723 branches = opts.get('branch', []) + opts.get('only_branch', [])
3655 3724 opts['branch'] = [repo.lookupbranch(b) for b in branches]
3656 3725
3657 3726 displayer = cmdutil.show_changeset(ui, repo, opts, True)
3658 3727 def prep(ctx, fns):
3659 3728 rev = ctx.rev()
3660 3729 parents = [p for p in repo.changelog.parentrevs(rev)
3661 3730 if p != nullrev]
3662 3731 if opts.get('no_merges') and len(parents) == 2:
3663 3732 return
3664 3733 if opts.get('only_merges') and len(parents) != 2:
3665 3734 return
3666 3735 if opts.get('branch') and ctx.branch() not in opts['branch']:
3667 3736 return
3668 3737 if not opts.get('hidden') and ctx.hidden():
3669 3738 return
3670 3739 if df and not df(ctx.date()[0]):
3671 3740 return
3672 3741 if opts['user'] and not [k for k in opts['user']
3673 3742 if k.lower() in ctx.user().lower()]:
3674 3743 return
3675 3744 if opts.get('keyword'):
3676 3745 for k in [kw.lower() for kw in opts['keyword']]:
3677 3746 if (k in ctx.user().lower() or
3678 3747 k in ctx.description().lower() or
3679 3748 k in " ".join(ctx.files()).lower()):
3680 3749 break
3681 3750 else:
3682 3751 return
3683 3752
3684 3753 copies = None
3685 3754 if opts.get('copies') and rev:
3686 3755 copies = []
3687 3756 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3688 3757 for fn in ctx.files():
3689 3758 rename = getrenamed(fn, rev)
3690 3759 if rename:
3691 3760 copies.append((fn, rename[0]))
3692 3761
3693 3762 revmatchfn = None
3694 3763 if opts.get('patch') or opts.get('stat'):
3695 3764 if opts.get('follow') or opts.get('follow_first'):
3696 3765 # note: this might be wrong when following through merges
3697 3766 revmatchfn = scmutil.match(repo[None], fns, default='path')
3698 3767 else:
3699 3768 revmatchfn = matchfn
3700 3769
3701 3770 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3702 3771
3703 3772 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3704 3773 if count == limit:
3705 3774 break
3706 3775 if displayer.flush(ctx.rev()):
3707 3776 count += 1
3708 3777 displayer.close()
3709 3778
3710 3779 @command('manifest',
3711 3780 [('r', 'rev', '', _('revision to display'), _('REV')),
3712 3781 ('', 'all', False, _("list files from all revisions"))],
3713 3782 _('[-r REV]'))
3714 3783 def manifest(ui, repo, node=None, rev=None, **opts):
3715 3784 """output the current or given revision of the project manifest
3716 3785
3717 3786 Print a list of version controlled files for the given revision.
3718 3787 If no revision is given, the first parent of the working directory
3719 3788 is used, or the null revision if no revision is checked out.
3720 3789
3721 3790 With -v, print file permissions, symlink and executable bits.
3722 3791 With --debug, print file revision hashes.
3723 3792
3724 3793 If option --all is specified, the list of all files from all revisions
3725 3794 is printed. This includes deleted and renamed files.
3726 3795
3727 3796 Returns 0 on success.
3728 3797 """
3729 3798 if opts.get('all'):
3730 3799 if rev or node:
3731 3800 raise util.Abort(_("can't specify a revision with --all"))
3732 3801
3733 3802 res = []
3734 3803 prefix = "data/"
3735 3804 suffix = ".i"
3736 3805 plen = len(prefix)
3737 3806 slen = len(suffix)
3738 3807 lock = repo.lock()
3739 3808 try:
3740 3809 for fn, b, size in repo.store.datafiles():
3741 3810 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3742 3811 res.append(fn[plen:-slen])
3743 3812 finally:
3744 3813 lock.release()
3745 3814 for f in sorted(res):
3746 3815 ui.write("%s\n" % f)
3747 3816 return
3748 3817
3749 3818 if rev and node:
3750 3819 raise util.Abort(_("please specify just one revision"))
3751 3820
3752 3821 if not node:
3753 3822 node = rev
3754 3823
3755 3824 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
3756 3825 ctx = scmutil.revsingle(repo, node)
3757 3826 for f in ctx:
3758 3827 if ui.debugflag:
3759 3828 ui.write("%40s " % hex(ctx.manifest()[f]))
3760 3829 if ui.verbose:
3761 3830 ui.write(decor[ctx.flags(f)])
3762 3831 ui.write("%s\n" % f)
3763 3832
3764 3833 @command('^merge',
3765 3834 [('f', 'force', None, _('force a merge with outstanding changes')),
3766 3835 ('r', 'rev', '', _('revision to merge'), _('REV')),
3767 3836 ('P', 'preview', None,
3768 3837 _('review revisions to merge (no merge is performed)'))
3769 3838 ] + mergetoolopts,
3770 3839 _('[-P] [-f] [[-r] REV]'))
3771 3840 def merge(ui, repo, node=None, **opts):
3772 3841 """merge working directory with another revision
3773 3842
3774 3843 The current working directory is updated with all changes made in
3775 3844 the requested revision since the last common predecessor revision.
3776 3845
3777 3846 Files that changed between either parent are marked as changed for
3778 3847 the next commit and a commit must be performed before any further
3779 3848 updates to the repository are allowed. The next commit will have
3780 3849 two parents.
3781 3850
3782 3851 ``--tool`` can be used to specify the merge tool used for file
3783 3852 merges. It overrides the HGMERGE environment variable and your
3784 3853 configuration files. See :hg:`help merge-tools` for options.
3785 3854
3786 3855 If no revision is specified, the working directory's parent is a
3787 3856 head revision, and the current branch contains exactly one other
3788 3857 head, the other head is merged with by default. Otherwise, an
3789 3858 explicit revision with which to merge with must be provided.
3790 3859
3791 3860 :hg:`resolve` must be used to resolve unresolved files.
3792 3861
3793 3862 To undo an uncommitted merge, use :hg:`update --clean .` which
3794 3863 will check out a clean copy of the original merge parent, losing
3795 3864 all changes.
3796 3865
3797 3866 Returns 0 on success, 1 if there are unresolved files.
3798 3867 """
3799 3868
3800 3869 if opts.get('rev') and node:
3801 3870 raise util.Abort(_("please specify just one revision"))
3802 3871 if not node:
3803 3872 node = opts.get('rev')
3804 3873
3805 3874 if not node:
3806 3875 branch = repo[None].branch()
3807 3876 bheads = repo.branchheads(branch)
3808 3877 if len(bheads) > 2:
3809 3878 raise util.Abort(_("branch '%s' has %d heads - "
3810 3879 "please merge with an explicit rev")
3811 3880 % (branch, len(bheads)),
3812 3881 hint=_("run 'hg heads .' to see heads"))
3813 3882
3814 3883 parent = repo.dirstate.p1()
3815 3884 if len(bheads) == 1:
3816 3885 if len(repo.heads()) > 1:
3817 3886 raise util.Abort(_("branch '%s' has one head - "
3818 3887 "please merge with an explicit rev")
3819 3888 % branch,
3820 3889 hint=_("run 'hg heads' to see all heads"))
3821 3890 msg = _('there is nothing to merge')
3822 3891 if parent != repo.lookup(repo[None].branch()):
3823 3892 msg = _('%s - use "hg update" instead') % msg
3824 3893 raise util.Abort(msg)
3825 3894
3826 3895 if parent not in bheads:
3827 3896 raise util.Abort(_('working directory not at a head revision'),
3828 3897 hint=_("use 'hg update' or merge with an "
3829 3898 "explicit revision"))
3830 3899 node = parent == bheads[0] and bheads[-1] or bheads[0]
3831 3900 else:
3832 3901 node = scmutil.revsingle(repo, node).node()
3833 3902
3834 3903 if opts.get('preview'):
3835 3904 # find nodes that are ancestors of p2 but not of p1
3836 3905 p1 = repo.lookup('.')
3837 3906 p2 = repo.lookup(node)
3838 3907 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3839 3908
3840 3909 displayer = cmdutil.show_changeset(ui, repo, opts)
3841 3910 for node in nodes:
3842 3911 displayer.show(repo[node])
3843 3912 displayer.close()
3844 3913 return 0
3845 3914
3846 3915 try:
3847 3916 # ui.forcemerge is an internal variable, do not document
3848 3917 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3849 3918 return hg.merge(repo, node, force=opts.get('force'))
3850 3919 finally:
3851 3920 ui.setconfig('ui', 'forcemerge', '')
3852 3921
3853 3922 @command('outgoing|out',
3854 3923 [('f', 'force', None, _('run even when the destination is unrelated')),
3855 3924 ('r', 'rev', [],
3856 3925 _('a changeset intended to be included in the destination'), _('REV')),
3857 3926 ('n', 'newest-first', None, _('show newest record first')),
3858 3927 ('B', 'bookmarks', False, _('compare bookmarks')),
3859 3928 ('b', 'branch', [], _('a specific branch you would like to push'),
3860 3929 _('BRANCH')),
3861 3930 ] + logopts + remoteopts + subrepoopts,
3862 3931 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3863 3932 def outgoing(ui, repo, dest=None, **opts):
3864 3933 """show changesets not found in the destination
3865 3934
3866 3935 Show changesets not found in the specified destination repository
3867 3936 or the default push location. These are the changesets that would
3868 3937 be pushed if a push was requested.
3869 3938
3870 3939 See pull for details of valid destination formats.
3871 3940
3872 3941 Returns 0 if there are outgoing changes, 1 otherwise.
3873 3942 """
3874 3943
3875 3944 if opts.get('bookmarks'):
3876 3945 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3877 3946 dest, branches = hg.parseurl(dest, opts.get('branch'))
3878 3947 other = hg.peer(repo, opts, dest)
3879 3948 if 'bookmarks' not in other.listkeys('namespaces'):
3880 3949 ui.warn(_("remote doesn't support bookmarks\n"))
3881 3950 return 0
3882 3951 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3883 3952 return bookmarks.diff(ui, other, repo)
3884 3953
3885 3954 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3886 3955 try:
3887 3956 return hg.outgoing(ui, repo, dest, opts)
3888 3957 finally:
3889 3958 del repo._subtoppath
3890 3959
3891 3960 @command('parents',
3892 3961 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3893 3962 ] + templateopts,
3894 3963 _('[-r REV] [FILE]'))
3895 3964 def parents(ui, repo, file_=None, **opts):
3896 3965 """show the parents of the working directory or revision
3897 3966
3898 3967 Print the working directory's parent revisions. If a revision is
3899 3968 given via -r/--rev, the parent of that revision will be printed.
3900 3969 If a file argument is given, the revision in which the file was
3901 3970 last changed (before the working directory revision or the
3902 3971 argument to --rev if given) is printed.
3903 3972
3904 3973 Returns 0 on success.
3905 3974 """
3906 3975
3907 3976 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3908 3977
3909 3978 if file_:
3910 3979 m = scmutil.match(ctx, (file_,), opts)
3911 3980 if m.anypats() or len(m.files()) != 1:
3912 3981 raise util.Abort(_('can only specify an explicit filename'))
3913 3982 file_ = m.files()[0]
3914 3983 filenodes = []
3915 3984 for cp in ctx.parents():
3916 3985 if not cp:
3917 3986 continue
3918 3987 try:
3919 3988 filenodes.append(cp.filenode(file_))
3920 3989 except error.LookupError:
3921 3990 pass
3922 3991 if not filenodes:
3923 3992 raise util.Abort(_("'%s' not found in manifest!") % file_)
3924 3993 fl = repo.file(file_)
3925 3994 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
3926 3995 else:
3927 3996 p = [cp.node() for cp in ctx.parents()]
3928 3997
3929 3998 displayer = cmdutil.show_changeset(ui, repo, opts)
3930 3999 for n in p:
3931 4000 if n != nullid:
3932 4001 displayer.show(repo[n])
3933 4002 displayer.close()
3934 4003
3935 4004 @command('paths', [], _('[NAME]'))
3936 4005 def paths(ui, repo, search=None):
3937 4006 """show aliases for remote repositories
3938 4007
3939 4008 Show definition of symbolic path name NAME. If no name is given,
3940 4009 show definition of all available names.
3941 4010
3942 4011 Option -q/--quiet suppresses all output when searching for NAME
3943 4012 and shows only the path names when listing all definitions.
3944 4013
3945 4014 Path names are defined in the [paths] section of your
3946 4015 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3947 4016 repository, ``.hg/hgrc`` is used, too.
3948 4017
3949 4018 The path names ``default`` and ``default-push`` have a special
3950 4019 meaning. When performing a push or pull operation, they are used
3951 4020 as fallbacks if no location is specified on the command-line.
3952 4021 When ``default-push`` is set, it will be used for push and
3953 4022 ``default`` will be used for pull; otherwise ``default`` is used
3954 4023 as the fallback for both. When cloning a repository, the clone
3955 4024 source is written as ``default`` in ``.hg/hgrc``. Note that
3956 4025 ``default`` and ``default-push`` apply to all inbound (e.g.
3957 4026 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
3958 4027 :hg:`bundle`) operations.
3959 4028
3960 4029 See :hg:`help urls` for more information.
3961 4030
3962 4031 Returns 0 on success.
3963 4032 """
3964 4033 if search:
3965 4034 for name, path in ui.configitems("paths"):
3966 4035 if name == search:
3967 4036 ui.status("%s\n" % util.hidepassword(path))
3968 4037 return
3969 4038 if not ui.quiet:
3970 4039 ui.warn(_("not found!\n"))
3971 4040 return 1
3972 4041 else:
3973 4042 for name, path in ui.configitems("paths"):
3974 4043 if ui.quiet:
3975 4044 ui.write("%s\n" % name)
3976 4045 else:
3977 4046 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
3978 4047
3979 4048 def postincoming(ui, repo, modheads, optupdate, checkout):
3980 4049 if modheads == 0:
3981 4050 return
3982 4051 if optupdate:
3983 4052 try:
3984 4053 return hg.update(repo, checkout)
3985 4054 except util.Abort, inst:
3986 4055 ui.warn(_("not updating: %s\n" % str(inst)))
3987 4056 return 0
3988 4057 if modheads > 1:
3989 4058 currentbranchheads = len(repo.branchheads())
3990 4059 if currentbranchheads == modheads:
3991 4060 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3992 4061 elif currentbranchheads > 1:
3993 4062 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to merge)\n"))
3994 4063 else:
3995 4064 ui.status(_("(run 'hg heads' to see heads)\n"))
3996 4065 else:
3997 4066 ui.status(_("(run 'hg update' to get a working copy)\n"))
3998 4067
3999 4068 @command('^pull',
4000 4069 [('u', 'update', None,
4001 4070 _('update to new branch head if changesets were pulled')),
4002 4071 ('f', 'force', None, _('run even when remote repository is unrelated')),
4003 4072 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4004 4073 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4005 4074 ('b', 'branch', [], _('a specific branch you would like to pull'),
4006 4075 _('BRANCH')),
4007 4076 ] + remoteopts,
4008 4077 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4009 4078 def pull(ui, repo, source="default", **opts):
4010 4079 """pull changes from the specified source
4011 4080
4012 4081 Pull changes from a remote repository to a local one.
4013 4082
4014 4083 This finds all changes from the repository at the specified path
4015 4084 or URL and adds them to a local repository (the current one unless
4016 4085 -R is specified). By default, this does not update the copy of the
4017 4086 project in the working directory.
4018 4087
4019 4088 Use :hg:`incoming` if you want to see what would have been added
4020 4089 by a pull at the time you issued this command. If you then decide
4021 4090 to add those changes to the repository, you should use :hg:`pull
4022 4091 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4023 4092
4024 4093 If SOURCE is omitted, the 'default' path will be used.
4025 4094 See :hg:`help urls` for more information.
4026 4095
4027 4096 Returns 0 on success, 1 if an update had unresolved files.
4028 4097 """
4029 4098 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4030 4099 other = hg.peer(repo, opts, source)
4031 4100 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4032 4101 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4033 4102
4034 4103 if opts.get('bookmark'):
4035 4104 if not revs:
4036 4105 revs = []
4037 4106 rb = other.listkeys('bookmarks')
4038 4107 for b in opts['bookmark']:
4039 4108 if b not in rb:
4040 4109 raise util.Abort(_('remote bookmark %s not found!') % b)
4041 4110 revs.append(rb[b])
4042 4111
4043 4112 if revs:
4044 4113 try:
4045 4114 revs = [other.lookup(rev) for rev in revs]
4046 4115 except error.CapabilityError:
4047 4116 err = _("other repository doesn't support revision lookup, "
4048 4117 "so a rev cannot be specified.")
4049 4118 raise util.Abort(err)
4050 4119
4051 4120 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4052 4121 bookmarks.updatefromremote(ui, repo, other)
4053 4122 if checkout:
4054 4123 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4055 4124 repo._subtoppath = source
4056 4125 try:
4057 4126 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4058 4127
4059 4128 finally:
4060 4129 del repo._subtoppath
4061 4130
4062 4131 # update specified bookmarks
4063 4132 if opts.get('bookmark'):
4064 4133 for b in opts['bookmark']:
4065 4134 # explicit pull overrides local bookmark if any
4066 4135 ui.status(_("importing bookmark %s\n") % b)
4067 4136 repo._bookmarks[b] = repo[rb[b]].node()
4068 4137 bookmarks.write(repo)
4069 4138
4070 4139 return ret
4071 4140
4072 4141 @command('^push',
4073 4142 [('f', 'force', None, _('force push')),
4074 4143 ('r', 'rev', [],
4075 4144 _('a changeset intended to be included in the destination'),
4076 4145 _('REV')),
4077 4146 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4078 4147 ('b', 'branch', [],
4079 4148 _('a specific branch you would like to push'), _('BRANCH')),
4080 4149 ('', 'new-branch', False, _('allow pushing a new branch')),
4081 4150 ] + remoteopts,
4082 4151 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4083 4152 def push(ui, repo, dest=None, **opts):
4084 4153 """push changes to the specified destination
4085 4154
4086 4155 Push changesets from the local repository to the specified
4087 4156 destination.
4088 4157
4089 4158 This operation is symmetrical to pull: it is identical to a pull
4090 4159 in the destination repository from the current one.
4091 4160
4092 4161 By default, push will not allow creation of new heads at the
4093 4162 destination, since multiple heads would make it unclear which head
4094 4163 to use. In this situation, it is recommended to pull and merge
4095 4164 before pushing.
4096 4165
4097 4166 Use --new-branch if you want to allow push to create a new named
4098 4167 branch that is not present at the destination. This allows you to
4099 4168 only create a new branch without forcing other changes.
4100 4169
4101 4170 Use -f/--force to override the default behavior and push all
4102 4171 changesets on all branches.
4103 4172
4104 4173 If -r/--rev is used, the specified revision and all its ancestors
4105 4174 will be pushed to the remote repository.
4106 4175
4107 4176 Please see :hg:`help urls` for important details about ``ssh://``
4108 4177 URLs. If DESTINATION is omitted, a default path will be used.
4109 4178
4110 4179 Returns 0 if push was successful, 1 if nothing to push.
4111 4180 """
4112 4181
4113 4182 if opts.get('bookmark'):
4114 4183 for b in opts['bookmark']:
4115 4184 # translate -B options to -r so changesets get pushed
4116 4185 if b in repo._bookmarks:
4117 4186 opts.setdefault('rev', []).append(b)
4118 4187 else:
4119 4188 # if we try to push a deleted bookmark, translate it to null
4120 4189 # this lets simultaneous -r, -b options continue working
4121 4190 opts.setdefault('rev', []).append("null")
4122 4191
4123 4192 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4124 4193 dest, branches = hg.parseurl(dest, opts.get('branch'))
4125 4194 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4126 4195 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4127 4196 other = hg.peer(repo, opts, dest)
4128 4197 if revs:
4129 4198 revs = [repo.lookup(rev) for rev in revs]
4130 4199
4131 4200 repo._subtoppath = dest
4132 4201 try:
4133 4202 # push subrepos depth-first for coherent ordering
4134 4203 c = repo['']
4135 4204 subs = c.substate # only repos that are committed
4136 4205 for s in sorted(subs):
4137 4206 if not c.sub(s).push(opts.get('force')):
4138 4207 return False
4139 4208 finally:
4140 4209 del repo._subtoppath
4141 4210 result = repo.push(other, opts.get('force'), revs=revs,
4142 4211 newbranch=opts.get('new_branch'))
4143 4212
4144 4213 result = (result == 0)
4145 4214
4146 4215 if opts.get('bookmark'):
4147 4216 rb = other.listkeys('bookmarks')
4148 4217 for b in opts['bookmark']:
4149 4218 # explicit push overrides remote bookmark if any
4150 4219 if b in repo._bookmarks:
4151 4220 ui.status(_("exporting bookmark %s\n") % b)
4152 4221 new = repo[b].hex()
4153 4222 elif b in rb:
4154 4223 ui.status(_("deleting remote bookmark %s\n") % b)
4155 4224 new = '' # delete
4156 4225 else:
4157 4226 ui.warn(_('bookmark %s does not exist on the local '
4158 4227 'or remote repository!\n') % b)
4159 4228 return 2
4160 4229 old = rb.get(b, '')
4161 4230 r = other.pushkey('bookmarks', b, old, new)
4162 4231 if not r:
4163 4232 ui.warn(_('updating bookmark %s failed!\n') % b)
4164 4233 if not result:
4165 4234 result = 2
4166 4235
4167 4236 return result
4168 4237
4169 4238 @command('recover', [])
4170 4239 def recover(ui, repo):
4171 4240 """roll back an interrupted transaction
4172 4241
4173 4242 Recover from an interrupted commit or pull.
4174 4243
4175 4244 This command tries to fix the repository status after an
4176 4245 interrupted operation. It should only be necessary when Mercurial
4177 4246 suggests it.
4178 4247
4179 4248 Returns 0 if successful, 1 if nothing to recover or verify fails.
4180 4249 """
4181 4250 if repo.recover():
4182 4251 return hg.verify(repo)
4183 4252 return 1
4184 4253
4185 4254 @command('^remove|rm',
4186 4255 [('A', 'after', None, _('record delete for missing files')),
4187 4256 ('f', 'force', None,
4188 4257 _('remove (and delete) file even if added or modified')),
4189 4258 ] + walkopts,
4190 4259 _('[OPTION]... FILE...'))
4191 4260 def remove(ui, repo, *pats, **opts):
4192 4261 """remove the specified files on the next commit
4193 4262
4194 4263 Schedule the indicated files for removal from the current branch.
4195 4264
4196 4265 This command schedules the files to be removed at the next commit.
4197 4266 To undo a remove before that, see :hg:`revert`. To undo added
4198 4267 files, see :hg:`forget`.
4199 4268
4200 4269 .. container:: verbose
4201 4270
4202 4271 -A/--after can be used to remove only files that have already
4203 4272 been deleted, -f/--force can be used to force deletion, and -Af
4204 4273 can be used to remove files from the next revision without
4205 4274 deleting them from the working directory.
4206 4275
4207 4276 The following table details the behavior of remove for different
4208 4277 file states (columns) and option combinations (rows). The file
4209 4278 states are Added [A], Clean [C], Modified [M] and Missing [!]
4210 4279 (as reported by :hg:`status`). The actions are Warn, Remove
4211 4280 (from branch) and Delete (from disk):
4212 4281
4213 4282 ======= == == == ==
4214 4283 A C M !
4215 4284 ======= == == == ==
4216 4285 none W RD W R
4217 4286 -f R RD RD R
4218 4287 -A W W W R
4219 4288 -Af R R R R
4220 4289 ======= == == == ==
4221 4290
4222 4291 Note that remove never deletes files in Added [A] state from the
4223 4292 working directory, not even if option --force is specified.
4224 4293
4225 4294 Returns 0 on success, 1 if any warnings encountered.
4226 4295 """
4227 4296
4228 4297 ret = 0
4229 4298 after, force = opts.get('after'), opts.get('force')
4230 4299 if not pats and not after:
4231 4300 raise util.Abort(_('no files specified'))
4232 4301
4233 4302 m = scmutil.match(repo[None], pats, opts)
4234 4303 s = repo.status(match=m, clean=True)
4235 4304 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4236 4305
4237 4306 for f in m.files():
4238 4307 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4239 4308 if os.path.exists(m.rel(f)):
4240 4309 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4241 4310 ret = 1
4242 4311
4243 4312 if force:
4244 4313 list = modified + deleted + clean + added
4245 4314 elif after:
4246 4315 list = deleted
4247 4316 for f in modified + added + clean:
4248 4317 ui.warn(_('not removing %s: file still exists (use -f'
4249 4318 ' to force removal)\n') % m.rel(f))
4250 4319 ret = 1
4251 4320 else:
4252 4321 list = deleted + clean
4253 4322 for f in modified:
4254 4323 ui.warn(_('not removing %s: file is modified (use -f'
4255 4324 ' to force removal)\n') % m.rel(f))
4256 4325 ret = 1
4257 4326 for f in added:
4258 4327 ui.warn(_('not removing %s: file has been marked for add'
4259 4328 ' (use forget to undo)\n') % m.rel(f))
4260 4329 ret = 1
4261 4330
4262 4331 for f in sorted(list):
4263 4332 if ui.verbose or not m.exact(f):
4264 4333 ui.status(_('removing %s\n') % m.rel(f))
4265 4334
4266 4335 wlock = repo.wlock()
4267 4336 try:
4268 4337 if not after:
4269 4338 for f in list:
4270 4339 if f in added:
4271 4340 continue # we never unlink added files on remove
4272 4341 try:
4273 4342 util.unlinkpath(repo.wjoin(f))
4274 4343 except OSError, inst:
4275 4344 if inst.errno != errno.ENOENT:
4276 4345 raise
4277 4346 repo[None].forget(list)
4278 4347 finally:
4279 4348 wlock.release()
4280 4349
4281 4350 return ret
4282 4351
4283 4352 @command('rename|move|mv',
4284 4353 [('A', 'after', None, _('record a rename that has already occurred')),
4285 4354 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4286 4355 ] + walkopts + dryrunopts,
4287 4356 _('[OPTION]... SOURCE... DEST'))
4288 4357 def rename(ui, repo, *pats, **opts):
4289 4358 """rename files; equivalent of copy + remove
4290 4359
4291 4360 Mark dest as copies of sources; mark sources for deletion. If dest
4292 4361 is a directory, copies are put in that directory. If dest is a
4293 4362 file, there can only be one source.
4294 4363
4295 4364 By default, this command copies the contents of files as they
4296 4365 exist in the working directory. If invoked with -A/--after, the
4297 4366 operation is recorded, but no copying is performed.
4298 4367
4299 4368 This command takes effect at the next commit. To undo a rename
4300 4369 before that, see :hg:`revert`.
4301 4370
4302 4371 Returns 0 on success, 1 if errors are encountered.
4303 4372 """
4304 4373 wlock = repo.wlock(False)
4305 4374 try:
4306 4375 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4307 4376 finally:
4308 4377 wlock.release()
4309 4378
4310 4379 @command('resolve',
4311 4380 [('a', 'all', None, _('select all unresolved files')),
4312 4381 ('l', 'list', None, _('list state of files needing merge')),
4313 4382 ('m', 'mark', None, _('mark files as resolved')),
4314 4383 ('u', 'unmark', None, _('mark files as unresolved')),
4315 4384 ('n', 'no-status', None, _('hide status prefix'))]
4316 4385 + mergetoolopts + walkopts,
4317 4386 _('[OPTION]... [FILE]...'))
4318 4387 def resolve(ui, repo, *pats, **opts):
4319 4388 """redo merges or set/view the merge status of files
4320 4389
4321 4390 Merges with unresolved conflicts are often the result of
4322 4391 non-interactive merging using the ``internal:merge`` configuration
4323 4392 setting, or a command-line merge tool like ``diff3``. The resolve
4324 4393 command is used to manage the files involved in a merge, after
4325 4394 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4326 4395 working directory must have two parents).
4327 4396
4328 4397 The resolve command can be used in the following ways:
4329 4398
4330 4399 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4331 4400 files, discarding any previous merge attempts. Re-merging is not
4332 4401 performed for files already marked as resolved. Use ``--all/-a``
4333 4402 to select all unresolved files. ``--tool`` can be used to specify
4334 4403 the merge tool used for the given files. It overrides the HGMERGE
4335 4404 environment variable and your configuration files. Previous file
4336 4405 contents are saved with a ``.orig`` suffix.
4337 4406
4338 4407 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4339 4408 (e.g. after having manually fixed-up the files). The default is
4340 4409 to mark all unresolved files.
4341 4410
4342 4411 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4343 4412 default is to mark all resolved files.
4344 4413
4345 4414 - :hg:`resolve -l`: list files which had or still have conflicts.
4346 4415 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4347 4416
4348 4417 Note that Mercurial will not let you commit files with unresolved
4349 4418 merge conflicts. You must use :hg:`resolve -m ...` before you can
4350 4419 commit after a conflicting merge.
4351 4420
4352 4421 Returns 0 on success, 1 if any files fail a resolve attempt.
4353 4422 """
4354 4423
4355 4424 all, mark, unmark, show, nostatus = \
4356 4425 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4357 4426
4358 4427 if (show and (mark or unmark)) or (mark and unmark):
4359 4428 raise util.Abort(_("too many options specified"))
4360 4429 if pats and all:
4361 4430 raise util.Abort(_("can't specify --all and patterns"))
4362 4431 if not (all or pats or show or mark or unmark):
4363 4432 raise util.Abort(_('no files or directories specified; '
4364 4433 'use --all to remerge all files'))
4365 4434
4366 4435 ms = mergemod.mergestate(repo)
4367 4436 m = scmutil.match(repo[None], pats, opts)
4368 4437 ret = 0
4369 4438
4370 4439 for f in ms:
4371 4440 if m(f):
4372 4441 if show:
4373 4442 if nostatus:
4374 4443 ui.write("%s\n" % f)
4375 4444 else:
4376 4445 ui.write("%s %s\n" % (ms[f].upper(), f),
4377 4446 label='resolve.' +
4378 4447 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4379 4448 elif mark:
4380 4449 ms.mark(f, "r")
4381 4450 elif unmark:
4382 4451 ms.mark(f, "u")
4383 4452 else:
4384 4453 wctx = repo[None]
4385 4454 mctx = wctx.parents()[-1]
4386 4455
4387 4456 # backup pre-resolve (merge uses .orig for its own purposes)
4388 4457 a = repo.wjoin(f)
4389 4458 util.copyfile(a, a + ".resolve")
4390 4459
4391 4460 try:
4392 4461 # resolve file
4393 4462 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4394 4463 if ms.resolve(f, wctx, mctx):
4395 4464 ret = 1
4396 4465 finally:
4397 4466 ui.setconfig('ui', 'forcemerge', '')
4398 4467
4399 4468 # replace filemerge's .orig file with our resolve file
4400 4469 util.rename(a + ".resolve", a + ".orig")
4401 4470
4402 4471 ms.commit()
4403 4472 return ret
4404 4473
4405 4474 @command('revert',
4406 4475 [('a', 'all', None, _('revert all changes when no arguments given')),
4407 4476 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4408 4477 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4409 4478 ('C', 'no-backup', None, _('do not save backup copies of files')),
4410 4479 ] + walkopts + dryrunopts,
4411 4480 _('[OPTION]... [-r REV] [NAME]...'))
4412 4481 def revert(ui, repo, *pats, **opts):
4413 4482 """restore files to their checkout state
4414 4483
4415 4484 .. note::
4416 4485 To check out earlier revisions, you should use :hg:`update REV`.
4417 4486 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4418 4487
4419 4488 With no revision specified, revert the specified files or directories
4420 4489 to the contents they had in the parent of the working directory.
4421 4490 This restores the contents of files to an unmodified
4422 4491 state and unschedules adds, removes, copies, and renames. If the
4423 4492 working directory has two parents, you must explicitly specify a
4424 4493 revision.
4425 4494
4426 4495 Using the -r/--rev or -d/--date options, revert the given files or
4427 4496 directories to their states as of a specific revision. Because
4428 4497 revert does not change the working directory parents, this will
4429 4498 cause these files to appear modified. This can be helpful to "back
4430 4499 out" some or all of an earlier change. See :hg:`backout` for a
4431 4500 related method.
4432 4501
4433 4502 Modified files are saved with a .orig suffix before reverting.
4434 4503 To disable these backups, use --no-backup.
4435 4504
4436 4505 See :hg:`help dates` for a list of formats valid for -d/--date.
4437 4506
4438 4507 Returns 0 on success.
4439 4508 """
4440 4509
4441 4510 if opts.get("date"):
4442 4511 if opts.get("rev"):
4443 4512 raise util.Abort(_("you can't specify a revision and a date"))
4444 4513 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4445 4514
4446 4515 parent, p2 = repo.dirstate.parents()
4447 4516 if not opts.get('rev') and p2 != nullid:
4448 4517 # revert after merge is a trap for new users (issue2915)
4449 4518 raise util.Abort(_('uncommitted merge with no revision specified'),
4450 4519 hint=_('use "hg update" or see "hg help revert"'))
4451 4520
4452 4521 ctx = scmutil.revsingle(repo, opts.get('rev'))
4453 4522 node = ctx.node()
4454 4523
4455 4524 if not pats and not opts.get('all'):
4456 4525 msg = _("no files or directories specified")
4457 4526 if p2 != nullid:
4458 4527 hint = _("uncommitted merge, use --all to discard all changes,"
4459 4528 " or 'hg update -C .' to abort the merge")
4460 4529 raise util.Abort(msg, hint=hint)
4461 4530 dirty = util.any(repo.status())
4462 4531 if node != parent:
4463 4532 if dirty:
4464 4533 hint = _("uncommitted changes, use --all to discard all"
4465 4534 " changes, or 'hg update %s' to update") % ctx.rev()
4466 4535 else:
4467 4536 hint = _("use --all to revert all files,"
4468 4537 " or 'hg update %s' to update") % ctx.rev()
4469 4538 elif dirty:
4470 4539 hint = _("uncommitted changes, use --all to discard all changes")
4471 4540 else:
4472 4541 hint = _("use --all to revert all files")
4473 4542 raise util.Abort(msg, hint=hint)
4474 4543
4475 4544 mf = ctx.manifest()
4476 4545 if node == parent:
4477 4546 pmf = mf
4478 4547 else:
4479 4548 pmf = None
4480 4549
4481 4550 # need all matching names in dirstate and manifest of target rev,
4482 4551 # so have to walk both. do not print errors if files exist in one
4483 4552 # but not other.
4484 4553
4485 4554 names = {}
4486 4555
4487 4556 wlock = repo.wlock()
4488 4557 try:
4489 4558 # walk dirstate.
4490 4559
4491 4560 m = scmutil.match(repo[None], pats, opts)
4492 4561 m.bad = lambda x, y: False
4493 4562 for abs in repo.walk(m):
4494 4563 names[abs] = m.rel(abs), m.exact(abs)
4495 4564
4496 4565 # walk target manifest.
4497 4566
4498 4567 def badfn(path, msg):
4499 4568 if path in names:
4500 4569 return
4501 4570 path_ = path + '/'
4502 4571 for f in names:
4503 4572 if f.startswith(path_):
4504 4573 return
4505 4574 ui.warn("%s: %s\n" % (m.rel(path), msg))
4506 4575
4507 4576 m = scmutil.match(repo[node], pats, opts)
4508 4577 m.bad = badfn
4509 4578 for abs in repo[node].walk(m):
4510 4579 if abs not in names:
4511 4580 names[abs] = m.rel(abs), m.exact(abs)
4512 4581
4513 4582 m = scmutil.matchfiles(repo, names)
4514 4583 changes = repo.status(match=m)[:4]
4515 4584 modified, added, removed, deleted = map(set, changes)
4516 4585
4517 4586 # if f is a rename, also revert the source
4518 4587 cwd = repo.getcwd()
4519 4588 for f in added:
4520 4589 src = repo.dirstate.copied(f)
4521 4590 if src and src not in names and repo.dirstate[src] == 'r':
4522 4591 removed.add(src)
4523 4592 names[src] = (repo.pathto(src, cwd), True)
4524 4593
4525 4594 def removeforget(abs):
4526 4595 if repo.dirstate[abs] == 'a':
4527 4596 return _('forgetting %s\n')
4528 4597 return _('removing %s\n')
4529 4598
4530 4599 revert = ([], _('reverting %s\n'))
4531 4600 add = ([], _('adding %s\n'))
4532 4601 remove = ([], removeforget)
4533 4602 undelete = ([], _('undeleting %s\n'))
4534 4603
4535 4604 disptable = (
4536 4605 # dispatch table:
4537 4606 # file state
4538 4607 # action if in target manifest
4539 4608 # action if not in target manifest
4540 4609 # make backup if in target manifest
4541 4610 # make backup if not in target manifest
4542 4611 (modified, revert, remove, True, True),
4543 4612 (added, revert, remove, True, False),
4544 4613 (removed, undelete, None, False, False),
4545 4614 (deleted, revert, remove, False, False),
4546 4615 )
4547 4616
4548 4617 for abs, (rel, exact) in sorted(names.items()):
4549 4618 mfentry = mf.get(abs)
4550 4619 target = repo.wjoin(abs)
4551 4620 def handle(xlist, dobackup):
4552 4621 xlist[0].append(abs)
4553 4622 if (dobackup and not opts.get('no_backup') and
4554 4623 os.path.lexists(target)):
4555 4624 bakname = "%s.orig" % rel
4556 4625 ui.note(_('saving current version of %s as %s\n') %
4557 4626 (rel, bakname))
4558 4627 if not opts.get('dry_run'):
4559 4628 util.rename(target, bakname)
4560 4629 if ui.verbose or not exact:
4561 4630 msg = xlist[1]
4562 4631 if not isinstance(msg, basestring):
4563 4632 msg = msg(abs)
4564 4633 ui.status(msg % rel)
4565 4634 for table, hitlist, misslist, backuphit, backupmiss in disptable:
4566 4635 if abs not in table:
4567 4636 continue
4568 4637 # file has changed in dirstate
4569 4638 if mfentry:
4570 4639 handle(hitlist, backuphit)
4571 4640 elif misslist is not None:
4572 4641 handle(misslist, backupmiss)
4573 4642 break
4574 4643 else:
4575 4644 if abs not in repo.dirstate:
4576 4645 if mfentry:
4577 4646 handle(add, True)
4578 4647 elif exact:
4579 4648 ui.warn(_('file not managed: %s\n') % rel)
4580 4649 continue
4581 4650 # file has not changed in dirstate
4582 4651 if node == parent:
4583 4652 if exact:
4584 4653 ui.warn(_('no changes needed to %s\n') % rel)
4585 4654 continue
4586 4655 if pmf is None:
4587 4656 # only need parent manifest in this unlikely case,
4588 4657 # so do not read by default
4589 4658 pmf = repo[parent].manifest()
4590 4659 if abs in pmf:
4591 4660 if mfentry:
4592 4661 # if version of file is same in parent and target
4593 4662 # manifests, do nothing
4594 4663 if (pmf[abs] != mfentry or
4595 4664 pmf.flags(abs) != mf.flags(abs)):
4596 4665 handle(revert, False)
4597 4666 else:
4598 4667 handle(remove, False)
4599 4668
4600 4669 if not opts.get('dry_run'):
4601 4670 def checkout(f):
4602 4671 fc = ctx[f]
4603 4672 repo.wwrite(f, fc.data(), fc.flags())
4604 4673
4605 4674 audit_path = scmutil.pathauditor(repo.root)
4606 4675 for f in remove[0]:
4607 4676 if repo.dirstate[f] == 'a':
4608 4677 repo.dirstate.drop(f)
4609 4678 continue
4610 4679 audit_path(f)
4611 4680 try:
4612 4681 util.unlinkpath(repo.wjoin(f))
4613 4682 except OSError:
4614 4683 pass
4615 4684 repo.dirstate.remove(f)
4616 4685
4617 4686 normal = None
4618 4687 if node == parent:
4619 4688 # We're reverting to our parent. If possible, we'd like status
4620 4689 # to report the file as clean. We have to use normallookup for
4621 4690 # merges to avoid losing information about merged/dirty files.
4622 4691 if p2 != nullid:
4623 4692 normal = repo.dirstate.normallookup
4624 4693 else:
4625 4694 normal = repo.dirstate.normal
4626 4695 for f in revert[0]:
4627 4696 checkout(f)
4628 4697 if normal:
4629 4698 normal(f)
4630 4699
4631 4700 for f in add[0]:
4632 4701 checkout(f)
4633 4702 repo.dirstate.add(f)
4634 4703
4635 4704 normal = repo.dirstate.normallookup
4636 4705 if node == parent and p2 == nullid:
4637 4706 normal = repo.dirstate.normal
4638 4707 for f in undelete[0]:
4639 4708 checkout(f)
4640 4709 normal(f)
4641 4710
4642 4711 finally:
4643 4712 wlock.release()
4644 4713
4645 4714 @command('rollback', dryrunopts +
4646 4715 [('f', 'force', False, _('ignore safety measures'))])
4647 4716 def rollback(ui, repo, **opts):
4648 4717 """roll back the last transaction (dangerous)
4649 4718
4650 4719 This command should be used with care. There is only one level of
4651 4720 rollback, and there is no way to undo a rollback. It will also
4652 4721 restore the dirstate at the time of the last transaction, losing
4653 4722 any dirstate changes since that time. This command does not alter
4654 4723 the working directory.
4655 4724
4656 4725 Transactions are used to encapsulate the effects of all commands
4657 4726 that create new changesets or propagate existing changesets into a
4658 4727 repository. For example, the following commands are transactional,
4659 4728 and their effects can be rolled back:
4660 4729
4661 4730 - commit
4662 4731 - import
4663 4732 - pull
4664 4733 - push (with this repository as the destination)
4665 4734 - unbundle
4666 4735
4667 4736 It's possible to lose data with rollback: commit, update back to
4668 4737 an older changeset, and then rollback. The update removes the
4669 4738 changes you committed from the working directory, and rollback
4670 4739 removes them from history. To avoid data loss, you must pass
4671 4740 --force in this case.
4672 4741
4673 4742 This command is not intended for use on public repositories. Once
4674 4743 changes are visible for pull by other users, rolling a transaction
4675 4744 back locally is ineffective (someone else may already have pulled
4676 4745 the changes). Furthermore, a race is possible with readers of the
4677 4746 repository; for example an in-progress pull from the repository
4678 4747 may fail if a rollback is performed.
4679 4748
4680 4749 Returns 0 on success, 1 if no rollback data is available.
4681 4750 """
4682 4751 return repo.rollback(dryrun=opts.get('dry_run'),
4683 4752 force=opts.get('force'))
4684 4753
4685 4754 @command('root', [])
4686 4755 def root(ui, repo):
4687 4756 """print the root (top) of the current working directory
4688 4757
4689 4758 Print the root directory of the current repository.
4690 4759
4691 4760 Returns 0 on success.
4692 4761 """
4693 4762 ui.write(repo.root + "\n")
4694 4763
4695 4764 @command('^serve',
4696 4765 [('A', 'accesslog', '', _('name of access log file to write to'),
4697 4766 _('FILE')),
4698 4767 ('d', 'daemon', None, _('run server in background')),
4699 4768 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4700 4769 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4701 4770 # use string type, then we can check if something was passed
4702 4771 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4703 4772 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4704 4773 _('ADDR')),
4705 4774 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4706 4775 _('PREFIX')),
4707 4776 ('n', 'name', '',
4708 4777 _('name to show in web pages (default: working directory)'), _('NAME')),
4709 4778 ('', 'web-conf', '',
4710 4779 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
4711 4780 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4712 4781 _('FILE')),
4713 4782 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4714 4783 ('', 'stdio', None, _('for remote clients')),
4715 4784 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4716 4785 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4717 4786 ('', 'style', '', _('template style to use'), _('STYLE')),
4718 4787 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4719 4788 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4720 4789 _('[OPTION]...'))
4721 4790 def serve(ui, repo, **opts):
4722 4791 """start stand-alone webserver
4723 4792
4724 4793 Start a local HTTP repository browser and pull server. You can use
4725 4794 this for ad-hoc sharing and browsing of repositories. It is
4726 4795 recommended to use a real web server to serve a repository for
4727 4796 longer periods of time.
4728 4797
4729 4798 Please note that the server does not implement access control.
4730 4799 This means that, by default, anybody can read from the server and
4731 4800 nobody can write to it by default. Set the ``web.allow_push``
4732 4801 option to ``*`` to allow everybody to push to the server. You
4733 4802 should use a real web server if you need to authenticate users.
4734 4803
4735 4804 By default, the server logs accesses to stdout and errors to
4736 4805 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4737 4806 files.
4738 4807
4739 4808 To have the server choose a free port number to listen on, specify
4740 4809 a port number of 0; in this case, the server will print the port
4741 4810 number it uses.
4742 4811
4743 4812 Returns 0 on success.
4744 4813 """
4745 4814
4746 4815 if opts["stdio"] and opts["cmdserver"]:
4747 4816 raise util.Abort(_("cannot use --stdio with --cmdserver"))
4748 4817
4749 4818 def checkrepo():
4750 4819 if repo is None:
4751 4820 raise error.RepoError(_("There is no Mercurial repository here"
4752 4821 " (.hg not found)"))
4753 4822
4754 4823 if opts["stdio"]:
4755 4824 checkrepo()
4756 4825 s = sshserver.sshserver(ui, repo)
4757 4826 s.serve_forever()
4758 4827
4759 4828 if opts["cmdserver"]:
4760 4829 checkrepo()
4761 4830 s = commandserver.server(ui, repo, opts["cmdserver"])
4762 4831 return s.serve()
4763 4832
4764 4833 # this way we can check if something was given in the command-line
4765 4834 if opts.get('port'):
4766 4835 opts['port'] = util.getport(opts.get('port'))
4767 4836
4768 4837 baseui = repo and repo.baseui or ui
4769 4838 optlist = ("name templates style address port prefix ipv6"
4770 4839 " accesslog errorlog certificate encoding")
4771 4840 for o in optlist.split():
4772 4841 val = opts.get(o, '')
4773 4842 if val in (None, ''): # should check against default options instead
4774 4843 continue
4775 4844 baseui.setconfig("web", o, val)
4776 4845 if repo and repo.ui != baseui:
4777 4846 repo.ui.setconfig("web", o, val)
4778 4847
4779 4848 o = opts.get('web_conf') or opts.get('webdir_conf')
4780 4849 if not o:
4781 4850 if not repo:
4782 4851 raise error.RepoError(_("There is no Mercurial repository"
4783 4852 " here (.hg not found)"))
4784 4853 o = repo.root
4785 4854
4786 4855 app = hgweb.hgweb(o, baseui=ui)
4787 4856
4788 4857 class service(object):
4789 4858 def init(self):
4790 4859 util.setsignalhandler()
4791 4860 self.httpd = hgweb.server.create_server(ui, app)
4792 4861
4793 4862 if opts['port'] and not ui.verbose:
4794 4863 return
4795 4864
4796 4865 if self.httpd.prefix:
4797 4866 prefix = self.httpd.prefix.strip('/') + '/'
4798 4867 else:
4799 4868 prefix = ''
4800 4869
4801 4870 port = ':%d' % self.httpd.port
4802 4871 if port == ':80':
4803 4872 port = ''
4804 4873
4805 4874 bindaddr = self.httpd.addr
4806 4875 if bindaddr == '0.0.0.0':
4807 4876 bindaddr = '*'
4808 4877 elif ':' in bindaddr: # IPv6
4809 4878 bindaddr = '[%s]' % bindaddr
4810 4879
4811 4880 fqaddr = self.httpd.fqaddr
4812 4881 if ':' in fqaddr:
4813 4882 fqaddr = '[%s]' % fqaddr
4814 4883 if opts['port']:
4815 4884 write = ui.status
4816 4885 else:
4817 4886 write = ui.write
4818 4887 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
4819 4888 (fqaddr, port, prefix, bindaddr, self.httpd.port))
4820 4889
4821 4890 def run(self):
4822 4891 self.httpd.serve_forever()
4823 4892
4824 4893 service = service()
4825 4894
4826 4895 cmdutil.service(opts, initfn=service.init, runfn=service.run)
4827 4896
4828 4897 @command('showconfig|debugconfig',
4829 4898 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4830 4899 _('[-u] [NAME]...'))
4831 4900 def showconfig(ui, repo, *values, **opts):
4832 4901 """show combined config settings from all hgrc files
4833 4902
4834 4903 With no arguments, print names and values of all config items.
4835 4904
4836 4905 With one argument of the form section.name, print just the value
4837 4906 of that config item.
4838 4907
4839 4908 With multiple arguments, print names and values of all config
4840 4909 items with matching section names.
4841 4910
4842 4911 With --debug, the source (filename and line number) is printed
4843 4912 for each config item.
4844 4913
4845 4914 Returns 0 on success.
4846 4915 """
4847 4916
4848 4917 for f in scmutil.rcpath():
4849 4918 ui.debug('read config from: %s\n' % f)
4850 4919 untrusted = bool(opts.get('untrusted'))
4851 4920 if values:
4852 4921 sections = [v for v in values if '.' not in v]
4853 4922 items = [v for v in values if '.' in v]
4854 4923 if len(items) > 1 or items and sections:
4855 4924 raise util.Abort(_('only one config item permitted'))
4856 4925 for section, name, value in ui.walkconfig(untrusted=untrusted):
4857 4926 value = str(value).replace('\n', '\\n')
4858 4927 sectname = section + '.' + name
4859 4928 if values:
4860 4929 for v in values:
4861 4930 if v == section:
4862 4931 ui.debug('%s: ' %
4863 4932 ui.configsource(section, name, untrusted))
4864 4933 ui.write('%s=%s\n' % (sectname, value))
4865 4934 elif v == sectname:
4866 4935 ui.debug('%s: ' %
4867 4936 ui.configsource(section, name, untrusted))
4868 4937 ui.write(value, '\n')
4869 4938 else:
4870 4939 ui.debug('%s: ' %
4871 4940 ui.configsource(section, name, untrusted))
4872 4941 ui.write('%s=%s\n' % (sectname, value))
4873 4942
4874 4943 @command('^status|st',
4875 4944 [('A', 'all', None, _('show status of all files')),
4876 4945 ('m', 'modified', None, _('show only modified files')),
4877 4946 ('a', 'added', None, _('show only added files')),
4878 4947 ('r', 'removed', None, _('show only removed files')),
4879 4948 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4880 4949 ('c', 'clean', None, _('show only files without changes')),
4881 4950 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4882 4951 ('i', 'ignored', None, _('show only ignored files')),
4883 4952 ('n', 'no-status', None, _('hide status prefix')),
4884 4953 ('C', 'copies', None, _('show source of copied files')),
4885 4954 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4886 4955 ('', 'rev', [], _('show difference from revision'), _('REV')),
4887 4956 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4888 4957 ] + walkopts + subrepoopts,
4889 4958 _('[OPTION]... [FILE]...'))
4890 4959 def status(ui, repo, *pats, **opts):
4891 4960 """show changed files in the working directory
4892 4961
4893 4962 Show status of files in the repository. If names are given, only
4894 4963 files that match are shown. Files that are clean or ignored or
4895 4964 the source of a copy/move operation, are not listed unless
4896 4965 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4897 4966 Unless options described with "show only ..." are given, the
4898 4967 options -mardu are used.
4899 4968
4900 4969 Option -q/--quiet hides untracked (unknown and ignored) files
4901 4970 unless explicitly requested with -u/--unknown or -i/--ignored.
4902 4971
4903 4972 .. note::
4904 4973 status may appear to disagree with diff if permissions have
4905 4974 changed or a merge has occurred. The standard diff format does
4906 4975 not report permission changes and diff only reports changes
4907 4976 relative to one merge parent.
4908 4977
4909 4978 If one revision is given, it is used as the base revision.
4910 4979 If two revisions are given, the differences between them are
4911 4980 shown. The --change option can also be used as a shortcut to list
4912 4981 the changed files of a revision from its first parent.
4913 4982
4914 4983 The codes used to show the status of files are::
4915 4984
4916 4985 M = modified
4917 4986 A = added
4918 4987 R = removed
4919 4988 C = clean
4920 4989 ! = missing (deleted by non-hg command, but still tracked)
4921 4990 ? = not tracked
4922 4991 I = ignored
4923 4992 = origin of the previous file listed as A (added)
4924 4993
4925 4994 .. container:: verbose
4926 4995
4927 4996 Examples:
4928 4997
4929 4998 - show changes in the working directory relative to a changeset:
4930 4999
4931 5000 hg status --rev 9353
4932 5001
4933 5002 - show all changes including copies in an existing changeset::
4934 5003
4935 5004 hg status --copies --change 9353
4936 5005
4937 5006 - get a NUL separated list of added files, suitable for xargs::
4938 5007
4939 5008 hg status -an0
4940 5009
4941 5010 Returns 0 on success.
4942 5011 """
4943 5012
4944 5013 revs = opts.get('rev')
4945 5014 change = opts.get('change')
4946 5015
4947 5016 if revs and change:
4948 5017 msg = _('cannot specify --rev and --change at the same time')
4949 5018 raise util.Abort(msg)
4950 5019 elif change:
4951 5020 node2 = repo.lookup(change)
4952 5021 node1 = repo[node2].p1().node()
4953 5022 else:
4954 5023 node1, node2 = scmutil.revpair(repo, revs)
4955 5024
4956 5025 cwd = (pats and repo.getcwd()) or ''
4957 5026 end = opts.get('print0') and '\0' or '\n'
4958 5027 copy = {}
4959 5028 states = 'modified added removed deleted unknown ignored clean'.split()
4960 5029 show = [k for k in states if opts.get(k)]
4961 5030 if opts.get('all'):
4962 5031 show += ui.quiet and (states[:4] + ['clean']) or states
4963 5032 if not show:
4964 5033 show = ui.quiet and states[:4] or states[:5]
4965 5034
4966 5035 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
4967 5036 'ignored' in show, 'clean' in show, 'unknown' in show,
4968 5037 opts.get('subrepos'))
4969 5038 changestates = zip(states, 'MAR!?IC', stat)
4970 5039
4971 5040 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
4972 5041 ctxn = repo[nullid]
4973 5042 ctx1 = repo[node1]
4974 5043 ctx2 = repo[node2]
4975 5044 added = stat[1]
4976 5045 if node2 is None:
4977 5046 added = stat[0] + stat[1] # merged?
4978 5047
4979 5048 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
4980 5049 if k in added:
4981 5050 copy[k] = v
4982 5051 elif v in added:
4983 5052 copy[v] = k
4984 5053
4985 5054 for state, char, files in changestates:
4986 5055 if state in show:
4987 5056 format = "%s %%s%s" % (char, end)
4988 5057 if opts.get('no_status'):
4989 5058 format = "%%s%s" % end
4990 5059
4991 5060 for f in files:
4992 5061 ui.write(format % repo.pathto(f, cwd),
4993 5062 label='status.' + state)
4994 5063 if f in copy:
4995 5064 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
4996 5065 label='status.copied')
4997 5066
4998 5067 @command('^summary|sum',
4999 5068 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5000 5069 def summary(ui, repo, **opts):
5001 5070 """summarize working directory state
5002 5071
5003 5072 This generates a brief summary of the working directory state,
5004 5073 including parents, branch, commit status, and available updates.
5005 5074
5006 5075 With the --remote option, this will check the default paths for
5007 5076 incoming and outgoing changes. This can be time-consuming.
5008 5077
5009 5078 Returns 0 on success.
5010 5079 """
5011 5080
5012 5081 ctx = repo[None]
5013 5082 parents = ctx.parents()
5014 5083 pnode = parents[0].node()
5015 5084 marks = []
5016 5085
5017 5086 for p in parents:
5018 5087 # label with log.changeset (instead of log.parent) since this
5019 5088 # shows a working directory parent *changeset*:
5020 5089 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5021 5090 label='log.changeset')
5022 5091 ui.write(' '.join(p.tags()), label='log.tag')
5023 5092 if p.bookmarks():
5024 5093 marks.extend(p.bookmarks())
5025 5094 if p.rev() == -1:
5026 5095 if not len(repo):
5027 5096 ui.write(_(' (empty repository)'))
5028 5097 else:
5029 5098 ui.write(_(' (no revision checked out)'))
5030 5099 ui.write('\n')
5031 5100 if p.description():
5032 5101 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5033 5102 label='log.summary')
5034 5103
5035 5104 branch = ctx.branch()
5036 5105 bheads = repo.branchheads(branch)
5037 5106 m = _('branch: %s\n') % branch
5038 5107 if branch != 'default':
5039 5108 ui.write(m, label='log.branch')
5040 5109 else:
5041 5110 ui.status(m, label='log.branch')
5042 5111
5043 5112 if marks:
5044 5113 current = repo._bookmarkcurrent
5045 5114 ui.write(_('bookmarks:'), label='log.bookmark')
5046 5115 if current is not None:
5047 5116 try:
5048 5117 marks.remove(current)
5049 5118 ui.write(' *' + current, label='bookmarks.current')
5050 5119 except ValueError:
5051 5120 # current bookmark not in parent ctx marks
5052 5121 pass
5053 5122 for m in marks:
5054 5123 ui.write(' ' + m, label='log.bookmark')
5055 5124 ui.write('\n', label='log.bookmark')
5056 5125
5057 5126 st = list(repo.status(unknown=True))[:6]
5058 5127
5059 5128 c = repo.dirstate.copies()
5060 5129 copied, renamed = [], []
5061 5130 for d, s in c.iteritems():
5062 5131 if s in st[2]:
5063 5132 st[2].remove(s)
5064 5133 renamed.append(d)
5065 5134 else:
5066 5135 copied.append(d)
5067 5136 if d in st[1]:
5068 5137 st[1].remove(d)
5069 5138 st.insert(3, renamed)
5070 5139 st.insert(4, copied)
5071 5140
5072 5141 ms = mergemod.mergestate(repo)
5073 5142 st.append([f for f in ms if ms[f] == 'u'])
5074 5143
5075 5144 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5076 5145 st.append(subs)
5077 5146
5078 5147 labels = [ui.label(_('%d modified'), 'status.modified'),
5079 5148 ui.label(_('%d added'), 'status.added'),
5080 5149 ui.label(_('%d removed'), 'status.removed'),
5081 5150 ui.label(_('%d renamed'), 'status.copied'),
5082 5151 ui.label(_('%d copied'), 'status.copied'),
5083 5152 ui.label(_('%d deleted'), 'status.deleted'),
5084 5153 ui.label(_('%d unknown'), 'status.unknown'),
5085 5154 ui.label(_('%d ignored'), 'status.ignored'),
5086 5155 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5087 5156 ui.label(_('%d subrepos'), 'status.modified')]
5088 5157 t = []
5089 5158 for s, l in zip(st, labels):
5090 5159 if s:
5091 5160 t.append(l % len(s))
5092 5161
5093 5162 t = ', '.join(t)
5094 5163 cleanworkdir = False
5095 5164
5096 5165 if len(parents) > 1:
5097 5166 t += _(' (merge)')
5098 5167 elif branch != parents[0].branch():
5099 5168 t += _(' (new branch)')
5100 5169 elif (parents[0].extra().get('close') and
5101 5170 pnode in repo.branchheads(branch, closed=True)):
5102 5171 t += _(' (head closed)')
5103 5172 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5104 5173 t += _(' (clean)')
5105 5174 cleanworkdir = True
5106 5175 elif pnode not in bheads:
5107 5176 t += _(' (new branch head)')
5108 5177
5109 5178 if cleanworkdir:
5110 5179 ui.status(_('commit: %s\n') % t.strip())
5111 5180 else:
5112 5181 ui.write(_('commit: %s\n') % t.strip())
5113 5182
5114 5183 # all ancestors of branch heads - all ancestors of parent = new csets
5115 5184 new = [0] * len(repo)
5116 5185 cl = repo.changelog
5117 5186 for a in [cl.rev(n) for n in bheads]:
5118 5187 new[a] = 1
5119 5188 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
5120 5189 new[a] = 1
5121 5190 for a in [p.rev() for p in parents]:
5122 5191 if a >= 0:
5123 5192 new[a] = 0
5124 5193 for a in cl.ancestors(*[p.rev() for p in parents]):
5125 5194 new[a] = 0
5126 5195 new = sum(new)
5127 5196
5128 5197 if new == 0:
5129 5198 ui.status(_('update: (current)\n'))
5130 5199 elif pnode not in bheads:
5131 5200 ui.write(_('update: %d new changesets (update)\n') % new)
5132 5201 else:
5133 5202 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5134 5203 (new, len(bheads)))
5135 5204
5136 5205 if opts.get('remote'):
5137 5206 t = []
5138 5207 source, branches = hg.parseurl(ui.expandpath('default'))
5139 5208 other = hg.peer(repo, {}, source)
5140 5209 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
5141 5210 ui.debug('comparing with %s\n' % util.hidepassword(source))
5142 5211 repo.ui.pushbuffer()
5143 5212 commoninc = discovery.findcommonincoming(repo, other)
5144 5213 _common, incoming, _rheads = commoninc
5145 5214 repo.ui.popbuffer()
5146 5215 if incoming:
5147 5216 t.append(_('1 or more incoming'))
5148 5217
5149 5218 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5150 5219 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5151 5220 if source != dest:
5152 5221 other = hg.peer(repo, {}, dest)
5153 5222 commoninc = None
5154 5223 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5155 5224 repo.ui.pushbuffer()
5156 5225 common, outheads = discovery.findcommonoutgoing(repo, other,
5157 5226 commoninc=commoninc)
5158 5227 repo.ui.popbuffer()
5159 5228 o = repo.changelog.findmissing(common=common, heads=outheads)
5160 5229 if o:
5161 5230 t.append(_('%d outgoing') % len(o))
5162 5231 if 'bookmarks' in other.listkeys('namespaces'):
5163 5232 lmarks = repo.listkeys('bookmarks')
5164 5233 rmarks = other.listkeys('bookmarks')
5165 5234 diff = set(rmarks) - set(lmarks)
5166 5235 if len(diff) > 0:
5167 5236 t.append(_('%d incoming bookmarks') % len(diff))
5168 5237 diff = set(lmarks) - set(rmarks)
5169 5238 if len(diff) > 0:
5170 5239 t.append(_('%d outgoing bookmarks') % len(diff))
5171 5240
5172 5241 if t:
5173 5242 ui.write(_('remote: %s\n') % (', '.join(t)))
5174 5243 else:
5175 5244 ui.status(_('remote: (synced)\n'))
5176 5245
5177 5246 @command('tag',
5178 5247 [('f', 'force', None, _('force tag')),
5179 5248 ('l', 'local', None, _('make the tag local')),
5180 5249 ('r', 'rev', '', _('revision to tag'), _('REV')),
5181 5250 ('', 'remove', None, _('remove a tag')),
5182 5251 # -l/--local is already there, commitopts cannot be used
5183 5252 ('e', 'edit', None, _('edit commit message')),
5184 5253 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5185 5254 ] + commitopts2,
5186 5255 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5187 5256 def tag(ui, repo, name1, *names, **opts):
5188 5257 """add one or more tags for the current or given revision
5189 5258
5190 5259 Name a particular revision using <name>.
5191 5260
5192 5261 Tags are used to name particular revisions of the repository and are
5193 5262 very useful to compare different revisions, to go back to significant
5194 5263 earlier versions or to mark branch points as releases, etc. Changing
5195 5264 an existing tag is normally disallowed; use -f/--force to override.
5196 5265
5197 5266 If no revision is given, the parent of the working directory is
5198 5267 used, or tip if no revision is checked out.
5199 5268
5200 5269 To facilitate version control, distribution, and merging of tags,
5201 5270 they are stored as a file named ".hgtags" which is managed similarly
5202 5271 to other project files and can be hand-edited if necessary. This
5203 5272 also means that tagging creates a new commit. The file
5204 5273 ".hg/localtags" is used for local tags (not shared among
5205 5274 repositories).
5206 5275
5207 5276 Tag commits are usually made at the head of a branch. If the parent
5208 5277 of the working directory is not a branch head, :hg:`tag` aborts; use
5209 5278 -f/--force to force the tag commit to be based on a non-head
5210 5279 changeset.
5211 5280
5212 5281 See :hg:`help dates` for a list of formats valid for -d/--date.
5213 5282
5214 5283 Since tag names have priority over branch names during revision
5215 5284 lookup, using an existing branch name as a tag name is discouraged.
5216 5285
5217 5286 Returns 0 on success.
5218 5287 """
5219 5288
5220 5289 rev_ = "."
5221 5290 names = [t.strip() for t in (name1,) + names]
5222 5291 if len(names) != len(set(names)):
5223 5292 raise util.Abort(_('tag names must be unique'))
5224 5293 for n in names:
5225 5294 if n in ['tip', '.', 'null']:
5226 5295 raise util.Abort(_("the name '%s' is reserved") % n)
5227 5296 if not n:
5228 5297 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
5229 5298 if opts.get('rev') and opts.get('remove'):
5230 5299 raise util.Abort(_("--rev and --remove are incompatible"))
5231 5300 if opts.get('rev'):
5232 5301 rev_ = opts['rev']
5233 5302 message = opts.get('message')
5234 5303 if opts.get('remove'):
5235 5304 expectedtype = opts.get('local') and 'local' or 'global'
5236 5305 for n in names:
5237 5306 if not repo.tagtype(n):
5238 5307 raise util.Abort(_("tag '%s' does not exist") % n)
5239 5308 if repo.tagtype(n) != expectedtype:
5240 5309 if expectedtype == 'global':
5241 5310 raise util.Abort(_("tag '%s' is not a global tag") % n)
5242 5311 else:
5243 5312 raise util.Abort(_("tag '%s' is not a local tag") % n)
5244 5313 rev_ = nullid
5245 5314 if not message:
5246 5315 # we don't translate commit messages
5247 5316 message = 'Removed tag %s' % ', '.join(names)
5248 5317 elif not opts.get('force'):
5249 5318 for n in names:
5250 5319 if n in repo.tags():
5251 5320 raise util.Abort(_("tag '%s' already exists "
5252 5321 "(use -f to force)") % n)
5253 5322 if not opts.get('local'):
5254 5323 p1, p2 = repo.dirstate.parents()
5255 5324 if p2 != nullid:
5256 5325 raise util.Abort(_('uncommitted merge'))
5257 5326 bheads = repo.branchheads()
5258 5327 if not opts.get('force') and bheads and p1 not in bheads:
5259 5328 raise util.Abort(_('not at a branch head (use -f to force)'))
5260 5329 r = scmutil.revsingle(repo, rev_).node()
5261 5330
5262 5331 if not message:
5263 5332 # we don't translate commit messages
5264 5333 message = ('Added tag %s for changeset %s' %
5265 5334 (', '.join(names), short(r)))
5266 5335
5267 5336 date = opts.get('date')
5268 5337 if date:
5269 5338 date = util.parsedate(date)
5270 5339
5271 5340 if opts.get('edit'):
5272 5341 message = ui.edit(message, ui.username())
5273 5342
5274 5343 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5275 5344
5276 5345 @command('tags', [], '')
5277 5346 def tags(ui, repo):
5278 5347 """list repository tags
5279 5348
5280 5349 This lists both regular and local tags. When the -v/--verbose
5281 5350 switch is used, a third column "local" is printed for local tags.
5282 5351
5283 5352 Returns 0 on success.
5284 5353 """
5285 5354
5286 5355 hexfunc = ui.debugflag and hex or short
5287 5356 tagtype = ""
5288 5357
5289 5358 for t, n in reversed(repo.tagslist()):
5290 5359 if ui.quiet:
5291 5360 ui.write("%s\n" % t, label='tags.normal')
5292 5361 continue
5293 5362
5294 5363 hn = hexfunc(n)
5295 5364 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5296 5365 rev = ui.label(r, 'log.changeset')
5297 5366 spaces = " " * (30 - encoding.colwidth(t))
5298 5367
5299 5368 tag = ui.label(t, 'tags.normal')
5300 5369 if ui.verbose:
5301 5370 if repo.tagtype(t) == 'local':
5302 5371 tagtype = " local"
5303 5372 tag = ui.label(t, 'tags.local')
5304 5373 else:
5305 5374 tagtype = ""
5306 5375 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5307 5376
5308 5377 @command('tip',
5309 5378 [('p', 'patch', None, _('show patch')),
5310 5379 ('g', 'git', None, _('use git extended diff format')),
5311 5380 ] + templateopts,
5312 5381 _('[-p] [-g]'))
5313 5382 def tip(ui, repo, **opts):
5314 5383 """show the tip revision
5315 5384
5316 5385 The tip revision (usually just called the tip) is the changeset
5317 5386 most recently added to the repository (and therefore the most
5318 5387 recently changed head).
5319 5388
5320 5389 If you have just made a commit, that commit will be the tip. If
5321 5390 you have just pulled changes from another repository, the tip of
5322 5391 that repository becomes the current tip. The "tip" tag is special
5323 5392 and cannot be renamed or assigned to a different changeset.
5324 5393
5325 5394 Returns 0 on success.
5326 5395 """
5327 5396 displayer = cmdutil.show_changeset(ui, repo, opts)
5328 5397 displayer.show(repo[len(repo) - 1])
5329 5398 displayer.close()
5330 5399
5331 5400 @command('unbundle',
5332 5401 [('u', 'update', None,
5333 5402 _('update to new branch head if changesets were unbundled'))],
5334 5403 _('[-u] FILE...'))
5335 5404 def unbundle(ui, repo, fname1, *fnames, **opts):
5336 5405 """apply one or more changegroup files
5337 5406
5338 5407 Apply one or more compressed changegroup files generated by the
5339 5408 bundle command.
5340 5409
5341 5410 Returns 0 on success, 1 if an update has unresolved files.
5342 5411 """
5343 5412 fnames = (fname1,) + fnames
5344 5413
5345 5414 lock = repo.lock()
5346 5415 wc = repo['.']
5347 5416 try:
5348 5417 for fname in fnames:
5349 5418 f = url.open(ui, fname)
5350 5419 gen = changegroup.readbundle(f, fname)
5351 5420 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
5352 5421 lock=lock)
5353 5422 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5354 5423 finally:
5355 5424 lock.release()
5356 5425 return postincoming(ui, repo, modheads, opts.get('update'), None)
5357 5426
5358 5427 @command('^update|up|checkout|co',
5359 5428 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5360 5429 ('c', 'check', None,
5361 5430 _('update across branches if no uncommitted changes')),
5362 5431 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5363 5432 ('r', 'rev', '', _('revision'), _('REV'))],
5364 5433 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5365 5434 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5366 5435 """update working directory (or switch revisions)
5367 5436
5368 5437 Update the repository's working directory to the specified
5369 5438 changeset. If no changeset is specified, update to the tip of the
5370 5439 current named branch.
5371 5440
5372 5441 If the changeset is not a descendant of the working directory's
5373 5442 parent, the update is aborted. With the -c/--check option, the
5374 5443 working directory is checked for uncommitted changes; if none are
5375 5444 found, the working directory is updated to the specified
5376 5445 changeset.
5377 5446
5378 5447 Update sets the working directory's parent revison to the specified
5379 5448 changeset (see :hg:`help parents`).
5380 5449
5381 5450 The following rules apply when the working directory contains
5382 5451 uncommitted changes:
5383 5452
5384 5453 1. If neither -c/--check nor -C/--clean is specified, and if
5385 5454 the requested changeset is an ancestor or descendant of
5386 5455 the working directory's parent, the uncommitted changes
5387 5456 are merged into the requested changeset and the merged
5388 5457 result is left uncommitted. If the requested changeset is
5389 5458 not an ancestor or descendant (that is, it is on another
5390 5459 branch), the update is aborted and the uncommitted changes
5391 5460 are preserved.
5392 5461
5393 5462 2. With the -c/--check option, the update is aborted and the
5394 5463 uncommitted changes are preserved.
5395 5464
5396 5465 3. With the -C/--clean option, uncommitted changes are discarded and
5397 5466 the working directory is updated to the requested changeset.
5398 5467
5399 5468 Use null as the changeset to remove the working directory (like
5400 5469 :hg:`clone -U`).
5401 5470
5402 5471 If you want to revert just one file to an older revision, use
5403 5472 :hg:`revert [-r REV] NAME`.
5404 5473
5405 5474 See :hg:`help dates` for a list of formats valid for -d/--date.
5406 5475
5407 5476 Returns 0 on success, 1 if there are unresolved files.
5408 5477 """
5409 5478 if rev and node:
5410 5479 raise util.Abort(_("please specify just one revision"))
5411 5480
5412 5481 if rev is None or rev == '':
5413 5482 rev = node
5414 5483
5415 5484 # if we defined a bookmark, we have to remember the original bookmark name
5416 5485 brev = rev
5417 5486 rev = scmutil.revsingle(repo, rev, rev).rev()
5418 5487
5419 5488 if check and clean:
5420 5489 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5421 5490
5422 5491 if check:
5423 5492 # we could use dirty() but we can ignore merge and branch trivia
5424 5493 c = repo[None]
5425 5494 if c.modified() or c.added() or c.removed():
5426 5495 raise util.Abort(_("uncommitted local changes"))
5427 5496
5428 5497 if date:
5429 5498 if rev is not None:
5430 5499 raise util.Abort(_("you can't specify a revision and a date"))
5431 5500 rev = cmdutil.finddate(ui, repo, date)
5432 5501
5433 5502 if clean or check:
5434 5503 ret = hg.clean(repo, rev)
5435 5504 else:
5436 5505 ret = hg.update(repo, rev)
5437 5506
5438 5507 if brev in repo._bookmarks:
5439 5508 bookmarks.setcurrent(repo, brev)
5440 5509
5441 5510 return ret
5442 5511
5443 5512 @command('verify', [])
5444 5513 def verify(ui, repo):
5445 5514 """verify the integrity of the repository
5446 5515
5447 5516 Verify the integrity of the current repository.
5448 5517
5449 5518 This will perform an extensive check of the repository's
5450 5519 integrity, validating the hashes and checksums of each entry in
5451 5520 the changelog, manifest, and tracked files, as well as the
5452 5521 integrity of their crosslinks and indices.
5453 5522
5454 5523 Returns 0 on success, 1 if errors are encountered.
5455 5524 """
5456 5525 return hg.verify(repo)
5457 5526
5458 5527 @command('version', [])
5459 5528 def version_(ui):
5460 5529 """output version and copyright information"""
5461 5530 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5462 5531 % util.version())
5463 5532 ui.status(_(
5464 5533 "(see http://mercurial.selenic.com for more information)\n"
5465 5534 "\nCopyright (C) 2005-2011 Matt Mackall and others\n"
5466 5535 "This is free software; see the source for copying conditions. "
5467 5536 "There is NO\nwarranty; "
5468 5537 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5469 5538 ))
5470 5539
5471 5540 norepo = ("clone init version help debugcommands debugcomplete"
5472 5541 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5473 5542 " debugknown debuggetbundle debugbundle")
5474 5543 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5475 5544 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,268 +1,270 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 add
4 4 addremove
5 5 annotate
6 6 archive
7 7 backout
8 8 bisect
9 9 bookmarks
10 10 branch
11 11 branches
12 12 bundle
13 13 cat
14 14 clone
15 15 commit
16 16 copy
17 17 diff
18 18 export
19 19 forget
20 graft
20 21 grep
21 22 heads
22 23 help
23 24 identify
24 25 import
25 26 incoming
26 27 init
27 28 locate
28 29 log
29 30 manifest
30 31 merge
31 32 outgoing
32 33 parents
33 34 paths
34 35 pull
35 36 push
36 37 recover
37 38 remove
38 39 rename
39 40 resolve
40 41 revert
41 42 rollback
42 43 root
43 44 serve
44 45 showconfig
45 46 status
46 47 summary
47 48 tag
48 49 tags
49 50 tip
50 51 unbundle
51 52 update
52 53 verify
53 54 version
54 55
55 56 Show all commands that start with "a"
56 57 $ hg debugcomplete a
57 58 add
58 59 addremove
59 60 annotate
60 61 archive
61 62
62 63 Do not show debug commands if there are other candidates
63 64 $ hg debugcomplete d
64 65 diff
65 66
66 67 Show debug commands if there are no other candidates
67 68 $ hg debugcomplete debug
68 69 debugancestor
69 70 debugbuilddag
70 71 debugbundle
71 72 debugcheckstate
72 73 debugcommands
73 74 debugcomplete
74 75 debugconfig
75 76 debugdag
76 77 debugdata
77 78 debugdate
78 79 debugdiscovery
79 80 debugfileset
80 81 debugfsinfo
81 82 debuggetbundle
82 83 debugignore
83 84 debugindex
84 85 debugindexdot
85 86 debuginstall
86 87 debugknown
87 88 debugpushkey
88 89 debugrebuildstate
89 90 debugrename
90 91 debugrevlog
91 92 debugrevspec
92 93 debugsetparents
93 94 debugstate
94 95 debugsub
95 96 debugwalk
96 97 debugwireargs
97 98
98 99 Do not show the alias of a debug command if there are other candidates
99 100 (this should hide rawcommit)
100 101 $ hg debugcomplete r
101 102 recover
102 103 remove
103 104 rename
104 105 resolve
105 106 revert
106 107 rollback
107 108 root
108 109 Show the alias of a debug command if there are no other candidates
109 110 $ hg debugcomplete rawc
110 111
111 112
112 113 Show the global options
113 114 $ hg debugcomplete --options | sort
114 115 --config
115 116 --cwd
116 117 --debug
117 118 --debugger
118 119 --encoding
119 120 --encodingmode
120 121 --help
121 122 --noninteractive
122 123 --profile
123 124 --quiet
124 125 --repository
125 126 --time
126 127 --traceback
127 128 --verbose
128 129 --version
129 130 -R
130 131 -h
131 132 -q
132 133 -v
133 134 -y
134 135
135 136 Show the options for the "serve" command
136 137 $ hg debugcomplete --options serve | sort
137 138 --accesslog
138 139 --address
139 140 --certificate
140 141 --cmdserver
141 142 --config
142 143 --cwd
143 144 --daemon
144 145 --daemon-pipefds
145 146 --debug
146 147 --debugger
147 148 --encoding
148 149 --encodingmode
149 150 --errorlog
150 151 --help
151 152 --ipv6
152 153 --name
153 154 --noninteractive
154 155 --pid-file
155 156 --port
156 157 --prefix
157 158 --profile
158 159 --quiet
159 160 --repository
160 161 --stdio
161 162 --style
162 163 --templates
163 164 --time
164 165 --traceback
165 166 --verbose
166 167 --version
167 168 --web-conf
168 169 -6
169 170 -A
170 171 -E
171 172 -R
172 173 -a
173 174 -d
174 175 -h
175 176 -n
176 177 -p
177 178 -q
178 179 -t
179 180 -v
180 181 -y
181 182
182 183 Show an error if we use --options with an ambiguous abbreviation
183 184 $ hg debugcomplete --options s
184 185 hg: command 's' is ambiguous:
185 186 serve showconfig status summary
186 187 [255]
187 188
188 189 Show all commands + options
189 190 $ hg debugcommands
190 191 add: include, exclude, subrepos, dry-run
191 192 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, include, exclude
192 193 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
193 194 commit: addremove, close-branch, include, exclude, message, logfile, date, user
194 195 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
195 196 export: output, switch-parent, rev, text, git, nodates
196 197 forget: include, exclude
197 198 init: ssh, remotecmd, insecure
198 199 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, hidden, patch, git, limit, no-merges, stat, style, template, include, exclude
199 200 merge: force, rev, preview, tool
200 201 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
201 202 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
202 203 remove: after, force, include, exclude
203 204 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
204 205 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
205 206 summary: remote
206 207 update: clean, check, date, rev
207 208 addremove: similarity, include, exclude, dry-run
208 209 archive: no-decode, prefix, rev, type, subrepos, include, exclude
209 210 backout: merge, parent, rev, tool, include, exclude, message, logfile, date, user
210 211 bisect: reset, good, bad, skip, extend, command, noupdate
211 212 bookmarks: force, rev, delete, rename, inactive
212 213 branch: force, clean
213 214 branches: active, closed
214 215 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
215 216 cat: output, rev, decode, include, exclude
216 217 copy: after, force, include, exclude, dry-run
217 218 debugancestor:
218 219 debugbuilddag: mergeable-file, overwritten-file, new-file
219 220 debugbundle: all
220 221 debugcheckstate:
221 222 debugcommands:
222 223 debugcomplete: options
223 224 debugdag: tags, branches, dots, spaces
224 225 debugdata: changelog, manifest
225 226 debugdate: extended
226 227 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
227 228 debugfileset:
228 229 debugfsinfo:
229 230 debuggetbundle: head, common, type
230 231 debugignore:
231 232 debugindex: changelog, manifest, format
232 233 debugindexdot:
233 234 debuginstall:
234 235 debugknown:
235 236 debugpushkey:
236 237 debugrebuildstate: rev
237 238 debugrename: rev
238 239 debugrevlog: changelog, manifest, dump
239 240 debugrevspec:
240 241 debugsetparents:
241 242 debugstate: nodates, datesort
242 243 debugsub: rev
243 244 debugwalk: include, exclude
244 245 debugwireargs: three, four, five, ssh, remotecmd, insecure
246 graft:
245 247 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
246 248 heads: rev, topo, active, closed, style, template
247 249 help: extension, command
248 250 identify: rev, num, id, branch, tags, bookmarks
249 251 import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
250 252 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
251 253 locate: rev, print0, fullpath, include, exclude
252 254 manifest: rev, all
253 255 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
254 256 parents: rev, style, template
255 257 paths:
256 258 recover:
257 259 rename: after, force, include, exclude, dry-run
258 260 resolve: all, list, mark, unmark, no-status, tool, include, exclude
259 261 revert: all, date, rev, no-backup, include, exclude, dry-run
260 262 rollback: dry-run, force
261 263 root:
262 264 showconfig: untrusted
263 265 tag: force, local, rev, remove, edit, message, date, user
264 266 tags:
265 267 tip: patch, git, style, template
266 268 unbundle: update
267 269 verify:
268 270 version:
@@ -1,438 +1,440 b''
1 1 $ "$TESTDIR/hghave" no-outer-repo || exit 80
2 2
3 3 $ hg init a
4 4 $ cd a
5 5 $ echo a > a
6 6 $ hg ci -A -d'1 0' -m a
7 7 adding a
8 8
9 9 $ cd ..
10 10
11 11 $ hg init b
12 12 $ cd b
13 13 $ echo b > b
14 14 $ hg ci -A -d'1 0' -m b
15 15 adding b
16 16
17 17 $ cd ..
18 18
19 19 $ hg clone a c
20 20 updating to branch default
21 21 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
22 22 $ cd c
23 23 $ cat >> .hg/hgrc <<EOF
24 24 > [paths]
25 25 > relative = ../a
26 26 > EOF
27 27 $ hg pull -f ../b
28 28 pulling from ../b
29 29 searching for changes
30 30 warning: repository is unrelated
31 31 requesting all changes
32 32 adding changesets
33 33 adding manifests
34 34 adding file changes
35 35 added 1 changesets with 1 changes to 1 files (+1 heads)
36 36 (run 'hg heads' to see heads, 'hg merge' to merge)
37 37 $ hg merge
38 38 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
39 39 (branch merge, don't forget to commit)
40 40
41 41 $ cd ..
42 42
43 43 Testing -R/--repository:
44 44
45 45 $ hg -R a tip
46 46 changeset: 0:8580ff50825a
47 47 tag: tip
48 48 user: test
49 49 date: Thu Jan 01 00:00:01 1970 +0000
50 50 summary: a
51 51
52 52 $ hg --repository b tip
53 53 changeset: 0:b6c483daf290
54 54 tag: tip
55 55 user: test
56 56 date: Thu Jan 01 00:00:01 1970 +0000
57 57 summary: b
58 58
59 59
60 60 -R with a URL:
61 61
62 62 $ hg -R file:a identify
63 63 8580ff50825a tip
64 64 $ hg -R file://localhost/`pwd`/a/ identify
65 65 8580ff50825a tip
66 66
67 67 -R with path aliases:
68 68
69 69 $ cd c
70 70 $ hg -R default identify
71 71 8580ff50825a tip
72 72 $ hg -R relative identify
73 73 8580ff50825a tip
74 74 $ echo '[paths]' >> $HGRCPATH
75 75 $ echo 'relativetohome = a' >> $HGRCPATH
76 76 $ HOME=`pwd`/../ hg -R relativetohome identify
77 77 8580ff50825a tip
78 78 $ cd ..
79 79
80 80 Implicit -R:
81 81
82 82 $ hg ann a/a
83 83 0: a
84 84 $ hg ann a/a a/a
85 85 0: a
86 86 $ hg ann a/a b/b
87 87 abort: no repository found in '$TESTTMP' (.hg not found)!
88 88 [255]
89 89 $ hg -R b ann a/a
90 90 abort: a/a not under root
91 91 [255]
92 92 $ hg log
93 93 abort: no repository found in '$TESTTMP' (.hg not found)!
94 94 [255]
95 95
96 96 Abbreviation of long option:
97 97
98 98 $ hg --repo c tip
99 99 changeset: 1:b6c483daf290
100 100 tag: tip
101 101 parent: -1:000000000000
102 102 user: test
103 103 date: Thu Jan 01 00:00:01 1970 +0000
104 104 summary: b
105 105
106 106
107 107 earlygetopt with duplicate options (36d23de02da1):
108 108
109 109 $ hg --cwd a --cwd b --cwd c tip
110 110 changeset: 1:b6c483daf290
111 111 tag: tip
112 112 parent: -1:000000000000
113 113 user: test
114 114 date: Thu Jan 01 00:00:01 1970 +0000
115 115 summary: b
116 116
117 117 $ hg --repo c --repository b -R a tip
118 118 changeset: 0:8580ff50825a
119 119 tag: tip
120 120 user: test
121 121 date: Thu Jan 01 00:00:01 1970 +0000
122 122 summary: a
123 123
124 124
125 125 earlygetopt short option without following space:
126 126
127 127 $ hg -q -Rb tip
128 128 0:b6c483daf290
129 129
130 130 earlygetopt with illegal abbreviations:
131 131
132 132 $ hg --confi "foo.bar=baz"
133 133 abort: option --config may not be abbreviated!
134 134 [255]
135 135 $ hg --cw a tip
136 136 abort: option --cwd may not be abbreviated!
137 137 [255]
138 138 $ hg --rep a tip
139 139 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
140 140 [255]
141 141 $ hg --repositor a tip
142 142 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
143 143 [255]
144 144 $ hg -qR a tip
145 145 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
146 146 [255]
147 147 $ hg -qRa tip
148 148 abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
149 149 [255]
150 150
151 151 Testing --cwd:
152 152
153 153 $ hg --cwd a parents
154 154 changeset: 0:8580ff50825a
155 155 tag: tip
156 156 user: test
157 157 date: Thu Jan 01 00:00:01 1970 +0000
158 158 summary: a
159 159
160 160
161 161 Testing -y/--noninteractive - just be sure it is parsed:
162 162
163 163 $ hg --cwd a tip -q --noninteractive
164 164 0:8580ff50825a
165 165 $ hg --cwd a tip -q -y
166 166 0:8580ff50825a
167 167
168 168 Testing -q/--quiet:
169 169
170 170 $ hg -R a -q tip
171 171 0:8580ff50825a
172 172 $ hg -R b -q tip
173 173 0:b6c483daf290
174 174 $ hg -R c --quiet parents
175 175 0:8580ff50825a
176 176 1:b6c483daf290
177 177
178 178 Testing -v/--verbose:
179 179
180 180 $ hg --cwd c head -v
181 181 changeset: 1:b6c483daf290
182 182 tag: tip
183 183 parent: -1:000000000000
184 184 user: test
185 185 date: Thu Jan 01 00:00:01 1970 +0000
186 186 files: b
187 187 description:
188 188 b
189 189
190 190
191 191 changeset: 0:8580ff50825a
192 192 user: test
193 193 date: Thu Jan 01 00:00:01 1970 +0000
194 194 files: a
195 195 description:
196 196 a
197 197
198 198
199 199 $ hg --cwd b tip --verbose
200 200 changeset: 0:b6c483daf290
201 201 tag: tip
202 202 user: test
203 203 date: Thu Jan 01 00:00:01 1970 +0000
204 204 files: b
205 205 description:
206 206 b
207 207
208 208
209 209
210 210 Testing --config:
211 211
212 212 $ hg --cwd c --config paths.quuxfoo=bar paths | grep quuxfoo > /dev/null && echo quuxfoo
213 213 quuxfoo
214 214 $ hg --cwd c --config '' tip -q
215 215 abort: malformed --config option: '' (use --config section.name=value)
216 216 [255]
217 217 $ hg --cwd c --config a.b tip -q
218 218 abort: malformed --config option: 'a.b' (use --config section.name=value)
219 219 [255]
220 220 $ hg --cwd c --config a tip -q
221 221 abort: malformed --config option: 'a' (use --config section.name=value)
222 222 [255]
223 223 $ hg --cwd c --config a.= tip -q
224 224 abort: malformed --config option: 'a.=' (use --config section.name=value)
225 225 [255]
226 226 $ hg --cwd c --config .b= tip -q
227 227 abort: malformed --config option: '.b=' (use --config section.name=value)
228 228 [255]
229 229
230 230 Testing --debug:
231 231
232 232 $ hg --cwd c log --debug
233 233 changeset: 1:b6c483daf2907ce5825c0bb50f5716226281cc1a
234 234 tag: tip
235 235 parent: -1:0000000000000000000000000000000000000000
236 236 parent: -1:0000000000000000000000000000000000000000
237 237 manifest: 1:23226e7a252cacdc2d99e4fbdc3653441056de49
238 238 user: test
239 239 date: Thu Jan 01 00:00:01 1970 +0000
240 240 files+: b
241 241 extra: branch=default
242 242 description:
243 243 b
244 244
245 245
246 246 changeset: 0:8580ff50825a50c8f716709acdf8de0deddcd6ab
247 247 parent: -1:0000000000000000000000000000000000000000
248 248 parent: -1:0000000000000000000000000000000000000000
249 249 manifest: 0:a0c8bcbbb45c63b90b70ad007bf38961f64f2af0
250 250 user: test
251 251 date: Thu Jan 01 00:00:01 1970 +0000
252 252 files+: a
253 253 extra: branch=default
254 254 description:
255 255 a
256 256
257 257
258 258
259 259 Testing --traceback:
260 260
261 261 $ hg --cwd c --config x --traceback id 2>&1 | grep -i 'traceback'
262 262 Traceback (most recent call last):
263 263
264 264 Testing --time:
265 265
266 266 $ hg --cwd a --time id
267 267 8580ff50825a tip
268 268 Time: real * (glob)
269 269
270 270 Testing --version:
271 271
272 272 $ hg --version -q
273 273 Mercurial Distributed SCM * (glob)
274 274
275 275 Testing -h/--help:
276 276
277 277 $ hg -h
278 278 Mercurial Distributed SCM
279 279
280 280 list of commands:
281 281
282 282 add add the specified files on the next commit
283 283 addremove add all new files, delete all missing files
284 284 annotate show changeset information by line for each file
285 285 archive create an unversioned archive of a repository revision
286 286 backout reverse effect of earlier changeset
287 287 bisect subdivision search of changesets
288 288 bookmarks track a line of development with movable markers
289 289 branch set or show the current branch name
290 290 branches list repository named branches
291 291 bundle create a changegroup file
292 292 cat output the current or given revision of files
293 293 clone make a copy of an existing repository
294 294 commit commit the specified files or all outstanding changes
295 295 copy mark files as copied for the next commit
296 296 diff diff repository (or selected files)
297 297 export dump the header and diffs for one or more changesets
298 298 forget forget the specified files on the next commit
299 graft copy changes from other branches onto the current branch
299 300 grep search for a pattern in specified files and revisions
300 301 heads show current repository heads or show branch heads
301 302 help show help for a given topic or a help overview
302 303 identify identify the working copy or specified revision
303 304 import import an ordered set of patches
304 305 incoming show new changesets found in source
305 306 init create a new repository in the given directory
306 307 locate locate files matching specific patterns
307 308 log show revision history of entire repository or files
308 309 manifest output the current or given revision of the project manifest
309 310 merge merge working directory with another revision
310 311 outgoing show changesets not found in the destination
311 312 parents show the parents of the working directory or revision
312 313 paths show aliases for remote repositories
313 314 pull pull changes from the specified source
314 315 push push changes to the specified destination
315 316 recover roll back an interrupted transaction
316 317 remove remove the specified files on the next commit
317 318 rename rename files; equivalent of copy + remove
318 319 resolve redo merges or set/view the merge status of files
319 320 revert restore files to their checkout state
320 321 rollback roll back the last transaction (dangerous)
321 322 root print the root (top) of the current working directory
322 323 serve start stand-alone webserver
323 324 showconfig show combined config settings from all hgrc files
324 325 status show changed files in the working directory
325 326 summary summarize working directory state
326 327 tag add one or more tags for the current or given revision
327 328 tags list repository tags
328 329 tip show the tip revision
329 330 unbundle apply one or more changegroup files
330 331 update update working directory (or switch revisions)
331 332 verify verify the integrity of the repository
332 333 version output version and copyright information
333 334
334 335 additional help topics:
335 336
336 337 config Configuration Files
337 338 dates Date Formats
338 339 diffs Diff Formats
339 340 environment Environment Variables
340 341 extensions Using additional features
341 342 filesets Specifying File Sets
342 343 glossary Glossary
343 344 hgignore syntax for Mercurial ignore files
344 345 hgweb Configuring hgweb
345 346 merge-tools Merge Tools
346 347 multirevs Specifying Multiple Revisions
347 348 patterns File Name Patterns
348 349 revisions Specifying Single Revisions
349 350 revsets Specifying Revision Sets
350 351 subrepos Subrepositories
351 352 templating Template Usage
352 353 urls URL Paths
353 354
354 355 use "hg -v help" to show builtin aliases and global options
355 356
356 357
357 358
358 359 $ hg --help
359 360 Mercurial Distributed SCM
360 361
361 362 list of commands:
362 363
363 364 add add the specified files on the next commit
364 365 addremove add all new files, delete all missing files
365 366 annotate show changeset information by line for each file
366 367 archive create an unversioned archive of a repository revision
367 368 backout reverse effect of earlier changeset
368 369 bisect subdivision search of changesets
369 370 bookmarks track a line of development with movable markers
370 371 branch set or show the current branch name
371 372 branches list repository named branches
372 373 bundle create a changegroup file
373 374 cat output the current or given revision of files
374 375 clone make a copy of an existing repository
375 376 commit commit the specified files or all outstanding changes
376 377 copy mark files as copied for the next commit
377 378 diff diff repository (or selected files)
378 379 export dump the header and diffs for one or more changesets
379 380 forget forget the specified files on the next commit
381 graft copy changes from other branches onto the current branch
380 382 grep search for a pattern in specified files and revisions
381 383 heads show current repository heads or show branch heads
382 384 help show help for a given topic or a help overview
383 385 identify identify the working copy or specified revision
384 386 import import an ordered set of patches
385 387 incoming show new changesets found in source
386 388 init create a new repository in the given directory
387 389 locate locate files matching specific patterns
388 390 log show revision history of entire repository or files
389 391 manifest output the current or given revision of the project manifest
390 392 merge merge working directory with another revision
391 393 outgoing show changesets not found in the destination
392 394 parents show the parents of the working directory or revision
393 395 paths show aliases for remote repositories
394 396 pull pull changes from the specified source
395 397 push push changes to the specified destination
396 398 recover roll back an interrupted transaction
397 399 remove remove the specified files on the next commit
398 400 rename rename files; equivalent of copy + remove
399 401 resolve redo merges or set/view the merge status of files
400 402 revert restore files to their checkout state
401 403 rollback roll back the last transaction (dangerous)
402 404 root print the root (top) of the current working directory
403 405 serve start stand-alone webserver
404 406 showconfig show combined config settings from all hgrc files
405 407 status show changed files in the working directory
406 408 summary summarize working directory state
407 409 tag add one or more tags for the current or given revision
408 410 tags list repository tags
409 411 tip show the tip revision
410 412 unbundle apply one or more changegroup files
411 413 update update working directory (or switch revisions)
412 414 verify verify the integrity of the repository
413 415 version output version and copyright information
414 416
415 417 additional help topics:
416 418
417 419 config Configuration Files
418 420 dates Date Formats
419 421 diffs Diff Formats
420 422 environment Environment Variables
421 423 extensions Using additional features
422 424 filesets Specifying File Sets
423 425 glossary Glossary
424 426 hgignore syntax for Mercurial ignore files
425 427 hgweb Configuring hgweb
426 428 merge-tools Merge Tools
427 429 multirevs Specifying Multiple Revisions
428 430 patterns File Name Patterns
429 431 revisions Specifying Single Revisions
430 432 revsets Specifying Revision Sets
431 433 subrepos Subrepositories
432 434 templating Template Usage
433 435 urls URL Paths
434 436
435 437 use "hg -v help" to show builtin aliases and global options
436 438
437 439 Not tested: --debugger
438 440
@@ -1,769 +1,772 b''
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge working directory with another revision
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 use "hg help" for the full list of commands or "hg -v" for details
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge working directory with another revision
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 $ hg help
48 48 Mercurial Distributed SCM
49 49
50 50 list of commands:
51 51
52 52 add add the specified files on the next commit
53 53 addremove add all new files, delete all missing files
54 54 annotate show changeset information by line for each file
55 55 archive create an unversioned archive of a repository revision
56 56 backout reverse effect of earlier changeset
57 57 bisect subdivision search of changesets
58 58 bookmarks track a line of development with movable markers
59 59 branch set or show the current branch name
60 60 branches list repository named branches
61 61 bundle create a changegroup file
62 62 cat output the current or given revision of files
63 63 clone make a copy of an existing repository
64 64 commit commit the specified files or all outstanding changes
65 65 copy mark files as copied for the next commit
66 66 diff diff repository (or selected files)
67 67 export dump the header and diffs for one or more changesets
68 68 forget forget the specified files on the next commit
69 graft copy changes from other branches onto the current branch
69 70 grep search for a pattern in specified files and revisions
70 71 heads show current repository heads or show branch heads
71 72 help show help for a given topic or a help overview
72 73 identify identify the working copy or specified revision
73 74 import import an ordered set of patches
74 75 incoming show new changesets found in source
75 76 init create a new repository in the given directory
76 77 locate locate files matching specific patterns
77 78 log show revision history of entire repository or files
78 79 manifest output the current or given revision of the project manifest
79 80 merge merge working directory with another revision
80 81 outgoing show changesets not found in the destination
81 82 parents show the parents of the working directory or revision
82 83 paths show aliases for remote repositories
83 84 pull pull changes from the specified source
84 85 push push changes to the specified destination
85 86 recover roll back an interrupted transaction
86 87 remove remove the specified files on the next commit
87 88 rename rename files; equivalent of copy + remove
88 89 resolve redo merges or set/view the merge status of files
89 90 revert restore files to their checkout state
90 91 rollback roll back the last transaction (dangerous)
91 92 root print the root (top) of the current working directory
92 93 serve start stand-alone webserver
93 94 showconfig show combined config settings from all hgrc files
94 95 status show changed files in the working directory
95 96 summary summarize working directory state
96 97 tag add one or more tags for the current or given revision
97 98 tags list repository tags
98 99 tip show the tip revision
99 100 unbundle apply one or more changegroup files
100 101 update update working directory (or switch revisions)
101 102 verify verify the integrity of the repository
102 103 version output version and copyright information
103 104
104 105 additional help topics:
105 106
106 107 config Configuration Files
107 108 dates Date Formats
108 109 diffs Diff Formats
109 110 environment Environment Variables
110 111 extensions Using additional features
111 112 filesets Specifying File Sets
112 113 glossary Glossary
113 114 hgignore syntax for Mercurial ignore files
114 115 hgweb Configuring hgweb
115 116 merge-tools Merge Tools
116 117 multirevs Specifying Multiple Revisions
117 118 patterns File Name Patterns
118 119 revisions Specifying Single Revisions
119 120 revsets Specifying Revision Sets
120 121 subrepos Subrepositories
121 122 templating Template Usage
122 123 urls URL Paths
123 124
124 125 use "hg -v help" to show builtin aliases and global options
125 126
126 127 $ hg -q help
127 128 add add the specified files on the next commit
128 129 addremove add all new files, delete all missing files
129 130 annotate show changeset information by line for each file
130 131 archive create an unversioned archive of a repository revision
131 132 backout reverse effect of earlier changeset
132 133 bisect subdivision search of changesets
133 134 bookmarks track a line of development with movable markers
134 135 branch set or show the current branch name
135 136 branches list repository named branches
136 137 bundle create a changegroup file
137 138 cat output the current or given revision of files
138 139 clone make a copy of an existing repository
139 140 commit commit the specified files or all outstanding changes
140 141 copy mark files as copied for the next commit
141 142 diff diff repository (or selected files)
142 143 export dump the header and diffs for one or more changesets
143 144 forget forget the specified files on the next commit
145 graft copy changes from other branches onto the current branch
144 146 grep search for a pattern in specified files and revisions
145 147 heads show current repository heads or show branch heads
146 148 help show help for a given topic or a help overview
147 149 identify identify the working copy or specified revision
148 150 import import an ordered set of patches
149 151 incoming show new changesets found in source
150 152 init create a new repository in the given directory
151 153 locate locate files matching specific patterns
152 154 log show revision history of entire repository or files
153 155 manifest output the current or given revision of the project manifest
154 156 merge merge working directory with another revision
155 157 outgoing show changesets not found in the destination
156 158 parents show the parents of the working directory or revision
157 159 paths show aliases for remote repositories
158 160 pull pull changes from the specified source
159 161 push push changes to the specified destination
160 162 recover roll back an interrupted transaction
161 163 remove remove the specified files on the next commit
162 164 rename rename files; equivalent of copy + remove
163 165 resolve redo merges or set/view the merge status of files
164 166 revert restore files to their checkout state
165 167 rollback roll back the last transaction (dangerous)
166 168 root print the root (top) of the current working directory
167 169 serve start stand-alone webserver
168 170 showconfig show combined config settings from all hgrc files
169 171 status show changed files in the working directory
170 172 summary summarize working directory state
171 173 tag add one or more tags for the current or given revision
172 174 tags list repository tags
173 175 tip show the tip revision
174 176 unbundle apply one or more changegroup files
175 177 update update working directory (or switch revisions)
176 178 verify verify the integrity of the repository
177 179 version output version and copyright information
178 180
179 181 additional help topics:
180 182
181 183 config Configuration Files
182 184 dates Date Formats
183 185 diffs Diff Formats
184 186 environment Environment Variables
185 187 extensions Using additional features
186 188 filesets Specifying File Sets
187 189 glossary Glossary
188 190 hgignore syntax for Mercurial ignore files
189 191 hgweb Configuring hgweb
190 192 merge-tools Merge Tools
191 193 multirevs Specifying Multiple Revisions
192 194 patterns File Name Patterns
193 195 revisions Specifying Single Revisions
194 196 revsets Specifying Revision Sets
195 197 subrepos Subrepositories
196 198 templating Template Usage
197 199 urls URL Paths
198 200
199 201 Test short command list with verbose option
200 202
201 203 $ hg -v help shortlist
202 204 Mercurial Distributed SCM
203 205
204 206 basic commands:
205 207
206 208 add:
207 209 add the specified files on the next commit
208 210 annotate, blame:
209 211 show changeset information by line for each file
210 212 clone:
211 213 make a copy of an existing repository
212 214 commit, ci:
213 215 commit the specified files or all outstanding changes
214 216 diff:
215 217 diff repository (or selected files)
216 218 export:
217 219 dump the header and diffs for one or more changesets
218 220 forget:
219 221 forget the specified files on the next commit
220 222 init:
221 223 create a new repository in the given directory
222 224 log, history:
223 225 show revision history of entire repository or files
224 226 merge:
225 227 merge working directory with another revision
226 228 pull:
227 229 pull changes from the specified source
228 230 push:
229 231 push changes to the specified destination
230 232 remove, rm:
231 233 remove the specified files on the next commit
232 234 serve:
233 235 start stand-alone webserver
234 236 status, st:
235 237 show changed files in the working directory
236 238 summary, sum:
237 239 summarize working directory state
238 240 update, up, checkout, co:
239 241 update working directory (or switch revisions)
240 242
241 243 global options:
242 244
243 245 -R --repository REPO repository root directory or name of overlay bundle
244 246 file
245 247 --cwd DIR change working directory
246 248 -y --noninteractive do not prompt, automatically pick the first choice for
247 249 all prompts
248 250 -q --quiet suppress output
249 251 -v --verbose enable additional output
250 252 --config CONFIG [+] set/override config option (use 'section.name=value')
251 253 --debug enable debugging output
252 254 --debugger start debugger
253 255 --encoding ENCODE set the charset encoding (default: ascii)
254 256 --encodingmode MODE set the charset encoding mode (default: strict)
255 257 --traceback always print a traceback on exception
256 258 --time time how long the command takes
257 259 --profile print command execution profile
258 260 --version output version information and exit
259 261 -h --help display help and exit
260 262
261 263 [+] marked option can be specified multiple times
262 264
263 265 use "hg help" for the full list of commands
264 266
265 267 $ hg add -h
266 268 hg add [OPTION]... [FILE]...
267 269
268 270 add the specified files on the next commit
269 271
270 272 Schedule files to be version controlled and added to the repository.
271 273
272 274 The files will be added to the repository at the next commit. To undo an
273 275 add before that, see "hg forget".
274 276
275 277 If no names are given, add all files to the repository.
276 278
277 279 Returns 0 if all files are successfully added.
278 280
279 281 options:
280 282
281 283 -I --include PATTERN [+] include names matching the given patterns
282 284 -X --exclude PATTERN [+] exclude names matching the given patterns
283 285 -S --subrepos recurse into subrepositories
284 286 -n --dry-run do not perform actions, just print output
285 287
286 288 [+] marked option can be specified multiple times
287 289
288 290 use "hg -v help add" to show more info
289 291
290 292 Verbose help for add
291 293
292 294 $ hg add -hv
293 295 hg add [OPTION]... [FILE]...
294 296
295 297 add the specified files on the next commit
296 298
297 299 Schedule files to be version controlled and added to the repository.
298 300
299 301 The files will be added to the repository at the next commit. To undo an
300 302 add before that, see "hg forget".
301 303
302 304 If no names are given, add all files to the repository.
303 305
304 306 An example showing how new (unknown) files are added automatically by "hg
305 307 add":
306 308
307 309 $ ls
308 310 foo.c
309 311 $ hg status
310 312 ? foo.c
311 313 $ hg add
312 314 adding foo.c
313 315 $ hg status
314 316 A foo.c
315 317
316 318 Returns 0 if all files are successfully added.
317 319
318 320 options:
319 321
320 322 -I --include PATTERN [+] include names matching the given patterns
321 323 -X --exclude PATTERN [+] exclude names matching the given patterns
322 324 -S --subrepos recurse into subrepositories
323 325 -n --dry-run do not perform actions, just print output
324 326
325 327 [+] marked option can be specified multiple times
326 328
327 329 global options:
328 330
329 331 -R --repository REPO repository root directory or name of overlay bundle
330 332 file
331 333 --cwd DIR change working directory
332 334 -y --noninteractive do not prompt, automatically pick the first choice for
333 335 all prompts
334 336 -q --quiet suppress output
335 337 -v --verbose enable additional output
336 338 --config CONFIG [+] set/override config option (use 'section.name=value')
337 339 --debug enable debugging output
338 340 --debugger start debugger
339 341 --encoding ENCODE set the charset encoding (default: ascii)
340 342 --encodingmode MODE set the charset encoding mode (default: strict)
341 343 --traceback always print a traceback on exception
342 344 --time time how long the command takes
343 345 --profile print command execution profile
344 346 --version output version information and exit
345 347 -h --help display help and exit
346 348
347 349 [+] marked option can be specified multiple times
348 350
349 351 Test help option with version option
350 352
351 353 $ hg add -h --version
352 354 Mercurial Distributed SCM (version *) (glob)
353 355 (see http://mercurial.selenic.com for more information)
354 356
355 357 Copyright (C) 2005-2011 Matt Mackall and others
356 358 This is free software; see the source for copying conditions. There is NO
357 359 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
358 360
359 361 $ hg add --skjdfks
360 362 hg add: option --skjdfks not recognized
361 363 hg add [OPTION]... [FILE]...
362 364
363 365 add the specified files on the next commit
364 366
365 367 options:
366 368
367 369 -I --include PATTERN [+] include names matching the given patterns
368 370 -X --exclude PATTERN [+] exclude names matching the given patterns
369 371 -S --subrepos recurse into subrepositories
370 372 -n --dry-run do not perform actions, just print output
371 373
372 374 [+] marked option can be specified multiple times
373 375
374 376 use "hg help add" to show the full help text
375 377 [255]
376 378
377 379 Test ambiguous command help
378 380
379 381 $ hg help ad
380 382 list of commands:
381 383
382 384 add add the specified files on the next commit
383 385 addremove add all new files, delete all missing files
384 386
385 387 use "hg -v help ad" to show builtin aliases and global options
386 388
387 389 Test command without options
388 390
389 391 $ hg help verify
390 392 hg verify
391 393
392 394 verify the integrity of the repository
393 395
394 396 Verify the integrity of the current repository.
395 397
396 398 This will perform an extensive check of the repository's integrity,
397 399 validating the hashes and checksums of each entry in the changelog,
398 400 manifest, and tracked files, as well as the integrity of their crosslinks
399 401 and indices.
400 402
401 403 Returns 0 on success, 1 if errors are encountered.
402 404
403 405 use "hg -v help verify" to show more info
404 406
405 407 $ hg help diff
406 408 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
407 409
408 410 diff repository (or selected files)
409 411
410 412 Show differences between revisions for the specified files.
411 413
412 414 Differences between files are shown using the unified diff format.
413 415
414 416 Note:
415 417 diff may generate unexpected results for merges, as it will default to
416 418 comparing against the working directory's first parent changeset if no
417 419 revisions are specified.
418 420
419 421 When two revision arguments are given, then changes are shown between
420 422 those revisions. If only one revision is specified then that revision is
421 423 compared to the working directory, and, when no revisions are specified,
422 424 the working directory files are compared to its parent.
423 425
424 426 Alternatively you can specify -c/--change with a revision to see the
425 427 changes in that changeset relative to its first parent.
426 428
427 429 Without the -a/--text option, diff will avoid generating diffs of files it
428 430 detects as binary. With -a, diff will generate a diff anyway, probably
429 431 with undesirable results.
430 432
431 433 Use the -g/--git option to generate diffs in the git extended diff format.
432 434 For more information, read "hg help diffs".
433 435
434 436 Returns 0 on success.
435 437
436 438 options:
437 439
438 440 -r --rev REV [+] revision
439 441 -c --change REV change made by revision
440 442 -a --text treat all files as text
441 443 -g --git use git extended diff format
442 444 --nodates omit dates from diff headers
443 445 -p --show-function show which function each change is in
444 446 --reverse produce a diff that undoes the changes
445 447 -w --ignore-all-space ignore white space when comparing lines
446 448 -b --ignore-space-change ignore changes in the amount of white space
447 449 -B --ignore-blank-lines ignore changes whose lines are all blank
448 450 -U --unified NUM number of lines of context to show
449 451 --stat output diffstat-style summary of changes
450 452 -I --include PATTERN [+] include names matching the given patterns
451 453 -X --exclude PATTERN [+] exclude names matching the given patterns
452 454 -S --subrepos recurse into subrepositories
453 455
454 456 [+] marked option can be specified multiple times
455 457
456 458 use "hg -v help diff" to show more info
457 459
458 460 $ hg help status
459 461 hg status [OPTION]... [FILE]...
460 462
461 463 aliases: st
462 464
463 465 show changed files in the working directory
464 466
465 467 Show status of files in the repository. If names are given, only files
466 468 that match are shown. Files that are clean or ignored or the source of a
467 469 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
468 470 -C/--copies or -A/--all are given. Unless options described with "show
469 471 only ..." are given, the options -mardu are used.
470 472
471 473 Option -q/--quiet hides untracked (unknown and ignored) files unless
472 474 explicitly requested with -u/--unknown or -i/--ignored.
473 475
474 476 Note:
475 477 status may appear to disagree with diff if permissions have changed or
476 478 a merge has occurred. The standard diff format does not report
477 479 permission changes and diff only reports changes relative to one merge
478 480 parent.
479 481
480 482 If one revision is given, it is used as the base revision. If two
481 483 revisions are given, the differences between them are shown. The --change
482 484 option can also be used as a shortcut to list the changed files of a
483 485 revision from its first parent.
484 486
485 487 The codes used to show the status of files are:
486 488
487 489 M = modified
488 490 A = added
489 491 R = removed
490 492 C = clean
491 493 ! = missing (deleted by non-hg command, but still tracked)
492 494 ? = not tracked
493 495 I = ignored
494 496 = origin of the previous file listed as A (added)
495 497
496 498 Returns 0 on success.
497 499
498 500 options:
499 501
500 502 -A --all show status of all files
501 503 -m --modified show only modified files
502 504 -a --added show only added files
503 505 -r --removed show only removed files
504 506 -d --deleted show only deleted (but tracked) files
505 507 -c --clean show only files without changes
506 508 -u --unknown show only unknown (not tracked) files
507 509 -i --ignored show only ignored files
508 510 -n --no-status hide status prefix
509 511 -C --copies show source of copied files
510 512 -0 --print0 end filenames with NUL, for use with xargs
511 513 --rev REV [+] show difference from revision
512 514 --change REV list the changed files of a revision
513 515 -I --include PATTERN [+] include names matching the given patterns
514 516 -X --exclude PATTERN [+] exclude names matching the given patterns
515 517 -S --subrepos recurse into subrepositories
516 518
517 519 [+] marked option can be specified multiple times
518 520
519 521 use "hg -v help status" to show more info
520 522
521 523 $ hg -q help status
522 524 hg status [OPTION]... [FILE]...
523 525
524 526 show changed files in the working directory
525 527
526 528 $ hg help foo
527 529 hg: unknown command 'foo'
528 530 Mercurial Distributed SCM
529 531
530 532 basic commands:
531 533
532 534 add add the specified files on the next commit
533 535 annotate show changeset information by line for each file
534 536 clone make a copy of an existing repository
535 537 commit commit the specified files or all outstanding changes
536 538 diff diff repository (or selected files)
537 539 export dump the header and diffs for one or more changesets
538 540 forget forget the specified files on the next commit
539 541 init create a new repository in the given directory
540 542 log show revision history of entire repository or files
541 543 merge merge working directory with another revision
542 544 pull pull changes from the specified source
543 545 push push changes to the specified destination
544 546 remove remove the specified files on the next commit
545 547 serve start stand-alone webserver
546 548 status show changed files in the working directory
547 549 summary summarize working directory state
548 550 update update working directory (or switch revisions)
549 551
550 552 use "hg help" for the full list of commands or "hg -v" for details
551 553 [255]
552 554
553 555 $ hg skjdfks
554 556 hg: unknown command 'skjdfks'
555 557 Mercurial Distributed SCM
556 558
557 559 basic commands:
558 560
559 561 add add the specified files on the next commit
560 562 annotate show changeset information by line for each file
561 563 clone make a copy of an existing repository
562 564 commit commit the specified files or all outstanding changes
563 565 diff diff repository (or selected files)
564 566 export dump the header and diffs for one or more changesets
565 567 forget forget the specified files on the next commit
566 568 init create a new repository in the given directory
567 569 log show revision history of entire repository or files
568 570 merge merge working directory with another revision
569 571 pull pull changes from the specified source
570 572 push push changes to the specified destination
571 573 remove remove the specified files on the next commit
572 574 serve start stand-alone webserver
573 575 status show changed files in the working directory
574 576 summary summarize working directory state
575 577 update update working directory (or switch revisions)
576 578
577 579 use "hg help" for the full list of commands or "hg -v" for details
578 580 [255]
579 581
580 582 $ cat > helpext.py <<EOF
581 583 > import os
582 584 > from mercurial import commands
583 585 >
584 586 > def nohelp(ui, *args, **kwargs):
585 587 > pass
586 588 >
587 589 > cmdtable = {
588 590 > "nohelp": (nohelp, [], "hg nohelp"),
589 591 > }
590 592 >
591 593 > commands.norepo += ' nohelp'
592 594 > EOF
593 595 $ echo '[extensions]' >> $HGRCPATH
594 596 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
595 597
596 598 Test command with no help text
597 599
598 600 $ hg help nohelp
599 601 hg nohelp
600 602
601 603 (no help text available)
602 604
603 605 use "hg -v help nohelp" to show more info
604 606
605 607 Test that default list of commands omits extension commands
606 608
607 609 $ hg help
608 610 Mercurial Distributed SCM
609 611
610 612 list of commands:
611 613
612 614 add add the specified files on the next commit
613 615 addremove add all new files, delete all missing files
614 616 annotate show changeset information by line for each file
615 617 archive create an unversioned archive of a repository revision
616 618 backout reverse effect of earlier changeset
617 619 bisect subdivision search of changesets
618 620 bookmarks track a line of development with movable markers
619 621 branch set or show the current branch name
620 622 branches list repository named branches
621 623 bundle create a changegroup file
622 624 cat output the current or given revision of files
623 625 clone make a copy of an existing repository
624 626 commit commit the specified files or all outstanding changes
625 627 copy mark files as copied for the next commit
626 628 diff diff repository (or selected files)
627 629 export dump the header and diffs for one or more changesets
628 630 forget forget the specified files on the next commit
631 graft copy changes from other branches onto the current branch
629 632 grep search for a pattern in specified files and revisions
630 633 heads show current repository heads or show branch heads
631 634 help show help for a given topic or a help overview
632 635 identify identify the working copy or specified revision
633 636 import import an ordered set of patches
634 637 incoming show new changesets found in source
635 638 init create a new repository in the given directory
636 639 locate locate files matching specific patterns
637 640 log show revision history of entire repository or files
638 641 manifest output the current or given revision of the project manifest
639 642 merge merge working directory with another revision
640 643 outgoing show changesets not found in the destination
641 644 parents show the parents of the working directory or revision
642 645 paths show aliases for remote repositories
643 646 pull pull changes from the specified source
644 647 push push changes to the specified destination
645 648 recover roll back an interrupted transaction
646 649 remove remove the specified files on the next commit
647 650 rename rename files; equivalent of copy + remove
648 651 resolve redo merges or set/view the merge status of files
649 652 revert restore files to their checkout state
650 653 rollback roll back the last transaction (dangerous)
651 654 root print the root (top) of the current working directory
652 655 serve start stand-alone webserver
653 656 showconfig show combined config settings from all hgrc files
654 657 status show changed files in the working directory
655 658 summary summarize working directory state
656 659 tag add one or more tags for the current or given revision
657 660 tags list repository tags
658 661 tip show the tip revision
659 662 unbundle apply one or more changegroup files
660 663 update update working directory (or switch revisions)
661 664 verify verify the integrity of the repository
662 665 version output version and copyright information
663 666
664 667 enabled extensions:
665 668
666 669 helpext (no help text available)
667 670
668 671 additional help topics:
669 672
670 673 config Configuration Files
671 674 dates Date Formats
672 675 diffs Diff Formats
673 676 environment Environment Variables
674 677 extensions Using additional features
675 678 filesets Specifying File Sets
676 679 glossary Glossary
677 680 hgignore syntax for Mercurial ignore files
678 681 hgweb Configuring hgweb
679 682 merge-tools Merge Tools
680 683 multirevs Specifying Multiple Revisions
681 684 patterns File Name Patterns
682 685 revisions Specifying Single Revisions
683 686 revsets Specifying Revision Sets
684 687 subrepos Subrepositories
685 688 templating Template Usage
686 689 urls URL Paths
687 690
688 691 use "hg -v help" to show builtin aliases and global options
689 692
690 693
691 694
692 695 Test list of commands with command with no help text
693 696
694 697 $ hg help helpext
695 698 helpext extension - no help text available
696 699
697 700 list of commands:
698 701
699 702 nohelp (no help text available)
700 703
701 704 use "hg -v help helpext" to show builtin aliases and global options
702 705
703 706 Test a help topic
704 707
705 708 $ hg help revs
706 709 Specifying Single Revisions
707 710
708 711 Mercurial supports several ways to specify individual revisions.
709 712
710 713 A plain integer is treated as a revision number. Negative integers are
711 714 treated as sequential offsets from the tip, with -1 denoting the tip, -2
712 715 denoting the revision prior to the tip, and so forth.
713 716
714 717 A 40-digit hexadecimal string is treated as a unique revision identifier.
715 718
716 719 A hexadecimal string less than 40 characters long is treated as a unique
717 720 revision identifier and is referred to as a short-form identifier. A
718 721 short-form identifier is only valid if it is the prefix of exactly one
719 722 full-length identifier.
720 723
721 724 Any other string is treated as a tag or branch name. A tag name is a
722 725 symbolic name associated with a revision identifier. A branch name denotes
723 726 the tipmost revision of that branch. Tag and branch names must not contain
724 727 the ":" character.
725 728
726 729 The reserved name "tip" is a special tag that always identifies the most
727 730 recent revision.
728 731
729 732 The reserved name "null" indicates the null revision. This is the revision
730 733 of an empty repository, and the parent of revision 0.
731 734
732 735 The reserved name "." indicates the working directory parent. If no
733 736 working directory is checked out, it is equivalent to null. If an
734 737 uncommitted merge is in progress, "." is the revision of the first parent.
735 738
736 739 Test templating help
737 740
738 741 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
739 742 desc String. The text of the changeset description.
740 743 diffstat String. Statistics of changes with the following format:
741 744 firstline Any text. Returns the first line of text.
742 745 nonempty Any text. Returns '(none)' if the string is empty.
743 746
744 747 Test help hooks
745 748
746 749 $ cat > helphook1.py <<EOF
747 750 > from mercurial import help
748 751 >
749 752 > def rewrite(topic, doc):
750 753 > return doc + '\nhelphook1\n'
751 754 >
752 755 > def extsetup(ui):
753 756 > help.addtopichook('revsets', rewrite)
754 757 > EOF
755 758 $ cat > helphook2.py <<EOF
756 759 > from mercurial import help
757 760 >
758 761 > def rewrite(topic, doc):
759 762 > return doc + '\nhelphook2\n'
760 763 >
761 764 > def extsetup(ui):
762 765 > help.addtopichook('revsets', rewrite)
763 766 > EOF
764 767 $ echo '[extensions]' >> $HGRCPATH
765 768 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
766 769 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
767 770 $ hg help revsets | grep helphook
768 771 helphook1
769 772 helphook2
General Comments 0
You need to be logged in to leave comments. Login now