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