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