##// END OF EJS Templates
pager: move more behavior into core...
Augie Fackler -
r30993:9c2977ce default
parent child Browse files
Show More
@@ -1,121 +1,107 b''
1 1 # pager.py - display output using a pager
2 2 #
3 3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7 #
8 8 # To load the extension, add it to your configuration file:
9 9 #
10 10 # [extension]
11 11 # pager =
12 12 #
13 13 # Run 'hg help pager' to get info on configuration.
14 14
15 15 '''browse command output with an external pager
16 16
17 17 To set the pager that should be used, set the application variable::
18 18
19 19 [pager]
20 20 pager = less -FRX
21 21
22 22 If no pager is set, the pager extensions uses the environment variable
23 23 $PAGER. If neither pager.pager, nor $PAGER is set, no pager is used.
24 24
25 25 You can disable the pager for certain commands by adding them to the
26 26 pager.ignore list::
27 27
28 28 [pager]
29 29 ignore = version, help, update
30 30
31 31 You can also enable the pager only for certain commands using
32 32 pager.attend. Below is the default list of commands to be paged::
33 33
34 34 [pager]
35 35 attend = annotate, cat, diff, export, glog, log, qdiff
36 36
37 37 Setting pager.attend to an empty value will cause all commands to be
38 38 paged.
39 39
40 40 If pager.attend is present, pager.ignore will be ignored.
41 41
42 42 Lastly, you can enable and disable paging for individual commands with
43 43 the attend-<command> option. This setting takes precedence over
44 44 existing attend and ignore options and defaults::
45 45
46 46 [pager]
47 47 attend-cat = false
48 48
49 49 To ignore global commands like :hg:`version` or :hg:`help`, you have
50 50 to specify them in your user configuration file.
51 51
52 52 To control whether the pager is used at all for an individual command,
53 53 you can use --pager=<value>::
54 54
55 55 - use as needed: `auto`.
56 56 - require the pager: `yes` or `on`.
57 57 - suppress the pager: `no` or `off` (any unrecognized value
58 58 will also work).
59 59
60 60 '''
61 61 from __future__ import absolute_import
62 62
63 from mercurial.i18n import _
64 63 from mercurial import (
65 64 cmdutil,
66 65 commands,
67 66 dispatch,
68 67 extensions,
69 util,
70 68 )
71 69
72 70 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
73 71 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
74 72 # be specifying the version(s) of Mercurial they are tested with, or
75 73 # leave the attribute unspecified.
76 74 testedwith = 'ships-with-hg-core'
77 75
78 76 def uisetup(ui):
79 77
80 78 def pagecmd(orig, ui, options, cmd, cmdfunc):
81 usepager = False
82 always = util.parsebool(options['pager'])
83 79 auto = options['pager'] == 'auto'
84
85 if always:
86 usepager = True
87 elif not auto:
80 if auto and not ui.pageractive:
88 81 usepager = False
89 else:
90 82 attend = ui.configlist('pager', 'attend', attended)
91 83 ignore = ui.configlist('pager', 'ignore')
92 84 cmds, _ = cmdutil.findcmd(cmd, commands.table)
93 85
94 86 for cmd in cmds:
95 87 var = 'attend-%s' % cmd
96 88 if ui.config('pager', var):
97 89 usepager = ui.configbool('pager', var)
98 90 break
99 91 if (cmd in attend or
100 92 (cmd not in ignore and not attend)):
101 93 usepager = True
102 94 break
103 95
104 if usepager:
105 ui.pager('extension-via-attend-' + cmd)
96 if usepager:
97 ui.pager('extension-via-attend-' + cmd)
106 98 return orig(ui, options, cmd, cmdfunc)
107 99
108 100 # Wrap dispatch._runcommand after color is loaded so color can see
109 101 # ui.pageractive. Otherwise, if we loaded first, color's wrapped
110 102 # dispatch._runcommand would run without having access to ui.pageractive.
111 103 def afterloaded(loaded):
112 104 extensions.wrapfunction(dispatch, '_runcommand', pagecmd)
113 105 extensions.afterloaded('color', afterloaded)
114 106
115 def extsetup(ui):
116 commands.globalopts.append(
117 ('', 'pager', 'auto',
118 _("when to paginate (boolean, always, auto, or never)"),
119 _('TYPE')))
120
121 107 attended = ['annotate', 'cat', 'diff', 'export', 'glog', 'log', 'qdiff']
@@ -1,5440 +1,5442 b''
1 1 # commands.py - command processing for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import
9 9
10 10 import difflib
11 11 import errno
12 12 import os
13 13 import re
14 14
15 15 from .i18n import _
16 16 from .node import (
17 17 hex,
18 18 nullid,
19 19 nullrev,
20 20 short,
21 21 )
22 22 from . import (
23 23 archival,
24 24 bookmarks,
25 25 bundle2,
26 26 changegroup,
27 27 cmdutil,
28 28 copies,
29 29 destutil,
30 30 dirstateguard,
31 31 discovery,
32 32 encoding,
33 33 error,
34 34 exchange,
35 35 extensions,
36 36 graphmod,
37 37 hbisect,
38 38 help,
39 39 hg,
40 40 lock as lockmod,
41 41 merge as mergemod,
42 42 minirst,
43 43 obsolete,
44 44 patch,
45 45 phases,
46 46 pycompat,
47 47 revset,
48 48 scmutil,
49 49 server,
50 50 sshserver,
51 51 streamclone,
52 52 templatekw,
53 53 ui as uimod,
54 54 util,
55 55 )
56 56
57 57 release = lockmod.release
58 58
59 59 table = {}
60 60
61 61 command = cmdutil.command(table)
62 62
63 63 # label constants
64 64 # until 3.5, bookmarks.current was the advertised name, not
65 65 # bookmarks.active, so we must use both to avoid breaking old
66 66 # custom styles
67 67 activebookmarklabel = 'bookmarks.active bookmarks.current'
68 68
69 69 # common command options
70 70
71 71 globalopts = [
72 72 ('R', 'repository', '',
73 73 _('repository root directory or name of overlay bundle file'),
74 74 _('REPO')),
75 75 ('', 'cwd', '',
76 76 _('change working directory'), _('DIR')),
77 77 ('y', 'noninteractive', None,
78 78 _('do not prompt, automatically pick the first choice for all prompts')),
79 79 ('q', 'quiet', None, _('suppress output')),
80 80 ('v', 'verbose', None, _('enable additional output')),
81 81 ('', 'config', [],
82 82 _('set/override config option (use \'section.name=value\')'),
83 83 _('CONFIG')),
84 84 ('', 'debug', None, _('enable debugging output')),
85 85 ('', 'debugger', None, _('start debugger')),
86 86 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
87 87 _('ENCODE')),
88 88 ('', 'encodingmode', encoding.encodingmode,
89 89 _('set the charset encoding mode'), _('MODE')),
90 90 ('', 'traceback', None, _('always print a traceback on exception')),
91 91 ('', 'time', None, _('time how long the command takes')),
92 92 ('', 'profile', None, _('print command execution profile')),
93 93 ('', 'version', None, _('output version information and exit')),
94 94 ('h', 'help', None, _('display help and exit')),
95 95 ('', 'hidden', False, _('consider hidden changesets')),
96 ('', 'pager', 'auto',
97 _("when to paginate (boolean, always, auto, or never)"), _('TYPE')),
96 98 ]
97 99
98 100 dryrunopts = [('n', 'dry-run', None,
99 101 _('do not perform actions, just print output'))]
100 102
101 103 remoteopts = [
102 104 ('e', 'ssh', '',
103 105 _('specify ssh command to use'), _('CMD')),
104 106 ('', 'remotecmd', '',
105 107 _('specify hg command to run on the remote side'), _('CMD')),
106 108 ('', 'insecure', None,
107 109 _('do not verify server certificate (ignoring web.cacerts config)')),
108 110 ]
109 111
110 112 walkopts = [
111 113 ('I', 'include', [],
112 114 _('include names matching the given patterns'), _('PATTERN')),
113 115 ('X', 'exclude', [],
114 116 _('exclude names matching the given patterns'), _('PATTERN')),
115 117 ]
116 118
117 119 commitopts = [
118 120 ('m', 'message', '',
119 121 _('use text as commit message'), _('TEXT')),
120 122 ('l', 'logfile', '',
121 123 _('read commit message from file'), _('FILE')),
122 124 ]
123 125
124 126 commitopts2 = [
125 127 ('d', 'date', '',
126 128 _('record the specified date as commit date'), _('DATE')),
127 129 ('u', 'user', '',
128 130 _('record the specified user as committer'), _('USER')),
129 131 ]
130 132
131 133 # hidden for now
132 134 formatteropts = [
133 135 ('T', 'template', '',
134 136 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
135 137 ]
136 138
137 139 templateopts = [
138 140 ('', 'style', '',
139 141 _('display using template map file (DEPRECATED)'), _('STYLE')),
140 142 ('T', 'template', '',
141 143 _('display with template'), _('TEMPLATE')),
142 144 ]
143 145
144 146 logopts = [
145 147 ('p', 'patch', None, _('show patch')),
146 148 ('g', 'git', None, _('use git extended diff format')),
147 149 ('l', 'limit', '',
148 150 _('limit number of changes displayed'), _('NUM')),
149 151 ('M', 'no-merges', None, _('do not show merges')),
150 152 ('', 'stat', None, _('output diffstat-style summary of changes')),
151 153 ('G', 'graph', None, _("show the revision DAG")),
152 154 ] + templateopts
153 155
154 156 diffopts = [
155 157 ('a', 'text', None, _('treat all files as text')),
156 158 ('g', 'git', None, _('use git extended diff format')),
157 159 ('', 'nodates', None, _('omit dates from diff headers'))
158 160 ]
159 161
160 162 diffwsopts = [
161 163 ('w', 'ignore-all-space', None,
162 164 _('ignore white space when comparing lines')),
163 165 ('b', 'ignore-space-change', None,
164 166 _('ignore changes in the amount of white space')),
165 167 ('B', 'ignore-blank-lines', None,
166 168 _('ignore changes whose lines are all blank')),
167 169 ]
168 170
169 171 diffopts2 = [
170 172 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
171 173 ('p', 'show-function', None, _('show which function each change is in')),
172 174 ('', 'reverse', None, _('produce a diff that undoes the changes')),
173 175 ] + diffwsopts + [
174 176 ('U', 'unified', '',
175 177 _('number of lines of context to show'), _('NUM')),
176 178 ('', 'stat', None, _('output diffstat-style summary of changes')),
177 179 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
178 180 ]
179 181
180 182 mergetoolopts = [
181 183 ('t', 'tool', '', _('specify merge tool')),
182 184 ]
183 185
184 186 similarityopts = [
185 187 ('s', 'similarity', '',
186 188 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
187 189 ]
188 190
189 191 subrepoopts = [
190 192 ('S', 'subrepos', None,
191 193 _('recurse into subrepositories'))
192 194 ]
193 195
194 196 debugrevlogopts = [
195 197 ('c', 'changelog', False, _('open changelog')),
196 198 ('m', 'manifest', False, _('open manifest')),
197 199 ('', 'dir', '', _('open directory manifest')),
198 200 ]
199 201
200 202 # Commands start here, listed alphabetically
201 203
202 204 @command('^add',
203 205 walkopts + subrepoopts + dryrunopts,
204 206 _('[OPTION]... [FILE]...'),
205 207 inferrepo=True)
206 208 def add(ui, repo, *pats, **opts):
207 209 """add the specified files on the next commit
208 210
209 211 Schedule files to be version controlled and added to the
210 212 repository.
211 213
212 214 The files will be added to the repository at the next commit. To
213 215 undo an add before that, see :hg:`forget`.
214 216
215 217 If no names are given, add all files to the repository (except
216 218 files matching ``.hgignore``).
217 219
218 220 .. container:: verbose
219 221
220 222 Examples:
221 223
222 224 - New (unknown) files are added
223 225 automatically by :hg:`add`::
224 226
225 227 $ ls
226 228 foo.c
227 229 $ hg status
228 230 ? foo.c
229 231 $ hg add
230 232 adding foo.c
231 233 $ hg status
232 234 A foo.c
233 235
234 236 - Specific files to be added can be specified::
235 237
236 238 $ ls
237 239 bar.c foo.c
238 240 $ hg status
239 241 ? bar.c
240 242 ? foo.c
241 243 $ hg add bar.c
242 244 $ hg status
243 245 A bar.c
244 246 ? foo.c
245 247
246 248 Returns 0 if all files are successfully added.
247 249 """
248 250
249 251 m = scmutil.match(repo[None], pats, opts)
250 252 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
251 253 return rejected and 1 or 0
252 254
253 255 @command('addremove',
254 256 similarityopts + subrepoopts + walkopts + dryrunopts,
255 257 _('[OPTION]... [FILE]...'),
256 258 inferrepo=True)
257 259 def addremove(ui, repo, *pats, **opts):
258 260 """add all new files, delete all missing files
259 261
260 262 Add all new files and remove all missing files from the
261 263 repository.
262 264
263 265 Unless names are given, new files are ignored if they match any of
264 266 the patterns in ``.hgignore``. As with add, these changes take
265 267 effect at the next commit.
266 268
267 269 Use the -s/--similarity option to detect renamed files. This
268 270 option takes a percentage between 0 (disabled) and 100 (files must
269 271 be identical) as its parameter. With a parameter greater than 0,
270 272 this compares every removed file with every added file and records
271 273 those similar enough as renames. Detecting renamed files this way
272 274 can be expensive. After using this option, :hg:`status -C` can be
273 275 used to check which files were identified as moved or renamed. If
274 276 not specified, -s/--similarity defaults to 100 and only renames of
275 277 identical files are detected.
276 278
277 279 .. container:: verbose
278 280
279 281 Examples:
280 282
281 283 - A number of files (bar.c and foo.c) are new,
282 284 while foobar.c has been removed (without using :hg:`remove`)
283 285 from the repository::
284 286
285 287 $ ls
286 288 bar.c foo.c
287 289 $ hg status
288 290 ! foobar.c
289 291 ? bar.c
290 292 ? foo.c
291 293 $ hg addremove
292 294 adding bar.c
293 295 adding foo.c
294 296 removing foobar.c
295 297 $ hg status
296 298 A bar.c
297 299 A foo.c
298 300 R foobar.c
299 301
300 302 - A file foobar.c was moved to foo.c without using :hg:`rename`.
301 303 Afterwards, it was edited slightly::
302 304
303 305 $ ls
304 306 foo.c
305 307 $ hg status
306 308 ! foobar.c
307 309 ? foo.c
308 310 $ hg addremove --similarity 90
309 311 removing foobar.c
310 312 adding foo.c
311 313 recording removal of foobar.c as rename to foo.c (94% similar)
312 314 $ hg status -C
313 315 A foo.c
314 316 foobar.c
315 317 R foobar.c
316 318
317 319 Returns 0 if all files are successfully added.
318 320 """
319 321 try:
320 322 sim = float(opts.get('similarity') or 100)
321 323 except ValueError:
322 324 raise error.Abort(_('similarity must be a number'))
323 325 if sim < 0 or sim > 100:
324 326 raise error.Abort(_('similarity must be between 0 and 100'))
325 327 matcher = scmutil.match(repo[None], pats, opts)
326 328 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
327 329
328 330 @command('^annotate|blame',
329 331 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
330 332 ('', 'follow', None,
331 333 _('follow copies/renames and list the filename (DEPRECATED)')),
332 334 ('', 'no-follow', None, _("don't follow copies and renames")),
333 335 ('a', 'text', None, _('treat all files as text')),
334 336 ('u', 'user', None, _('list the author (long with -v)')),
335 337 ('f', 'file', None, _('list the filename')),
336 338 ('d', 'date', None, _('list the date (short with -q)')),
337 339 ('n', 'number', None, _('list the revision number (default)')),
338 340 ('c', 'changeset', None, _('list the changeset')),
339 341 ('l', 'line-number', None, _('show line number at the first appearance'))
340 342 ] + diffwsopts + walkopts + formatteropts,
341 343 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
342 344 inferrepo=True)
343 345 def annotate(ui, repo, *pats, **opts):
344 346 """show changeset information by line for each file
345 347
346 348 List changes in files, showing the revision id responsible for
347 349 each line.
348 350
349 351 This command is useful for discovering when a change was made and
350 352 by whom.
351 353
352 354 If you include --file, --user, or --date, the revision number is
353 355 suppressed unless you also include --number.
354 356
355 357 Without the -a/--text option, annotate will avoid processing files
356 358 it detects as binary. With -a, annotate will annotate the file
357 359 anyway, although the results will probably be neither useful
358 360 nor desirable.
359 361
360 362 Returns 0 on success.
361 363 """
362 364 if not pats:
363 365 raise error.Abort(_('at least one filename or pattern is required'))
364 366
365 367 if opts.get('follow'):
366 368 # --follow is deprecated and now just an alias for -f/--file
367 369 # to mimic the behavior of Mercurial before version 1.5
368 370 opts['file'] = True
369 371
370 372 ctx = scmutil.revsingle(repo, opts.get('rev'))
371 373
372 374 fm = ui.formatter('annotate', opts)
373 375 if ui.quiet:
374 376 datefunc = util.shortdate
375 377 else:
376 378 datefunc = util.datestr
377 379 if ctx.rev() is None:
378 380 def hexfn(node):
379 381 if node is None:
380 382 return None
381 383 else:
382 384 return fm.hexfunc(node)
383 385 if opts.get('changeset'):
384 386 # omit "+" suffix which is appended to node hex
385 387 def formatrev(rev):
386 388 if rev is None:
387 389 return '%d' % ctx.p1().rev()
388 390 else:
389 391 return '%d' % rev
390 392 else:
391 393 def formatrev(rev):
392 394 if rev is None:
393 395 return '%d+' % ctx.p1().rev()
394 396 else:
395 397 return '%d ' % rev
396 398 def formathex(hex):
397 399 if hex is None:
398 400 return '%s+' % fm.hexfunc(ctx.p1().node())
399 401 else:
400 402 return '%s ' % hex
401 403 else:
402 404 hexfn = fm.hexfunc
403 405 formatrev = formathex = str
404 406
405 407 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
406 408 ('number', ' ', lambda x: x[0].rev(), formatrev),
407 409 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
408 410 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
409 411 ('file', ' ', lambda x: x[0].path(), str),
410 412 ('line_number', ':', lambda x: x[1], str),
411 413 ]
412 414 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
413 415
414 416 if (not opts.get('user') and not opts.get('changeset')
415 417 and not opts.get('date') and not opts.get('file')):
416 418 opts['number'] = True
417 419
418 420 linenumber = opts.get('line_number') is not None
419 421 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
420 422 raise error.Abort(_('at least one of -n/-c is required for -l'))
421 423
422 424 if fm.isplain():
423 425 def makefunc(get, fmt):
424 426 return lambda x: fmt(get(x))
425 427 else:
426 428 def makefunc(get, fmt):
427 429 return get
428 430 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
429 431 if opts.get(op)]
430 432 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
431 433 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
432 434 if opts.get(op))
433 435
434 436 def bad(x, y):
435 437 raise error.Abort("%s: %s" % (x, y))
436 438
437 439 m = scmutil.match(ctx, pats, opts, badfn=bad)
438 440
439 441 follow = not opts.get('no_follow')
440 442 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
441 443 whitespace=True)
442 444 for abs in ctx.walk(m):
443 445 fctx = ctx[abs]
444 446 if not opts.get('text') and util.binary(fctx.data()):
445 447 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
446 448 continue
447 449
448 450 lines = fctx.annotate(follow=follow, linenumber=linenumber,
449 451 diffopts=diffopts)
450 452 if not lines:
451 453 continue
452 454 formats = []
453 455 pieces = []
454 456
455 457 for f, sep in funcmap:
456 458 l = [f(n) for n, dummy in lines]
457 459 if fm.isplain():
458 460 sizes = [encoding.colwidth(x) for x in l]
459 461 ml = max(sizes)
460 462 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
461 463 else:
462 464 formats.append(['%s' for x in l])
463 465 pieces.append(l)
464 466
465 467 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
466 468 fm.startitem()
467 469 fm.write(fields, "".join(f), *p)
468 470 fm.write('line', ": %s", l[1])
469 471
470 472 if not lines[-1][1].endswith('\n'):
471 473 fm.plain('\n')
472 474
473 475 fm.end()
474 476
475 477 @command('archive',
476 478 [('', 'no-decode', None, _('do not pass files through decoders')),
477 479 ('p', 'prefix', '', _('directory prefix for files in archive'),
478 480 _('PREFIX')),
479 481 ('r', 'rev', '', _('revision to distribute'), _('REV')),
480 482 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
481 483 ] + subrepoopts + walkopts,
482 484 _('[OPTION]... DEST'))
483 485 def archive(ui, repo, dest, **opts):
484 486 '''create an unversioned archive of a repository revision
485 487
486 488 By default, the revision used is the parent of the working
487 489 directory; use -r/--rev to specify a different revision.
488 490
489 491 The archive type is automatically detected based on file
490 492 extension (to override, use -t/--type).
491 493
492 494 .. container:: verbose
493 495
494 496 Examples:
495 497
496 498 - create a zip file containing the 1.0 release::
497 499
498 500 hg archive -r 1.0 project-1.0.zip
499 501
500 502 - create a tarball excluding .hg files::
501 503
502 504 hg archive project.tar.gz -X ".hg*"
503 505
504 506 Valid types are:
505 507
506 508 :``files``: a directory full of files (default)
507 509 :``tar``: tar archive, uncompressed
508 510 :``tbz2``: tar archive, compressed using bzip2
509 511 :``tgz``: tar archive, compressed using gzip
510 512 :``uzip``: zip archive, uncompressed
511 513 :``zip``: zip archive, compressed using deflate
512 514
513 515 The exact name of the destination archive or directory is given
514 516 using a format string; see :hg:`help export` for details.
515 517
516 518 Each member added to an archive file has a directory prefix
517 519 prepended. Use -p/--prefix to specify a format string for the
518 520 prefix. The default is the basename of the archive, with suffixes
519 521 removed.
520 522
521 523 Returns 0 on success.
522 524 '''
523 525
524 526 ctx = scmutil.revsingle(repo, opts.get('rev'))
525 527 if not ctx:
526 528 raise error.Abort(_('no working directory: please specify a revision'))
527 529 node = ctx.node()
528 530 dest = cmdutil.makefilename(repo, dest, node)
529 531 if os.path.realpath(dest) == repo.root:
530 532 raise error.Abort(_('repository root cannot be destination'))
531 533
532 534 kind = opts.get('type') or archival.guesskind(dest) or 'files'
533 535 prefix = opts.get('prefix')
534 536
535 537 if dest == '-':
536 538 if kind == 'files':
537 539 raise error.Abort(_('cannot archive plain files to stdout'))
538 540 dest = cmdutil.makefileobj(repo, dest)
539 541 if not prefix:
540 542 prefix = os.path.basename(repo.root) + '-%h'
541 543
542 544 prefix = cmdutil.makefilename(repo, prefix, node)
543 545 matchfn = scmutil.match(ctx, [], opts)
544 546 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
545 547 matchfn, prefix, subrepos=opts.get('subrepos'))
546 548
547 549 @command('backout',
548 550 [('', 'merge', None, _('merge with old dirstate parent after backout')),
549 551 ('', 'commit', None,
550 552 _('commit if no conflicts were encountered (DEPRECATED)')),
551 553 ('', 'no-commit', None, _('do not commit')),
552 554 ('', 'parent', '',
553 555 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
554 556 ('r', 'rev', '', _('revision to backout'), _('REV')),
555 557 ('e', 'edit', False, _('invoke editor on commit messages')),
556 558 ] + mergetoolopts + walkopts + commitopts + commitopts2,
557 559 _('[OPTION]... [-r] REV'))
558 560 def backout(ui, repo, node=None, rev=None, **opts):
559 561 '''reverse effect of earlier changeset
560 562
561 563 Prepare a new changeset with the effect of REV undone in the
562 564 current working directory. If no conflicts were encountered,
563 565 it will be committed immediately.
564 566
565 567 If REV is the parent of the working directory, then this new changeset
566 568 is committed automatically (unless --no-commit is specified).
567 569
568 570 .. note::
569 571
570 572 :hg:`backout` cannot be used to fix either an unwanted or
571 573 incorrect merge.
572 574
573 575 .. container:: verbose
574 576
575 577 Examples:
576 578
577 579 - Reverse the effect of the parent of the working directory.
578 580 This backout will be committed immediately::
579 581
580 582 hg backout -r .
581 583
582 584 - Reverse the effect of previous bad revision 23::
583 585
584 586 hg backout -r 23
585 587
586 588 - Reverse the effect of previous bad revision 23 and
587 589 leave changes uncommitted::
588 590
589 591 hg backout -r 23 --no-commit
590 592 hg commit -m "Backout revision 23"
591 593
592 594 By default, the pending changeset will have one parent,
593 595 maintaining a linear history. With --merge, the pending
594 596 changeset will instead have two parents: the old parent of the
595 597 working directory and a new child of REV that simply undoes REV.
596 598
597 599 Before version 1.7, the behavior without --merge was equivalent
598 600 to specifying --merge followed by :hg:`update --clean .` to
599 601 cancel the merge and leave the child of REV as a head to be
600 602 merged separately.
601 603
602 604 See :hg:`help dates` for a list of formats valid for -d/--date.
603 605
604 606 See :hg:`help revert` for a way to restore files to the state
605 607 of another revision.
606 608
607 609 Returns 0 on success, 1 if nothing to backout or there are unresolved
608 610 files.
609 611 '''
610 612 wlock = lock = None
611 613 try:
612 614 wlock = repo.wlock()
613 615 lock = repo.lock()
614 616 return _dobackout(ui, repo, node, rev, **opts)
615 617 finally:
616 618 release(lock, wlock)
617 619
618 620 def _dobackout(ui, repo, node=None, rev=None, **opts):
619 621 if opts.get('commit') and opts.get('no_commit'):
620 622 raise error.Abort(_("cannot use --commit with --no-commit"))
621 623 if opts.get('merge') and opts.get('no_commit'):
622 624 raise error.Abort(_("cannot use --merge with --no-commit"))
623 625
624 626 if rev and node:
625 627 raise error.Abort(_("please specify just one revision"))
626 628
627 629 if not rev:
628 630 rev = node
629 631
630 632 if not rev:
631 633 raise error.Abort(_("please specify a revision to backout"))
632 634
633 635 date = opts.get('date')
634 636 if date:
635 637 opts['date'] = util.parsedate(date)
636 638
637 639 cmdutil.checkunfinished(repo)
638 640 cmdutil.bailifchanged(repo)
639 641 node = scmutil.revsingle(repo, rev).node()
640 642
641 643 op1, op2 = repo.dirstate.parents()
642 644 if not repo.changelog.isancestor(node, op1):
643 645 raise error.Abort(_('cannot backout change that is not an ancestor'))
644 646
645 647 p1, p2 = repo.changelog.parents(node)
646 648 if p1 == nullid:
647 649 raise error.Abort(_('cannot backout a change with no parents'))
648 650 if p2 != nullid:
649 651 if not opts.get('parent'):
650 652 raise error.Abort(_('cannot backout a merge changeset'))
651 653 p = repo.lookup(opts['parent'])
652 654 if p not in (p1, p2):
653 655 raise error.Abort(_('%s is not a parent of %s') %
654 656 (short(p), short(node)))
655 657 parent = p
656 658 else:
657 659 if opts.get('parent'):
658 660 raise error.Abort(_('cannot use --parent on non-merge changeset'))
659 661 parent = p1
660 662
661 663 # the backout should appear on the same branch
662 664 branch = repo.dirstate.branch()
663 665 bheads = repo.branchheads(branch)
664 666 rctx = scmutil.revsingle(repo, hex(parent))
665 667 if not opts.get('merge') and op1 != node:
666 668 dsguard = dirstateguard.dirstateguard(repo, 'backout')
667 669 try:
668 670 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
669 671 'backout')
670 672 stats = mergemod.update(repo, parent, True, True, node, False)
671 673 repo.setparents(op1, op2)
672 674 dsguard.close()
673 675 hg._showstats(repo, stats)
674 676 if stats[3]:
675 677 repo.ui.status(_("use 'hg resolve' to retry unresolved "
676 678 "file merges\n"))
677 679 return 1
678 680 finally:
679 681 ui.setconfig('ui', 'forcemerge', '', '')
680 682 lockmod.release(dsguard)
681 683 else:
682 684 hg.clean(repo, node, show_stats=False)
683 685 repo.dirstate.setbranch(branch)
684 686 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
685 687
686 688 if opts.get('no_commit'):
687 689 msg = _("changeset %s backed out, "
688 690 "don't forget to commit.\n")
689 691 ui.status(msg % short(node))
690 692 return 0
691 693
692 694 def commitfunc(ui, repo, message, match, opts):
693 695 editform = 'backout'
694 696 e = cmdutil.getcommiteditor(editform=editform, **opts)
695 697 if not message:
696 698 # we don't translate commit messages
697 699 message = "Backed out changeset %s" % short(node)
698 700 e = cmdutil.getcommiteditor(edit=True, editform=editform)
699 701 return repo.commit(message, opts.get('user'), opts.get('date'),
700 702 match, editor=e)
701 703 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
702 704 if not newnode:
703 705 ui.status(_("nothing changed\n"))
704 706 return 1
705 707 cmdutil.commitstatus(repo, newnode, branch, bheads)
706 708
707 709 def nice(node):
708 710 return '%d:%s' % (repo.changelog.rev(node), short(node))
709 711 ui.status(_('changeset %s backs out changeset %s\n') %
710 712 (nice(repo.changelog.tip()), nice(node)))
711 713 if opts.get('merge') and op1 != node:
712 714 hg.clean(repo, op1, show_stats=False)
713 715 ui.status(_('merging with changeset %s\n')
714 716 % nice(repo.changelog.tip()))
715 717 try:
716 718 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
717 719 'backout')
718 720 return hg.merge(repo, hex(repo.changelog.tip()))
719 721 finally:
720 722 ui.setconfig('ui', 'forcemerge', '', '')
721 723 return 0
722 724
723 725 @command('bisect',
724 726 [('r', 'reset', False, _('reset bisect state')),
725 727 ('g', 'good', False, _('mark changeset good')),
726 728 ('b', 'bad', False, _('mark changeset bad')),
727 729 ('s', 'skip', False, _('skip testing changeset')),
728 730 ('e', 'extend', False, _('extend the bisect range')),
729 731 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
730 732 ('U', 'noupdate', False, _('do not update to target'))],
731 733 _("[-gbsr] [-U] [-c CMD] [REV]"))
732 734 def bisect(ui, repo, rev=None, extra=None, command=None,
733 735 reset=None, good=None, bad=None, skip=None, extend=None,
734 736 noupdate=None):
735 737 """subdivision search of changesets
736 738
737 739 This command helps to find changesets which introduce problems. To
738 740 use, mark the earliest changeset you know exhibits the problem as
739 741 bad, then mark the latest changeset which is free from the problem
740 742 as good. Bisect will update your working directory to a revision
741 743 for testing (unless the -U/--noupdate option is specified). Once
742 744 you have performed tests, mark the working directory as good or
743 745 bad, and bisect will either update to another candidate changeset
744 746 or announce that it has found the bad revision.
745 747
746 748 As a shortcut, you can also use the revision argument to mark a
747 749 revision as good or bad without checking it out first.
748 750
749 751 If you supply a command, it will be used for automatic bisection.
750 752 The environment variable HG_NODE will contain the ID of the
751 753 changeset being tested. The exit status of the command will be
752 754 used to mark revisions as good or bad: status 0 means good, 125
753 755 means to skip the revision, 127 (command not found) will abort the
754 756 bisection, and any other non-zero exit status means the revision
755 757 is bad.
756 758
757 759 .. container:: verbose
758 760
759 761 Some examples:
760 762
761 763 - start a bisection with known bad revision 34, and good revision 12::
762 764
763 765 hg bisect --bad 34
764 766 hg bisect --good 12
765 767
766 768 - advance the current bisection by marking current revision as good or
767 769 bad::
768 770
769 771 hg bisect --good
770 772 hg bisect --bad
771 773
772 774 - mark the current revision, or a known revision, to be skipped (e.g. if
773 775 that revision is not usable because of another issue)::
774 776
775 777 hg bisect --skip
776 778 hg bisect --skip 23
777 779
778 780 - skip all revisions that do not touch directories ``foo`` or ``bar``::
779 781
780 782 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
781 783
782 784 - forget the current bisection::
783 785
784 786 hg bisect --reset
785 787
786 788 - use 'make && make tests' to automatically find the first broken
787 789 revision::
788 790
789 791 hg bisect --reset
790 792 hg bisect --bad 34
791 793 hg bisect --good 12
792 794 hg bisect --command "make && make tests"
793 795
794 796 - see all changesets whose states are already known in the current
795 797 bisection::
796 798
797 799 hg log -r "bisect(pruned)"
798 800
799 801 - see the changeset currently being bisected (especially useful
800 802 if running with -U/--noupdate)::
801 803
802 804 hg log -r "bisect(current)"
803 805
804 806 - see all changesets that took part in the current bisection::
805 807
806 808 hg log -r "bisect(range)"
807 809
808 810 - you can even get a nice graph::
809 811
810 812 hg log --graph -r "bisect(range)"
811 813
812 814 See :hg:`help revisions.bisect` for more about the `bisect()` predicate.
813 815
814 816 Returns 0 on success.
815 817 """
816 818 # backward compatibility
817 819 if rev in "good bad reset init".split():
818 820 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
819 821 cmd, rev, extra = rev, extra, None
820 822 if cmd == "good":
821 823 good = True
822 824 elif cmd == "bad":
823 825 bad = True
824 826 else:
825 827 reset = True
826 828 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
827 829 raise error.Abort(_('incompatible arguments'))
828 830
829 831 cmdutil.checkunfinished(repo)
830 832
831 833 if reset:
832 834 hbisect.resetstate(repo)
833 835 return
834 836
835 837 state = hbisect.load_state(repo)
836 838
837 839 # update state
838 840 if good or bad or skip:
839 841 if rev:
840 842 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
841 843 else:
842 844 nodes = [repo.lookup('.')]
843 845 if good:
844 846 state['good'] += nodes
845 847 elif bad:
846 848 state['bad'] += nodes
847 849 elif skip:
848 850 state['skip'] += nodes
849 851 hbisect.save_state(repo, state)
850 852 if not (state['good'] and state['bad']):
851 853 return
852 854
853 855 def mayupdate(repo, node, show_stats=True):
854 856 """common used update sequence"""
855 857 if noupdate:
856 858 return
857 859 cmdutil.bailifchanged(repo)
858 860 return hg.clean(repo, node, show_stats=show_stats)
859 861
860 862 displayer = cmdutil.show_changeset(ui, repo, {})
861 863
862 864 if command:
863 865 changesets = 1
864 866 if noupdate:
865 867 try:
866 868 node = state['current'][0]
867 869 except LookupError:
868 870 raise error.Abort(_('current bisect revision is unknown - '
869 871 'start a new bisect to fix'))
870 872 else:
871 873 node, p2 = repo.dirstate.parents()
872 874 if p2 != nullid:
873 875 raise error.Abort(_('current bisect revision is a merge'))
874 876 if rev:
875 877 node = repo[scmutil.revsingle(repo, rev, node)].node()
876 878 try:
877 879 while changesets:
878 880 # update state
879 881 state['current'] = [node]
880 882 hbisect.save_state(repo, state)
881 883 status = ui.system(command, environ={'HG_NODE': hex(node)})
882 884 if status == 125:
883 885 transition = "skip"
884 886 elif status == 0:
885 887 transition = "good"
886 888 # status < 0 means process was killed
887 889 elif status == 127:
888 890 raise error.Abort(_("failed to execute %s") % command)
889 891 elif status < 0:
890 892 raise error.Abort(_("%s killed") % command)
891 893 else:
892 894 transition = "bad"
893 895 state[transition].append(node)
894 896 ctx = repo[node]
895 897 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
896 898 hbisect.checkstate(state)
897 899 # bisect
898 900 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
899 901 # update to next check
900 902 node = nodes[0]
901 903 mayupdate(repo, node, show_stats=False)
902 904 finally:
903 905 state['current'] = [node]
904 906 hbisect.save_state(repo, state)
905 907 hbisect.printresult(ui, repo, state, displayer, nodes, bgood)
906 908 return
907 909
908 910 hbisect.checkstate(state)
909 911
910 912 # actually bisect
911 913 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
912 914 if extend:
913 915 if not changesets:
914 916 extendnode = hbisect.extendrange(repo, state, nodes, good)
915 917 if extendnode is not None:
916 918 ui.write(_("Extending search to changeset %d:%s\n")
917 919 % (extendnode.rev(), extendnode))
918 920 state['current'] = [extendnode.node()]
919 921 hbisect.save_state(repo, state)
920 922 return mayupdate(repo, extendnode.node())
921 923 raise error.Abort(_("nothing to extend"))
922 924
923 925 if changesets == 0:
924 926 hbisect.printresult(ui, repo, state, displayer, nodes, good)
925 927 else:
926 928 assert len(nodes) == 1 # only a single node can be tested next
927 929 node = nodes[0]
928 930 # compute the approximate number of remaining tests
929 931 tests, size = 0, 2
930 932 while size <= changesets:
931 933 tests, size = tests + 1, size * 2
932 934 rev = repo.changelog.rev(node)
933 935 ui.write(_("Testing changeset %d:%s "
934 936 "(%d changesets remaining, ~%d tests)\n")
935 937 % (rev, short(node), changesets, tests))
936 938 state['current'] = [node]
937 939 hbisect.save_state(repo, state)
938 940 return mayupdate(repo, node)
939 941
940 942 @command('bookmarks|bookmark',
941 943 [('f', 'force', False, _('force')),
942 944 ('r', 'rev', '', _('revision for bookmark action'), _('REV')),
943 945 ('d', 'delete', False, _('delete a given bookmark')),
944 946 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
945 947 ('i', 'inactive', False, _('mark a bookmark inactive')),
946 948 ] + formatteropts,
947 949 _('hg bookmarks [OPTIONS]... [NAME]...'))
948 950 def bookmark(ui, repo, *names, **opts):
949 951 '''create a new bookmark or list existing bookmarks
950 952
951 953 Bookmarks are labels on changesets to help track lines of development.
952 954 Bookmarks are unversioned and can be moved, renamed and deleted.
953 955 Deleting or moving a bookmark has no effect on the associated changesets.
954 956
955 957 Creating or updating to a bookmark causes it to be marked as 'active'.
956 958 The active bookmark is indicated with a '*'.
957 959 When a commit is made, the active bookmark will advance to the new commit.
958 960 A plain :hg:`update` will also advance an active bookmark, if possible.
959 961 Updating away from a bookmark will cause it to be deactivated.
960 962
961 963 Bookmarks can be pushed and pulled between repositories (see
962 964 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
963 965 diverged, a new 'divergent bookmark' of the form 'name@path' will
964 966 be created. Using :hg:`merge` will resolve the divergence.
965 967
966 968 A bookmark named '@' has the special property that :hg:`clone` will
967 969 check it out by default if it exists.
968 970
969 971 .. container:: verbose
970 972
971 973 Examples:
972 974
973 975 - create an active bookmark for a new line of development::
974 976
975 977 hg book new-feature
976 978
977 979 - create an inactive bookmark as a place marker::
978 980
979 981 hg book -i reviewed
980 982
981 983 - create an inactive bookmark on another changeset::
982 984
983 985 hg book -r .^ tested
984 986
985 987 - rename bookmark turkey to dinner::
986 988
987 989 hg book -m turkey dinner
988 990
989 991 - move the '@' bookmark from another branch::
990 992
991 993 hg book -f @
992 994 '''
993 995 force = opts.get('force')
994 996 rev = opts.get('rev')
995 997 delete = opts.get('delete')
996 998 rename = opts.get('rename')
997 999 inactive = opts.get('inactive')
998 1000
999 1001 def checkformat(mark):
1000 1002 mark = mark.strip()
1001 1003 if not mark:
1002 1004 raise error.Abort(_("bookmark names cannot consist entirely of "
1003 1005 "whitespace"))
1004 1006 scmutil.checknewlabel(repo, mark, 'bookmark')
1005 1007 return mark
1006 1008
1007 1009 def checkconflict(repo, mark, cur, force=False, target=None):
1008 1010 if mark in marks and not force:
1009 1011 if target:
1010 1012 if marks[mark] == target and target == cur:
1011 1013 # re-activating a bookmark
1012 1014 return
1013 1015 anc = repo.changelog.ancestors([repo[target].rev()])
1014 1016 bmctx = repo[marks[mark]]
1015 1017 divs = [repo[b].node() for b in marks
1016 1018 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1017 1019
1018 1020 # allow resolving a single divergent bookmark even if moving
1019 1021 # the bookmark across branches when a revision is specified
1020 1022 # that contains a divergent bookmark
1021 1023 if bmctx.rev() not in anc and target in divs:
1022 1024 bookmarks.deletedivergent(repo, [target], mark)
1023 1025 return
1024 1026
1025 1027 deletefrom = [b for b in divs
1026 1028 if repo[b].rev() in anc or b == target]
1027 1029 bookmarks.deletedivergent(repo, deletefrom, mark)
1028 1030 if bookmarks.validdest(repo, bmctx, repo[target]):
1029 1031 ui.status(_("moving bookmark '%s' forward from %s\n") %
1030 1032 (mark, short(bmctx.node())))
1031 1033 return
1032 1034 raise error.Abort(_("bookmark '%s' already exists "
1033 1035 "(use -f to force)") % mark)
1034 1036 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1035 1037 and not force):
1036 1038 raise error.Abort(
1037 1039 _("a bookmark cannot have the name of an existing branch"))
1038 1040
1039 1041 if delete and rename:
1040 1042 raise error.Abort(_("--delete and --rename are incompatible"))
1041 1043 if delete and rev:
1042 1044 raise error.Abort(_("--rev is incompatible with --delete"))
1043 1045 if rename and rev:
1044 1046 raise error.Abort(_("--rev is incompatible with --rename"))
1045 1047 if not names and (delete or rev):
1046 1048 raise error.Abort(_("bookmark name required"))
1047 1049
1048 1050 if delete or rename or names or inactive:
1049 1051 wlock = lock = tr = None
1050 1052 try:
1051 1053 wlock = repo.wlock()
1052 1054 lock = repo.lock()
1053 1055 cur = repo.changectx('.').node()
1054 1056 marks = repo._bookmarks
1055 1057 if delete:
1056 1058 tr = repo.transaction('bookmark')
1057 1059 for mark in names:
1058 1060 if mark not in marks:
1059 1061 raise error.Abort(_("bookmark '%s' does not exist") %
1060 1062 mark)
1061 1063 if mark == repo._activebookmark:
1062 1064 bookmarks.deactivate(repo)
1063 1065 del marks[mark]
1064 1066
1065 1067 elif rename:
1066 1068 tr = repo.transaction('bookmark')
1067 1069 if not names:
1068 1070 raise error.Abort(_("new bookmark name required"))
1069 1071 elif len(names) > 1:
1070 1072 raise error.Abort(_("only one new bookmark name allowed"))
1071 1073 mark = checkformat(names[0])
1072 1074 if rename not in marks:
1073 1075 raise error.Abort(_("bookmark '%s' does not exist")
1074 1076 % rename)
1075 1077 checkconflict(repo, mark, cur, force)
1076 1078 marks[mark] = marks[rename]
1077 1079 if repo._activebookmark == rename and not inactive:
1078 1080 bookmarks.activate(repo, mark)
1079 1081 del marks[rename]
1080 1082 elif names:
1081 1083 tr = repo.transaction('bookmark')
1082 1084 newact = None
1083 1085 for mark in names:
1084 1086 mark = checkformat(mark)
1085 1087 if newact is None:
1086 1088 newact = mark
1087 1089 if inactive and mark == repo._activebookmark:
1088 1090 bookmarks.deactivate(repo)
1089 1091 return
1090 1092 tgt = cur
1091 1093 if rev:
1092 1094 tgt = scmutil.revsingle(repo, rev).node()
1093 1095 checkconflict(repo, mark, cur, force, tgt)
1094 1096 marks[mark] = tgt
1095 1097 if not inactive and cur == marks[newact] and not rev:
1096 1098 bookmarks.activate(repo, newact)
1097 1099 elif cur != tgt and newact == repo._activebookmark:
1098 1100 bookmarks.deactivate(repo)
1099 1101 elif inactive:
1100 1102 if len(marks) == 0:
1101 1103 ui.status(_("no bookmarks set\n"))
1102 1104 elif not repo._activebookmark:
1103 1105 ui.status(_("no active bookmark\n"))
1104 1106 else:
1105 1107 bookmarks.deactivate(repo)
1106 1108 if tr is not None:
1107 1109 marks.recordchange(tr)
1108 1110 tr.close()
1109 1111 finally:
1110 1112 lockmod.release(tr, lock, wlock)
1111 1113 else: # show bookmarks
1112 1114 fm = ui.formatter('bookmarks', opts)
1113 1115 hexfn = fm.hexfunc
1114 1116 marks = repo._bookmarks
1115 1117 if len(marks) == 0 and fm.isplain():
1116 1118 ui.status(_("no bookmarks set\n"))
1117 1119 for bmark, n in sorted(marks.iteritems()):
1118 1120 active = repo._activebookmark
1119 1121 if bmark == active:
1120 1122 prefix, label = '*', activebookmarklabel
1121 1123 else:
1122 1124 prefix, label = ' ', ''
1123 1125
1124 1126 fm.startitem()
1125 1127 if not ui.quiet:
1126 1128 fm.plain(' %s ' % prefix, label=label)
1127 1129 fm.write('bookmark', '%s', bmark, label=label)
1128 1130 pad = " " * (25 - encoding.colwidth(bmark))
1129 1131 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1130 1132 repo.changelog.rev(n), hexfn(n), label=label)
1131 1133 fm.data(active=(bmark == active))
1132 1134 fm.plain('\n')
1133 1135 fm.end()
1134 1136
1135 1137 @command('branch',
1136 1138 [('f', 'force', None,
1137 1139 _('set branch name even if it shadows an existing branch')),
1138 1140 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1139 1141 _('[-fC] [NAME]'))
1140 1142 def branch(ui, repo, label=None, **opts):
1141 1143 """set or show the current branch name
1142 1144
1143 1145 .. note::
1144 1146
1145 1147 Branch names are permanent and global. Use :hg:`bookmark` to create a
1146 1148 light-weight bookmark instead. See :hg:`help glossary` for more
1147 1149 information about named branches and bookmarks.
1148 1150
1149 1151 With no argument, show the current branch name. With one argument,
1150 1152 set the working directory branch name (the branch will not exist
1151 1153 in the repository until the next commit). Standard practice
1152 1154 recommends that primary development take place on the 'default'
1153 1155 branch.
1154 1156
1155 1157 Unless -f/--force is specified, branch will not let you set a
1156 1158 branch name that already exists.
1157 1159
1158 1160 Use -C/--clean to reset the working directory branch to that of
1159 1161 the parent of the working directory, negating a previous branch
1160 1162 change.
1161 1163
1162 1164 Use the command :hg:`update` to switch to an existing branch. Use
1163 1165 :hg:`commit --close-branch` to mark this branch head as closed.
1164 1166 When all heads of a branch are closed, the branch will be
1165 1167 considered closed.
1166 1168
1167 1169 Returns 0 on success.
1168 1170 """
1169 1171 if label:
1170 1172 label = label.strip()
1171 1173
1172 1174 if not opts.get('clean') and not label:
1173 1175 ui.write("%s\n" % repo.dirstate.branch())
1174 1176 return
1175 1177
1176 1178 with repo.wlock():
1177 1179 if opts.get('clean'):
1178 1180 label = repo[None].p1().branch()
1179 1181 repo.dirstate.setbranch(label)
1180 1182 ui.status(_('reset working directory to branch %s\n') % label)
1181 1183 elif label:
1182 1184 if not opts.get('force') and label in repo.branchmap():
1183 1185 if label not in [p.branch() for p in repo[None].parents()]:
1184 1186 raise error.Abort(_('a branch of the same name already'
1185 1187 ' exists'),
1186 1188 # i18n: "it" refers to an existing branch
1187 1189 hint=_("use 'hg update' to switch to it"))
1188 1190 scmutil.checknewlabel(repo, label, 'branch')
1189 1191 repo.dirstate.setbranch(label)
1190 1192 ui.status(_('marked working directory as branch %s\n') % label)
1191 1193
1192 1194 # find any open named branches aside from default
1193 1195 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1194 1196 if n != "default" and not c]
1195 1197 if not others:
1196 1198 ui.status(_('(branches are permanent and global, '
1197 1199 'did you want a bookmark?)\n'))
1198 1200
1199 1201 @command('branches',
1200 1202 [('a', 'active', False,
1201 1203 _('show only branches that have unmerged heads (DEPRECATED)')),
1202 1204 ('c', 'closed', False, _('show normal and closed branches')),
1203 1205 ] + formatteropts,
1204 1206 _('[-c]'))
1205 1207 def branches(ui, repo, active=False, closed=False, **opts):
1206 1208 """list repository named branches
1207 1209
1208 1210 List the repository's named branches, indicating which ones are
1209 1211 inactive. If -c/--closed is specified, also list branches which have
1210 1212 been marked closed (see :hg:`commit --close-branch`).
1211 1213
1212 1214 Use the command :hg:`update` to switch to an existing branch.
1213 1215
1214 1216 Returns 0.
1215 1217 """
1216 1218
1217 1219 fm = ui.formatter('branches', opts)
1218 1220 hexfunc = fm.hexfunc
1219 1221
1220 1222 allheads = set(repo.heads())
1221 1223 branches = []
1222 1224 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1223 1225 isactive = not isclosed and bool(set(heads) & allheads)
1224 1226 branches.append((tag, repo[tip], isactive, not isclosed))
1225 1227 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1226 1228 reverse=True)
1227 1229
1228 1230 for tag, ctx, isactive, isopen in branches:
1229 1231 if active and not isactive:
1230 1232 continue
1231 1233 if isactive:
1232 1234 label = 'branches.active'
1233 1235 notice = ''
1234 1236 elif not isopen:
1235 1237 if not closed:
1236 1238 continue
1237 1239 label = 'branches.closed'
1238 1240 notice = _(' (closed)')
1239 1241 else:
1240 1242 label = 'branches.inactive'
1241 1243 notice = _(' (inactive)')
1242 1244 current = (tag == repo.dirstate.branch())
1243 1245 if current:
1244 1246 label = 'branches.current'
1245 1247
1246 1248 fm.startitem()
1247 1249 fm.write('branch', '%s', tag, label=label)
1248 1250 rev = ctx.rev()
1249 1251 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1250 1252 fmt = ' ' * padsize + ' %d:%s'
1251 1253 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1252 1254 label='log.changeset changeset.%s' % ctx.phasestr())
1253 1255 fm.data(active=isactive, closed=not isopen, current=current)
1254 1256 if not ui.quiet:
1255 1257 fm.plain(notice)
1256 1258 fm.plain('\n')
1257 1259 fm.end()
1258 1260
1259 1261 @command('bundle',
1260 1262 [('f', 'force', None, _('run even when the destination is unrelated')),
1261 1263 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1262 1264 _('REV')),
1263 1265 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1264 1266 _('BRANCH')),
1265 1267 ('', 'base', [],
1266 1268 _('a base changeset assumed to be available at the destination'),
1267 1269 _('REV')),
1268 1270 ('a', 'all', None, _('bundle all changesets in the repository')),
1269 1271 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1270 1272 ] + remoteopts,
1271 1273 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1272 1274 def bundle(ui, repo, fname, dest=None, **opts):
1273 1275 """create a changegroup file
1274 1276
1275 1277 Generate a changegroup file collecting changesets to be added
1276 1278 to a repository.
1277 1279
1278 1280 To create a bundle containing all changesets, use -a/--all
1279 1281 (or --base null). Otherwise, hg assumes the destination will have
1280 1282 all the nodes you specify with --base parameters. Otherwise, hg
1281 1283 will assume the repository has all the nodes in destination, or
1282 1284 default-push/default if no destination is specified.
1283 1285
1284 1286 You can change bundle format with the -t/--type option. You can
1285 1287 specify a compression, a bundle version or both using a dash
1286 1288 (comp-version). The available compression methods are: none, bzip2,
1287 1289 and gzip (by default, bundles are compressed using bzip2). The
1288 1290 available formats are: v1, v2 (default to most suitable).
1289 1291
1290 1292 The bundle file can then be transferred using conventional means
1291 1293 and applied to another repository with the unbundle or pull
1292 1294 command. This is useful when direct push and pull are not
1293 1295 available or when exporting an entire repository is undesirable.
1294 1296
1295 1297 Applying bundles preserves all changeset contents including
1296 1298 permissions, copy/rename information, and revision history.
1297 1299
1298 1300 Returns 0 on success, 1 if no changes found.
1299 1301 """
1300 1302 revs = None
1301 1303 if 'rev' in opts:
1302 1304 revstrings = opts['rev']
1303 1305 revs = scmutil.revrange(repo, revstrings)
1304 1306 if revstrings and not revs:
1305 1307 raise error.Abort(_('no commits to bundle'))
1306 1308
1307 1309 bundletype = opts.get('type', 'bzip2').lower()
1308 1310 try:
1309 1311 bcompression, cgversion, params = exchange.parsebundlespec(
1310 1312 repo, bundletype, strict=False)
1311 1313 except error.UnsupportedBundleSpecification as e:
1312 1314 raise error.Abort(str(e),
1313 1315 hint=_("see 'hg help bundle' for supported "
1314 1316 "values for --type"))
1315 1317
1316 1318 # Packed bundles are a pseudo bundle format for now.
1317 1319 if cgversion == 's1':
1318 1320 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1319 1321 hint=_("use 'hg debugcreatestreamclonebundle'"))
1320 1322
1321 1323 if opts.get('all'):
1322 1324 if dest:
1323 1325 raise error.Abort(_("--all is incompatible with specifying "
1324 1326 "a destination"))
1325 1327 if opts.get('base'):
1326 1328 ui.warn(_("ignoring --base because --all was specified\n"))
1327 1329 base = ['null']
1328 1330 else:
1329 1331 base = scmutil.revrange(repo, opts.get('base'))
1330 1332 # TODO: get desired bundlecaps from command line.
1331 1333 bundlecaps = None
1332 1334 if cgversion not in changegroup.supportedoutgoingversions(repo):
1333 1335 raise error.Abort(_("repository does not support bundle version %s") %
1334 1336 cgversion)
1335 1337
1336 1338 if base:
1337 1339 if dest:
1338 1340 raise error.Abort(_("--base is incompatible with specifying "
1339 1341 "a destination"))
1340 1342 common = [repo.lookup(rev) for rev in base]
1341 1343 heads = revs and map(repo.lookup, revs) or None
1342 1344 outgoing = discovery.outgoing(repo, common, heads)
1343 1345 cg = changegroup.getchangegroup(repo, 'bundle', outgoing,
1344 1346 bundlecaps=bundlecaps,
1345 1347 version=cgversion)
1346 1348 outgoing = None
1347 1349 else:
1348 1350 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1349 1351 dest, branches = hg.parseurl(dest, opts.get('branch'))
1350 1352 other = hg.peer(repo, opts, dest)
1351 1353 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1352 1354 heads = revs and map(repo.lookup, revs) or revs
1353 1355 outgoing = discovery.findcommonoutgoing(repo, other,
1354 1356 onlyheads=heads,
1355 1357 force=opts.get('force'),
1356 1358 portable=True)
1357 1359 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1358 1360 bundlecaps, version=cgversion)
1359 1361 if not cg:
1360 1362 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1361 1363 return 1
1362 1364
1363 1365 if cgversion == '01': #bundle1
1364 1366 if bcompression is None:
1365 1367 bcompression = 'UN'
1366 1368 bversion = 'HG10' + bcompression
1367 1369 bcompression = None
1368 1370 else:
1369 1371 assert cgversion == '02'
1370 1372 bversion = 'HG20'
1371 1373
1372 1374 # TODO compression options should be derived from bundlespec parsing.
1373 1375 # This is a temporary hack to allow adjusting bundle compression
1374 1376 # level without a) formalizing the bundlespec changes to declare it
1375 1377 # b) introducing a command flag.
1376 1378 compopts = {}
1377 1379 complevel = ui.configint('experimental', 'bundlecomplevel')
1378 1380 if complevel is not None:
1379 1381 compopts['level'] = complevel
1380 1382
1381 1383 bundle2.writebundle(ui, cg, fname, bversion, compression=bcompression,
1382 1384 compopts=compopts)
1383 1385
1384 1386 @command('cat',
1385 1387 [('o', 'output', '',
1386 1388 _('print output to file with formatted name'), _('FORMAT')),
1387 1389 ('r', 'rev', '', _('print the given revision'), _('REV')),
1388 1390 ('', 'decode', None, _('apply any matching decode filter')),
1389 1391 ] + walkopts,
1390 1392 _('[OPTION]... FILE...'),
1391 1393 inferrepo=True)
1392 1394 def cat(ui, repo, file1, *pats, **opts):
1393 1395 """output the current or given revision of files
1394 1396
1395 1397 Print the specified files as they were at the given revision. If
1396 1398 no revision is given, the parent of the working directory is used.
1397 1399
1398 1400 Output may be to a file, in which case the name of the file is
1399 1401 given using a format string. The formatting rules as follows:
1400 1402
1401 1403 :``%%``: literal "%" character
1402 1404 :``%s``: basename of file being printed
1403 1405 :``%d``: dirname of file being printed, or '.' if in repository root
1404 1406 :``%p``: root-relative path name of file being printed
1405 1407 :``%H``: changeset hash (40 hexadecimal digits)
1406 1408 :``%R``: changeset revision number
1407 1409 :``%h``: short-form changeset hash (12 hexadecimal digits)
1408 1410 :``%r``: zero-padded changeset revision number
1409 1411 :``%b``: basename of the exporting repository
1410 1412
1411 1413 Returns 0 on success.
1412 1414 """
1413 1415 ctx = scmutil.revsingle(repo, opts.get('rev'))
1414 1416 m = scmutil.match(ctx, (file1,) + pats, opts)
1415 1417
1416 1418 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1417 1419
1418 1420 @command('^clone',
1419 1421 [('U', 'noupdate', None, _('the clone will include an empty working '
1420 1422 'directory (only a repository)')),
1421 1423 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1422 1424 _('REV')),
1423 1425 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1424 1426 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1425 1427 ('', 'pull', None, _('use pull protocol to copy metadata')),
1426 1428 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1427 1429 ] + remoteopts,
1428 1430 _('[OPTION]... SOURCE [DEST]'),
1429 1431 norepo=True)
1430 1432 def clone(ui, source, dest=None, **opts):
1431 1433 """make a copy of an existing repository
1432 1434
1433 1435 Create a copy of an existing repository in a new directory.
1434 1436
1435 1437 If no destination directory name is specified, it defaults to the
1436 1438 basename of the source.
1437 1439
1438 1440 The location of the source is added to the new repository's
1439 1441 ``.hg/hgrc`` file, as the default to be used for future pulls.
1440 1442
1441 1443 Only local paths and ``ssh://`` URLs are supported as
1442 1444 destinations. For ``ssh://`` destinations, no working directory or
1443 1445 ``.hg/hgrc`` will be created on the remote side.
1444 1446
1445 1447 If the source repository has a bookmark called '@' set, that
1446 1448 revision will be checked out in the new repository by default.
1447 1449
1448 1450 To check out a particular version, use -u/--update, or
1449 1451 -U/--noupdate to create a clone with no working directory.
1450 1452
1451 1453 To pull only a subset of changesets, specify one or more revisions
1452 1454 identifiers with -r/--rev or branches with -b/--branch. The
1453 1455 resulting clone will contain only the specified changesets and
1454 1456 their ancestors. These options (or 'clone src#rev dest') imply
1455 1457 --pull, even for local source repositories.
1456 1458
1457 1459 .. note::
1458 1460
1459 1461 Specifying a tag will include the tagged changeset but not the
1460 1462 changeset containing the tag.
1461 1463
1462 1464 .. container:: verbose
1463 1465
1464 1466 For efficiency, hardlinks are used for cloning whenever the
1465 1467 source and destination are on the same filesystem (note this
1466 1468 applies only to the repository data, not to the working
1467 1469 directory). Some filesystems, such as AFS, implement hardlinking
1468 1470 incorrectly, but do not report errors. In these cases, use the
1469 1471 --pull option to avoid hardlinking.
1470 1472
1471 1473 In some cases, you can clone repositories and the working
1472 1474 directory using full hardlinks with ::
1473 1475
1474 1476 $ cp -al REPO REPOCLONE
1475 1477
1476 1478 This is the fastest way to clone, but it is not always safe. The
1477 1479 operation is not atomic (making sure REPO is not modified during
1478 1480 the operation is up to you) and you have to make sure your
1479 1481 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1480 1482 so). Also, this is not compatible with certain extensions that
1481 1483 place their metadata under the .hg directory, such as mq.
1482 1484
1483 1485 Mercurial will update the working directory to the first applicable
1484 1486 revision from this list:
1485 1487
1486 1488 a) null if -U or the source repository has no changesets
1487 1489 b) if -u . and the source repository is local, the first parent of
1488 1490 the source repository's working directory
1489 1491 c) the changeset specified with -u (if a branch name, this means the
1490 1492 latest head of that branch)
1491 1493 d) the changeset specified with -r
1492 1494 e) the tipmost head specified with -b
1493 1495 f) the tipmost head specified with the url#branch source syntax
1494 1496 g) the revision marked with the '@' bookmark, if present
1495 1497 h) the tipmost head of the default branch
1496 1498 i) tip
1497 1499
1498 1500 When cloning from servers that support it, Mercurial may fetch
1499 1501 pre-generated data from a server-advertised URL. When this is done,
1500 1502 hooks operating on incoming changesets and changegroups may fire twice,
1501 1503 once for the bundle fetched from the URL and another for any additional
1502 1504 data not fetched from this URL. In addition, if an error occurs, the
1503 1505 repository may be rolled back to a partial clone. This behavior may
1504 1506 change in future releases. See :hg:`help -e clonebundles` for more.
1505 1507
1506 1508 Examples:
1507 1509
1508 1510 - clone a remote repository to a new directory named hg/::
1509 1511
1510 1512 hg clone https://www.mercurial-scm.org/repo/hg/
1511 1513
1512 1514 - create a lightweight local clone::
1513 1515
1514 1516 hg clone project/ project-feature/
1515 1517
1516 1518 - clone from an absolute path on an ssh server (note double-slash)::
1517 1519
1518 1520 hg clone ssh://user@server//home/projects/alpha/
1519 1521
1520 1522 - do a high-speed clone over a LAN while checking out a
1521 1523 specified version::
1522 1524
1523 1525 hg clone --uncompressed http://server/repo -u 1.5
1524 1526
1525 1527 - create a repository without changesets after a particular revision::
1526 1528
1527 1529 hg clone -r 04e544 experimental/ good/
1528 1530
1529 1531 - clone (and track) a particular named branch::
1530 1532
1531 1533 hg clone https://www.mercurial-scm.org/repo/hg/#stable
1532 1534
1533 1535 See :hg:`help urls` for details on specifying URLs.
1534 1536
1535 1537 Returns 0 on success.
1536 1538 """
1537 1539 if opts.get('noupdate') and opts.get('updaterev'):
1538 1540 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1539 1541
1540 1542 r = hg.clone(ui, opts, source, dest,
1541 1543 pull=opts.get('pull'),
1542 1544 stream=opts.get('uncompressed'),
1543 1545 rev=opts.get('rev'),
1544 1546 update=opts.get('updaterev') or not opts.get('noupdate'),
1545 1547 branch=opts.get('branch'),
1546 1548 shareopts=opts.get('shareopts'))
1547 1549
1548 1550 return r is None
1549 1551
1550 1552 @command('^commit|ci',
1551 1553 [('A', 'addremove', None,
1552 1554 _('mark new/missing files as added/removed before committing')),
1553 1555 ('', 'close-branch', None,
1554 1556 _('mark a branch head as closed')),
1555 1557 ('', 'amend', None, _('amend the parent of the working directory')),
1556 1558 ('s', 'secret', None, _('use the secret phase for committing')),
1557 1559 ('e', 'edit', None, _('invoke editor on commit messages')),
1558 1560 ('i', 'interactive', None, _('use interactive mode')),
1559 1561 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1560 1562 _('[OPTION]... [FILE]...'),
1561 1563 inferrepo=True)
1562 1564 def commit(ui, repo, *pats, **opts):
1563 1565 """commit the specified files or all outstanding changes
1564 1566
1565 1567 Commit changes to the given files into the repository. Unlike a
1566 1568 centralized SCM, this operation is a local operation. See
1567 1569 :hg:`push` for a way to actively distribute your changes.
1568 1570
1569 1571 If a list of files is omitted, all changes reported by :hg:`status`
1570 1572 will be committed.
1571 1573
1572 1574 If you are committing the result of a merge, do not provide any
1573 1575 filenames or -I/-X filters.
1574 1576
1575 1577 If no commit message is specified, Mercurial starts your
1576 1578 configured editor where you can enter a message. In case your
1577 1579 commit fails, you will find a backup of your message in
1578 1580 ``.hg/last-message.txt``.
1579 1581
1580 1582 The --close-branch flag can be used to mark the current branch
1581 1583 head closed. When all heads of a branch are closed, the branch
1582 1584 will be considered closed and no longer listed.
1583 1585
1584 1586 The --amend flag can be used to amend the parent of the
1585 1587 working directory with a new commit that contains the changes
1586 1588 in the parent in addition to those currently reported by :hg:`status`,
1587 1589 if there are any. The old commit is stored in a backup bundle in
1588 1590 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1589 1591 on how to restore it).
1590 1592
1591 1593 Message, user and date are taken from the amended commit unless
1592 1594 specified. When a message isn't specified on the command line,
1593 1595 the editor will open with the message of the amended commit.
1594 1596
1595 1597 It is not possible to amend public changesets (see :hg:`help phases`)
1596 1598 or changesets that have children.
1597 1599
1598 1600 See :hg:`help dates` for a list of formats valid for -d/--date.
1599 1601
1600 1602 Returns 0 on success, 1 if nothing changed.
1601 1603
1602 1604 .. container:: verbose
1603 1605
1604 1606 Examples:
1605 1607
1606 1608 - commit all files ending in .py::
1607 1609
1608 1610 hg commit --include "set:**.py"
1609 1611
1610 1612 - commit all non-binary files::
1611 1613
1612 1614 hg commit --exclude "set:binary()"
1613 1615
1614 1616 - amend the current commit and set the date to now::
1615 1617
1616 1618 hg commit --amend --date now
1617 1619 """
1618 1620 wlock = lock = None
1619 1621 try:
1620 1622 wlock = repo.wlock()
1621 1623 lock = repo.lock()
1622 1624 return _docommit(ui, repo, *pats, **opts)
1623 1625 finally:
1624 1626 release(lock, wlock)
1625 1627
1626 1628 def _docommit(ui, repo, *pats, **opts):
1627 1629 if opts.get('interactive'):
1628 1630 opts.pop('interactive')
1629 1631 ret = cmdutil.dorecord(ui, repo, commit, None, False,
1630 1632 cmdutil.recordfilter, *pats, **opts)
1631 1633 # ret can be 0 (no changes to record) or the value returned by
1632 1634 # commit(), 1 if nothing changed or None on success.
1633 1635 return 1 if ret == 0 else ret
1634 1636
1635 1637 if opts.get('subrepos'):
1636 1638 if opts.get('amend'):
1637 1639 raise error.Abort(_('cannot amend with --subrepos'))
1638 1640 # Let --subrepos on the command line override config setting.
1639 1641 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1640 1642
1641 1643 cmdutil.checkunfinished(repo, commit=True)
1642 1644
1643 1645 branch = repo[None].branch()
1644 1646 bheads = repo.branchheads(branch)
1645 1647
1646 1648 extra = {}
1647 1649 if opts.get('close_branch'):
1648 1650 extra['close'] = 1
1649 1651
1650 1652 if not bheads:
1651 1653 raise error.Abort(_('can only close branch heads'))
1652 1654 elif opts.get('amend'):
1653 1655 if repo[None].parents()[0].p1().branch() != branch and \
1654 1656 repo[None].parents()[0].p2().branch() != branch:
1655 1657 raise error.Abort(_('can only close branch heads'))
1656 1658
1657 1659 if opts.get('amend'):
1658 1660 if ui.configbool('ui', 'commitsubrepos'):
1659 1661 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1660 1662
1661 1663 old = repo['.']
1662 1664 if not old.mutable():
1663 1665 raise error.Abort(_('cannot amend public changesets'))
1664 1666 if len(repo[None].parents()) > 1:
1665 1667 raise error.Abort(_('cannot amend while merging'))
1666 1668 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1667 1669 if not allowunstable and old.children():
1668 1670 raise error.Abort(_('cannot amend changeset with children'))
1669 1671
1670 1672 # Currently histedit gets confused if an amend happens while histedit
1671 1673 # is in progress. Since we have a checkunfinished command, we are
1672 1674 # temporarily honoring it.
1673 1675 #
1674 1676 # Note: eventually this guard will be removed. Please do not expect
1675 1677 # this behavior to remain.
1676 1678 if not obsolete.isenabled(repo, obsolete.createmarkersopt):
1677 1679 cmdutil.checkunfinished(repo)
1678 1680
1679 1681 # commitfunc is used only for temporary amend commit by cmdutil.amend
1680 1682 def commitfunc(ui, repo, message, match, opts):
1681 1683 return repo.commit(message,
1682 1684 opts.get('user') or old.user(),
1683 1685 opts.get('date') or old.date(),
1684 1686 match,
1685 1687 extra=extra)
1686 1688
1687 1689 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1688 1690 if node == old.node():
1689 1691 ui.status(_("nothing changed\n"))
1690 1692 return 1
1691 1693 else:
1692 1694 def commitfunc(ui, repo, message, match, opts):
1693 1695 backup = ui.backupconfig('phases', 'new-commit')
1694 1696 baseui = repo.baseui
1695 1697 basebackup = baseui.backupconfig('phases', 'new-commit')
1696 1698 try:
1697 1699 if opts.get('secret'):
1698 1700 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1699 1701 # Propagate to subrepos
1700 1702 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1701 1703
1702 1704 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1703 1705 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1704 1706 return repo.commit(message, opts.get('user'), opts.get('date'),
1705 1707 match,
1706 1708 editor=editor,
1707 1709 extra=extra)
1708 1710 finally:
1709 1711 ui.restoreconfig(backup)
1710 1712 repo.baseui.restoreconfig(basebackup)
1711 1713
1712 1714
1713 1715 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1714 1716
1715 1717 if not node:
1716 1718 stat = cmdutil.postcommitstatus(repo, pats, opts)
1717 1719 if stat[3]:
1718 1720 ui.status(_("nothing changed (%d missing files, see "
1719 1721 "'hg status')\n") % len(stat[3]))
1720 1722 else:
1721 1723 ui.status(_("nothing changed\n"))
1722 1724 return 1
1723 1725
1724 1726 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1725 1727
1726 1728 @command('config|showconfig|debugconfig',
1727 1729 [('u', 'untrusted', None, _('show untrusted configuration options')),
1728 1730 ('e', 'edit', None, _('edit user config')),
1729 1731 ('l', 'local', None, _('edit repository config')),
1730 1732 ('g', 'global', None, _('edit global config'))] + formatteropts,
1731 1733 _('[-u] [NAME]...'),
1732 1734 optionalrepo=True)
1733 1735 def config(ui, repo, *values, **opts):
1734 1736 """show combined config settings from all hgrc files
1735 1737
1736 1738 With no arguments, print names and values of all config items.
1737 1739
1738 1740 With one argument of the form section.name, print just the value
1739 1741 of that config item.
1740 1742
1741 1743 With multiple arguments, print names and values of all config
1742 1744 items with matching section names.
1743 1745
1744 1746 With --edit, start an editor on the user-level config file. With
1745 1747 --global, edit the system-wide config file. With --local, edit the
1746 1748 repository-level config file.
1747 1749
1748 1750 With --debug, the source (filename and line number) is printed
1749 1751 for each config item.
1750 1752
1751 1753 See :hg:`help config` for more information about config files.
1752 1754
1753 1755 Returns 0 on success, 1 if NAME does not exist.
1754 1756
1755 1757 """
1756 1758
1757 1759 if opts.get('edit') or opts.get('local') or opts.get('global'):
1758 1760 if opts.get('local') and opts.get('global'):
1759 1761 raise error.Abort(_("can't use --local and --global together"))
1760 1762
1761 1763 if opts.get('local'):
1762 1764 if not repo:
1763 1765 raise error.Abort(_("can't use --local outside a repository"))
1764 1766 paths = [repo.join('hgrc')]
1765 1767 elif opts.get('global'):
1766 1768 paths = scmutil.systemrcpath()
1767 1769 else:
1768 1770 paths = scmutil.userrcpath()
1769 1771
1770 1772 for f in paths:
1771 1773 if os.path.exists(f):
1772 1774 break
1773 1775 else:
1774 1776 if opts.get('global'):
1775 1777 samplehgrc = uimod.samplehgrcs['global']
1776 1778 elif opts.get('local'):
1777 1779 samplehgrc = uimod.samplehgrcs['local']
1778 1780 else:
1779 1781 samplehgrc = uimod.samplehgrcs['user']
1780 1782
1781 1783 f = paths[0]
1782 1784 fp = open(f, "w")
1783 1785 fp.write(samplehgrc)
1784 1786 fp.close()
1785 1787
1786 1788 editor = ui.geteditor()
1787 1789 ui.system("%s \"%s\"" % (editor, f),
1788 1790 onerr=error.Abort, errprefix=_("edit failed"))
1789 1791 return
1790 1792
1791 1793 fm = ui.formatter('config', opts)
1792 1794 for f in scmutil.rcpath():
1793 1795 ui.debug('read config from: %s\n' % f)
1794 1796 untrusted = bool(opts.get('untrusted'))
1795 1797 if values:
1796 1798 sections = [v for v in values if '.' not in v]
1797 1799 items = [v for v in values if '.' in v]
1798 1800 if len(items) > 1 or items and sections:
1799 1801 raise error.Abort(_('only one config item permitted'))
1800 1802 matched = False
1801 1803 for section, name, value in ui.walkconfig(untrusted=untrusted):
1802 1804 source = ui.configsource(section, name, untrusted)
1803 1805 value = str(value)
1804 1806 if fm.isplain():
1805 1807 source = source or 'none'
1806 1808 value = value.replace('\n', '\\n')
1807 1809 entryname = section + '.' + name
1808 1810 if values:
1809 1811 for v in values:
1810 1812 if v == section:
1811 1813 fm.startitem()
1812 1814 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1813 1815 fm.write('name value', '%s=%s\n', entryname, value)
1814 1816 matched = True
1815 1817 elif v == entryname:
1816 1818 fm.startitem()
1817 1819 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1818 1820 fm.write('value', '%s\n', value)
1819 1821 fm.data(name=entryname)
1820 1822 matched = True
1821 1823 else:
1822 1824 fm.startitem()
1823 1825 fm.condwrite(ui.debugflag, 'source', '%s: ', source)
1824 1826 fm.write('name value', '%s=%s\n', entryname, value)
1825 1827 matched = True
1826 1828 fm.end()
1827 1829 if matched:
1828 1830 return 0
1829 1831 return 1
1830 1832
1831 1833 @command('copy|cp',
1832 1834 [('A', 'after', None, _('record a copy that has already occurred')),
1833 1835 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1834 1836 ] + walkopts + dryrunopts,
1835 1837 _('[OPTION]... [SOURCE]... DEST'))
1836 1838 def copy(ui, repo, *pats, **opts):
1837 1839 """mark files as copied for the next commit
1838 1840
1839 1841 Mark dest as having copies of source files. If dest is a
1840 1842 directory, copies are put in that directory. If dest is a file,
1841 1843 the source must be a single file.
1842 1844
1843 1845 By default, this command copies the contents of files as they
1844 1846 exist in the working directory. If invoked with -A/--after, the
1845 1847 operation is recorded, but no copying is performed.
1846 1848
1847 1849 This command takes effect with the next commit. To undo a copy
1848 1850 before that, see :hg:`revert`.
1849 1851
1850 1852 Returns 0 on success, 1 if errors are encountered.
1851 1853 """
1852 1854 with repo.wlock(False):
1853 1855 return cmdutil.copy(ui, repo, pats, opts)
1854 1856
1855 1857 @command('^diff',
1856 1858 [('r', 'rev', [], _('revision'), _('REV')),
1857 1859 ('c', 'change', '', _('change made by revision'), _('REV'))
1858 1860 ] + diffopts + diffopts2 + walkopts + subrepoopts,
1859 1861 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
1860 1862 inferrepo=True)
1861 1863 def diff(ui, repo, *pats, **opts):
1862 1864 """diff repository (or selected files)
1863 1865
1864 1866 Show differences between revisions for the specified files.
1865 1867
1866 1868 Differences between files are shown using the unified diff format.
1867 1869
1868 1870 .. note::
1869 1871
1870 1872 :hg:`diff` may generate unexpected results for merges, as it will
1871 1873 default to comparing against the working directory's first
1872 1874 parent changeset if no revisions are specified.
1873 1875
1874 1876 When two revision arguments are given, then changes are shown
1875 1877 between those revisions. If only one revision is specified then
1876 1878 that revision is compared to the working directory, and, when no
1877 1879 revisions are specified, the working directory files are compared
1878 1880 to its first parent.
1879 1881
1880 1882 Alternatively you can specify -c/--change with a revision to see
1881 1883 the changes in that changeset relative to its first parent.
1882 1884
1883 1885 Without the -a/--text option, diff will avoid generating diffs of
1884 1886 files it detects as binary. With -a, diff will generate a diff
1885 1887 anyway, probably with undesirable results.
1886 1888
1887 1889 Use the -g/--git option to generate diffs in the git extended diff
1888 1890 format. For more information, read :hg:`help diffs`.
1889 1891
1890 1892 .. container:: verbose
1891 1893
1892 1894 Examples:
1893 1895
1894 1896 - compare a file in the current working directory to its parent::
1895 1897
1896 1898 hg diff foo.c
1897 1899
1898 1900 - compare two historical versions of a directory, with rename info::
1899 1901
1900 1902 hg diff --git -r 1.0:1.2 lib/
1901 1903
1902 1904 - get change stats relative to the last change on some date::
1903 1905
1904 1906 hg diff --stat -r "date('may 2')"
1905 1907
1906 1908 - diff all newly-added files that contain a keyword::
1907 1909
1908 1910 hg diff "set:added() and grep(GNU)"
1909 1911
1910 1912 - compare a revision and its parents::
1911 1913
1912 1914 hg diff -c 9353 # compare against first parent
1913 1915 hg diff -r 9353^:9353 # same using revset syntax
1914 1916 hg diff -r 9353^2:9353 # compare against the second parent
1915 1917
1916 1918 Returns 0 on success.
1917 1919 """
1918 1920
1919 1921 revs = opts.get('rev')
1920 1922 change = opts.get('change')
1921 1923 stat = opts.get('stat')
1922 1924 reverse = opts.get('reverse')
1923 1925
1924 1926 if revs and change:
1925 1927 msg = _('cannot specify --rev and --change at the same time')
1926 1928 raise error.Abort(msg)
1927 1929 elif change:
1928 1930 node2 = scmutil.revsingle(repo, change, None).node()
1929 1931 node1 = repo[node2].p1().node()
1930 1932 else:
1931 1933 node1, node2 = scmutil.revpair(repo, revs)
1932 1934
1933 1935 if reverse:
1934 1936 node1, node2 = node2, node1
1935 1937
1936 1938 diffopts = patch.diffallopts(ui, opts)
1937 1939 m = scmutil.match(repo[node2], pats, opts)
1938 1940 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1939 1941 listsubrepos=opts.get('subrepos'),
1940 1942 root=opts.get('root'))
1941 1943
1942 1944 @command('^export',
1943 1945 [('o', 'output', '',
1944 1946 _('print output to file with formatted name'), _('FORMAT')),
1945 1947 ('', 'switch-parent', None, _('diff against the second parent')),
1946 1948 ('r', 'rev', [], _('revisions to export'), _('REV')),
1947 1949 ] + diffopts,
1948 1950 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
1949 1951 def export(ui, repo, *changesets, **opts):
1950 1952 """dump the header and diffs for one or more changesets
1951 1953
1952 1954 Print the changeset header and diffs for one or more revisions.
1953 1955 If no revision is given, the parent of the working directory is used.
1954 1956
1955 1957 The information shown in the changeset header is: author, date,
1956 1958 branch name (if non-default), changeset hash, parent(s) and commit
1957 1959 comment.
1958 1960
1959 1961 .. note::
1960 1962
1961 1963 :hg:`export` may generate unexpected diff output for merge
1962 1964 changesets, as it will compare the merge changeset against its
1963 1965 first parent only.
1964 1966
1965 1967 Output may be to a file, in which case the name of the file is
1966 1968 given using a format string. The formatting rules are as follows:
1967 1969
1968 1970 :``%%``: literal "%" character
1969 1971 :``%H``: changeset hash (40 hexadecimal digits)
1970 1972 :``%N``: number of patches being generated
1971 1973 :``%R``: changeset revision number
1972 1974 :``%b``: basename of the exporting repository
1973 1975 :``%h``: short-form changeset hash (12 hexadecimal digits)
1974 1976 :``%m``: first line of the commit message (only alphanumeric characters)
1975 1977 :``%n``: zero-padded sequence number, starting at 1
1976 1978 :``%r``: zero-padded changeset revision number
1977 1979
1978 1980 Without the -a/--text option, export will avoid generating diffs
1979 1981 of files it detects as binary. With -a, export will generate a
1980 1982 diff anyway, probably with undesirable results.
1981 1983
1982 1984 Use the -g/--git option to generate diffs in the git extended diff
1983 1985 format. See :hg:`help diffs` for more information.
1984 1986
1985 1987 With the --switch-parent option, the diff will be against the
1986 1988 second parent. It can be useful to review a merge.
1987 1989
1988 1990 .. container:: verbose
1989 1991
1990 1992 Examples:
1991 1993
1992 1994 - use export and import to transplant a bugfix to the current
1993 1995 branch::
1994 1996
1995 1997 hg export -r 9353 | hg import -
1996 1998
1997 1999 - export all the changesets between two revisions to a file with
1998 2000 rename information::
1999 2001
2000 2002 hg export --git -r 123:150 > changes.txt
2001 2003
2002 2004 - split outgoing changes into a series of patches with
2003 2005 descriptive names::
2004 2006
2005 2007 hg export -r "outgoing()" -o "%n-%m.patch"
2006 2008
2007 2009 Returns 0 on success.
2008 2010 """
2009 2011 changesets += tuple(opts.get('rev', []))
2010 2012 if not changesets:
2011 2013 changesets = ['.']
2012 2014 revs = scmutil.revrange(repo, changesets)
2013 2015 if not revs:
2014 2016 raise error.Abort(_("export requires at least one changeset"))
2015 2017 if len(revs) > 1:
2016 2018 ui.note(_('exporting patches:\n'))
2017 2019 else:
2018 2020 ui.note(_('exporting patch:\n'))
2019 2021 cmdutil.export(repo, revs, template=opts.get('output'),
2020 2022 switch_parent=opts.get('switch_parent'),
2021 2023 opts=patch.diffallopts(ui, opts))
2022 2024
2023 2025 @command('files',
2024 2026 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
2025 2027 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2026 2028 ] + walkopts + formatteropts + subrepoopts,
2027 2029 _('[OPTION]... [FILE]...'))
2028 2030 def files(ui, repo, *pats, **opts):
2029 2031 """list tracked files
2030 2032
2031 2033 Print files under Mercurial control in the working directory or
2032 2034 specified revision for given files (excluding removed files).
2033 2035 Files can be specified as filenames or filesets.
2034 2036
2035 2037 If no files are given to match, this command prints the names
2036 2038 of all files under Mercurial control.
2037 2039
2038 2040 .. container:: verbose
2039 2041
2040 2042 Examples:
2041 2043
2042 2044 - list all files under the current directory::
2043 2045
2044 2046 hg files .
2045 2047
2046 2048 - shows sizes and flags for current revision::
2047 2049
2048 2050 hg files -vr .
2049 2051
2050 2052 - list all files named README::
2051 2053
2052 2054 hg files -I "**/README"
2053 2055
2054 2056 - list all binary files::
2055 2057
2056 2058 hg files "set:binary()"
2057 2059
2058 2060 - find files containing a regular expression::
2059 2061
2060 2062 hg files "set:grep('bob')"
2061 2063
2062 2064 - search tracked file contents with xargs and grep::
2063 2065
2064 2066 hg files -0 | xargs -0 grep foo
2065 2067
2066 2068 See :hg:`help patterns` and :hg:`help filesets` for more information
2067 2069 on specifying file patterns.
2068 2070
2069 2071 Returns 0 if a match is found, 1 otherwise.
2070 2072
2071 2073 """
2072 2074 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2073 2075
2074 2076 end = '\n'
2075 2077 if opts.get('print0'):
2076 2078 end = '\0'
2077 2079 fmt = '%s' + end
2078 2080
2079 2081 m = scmutil.match(ctx, pats, opts)
2080 2082 with ui.formatter('files', opts) as fm:
2081 2083 return cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
2082 2084
2083 2085 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
2084 2086 def forget(ui, repo, *pats, **opts):
2085 2087 """forget the specified files on the next commit
2086 2088
2087 2089 Mark the specified files so they will no longer be tracked
2088 2090 after the next commit.
2089 2091
2090 2092 This only removes files from the current branch, not from the
2091 2093 entire project history, and it does not delete them from the
2092 2094 working directory.
2093 2095
2094 2096 To delete the file from the working directory, see :hg:`remove`.
2095 2097
2096 2098 To undo a forget before the next commit, see :hg:`add`.
2097 2099
2098 2100 .. container:: verbose
2099 2101
2100 2102 Examples:
2101 2103
2102 2104 - forget newly-added binary files::
2103 2105
2104 2106 hg forget "set:added() and binary()"
2105 2107
2106 2108 - forget files that would be excluded by .hgignore::
2107 2109
2108 2110 hg forget "set:hgignore()"
2109 2111
2110 2112 Returns 0 on success.
2111 2113 """
2112 2114
2113 2115 if not pats:
2114 2116 raise error.Abort(_('no files specified'))
2115 2117
2116 2118 m = scmutil.match(repo[None], pats, opts)
2117 2119 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2118 2120 return rejected and 1 or 0
2119 2121
2120 2122 @command(
2121 2123 'graft',
2122 2124 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2123 2125 ('c', 'continue', False, _('resume interrupted graft')),
2124 2126 ('e', 'edit', False, _('invoke editor on commit messages')),
2125 2127 ('', 'log', None, _('append graft info to log message')),
2126 2128 ('f', 'force', False, _('force graft')),
2127 2129 ('D', 'currentdate', False,
2128 2130 _('record the current date as commit date')),
2129 2131 ('U', 'currentuser', False,
2130 2132 _('record the current user as committer'), _('DATE'))]
2131 2133 + commitopts2 + mergetoolopts + dryrunopts,
2132 2134 _('[OPTION]... [-r REV]... REV...'))
2133 2135 def graft(ui, repo, *revs, **opts):
2134 2136 '''copy changes from other branches onto the current branch
2135 2137
2136 2138 This command uses Mercurial's merge logic to copy individual
2137 2139 changes from other branches without merging branches in the
2138 2140 history graph. This is sometimes known as 'backporting' or
2139 2141 'cherry-picking'. By default, graft will copy user, date, and
2140 2142 description from the source changesets.
2141 2143
2142 2144 Changesets that are ancestors of the current revision, that have
2143 2145 already been grafted, or that are merges will be skipped.
2144 2146
2145 2147 If --log is specified, log messages will have a comment appended
2146 2148 of the form::
2147 2149
2148 2150 (grafted from CHANGESETHASH)
2149 2151
2150 2152 If --force is specified, revisions will be grafted even if they
2151 2153 are already ancestors of or have been grafted to the destination.
2152 2154 This is useful when the revisions have since been backed out.
2153 2155
2154 2156 If a graft merge results in conflicts, the graft process is
2155 2157 interrupted so that the current merge can be manually resolved.
2156 2158 Once all conflicts are addressed, the graft process can be
2157 2159 continued with the -c/--continue option.
2158 2160
2159 2161 .. note::
2160 2162
2161 2163 The -c/--continue option does not reapply earlier options, except
2162 2164 for --force.
2163 2165
2164 2166 .. container:: verbose
2165 2167
2166 2168 Examples:
2167 2169
2168 2170 - copy a single change to the stable branch and edit its description::
2169 2171
2170 2172 hg update stable
2171 2173 hg graft --edit 9393
2172 2174
2173 2175 - graft a range of changesets with one exception, updating dates::
2174 2176
2175 2177 hg graft -D "2085::2093 and not 2091"
2176 2178
2177 2179 - continue a graft after resolving conflicts::
2178 2180
2179 2181 hg graft -c
2180 2182
2181 2183 - show the source of a grafted changeset::
2182 2184
2183 2185 hg log --debug -r .
2184 2186
2185 2187 - show revisions sorted by date::
2186 2188
2187 2189 hg log -r "sort(all(), date)"
2188 2190
2189 2191 See :hg:`help revisions` for more about specifying revisions.
2190 2192
2191 2193 Returns 0 on successful completion.
2192 2194 '''
2193 2195 with repo.wlock():
2194 2196 return _dograft(ui, repo, *revs, **opts)
2195 2197
2196 2198 def _dograft(ui, repo, *revs, **opts):
2197 2199 if revs and opts.get('rev'):
2198 2200 ui.warn(_('warning: inconsistent use of --rev might give unexpected '
2199 2201 'revision ordering!\n'))
2200 2202
2201 2203 revs = list(revs)
2202 2204 revs.extend(opts.get('rev'))
2203 2205
2204 2206 if not opts.get('user') and opts.get('currentuser'):
2205 2207 opts['user'] = ui.username()
2206 2208 if not opts.get('date') and opts.get('currentdate'):
2207 2209 opts['date'] = "%d %d" % util.makedate()
2208 2210
2209 2211 editor = cmdutil.getcommiteditor(editform='graft', **opts)
2210 2212
2211 2213 cont = False
2212 2214 if opts.get('continue'):
2213 2215 cont = True
2214 2216 if revs:
2215 2217 raise error.Abort(_("can't specify --continue and revisions"))
2216 2218 # read in unfinished revisions
2217 2219 try:
2218 2220 nodes = repo.vfs.read('graftstate').splitlines()
2219 2221 revs = [repo[node].rev() for node in nodes]
2220 2222 except IOError as inst:
2221 2223 if inst.errno != errno.ENOENT:
2222 2224 raise
2223 2225 cmdutil.wrongtooltocontinue(repo, _('graft'))
2224 2226 else:
2225 2227 cmdutil.checkunfinished(repo)
2226 2228 cmdutil.bailifchanged(repo)
2227 2229 if not revs:
2228 2230 raise error.Abort(_('no revisions specified'))
2229 2231 revs = scmutil.revrange(repo, revs)
2230 2232
2231 2233 skipped = set()
2232 2234 # check for merges
2233 2235 for rev in repo.revs('%ld and merge()', revs):
2234 2236 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2235 2237 skipped.add(rev)
2236 2238 revs = [r for r in revs if r not in skipped]
2237 2239 if not revs:
2238 2240 return -1
2239 2241
2240 2242 # Don't check in the --continue case, in effect retaining --force across
2241 2243 # --continues. That's because without --force, any revisions we decided to
2242 2244 # skip would have been filtered out here, so they wouldn't have made their
2243 2245 # way to the graftstate. With --force, any revisions we would have otherwise
2244 2246 # skipped would not have been filtered out, and if they hadn't been applied
2245 2247 # already, they'd have been in the graftstate.
2246 2248 if not (cont or opts.get('force')):
2247 2249 # check for ancestors of dest branch
2248 2250 crev = repo['.'].rev()
2249 2251 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2250 2252 # XXX make this lazy in the future
2251 2253 # don't mutate while iterating, create a copy
2252 2254 for rev in list(revs):
2253 2255 if rev in ancestors:
2254 2256 ui.warn(_('skipping ancestor revision %d:%s\n') %
2255 2257 (rev, repo[rev]))
2256 2258 # XXX remove on list is slow
2257 2259 revs.remove(rev)
2258 2260 if not revs:
2259 2261 return -1
2260 2262
2261 2263 # analyze revs for earlier grafts
2262 2264 ids = {}
2263 2265 for ctx in repo.set("%ld", revs):
2264 2266 ids[ctx.hex()] = ctx.rev()
2265 2267 n = ctx.extra().get('source')
2266 2268 if n:
2267 2269 ids[n] = ctx.rev()
2268 2270
2269 2271 # check ancestors for earlier grafts
2270 2272 ui.debug('scanning for duplicate grafts\n')
2271 2273
2272 2274 for rev in repo.changelog.findmissingrevs(revs, [crev]):
2273 2275 ctx = repo[rev]
2274 2276 n = ctx.extra().get('source')
2275 2277 if n in ids:
2276 2278 try:
2277 2279 r = repo[n].rev()
2278 2280 except error.RepoLookupError:
2279 2281 r = None
2280 2282 if r in revs:
2281 2283 ui.warn(_('skipping revision %d:%s '
2282 2284 '(already grafted to %d:%s)\n')
2283 2285 % (r, repo[r], rev, ctx))
2284 2286 revs.remove(r)
2285 2287 elif ids[n] in revs:
2286 2288 if r is None:
2287 2289 ui.warn(_('skipping already grafted revision %d:%s '
2288 2290 '(%d:%s also has unknown origin %s)\n')
2289 2291 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
2290 2292 else:
2291 2293 ui.warn(_('skipping already grafted revision %d:%s '
2292 2294 '(%d:%s also has origin %d:%s)\n')
2293 2295 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
2294 2296 revs.remove(ids[n])
2295 2297 elif ctx.hex() in ids:
2296 2298 r = ids[ctx.hex()]
2297 2299 ui.warn(_('skipping already grafted revision %d:%s '
2298 2300 '(was grafted from %d:%s)\n') %
2299 2301 (r, repo[r], rev, ctx))
2300 2302 revs.remove(r)
2301 2303 if not revs:
2302 2304 return -1
2303 2305
2304 2306 for pos, ctx in enumerate(repo.set("%ld", revs)):
2305 2307 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
2306 2308 ctx.description().split('\n', 1)[0])
2307 2309 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
2308 2310 if names:
2309 2311 desc += ' (%s)' % ' '.join(names)
2310 2312 ui.status(_('grafting %s\n') % desc)
2311 2313 if opts.get('dry_run'):
2312 2314 continue
2313 2315
2314 2316 source = ctx.extra().get('source')
2315 2317 extra = {}
2316 2318 if source:
2317 2319 extra['source'] = source
2318 2320 extra['intermediate-source'] = ctx.hex()
2319 2321 else:
2320 2322 extra['source'] = ctx.hex()
2321 2323 user = ctx.user()
2322 2324 if opts.get('user'):
2323 2325 user = opts['user']
2324 2326 date = ctx.date()
2325 2327 if opts.get('date'):
2326 2328 date = opts['date']
2327 2329 message = ctx.description()
2328 2330 if opts.get('log'):
2329 2331 message += '\n(grafted from %s)' % ctx.hex()
2330 2332
2331 2333 # we don't merge the first commit when continuing
2332 2334 if not cont:
2333 2335 # perform the graft merge with p1(rev) as 'ancestor'
2334 2336 try:
2335 2337 # ui.forcemerge is an internal variable, do not document
2336 2338 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
2337 2339 'graft')
2338 2340 stats = mergemod.graft(repo, ctx, ctx.p1(),
2339 2341 ['local', 'graft'])
2340 2342 finally:
2341 2343 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
2342 2344 # report any conflicts
2343 2345 if stats and stats[3] > 0:
2344 2346 # write out state for --continue
2345 2347 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2346 2348 repo.vfs.write('graftstate', ''.join(nodelines))
2347 2349 extra = ''
2348 2350 if opts.get('user'):
2349 2351 extra += ' --user %s' % util.shellquote(opts['user'])
2350 2352 if opts.get('date'):
2351 2353 extra += ' --date %s' % util.shellquote(opts['date'])
2352 2354 if opts.get('log'):
2353 2355 extra += ' --log'
2354 2356 hint=_("use 'hg resolve' and 'hg graft --continue%s'") % extra
2355 2357 raise error.Abort(
2356 2358 _("unresolved conflicts, can't continue"),
2357 2359 hint=hint)
2358 2360 else:
2359 2361 cont = False
2360 2362
2361 2363 # commit
2362 2364 node = repo.commit(text=message, user=user,
2363 2365 date=date, extra=extra, editor=editor)
2364 2366 if node is None:
2365 2367 ui.warn(
2366 2368 _('note: graft of %d:%s created no changes to commit\n') %
2367 2369 (ctx.rev(), ctx))
2368 2370
2369 2371 # remove state when we complete successfully
2370 2372 if not opts.get('dry_run'):
2371 2373 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
2372 2374
2373 2375 return 0
2374 2376
2375 2377 @command('grep',
2376 2378 [('0', 'print0', None, _('end fields with NUL')),
2377 2379 ('', 'all', None, _('print all revisions that match')),
2378 2380 ('a', 'text', None, _('treat all files as text')),
2379 2381 ('f', 'follow', None,
2380 2382 _('follow changeset history,'
2381 2383 ' or file history across copies and renames')),
2382 2384 ('i', 'ignore-case', None, _('ignore case when matching')),
2383 2385 ('l', 'files-with-matches', None,
2384 2386 _('print only filenames and revisions that match')),
2385 2387 ('n', 'line-number', None, _('print matching line numbers')),
2386 2388 ('r', 'rev', [],
2387 2389 _('only search files changed within revision range'), _('REV')),
2388 2390 ('u', 'user', None, _('list the author (long with -v)')),
2389 2391 ('d', 'date', None, _('list the date (short with -q)')),
2390 2392 ] + formatteropts + walkopts,
2391 2393 _('[OPTION]... PATTERN [FILE]...'),
2392 2394 inferrepo=True)
2393 2395 def grep(ui, repo, pattern, *pats, **opts):
2394 2396 """search revision history for a pattern in specified files
2395 2397
2396 2398 Search revision history for a regular expression in the specified
2397 2399 files or the entire project.
2398 2400
2399 2401 By default, grep prints the most recent revision number for each
2400 2402 file in which it finds a match. To get it to print every revision
2401 2403 that contains a change in match status ("-" for a match that becomes
2402 2404 a non-match, or "+" for a non-match that becomes a match), use the
2403 2405 --all flag.
2404 2406
2405 2407 PATTERN can be any Python (roughly Perl-compatible) regular
2406 2408 expression.
2407 2409
2408 2410 If no FILEs are specified (and -f/--follow isn't set), all files in
2409 2411 the repository are searched, including those that don't exist in the
2410 2412 current branch or have been deleted in a prior changeset.
2411 2413
2412 2414 Returns 0 if a match is found, 1 otherwise.
2413 2415 """
2414 2416 reflags = re.M
2415 2417 if opts.get('ignore_case'):
2416 2418 reflags |= re.I
2417 2419 try:
2418 2420 regexp = util.re.compile(pattern, reflags)
2419 2421 except re.error as inst:
2420 2422 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2421 2423 return 1
2422 2424 sep, eol = ':', '\n'
2423 2425 if opts.get('print0'):
2424 2426 sep = eol = '\0'
2425 2427
2426 2428 getfile = util.lrucachefunc(repo.file)
2427 2429
2428 2430 def matchlines(body):
2429 2431 begin = 0
2430 2432 linenum = 0
2431 2433 while begin < len(body):
2432 2434 match = regexp.search(body, begin)
2433 2435 if not match:
2434 2436 break
2435 2437 mstart, mend = match.span()
2436 2438 linenum += body.count('\n', begin, mstart) + 1
2437 2439 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2438 2440 begin = body.find('\n', mend) + 1 or len(body) + 1
2439 2441 lend = begin - 1
2440 2442 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2441 2443
2442 2444 class linestate(object):
2443 2445 def __init__(self, line, linenum, colstart, colend):
2444 2446 self.line = line
2445 2447 self.linenum = linenum
2446 2448 self.colstart = colstart
2447 2449 self.colend = colend
2448 2450
2449 2451 def __hash__(self):
2450 2452 return hash((self.linenum, self.line))
2451 2453
2452 2454 def __eq__(self, other):
2453 2455 return self.line == other.line
2454 2456
2455 2457 def findpos(self):
2456 2458 """Iterate all (start, end) indices of matches"""
2457 2459 yield self.colstart, self.colend
2458 2460 p = self.colend
2459 2461 while p < len(self.line):
2460 2462 m = regexp.search(self.line, p)
2461 2463 if not m:
2462 2464 break
2463 2465 yield m.span()
2464 2466 p = m.end()
2465 2467
2466 2468 matches = {}
2467 2469 copies = {}
2468 2470 def grepbody(fn, rev, body):
2469 2471 matches[rev].setdefault(fn, [])
2470 2472 m = matches[rev][fn]
2471 2473 for lnum, cstart, cend, line in matchlines(body):
2472 2474 s = linestate(line, lnum, cstart, cend)
2473 2475 m.append(s)
2474 2476
2475 2477 def difflinestates(a, b):
2476 2478 sm = difflib.SequenceMatcher(None, a, b)
2477 2479 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2478 2480 if tag == 'insert':
2479 2481 for i in xrange(blo, bhi):
2480 2482 yield ('+', b[i])
2481 2483 elif tag == 'delete':
2482 2484 for i in xrange(alo, ahi):
2483 2485 yield ('-', a[i])
2484 2486 elif tag == 'replace':
2485 2487 for i in xrange(alo, ahi):
2486 2488 yield ('-', a[i])
2487 2489 for i in xrange(blo, bhi):
2488 2490 yield ('+', b[i])
2489 2491
2490 2492 def display(fm, fn, ctx, pstates, states):
2491 2493 rev = ctx.rev()
2492 2494 if fm.isplain():
2493 2495 formatuser = ui.shortuser
2494 2496 else:
2495 2497 formatuser = str
2496 2498 if ui.quiet:
2497 2499 datefmt = '%Y-%m-%d'
2498 2500 else:
2499 2501 datefmt = '%a %b %d %H:%M:%S %Y %1%2'
2500 2502 found = False
2501 2503 @util.cachefunc
2502 2504 def binary():
2503 2505 flog = getfile(fn)
2504 2506 return util.binary(flog.read(ctx.filenode(fn)))
2505 2507
2506 2508 fieldnamemap = {'filename': 'file', 'linenumber': 'line_number'}
2507 2509 if opts.get('all'):
2508 2510 iter = difflinestates(pstates, states)
2509 2511 else:
2510 2512 iter = [('', l) for l in states]
2511 2513 for change, l in iter:
2512 2514 fm.startitem()
2513 2515 fm.data(node=fm.hexfunc(ctx.node()))
2514 2516 cols = [
2515 2517 ('filename', fn, True),
2516 2518 ('rev', rev, True),
2517 2519 ('linenumber', l.linenum, opts.get('line_number')),
2518 2520 ]
2519 2521 if opts.get('all'):
2520 2522 cols.append(('change', change, True))
2521 2523 cols.extend([
2522 2524 ('user', formatuser(ctx.user()), opts.get('user')),
2523 2525 ('date', fm.formatdate(ctx.date(), datefmt), opts.get('date')),
2524 2526 ])
2525 2527 lastcol = next(name for name, data, cond in reversed(cols) if cond)
2526 2528 for name, data, cond in cols:
2527 2529 field = fieldnamemap.get(name, name)
2528 2530 fm.condwrite(cond, field, '%s', data, label='grep.%s' % name)
2529 2531 if cond and name != lastcol:
2530 2532 fm.plain(sep, label='grep.sep')
2531 2533 if not opts.get('files_with_matches'):
2532 2534 fm.plain(sep, label='grep.sep')
2533 2535 if not opts.get('text') and binary():
2534 2536 fm.plain(_(" Binary file matches"))
2535 2537 else:
2536 2538 displaymatches(fm.nested('texts'), l)
2537 2539 fm.plain(eol)
2538 2540 found = True
2539 2541 if opts.get('files_with_matches'):
2540 2542 break
2541 2543 return found
2542 2544
2543 2545 def displaymatches(fm, l):
2544 2546 p = 0
2545 2547 for s, e in l.findpos():
2546 2548 if p < s:
2547 2549 fm.startitem()
2548 2550 fm.write('text', '%s', l.line[p:s])
2549 2551 fm.data(matched=False)
2550 2552 fm.startitem()
2551 2553 fm.write('text', '%s', l.line[s:e], label='grep.match')
2552 2554 fm.data(matched=True)
2553 2555 p = e
2554 2556 if p < len(l.line):
2555 2557 fm.startitem()
2556 2558 fm.write('text', '%s', l.line[p:])
2557 2559 fm.data(matched=False)
2558 2560 fm.end()
2559 2561
2560 2562 skip = {}
2561 2563 revfiles = {}
2562 2564 matchfn = scmutil.match(repo[None], pats, opts)
2563 2565 found = False
2564 2566 follow = opts.get('follow')
2565 2567
2566 2568 def prep(ctx, fns):
2567 2569 rev = ctx.rev()
2568 2570 pctx = ctx.p1()
2569 2571 parent = pctx.rev()
2570 2572 matches.setdefault(rev, {})
2571 2573 matches.setdefault(parent, {})
2572 2574 files = revfiles.setdefault(rev, [])
2573 2575 for fn in fns:
2574 2576 flog = getfile(fn)
2575 2577 try:
2576 2578 fnode = ctx.filenode(fn)
2577 2579 except error.LookupError:
2578 2580 continue
2579 2581
2580 2582 copied = flog.renamed(fnode)
2581 2583 copy = follow and copied and copied[0]
2582 2584 if copy:
2583 2585 copies.setdefault(rev, {})[fn] = copy
2584 2586 if fn in skip:
2585 2587 if copy:
2586 2588 skip[copy] = True
2587 2589 continue
2588 2590 files.append(fn)
2589 2591
2590 2592 if fn not in matches[rev]:
2591 2593 grepbody(fn, rev, flog.read(fnode))
2592 2594
2593 2595 pfn = copy or fn
2594 2596 if pfn not in matches[parent]:
2595 2597 try:
2596 2598 fnode = pctx.filenode(pfn)
2597 2599 grepbody(pfn, parent, flog.read(fnode))
2598 2600 except error.LookupError:
2599 2601 pass
2600 2602
2601 2603 fm = ui.formatter('grep', opts)
2602 2604 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2603 2605 rev = ctx.rev()
2604 2606 parent = ctx.p1().rev()
2605 2607 for fn in sorted(revfiles.get(rev, [])):
2606 2608 states = matches[rev][fn]
2607 2609 copy = copies.get(rev, {}).get(fn)
2608 2610 if fn in skip:
2609 2611 if copy:
2610 2612 skip[copy] = True
2611 2613 continue
2612 2614 pstates = matches.get(parent, {}).get(copy or fn, [])
2613 2615 if pstates or states:
2614 2616 r = display(fm, fn, ctx, pstates, states)
2615 2617 found = found or r
2616 2618 if r and not opts.get('all'):
2617 2619 skip[fn] = True
2618 2620 if copy:
2619 2621 skip[copy] = True
2620 2622 del matches[rev]
2621 2623 del revfiles[rev]
2622 2624 fm.end()
2623 2625
2624 2626 return not found
2625 2627
2626 2628 @command('heads',
2627 2629 [('r', 'rev', '',
2628 2630 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
2629 2631 ('t', 'topo', False, _('show topological heads only')),
2630 2632 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
2631 2633 ('c', 'closed', False, _('show normal and closed branch heads')),
2632 2634 ] + templateopts,
2633 2635 _('[-ct] [-r STARTREV] [REV]...'))
2634 2636 def heads(ui, repo, *branchrevs, **opts):
2635 2637 """show branch heads
2636 2638
2637 2639 With no arguments, show all open branch heads in the repository.
2638 2640 Branch heads are changesets that have no descendants on the
2639 2641 same branch. They are where development generally takes place and
2640 2642 are the usual targets for update and merge operations.
2641 2643
2642 2644 If one or more REVs are given, only open branch heads on the
2643 2645 branches associated with the specified changesets are shown. This
2644 2646 means that you can use :hg:`heads .` to see the heads on the
2645 2647 currently checked-out branch.
2646 2648
2647 2649 If -c/--closed is specified, also show branch heads marked closed
2648 2650 (see :hg:`commit --close-branch`).
2649 2651
2650 2652 If STARTREV is specified, only those heads that are descendants of
2651 2653 STARTREV will be displayed.
2652 2654
2653 2655 If -t/--topo is specified, named branch mechanics will be ignored and only
2654 2656 topological heads (changesets with no children) will be shown.
2655 2657
2656 2658 Returns 0 if matching heads are found, 1 if not.
2657 2659 """
2658 2660
2659 2661 start = None
2660 2662 if 'rev' in opts:
2661 2663 start = scmutil.revsingle(repo, opts['rev'], None).node()
2662 2664
2663 2665 if opts.get('topo'):
2664 2666 heads = [repo[h] for h in repo.heads(start)]
2665 2667 else:
2666 2668 heads = []
2667 2669 for branch in repo.branchmap():
2668 2670 heads += repo.branchheads(branch, start, opts.get('closed'))
2669 2671 heads = [repo[h] for h in heads]
2670 2672
2671 2673 if branchrevs:
2672 2674 branches = set(repo[br].branch() for br in branchrevs)
2673 2675 heads = [h for h in heads if h.branch() in branches]
2674 2676
2675 2677 if opts.get('active') and branchrevs:
2676 2678 dagheads = repo.heads(start)
2677 2679 heads = [h for h in heads if h.node() in dagheads]
2678 2680
2679 2681 if branchrevs:
2680 2682 haveheads = set(h.branch() for h in heads)
2681 2683 if branches - haveheads:
2682 2684 headless = ', '.join(b for b in branches - haveheads)
2683 2685 msg = _('no open branch heads found on branches %s')
2684 2686 if opts.get('rev'):
2685 2687 msg += _(' (started at %s)') % opts['rev']
2686 2688 ui.warn((msg + '\n') % headless)
2687 2689
2688 2690 if not heads:
2689 2691 return 1
2690 2692
2691 2693 heads = sorted(heads, key=lambda x: -x.rev())
2692 2694 displayer = cmdutil.show_changeset(ui, repo, opts)
2693 2695 for ctx in heads:
2694 2696 displayer.show(ctx)
2695 2697 displayer.close()
2696 2698
2697 2699 @command('help',
2698 2700 [('e', 'extension', None, _('show only help for extensions')),
2699 2701 ('c', 'command', None, _('show only help for commands')),
2700 2702 ('k', 'keyword', None, _('show topics matching keyword')),
2701 2703 ('s', 'system', [], _('show help for specific platform(s)')),
2702 2704 ],
2703 2705 _('[-ecks] [TOPIC]'),
2704 2706 norepo=True)
2705 2707 def help_(ui, name=None, **opts):
2706 2708 """show help for a given topic or a help overview
2707 2709
2708 2710 With no arguments, print a list of commands with short help messages.
2709 2711
2710 2712 Given a topic, extension, or command name, print help for that
2711 2713 topic.
2712 2714
2713 2715 Returns 0 if successful.
2714 2716 """
2715 2717
2716 2718 textwidth = ui.configint('ui', 'textwidth', 78)
2717 2719 termwidth = ui.termwidth() - 2
2718 2720 if textwidth <= 0 or termwidth < textwidth:
2719 2721 textwidth = termwidth
2720 2722
2721 2723 keep = opts.get('system') or []
2722 2724 if len(keep) == 0:
2723 2725 if pycompat.sysplatform.startswith('win'):
2724 2726 keep.append('windows')
2725 2727 elif pycompat.sysplatform == 'OpenVMS':
2726 2728 keep.append('vms')
2727 2729 elif pycompat.sysplatform == 'plan9':
2728 2730 keep.append('plan9')
2729 2731 else:
2730 2732 keep.append('unix')
2731 2733 keep.append(pycompat.sysplatform.lower())
2732 2734 if ui.verbose:
2733 2735 keep.append('verbose')
2734 2736
2735 2737 fullname = name
2736 2738 section = None
2737 2739 subtopic = None
2738 2740 if name and '.' in name:
2739 2741 name, remaining = name.split('.', 1)
2740 2742 remaining = encoding.lower(remaining)
2741 2743 if '.' in remaining:
2742 2744 subtopic, section = remaining.split('.', 1)
2743 2745 else:
2744 2746 if name in help.subtopics:
2745 2747 subtopic = remaining
2746 2748 else:
2747 2749 section = remaining
2748 2750
2749 2751 text = help.help_(ui, name, subtopic=subtopic, **opts)
2750 2752
2751 2753 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2752 2754 section=section)
2753 2755
2754 2756 # We could have been given a weird ".foo" section without a name
2755 2757 # to look for, or we could have simply failed to found "foo.bar"
2756 2758 # because bar isn't a section of foo
2757 2759 if section and not (formatted and name):
2758 2760 raise error.Abort(_("help section not found: %s") % fullname)
2759 2761
2760 2762 if 'verbose' in pruned:
2761 2763 keep.append('omitted')
2762 2764 else:
2763 2765 keep.append('notomitted')
2764 2766 formatted, pruned = minirst.format(text, textwidth, keep=keep,
2765 2767 section=section)
2766 2768 ui.write(formatted)
2767 2769
2768 2770
2769 2771 @command('identify|id',
2770 2772 [('r', 'rev', '',
2771 2773 _('identify the specified revision'), _('REV')),
2772 2774 ('n', 'num', None, _('show local revision number')),
2773 2775 ('i', 'id', None, _('show global revision id')),
2774 2776 ('b', 'branch', None, _('show branch')),
2775 2777 ('t', 'tags', None, _('show tags')),
2776 2778 ('B', 'bookmarks', None, _('show bookmarks')),
2777 2779 ] + remoteopts,
2778 2780 _('[-nibtB] [-r REV] [SOURCE]'),
2779 2781 optionalrepo=True)
2780 2782 def identify(ui, repo, source=None, rev=None,
2781 2783 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
2782 2784 """identify the working directory or specified revision
2783 2785
2784 2786 Print a summary identifying the repository state at REV using one or
2785 2787 two parent hash identifiers, followed by a "+" if the working
2786 2788 directory has uncommitted changes, the branch name (if not default),
2787 2789 a list of tags, and a list of bookmarks.
2788 2790
2789 2791 When REV is not given, print a summary of the current state of the
2790 2792 repository.
2791 2793
2792 2794 Specifying a path to a repository root or Mercurial bundle will
2793 2795 cause lookup to operate on that repository/bundle.
2794 2796
2795 2797 .. container:: verbose
2796 2798
2797 2799 Examples:
2798 2800
2799 2801 - generate a build identifier for the working directory::
2800 2802
2801 2803 hg id --id > build-id.dat
2802 2804
2803 2805 - find the revision corresponding to a tag::
2804 2806
2805 2807 hg id -n -r 1.3
2806 2808
2807 2809 - check the most recent revision of a remote repository::
2808 2810
2809 2811 hg id -r tip https://www.mercurial-scm.org/repo/hg/
2810 2812
2811 2813 See :hg:`log` for generating more information about specific revisions,
2812 2814 including full hash identifiers.
2813 2815
2814 2816 Returns 0 if successful.
2815 2817 """
2816 2818
2817 2819 if not repo and not source:
2818 2820 raise error.Abort(_("there is no Mercurial repository here "
2819 2821 "(.hg not found)"))
2820 2822
2821 2823 if ui.debugflag:
2822 2824 hexfunc = hex
2823 2825 else:
2824 2826 hexfunc = short
2825 2827 default = not (num or id or branch or tags or bookmarks)
2826 2828 output = []
2827 2829 revs = []
2828 2830
2829 2831 if source:
2830 2832 source, branches = hg.parseurl(ui.expandpath(source))
2831 2833 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
2832 2834 repo = peer.local()
2833 2835 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
2834 2836
2835 2837 if not repo:
2836 2838 if num or branch or tags:
2837 2839 raise error.Abort(
2838 2840 _("can't query remote revision number, branch, or tags"))
2839 2841 if not rev and revs:
2840 2842 rev = revs[0]
2841 2843 if not rev:
2842 2844 rev = "tip"
2843 2845
2844 2846 remoterev = peer.lookup(rev)
2845 2847 if default or id:
2846 2848 output = [hexfunc(remoterev)]
2847 2849
2848 2850 def getbms():
2849 2851 bms = []
2850 2852
2851 2853 if 'bookmarks' in peer.listkeys('namespaces'):
2852 2854 hexremoterev = hex(remoterev)
2853 2855 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
2854 2856 if bmr == hexremoterev]
2855 2857
2856 2858 return sorted(bms)
2857 2859
2858 2860 if bookmarks:
2859 2861 output.extend(getbms())
2860 2862 elif default and not ui.quiet:
2861 2863 # multiple bookmarks for a single parent separated by '/'
2862 2864 bm = '/'.join(getbms())
2863 2865 if bm:
2864 2866 output.append(bm)
2865 2867 else:
2866 2868 ctx = scmutil.revsingle(repo, rev, None)
2867 2869
2868 2870 if ctx.rev() is None:
2869 2871 ctx = repo[None]
2870 2872 parents = ctx.parents()
2871 2873 taglist = []
2872 2874 for p in parents:
2873 2875 taglist.extend(p.tags())
2874 2876
2875 2877 changed = ""
2876 2878 if default or id or num:
2877 2879 if (any(repo.status())
2878 2880 or any(ctx.sub(s).dirty() for s in ctx.substate)):
2879 2881 changed = '+'
2880 2882 if default or id:
2881 2883 output = ["%s%s" %
2882 2884 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
2883 2885 if num:
2884 2886 output.append("%s%s" %
2885 2887 ('+'.join([str(p.rev()) for p in parents]), changed))
2886 2888 else:
2887 2889 if default or id:
2888 2890 output = [hexfunc(ctx.node())]
2889 2891 if num:
2890 2892 output.append(str(ctx.rev()))
2891 2893 taglist = ctx.tags()
2892 2894
2893 2895 if default and not ui.quiet:
2894 2896 b = ctx.branch()
2895 2897 if b != 'default':
2896 2898 output.append("(%s)" % b)
2897 2899
2898 2900 # multiple tags for a single parent separated by '/'
2899 2901 t = '/'.join(taglist)
2900 2902 if t:
2901 2903 output.append(t)
2902 2904
2903 2905 # multiple bookmarks for a single parent separated by '/'
2904 2906 bm = '/'.join(ctx.bookmarks())
2905 2907 if bm:
2906 2908 output.append(bm)
2907 2909 else:
2908 2910 if branch:
2909 2911 output.append(ctx.branch())
2910 2912
2911 2913 if tags:
2912 2914 output.extend(taglist)
2913 2915
2914 2916 if bookmarks:
2915 2917 output.extend(ctx.bookmarks())
2916 2918
2917 2919 ui.write("%s\n" % ' '.join(output))
2918 2920
2919 2921 @command('import|patch',
2920 2922 [('p', 'strip', 1,
2921 2923 _('directory strip option for patch. This has the same '
2922 2924 'meaning as the corresponding patch option'), _('NUM')),
2923 2925 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
2924 2926 ('e', 'edit', False, _('invoke editor on commit messages')),
2925 2927 ('f', 'force', None,
2926 2928 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
2927 2929 ('', 'no-commit', None,
2928 2930 _("don't commit, just update the working directory")),
2929 2931 ('', 'bypass', None,
2930 2932 _("apply patch without touching the working directory")),
2931 2933 ('', 'partial', None,
2932 2934 _('commit even if some hunks fail')),
2933 2935 ('', 'exact', None,
2934 2936 _('abort if patch would apply lossily')),
2935 2937 ('', 'prefix', '',
2936 2938 _('apply patch to subdirectory'), _('DIR')),
2937 2939 ('', 'import-branch', None,
2938 2940 _('use any branch information in patch (implied by --exact)'))] +
2939 2941 commitopts + commitopts2 + similarityopts,
2940 2942 _('[OPTION]... PATCH...'))
2941 2943 def import_(ui, repo, patch1=None, *patches, **opts):
2942 2944 """import an ordered set of patches
2943 2945
2944 2946 Import a list of patches and commit them individually (unless
2945 2947 --no-commit is specified).
2946 2948
2947 2949 To read a patch from standard input (stdin), use "-" as the patch
2948 2950 name. If a URL is specified, the patch will be downloaded from
2949 2951 there.
2950 2952
2951 2953 Import first applies changes to the working directory (unless
2952 2954 --bypass is specified), import will abort if there are outstanding
2953 2955 changes.
2954 2956
2955 2957 Use --bypass to apply and commit patches directly to the
2956 2958 repository, without affecting the working directory. Without
2957 2959 --exact, patches will be applied on top of the working directory
2958 2960 parent revision.
2959 2961
2960 2962 You can import a patch straight from a mail message. Even patches
2961 2963 as attachments work (to use the body part, it must have type
2962 2964 text/plain or text/x-patch). From and Subject headers of email
2963 2965 message are used as default committer and commit message. All
2964 2966 text/plain body parts before first diff are added to the commit
2965 2967 message.
2966 2968
2967 2969 If the imported patch was generated by :hg:`export`, user and
2968 2970 description from patch override values from message headers and
2969 2971 body. Values given on command line with -m/--message and -u/--user
2970 2972 override these.
2971 2973
2972 2974 If --exact is specified, import will set the working directory to
2973 2975 the parent of each patch before applying it, and will abort if the
2974 2976 resulting changeset has a different ID than the one recorded in
2975 2977 the patch. This will guard against various ways that portable
2976 2978 patch formats and mail systems might fail to transfer Mercurial
2977 2979 data or metadata. See :hg:`bundle` for lossless transmission.
2978 2980
2979 2981 Use --partial to ensure a changeset will be created from the patch
2980 2982 even if some hunks fail to apply. Hunks that fail to apply will be
2981 2983 written to a <target-file>.rej file. Conflicts can then be resolved
2982 2984 by hand before :hg:`commit --amend` is run to update the created
2983 2985 changeset. This flag exists to let people import patches that
2984 2986 partially apply without losing the associated metadata (author,
2985 2987 date, description, ...).
2986 2988
2987 2989 .. note::
2988 2990
2989 2991 When no hunks apply cleanly, :hg:`import --partial` will create
2990 2992 an empty changeset, importing only the patch metadata.
2991 2993
2992 2994 With -s/--similarity, hg will attempt to discover renames and
2993 2995 copies in the patch in the same way as :hg:`addremove`.
2994 2996
2995 2997 It is possible to use external patch programs to perform the patch
2996 2998 by setting the ``ui.patch`` configuration option. For the default
2997 2999 internal tool, the fuzz can also be configured via ``patch.fuzz``.
2998 3000 See :hg:`help config` for more information about configuration
2999 3001 files and how to use these options.
3000 3002
3001 3003 See :hg:`help dates` for a list of formats valid for -d/--date.
3002 3004
3003 3005 .. container:: verbose
3004 3006
3005 3007 Examples:
3006 3008
3007 3009 - import a traditional patch from a website and detect renames::
3008 3010
3009 3011 hg import -s 80 http://example.com/bugfix.patch
3010 3012
3011 3013 - import a changeset from an hgweb server::
3012 3014
3013 3015 hg import https://www.mercurial-scm.org/repo/hg/rev/5ca8c111e9aa
3014 3016
3015 3017 - import all the patches in an Unix-style mbox::
3016 3018
3017 3019 hg import incoming-patches.mbox
3018 3020
3019 3021 - import patches from stdin::
3020 3022
3021 3023 hg import -
3022 3024
3023 3025 - attempt to exactly restore an exported changeset (not always
3024 3026 possible)::
3025 3027
3026 3028 hg import --exact proposed-fix.patch
3027 3029
3028 3030 - use an external tool to apply a patch which is too fuzzy for
3029 3031 the default internal tool.
3030 3032
3031 3033 hg import --config ui.patch="patch --merge" fuzzy.patch
3032 3034
3033 3035 - change the default fuzzing from 2 to a less strict 7
3034 3036
3035 3037 hg import --config ui.fuzz=7 fuzz.patch
3036 3038
3037 3039 Returns 0 on success, 1 on partial success (see --partial).
3038 3040 """
3039 3041
3040 3042 if not patch1:
3041 3043 raise error.Abort(_('need at least one patch to import'))
3042 3044
3043 3045 patches = (patch1,) + patches
3044 3046
3045 3047 date = opts.get('date')
3046 3048 if date:
3047 3049 opts['date'] = util.parsedate(date)
3048 3050
3049 3051 exact = opts.get('exact')
3050 3052 update = not opts.get('bypass')
3051 3053 if not update and opts.get('no_commit'):
3052 3054 raise error.Abort(_('cannot use --no-commit with --bypass'))
3053 3055 try:
3054 3056 sim = float(opts.get('similarity') or 0)
3055 3057 except ValueError:
3056 3058 raise error.Abort(_('similarity must be a number'))
3057 3059 if sim < 0 or sim > 100:
3058 3060 raise error.Abort(_('similarity must be between 0 and 100'))
3059 3061 if sim and not update:
3060 3062 raise error.Abort(_('cannot use --similarity with --bypass'))
3061 3063 if exact:
3062 3064 if opts.get('edit'):
3063 3065 raise error.Abort(_('cannot use --exact with --edit'))
3064 3066 if opts.get('prefix'):
3065 3067 raise error.Abort(_('cannot use --exact with --prefix'))
3066 3068
3067 3069 base = opts["base"]
3068 3070 wlock = dsguard = lock = tr = None
3069 3071 msgs = []
3070 3072 ret = 0
3071 3073
3072 3074
3073 3075 try:
3074 3076 wlock = repo.wlock()
3075 3077
3076 3078 if update:
3077 3079 cmdutil.checkunfinished(repo)
3078 3080 if (exact or not opts.get('force')):
3079 3081 cmdutil.bailifchanged(repo)
3080 3082
3081 3083 if not opts.get('no_commit'):
3082 3084 lock = repo.lock()
3083 3085 tr = repo.transaction('import')
3084 3086 else:
3085 3087 dsguard = dirstateguard.dirstateguard(repo, 'import')
3086 3088 parents = repo[None].parents()
3087 3089 for patchurl in patches:
3088 3090 if patchurl == '-':
3089 3091 ui.status(_('applying patch from stdin\n'))
3090 3092 patchfile = ui.fin
3091 3093 patchurl = 'stdin' # for error message
3092 3094 else:
3093 3095 patchurl = os.path.join(base, patchurl)
3094 3096 ui.status(_('applying %s\n') % patchurl)
3095 3097 patchfile = hg.openpath(ui, patchurl)
3096 3098
3097 3099 haspatch = False
3098 3100 for hunk in patch.split(patchfile):
3099 3101 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
3100 3102 parents, opts,
3101 3103 msgs, hg.clean)
3102 3104 if msg:
3103 3105 haspatch = True
3104 3106 ui.note(msg + '\n')
3105 3107 if update or exact:
3106 3108 parents = repo[None].parents()
3107 3109 else:
3108 3110 parents = [repo[node]]
3109 3111 if rej:
3110 3112 ui.write_err(_("patch applied partially\n"))
3111 3113 ui.write_err(_("(fix the .rej files and run "
3112 3114 "`hg commit --amend`)\n"))
3113 3115 ret = 1
3114 3116 break
3115 3117
3116 3118 if not haspatch:
3117 3119 raise error.Abort(_('%s: no diffs found') % patchurl)
3118 3120
3119 3121 if tr:
3120 3122 tr.close()
3121 3123 if msgs:
3122 3124 repo.savecommitmessage('\n* * *\n'.join(msgs))
3123 3125 if dsguard:
3124 3126 dsguard.close()
3125 3127 return ret
3126 3128 finally:
3127 3129 if tr:
3128 3130 tr.release()
3129 3131 release(lock, dsguard, wlock)
3130 3132
3131 3133 @command('incoming|in',
3132 3134 [('f', 'force', None,
3133 3135 _('run even if remote repository is unrelated')),
3134 3136 ('n', 'newest-first', None, _('show newest record first')),
3135 3137 ('', 'bundle', '',
3136 3138 _('file to store the bundles into'), _('FILE')),
3137 3139 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3138 3140 ('B', 'bookmarks', False, _("compare bookmarks")),
3139 3141 ('b', 'branch', [],
3140 3142 _('a specific branch you would like to pull'), _('BRANCH')),
3141 3143 ] + logopts + remoteopts + subrepoopts,
3142 3144 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3143 3145 def incoming(ui, repo, source="default", **opts):
3144 3146 """show new changesets found in source
3145 3147
3146 3148 Show new changesets found in the specified path/URL or the default
3147 3149 pull location. These are the changesets that would have been pulled
3148 3150 if a pull at the time you issued this command.
3149 3151
3150 3152 See pull for valid source format details.
3151 3153
3152 3154 .. container:: verbose
3153 3155
3154 3156 With -B/--bookmarks, the result of bookmark comparison between
3155 3157 local and remote repositories is displayed. With -v/--verbose,
3156 3158 status is also displayed for each bookmark like below::
3157 3159
3158 3160 BM1 01234567890a added
3159 3161 BM2 1234567890ab advanced
3160 3162 BM3 234567890abc diverged
3161 3163 BM4 34567890abcd changed
3162 3164
3163 3165 The action taken locally when pulling depends on the
3164 3166 status of each bookmark:
3165 3167
3166 3168 :``added``: pull will create it
3167 3169 :``advanced``: pull will update it
3168 3170 :``diverged``: pull will create a divergent bookmark
3169 3171 :``changed``: result depends on remote changesets
3170 3172
3171 3173 From the point of view of pulling behavior, bookmark
3172 3174 existing only in the remote repository are treated as ``added``,
3173 3175 even if it is in fact locally deleted.
3174 3176
3175 3177 .. container:: verbose
3176 3178
3177 3179 For remote repository, using --bundle avoids downloading the
3178 3180 changesets twice if the incoming is followed by a pull.
3179 3181
3180 3182 Examples:
3181 3183
3182 3184 - show incoming changes with patches and full description::
3183 3185
3184 3186 hg incoming -vp
3185 3187
3186 3188 - show incoming changes excluding merges, store a bundle::
3187 3189
3188 3190 hg in -vpM --bundle incoming.hg
3189 3191 hg pull incoming.hg
3190 3192
3191 3193 - briefly list changes inside a bundle::
3192 3194
3193 3195 hg in changes.hg -T "{desc|firstline}\\n"
3194 3196
3195 3197 Returns 0 if there are incoming changes, 1 otherwise.
3196 3198 """
3197 3199 if opts.get('graph'):
3198 3200 cmdutil.checkunsupportedgraphflags([], opts)
3199 3201 def display(other, chlist, displayer):
3200 3202 revdag = cmdutil.graphrevs(other, chlist, opts)
3201 3203 cmdutil.displaygraph(ui, repo, revdag, displayer,
3202 3204 graphmod.asciiedges)
3203 3205
3204 3206 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3205 3207 return 0
3206 3208
3207 3209 if opts.get('bundle') and opts.get('subrepos'):
3208 3210 raise error.Abort(_('cannot combine --bundle and --subrepos'))
3209 3211
3210 3212 if opts.get('bookmarks'):
3211 3213 source, branches = hg.parseurl(ui.expandpath(source),
3212 3214 opts.get('branch'))
3213 3215 other = hg.peer(repo, opts, source)
3214 3216 if 'bookmarks' not in other.listkeys('namespaces'):
3215 3217 ui.warn(_("remote doesn't support bookmarks\n"))
3216 3218 return 0
3217 3219 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3218 3220 return bookmarks.incoming(ui, repo, other)
3219 3221
3220 3222 repo._subtoppath = ui.expandpath(source)
3221 3223 try:
3222 3224 return hg.incoming(ui, repo, source, opts)
3223 3225 finally:
3224 3226 del repo._subtoppath
3225 3227
3226 3228
3227 3229 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
3228 3230 norepo=True)
3229 3231 def init(ui, dest=".", **opts):
3230 3232 """create a new repository in the given directory
3231 3233
3232 3234 Initialize a new repository in the given directory. If the given
3233 3235 directory does not exist, it will be created.
3234 3236
3235 3237 If no directory is given, the current directory is used.
3236 3238
3237 3239 It is possible to specify an ``ssh://`` URL as the destination.
3238 3240 See :hg:`help urls` for more information.
3239 3241
3240 3242 Returns 0 on success.
3241 3243 """
3242 3244 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3243 3245
3244 3246 @command('locate',
3245 3247 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3246 3248 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3247 3249 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3248 3250 ] + walkopts,
3249 3251 _('[OPTION]... [PATTERN]...'))
3250 3252 def locate(ui, repo, *pats, **opts):
3251 3253 """locate files matching specific patterns (DEPRECATED)
3252 3254
3253 3255 Print files under Mercurial control in the working directory whose
3254 3256 names match the given patterns.
3255 3257
3256 3258 By default, this command searches all directories in the working
3257 3259 directory. To search just the current directory and its
3258 3260 subdirectories, use "--include .".
3259 3261
3260 3262 If no patterns are given to match, this command prints the names
3261 3263 of all files under Mercurial control in the working directory.
3262 3264
3263 3265 If you want to feed the output of this command into the "xargs"
3264 3266 command, use the -0 option to both this command and "xargs". This
3265 3267 will avoid the problem of "xargs" treating single filenames that
3266 3268 contain whitespace as multiple filenames.
3267 3269
3268 3270 See :hg:`help files` for a more versatile command.
3269 3271
3270 3272 Returns 0 if a match is found, 1 otherwise.
3271 3273 """
3272 3274 if opts.get('print0'):
3273 3275 end = '\0'
3274 3276 else:
3275 3277 end = '\n'
3276 3278 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3277 3279
3278 3280 ret = 1
3279 3281 ctx = repo[rev]
3280 3282 m = scmutil.match(ctx, pats, opts, default='relglob',
3281 3283 badfn=lambda x, y: False)
3282 3284
3283 3285 for abs in ctx.matches(m):
3284 3286 if opts.get('fullpath'):
3285 3287 ui.write(repo.wjoin(abs), end)
3286 3288 else:
3287 3289 ui.write(((pats and m.rel(abs)) or abs), end)
3288 3290 ret = 0
3289 3291
3290 3292 return ret
3291 3293
3292 3294 @command('^log|history',
3293 3295 [('f', 'follow', None,
3294 3296 _('follow changeset history, or file history across copies and renames')),
3295 3297 ('', 'follow-first', None,
3296 3298 _('only follow the first parent of merge changesets (DEPRECATED)')),
3297 3299 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3298 3300 ('C', 'copies', None, _('show copied files')),
3299 3301 ('k', 'keyword', [],
3300 3302 _('do case-insensitive search for a given text'), _('TEXT')),
3301 3303 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
3302 3304 ('', 'removed', None, _('include revisions where files were removed')),
3303 3305 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3304 3306 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3305 3307 ('', 'only-branch', [],
3306 3308 _('show only changesets within the given named branch (DEPRECATED)'),
3307 3309 _('BRANCH')),
3308 3310 ('b', 'branch', [],
3309 3311 _('show changesets within the given named branch'), _('BRANCH')),
3310 3312 ('P', 'prune', [],
3311 3313 _('do not display revision or any of its ancestors'), _('REV')),
3312 3314 ] + logopts + walkopts,
3313 3315 _('[OPTION]... [FILE]'),
3314 3316 inferrepo=True)
3315 3317 def log(ui, repo, *pats, **opts):
3316 3318 """show revision history of entire repository or files
3317 3319
3318 3320 Print the revision history of the specified files or the entire
3319 3321 project.
3320 3322
3321 3323 If no revision range is specified, the default is ``tip:0`` unless
3322 3324 --follow is set, in which case the working directory parent is
3323 3325 used as the starting revision.
3324 3326
3325 3327 File history is shown without following rename or copy history of
3326 3328 files. Use -f/--follow with a filename to follow history across
3327 3329 renames and copies. --follow without a filename will only show
3328 3330 ancestors or descendants of the starting revision.
3329 3331
3330 3332 By default this command prints revision number and changeset id,
3331 3333 tags, non-trivial parents, user, date and time, and a summary for
3332 3334 each commit. When the -v/--verbose switch is used, the list of
3333 3335 changed files and full commit message are shown.
3334 3336
3335 3337 With --graph the revisions are shown as an ASCII art DAG with the most
3336 3338 recent changeset at the top.
3337 3339 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
3338 3340 and '+' represents a fork where the changeset from the lines below is a
3339 3341 parent of the 'o' merge on the same line.
3340 3342
3341 3343 .. note::
3342 3344
3343 3345 :hg:`log --patch` may generate unexpected diff output for merge
3344 3346 changesets, as it will only compare the merge changeset against
3345 3347 its first parent. Also, only files different from BOTH parents
3346 3348 will appear in files:.
3347 3349
3348 3350 .. note::
3349 3351
3350 3352 For performance reasons, :hg:`log FILE` may omit duplicate changes
3351 3353 made on branches and will not show removals or mode changes. To
3352 3354 see all such changes, use the --removed switch.
3353 3355
3354 3356 .. container:: verbose
3355 3357
3356 3358 Some examples:
3357 3359
3358 3360 - changesets with full descriptions and file lists::
3359 3361
3360 3362 hg log -v
3361 3363
3362 3364 - changesets ancestral to the working directory::
3363 3365
3364 3366 hg log -f
3365 3367
3366 3368 - last 10 commits on the current branch::
3367 3369
3368 3370 hg log -l 10 -b .
3369 3371
3370 3372 - changesets showing all modifications of a file, including removals::
3371 3373
3372 3374 hg log --removed file.c
3373 3375
3374 3376 - all changesets that touch a directory, with diffs, excluding merges::
3375 3377
3376 3378 hg log -Mp lib/
3377 3379
3378 3380 - all revision numbers that match a keyword::
3379 3381
3380 3382 hg log -k bug --template "{rev}\\n"
3381 3383
3382 3384 - the full hash identifier of the working directory parent::
3383 3385
3384 3386 hg log -r . --template "{node}\\n"
3385 3387
3386 3388 - list available log templates::
3387 3389
3388 3390 hg log -T list
3389 3391
3390 3392 - check if a given changeset is included in a tagged release::
3391 3393
3392 3394 hg log -r "a21ccf and ancestor(1.9)"
3393 3395
3394 3396 - find all changesets by some user in a date range::
3395 3397
3396 3398 hg log -k alice -d "may 2008 to jul 2008"
3397 3399
3398 3400 - summary of all changesets after the last tag::
3399 3401
3400 3402 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3401 3403
3402 3404 See :hg:`help dates` for a list of formats valid for -d/--date.
3403 3405
3404 3406 See :hg:`help revisions` for more about specifying and ordering
3405 3407 revisions.
3406 3408
3407 3409 See :hg:`help templates` for more about pre-packaged styles and
3408 3410 specifying custom templates.
3409 3411
3410 3412 Returns 0 on success.
3411 3413
3412 3414 """
3413 3415 if opts.get('follow') and opts.get('rev'):
3414 3416 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
3415 3417 del opts['follow']
3416 3418
3417 3419 if opts.get('graph'):
3418 3420 return cmdutil.graphlog(ui, repo, *pats, **opts)
3419 3421
3420 3422 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
3421 3423 limit = cmdutil.loglimit(opts)
3422 3424 count = 0
3423 3425
3424 3426 getrenamed = None
3425 3427 if opts.get('copies'):
3426 3428 endrev = None
3427 3429 if opts.get('rev'):
3428 3430 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
3429 3431 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3430 3432
3431 3433 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3432 3434 for rev in revs:
3433 3435 if count == limit:
3434 3436 break
3435 3437 ctx = repo[rev]
3436 3438 copies = None
3437 3439 if getrenamed is not None and rev:
3438 3440 copies = []
3439 3441 for fn in ctx.files():
3440 3442 rename = getrenamed(fn, rev)
3441 3443 if rename:
3442 3444 copies.append((fn, rename[0]))
3443 3445 if filematcher:
3444 3446 revmatchfn = filematcher(ctx.rev())
3445 3447 else:
3446 3448 revmatchfn = None
3447 3449 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
3448 3450 if displayer.flush(ctx):
3449 3451 count += 1
3450 3452
3451 3453 displayer.close()
3452 3454
3453 3455 @command('manifest',
3454 3456 [('r', 'rev', '', _('revision to display'), _('REV')),
3455 3457 ('', 'all', False, _("list files from all revisions"))]
3456 3458 + formatteropts,
3457 3459 _('[-r REV]'))
3458 3460 def manifest(ui, repo, node=None, rev=None, **opts):
3459 3461 """output the current or given revision of the project manifest
3460 3462
3461 3463 Print a list of version controlled files for the given revision.
3462 3464 If no revision is given, the first parent of the working directory
3463 3465 is used, or the null revision if no revision is checked out.
3464 3466
3465 3467 With -v, print file permissions, symlink and executable bits.
3466 3468 With --debug, print file revision hashes.
3467 3469
3468 3470 If option --all is specified, the list of all files from all revisions
3469 3471 is printed. This includes deleted and renamed files.
3470 3472
3471 3473 Returns 0 on success.
3472 3474 """
3473 3475
3474 3476 fm = ui.formatter('manifest', opts)
3475 3477
3476 3478 if opts.get('all'):
3477 3479 if rev or node:
3478 3480 raise error.Abort(_("can't specify a revision with --all"))
3479 3481
3480 3482 res = []
3481 3483 prefix = "data/"
3482 3484 suffix = ".i"
3483 3485 plen = len(prefix)
3484 3486 slen = len(suffix)
3485 3487 with repo.lock():
3486 3488 for fn, b, size in repo.store.datafiles():
3487 3489 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
3488 3490 res.append(fn[plen:-slen])
3489 3491 for f in res:
3490 3492 fm.startitem()
3491 3493 fm.write("path", '%s\n', f)
3492 3494 fm.end()
3493 3495 return
3494 3496
3495 3497 if rev and node:
3496 3498 raise error.Abort(_("please specify just one revision"))
3497 3499
3498 3500 if not node:
3499 3501 node = rev
3500 3502
3501 3503 char = {'l': '@', 'x': '*', '': ''}
3502 3504 mode = {'l': '644', 'x': '755', '': '644'}
3503 3505 ctx = scmutil.revsingle(repo, node)
3504 3506 mf = ctx.manifest()
3505 3507 for f in ctx:
3506 3508 fm.startitem()
3507 3509 fl = ctx[f].flags()
3508 3510 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
3509 3511 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
3510 3512 fm.write('path', '%s\n', f)
3511 3513 fm.end()
3512 3514
3513 3515 @command('^merge',
3514 3516 [('f', 'force', None,
3515 3517 _('force a merge including outstanding changes (DEPRECATED)')),
3516 3518 ('r', 'rev', '', _('revision to merge'), _('REV')),
3517 3519 ('P', 'preview', None,
3518 3520 _('review revisions to merge (no merge is performed)'))
3519 3521 ] + mergetoolopts,
3520 3522 _('[-P] [[-r] REV]'))
3521 3523 def merge(ui, repo, node=None, **opts):
3522 3524 """merge another revision into working directory
3523 3525
3524 3526 The current working directory is updated with all changes made in
3525 3527 the requested revision since the last common predecessor revision.
3526 3528
3527 3529 Files that changed between either parent are marked as changed for
3528 3530 the next commit and a commit must be performed before any further
3529 3531 updates to the repository are allowed. The next commit will have
3530 3532 two parents.
3531 3533
3532 3534 ``--tool`` can be used to specify the merge tool used for file
3533 3535 merges. It overrides the HGMERGE environment variable and your
3534 3536 configuration files. See :hg:`help merge-tools` for options.
3535 3537
3536 3538 If no revision is specified, the working directory's parent is a
3537 3539 head revision, and the current branch contains exactly one other
3538 3540 head, the other head is merged with by default. Otherwise, an
3539 3541 explicit revision with which to merge with must be provided.
3540 3542
3541 3543 See :hg:`help resolve` for information on handling file conflicts.
3542 3544
3543 3545 To undo an uncommitted merge, use :hg:`update --clean .` which
3544 3546 will check out a clean copy of the original merge parent, losing
3545 3547 all changes.
3546 3548
3547 3549 Returns 0 on success, 1 if there are unresolved files.
3548 3550 """
3549 3551
3550 3552 if opts.get('rev') and node:
3551 3553 raise error.Abort(_("please specify just one revision"))
3552 3554 if not node:
3553 3555 node = opts.get('rev')
3554 3556
3555 3557 if node:
3556 3558 node = scmutil.revsingle(repo, node).node()
3557 3559
3558 3560 if not node:
3559 3561 node = repo[destutil.destmerge(repo)].node()
3560 3562
3561 3563 if opts.get('preview'):
3562 3564 # find nodes that are ancestors of p2 but not of p1
3563 3565 p1 = repo.lookup('.')
3564 3566 p2 = repo.lookup(node)
3565 3567 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
3566 3568
3567 3569 displayer = cmdutil.show_changeset(ui, repo, opts)
3568 3570 for node in nodes:
3569 3571 displayer.show(repo[node])
3570 3572 displayer.close()
3571 3573 return 0
3572 3574
3573 3575 try:
3574 3576 # ui.forcemerge is an internal variable, do not document
3575 3577 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
3576 3578 force = opts.get('force')
3577 3579 labels = ['working copy', 'merge rev']
3578 3580 return hg.merge(repo, node, force=force, mergeforce=force,
3579 3581 labels=labels)
3580 3582 finally:
3581 3583 ui.setconfig('ui', 'forcemerge', '', 'merge')
3582 3584
3583 3585 @command('outgoing|out',
3584 3586 [('f', 'force', None, _('run even when the destination is unrelated')),
3585 3587 ('r', 'rev', [],
3586 3588 _('a changeset intended to be included in the destination'), _('REV')),
3587 3589 ('n', 'newest-first', None, _('show newest record first')),
3588 3590 ('B', 'bookmarks', False, _('compare bookmarks')),
3589 3591 ('b', 'branch', [], _('a specific branch you would like to push'),
3590 3592 _('BRANCH')),
3591 3593 ] + logopts + remoteopts + subrepoopts,
3592 3594 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
3593 3595 def outgoing(ui, repo, dest=None, **opts):
3594 3596 """show changesets not found in the destination
3595 3597
3596 3598 Show changesets not found in the specified destination repository
3597 3599 or the default push location. These are the changesets that would
3598 3600 be pushed if a push was requested.
3599 3601
3600 3602 See pull for details of valid destination formats.
3601 3603
3602 3604 .. container:: verbose
3603 3605
3604 3606 With -B/--bookmarks, the result of bookmark comparison between
3605 3607 local and remote repositories is displayed. With -v/--verbose,
3606 3608 status is also displayed for each bookmark like below::
3607 3609
3608 3610 BM1 01234567890a added
3609 3611 BM2 deleted
3610 3612 BM3 234567890abc advanced
3611 3613 BM4 34567890abcd diverged
3612 3614 BM5 4567890abcde changed
3613 3615
3614 3616 The action taken when pushing depends on the
3615 3617 status of each bookmark:
3616 3618
3617 3619 :``added``: push with ``-B`` will create it
3618 3620 :``deleted``: push with ``-B`` will delete it
3619 3621 :``advanced``: push will update it
3620 3622 :``diverged``: push with ``-B`` will update it
3621 3623 :``changed``: push with ``-B`` will update it
3622 3624
3623 3625 From the point of view of pushing behavior, bookmarks
3624 3626 existing only in the remote repository are treated as
3625 3627 ``deleted``, even if it is in fact added remotely.
3626 3628
3627 3629 Returns 0 if there are outgoing changes, 1 otherwise.
3628 3630 """
3629 3631 if opts.get('graph'):
3630 3632 cmdutil.checkunsupportedgraphflags([], opts)
3631 3633 o, other = hg._outgoing(ui, repo, dest, opts)
3632 3634 if not o:
3633 3635 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3634 3636 return
3635 3637
3636 3638 revdag = cmdutil.graphrevs(repo, o, opts)
3637 3639 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
3638 3640 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
3639 3641 cmdutil.outgoinghooks(ui, repo, other, opts, o)
3640 3642 return 0
3641 3643
3642 3644 if opts.get('bookmarks'):
3643 3645 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3644 3646 dest, branches = hg.parseurl(dest, opts.get('branch'))
3645 3647 other = hg.peer(repo, opts, dest)
3646 3648 if 'bookmarks' not in other.listkeys('namespaces'):
3647 3649 ui.warn(_("remote doesn't support bookmarks\n"))
3648 3650 return 0
3649 3651 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
3650 3652 return bookmarks.outgoing(ui, repo, other)
3651 3653
3652 3654 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
3653 3655 try:
3654 3656 return hg.outgoing(ui, repo, dest, opts)
3655 3657 finally:
3656 3658 del repo._subtoppath
3657 3659
3658 3660 @command('parents',
3659 3661 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
3660 3662 ] + templateopts,
3661 3663 _('[-r REV] [FILE]'),
3662 3664 inferrepo=True)
3663 3665 def parents(ui, repo, file_=None, **opts):
3664 3666 """show the parents of the working directory or revision (DEPRECATED)
3665 3667
3666 3668 Print the working directory's parent revisions. If a revision is
3667 3669 given via -r/--rev, the parent of that revision will be printed.
3668 3670 If a file argument is given, the revision in which the file was
3669 3671 last changed (before the working directory revision or the
3670 3672 argument to --rev if given) is printed.
3671 3673
3672 3674 This command is equivalent to::
3673 3675
3674 3676 hg log -r "p1()+p2()" or
3675 3677 hg log -r "p1(REV)+p2(REV)" or
3676 3678 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
3677 3679 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
3678 3680
3679 3681 See :hg:`summary` and :hg:`help revsets` for related information.
3680 3682
3681 3683 Returns 0 on success.
3682 3684 """
3683 3685
3684 3686 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3685 3687
3686 3688 if file_:
3687 3689 m = scmutil.match(ctx, (file_,), opts)
3688 3690 if m.anypats() or len(m.files()) != 1:
3689 3691 raise error.Abort(_('can only specify an explicit filename'))
3690 3692 file_ = m.files()[0]
3691 3693 filenodes = []
3692 3694 for cp in ctx.parents():
3693 3695 if not cp:
3694 3696 continue
3695 3697 try:
3696 3698 filenodes.append(cp.filenode(file_))
3697 3699 except error.LookupError:
3698 3700 pass
3699 3701 if not filenodes:
3700 3702 raise error.Abort(_("'%s' not found in manifest!") % file_)
3701 3703 p = []
3702 3704 for fn in filenodes:
3703 3705 fctx = repo.filectx(file_, fileid=fn)
3704 3706 p.append(fctx.node())
3705 3707 else:
3706 3708 p = [cp.node() for cp in ctx.parents()]
3707 3709
3708 3710 displayer = cmdutil.show_changeset(ui, repo, opts)
3709 3711 for n in p:
3710 3712 if n != nullid:
3711 3713 displayer.show(repo[n])
3712 3714 displayer.close()
3713 3715
3714 3716 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
3715 3717 def paths(ui, repo, search=None, **opts):
3716 3718 """show aliases for remote repositories
3717 3719
3718 3720 Show definition of symbolic path name NAME. If no name is given,
3719 3721 show definition of all available names.
3720 3722
3721 3723 Option -q/--quiet suppresses all output when searching for NAME
3722 3724 and shows only the path names when listing all definitions.
3723 3725
3724 3726 Path names are defined in the [paths] section of your
3725 3727 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
3726 3728 repository, ``.hg/hgrc`` is used, too.
3727 3729
3728 3730 The path names ``default`` and ``default-push`` have a special
3729 3731 meaning. When performing a push or pull operation, they are used
3730 3732 as fallbacks if no location is specified on the command-line.
3731 3733 When ``default-push`` is set, it will be used for push and
3732 3734 ``default`` will be used for pull; otherwise ``default`` is used
3733 3735 as the fallback for both. When cloning a repository, the clone
3734 3736 source is written as ``default`` in ``.hg/hgrc``.
3735 3737
3736 3738 .. note::
3737 3739
3738 3740 ``default`` and ``default-push`` apply to all inbound (e.g.
3739 3741 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
3740 3742 and :hg:`bundle`) operations.
3741 3743
3742 3744 See :hg:`help urls` for more information.
3743 3745
3744 3746 Returns 0 on success.
3745 3747 """
3746 3748 if search:
3747 3749 pathitems = [(name, path) for name, path in ui.paths.iteritems()
3748 3750 if name == search]
3749 3751 else:
3750 3752 pathitems = sorted(ui.paths.iteritems())
3751 3753
3752 3754 fm = ui.formatter('paths', opts)
3753 3755 if fm.isplain():
3754 3756 hidepassword = util.hidepassword
3755 3757 else:
3756 3758 hidepassword = str
3757 3759 if ui.quiet:
3758 3760 namefmt = '%s\n'
3759 3761 else:
3760 3762 namefmt = '%s = '
3761 3763 showsubopts = not search and not ui.quiet
3762 3764
3763 3765 for name, path in pathitems:
3764 3766 fm.startitem()
3765 3767 fm.condwrite(not search, 'name', namefmt, name)
3766 3768 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
3767 3769 for subopt, value in sorted(path.suboptions.items()):
3768 3770 assert subopt not in ('name', 'url')
3769 3771 if showsubopts:
3770 3772 fm.plain('%s:%s = ' % (name, subopt))
3771 3773 fm.condwrite(showsubopts, subopt, '%s\n', value)
3772 3774
3773 3775 fm.end()
3774 3776
3775 3777 if search and not pathitems:
3776 3778 if not ui.quiet:
3777 3779 ui.warn(_("not found!\n"))
3778 3780 return 1
3779 3781 else:
3780 3782 return 0
3781 3783
3782 3784 @command('phase',
3783 3785 [('p', 'public', False, _('set changeset phase to public')),
3784 3786 ('d', 'draft', False, _('set changeset phase to draft')),
3785 3787 ('s', 'secret', False, _('set changeset phase to secret')),
3786 3788 ('f', 'force', False, _('allow to move boundary backward')),
3787 3789 ('r', 'rev', [], _('target revision'), _('REV')),
3788 3790 ],
3789 3791 _('[-p|-d|-s] [-f] [-r] [REV...]'))
3790 3792 def phase(ui, repo, *revs, **opts):
3791 3793 """set or show the current phase name
3792 3794
3793 3795 With no argument, show the phase name of the current revision(s).
3794 3796
3795 3797 With one of -p/--public, -d/--draft or -s/--secret, change the
3796 3798 phase value of the specified revisions.
3797 3799
3798 3800 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
3799 3801 lower phase to an higher phase. Phases are ordered as follows::
3800 3802
3801 3803 public < draft < secret
3802 3804
3803 3805 Returns 0 on success, 1 if some phases could not be changed.
3804 3806
3805 3807 (For more information about the phases concept, see :hg:`help phases`.)
3806 3808 """
3807 3809 # search for a unique phase argument
3808 3810 targetphase = None
3809 3811 for idx, name in enumerate(phases.phasenames):
3810 3812 if opts[name]:
3811 3813 if targetphase is not None:
3812 3814 raise error.Abort(_('only one phase can be specified'))
3813 3815 targetphase = idx
3814 3816
3815 3817 # look for specified revision
3816 3818 revs = list(revs)
3817 3819 revs.extend(opts['rev'])
3818 3820 if not revs:
3819 3821 # display both parents as the second parent phase can influence
3820 3822 # the phase of a merge commit
3821 3823 revs = [c.rev() for c in repo[None].parents()]
3822 3824
3823 3825 revs = scmutil.revrange(repo, revs)
3824 3826
3825 3827 lock = None
3826 3828 ret = 0
3827 3829 if targetphase is None:
3828 3830 # display
3829 3831 for r in revs:
3830 3832 ctx = repo[r]
3831 3833 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
3832 3834 else:
3833 3835 tr = None
3834 3836 lock = repo.lock()
3835 3837 try:
3836 3838 tr = repo.transaction("phase")
3837 3839 # set phase
3838 3840 if not revs:
3839 3841 raise error.Abort(_('empty revision set'))
3840 3842 nodes = [repo[r].node() for r in revs]
3841 3843 # moving revision from public to draft may hide them
3842 3844 # We have to check result on an unfiltered repository
3843 3845 unfi = repo.unfiltered()
3844 3846 getphase = unfi._phasecache.phase
3845 3847 olddata = [getphase(unfi, r) for r in unfi]
3846 3848 phases.advanceboundary(repo, tr, targetphase, nodes)
3847 3849 if opts['force']:
3848 3850 phases.retractboundary(repo, tr, targetphase, nodes)
3849 3851 tr.close()
3850 3852 finally:
3851 3853 if tr is not None:
3852 3854 tr.release()
3853 3855 lock.release()
3854 3856 getphase = unfi._phasecache.phase
3855 3857 newdata = [getphase(unfi, r) for r in unfi]
3856 3858 changes = sum(newdata[r] != olddata[r] for r in unfi)
3857 3859 cl = unfi.changelog
3858 3860 rejected = [n for n in nodes
3859 3861 if newdata[cl.rev(n)] < targetphase]
3860 3862 if rejected:
3861 3863 ui.warn(_('cannot move %i changesets to a higher '
3862 3864 'phase, use --force\n') % len(rejected))
3863 3865 ret = 1
3864 3866 if changes:
3865 3867 msg = _('phase changed for %i changesets\n') % changes
3866 3868 if ret:
3867 3869 ui.status(msg)
3868 3870 else:
3869 3871 ui.note(msg)
3870 3872 else:
3871 3873 ui.warn(_('no phases changed\n'))
3872 3874 return ret
3873 3875
3874 3876 def postincoming(ui, repo, modheads, optupdate, checkout, brev):
3875 3877 """Run after a changegroup has been added via pull/unbundle
3876 3878
3877 3879 This takes arguments below:
3878 3880
3879 3881 :modheads: change of heads by pull/unbundle
3880 3882 :optupdate: updating working directory is needed or not
3881 3883 :checkout: update destination revision (or None to default destination)
3882 3884 :brev: a name, which might be a bookmark to be activated after updating
3883 3885 """
3884 3886 if modheads == 0:
3885 3887 return
3886 3888 if optupdate:
3887 3889 try:
3888 3890 return hg.updatetotally(ui, repo, checkout, brev)
3889 3891 except error.UpdateAbort as inst:
3890 3892 msg = _("not updating: %s") % str(inst)
3891 3893 hint = inst.hint
3892 3894 raise error.UpdateAbort(msg, hint=hint)
3893 3895 if modheads > 1:
3894 3896 currentbranchheads = len(repo.branchheads())
3895 3897 if currentbranchheads == modheads:
3896 3898 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
3897 3899 elif currentbranchheads > 1:
3898 3900 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
3899 3901 "merge)\n"))
3900 3902 else:
3901 3903 ui.status(_("(run 'hg heads' to see heads)\n"))
3902 3904 else:
3903 3905 ui.status(_("(run 'hg update' to get a working copy)\n"))
3904 3906
3905 3907 @command('^pull',
3906 3908 [('u', 'update', None,
3907 3909 _('update to new branch head if changesets were pulled')),
3908 3910 ('f', 'force', None, _('run even when remote repository is unrelated')),
3909 3911 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3910 3912 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
3911 3913 ('b', 'branch', [], _('a specific branch you would like to pull'),
3912 3914 _('BRANCH')),
3913 3915 ] + remoteopts,
3914 3916 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
3915 3917 def pull(ui, repo, source="default", **opts):
3916 3918 """pull changes from the specified source
3917 3919
3918 3920 Pull changes from a remote repository to a local one.
3919 3921
3920 3922 This finds all changes from the repository at the specified path
3921 3923 or URL and adds them to a local repository (the current one unless
3922 3924 -R is specified). By default, this does not update the copy of the
3923 3925 project in the working directory.
3924 3926
3925 3927 Use :hg:`incoming` if you want to see what would have been added
3926 3928 by a pull at the time you issued this command. If you then decide
3927 3929 to add those changes to the repository, you should use :hg:`pull
3928 3930 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
3929 3931
3930 3932 If SOURCE is omitted, the 'default' path will be used.
3931 3933 See :hg:`help urls` for more information.
3932 3934
3933 3935 Specifying bookmark as ``.`` is equivalent to specifying the active
3934 3936 bookmark's name.
3935 3937
3936 3938 Returns 0 on success, 1 if an update had unresolved files.
3937 3939 """
3938 3940 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3939 3941 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3940 3942 other = hg.peer(repo, opts, source)
3941 3943 try:
3942 3944 revs, checkout = hg.addbranchrevs(repo, other, branches,
3943 3945 opts.get('rev'))
3944 3946
3945 3947
3946 3948 pullopargs = {}
3947 3949 if opts.get('bookmark'):
3948 3950 if not revs:
3949 3951 revs = []
3950 3952 # The list of bookmark used here is not the one used to actually
3951 3953 # update the bookmark name. This can result in the revision pulled
3952 3954 # not ending up with the name of the bookmark because of a race
3953 3955 # condition on the server. (See issue 4689 for details)
3954 3956 remotebookmarks = other.listkeys('bookmarks')
3955 3957 pullopargs['remotebookmarks'] = remotebookmarks
3956 3958 for b in opts['bookmark']:
3957 3959 b = repo._bookmarks.expandname(b)
3958 3960 if b not in remotebookmarks:
3959 3961 raise error.Abort(_('remote bookmark %s not found!') % b)
3960 3962 revs.append(remotebookmarks[b])
3961 3963
3962 3964 if revs:
3963 3965 try:
3964 3966 # When 'rev' is a bookmark name, we cannot guarantee that it
3965 3967 # will be updated with that name because of a race condition
3966 3968 # server side. (See issue 4689 for details)
3967 3969 oldrevs = revs
3968 3970 revs = [] # actually, nodes
3969 3971 for r in oldrevs:
3970 3972 node = other.lookup(r)
3971 3973 revs.append(node)
3972 3974 if r == checkout:
3973 3975 checkout = node
3974 3976 except error.CapabilityError:
3975 3977 err = _("other repository doesn't support revision lookup, "
3976 3978 "so a rev cannot be specified.")
3977 3979 raise error.Abort(err)
3978 3980
3979 3981 pullopargs.update(opts.get('opargs', {}))
3980 3982 modheads = exchange.pull(repo, other, heads=revs,
3981 3983 force=opts.get('force'),
3982 3984 bookmarks=opts.get('bookmark', ()),
3983 3985 opargs=pullopargs).cgresult
3984 3986
3985 3987 # brev is a name, which might be a bookmark to be activated at
3986 3988 # the end of the update. In other words, it is an explicit
3987 3989 # destination of the update
3988 3990 brev = None
3989 3991
3990 3992 if checkout:
3991 3993 checkout = str(repo.changelog.rev(checkout))
3992 3994
3993 3995 # order below depends on implementation of
3994 3996 # hg.addbranchrevs(). opts['bookmark'] is ignored,
3995 3997 # because 'checkout' is determined without it.
3996 3998 if opts.get('rev'):
3997 3999 brev = opts['rev'][0]
3998 4000 elif opts.get('branch'):
3999 4001 brev = opts['branch'][0]
4000 4002 else:
4001 4003 brev = branches[0]
4002 4004 repo._subtoppath = source
4003 4005 try:
4004 4006 ret = postincoming(ui, repo, modheads, opts.get('update'),
4005 4007 checkout, brev)
4006 4008
4007 4009 finally:
4008 4010 del repo._subtoppath
4009 4011
4010 4012 finally:
4011 4013 other.close()
4012 4014 return ret
4013 4015
4014 4016 @command('^push',
4015 4017 [('f', 'force', None, _('force push')),
4016 4018 ('r', 'rev', [],
4017 4019 _('a changeset intended to be included in the destination'),
4018 4020 _('REV')),
4019 4021 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4020 4022 ('b', 'branch', [],
4021 4023 _('a specific branch you would like to push'), _('BRANCH')),
4022 4024 ('', 'new-branch', False, _('allow pushing a new branch')),
4023 4025 ] + remoteopts,
4024 4026 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4025 4027 def push(ui, repo, dest=None, **opts):
4026 4028 """push changes to the specified destination
4027 4029
4028 4030 Push changesets from the local repository to the specified
4029 4031 destination.
4030 4032
4031 4033 This operation is symmetrical to pull: it is identical to a pull
4032 4034 in the destination repository from the current one.
4033 4035
4034 4036 By default, push will not allow creation of new heads at the
4035 4037 destination, since multiple heads would make it unclear which head
4036 4038 to use. In this situation, it is recommended to pull and merge
4037 4039 before pushing.
4038 4040
4039 4041 Use --new-branch if you want to allow push to create a new named
4040 4042 branch that is not present at the destination. This allows you to
4041 4043 only create a new branch without forcing other changes.
4042 4044
4043 4045 .. note::
4044 4046
4045 4047 Extra care should be taken with the -f/--force option,
4046 4048 which will push all new heads on all branches, an action which will
4047 4049 almost always cause confusion for collaborators.
4048 4050
4049 4051 If -r/--rev is used, the specified revision and all its ancestors
4050 4052 will be pushed to the remote repository.
4051 4053
4052 4054 If -B/--bookmark is used, the specified bookmarked revision, its
4053 4055 ancestors, and the bookmark will be pushed to the remote
4054 4056 repository. Specifying ``.`` is equivalent to specifying the active
4055 4057 bookmark's name.
4056 4058
4057 4059 Please see :hg:`help urls` for important details about ``ssh://``
4058 4060 URLs. If DESTINATION is omitted, a default path will be used.
4059 4061
4060 4062 Returns 0 if push was successful, 1 if nothing to push.
4061 4063 """
4062 4064
4063 4065 if opts.get('bookmark'):
4064 4066 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4065 4067 for b in opts['bookmark']:
4066 4068 # translate -B options to -r so changesets get pushed
4067 4069 b = repo._bookmarks.expandname(b)
4068 4070 if b in repo._bookmarks:
4069 4071 opts.setdefault('rev', []).append(b)
4070 4072 else:
4071 4073 # if we try to push a deleted bookmark, translate it to null
4072 4074 # this lets simultaneous -r, -b options continue working
4073 4075 opts.setdefault('rev', []).append("null")
4074 4076
4075 4077 path = ui.paths.getpath(dest, default=('default-push', 'default'))
4076 4078 if not path:
4077 4079 raise error.Abort(_('default repository not configured!'),
4078 4080 hint=_("see 'hg help config.paths'"))
4079 4081 dest = path.pushloc or path.loc
4080 4082 branches = (path.branch, opts.get('branch') or [])
4081 4083 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4082 4084 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4083 4085 other = hg.peer(repo, opts, dest)
4084 4086
4085 4087 if revs:
4086 4088 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4087 4089 if not revs:
4088 4090 raise error.Abort(_("specified revisions evaluate to an empty set"),
4089 4091 hint=_("use different revision arguments"))
4090 4092 elif path.pushrev:
4091 4093 # It doesn't make any sense to specify ancestor revisions. So limit
4092 4094 # to DAG heads to make discovery simpler.
4093 4095 expr = revset.formatspec('heads(%r)', path.pushrev)
4094 4096 revs = scmutil.revrange(repo, [expr])
4095 4097 revs = [repo[rev].node() for rev in revs]
4096 4098 if not revs:
4097 4099 raise error.Abort(_('default push revset for path evaluates to an '
4098 4100 'empty set'))
4099 4101
4100 4102 repo._subtoppath = dest
4101 4103 try:
4102 4104 # push subrepos depth-first for coherent ordering
4103 4105 c = repo['']
4104 4106 subs = c.substate # only repos that are committed
4105 4107 for s in sorted(subs):
4106 4108 result = c.sub(s).push(opts)
4107 4109 if result == 0:
4108 4110 return not result
4109 4111 finally:
4110 4112 del repo._subtoppath
4111 4113 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
4112 4114 newbranch=opts.get('new_branch'),
4113 4115 bookmarks=opts.get('bookmark', ()),
4114 4116 opargs=opts.get('opargs'))
4115 4117
4116 4118 result = not pushop.cgresult
4117 4119
4118 4120 if pushop.bkresult is not None:
4119 4121 if pushop.bkresult == 2:
4120 4122 result = 2
4121 4123 elif not result and pushop.bkresult:
4122 4124 result = 2
4123 4125
4124 4126 return result
4125 4127
4126 4128 @command('recover', [])
4127 4129 def recover(ui, repo):
4128 4130 """roll back an interrupted transaction
4129 4131
4130 4132 Recover from an interrupted commit or pull.
4131 4133
4132 4134 This command tries to fix the repository status after an
4133 4135 interrupted operation. It should only be necessary when Mercurial
4134 4136 suggests it.
4135 4137
4136 4138 Returns 0 if successful, 1 if nothing to recover or verify fails.
4137 4139 """
4138 4140 if repo.recover():
4139 4141 return hg.verify(repo)
4140 4142 return 1
4141 4143
4142 4144 @command('^remove|rm',
4143 4145 [('A', 'after', None, _('record delete for missing files')),
4144 4146 ('f', 'force', None,
4145 4147 _('forget added files, delete modified files')),
4146 4148 ] + subrepoopts + walkopts,
4147 4149 _('[OPTION]... FILE...'),
4148 4150 inferrepo=True)
4149 4151 def remove(ui, repo, *pats, **opts):
4150 4152 """remove the specified files on the next commit
4151 4153
4152 4154 Schedule the indicated files for removal from the current branch.
4153 4155
4154 4156 This command schedules the files to be removed at the next commit.
4155 4157 To undo a remove before that, see :hg:`revert`. To undo added
4156 4158 files, see :hg:`forget`.
4157 4159
4158 4160 .. container:: verbose
4159 4161
4160 4162 -A/--after can be used to remove only files that have already
4161 4163 been deleted, -f/--force can be used to force deletion, and -Af
4162 4164 can be used to remove files from the next revision without
4163 4165 deleting them from the working directory.
4164 4166
4165 4167 The following table details the behavior of remove for different
4166 4168 file states (columns) and option combinations (rows). The file
4167 4169 states are Added [A], Clean [C], Modified [M] and Missing [!]
4168 4170 (as reported by :hg:`status`). The actions are Warn, Remove
4169 4171 (from branch) and Delete (from disk):
4170 4172
4171 4173 ========= == == == ==
4172 4174 opt/state A C M !
4173 4175 ========= == == == ==
4174 4176 none W RD W R
4175 4177 -f R RD RD R
4176 4178 -A W W W R
4177 4179 -Af R R R R
4178 4180 ========= == == == ==
4179 4181
4180 4182 .. note::
4181 4183
4182 4184 :hg:`remove` never deletes files in Added [A] state from the
4183 4185 working directory, not even if ``--force`` is specified.
4184 4186
4185 4187 Returns 0 on success, 1 if any warnings encountered.
4186 4188 """
4187 4189
4188 4190 after, force = opts.get('after'), opts.get('force')
4189 4191 if not pats and not after:
4190 4192 raise error.Abort(_('no files specified'))
4191 4193
4192 4194 m = scmutil.match(repo[None], pats, opts)
4193 4195 subrepos = opts.get('subrepos')
4194 4196 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
4195 4197
4196 4198 @command('rename|move|mv',
4197 4199 [('A', 'after', None, _('record a rename that has already occurred')),
4198 4200 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4199 4201 ] + walkopts + dryrunopts,
4200 4202 _('[OPTION]... SOURCE... DEST'))
4201 4203 def rename(ui, repo, *pats, **opts):
4202 4204 """rename files; equivalent of copy + remove
4203 4205
4204 4206 Mark dest as copies of sources; mark sources for deletion. If dest
4205 4207 is a directory, copies are put in that directory. If dest is a
4206 4208 file, there can only be one source.
4207 4209
4208 4210 By default, this command copies the contents of files as they
4209 4211 exist in the working directory. If invoked with -A/--after, the
4210 4212 operation is recorded, but no copying is performed.
4211 4213
4212 4214 This command takes effect at the next commit. To undo a rename
4213 4215 before that, see :hg:`revert`.
4214 4216
4215 4217 Returns 0 on success, 1 if errors are encountered.
4216 4218 """
4217 4219 with repo.wlock(False):
4218 4220 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4219 4221
4220 4222 @command('resolve',
4221 4223 [('a', 'all', None, _('select all unresolved files')),
4222 4224 ('l', 'list', None, _('list state of files needing merge')),
4223 4225 ('m', 'mark', None, _('mark files as resolved')),
4224 4226 ('u', 'unmark', None, _('mark files as unresolved')),
4225 4227 ('n', 'no-status', None, _('hide status prefix'))]
4226 4228 + mergetoolopts + walkopts + formatteropts,
4227 4229 _('[OPTION]... [FILE]...'),
4228 4230 inferrepo=True)
4229 4231 def resolve(ui, repo, *pats, **opts):
4230 4232 """redo merges or set/view the merge status of files
4231 4233
4232 4234 Merges with unresolved conflicts are often the result of
4233 4235 non-interactive merging using the ``internal:merge`` configuration
4234 4236 setting, or a command-line merge tool like ``diff3``. The resolve
4235 4237 command is used to manage the files involved in a merge, after
4236 4238 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4237 4239 working directory must have two parents). See :hg:`help
4238 4240 merge-tools` for information on configuring merge tools.
4239 4241
4240 4242 The resolve command can be used in the following ways:
4241 4243
4242 4244 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4243 4245 files, discarding any previous merge attempts. Re-merging is not
4244 4246 performed for files already marked as resolved. Use ``--all/-a``
4245 4247 to select all unresolved files. ``--tool`` can be used to specify
4246 4248 the merge tool used for the given files. It overrides the HGMERGE
4247 4249 environment variable and your configuration files. Previous file
4248 4250 contents are saved with a ``.orig`` suffix.
4249 4251
4250 4252 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4251 4253 (e.g. after having manually fixed-up the files). The default is
4252 4254 to mark all unresolved files.
4253 4255
4254 4256 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4255 4257 default is to mark all resolved files.
4256 4258
4257 4259 - :hg:`resolve -l`: list files which had or still have conflicts.
4258 4260 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4259 4261
4260 4262 .. note::
4261 4263
4262 4264 Mercurial will not let you commit files with unresolved merge
4263 4265 conflicts. You must use :hg:`resolve -m ...` before you can
4264 4266 commit after a conflicting merge.
4265 4267
4266 4268 Returns 0 on success, 1 if any files fail a resolve attempt.
4267 4269 """
4268 4270
4269 4271 flaglist = 'all mark unmark list no_status'.split()
4270 4272 all, mark, unmark, show, nostatus = \
4271 4273 [opts.get(o) for o in flaglist]
4272 4274
4273 4275 if (show and (mark or unmark)) or (mark and unmark):
4274 4276 raise error.Abort(_("too many options specified"))
4275 4277 if pats and all:
4276 4278 raise error.Abort(_("can't specify --all and patterns"))
4277 4279 if not (all or pats or show or mark or unmark):
4278 4280 raise error.Abort(_('no files or directories specified'),
4279 4281 hint=('use --all to re-merge all unresolved files'))
4280 4282
4281 4283 if show:
4282 4284 fm = ui.formatter('resolve', opts)
4283 4285 ms = mergemod.mergestate.read(repo)
4284 4286 m = scmutil.match(repo[None], pats, opts)
4285 4287 for f in ms:
4286 4288 if not m(f):
4287 4289 continue
4288 4290 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
4289 4291 'd': 'driverresolved'}[ms[f]]
4290 4292 fm.startitem()
4291 4293 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
4292 4294 fm.write('path', '%s\n', f, label=l)
4293 4295 fm.end()
4294 4296 return 0
4295 4297
4296 4298 with repo.wlock():
4297 4299 ms = mergemod.mergestate.read(repo)
4298 4300
4299 4301 if not (ms.active() or repo.dirstate.p2() != nullid):
4300 4302 raise error.Abort(
4301 4303 _('resolve command not applicable when not merging'))
4302 4304
4303 4305 wctx = repo[None]
4304 4306
4305 4307 if ms.mergedriver and ms.mdstate() == 'u':
4306 4308 proceed = mergemod.driverpreprocess(repo, ms, wctx)
4307 4309 ms.commit()
4308 4310 # allow mark and unmark to go through
4309 4311 if not mark and not unmark and not proceed:
4310 4312 return 1
4311 4313
4312 4314 m = scmutil.match(wctx, pats, opts)
4313 4315 ret = 0
4314 4316 didwork = False
4315 4317 runconclude = False
4316 4318
4317 4319 tocomplete = []
4318 4320 for f in ms:
4319 4321 if not m(f):
4320 4322 continue
4321 4323
4322 4324 didwork = True
4323 4325
4324 4326 # don't let driver-resolved files be marked, and run the conclude
4325 4327 # step if asked to resolve
4326 4328 if ms[f] == "d":
4327 4329 exact = m.exact(f)
4328 4330 if mark:
4329 4331 if exact:
4330 4332 ui.warn(_('not marking %s as it is driver-resolved\n')
4331 4333 % f)
4332 4334 elif unmark:
4333 4335 if exact:
4334 4336 ui.warn(_('not unmarking %s as it is driver-resolved\n')
4335 4337 % f)
4336 4338 else:
4337 4339 runconclude = True
4338 4340 continue
4339 4341
4340 4342 if mark:
4341 4343 ms.mark(f, "r")
4342 4344 elif unmark:
4343 4345 ms.mark(f, "u")
4344 4346 else:
4345 4347 # backup pre-resolve (merge uses .orig for its own purposes)
4346 4348 a = repo.wjoin(f)
4347 4349 try:
4348 4350 util.copyfile(a, a + ".resolve")
4349 4351 except (IOError, OSError) as inst:
4350 4352 if inst.errno != errno.ENOENT:
4351 4353 raise
4352 4354
4353 4355 try:
4354 4356 # preresolve file
4355 4357 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4356 4358 'resolve')
4357 4359 complete, r = ms.preresolve(f, wctx)
4358 4360 if not complete:
4359 4361 tocomplete.append(f)
4360 4362 elif r:
4361 4363 ret = 1
4362 4364 finally:
4363 4365 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4364 4366 ms.commit()
4365 4367
4366 4368 # replace filemerge's .orig file with our resolve file, but only
4367 4369 # for merges that are complete
4368 4370 if complete:
4369 4371 try:
4370 4372 util.rename(a + ".resolve",
4371 4373 scmutil.origpath(ui, repo, a))
4372 4374 except OSError as inst:
4373 4375 if inst.errno != errno.ENOENT:
4374 4376 raise
4375 4377
4376 4378 for f in tocomplete:
4377 4379 try:
4378 4380 # resolve file
4379 4381 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4380 4382 'resolve')
4381 4383 r = ms.resolve(f, wctx)
4382 4384 if r:
4383 4385 ret = 1
4384 4386 finally:
4385 4387 ui.setconfig('ui', 'forcemerge', '', 'resolve')
4386 4388 ms.commit()
4387 4389
4388 4390 # replace filemerge's .orig file with our resolve file
4389 4391 a = repo.wjoin(f)
4390 4392 try:
4391 4393 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
4392 4394 except OSError as inst:
4393 4395 if inst.errno != errno.ENOENT:
4394 4396 raise
4395 4397
4396 4398 ms.commit()
4397 4399 ms.recordactions()
4398 4400
4399 4401 if not didwork and pats:
4400 4402 hint = None
4401 4403 if not any([p for p in pats if p.find(':') >= 0]):
4402 4404 pats = ['path:%s' % p for p in pats]
4403 4405 m = scmutil.match(wctx, pats, opts)
4404 4406 for f in ms:
4405 4407 if not m(f):
4406 4408 continue
4407 4409 flags = ''.join(['-%s ' % o[0] for o in flaglist
4408 4410 if opts.get(o)])
4409 4411 hint = _("(try: hg resolve %s%s)\n") % (
4410 4412 flags,
4411 4413 ' '.join(pats))
4412 4414 break
4413 4415 ui.warn(_("arguments do not match paths that need resolving\n"))
4414 4416 if hint:
4415 4417 ui.warn(hint)
4416 4418 elif ms.mergedriver and ms.mdstate() != 's':
4417 4419 # run conclude step when either a driver-resolved file is requested
4418 4420 # or there are no driver-resolved files
4419 4421 # we can't use 'ret' to determine whether any files are unresolved
4420 4422 # because we might not have tried to resolve some
4421 4423 if ((runconclude or not list(ms.driverresolved()))
4422 4424 and not list(ms.unresolved())):
4423 4425 proceed = mergemod.driverconclude(repo, ms, wctx)
4424 4426 ms.commit()
4425 4427 if not proceed:
4426 4428 return 1
4427 4429
4428 4430 # Nudge users into finishing an unfinished operation
4429 4431 unresolvedf = list(ms.unresolved())
4430 4432 driverresolvedf = list(ms.driverresolved())
4431 4433 if not unresolvedf and not driverresolvedf:
4432 4434 ui.status(_('(no more unresolved files)\n'))
4433 4435 cmdutil.checkafterresolved(repo)
4434 4436 elif not unresolvedf:
4435 4437 ui.status(_('(no more unresolved files -- '
4436 4438 'run "hg resolve --all" to conclude)\n'))
4437 4439
4438 4440 return ret
4439 4441
4440 4442 @command('revert',
4441 4443 [('a', 'all', None, _('revert all changes when no arguments given')),
4442 4444 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4443 4445 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4444 4446 ('C', 'no-backup', None, _('do not save backup copies of files')),
4445 4447 ('i', 'interactive', None,
4446 4448 _('interactively select the changes (EXPERIMENTAL)')),
4447 4449 ] + walkopts + dryrunopts,
4448 4450 _('[OPTION]... [-r REV] [NAME]...'))
4449 4451 def revert(ui, repo, *pats, **opts):
4450 4452 """restore files to their checkout state
4451 4453
4452 4454 .. note::
4453 4455
4454 4456 To check out earlier revisions, you should use :hg:`update REV`.
4455 4457 To cancel an uncommitted merge (and lose your changes),
4456 4458 use :hg:`update --clean .`.
4457 4459
4458 4460 With no revision specified, revert the specified files or directories
4459 4461 to the contents they had in the parent of the working directory.
4460 4462 This restores the contents of files to an unmodified
4461 4463 state and unschedules adds, removes, copies, and renames. If the
4462 4464 working directory has two parents, you must explicitly specify a
4463 4465 revision.
4464 4466
4465 4467 Using the -r/--rev or -d/--date options, revert the given files or
4466 4468 directories to their states as of a specific revision. Because
4467 4469 revert does not change the working directory parents, this will
4468 4470 cause these files to appear modified. This can be helpful to "back
4469 4471 out" some or all of an earlier change. See :hg:`backout` for a
4470 4472 related method.
4471 4473
4472 4474 Modified files are saved with a .orig suffix before reverting.
4473 4475 To disable these backups, use --no-backup. It is possible to store
4474 4476 the backup files in a custom directory relative to the root of the
4475 4477 repository by setting the ``ui.origbackuppath`` configuration
4476 4478 option.
4477 4479
4478 4480 See :hg:`help dates` for a list of formats valid for -d/--date.
4479 4481
4480 4482 See :hg:`help backout` for a way to reverse the effect of an
4481 4483 earlier changeset.
4482 4484
4483 4485 Returns 0 on success.
4484 4486 """
4485 4487
4486 4488 if opts.get("date"):
4487 4489 if opts.get("rev"):
4488 4490 raise error.Abort(_("you can't specify a revision and a date"))
4489 4491 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4490 4492
4491 4493 parent, p2 = repo.dirstate.parents()
4492 4494 if not opts.get('rev') and p2 != nullid:
4493 4495 # revert after merge is a trap for new users (issue2915)
4494 4496 raise error.Abort(_('uncommitted merge with no revision specified'),
4495 4497 hint=_("use 'hg update' or see 'hg help revert'"))
4496 4498
4497 4499 ctx = scmutil.revsingle(repo, opts.get('rev'))
4498 4500
4499 4501 if (not (pats or opts.get('include') or opts.get('exclude') or
4500 4502 opts.get('all') or opts.get('interactive'))):
4501 4503 msg = _("no files or directories specified")
4502 4504 if p2 != nullid:
4503 4505 hint = _("uncommitted merge, use --all to discard all changes,"
4504 4506 " or 'hg update -C .' to abort the merge")
4505 4507 raise error.Abort(msg, hint=hint)
4506 4508 dirty = any(repo.status())
4507 4509 node = ctx.node()
4508 4510 if node != parent:
4509 4511 if dirty:
4510 4512 hint = _("uncommitted changes, use --all to discard all"
4511 4513 " changes, or 'hg update %s' to update") % ctx.rev()
4512 4514 else:
4513 4515 hint = _("use --all to revert all files,"
4514 4516 " or 'hg update %s' to update") % ctx.rev()
4515 4517 elif dirty:
4516 4518 hint = _("uncommitted changes, use --all to discard all changes")
4517 4519 else:
4518 4520 hint = _("use --all to revert all files")
4519 4521 raise error.Abort(msg, hint=hint)
4520 4522
4521 4523 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4522 4524
4523 4525 @command('rollback', dryrunopts +
4524 4526 [('f', 'force', False, _('ignore safety measures'))])
4525 4527 def rollback(ui, repo, **opts):
4526 4528 """roll back the last transaction (DANGEROUS) (DEPRECATED)
4527 4529
4528 4530 Please use :hg:`commit --amend` instead of rollback to correct
4529 4531 mistakes in the last commit.
4530 4532
4531 4533 This command should be used with care. There is only one level of
4532 4534 rollback, and there is no way to undo a rollback. It will also
4533 4535 restore the dirstate at the time of the last transaction, losing
4534 4536 any dirstate changes since that time. This command does not alter
4535 4537 the working directory.
4536 4538
4537 4539 Transactions are used to encapsulate the effects of all commands
4538 4540 that create new changesets or propagate existing changesets into a
4539 4541 repository.
4540 4542
4541 4543 .. container:: verbose
4542 4544
4543 4545 For example, the following commands are transactional, and their
4544 4546 effects can be rolled back:
4545 4547
4546 4548 - commit
4547 4549 - import
4548 4550 - pull
4549 4551 - push (with this repository as the destination)
4550 4552 - unbundle
4551 4553
4552 4554 To avoid permanent data loss, rollback will refuse to rollback a
4553 4555 commit transaction if it isn't checked out. Use --force to
4554 4556 override this protection.
4555 4557
4556 4558 The rollback command can be entirely disabled by setting the
4557 4559 ``ui.rollback`` configuration setting to false. If you're here
4558 4560 because you want to use rollback and it's disabled, you can
4559 4561 re-enable the command by setting ``ui.rollback`` to true.
4560 4562
4561 4563 This command is not intended for use on public repositories. Once
4562 4564 changes are visible for pull by other users, rolling a transaction
4563 4565 back locally is ineffective (someone else may already have pulled
4564 4566 the changes). Furthermore, a race is possible with readers of the
4565 4567 repository; for example an in-progress pull from the repository
4566 4568 may fail if a rollback is performed.
4567 4569
4568 4570 Returns 0 on success, 1 if no rollback data is available.
4569 4571 """
4570 4572 if not ui.configbool('ui', 'rollback', True):
4571 4573 raise error.Abort(_('rollback is disabled because it is unsafe'),
4572 4574 hint=('see `hg help -v rollback` for information'))
4573 4575 return repo.rollback(dryrun=opts.get('dry_run'),
4574 4576 force=opts.get('force'))
4575 4577
4576 4578 @command('root', [])
4577 4579 def root(ui, repo):
4578 4580 """print the root (top) of the current working directory
4579 4581
4580 4582 Print the root directory of the current repository.
4581 4583
4582 4584 Returns 0 on success.
4583 4585 """
4584 4586 ui.write(repo.root + "\n")
4585 4587
4586 4588 @command('^serve',
4587 4589 [('A', 'accesslog', '', _('name of access log file to write to'),
4588 4590 _('FILE')),
4589 4591 ('d', 'daemon', None, _('run server in background')),
4590 4592 ('', 'daemon-postexec', [], _('used internally by daemon mode')),
4591 4593 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4592 4594 # use string type, then we can check if something was passed
4593 4595 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4594 4596 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4595 4597 _('ADDR')),
4596 4598 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
4597 4599 _('PREFIX')),
4598 4600 ('n', 'name', '',
4599 4601 _('name to show in web pages (default: working directory)'), _('NAME')),
4600 4602 ('', 'web-conf', '',
4601 4603 _("name of the hgweb config file (see 'hg help hgweb')"), _('FILE')),
4602 4604 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
4603 4605 _('FILE')),
4604 4606 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
4605 4607 ('', 'stdio', None, _('for remote clients')),
4606 4608 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
4607 4609 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
4608 4610 ('', 'style', '', _('template style to use'), _('STYLE')),
4609 4611 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4610 4612 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
4611 4613 _('[OPTION]...'),
4612 4614 optionalrepo=True)
4613 4615 def serve(ui, repo, **opts):
4614 4616 """start stand-alone webserver
4615 4617
4616 4618 Start a local HTTP repository browser and pull server. You can use
4617 4619 this for ad-hoc sharing and browsing of repositories. It is
4618 4620 recommended to use a real web server to serve a repository for
4619 4621 longer periods of time.
4620 4622
4621 4623 Please note that the server does not implement access control.
4622 4624 This means that, by default, anybody can read from the server and
4623 4625 nobody can write to it by default. Set the ``web.allow_push``
4624 4626 option to ``*`` to allow everybody to push to the server. You
4625 4627 should use a real web server if you need to authenticate users.
4626 4628
4627 4629 By default, the server logs accesses to stdout and errors to
4628 4630 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
4629 4631 files.
4630 4632
4631 4633 To have the server choose a free port number to listen on, specify
4632 4634 a port number of 0; in this case, the server will print the port
4633 4635 number it uses.
4634 4636
4635 4637 Returns 0 on success.
4636 4638 """
4637 4639
4638 4640 if opts["stdio"] and opts["cmdserver"]:
4639 4641 raise error.Abort(_("cannot use --stdio with --cmdserver"))
4640 4642
4641 4643 if opts["stdio"]:
4642 4644 if repo is None:
4643 4645 raise error.RepoError(_("there is no Mercurial repository here"
4644 4646 " (.hg not found)"))
4645 4647 s = sshserver.sshserver(ui, repo)
4646 4648 s.serve_forever()
4647 4649
4648 4650 service = server.createservice(ui, repo, opts)
4649 4651 return server.runservice(opts, initfn=service.init, runfn=service.run)
4650 4652
4651 4653 @command('^status|st',
4652 4654 [('A', 'all', None, _('show status of all files')),
4653 4655 ('m', 'modified', None, _('show only modified files')),
4654 4656 ('a', 'added', None, _('show only added files')),
4655 4657 ('r', 'removed', None, _('show only removed files')),
4656 4658 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4657 4659 ('c', 'clean', None, _('show only files without changes')),
4658 4660 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4659 4661 ('i', 'ignored', None, _('show only ignored files')),
4660 4662 ('n', 'no-status', None, _('hide status prefix')),
4661 4663 ('C', 'copies', None, _('show source of copied files')),
4662 4664 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4663 4665 ('', 'rev', [], _('show difference from revision'), _('REV')),
4664 4666 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
4665 4667 ] + walkopts + subrepoopts + formatteropts,
4666 4668 _('[OPTION]... [FILE]...'),
4667 4669 inferrepo=True)
4668 4670 def status(ui, repo, *pats, **opts):
4669 4671 """show changed files in the working directory
4670 4672
4671 4673 Show status of files in the repository. If names are given, only
4672 4674 files that match are shown. Files that are clean or ignored or
4673 4675 the source of a copy/move operation, are not listed unless
4674 4676 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
4675 4677 Unless options described with "show only ..." are given, the
4676 4678 options -mardu are used.
4677 4679
4678 4680 Option -q/--quiet hides untracked (unknown and ignored) files
4679 4681 unless explicitly requested with -u/--unknown or -i/--ignored.
4680 4682
4681 4683 .. note::
4682 4684
4683 4685 :hg:`status` may appear to disagree with diff if permissions have
4684 4686 changed or a merge has occurred. The standard diff format does
4685 4687 not report permission changes and diff only reports changes
4686 4688 relative to one merge parent.
4687 4689
4688 4690 If one revision is given, it is used as the base revision.
4689 4691 If two revisions are given, the differences between them are
4690 4692 shown. The --change option can also be used as a shortcut to list
4691 4693 the changed files of a revision from its first parent.
4692 4694
4693 4695 The codes used to show the status of files are::
4694 4696
4695 4697 M = modified
4696 4698 A = added
4697 4699 R = removed
4698 4700 C = clean
4699 4701 ! = missing (deleted by non-hg command, but still tracked)
4700 4702 ? = not tracked
4701 4703 I = ignored
4702 4704 = origin of the previous file (with --copies)
4703 4705
4704 4706 .. container:: verbose
4705 4707
4706 4708 Examples:
4707 4709
4708 4710 - show changes in the working directory relative to a
4709 4711 changeset::
4710 4712
4711 4713 hg status --rev 9353
4712 4714
4713 4715 - show changes in the working directory relative to the
4714 4716 current directory (see :hg:`help patterns` for more information)::
4715 4717
4716 4718 hg status re:
4717 4719
4718 4720 - show all changes including copies in an existing changeset::
4719 4721
4720 4722 hg status --copies --change 9353
4721 4723
4722 4724 - get a NUL separated list of added files, suitable for xargs::
4723 4725
4724 4726 hg status -an0
4725 4727
4726 4728 Returns 0 on success.
4727 4729 """
4728 4730
4729 4731 revs = opts.get('rev')
4730 4732 change = opts.get('change')
4731 4733
4732 4734 if revs and change:
4733 4735 msg = _('cannot specify --rev and --change at the same time')
4734 4736 raise error.Abort(msg)
4735 4737 elif change:
4736 4738 node2 = scmutil.revsingle(repo, change, None).node()
4737 4739 node1 = repo[node2].p1().node()
4738 4740 else:
4739 4741 node1, node2 = scmutil.revpair(repo, revs)
4740 4742
4741 4743 if pats:
4742 4744 cwd = repo.getcwd()
4743 4745 else:
4744 4746 cwd = ''
4745 4747
4746 4748 if opts.get('print0'):
4747 4749 end = '\0'
4748 4750 else:
4749 4751 end = '\n'
4750 4752 copy = {}
4751 4753 states = 'modified added removed deleted unknown ignored clean'.split()
4752 4754 show = [k for k in states if opts.get(k)]
4753 4755 if opts.get('all'):
4754 4756 show += ui.quiet and (states[:4] + ['clean']) or states
4755 4757 if not show:
4756 4758 if ui.quiet:
4757 4759 show = states[:4]
4758 4760 else:
4759 4761 show = states[:5]
4760 4762
4761 4763 m = scmutil.match(repo[node2], pats, opts)
4762 4764 stat = repo.status(node1, node2, m,
4763 4765 'ignored' in show, 'clean' in show, 'unknown' in show,
4764 4766 opts.get('subrepos'))
4765 4767 changestates = zip(states, 'MAR!?IC', stat)
4766 4768
4767 4769 if (opts.get('all') or opts.get('copies')
4768 4770 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
4769 4771 copy = copies.pathcopies(repo[node1], repo[node2], m)
4770 4772
4771 4773 fm = ui.formatter('status', opts)
4772 4774 fmt = '%s' + end
4773 4775 showchar = not opts.get('no_status')
4774 4776
4775 4777 for state, char, files in changestates:
4776 4778 if state in show:
4777 4779 label = 'status.' + state
4778 4780 for f in files:
4779 4781 fm.startitem()
4780 4782 fm.condwrite(showchar, 'status', '%s ', char, label=label)
4781 4783 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
4782 4784 if f in copy:
4783 4785 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
4784 4786 label='status.copied')
4785 4787 fm.end()
4786 4788
4787 4789 @command('^summary|sum',
4788 4790 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
4789 4791 def summary(ui, repo, **opts):
4790 4792 """summarize working directory state
4791 4793
4792 4794 This generates a brief summary of the working directory state,
4793 4795 including parents, branch, commit status, phase and available updates.
4794 4796
4795 4797 With the --remote option, this will check the default paths for
4796 4798 incoming and outgoing changes. This can be time-consuming.
4797 4799
4798 4800 Returns 0 on success.
4799 4801 """
4800 4802
4801 4803 ctx = repo[None]
4802 4804 parents = ctx.parents()
4803 4805 pnode = parents[0].node()
4804 4806 marks = []
4805 4807
4806 4808 ms = None
4807 4809 try:
4808 4810 ms = mergemod.mergestate.read(repo)
4809 4811 except error.UnsupportedMergeRecords as e:
4810 4812 s = ' '.join(e.recordtypes)
4811 4813 ui.warn(
4812 4814 _('warning: merge state has unsupported record types: %s\n') % s)
4813 4815 unresolved = 0
4814 4816 else:
4815 4817 unresolved = [f for f in ms if ms[f] == 'u']
4816 4818
4817 4819 for p in parents:
4818 4820 # label with log.changeset (instead of log.parent) since this
4819 4821 # shows a working directory parent *changeset*:
4820 4822 # i18n: column positioning for "hg summary"
4821 4823 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
4822 4824 label=cmdutil._changesetlabels(p))
4823 4825 ui.write(' '.join(p.tags()), label='log.tag')
4824 4826 if p.bookmarks():
4825 4827 marks.extend(p.bookmarks())
4826 4828 if p.rev() == -1:
4827 4829 if not len(repo):
4828 4830 ui.write(_(' (empty repository)'))
4829 4831 else:
4830 4832 ui.write(_(' (no revision checked out)'))
4831 4833 if p.troubled():
4832 4834 ui.write(' ('
4833 4835 + ', '.join(ui.label(trouble, 'trouble.%s' % trouble)
4834 4836 for trouble in p.troubles())
4835 4837 + ')')
4836 4838 ui.write('\n')
4837 4839 if p.description():
4838 4840 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
4839 4841 label='log.summary')
4840 4842
4841 4843 branch = ctx.branch()
4842 4844 bheads = repo.branchheads(branch)
4843 4845 # i18n: column positioning for "hg summary"
4844 4846 m = _('branch: %s\n') % branch
4845 4847 if branch != 'default':
4846 4848 ui.write(m, label='log.branch')
4847 4849 else:
4848 4850 ui.status(m, label='log.branch')
4849 4851
4850 4852 if marks:
4851 4853 active = repo._activebookmark
4852 4854 # i18n: column positioning for "hg summary"
4853 4855 ui.write(_('bookmarks:'), label='log.bookmark')
4854 4856 if active is not None:
4855 4857 if active in marks:
4856 4858 ui.write(' *' + active, label=activebookmarklabel)
4857 4859 marks.remove(active)
4858 4860 else:
4859 4861 ui.write(' [%s]' % active, label=activebookmarklabel)
4860 4862 for m in marks:
4861 4863 ui.write(' ' + m, label='log.bookmark')
4862 4864 ui.write('\n', label='log.bookmark')
4863 4865
4864 4866 status = repo.status(unknown=True)
4865 4867
4866 4868 c = repo.dirstate.copies()
4867 4869 copied, renamed = [], []
4868 4870 for d, s in c.iteritems():
4869 4871 if s in status.removed:
4870 4872 status.removed.remove(s)
4871 4873 renamed.append(d)
4872 4874 else:
4873 4875 copied.append(d)
4874 4876 if d in status.added:
4875 4877 status.added.remove(d)
4876 4878
4877 4879 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
4878 4880
4879 4881 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
4880 4882 (ui.label(_('%d added'), 'status.added'), status.added),
4881 4883 (ui.label(_('%d removed'), 'status.removed'), status.removed),
4882 4884 (ui.label(_('%d renamed'), 'status.copied'), renamed),
4883 4885 (ui.label(_('%d copied'), 'status.copied'), copied),
4884 4886 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
4885 4887 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
4886 4888 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
4887 4889 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
4888 4890 t = []
4889 4891 for l, s in labels:
4890 4892 if s:
4891 4893 t.append(l % len(s))
4892 4894
4893 4895 t = ', '.join(t)
4894 4896 cleanworkdir = False
4895 4897
4896 4898 if repo.vfs.exists('graftstate'):
4897 4899 t += _(' (graft in progress)')
4898 4900 if repo.vfs.exists('updatestate'):
4899 4901 t += _(' (interrupted update)')
4900 4902 elif len(parents) > 1:
4901 4903 t += _(' (merge)')
4902 4904 elif branch != parents[0].branch():
4903 4905 t += _(' (new branch)')
4904 4906 elif (parents[0].closesbranch() and
4905 4907 pnode in repo.branchheads(branch, closed=True)):
4906 4908 t += _(' (head closed)')
4907 4909 elif not (status.modified or status.added or status.removed or renamed or
4908 4910 copied or subs):
4909 4911 t += _(' (clean)')
4910 4912 cleanworkdir = True
4911 4913 elif pnode not in bheads:
4912 4914 t += _(' (new branch head)')
4913 4915
4914 4916 if parents:
4915 4917 pendingphase = max(p.phase() for p in parents)
4916 4918 else:
4917 4919 pendingphase = phases.public
4918 4920
4919 4921 if pendingphase > phases.newcommitphase(ui):
4920 4922 t += ' (%s)' % phases.phasenames[pendingphase]
4921 4923
4922 4924 if cleanworkdir:
4923 4925 # i18n: column positioning for "hg summary"
4924 4926 ui.status(_('commit: %s\n') % t.strip())
4925 4927 else:
4926 4928 # i18n: column positioning for "hg summary"
4927 4929 ui.write(_('commit: %s\n') % t.strip())
4928 4930
4929 4931 # all ancestors of branch heads - all ancestors of parent = new csets
4930 4932 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
4931 4933 bheads))
4932 4934
4933 4935 if new == 0:
4934 4936 # i18n: column positioning for "hg summary"
4935 4937 ui.status(_('update: (current)\n'))
4936 4938 elif pnode not in bheads:
4937 4939 # i18n: column positioning for "hg summary"
4938 4940 ui.write(_('update: %d new changesets (update)\n') % new)
4939 4941 else:
4940 4942 # i18n: column positioning for "hg summary"
4941 4943 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
4942 4944 (new, len(bheads)))
4943 4945
4944 4946 t = []
4945 4947 draft = len(repo.revs('draft()'))
4946 4948 if draft:
4947 4949 t.append(_('%d draft') % draft)
4948 4950 secret = len(repo.revs('secret()'))
4949 4951 if secret:
4950 4952 t.append(_('%d secret') % secret)
4951 4953
4952 4954 if draft or secret:
4953 4955 ui.status(_('phases: %s\n') % ', '.join(t))
4954 4956
4955 4957 if obsolete.isenabled(repo, obsolete.createmarkersopt):
4956 4958 for trouble in ("unstable", "divergent", "bumped"):
4957 4959 numtrouble = len(repo.revs(trouble + "()"))
4958 4960 # We write all the possibilities to ease translation
4959 4961 troublemsg = {
4960 4962 "unstable": _("unstable: %d changesets"),
4961 4963 "divergent": _("divergent: %d changesets"),
4962 4964 "bumped": _("bumped: %d changesets"),
4963 4965 }
4964 4966 if numtrouble > 0:
4965 4967 ui.status(troublemsg[trouble] % numtrouble + "\n")
4966 4968
4967 4969 cmdutil.summaryhooks(ui, repo)
4968 4970
4969 4971 if opts.get('remote'):
4970 4972 needsincoming, needsoutgoing = True, True
4971 4973 else:
4972 4974 needsincoming, needsoutgoing = False, False
4973 4975 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
4974 4976 if i:
4975 4977 needsincoming = True
4976 4978 if o:
4977 4979 needsoutgoing = True
4978 4980 if not needsincoming and not needsoutgoing:
4979 4981 return
4980 4982
4981 4983 def getincoming():
4982 4984 source, branches = hg.parseurl(ui.expandpath('default'))
4983 4985 sbranch = branches[0]
4984 4986 try:
4985 4987 other = hg.peer(repo, {}, source)
4986 4988 except error.RepoError:
4987 4989 if opts.get('remote'):
4988 4990 raise
4989 4991 return source, sbranch, None, None, None
4990 4992 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
4991 4993 if revs:
4992 4994 revs = [other.lookup(rev) for rev in revs]
4993 4995 ui.debug('comparing with %s\n' % util.hidepassword(source))
4994 4996 repo.ui.pushbuffer()
4995 4997 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
4996 4998 repo.ui.popbuffer()
4997 4999 return source, sbranch, other, commoninc, commoninc[1]
4998 5000
4999 5001 if needsincoming:
5000 5002 source, sbranch, sother, commoninc, incoming = getincoming()
5001 5003 else:
5002 5004 source = sbranch = sother = commoninc = incoming = None
5003 5005
5004 5006 def getoutgoing():
5005 5007 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5006 5008 dbranch = branches[0]
5007 5009 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5008 5010 if source != dest:
5009 5011 try:
5010 5012 dother = hg.peer(repo, {}, dest)
5011 5013 except error.RepoError:
5012 5014 if opts.get('remote'):
5013 5015 raise
5014 5016 return dest, dbranch, None, None
5015 5017 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5016 5018 elif sother is None:
5017 5019 # there is no explicit destination peer, but source one is invalid
5018 5020 return dest, dbranch, None, None
5019 5021 else:
5020 5022 dother = sother
5021 5023 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5022 5024 common = None
5023 5025 else:
5024 5026 common = commoninc
5025 5027 if revs:
5026 5028 revs = [repo.lookup(rev) for rev in revs]
5027 5029 repo.ui.pushbuffer()
5028 5030 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5029 5031 commoninc=common)
5030 5032 repo.ui.popbuffer()
5031 5033 return dest, dbranch, dother, outgoing
5032 5034
5033 5035 if needsoutgoing:
5034 5036 dest, dbranch, dother, outgoing = getoutgoing()
5035 5037 else:
5036 5038 dest = dbranch = dother = outgoing = None
5037 5039
5038 5040 if opts.get('remote'):
5039 5041 t = []
5040 5042 if incoming:
5041 5043 t.append(_('1 or more incoming'))
5042 5044 o = outgoing.missing
5043 5045 if o:
5044 5046 t.append(_('%d outgoing') % len(o))
5045 5047 other = dother or sother
5046 5048 if 'bookmarks' in other.listkeys('namespaces'):
5047 5049 counts = bookmarks.summary(repo, other)
5048 5050 if counts[0] > 0:
5049 5051 t.append(_('%d incoming bookmarks') % counts[0])
5050 5052 if counts[1] > 0:
5051 5053 t.append(_('%d outgoing bookmarks') % counts[1])
5052 5054
5053 5055 if t:
5054 5056 # i18n: column positioning for "hg summary"
5055 5057 ui.write(_('remote: %s\n') % (', '.join(t)))
5056 5058 else:
5057 5059 # i18n: column positioning for "hg summary"
5058 5060 ui.status(_('remote: (synced)\n'))
5059 5061
5060 5062 cmdutil.summaryremotehooks(ui, repo, opts,
5061 5063 ((source, sbranch, sother, commoninc),
5062 5064 (dest, dbranch, dother, outgoing)))
5063 5065
5064 5066 @command('tag',
5065 5067 [('f', 'force', None, _('force tag')),
5066 5068 ('l', 'local', None, _('make the tag local')),
5067 5069 ('r', 'rev', '', _('revision to tag'), _('REV')),
5068 5070 ('', 'remove', None, _('remove a tag')),
5069 5071 # -l/--local is already there, commitopts cannot be used
5070 5072 ('e', 'edit', None, _('invoke editor on commit messages')),
5071 5073 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5072 5074 ] + commitopts2,
5073 5075 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5074 5076 def tag(ui, repo, name1, *names, **opts):
5075 5077 """add one or more tags for the current or given revision
5076 5078
5077 5079 Name a particular revision using <name>.
5078 5080
5079 5081 Tags are used to name particular revisions of the repository and are
5080 5082 very useful to compare different revisions, to go back to significant
5081 5083 earlier versions or to mark branch points as releases, etc. Changing
5082 5084 an existing tag is normally disallowed; use -f/--force to override.
5083 5085
5084 5086 If no revision is given, the parent of the working directory is
5085 5087 used.
5086 5088
5087 5089 To facilitate version control, distribution, and merging of tags,
5088 5090 they are stored as a file named ".hgtags" which is managed similarly
5089 5091 to other project files and can be hand-edited if necessary. This
5090 5092 also means that tagging creates a new commit. The file
5091 5093 ".hg/localtags" is used for local tags (not shared among
5092 5094 repositories).
5093 5095
5094 5096 Tag commits are usually made at the head of a branch. If the parent
5095 5097 of the working directory is not a branch head, :hg:`tag` aborts; use
5096 5098 -f/--force to force the tag commit to be based on a non-head
5097 5099 changeset.
5098 5100
5099 5101 See :hg:`help dates` for a list of formats valid for -d/--date.
5100 5102
5101 5103 Since tag names have priority over branch names during revision
5102 5104 lookup, using an existing branch name as a tag name is discouraged.
5103 5105
5104 5106 Returns 0 on success.
5105 5107 """
5106 5108 wlock = lock = None
5107 5109 try:
5108 5110 wlock = repo.wlock()
5109 5111 lock = repo.lock()
5110 5112 rev_ = "."
5111 5113 names = [t.strip() for t in (name1,) + names]
5112 5114 if len(names) != len(set(names)):
5113 5115 raise error.Abort(_('tag names must be unique'))
5114 5116 for n in names:
5115 5117 scmutil.checknewlabel(repo, n, 'tag')
5116 5118 if not n:
5117 5119 raise error.Abort(_('tag names cannot consist entirely of '
5118 5120 'whitespace'))
5119 5121 if opts.get('rev') and opts.get('remove'):
5120 5122 raise error.Abort(_("--rev and --remove are incompatible"))
5121 5123 if opts.get('rev'):
5122 5124 rev_ = opts['rev']
5123 5125 message = opts.get('message')
5124 5126 if opts.get('remove'):
5125 5127 if opts.get('local'):
5126 5128 expectedtype = 'local'
5127 5129 else:
5128 5130 expectedtype = 'global'
5129 5131
5130 5132 for n in names:
5131 5133 if not repo.tagtype(n):
5132 5134 raise error.Abort(_("tag '%s' does not exist") % n)
5133 5135 if repo.tagtype(n) != expectedtype:
5134 5136 if expectedtype == 'global':
5135 5137 raise error.Abort(_("tag '%s' is not a global tag") % n)
5136 5138 else:
5137 5139 raise error.Abort(_("tag '%s' is not a local tag") % n)
5138 5140 rev_ = 'null'
5139 5141 if not message:
5140 5142 # we don't translate commit messages
5141 5143 message = 'Removed tag %s' % ', '.join(names)
5142 5144 elif not opts.get('force'):
5143 5145 for n in names:
5144 5146 if n in repo.tags():
5145 5147 raise error.Abort(_("tag '%s' already exists "
5146 5148 "(use -f to force)") % n)
5147 5149 if not opts.get('local'):
5148 5150 p1, p2 = repo.dirstate.parents()
5149 5151 if p2 != nullid:
5150 5152 raise error.Abort(_('uncommitted merge'))
5151 5153 bheads = repo.branchheads()
5152 5154 if not opts.get('force') and bheads and p1 not in bheads:
5153 5155 raise error.Abort(_('working directory is not at a branch head '
5154 5156 '(use -f to force)'))
5155 5157 r = scmutil.revsingle(repo, rev_).node()
5156 5158
5157 5159 if not message:
5158 5160 # we don't translate commit messages
5159 5161 message = ('Added tag %s for changeset %s' %
5160 5162 (', '.join(names), short(r)))
5161 5163
5162 5164 date = opts.get('date')
5163 5165 if date:
5164 5166 date = util.parsedate(date)
5165 5167
5166 5168 if opts.get('remove'):
5167 5169 editform = 'tag.remove'
5168 5170 else:
5169 5171 editform = 'tag.add'
5170 5172 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5171 5173
5172 5174 # don't allow tagging the null rev
5173 5175 if (not opts.get('remove') and
5174 5176 scmutil.revsingle(repo, rev_).rev() == nullrev):
5175 5177 raise error.Abort(_("cannot tag null revision"))
5176 5178
5177 5179 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5178 5180 editor=editor)
5179 5181 finally:
5180 5182 release(lock, wlock)
5181 5183
5182 5184 @command('tags', formatteropts, '')
5183 5185 def tags(ui, repo, **opts):
5184 5186 """list repository tags
5185 5187
5186 5188 This lists both regular and local tags. When the -v/--verbose
5187 5189 switch is used, a third column "local" is printed for local tags.
5188 5190 When the -q/--quiet switch is used, only the tag name is printed.
5189 5191
5190 5192 Returns 0 on success.
5191 5193 """
5192 5194
5193 5195 fm = ui.formatter('tags', opts)
5194 5196 hexfunc = fm.hexfunc
5195 5197 tagtype = ""
5196 5198
5197 5199 for t, n in reversed(repo.tagslist()):
5198 5200 hn = hexfunc(n)
5199 5201 label = 'tags.normal'
5200 5202 tagtype = ''
5201 5203 if repo.tagtype(t) == 'local':
5202 5204 label = 'tags.local'
5203 5205 tagtype = 'local'
5204 5206
5205 5207 fm.startitem()
5206 5208 fm.write('tag', '%s', t, label=label)
5207 5209 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5208 5210 fm.condwrite(not ui.quiet, 'rev node', fmt,
5209 5211 repo.changelog.rev(n), hn, label=label)
5210 5212 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5211 5213 tagtype, label=label)
5212 5214 fm.plain('\n')
5213 5215 fm.end()
5214 5216
5215 5217 @command('tip',
5216 5218 [('p', 'patch', None, _('show patch')),
5217 5219 ('g', 'git', None, _('use git extended diff format')),
5218 5220 ] + templateopts,
5219 5221 _('[-p] [-g]'))
5220 5222 def tip(ui, repo, **opts):
5221 5223 """show the tip revision (DEPRECATED)
5222 5224
5223 5225 The tip revision (usually just called the tip) is the changeset
5224 5226 most recently added to the repository (and therefore the most
5225 5227 recently changed head).
5226 5228
5227 5229 If you have just made a commit, that commit will be the tip. If
5228 5230 you have just pulled changes from another repository, the tip of
5229 5231 that repository becomes the current tip. The "tip" tag is special
5230 5232 and cannot be renamed or assigned to a different changeset.
5231 5233
5232 5234 This command is deprecated, please use :hg:`heads` instead.
5233 5235
5234 5236 Returns 0 on success.
5235 5237 """
5236 5238 displayer = cmdutil.show_changeset(ui, repo, opts)
5237 5239 displayer.show(repo['tip'])
5238 5240 displayer.close()
5239 5241
5240 5242 @command('unbundle',
5241 5243 [('u', 'update', None,
5242 5244 _('update to new branch head if changesets were unbundled'))],
5243 5245 _('[-u] FILE...'))
5244 5246 def unbundle(ui, repo, fname1, *fnames, **opts):
5245 5247 """apply one or more changegroup files
5246 5248
5247 5249 Apply one or more compressed changegroup files generated by the
5248 5250 bundle command.
5249 5251
5250 5252 Returns 0 on success, 1 if an update has unresolved files.
5251 5253 """
5252 5254 fnames = (fname1,) + fnames
5253 5255
5254 5256 with repo.lock():
5255 5257 for fname in fnames:
5256 5258 f = hg.openpath(ui, fname)
5257 5259 gen = exchange.readbundle(ui, f, fname)
5258 5260 if isinstance(gen, bundle2.unbundle20):
5259 5261 tr = repo.transaction('unbundle')
5260 5262 try:
5261 5263 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
5262 5264 url='bundle:' + fname)
5263 5265 tr.close()
5264 5266 except error.BundleUnknownFeatureError as exc:
5265 5267 raise error.Abort(_('%s: unknown bundle feature, %s')
5266 5268 % (fname, exc),
5267 5269 hint=_("see https://mercurial-scm.org/"
5268 5270 "wiki/BundleFeature for more "
5269 5271 "information"))
5270 5272 finally:
5271 5273 if tr:
5272 5274 tr.release()
5273 5275 changes = [r.get('return', 0)
5274 5276 for r in op.records['changegroup']]
5275 5277 modheads = changegroup.combineresults(changes)
5276 5278 elif isinstance(gen, streamclone.streamcloneapplier):
5277 5279 raise error.Abort(
5278 5280 _('packed bundles cannot be applied with '
5279 5281 '"hg unbundle"'),
5280 5282 hint=_('use "hg debugapplystreamclonebundle"'))
5281 5283 else:
5282 5284 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
5283 5285
5284 5286 return postincoming(ui, repo, modheads, opts.get('update'), None, None)
5285 5287
5286 5288 @command('^update|up|checkout|co',
5287 5289 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5288 5290 ('c', 'check', None, _('require clean working directory')),
5289 5291 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5290 5292 ('r', 'rev', '', _('revision'), _('REV'))
5291 5293 ] + mergetoolopts,
5292 5294 _('[-C|-c] [-d DATE] [[-r] REV]'))
5293 5295 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
5294 5296 tool=None):
5295 5297 """update working directory (or switch revisions)
5296 5298
5297 5299 Update the repository's working directory to the specified
5298 5300 changeset. If no changeset is specified, update to the tip of the
5299 5301 current named branch and move the active bookmark (see :hg:`help
5300 5302 bookmarks`).
5301 5303
5302 5304 Update sets the working directory's parent revision to the specified
5303 5305 changeset (see :hg:`help parents`).
5304 5306
5305 5307 If the changeset is not a descendant or ancestor of the working
5306 5308 directory's parent and there are uncommitted changes, the update is
5307 5309 aborted. With the -c/--check option, the working directory is checked
5308 5310 for uncommitted changes; if none are found, the working directory is
5309 5311 updated to the specified changeset.
5310 5312
5311 5313 .. container:: verbose
5312 5314
5313 5315 The -C/--clean and -c/--check options control what happens if the
5314 5316 working directory contains uncommitted changes.
5315 5317 At most of one of them can be specified.
5316 5318
5317 5319 1. If no option is specified, and if
5318 5320 the requested changeset is an ancestor or descendant of
5319 5321 the working directory's parent, the uncommitted changes
5320 5322 are merged into the requested changeset and the merged
5321 5323 result is left uncommitted. If the requested changeset is
5322 5324 not an ancestor or descendant (that is, it is on another
5323 5325 branch), the update is aborted and the uncommitted changes
5324 5326 are preserved.
5325 5327
5326 5328 2. With the -c/--check option, the update is aborted and the
5327 5329 uncommitted changes are preserved.
5328 5330
5329 5331 3. With the -C/--clean option, uncommitted changes are discarded and
5330 5332 the working directory is updated to the requested changeset.
5331 5333
5332 5334 To cancel an uncommitted merge (and lose your changes), use
5333 5335 :hg:`update --clean .`.
5334 5336
5335 5337 Use null as the changeset to remove the working directory (like
5336 5338 :hg:`clone -U`).
5337 5339
5338 5340 If you want to revert just one file to an older revision, use
5339 5341 :hg:`revert [-r REV] NAME`.
5340 5342
5341 5343 See :hg:`help dates` for a list of formats valid for -d/--date.
5342 5344
5343 5345 Returns 0 on success, 1 if there are unresolved files.
5344 5346 """
5345 5347 if rev and node:
5346 5348 raise error.Abort(_("please specify just one revision"))
5347 5349
5348 5350 if rev is None or rev == '':
5349 5351 rev = node
5350 5352
5351 5353 if date and rev is not None:
5352 5354 raise error.Abort(_("you can't specify a revision and a date"))
5353 5355
5354 5356 if check and clean:
5355 5357 raise error.Abort(_("cannot specify both -c/--check and -C/--clean"))
5356 5358
5357 5359 with repo.wlock():
5358 5360 cmdutil.clearunfinished(repo)
5359 5361
5360 5362 if date:
5361 5363 rev = cmdutil.finddate(ui, repo, date)
5362 5364
5363 5365 # if we defined a bookmark, we have to remember the original name
5364 5366 brev = rev
5365 5367 rev = scmutil.revsingle(repo, rev, rev).rev()
5366 5368
5367 5369 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
5368 5370
5369 5371 return hg.updatetotally(ui, repo, rev, brev, clean=clean, check=check)
5370 5372
5371 5373 @command('verify', [])
5372 5374 def verify(ui, repo):
5373 5375 """verify the integrity of the repository
5374 5376
5375 5377 Verify the integrity of the current repository.
5376 5378
5377 5379 This will perform an extensive check of the repository's
5378 5380 integrity, validating the hashes and checksums of each entry in
5379 5381 the changelog, manifest, and tracked files, as well as the
5380 5382 integrity of their crosslinks and indices.
5381 5383
5382 5384 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
5383 5385 for more information about recovery from corruption of the
5384 5386 repository.
5385 5387
5386 5388 Returns 0 on success, 1 if errors are encountered.
5387 5389 """
5388 5390 return hg.verify(repo)
5389 5391
5390 5392 @command('version', [] + formatteropts, norepo=True)
5391 5393 def version_(ui, **opts):
5392 5394 """output version and copyright information"""
5393 5395 fm = ui.formatter("version", opts)
5394 5396 fm.startitem()
5395 5397 fm.write("ver", _("Mercurial Distributed SCM (version %s)\n"),
5396 5398 util.version())
5397 5399 license = _(
5398 5400 "(see https://mercurial-scm.org for more information)\n"
5399 5401 "\nCopyright (C) 2005-2017 Matt Mackall and others\n"
5400 5402 "This is free software; see the source for copying conditions. "
5401 5403 "There is NO\nwarranty; "
5402 5404 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5403 5405 )
5404 5406 if not ui.quiet:
5405 5407 fm.plain(license)
5406 5408
5407 5409 if ui.verbose:
5408 5410 fm.plain(_("\nEnabled extensions:\n\n"))
5409 5411 # format names and versions into columns
5410 5412 names = []
5411 5413 vers = []
5412 5414 isinternals = []
5413 5415 for name, module in extensions.extensions():
5414 5416 names.append(name)
5415 5417 vers.append(extensions.moduleversion(module) or None)
5416 5418 isinternals.append(extensions.ismoduleinternal(module))
5417 5419 fn = fm.nested("extensions")
5418 5420 if names:
5419 5421 namefmt = " %%-%ds " % max(len(n) for n in names)
5420 5422 places = [_("external"), _("internal")]
5421 5423 for n, v, p in zip(names, vers, isinternals):
5422 5424 fn.startitem()
5423 5425 fn.condwrite(ui.verbose, "name", namefmt, n)
5424 5426 if ui.verbose:
5425 5427 fn.plain("%s " % places[p])
5426 5428 fn.data(bundled=p)
5427 5429 fn.condwrite(ui.verbose and v, "ver", "%s", v)
5428 5430 if ui.verbose:
5429 5431 fn.plain("\n")
5430 5432 fn.end()
5431 5433 fm.end()
5432 5434
5433 5435 def loadcmdtable(ui, name, cmdtable):
5434 5436 """Load command functions from specified cmdtable
5435 5437 """
5436 5438 overrides = [cmd for cmd in cmdtable if cmd in table]
5437 5439 if overrides:
5438 5440 ui.warn(_("extension '%s' overrides commands: %s\n")
5439 5441 % (name, " ".join(overrides)))
5440 5442 table.update(cmdtable)
@@ -1,892 +1,894 b''
1 1 # dispatch.py - command dispatching for mercurial
2 2 #
3 3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from __future__ import absolute_import, print_function
9 9
10 10 import atexit
11 11 import difflib
12 12 import errno
13 13 import getopt
14 14 import os
15 15 import pdb
16 16 import re
17 17 import signal
18 18 import sys
19 19 import time
20 20 import traceback
21 21
22 22
23 23 from .i18n import _
24 24
25 25 from . import (
26 26 cmdutil,
27 27 color,
28 28 commands,
29 29 debugcommands,
30 30 demandimport,
31 31 encoding,
32 32 error,
33 33 extensions,
34 34 fancyopts,
35 35 fileset,
36 36 hg,
37 37 hook,
38 38 profiling,
39 39 pycompat,
40 40 revset,
41 41 scmutil,
42 42 templatefilters,
43 43 templatekw,
44 44 templater,
45 45 ui as uimod,
46 46 util,
47 47 )
48 48
49 49 class request(object):
50 50 def __init__(self, args, ui=None, repo=None, fin=None, fout=None,
51 51 ferr=None):
52 52 self.args = args
53 53 self.ui = ui
54 54 self.repo = repo
55 55
56 56 # input/output/error streams
57 57 self.fin = fin
58 58 self.fout = fout
59 59 self.ferr = ferr
60 60
61 61 def run():
62 62 "run the command in sys.argv"
63 63 sys.exit((dispatch(request(pycompat.sysargv[1:])) or 0) & 255)
64 64
65 65 def _getsimilar(symbols, value):
66 66 sim = lambda x: difflib.SequenceMatcher(None, value, x).ratio()
67 67 # The cutoff for similarity here is pretty arbitrary. It should
68 68 # probably be investigated and tweaked.
69 69 return [s for s in symbols if sim(s) > 0.6]
70 70
71 71 def _reportsimilar(write, similar):
72 72 if len(similar) == 1:
73 73 write(_("(did you mean %s?)\n") % similar[0])
74 74 elif similar:
75 75 ss = ", ".join(sorted(similar))
76 76 write(_("(did you mean one of %s?)\n") % ss)
77 77
78 78 def _formatparse(write, inst):
79 79 similar = []
80 80 if isinstance(inst, error.UnknownIdentifier):
81 81 # make sure to check fileset first, as revset can invoke fileset
82 82 similar = _getsimilar(inst.symbols, inst.function)
83 83 if len(inst.args) > 1:
84 84 write(_("hg: parse error at %s: %s\n") %
85 85 (inst.args[1], inst.args[0]))
86 86 if (inst.args[0][0] == ' '):
87 87 write(_("unexpected leading whitespace\n"))
88 88 else:
89 89 write(_("hg: parse error: %s\n") % inst.args[0])
90 90 _reportsimilar(write, similar)
91 91 if inst.hint:
92 92 write(_("(%s)\n") % inst.hint)
93 93
94 94 def dispatch(req):
95 95 "run the command specified in req.args"
96 96 if req.ferr:
97 97 ferr = req.ferr
98 98 elif req.ui:
99 99 ferr = req.ui.ferr
100 100 else:
101 101 ferr = util.stderr
102 102
103 103 try:
104 104 if not req.ui:
105 105 req.ui = uimod.ui.load()
106 106 if '--traceback' in req.args:
107 107 req.ui.setconfig('ui', 'traceback', 'on', '--traceback')
108 108
109 109 # set ui streams from the request
110 110 if req.fin:
111 111 req.ui.fin = req.fin
112 112 if req.fout:
113 113 req.ui.fout = req.fout
114 114 if req.ferr:
115 115 req.ui.ferr = req.ferr
116 116 except error.Abort as inst:
117 117 ferr.write(_("abort: %s\n") % inst)
118 118 if inst.hint:
119 119 ferr.write(_("(%s)\n") % inst.hint)
120 120 return -1
121 121 except error.ParseError as inst:
122 122 _formatparse(ferr.write, inst)
123 123 return -1
124 124
125 125 msg = ' '.join(' ' in a and repr(a) or a for a in req.args)
126 126 starttime = util.timer()
127 127 ret = None
128 128 try:
129 129 ret = _runcatch(req)
130 130 except KeyboardInterrupt:
131 131 try:
132 132 req.ui.warn(_("interrupted!\n"))
133 133 except IOError as inst:
134 134 if inst.errno != errno.EPIPE:
135 135 raise
136 136 ret = -1
137 137 finally:
138 138 duration = util.timer() - starttime
139 139 req.ui.flush()
140 140 if req.ui.logblockedtimes:
141 141 req.ui._blockedtimes['command_duration'] = duration * 1000
142 142 req.ui.log('uiblocked', 'ui blocked ms', **req.ui._blockedtimes)
143 143 req.ui.log("commandfinish", "%s exited %s after %0.2f seconds\n",
144 144 msg, ret or 0, duration)
145 145 return ret
146 146
147 147 def _runcatch(req):
148 148 def catchterm(*args):
149 149 raise error.SignalInterrupt
150 150
151 151 ui = req.ui
152 152 try:
153 153 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
154 154 num = getattr(signal, name, None)
155 155 if num:
156 156 signal.signal(num, catchterm)
157 157 except ValueError:
158 158 pass # happens if called in a thread
159 159
160 160 def _runcatchfunc():
161 161 try:
162 162 debugger = 'pdb'
163 163 debugtrace = {
164 164 'pdb' : pdb.set_trace
165 165 }
166 166 debugmortem = {
167 167 'pdb' : pdb.post_mortem
168 168 }
169 169
170 170 # read --config before doing anything else
171 171 # (e.g. to change trust settings for reading .hg/hgrc)
172 172 cfgs = _parseconfig(req.ui, _earlygetopt(['--config'], req.args))
173 173
174 174 if req.repo:
175 175 # copy configs that were passed on the cmdline (--config) to
176 176 # the repo ui
177 177 for sec, name, val in cfgs:
178 178 req.repo.ui.setconfig(sec, name, val, source='--config')
179 179
180 180 # developer config: ui.debugger
181 181 debugger = ui.config("ui", "debugger")
182 182 debugmod = pdb
183 183 if not debugger or ui.plain():
184 184 # if we are in HGPLAIN mode, then disable custom debugging
185 185 debugger = 'pdb'
186 186 elif '--debugger' in req.args:
187 187 # This import can be slow for fancy debuggers, so only
188 188 # do it when absolutely necessary, i.e. when actual
189 189 # debugging has been requested
190 190 with demandimport.deactivated():
191 191 try:
192 192 debugmod = __import__(debugger)
193 193 except ImportError:
194 194 pass # Leave debugmod = pdb
195 195
196 196 debugtrace[debugger] = debugmod.set_trace
197 197 debugmortem[debugger] = debugmod.post_mortem
198 198
199 199 # enter the debugger before command execution
200 200 if '--debugger' in req.args:
201 201 ui.warn(_("entering debugger - "
202 202 "type c to continue starting hg or h for help\n"))
203 203
204 204 if (debugger != 'pdb' and
205 205 debugtrace[debugger] == debugtrace['pdb']):
206 206 ui.warn(_("%s debugger specified "
207 207 "but its module was not found\n") % debugger)
208 208 with demandimport.deactivated():
209 209 debugtrace[debugger]()
210 210 try:
211 211 return _dispatch(req)
212 212 finally:
213 213 ui.flush()
214 214 except: # re-raises
215 215 # enter the debugger when we hit an exception
216 216 if '--debugger' in req.args:
217 217 traceback.print_exc()
218 218 debugmortem[debugger](sys.exc_info()[2])
219 219 ui.traceback()
220 220 raise
221 221
222 222 return callcatch(ui, _runcatchfunc)
223 223
224 224 def callcatch(ui, func):
225 225 """like scmutil.callcatch but handles more high-level exceptions about
226 226 config parsing and commands. besides, use handlecommandexception to handle
227 227 uncaught exceptions.
228 228 """
229 229 try:
230 230 return scmutil.callcatch(ui, func)
231 231 except error.AmbiguousCommand as inst:
232 232 ui.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
233 233 (inst.args[0], " ".join(inst.args[1])))
234 234 except error.CommandError as inst:
235 235 if inst.args[0]:
236 236 ui.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
237 237 commands.help_(ui, inst.args[0], full=False, command=True)
238 238 else:
239 239 ui.warn(_("hg: %s\n") % inst.args[1])
240 240 commands.help_(ui, 'shortlist')
241 241 except error.ParseError as inst:
242 242 _formatparse(ui.warn, inst)
243 243 return -1
244 244 except error.UnknownCommand as inst:
245 245 ui.warn(_("hg: unknown command '%s'\n") % inst.args[0])
246 246 try:
247 247 # check if the command is in a disabled extension
248 248 # (but don't check for extensions themselves)
249 249 commands.help_(ui, inst.args[0], unknowncmd=True)
250 250 except (error.UnknownCommand, error.Abort):
251 251 suggested = False
252 252 if len(inst.args) == 2:
253 253 sim = _getsimilar(inst.args[1], inst.args[0])
254 254 if sim:
255 255 _reportsimilar(ui.warn, sim)
256 256 suggested = True
257 257 if not suggested:
258 258 commands.help_(ui, 'shortlist')
259 259 except IOError:
260 260 raise
261 261 except KeyboardInterrupt:
262 262 raise
263 263 except: # probably re-raises
264 264 if not handlecommandexception(ui):
265 265 raise
266 266
267 267 return -1
268 268
269 269 def aliasargs(fn, givenargs):
270 270 args = getattr(fn, 'args', [])
271 271 if args:
272 272 cmd = ' '.join(map(util.shellquote, args))
273 273
274 274 nums = []
275 275 def replacer(m):
276 276 num = int(m.group(1)) - 1
277 277 nums.append(num)
278 278 if num < len(givenargs):
279 279 return givenargs[num]
280 280 raise error.Abort(_('too few arguments for command alias'))
281 281 cmd = re.sub(r'\$(\d+|\$)', replacer, cmd)
282 282 givenargs = [x for i, x in enumerate(givenargs)
283 283 if i not in nums]
284 284 args = pycompat.shlexsplit(cmd)
285 285 return args + givenargs
286 286
287 287 def aliasinterpolate(name, args, cmd):
288 288 '''interpolate args into cmd for shell aliases
289 289
290 290 This also handles $0, $@ and "$@".
291 291 '''
292 292 # util.interpolate can't deal with "$@" (with quotes) because it's only
293 293 # built to match prefix + patterns.
294 294 replacemap = dict(('$%d' % (i + 1), arg) for i, arg in enumerate(args))
295 295 replacemap['$0'] = name
296 296 replacemap['$$'] = '$'
297 297 replacemap['$@'] = ' '.join(args)
298 298 # Typical Unix shells interpolate "$@" (with quotes) as all the positional
299 299 # parameters, separated out into words. Emulate the same behavior here by
300 300 # quoting the arguments individually. POSIX shells will then typically
301 301 # tokenize each argument into exactly one word.
302 302 replacemap['"$@"'] = ' '.join(util.shellquote(arg) for arg in args)
303 303 # escape '\$' for regex
304 304 regex = '|'.join(replacemap.keys()).replace('$', r'\$')
305 305 r = re.compile(regex)
306 306 return r.sub(lambda x: replacemap[x.group()], cmd)
307 307
308 308 class cmdalias(object):
309 309 def __init__(self, name, definition, cmdtable, source):
310 310 self.name = self.cmd = name
311 311 self.cmdname = ''
312 312 self.definition = definition
313 313 self.fn = None
314 314 self.givenargs = []
315 315 self.opts = []
316 316 self.help = ''
317 317 self.badalias = None
318 318 self.unknowncmd = False
319 319 self.source = source
320 320
321 321 try:
322 322 aliases, entry = cmdutil.findcmd(self.name, cmdtable)
323 323 for alias, e in cmdtable.iteritems():
324 324 if e is entry:
325 325 self.cmd = alias
326 326 break
327 327 self.shadows = True
328 328 except error.UnknownCommand:
329 329 self.shadows = False
330 330
331 331 if not self.definition:
332 332 self.badalias = _("no definition for alias '%s'") % self.name
333 333 return
334 334
335 335 if self.definition.startswith('!'):
336 336 self.shell = True
337 337 def fn(ui, *args):
338 338 env = {'HG_ARGS': ' '.join((self.name,) + args)}
339 339 def _checkvar(m):
340 340 if m.groups()[0] == '$':
341 341 return m.group()
342 342 elif int(m.groups()[0]) <= len(args):
343 343 return m.group()
344 344 else:
345 345 ui.debug("No argument found for substitution "
346 346 "of %i variable in alias '%s' definition."
347 347 % (int(m.groups()[0]), self.name))
348 348 return ''
349 349 cmd = re.sub(r'\$(\d+|\$)', _checkvar, self.definition[1:])
350 350 cmd = aliasinterpolate(self.name, args, cmd)
351 351 return ui.system(cmd, environ=env)
352 352 self.fn = fn
353 353 return
354 354
355 355 try:
356 356 args = pycompat.shlexsplit(self.definition)
357 357 except ValueError as inst:
358 358 self.badalias = (_("error in definition for alias '%s': %s")
359 359 % (self.name, inst))
360 360 return
361 361 self.cmdname = cmd = args.pop(0)
362 362 self.givenargs = args
363 363
364 364 for invalidarg in ("--cwd", "-R", "--repository", "--repo", "--config"):
365 365 if _earlygetopt([invalidarg], args):
366 366 self.badalias = (_("error in definition for alias '%s': %s may "
367 367 "only be given on the command line")
368 368 % (self.name, invalidarg))
369 369 return
370 370
371 371 try:
372 372 tableentry = cmdutil.findcmd(cmd, cmdtable, False)[1]
373 373 if len(tableentry) > 2:
374 374 self.fn, self.opts, self.help = tableentry
375 375 else:
376 376 self.fn, self.opts = tableentry
377 377
378 378 if self.help.startswith("hg " + cmd):
379 379 # drop prefix in old-style help lines so hg shows the alias
380 380 self.help = self.help[4 + len(cmd):]
381 381 self.__doc__ = self.fn.__doc__
382 382
383 383 except error.UnknownCommand:
384 384 self.badalias = (_("alias '%s' resolves to unknown command '%s'")
385 385 % (self.name, cmd))
386 386 self.unknowncmd = True
387 387 except error.AmbiguousCommand:
388 388 self.badalias = (_("alias '%s' resolves to ambiguous command '%s'")
389 389 % (self.name, cmd))
390 390
391 391 @property
392 392 def args(self):
393 393 args = map(util.expandpath, self.givenargs)
394 394 return aliasargs(self.fn, args)
395 395
396 396 def __getattr__(self, name):
397 397 adefaults = {'norepo': True, 'optionalrepo': False, 'inferrepo': False}
398 398 if name not in adefaults:
399 399 raise AttributeError(name)
400 400 if self.badalias or util.safehasattr(self, 'shell'):
401 401 return adefaults[name]
402 402 return getattr(self.fn, name)
403 403
404 404 def __call__(self, ui, *args, **opts):
405 405 if self.badalias:
406 406 hint = None
407 407 if self.unknowncmd:
408 408 try:
409 409 # check if the command is in a disabled extension
410 410 cmd, ext = extensions.disabledcmd(ui, self.cmdname)[:2]
411 411 hint = _("'%s' is provided by '%s' extension") % (cmd, ext)
412 412 except error.UnknownCommand:
413 413 pass
414 414 raise error.Abort(self.badalias, hint=hint)
415 415 if self.shadows:
416 416 ui.debug("alias '%s' shadows command '%s'\n" %
417 417 (self.name, self.cmdname))
418 418
419 419 ui.log('commandalias', "alias '%s' expands to '%s'\n",
420 420 self.name, self.definition)
421 421 if util.safehasattr(self, 'shell'):
422 422 return self.fn(ui, *args, **opts)
423 423 else:
424 424 try:
425 425 return util.checksignature(self.fn)(ui, *args, **opts)
426 426 except error.SignatureError:
427 427 args = ' '.join([self.cmdname] + self.args)
428 428 ui.debug("alias '%s' expands to '%s'\n" % (self.name, args))
429 429 raise
430 430
431 431 def addaliases(ui, cmdtable):
432 432 # aliases are processed after extensions have been loaded, so they
433 433 # may use extension commands. Aliases can also use other alias definitions,
434 434 # but only if they have been defined prior to the current definition.
435 435 for alias, definition in ui.configitems('alias'):
436 436 source = ui.configsource('alias', alias)
437 437 aliasdef = cmdalias(alias, definition, cmdtable, source)
438 438
439 439 try:
440 440 olddef = cmdtable[aliasdef.cmd][0]
441 441 if olddef.definition == aliasdef.definition:
442 442 continue
443 443 except (KeyError, AttributeError):
444 444 # definition might not exist or it might not be a cmdalias
445 445 pass
446 446
447 447 cmdtable[aliasdef.name] = (aliasdef, aliasdef.opts, aliasdef.help)
448 448
449 449 def _parse(ui, args):
450 450 options = {}
451 451 cmdoptions = {}
452 452
453 453 try:
454 454 args = fancyopts.fancyopts(args, commands.globalopts, options)
455 455 except getopt.GetoptError as inst:
456 456 raise error.CommandError(None, inst)
457 457
458 458 if args:
459 459 cmd, args = args[0], args[1:]
460 460 aliases, entry = cmdutil.findcmd(cmd, commands.table,
461 461 ui.configbool("ui", "strict"))
462 462 cmd = aliases[0]
463 463 args = aliasargs(entry[0], args)
464 464 defaults = ui.config("defaults", cmd)
465 465 if defaults:
466 466 args = map(util.expandpath, pycompat.shlexsplit(defaults)) + args
467 467 c = list(entry[1])
468 468 else:
469 469 cmd = None
470 470 c = []
471 471
472 472 # combine global options into local
473 473 for o in commands.globalopts:
474 474 c.append((o[0], o[1], options[o[1]], o[3]))
475 475
476 476 try:
477 477 args = fancyopts.fancyopts(args, c, cmdoptions, gnu=True)
478 478 except getopt.GetoptError as inst:
479 479 raise error.CommandError(cmd, inst)
480 480
481 481 # separate global options back out
482 482 for o in commands.globalopts:
483 483 n = o[1]
484 484 options[n] = cmdoptions[n]
485 485 del cmdoptions[n]
486 486
487 487 return (cmd, cmd and entry[0] or None, args, options, cmdoptions)
488 488
489 489 def _parseconfig(ui, config):
490 490 """parse the --config options from the command line"""
491 491 configs = []
492 492
493 493 for cfg in config:
494 494 try:
495 495 name, value = [cfgelem.strip()
496 496 for cfgelem in cfg.split('=', 1)]
497 497 section, name = name.split('.', 1)
498 498 if not section or not name:
499 499 raise IndexError
500 500 ui.setconfig(section, name, value, '--config')
501 501 configs.append((section, name, value))
502 502 except (IndexError, ValueError):
503 503 raise error.Abort(_('malformed --config option: %r '
504 504 '(use --config section.name=value)') % cfg)
505 505
506 506 return configs
507 507
508 508 def _earlygetopt(aliases, args):
509 509 """Return list of values for an option (or aliases).
510 510
511 511 The values are listed in the order they appear in args.
512 512 The options and values are removed from args.
513 513
514 514 >>> args = ['x', '--cwd', 'foo', 'y']
515 515 >>> _earlygetopt(['--cwd'], args), args
516 516 (['foo'], ['x', 'y'])
517 517
518 518 >>> args = ['x', '--cwd=bar', 'y']
519 519 >>> _earlygetopt(['--cwd'], args), args
520 520 (['bar'], ['x', 'y'])
521 521
522 522 >>> args = ['x', '-R', 'foo', 'y']
523 523 >>> _earlygetopt(['-R'], args), args
524 524 (['foo'], ['x', 'y'])
525 525
526 526 >>> args = ['x', '-Rbar', 'y']
527 527 >>> _earlygetopt(['-R'], args), args
528 528 (['bar'], ['x', 'y'])
529 529 """
530 530 try:
531 531 argcount = args.index("--")
532 532 except ValueError:
533 533 argcount = len(args)
534 534 shortopts = [opt for opt in aliases if len(opt) == 2]
535 535 values = []
536 536 pos = 0
537 537 while pos < argcount:
538 538 fullarg = arg = args[pos]
539 539 equals = arg.find('=')
540 540 if equals > -1:
541 541 arg = arg[:equals]
542 542 if arg in aliases:
543 543 del args[pos]
544 544 if equals > -1:
545 545 values.append(fullarg[equals + 1:])
546 546 argcount -= 1
547 547 else:
548 548 if pos + 1 >= argcount:
549 549 # ignore and let getopt report an error if there is no value
550 550 break
551 551 values.append(args.pop(pos))
552 552 argcount -= 2
553 553 elif arg[:2] in shortopts:
554 554 # short option can have no following space, e.g. hg log -Rfoo
555 555 values.append(args.pop(pos)[2:])
556 556 argcount -= 1
557 557 else:
558 558 pos += 1
559 559 return values
560 560
561 561 def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions):
562 562 # run pre-hook, and abort if it fails
563 563 hook.hook(lui, repo, "pre-%s" % cmd, True, args=" ".join(fullargs),
564 564 pats=cmdpats, opts=cmdoptions)
565 565 try:
566 566 ret = _runcommand(ui, options, cmd, d)
567 567 # run post-hook, passing command result
568 568 hook.hook(lui, repo, "post-%s" % cmd, False, args=" ".join(fullargs),
569 569 result=ret, pats=cmdpats, opts=cmdoptions)
570 570 except Exception:
571 571 # run failure hook and re-raise
572 572 hook.hook(lui, repo, "fail-%s" % cmd, False, args=" ".join(fullargs),
573 573 pats=cmdpats, opts=cmdoptions)
574 574 raise
575 575 return ret
576 576
577 577 def _getlocal(ui, rpath, wd=None):
578 578 """Return (path, local ui object) for the given target path.
579 579
580 580 Takes paths in [cwd]/.hg/hgrc into account."
581 581 """
582 582 if wd is None:
583 583 try:
584 584 wd = pycompat.getcwd()
585 585 except OSError as e:
586 586 raise error.Abort(_("error getting current working directory: %s") %
587 587 e.strerror)
588 588 path = cmdutil.findrepo(wd) or ""
589 589 if not path:
590 590 lui = ui
591 591 else:
592 592 lui = ui.copy()
593 593 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
594 594
595 595 if rpath and rpath[-1]:
596 596 path = lui.expandpath(rpath[-1])
597 597 lui = ui.copy()
598 598 lui.readconfig(os.path.join(path, ".hg", "hgrc"), path)
599 599
600 600 return path, lui
601 601
602 602 def _checkshellalias(lui, ui, args):
603 603 """Return the function to run the shell alias, if it is required"""
604 604 options = {}
605 605
606 606 try:
607 607 args = fancyopts.fancyopts(args, commands.globalopts, options)
608 608 except getopt.GetoptError:
609 609 return
610 610
611 611 if not args:
612 612 return
613 613
614 614 cmdtable = commands.table
615 615
616 616 cmd = args[0]
617 617 try:
618 618 strict = ui.configbool("ui", "strict")
619 619 aliases, entry = cmdutil.findcmd(cmd, cmdtable, strict)
620 620 except (error.AmbiguousCommand, error.UnknownCommand):
621 621 return
622 622
623 623 cmd = aliases[0]
624 624 fn = entry[0]
625 625
626 626 if cmd and util.safehasattr(fn, 'shell'):
627 627 d = lambda: fn(ui, *args[1:])
628 628 return lambda: runcommand(lui, None, cmd, args[:1], ui, options, d,
629 629 [], {})
630 630
631 631 _loaded = set()
632 632
633 633 # list of (objname, loadermod, loadername) tuple:
634 634 # - objname is the name of an object in extension module, from which
635 635 # extra information is loaded
636 636 # - loadermod is the module where loader is placed
637 637 # - loadername is the name of the function, which takes (ui, extensionname,
638 638 # extraobj) arguments
639 639 extraloaders = [
640 640 ('cmdtable', commands, 'loadcmdtable'),
641 641 ('colortable', color, 'loadcolortable'),
642 642 ('filesetpredicate', fileset, 'loadpredicate'),
643 643 ('revsetpredicate', revset, 'loadpredicate'),
644 644 ('templatefilter', templatefilters, 'loadfilter'),
645 645 ('templatefunc', templater, 'loadfunction'),
646 646 ('templatekeyword', templatekw, 'loadkeyword'),
647 647 ]
648 648
649 649 def _dispatch(req):
650 650 args = req.args
651 651 ui = req.ui
652 652
653 653 # check for cwd
654 654 cwd = _earlygetopt(['--cwd'], args)
655 655 if cwd:
656 656 os.chdir(cwd[-1])
657 657
658 658 rpath = _earlygetopt(["-R", "--repository", "--repo"], args)
659 659 path, lui = _getlocal(ui, rpath)
660 660
661 661 # Side-effect of accessing is debugcommands module is guaranteed to be
662 662 # imported and commands.table is populated.
663 663 debugcommands.command
664 664
665 665 uis = set([ui, lui])
666 666
667 667 if req.repo:
668 668 uis.add(req.repo.ui)
669 669
670 670 if '--profile' in args:
671 671 for ui_ in uis:
672 672 ui_.setconfig('profiling', 'enabled', 'true', '--profile')
673 673
674 674 with profiling.maybeprofile(lui):
675 675 # Configure extensions in phases: uisetup, extsetup, cmdtable, and
676 676 # reposetup. Programs like TortoiseHg will call _dispatch several
677 677 # times so we keep track of configured extensions in _loaded.
678 678 extensions.loadall(lui)
679 679 exts = [ext for ext in extensions.extensions() if ext[0] not in _loaded]
680 680 # Propagate any changes to lui.__class__ by extensions
681 681 ui.__class__ = lui.__class__
682 682
683 683 # (uisetup and extsetup are handled in extensions.loadall)
684 684
685 685 for name, module in exts:
686 686 for objname, loadermod, loadername in extraloaders:
687 687 extraobj = getattr(module, objname, None)
688 688 if extraobj is not None:
689 689 getattr(loadermod, loadername)(ui, name, extraobj)
690 690 _loaded.add(name)
691 691
692 692 # (reposetup is handled in hg.repository)
693 693
694 694 addaliases(lui, commands.table)
695 695
696 696 # All aliases and commands are completely defined, now.
697 697 # Check abbreviation/ambiguity of shell alias.
698 698 shellaliasfn = _checkshellalias(lui, ui, args)
699 699 if shellaliasfn:
700 700 return shellaliasfn()
701 701
702 702 # check for fallback encoding
703 703 fallback = lui.config('ui', 'fallbackencoding')
704 704 if fallback:
705 705 encoding.fallbackencoding = fallback
706 706
707 707 fullargs = args
708 708 cmd, func, args, options, cmdoptions = _parse(lui, args)
709 709
710 710 if options["config"]:
711 711 raise error.Abort(_("option --config may not be abbreviated!"))
712 712 if options["cwd"]:
713 713 raise error.Abort(_("option --cwd may not be abbreviated!"))
714 714 if options["repository"]:
715 715 raise error.Abort(_(
716 716 "option -R has to be separated from other options (e.g. not "
717 717 "-qR) and --repository may only be abbreviated as --repo!"))
718 718
719 719 if options["encoding"]:
720 720 encoding.encoding = options["encoding"]
721 721 if options["encodingmode"]:
722 722 encoding.encodingmode = options["encodingmode"]
723 723 if options["time"]:
724 724 def get_times():
725 725 t = os.times()
726 726 if t[4] == 0.0:
727 727 # Windows leaves this as zero, so use time.clock()
728 728 t = (t[0], t[1], t[2], t[3], time.clock())
729 729 return t
730 730 s = get_times()
731 731 def print_time():
732 732 t = get_times()
733 733 ui.warn(
734 734 _("time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
735 735 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
736 736 atexit.register(print_time)
737 737
738 738 if options['verbose'] or options['debug'] or options['quiet']:
739 739 for opt in ('verbose', 'debug', 'quiet'):
740 740 val = str(bool(options[opt]))
741 741 for ui_ in uis:
742 742 ui_.setconfig('ui', opt, val, '--' + opt)
743 743
744 744 if options['traceback']:
745 745 for ui_ in uis:
746 746 ui_.setconfig('ui', 'traceback', 'on', '--traceback')
747 747
748 748 if options['noninteractive']:
749 749 for ui_ in uis:
750 750 ui_.setconfig('ui', 'interactive', 'off', '-y')
751 751
752 752 if cmdoptions.get('insecure', False):
753 753 for ui_ in uis:
754 754 ui_.insecureconnections = True
755 755
756 756 if options['version']:
757 757 return commands.version_(ui)
758 758 if options['help']:
759 759 return commands.help_(ui, cmd, command=cmd is not None)
760 760 elif not cmd:
761 761 return commands.help_(ui, 'shortlist')
762 762
763 763 repo = None
764 764 cmdpats = args[:]
765 765 if not func.norepo:
766 766 # use the repo from the request only if we don't have -R
767 767 if not rpath and not cwd:
768 768 repo = req.repo
769 769
770 770 if repo:
771 771 # set the descriptors of the repo ui to those of ui
772 772 repo.ui.fin = ui.fin
773 773 repo.ui.fout = ui.fout
774 774 repo.ui.ferr = ui.ferr
775 775 else:
776 776 try:
777 777 repo = hg.repository(ui, path=path)
778 778 if not repo.local():
779 779 raise error.Abort(_("repository '%s' is not local")
780 780 % path)
781 781 repo.ui.setconfig("bundle", "mainreporoot", repo.root,
782 782 'repo')
783 783 except error.RequirementError:
784 784 raise
785 785 except error.RepoError:
786 786 if rpath and rpath[-1]: # invalid -R path
787 787 raise
788 788 if not func.optionalrepo:
789 789 if func.inferrepo and args and not path:
790 790 # try to infer -R from command args
791 791 repos = map(cmdutil.findrepo, args)
792 792 guess = repos[0]
793 793 if guess and repos.count(guess) == len(repos):
794 794 req.args = ['--repository', guess] + fullargs
795 795 return _dispatch(req)
796 796 if not path:
797 797 raise error.RepoError(_("no repository found in"
798 798 " '%s' (.hg not found)")
799 799 % pycompat.getcwd())
800 800 raise
801 801 if repo:
802 802 ui = repo.ui
803 803 if options['hidden']:
804 804 repo = repo.unfiltered()
805 805 args.insert(0, repo)
806 806 elif rpath:
807 807 ui.warn(_("warning: --repository ignored\n"))
808 808
809 809 msg = ' '.join(' ' in a and repr(a) or a for a in fullargs)
810 810 ui.log("command", '%s\n', msg)
811 811 strcmdopt = pycompat.strkwargs(cmdoptions)
812 812 d = lambda: util.checksignature(func)(ui, *args, **strcmdopt)
813 813 try:
814 814 return runcommand(lui, repo, cmd, fullargs, ui, options, d,
815 815 cmdpats, cmdoptions)
816 816 finally:
817 817 if repo and repo != req.repo:
818 818 repo.close()
819 819
820 820 def _runcommand(ui, options, cmd, cmdfunc):
821 821 """Run a command function, possibly with profiling enabled."""
822 if util.parsebool(options['pager']):
823 ui.pager('internal-always-' + cmd)
822 824 try:
823 825 return cmdfunc()
824 826 except error.SignatureError:
825 827 raise error.CommandError(cmd, _('invalid arguments'))
826 828
827 829 def _exceptionwarning(ui):
828 830 """Produce a warning message for the current active exception"""
829 831
830 832 # For compatibility checking, we discard the portion of the hg
831 833 # version after the + on the assumption that if a "normal
832 834 # user" is running a build with a + in it the packager
833 835 # probably built from fairly close to a tag and anyone with a
834 836 # 'make local' copy of hg (where the version number can be out
835 837 # of date) will be clueful enough to notice the implausible
836 838 # version number and try updating.
837 839 ct = util.versiontuple(n=2)
838 840 worst = None, ct, ''
839 841 if ui.config('ui', 'supportcontact', None) is None:
840 842 for name, mod in extensions.extensions():
841 843 testedwith = getattr(mod, 'testedwith', '')
842 844 report = getattr(mod, 'buglink', _('the extension author.'))
843 845 if not testedwith.strip():
844 846 # We found an untested extension. It's likely the culprit.
845 847 worst = name, 'unknown', report
846 848 break
847 849
848 850 # Never blame on extensions bundled with Mercurial.
849 851 if extensions.ismoduleinternal(mod):
850 852 continue
851 853
852 854 tested = [util.versiontuple(t, 2) for t in testedwith.split()]
853 855 if ct in tested:
854 856 continue
855 857
856 858 lower = [t for t in tested if t < ct]
857 859 nearest = max(lower or tested)
858 860 if worst[0] is None or nearest < worst[1]:
859 861 worst = name, nearest, report
860 862 if worst[0] is not None:
861 863 name, testedwith, report = worst
862 864 if not isinstance(testedwith, str):
863 865 testedwith = '.'.join([str(c) for c in testedwith])
864 866 warning = (_('** Unknown exception encountered with '
865 867 'possibly-broken third-party extension %s\n'
866 868 '** which supports versions %s of Mercurial.\n'
867 869 '** Please disable %s and try your action again.\n'
868 870 '** If that fixes the bug please report it to %s\n')
869 871 % (name, testedwith, name, report))
870 872 else:
871 873 bugtracker = ui.config('ui', 'supportcontact', None)
872 874 if bugtracker is None:
873 875 bugtracker = _("https://mercurial-scm.org/wiki/BugTracker")
874 876 warning = (_("** unknown exception encountered, "
875 877 "please report by visiting\n** ") + bugtracker + '\n')
876 878 warning += ((_("** Python %s\n") % sys.version.replace('\n', '')) +
877 879 (_("** Mercurial Distributed SCM (version %s)\n") %
878 880 util.version()) +
879 881 (_("** Extensions loaded: %s\n") %
880 882 ", ".join([x[0] for x in extensions.extensions()])))
881 883 return warning
882 884
883 885 def handlecommandexception(ui):
884 886 """Produce a warning message for broken commands
885 887
886 888 Called when handling an exception; the exception is reraised if
887 889 this function returns False, ignored otherwise.
888 890 """
889 891 warning = _exceptionwarning(ui)
890 892 ui.log("commandexception", "%s\n%s\n", warning, traceback.format_exc())
891 893 ui.warn(warning)
892 894 return False # re-raise the exception
@@ -1,354 +1,356 b''
1 1 Show all commands except debug commands
2 2 $ hg debugcomplete
3 3 add
4 4 addremove
5 5 annotate
6 6 archive
7 7 backout
8 8 bisect
9 9 bookmarks
10 10 branch
11 11 branches
12 12 bundle
13 13 cat
14 14 clone
15 15 commit
16 16 config
17 17 copy
18 18 diff
19 19 export
20 20 files
21 21 forget
22 22 graft
23 23 grep
24 24 heads
25 25 help
26 26 identify
27 27 import
28 28 incoming
29 29 init
30 30 locate
31 31 log
32 32 manifest
33 33 merge
34 34 outgoing
35 35 parents
36 36 paths
37 37 phase
38 38 pull
39 39 push
40 40 recover
41 41 remove
42 42 rename
43 43 resolve
44 44 revert
45 45 rollback
46 46 root
47 47 serve
48 48 status
49 49 summary
50 50 tag
51 51 tags
52 52 tip
53 53 unbundle
54 54 update
55 55 verify
56 56 version
57 57
58 58 Show all commands that start with "a"
59 59 $ hg debugcomplete a
60 60 add
61 61 addremove
62 62 annotate
63 63 archive
64 64
65 65 Do not show debug commands if there are other candidates
66 66 $ hg debugcomplete d
67 67 diff
68 68
69 69 Show debug commands if there are no other candidates
70 70 $ hg debugcomplete debug
71 71 debugancestor
72 72 debugapplystreamclonebundle
73 73 debugbuilddag
74 74 debugbundle
75 75 debugcheckstate
76 76 debugcommands
77 77 debugcomplete
78 78 debugconfig
79 79 debugcreatestreamclonebundle
80 80 debugdag
81 81 debugdata
82 82 debugdate
83 83 debugdeltachain
84 84 debugdirstate
85 85 debugdiscovery
86 86 debugextensions
87 87 debugfileset
88 88 debugfsinfo
89 89 debuggetbundle
90 90 debugignore
91 91 debugindex
92 92 debugindexdot
93 93 debuginstall
94 94 debugknown
95 95 debuglabelcomplete
96 96 debuglocks
97 97 debugmergestate
98 98 debugnamecomplete
99 99 debugobsolete
100 100 debugpathcomplete
101 101 debugpushkey
102 102 debugpvec
103 103 debugrebuilddirstate
104 104 debugrebuildfncache
105 105 debugrename
106 106 debugrevlog
107 107 debugrevspec
108 108 debugsetparents
109 109 debugsub
110 110 debugsuccessorssets
111 111 debugtemplate
112 112 debugupgraderepo
113 113 debugwalk
114 114 debugwireargs
115 115
116 116 Do not show the alias of a debug command if there are other candidates
117 117 (this should hide rawcommit)
118 118 $ hg debugcomplete r
119 119 recover
120 120 remove
121 121 rename
122 122 resolve
123 123 revert
124 124 rollback
125 125 root
126 126 Show the alias of a debug command if there are no other candidates
127 127 $ hg debugcomplete rawc
128 128
129 129
130 130 Show the global options
131 131 $ hg debugcomplete --options | sort
132 132 --config
133 133 --cwd
134 134 --debug
135 135 --debugger
136 136 --encoding
137 137 --encodingmode
138 138 --help
139 139 --hidden
140 140 --noninteractive
141 --pager
141 142 --profile
142 143 --quiet
143 144 --repository
144 145 --time
145 146 --traceback
146 147 --verbose
147 148 --version
148 149 -R
149 150 -h
150 151 -q
151 152 -v
152 153 -y
153 154
154 155 Show the options for the "serve" command
155 156 $ hg debugcomplete --options serve | sort
156 157 --accesslog
157 158 --address
158 159 --certificate
159 160 --cmdserver
160 161 --config
161 162 --cwd
162 163 --daemon
163 164 --daemon-postexec
164 165 --debug
165 166 --debugger
166 167 --encoding
167 168 --encodingmode
168 169 --errorlog
169 170 --help
170 171 --hidden
171 172 --ipv6
172 173 --name
173 174 --noninteractive
175 --pager
174 176 --pid-file
175 177 --port
176 178 --prefix
177 179 --profile
178 180 --quiet
179 181 --repository
180 182 --stdio
181 183 --style
182 184 --templates
183 185 --time
184 186 --traceback
185 187 --verbose
186 188 --version
187 189 --web-conf
188 190 -6
189 191 -A
190 192 -E
191 193 -R
192 194 -a
193 195 -d
194 196 -h
195 197 -n
196 198 -p
197 199 -q
198 200 -t
199 201 -v
200 202 -y
201 203
202 204 Show an error if we use --options with an ambiguous abbreviation
203 205 $ hg debugcomplete --options s
204 206 hg: command 's' is ambiguous:
205 207 serve showconfig status summary
206 208 [255]
207 209
208 210 Show all commands + options
209 211 $ hg debugcommands
210 212 add: include, exclude, subrepos, dry-run
211 213 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
212 214 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
213 215 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
214 216 diff: rev, change, text, git, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, root, include, exclude, subrepos
215 217 export: output, switch-parent, rev, text, git, nodates
216 218 forget: include, exclude
217 219 init: ssh, remotecmd, insecure
218 220 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
219 221 merge: force, rev, preview, tool
220 222 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
221 223 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
222 224 remove: after, force, subrepos, include, exclude
223 225 serve: accesslog, daemon, daemon-postexec, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
224 226 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
225 227 summary: remote
226 228 update: clean, check, date, rev, tool
227 229 addremove: similarity, subrepos, include, exclude, dry-run
228 230 archive: no-decode, prefix, rev, type, subrepos, include, exclude
229 231 backout: merge, commit, no-commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
230 232 bisect: reset, good, bad, skip, extend, command, noupdate
231 233 bookmarks: force, rev, delete, rename, inactive, template
232 234 branch: force, clean
233 235 branches: active, closed, template
234 236 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
235 237 cat: output, rev, decode, include, exclude
236 238 config: untrusted, edit, local, global, template
237 239 copy: after, force, include, exclude, dry-run
238 240 debugancestor:
239 241 debugapplystreamclonebundle:
240 242 debugbuilddag: mergeable-file, overwritten-file, new-file
241 243 debugbundle: all, spec
242 244 debugcheckstate:
243 245 debugcommands:
244 246 debugcomplete: options
245 247 debugcreatestreamclonebundle:
246 248 debugdag: tags, branches, dots, spaces
247 249 debugdata: changelog, manifest, dir
248 250 debugdate: extended
249 251 debugdeltachain: changelog, manifest, dir, template
250 252 debugdirstate: nodates, datesort
251 253 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
252 254 debugextensions: template
253 255 debugfileset: rev
254 256 debugfsinfo:
255 257 debuggetbundle: head, common, type
256 258 debugignore:
257 259 debugindex: changelog, manifest, dir, format
258 260 debugindexdot: changelog, manifest, dir
259 261 debuginstall: template
260 262 debugknown:
261 263 debuglabelcomplete:
262 264 debuglocks: force-lock, force-wlock
263 265 debugmergestate:
264 266 debugnamecomplete:
265 267 debugobsolete: flags, record-parents, rev, index, delete, date, user, template
266 268 debugpathcomplete: full, normal, added, removed
267 269 debugpushkey:
268 270 debugpvec:
269 271 debugrebuilddirstate: rev, minimal
270 272 debugrebuildfncache:
271 273 debugrename: rev
272 274 debugrevlog: changelog, manifest, dir, dump
273 275 debugrevspec: optimize, show-stage, no-optimized, verify-optimized
274 276 debugsetparents:
275 277 debugsub: rev
276 278 debugsuccessorssets:
277 279 debugtemplate: rev, define
278 280 debugupgraderepo: optimize, run
279 281 debugwalk: include, exclude
280 282 debugwireargs: three, four, five, ssh, remotecmd, insecure
281 283 files: rev, print0, include, exclude, template, subrepos
282 284 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
283 285 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, template, include, exclude
284 286 heads: rev, topo, active, closed, style, template
285 287 help: extension, command, keyword, system
286 288 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
287 289 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
288 290 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
289 291 locate: rev, print0, fullpath, include, exclude
290 292 manifest: rev, all, template
291 293 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
292 294 parents: rev, style, template
293 295 paths: template
294 296 phase: public, draft, secret, force, rev
295 297 recover:
296 298 rename: after, force, include, exclude, dry-run
297 299 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
298 300 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
299 301 rollback: dry-run, force
300 302 root:
301 303 tag: force, local, rev, remove, edit, message, date, user
302 304 tags: template
303 305 tip: patch, git, style, template
304 306 unbundle: update
305 307 verify:
306 308 version: template
307 309
308 310 $ hg init a
309 311 $ cd a
310 312 $ echo fee > fee
311 313 $ hg ci -q -Amfee
312 314 $ hg tag fee
313 315 $ mkdir fie
314 316 $ echo dead > fie/dead
315 317 $ echo live > fie/live
316 318 $ hg bookmark fo
317 319 $ hg branch -q fie
318 320 $ hg ci -q -Amfie
319 321 $ echo fo > fo
320 322 $ hg branch -qf default
321 323 $ hg ci -q -Amfo
322 324 $ echo Fum > Fum
323 325 $ hg ci -q -AmFum
324 326 $ hg bookmark Fum
325 327
326 328 Test debugpathcomplete
327 329
328 330 $ hg debugpathcomplete f
329 331 fee
330 332 fie
331 333 fo
332 334 $ hg debugpathcomplete -f f
333 335 fee
334 336 fie/dead
335 337 fie/live
336 338 fo
337 339
338 340 $ hg rm Fum
339 341 $ hg debugpathcomplete -r F
340 342 Fum
341 343
342 344 Test debugnamecomplete
343 345
344 346 $ hg debugnamecomplete
345 347 Fum
346 348 default
347 349 fee
348 350 fie
349 351 fo
350 352 tip
351 353 $ hg debugnamecomplete f
352 354 fee
353 355 fie
354 356 fo
@@ -1,1527 +1,1539 b''
1 1 Test basic extension support
2 2
3 3 $ cat > foobar.py <<EOF
4 4 > import os
5 5 > from mercurial import cmdutil, commands
6 6 > cmdtable = {}
7 7 > command = cmdutil.command(cmdtable)
8 8 > def uisetup(ui):
9 9 > ui.write("uisetup called\\n")
10 10 > ui.flush()
11 11 > def reposetup(ui, repo):
12 12 > ui.write("reposetup called for %s\\n" % os.path.basename(repo.root))
13 13 > ui.write("ui %s= repo.ui\\n" % (ui == repo.ui and "=" or "!"))
14 14 > ui.flush()
15 15 > @command('foo', [], 'hg foo')
16 16 > def foo(ui, *args, **kwargs):
17 17 > ui.write("Foo\\n")
18 18 > @command('bar', [], 'hg bar', norepo=True)
19 19 > def bar(ui, *args, **kwargs):
20 20 > ui.write("Bar\\n")
21 21 > EOF
22 22 $ abspath=`pwd`/foobar.py
23 23
24 24 $ mkdir barfoo
25 25 $ cp foobar.py barfoo/__init__.py
26 26 $ barfoopath=`pwd`/barfoo
27 27
28 28 $ hg init a
29 29 $ cd a
30 30 $ echo foo > file
31 31 $ hg add file
32 32 $ hg commit -m 'add file'
33 33
34 34 $ echo '[extensions]' >> $HGRCPATH
35 35 $ echo "foobar = $abspath" >> $HGRCPATH
36 36 $ hg foo
37 37 uisetup called
38 38 reposetup called for a
39 39 ui == repo.ui
40 40 Foo
41 41
42 42 $ cd ..
43 43 $ hg clone a b
44 44 uisetup called
45 45 reposetup called for a
46 46 ui == repo.ui
47 47 reposetup called for b
48 48 ui == repo.ui
49 49 updating to branch default
50 50 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
51 51
52 52 $ hg bar
53 53 uisetup called
54 54 Bar
55 55 $ echo 'foobar = !' >> $HGRCPATH
56 56
57 57 module/__init__.py-style
58 58
59 59 $ echo "barfoo = $barfoopath" >> $HGRCPATH
60 60 $ cd a
61 61 $ hg foo
62 62 uisetup called
63 63 reposetup called for a
64 64 ui == repo.ui
65 65 Foo
66 66 $ echo 'barfoo = !' >> $HGRCPATH
67 67
68 68 Check that extensions are loaded in phases:
69 69
70 70 $ cat > foo.py <<EOF
71 71 > import os
72 72 > name = os.path.basename(__file__).rsplit('.', 1)[0]
73 73 > print "1) %s imported" % name
74 74 > def uisetup(ui):
75 75 > print "2) %s uisetup" % name
76 76 > def extsetup():
77 77 > print "3) %s extsetup" % name
78 78 > def reposetup(ui, repo):
79 79 > print "4) %s reposetup" % name
80 80 > EOF
81 81
82 82 $ cp foo.py bar.py
83 83 $ echo 'foo = foo.py' >> $HGRCPATH
84 84 $ echo 'bar = bar.py' >> $HGRCPATH
85 85
86 86 Command with no output, we just want to see the extensions loaded:
87 87
88 88 $ hg paths
89 89 1) foo imported
90 90 1) bar imported
91 91 2) foo uisetup
92 92 2) bar uisetup
93 93 3) foo extsetup
94 94 3) bar extsetup
95 95 4) foo reposetup
96 96 4) bar reposetup
97 97
98 98 Check hgweb's load order:
99 99
100 100 $ cat > hgweb.cgi <<EOF
101 101 > #!/usr/bin/env python
102 102 > from mercurial import demandimport; demandimport.enable()
103 103 > from mercurial.hgweb import hgweb
104 104 > from mercurial.hgweb import wsgicgi
105 105 > application = hgweb('.', 'test repo')
106 106 > wsgicgi.launch(application)
107 107 > EOF
108 108
109 109 $ REQUEST_METHOD='GET' PATH_INFO='/' SCRIPT_NAME='' QUERY_STRING='' \
110 110 > SERVER_PORT='80' SERVER_NAME='localhost' python hgweb.cgi \
111 111 > | grep '^[0-9]) ' # ignores HTML output
112 112 1) foo imported
113 113 1) bar imported
114 114 2) foo uisetup
115 115 2) bar uisetup
116 116 3) foo extsetup
117 117 3) bar extsetup
118 118 4) foo reposetup
119 119 4) bar reposetup
120 120
121 121 $ echo 'foo = !' >> $HGRCPATH
122 122 $ echo 'bar = !' >> $HGRCPATH
123 123
124 124 Check "from __future__ import absolute_import" support for external libraries
125 125
126 126 #if windows
127 127 $ PATHSEP=";"
128 128 #else
129 129 $ PATHSEP=":"
130 130 #endif
131 131 $ export PATHSEP
132 132
133 133 $ mkdir $TESTTMP/libroot
134 134 $ echo "s = 'libroot/ambig.py'" > $TESTTMP/libroot/ambig.py
135 135 $ mkdir $TESTTMP/libroot/mod
136 136 $ touch $TESTTMP/libroot/mod/__init__.py
137 137 $ echo "s = 'libroot/mod/ambig.py'" > $TESTTMP/libroot/mod/ambig.py
138 138
139 139 #if absimport
140 140 $ cat > $TESTTMP/libroot/mod/ambigabs.py <<EOF
141 141 > from __future__ import absolute_import
142 142 > import ambig # should load "libroot/ambig.py"
143 143 > s = ambig.s
144 144 > EOF
145 145 $ cat > loadabs.py <<EOF
146 146 > import mod.ambigabs as ambigabs
147 147 > def extsetup():
148 148 > print 'ambigabs.s=%s' % ambigabs.s
149 149 > EOF
150 150 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadabs=loadabs.py root)
151 151 ambigabs.s=libroot/ambig.py
152 152 $TESTTMP/a (glob)
153 153 #endif
154 154
155 155 #if no-py3k
156 156 $ cat > $TESTTMP/libroot/mod/ambigrel.py <<EOF
157 157 > import ambig # should load "libroot/mod/ambig.py"
158 158 > s = ambig.s
159 159 > EOF
160 160 $ cat > loadrel.py <<EOF
161 161 > import mod.ambigrel as ambigrel
162 162 > def extsetup():
163 163 > print 'ambigrel.s=%s' % ambigrel.s
164 164 > EOF
165 165 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}/libroot; hg --config extensions.loadrel=loadrel.py root)
166 166 ambigrel.s=libroot/mod/ambig.py
167 167 $TESTTMP/a (glob)
168 168 #endif
169 169
170 170 Check absolute/relative import of extension specific modules
171 171
172 172 $ mkdir $TESTTMP/extroot
173 173 $ cat > $TESTTMP/extroot/bar.py <<EOF
174 174 > s = 'this is extroot.bar'
175 175 > EOF
176 176 $ mkdir $TESTTMP/extroot/sub1
177 177 $ cat > $TESTTMP/extroot/sub1/__init__.py <<EOF
178 178 > s = 'this is extroot.sub1.__init__'
179 179 > EOF
180 180 $ cat > $TESTTMP/extroot/sub1/baz.py <<EOF
181 181 > s = 'this is extroot.sub1.baz'
182 182 > EOF
183 183 $ cat > $TESTTMP/extroot/__init__.py <<EOF
184 184 > s = 'this is extroot.__init__'
185 185 > import foo
186 186 > def extsetup(ui):
187 187 > ui.write('(extroot) ', foo.func(), '\n')
188 188 > ui.flush()
189 189 > EOF
190 190
191 191 $ cat > $TESTTMP/extroot/foo.py <<EOF
192 192 > # test absolute import
193 193 > buf = []
194 194 > def func():
195 195 > # "not locals" case
196 196 > import extroot.bar
197 197 > buf.append('import extroot.bar in func(): %s' % extroot.bar.s)
198 198 > return '\n(extroot) '.join(buf)
199 199 > # "fromlist == ('*',)" case
200 200 > from extroot.bar import *
201 201 > buf.append('from extroot.bar import *: %s' % s)
202 202 > # "not fromlist" and "if '.' in name" case
203 203 > import extroot.sub1.baz
204 204 > buf.append('import extroot.sub1.baz: %s' % extroot.sub1.baz.s)
205 205 > # "not fromlist" and NOT "if '.' in name" case
206 206 > import extroot
207 207 > buf.append('import extroot: %s' % extroot.s)
208 208 > # NOT "not fromlist" and NOT "level != -1" case
209 209 > from extroot.bar import s
210 210 > buf.append('from extroot.bar import s: %s' % s)
211 211 > EOF
212 212 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.extroot=$TESTTMP/extroot root)
213 213 (extroot) from extroot.bar import *: this is extroot.bar
214 214 (extroot) import extroot.sub1.baz: this is extroot.sub1.baz
215 215 (extroot) import extroot: this is extroot.__init__
216 216 (extroot) from extroot.bar import s: this is extroot.bar
217 217 (extroot) import extroot.bar in func(): this is extroot.bar
218 218 $TESTTMP/a (glob)
219 219
220 220 #if no-py3k
221 221 $ rm "$TESTTMP"/extroot/foo.*
222 222 $ cat > $TESTTMP/extroot/foo.py <<EOF
223 223 > # test relative import
224 224 > buf = []
225 225 > def func():
226 226 > # "not locals" case
227 227 > import bar
228 228 > buf.append('import bar in func(): %s' % bar.s)
229 229 > return '\n(extroot) '.join(buf)
230 230 > # "fromlist == ('*',)" case
231 231 > from bar import *
232 232 > buf.append('from bar import *: %s' % s)
233 233 > # "not fromlist" and "if '.' in name" case
234 234 > import sub1.baz
235 235 > buf.append('import sub1.baz: %s' % sub1.baz.s)
236 236 > # "not fromlist" and NOT "if '.' in name" case
237 237 > import sub1
238 238 > buf.append('import sub1: %s' % sub1.s)
239 239 > # NOT "not fromlist" and NOT "level != -1" case
240 240 > from bar import s
241 241 > buf.append('from bar import s: %s' % s)
242 242 > EOF
243 243 $ hg --config extensions.extroot=$TESTTMP/extroot root
244 244 (extroot) from bar import *: this is extroot.bar
245 245 (extroot) import sub1.baz: this is extroot.sub1.baz
246 246 (extroot) import sub1: this is extroot.sub1.__init__
247 247 (extroot) from bar import s: this is extroot.bar
248 248 (extroot) import bar in func(): this is extroot.bar
249 249 $TESTTMP/a (glob)
250 250 #endif
251 251
252 252 #if demandimport absimport
253 253
254 254 Examine whether module loading is delayed until actual referring, even
255 255 though module is imported with "absolute_import" feature.
256 256
257 257 Files below in each packages are used for described purpose:
258 258
259 259 - "called": examine whether "from MODULE import ATTR" works correctly
260 260 - "unused": examine whether loading is delayed correctly
261 261 - "used": examine whether "from PACKAGE import MODULE" works correctly
262 262
263 263 Package hierarchy is needed to examine whether demand importing works
264 264 as expected for "from SUB.PACK.AGE import MODULE".
265 265
266 266 Setup "external library" to be imported with "absolute_import"
267 267 feature.
268 268
269 269 $ mkdir -p $TESTTMP/extlibroot/lsub1/lsub2
270 270 $ touch $TESTTMP/extlibroot/__init__.py
271 271 $ touch $TESTTMP/extlibroot/lsub1/__init__.py
272 272 $ touch $TESTTMP/extlibroot/lsub1/lsub2/__init__.py
273 273
274 274 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/called.py <<EOF
275 275 > def func():
276 276 > return "this is extlibroot.lsub1.lsub2.called.func()"
277 277 > EOF
278 278 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/unused.py <<EOF
279 279 > raise Exception("extlibroot.lsub1.lsub2.unused is loaded unintentionally")
280 280 > EOF
281 281 $ cat > $TESTTMP/extlibroot/lsub1/lsub2/used.py <<EOF
282 282 > detail = "this is extlibroot.lsub1.lsub2.used"
283 283 > EOF
284 284
285 285 Setup sub-package of "external library", which causes instantiation of
286 286 demandmod in "recurse down the module chain" code path. Relative
287 287 importing with "absolute_import" feature isn't tested, because "level
288 288 >=1 " doesn't cause instantiation of demandmod.
289 289
290 290 $ mkdir -p $TESTTMP/extlibroot/recursedown/abs
291 291 $ cat > $TESTTMP/extlibroot/recursedown/abs/used.py <<EOF
292 292 > detail = "this is extlibroot.recursedown.abs.used"
293 293 > EOF
294 294 $ cat > $TESTTMP/extlibroot/recursedown/abs/__init__.py <<EOF
295 295 > from __future__ import absolute_import
296 296 > from extlibroot.recursedown.abs.used import detail
297 297 > EOF
298 298
299 299 $ mkdir -p $TESTTMP/extlibroot/recursedown/legacy
300 300 $ cat > $TESTTMP/extlibroot/recursedown/legacy/used.py <<EOF
301 301 > detail = "this is extlibroot.recursedown.legacy.used"
302 302 > EOF
303 303 $ cat > $TESTTMP/extlibroot/recursedown/legacy/__init__.py <<EOF
304 304 > # legacy style (level == -1) import
305 305 > from extlibroot.recursedown.legacy.used import detail
306 306 > EOF
307 307
308 308 $ cat > $TESTTMP/extlibroot/recursedown/__init__.py <<EOF
309 309 > from __future__ import absolute_import
310 310 > from extlibroot.recursedown.abs import detail as absdetail
311 311 > from .legacy import detail as legacydetail
312 312 > EOF
313 313
314 314 Setup extension local modules to be imported with "absolute_import"
315 315 feature.
316 316
317 317 $ mkdir -p $TESTTMP/absextroot/xsub1/xsub2
318 318 $ touch $TESTTMP/absextroot/xsub1/__init__.py
319 319 $ touch $TESTTMP/absextroot/xsub1/xsub2/__init__.py
320 320
321 321 $ cat > $TESTTMP/absextroot/xsub1/xsub2/called.py <<EOF
322 322 > def func():
323 323 > return "this is absextroot.xsub1.xsub2.called.func()"
324 324 > EOF
325 325 $ cat > $TESTTMP/absextroot/xsub1/xsub2/unused.py <<EOF
326 326 > raise Exception("absextroot.xsub1.xsub2.unused is loaded unintentionally")
327 327 > EOF
328 328 $ cat > $TESTTMP/absextroot/xsub1/xsub2/used.py <<EOF
329 329 > detail = "this is absextroot.xsub1.xsub2.used"
330 330 > EOF
331 331
332 332 Setup extension local modules to examine whether demand importing
333 333 works as expected in "level > 1" case.
334 334
335 335 $ cat > $TESTTMP/absextroot/relimportee.py <<EOF
336 336 > detail = "this is absextroot.relimportee"
337 337 > EOF
338 338 $ cat > $TESTTMP/absextroot/xsub1/xsub2/relimporter.py <<EOF
339 339 > from __future__ import absolute_import
340 340 > from ... import relimportee
341 341 > detail = "this relimporter imports %r" % (relimportee.detail)
342 342 > EOF
343 343
344 344 Setup modules, which actually import extension local modules at
345 345 runtime.
346 346
347 347 $ cat > $TESTTMP/absextroot/absolute.py << EOF
348 348 > from __future__ import absolute_import
349 349 >
350 350 > # import extension local modules absolutely (level = 0)
351 351 > from absextroot.xsub1.xsub2 import used, unused
352 352 > from absextroot.xsub1.xsub2.called import func
353 353 >
354 354 > def getresult():
355 355 > result = []
356 356 > result.append(used.detail)
357 357 > result.append(func())
358 358 > return result
359 359 > EOF
360 360
361 361 $ cat > $TESTTMP/absextroot/relative.py << EOF
362 362 > from __future__ import absolute_import
363 363 >
364 364 > # import extension local modules relatively (level == 1)
365 365 > from .xsub1.xsub2 import used, unused
366 366 > from .xsub1.xsub2.called import func
367 367 >
368 368 > # import a module, which implies "importing with level > 1"
369 369 > from .xsub1.xsub2 import relimporter
370 370 >
371 371 > def getresult():
372 372 > result = []
373 373 > result.append(used.detail)
374 374 > result.append(func())
375 375 > result.append(relimporter.detail)
376 376 > return result
377 377 > EOF
378 378
379 379 Setup main procedure of extension.
380 380
381 381 $ cat > $TESTTMP/absextroot/__init__.py <<EOF
382 382 > from __future__ import absolute_import
383 383 > from mercurial import cmdutil
384 384 > cmdtable = {}
385 385 > command = cmdutil.command(cmdtable)
386 386 >
387 387 > # "absolute" and "relative" shouldn't be imported before actual
388 388 > # command execution, because (1) they import same modules, and (2)
389 389 > # preceding import (= instantiate "demandmod" object instead of
390 390 > # real "module" object) might hide problem of succeeding import.
391 391 >
392 392 > @command('showabsolute', [], norepo=True)
393 393 > def showabsolute(ui, *args, **opts):
394 394 > from absextroot import absolute
395 395 > ui.write('ABS: %s\n' % '\nABS: '.join(absolute.getresult()))
396 396 >
397 397 > @command('showrelative', [], norepo=True)
398 398 > def showrelative(ui, *args, **opts):
399 399 > from . import relative
400 400 > ui.write('REL: %s\n' % '\nREL: '.join(relative.getresult()))
401 401 >
402 402 > # import modules from external library
403 403 > from extlibroot.lsub1.lsub2 import used as lused, unused as lunused
404 404 > from extlibroot.lsub1.lsub2.called import func as lfunc
405 405 > from extlibroot.recursedown import absdetail, legacydetail
406 406 >
407 407 > def uisetup(ui):
408 408 > result = []
409 409 > result.append(lused.detail)
410 410 > result.append(lfunc())
411 411 > result.append(absdetail)
412 412 > result.append(legacydetail)
413 413 > ui.write('LIB: %s\n' % '\nLIB: '.join(result))
414 414 > EOF
415 415
416 416 Examine module importing.
417 417
418 418 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.absextroot=$TESTTMP/absextroot showabsolute)
419 419 LIB: this is extlibroot.lsub1.lsub2.used
420 420 LIB: this is extlibroot.lsub1.lsub2.called.func()
421 421 LIB: this is extlibroot.recursedown.abs.used
422 422 LIB: this is extlibroot.recursedown.legacy.used
423 423 ABS: this is absextroot.xsub1.xsub2.used
424 424 ABS: this is absextroot.xsub1.xsub2.called.func()
425 425
426 426 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.absextroot=$TESTTMP/absextroot showrelative)
427 427 LIB: this is extlibroot.lsub1.lsub2.used
428 428 LIB: this is extlibroot.lsub1.lsub2.called.func()
429 429 LIB: this is extlibroot.recursedown.abs.used
430 430 LIB: this is extlibroot.recursedown.legacy.used
431 431 REL: this is absextroot.xsub1.xsub2.used
432 432 REL: this is absextroot.xsub1.xsub2.called.func()
433 433 REL: this relimporter imports 'this is absextroot.relimportee'
434 434
435 435 Examine whether sub-module is imported relatively as expected.
436 436
437 437 See also issue5208 for detail about example case on Python 3.x.
438 438
439 439 $ f -q $TESTTMP/extlibroot/lsub1/lsub2/notexist.py
440 440 $TESTTMP/extlibroot/lsub1/lsub2/notexist.py: file not found
441 441
442 442 $ cat > $TESTTMP/notexist.py <<EOF
443 443 > text = 'notexist.py at root is loaded unintentionally\n'
444 444 > EOF
445 445
446 446 $ cat > $TESTTMP/checkrelativity.py <<EOF
447 447 > from mercurial import cmdutil
448 448 > cmdtable = {}
449 449 > command = cmdutil.command(cmdtable)
450 450 >
451 451 > # demand import avoids failure of importing notexist here
452 452 > import extlibroot.lsub1.lsub2.notexist
453 453 >
454 454 > @command('checkrelativity', [], norepo=True)
455 455 > def checkrelativity(ui, *args, **opts):
456 456 > try:
457 457 > ui.write(extlibroot.lsub1.lsub2.notexist.text)
458 458 > return 1 # unintentional success
459 459 > except ImportError:
460 460 > pass # intentional failure
461 461 > EOF
462 462
463 463 $ (PYTHONPATH=${PYTHONPATH}${PATHSEP}${TESTTMP}; hg --config extensions.checkrelativity=$TESTTMP/checkrelativity.py checkrelativity)
464 464
465 465 #endif
466 466
467 467 $ cd ..
468 468
469 469 hide outer repo
470 470 $ hg init
471 471
472 472 $ cat > empty.py <<EOF
473 473 > '''empty cmdtable
474 474 > '''
475 475 > cmdtable = {}
476 476 > EOF
477 477 $ emptypath=`pwd`/empty.py
478 478 $ echo "empty = $emptypath" >> $HGRCPATH
479 479 $ hg help empty
480 480 empty extension - empty cmdtable
481 481
482 482 no commands defined
483 483
484 484
485 485 $ echo 'empty = !' >> $HGRCPATH
486 486
487 487 $ cat > debugextension.py <<EOF
488 488 > '''only debugcommands
489 489 > '''
490 490 > from mercurial import cmdutil
491 491 > cmdtable = {}
492 492 > command = cmdutil.command(cmdtable)
493 493 > @command('debugfoobar', [], 'hg debugfoobar')
494 494 > def debugfoobar(ui, repo, *args, **opts):
495 495 > "yet another debug command"
496 496 > pass
497 497 > @command('foo', [], 'hg foo')
498 498 > def foo(ui, repo, *args, **opts):
499 499 > """yet another foo command
500 500 > This command has been DEPRECATED since forever.
501 501 > """
502 502 > pass
503 503 > EOF
504 504 $ debugpath=`pwd`/debugextension.py
505 505 $ echo "debugextension = $debugpath" >> $HGRCPATH
506 506
507 507 $ hg help debugextension
508 508 hg debugextensions
509 509
510 510 show information about active extensions
511 511
512 512 options:
513 513
514 514 (some details hidden, use --verbose to show complete help)
515 515
516 516
517 517 $ hg --verbose help debugextension
518 518 hg debugextensions
519 519
520 520 show information about active extensions
521 521
522 522 options:
523 523
524 524 -T --template TEMPLATE display with template (EXPERIMENTAL)
525 525
526 526 global options ([+] can be repeated):
527 527
528 528 -R --repository REPO repository root directory or name of overlay bundle
529 529 file
530 530 --cwd DIR change working directory
531 531 -y --noninteractive do not prompt, automatically pick the first choice for
532 532 all prompts
533 533 -q --quiet suppress output
534 534 -v --verbose enable additional output
535 535 --config CONFIG [+] set/override config option (use 'section.name=value')
536 536 --debug enable debugging output
537 537 --debugger start debugger
538 538 --encoding ENCODE set the charset encoding (default: ascii)
539 539 --encodingmode MODE set the charset encoding mode (default: strict)
540 540 --traceback always print a traceback on exception
541 541 --time time how long the command takes
542 542 --profile print command execution profile
543 543 --version output version information and exit
544 544 -h --help display help and exit
545 545 --hidden consider hidden changesets
546 --pager TYPE when to paginate (boolean, always, auto, or never)
547 (default: auto)
546 548
547 549
548 550
549 551
550 552
551 553
552 554 $ hg --debug help debugextension
553 555 hg debugextensions
554 556
555 557 show information about active extensions
556 558
557 559 options:
558 560
559 561 -T --template TEMPLATE display with template (EXPERIMENTAL)
560 562
561 563 global options ([+] can be repeated):
562 564
563 565 -R --repository REPO repository root directory or name of overlay bundle
564 566 file
565 567 --cwd DIR change working directory
566 568 -y --noninteractive do not prompt, automatically pick the first choice for
567 569 all prompts
568 570 -q --quiet suppress output
569 571 -v --verbose enable additional output
570 572 --config CONFIG [+] set/override config option (use 'section.name=value')
571 573 --debug enable debugging output
572 574 --debugger start debugger
573 575 --encoding ENCODE set the charset encoding (default: ascii)
574 576 --encodingmode MODE set the charset encoding mode (default: strict)
575 577 --traceback always print a traceback on exception
576 578 --time time how long the command takes
577 579 --profile print command execution profile
578 580 --version output version information and exit
579 581 -h --help display help and exit
580 582 --hidden consider hidden changesets
583 --pager TYPE when to paginate (boolean, always, auto, or never)
584 (default: auto)
581 585
582 586
583 587
584 588
585 589
586 590 $ echo 'debugextension = !' >> $HGRCPATH
587 591
588 592 Asking for help about a deprecated extension should do something useful:
589 593
590 594 $ hg help glog
591 595 'glog' is provided by the following extension:
592 596
593 597 graphlog command to view revision graphs from a shell (DEPRECATED)
594 598
595 599 (use 'hg help extensions' for information on enabling extensions)
596 600
597 601 Extension module help vs command help:
598 602
599 603 $ echo 'extdiff =' >> $HGRCPATH
600 604 $ hg help extdiff
601 605 hg extdiff [OPT]... [FILE]...
602 606
603 607 use external program to diff repository (or selected files)
604 608
605 609 Show differences between revisions for the specified files, using an
606 610 external program. The default program used is diff, with default options
607 611 "-Npru".
608 612
609 613 To select a different program, use the -p/--program option. The program
610 614 will be passed the names of two directories to compare. To pass additional
611 615 options to the program, use -o/--option. These will be passed before the
612 616 names of the directories to compare.
613 617
614 618 When two revision arguments are given, then changes are shown between
615 619 those revisions. If only one revision is specified then that revision is
616 620 compared to the working directory, and, when no revisions are specified,
617 621 the working directory files are compared to its parent.
618 622
619 623 (use 'hg help -e extdiff' to show help for the extdiff extension)
620 624
621 625 options ([+] can be repeated):
622 626
623 627 -p --program CMD comparison program to run
624 628 -o --option OPT [+] pass option to comparison program
625 629 -r --rev REV [+] revision
626 630 -c --change REV change made by revision
627 631 --patch compare patches for two revisions
628 632 -I --include PATTERN [+] include names matching the given patterns
629 633 -X --exclude PATTERN [+] exclude names matching the given patterns
630 634 -S --subrepos recurse into subrepositories
631 635
632 636 (some details hidden, use --verbose to show complete help)
633 637
634 638
635 639
636 640
637 641
638 642
639 643
640 644
641 645
642 646
643 647 $ hg help --extension extdiff
644 648 extdiff extension - command to allow external programs to compare revisions
645 649
646 650 The extdiff Mercurial extension allows you to use external programs to compare
647 651 revisions, or revision with working directory. The external diff programs are
648 652 called with a configurable set of options and two non-option arguments: paths
649 653 to directories containing snapshots of files to compare.
650 654
651 655 The extdiff extension also allows you to configure new diff commands, so you
652 656 do not need to type 'hg extdiff -p kdiff3' always.
653 657
654 658 [extdiff]
655 659 # add new command that runs GNU diff(1) in 'context diff' mode
656 660 cdiff = gdiff -Nprc5
657 661 ## or the old way:
658 662 #cmd.cdiff = gdiff
659 663 #opts.cdiff = -Nprc5
660 664
661 665 # add new command called meld, runs meld (no need to name twice). If
662 666 # the meld executable is not available, the meld tool in [merge-tools]
663 667 # will be used, if available
664 668 meld =
665 669
666 670 # add new command called vimdiff, runs gvimdiff with DirDiff plugin
667 671 # (see http://www.vim.org/scripts/script.php?script_id=102) Non
668 672 # English user, be sure to put "let g:DirDiffDynamicDiffText = 1" in
669 673 # your .vimrc
670 674 vimdiff = gvim -f "+next" \
671 675 "+execute 'DirDiff' fnameescape(argv(0)) fnameescape(argv(1))"
672 676
673 677 Tool arguments can include variables that are expanded at runtime:
674 678
675 679 $parent1, $plabel1 - filename, descriptive label of first parent
676 680 $child, $clabel - filename, descriptive label of child revision
677 681 $parent2, $plabel2 - filename, descriptive label of second parent
678 682 $root - repository root
679 683 $parent is an alias for $parent1.
680 684
681 685 The extdiff extension will look in your [diff-tools] and [merge-tools]
682 686 sections for diff tool arguments, when none are specified in [extdiff].
683 687
684 688 [extdiff]
685 689 kdiff3 =
686 690
687 691 [diff-tools]
688 692 kdiff3.diffargs=--L1 '$plabel1' --L2 '$clabel' $parent $child
689 693
690 694 You can use -I/-X and list of file or directory names like normal 'hg diff'
691 695 command. The extdiff extension makes snapshots of only needed files, so
692 696 running the external diff program will actually be pretty fast (at least
693 697 faster than having to compare the entire tree).
694 698
695 699 list of commands:
696 700
697 701 extdiff use external program to diff repository (or selected files)
698 702
699 703 (use 'hg help -v -e extdiff' to show built-in aliases and global options)
700 704
701 705
702 706
703 707
704 708
705 709
706 710
707 711
708 712
709 713
710 714
711 715
712 716
713 717
714 718
715 719
716 720 $ echo 'extdiff = !' >> $HGRCPATH
717 721
718 722 Test help topic with same name as extension
719 723
720 724 $ cat > multirevs.py <<EOF
721 725 > from mercurial import cmdutil, commands
722 726 > cmdtable = {}
723 727 > command = cmdutil.command(cmdtable)
724 728 > """multirevs extension
725 729 > Big multi-line module docstring."""
726 730 > @command('multirevs', [], 'ARG', norepo=True)
727 731 > def multirevs(ui, repo, arg, *args, **opts):
728 732 > """multirevs command"""
729 733 > pass
730 734 > EOF
731 735 $ echo "multirevs = multirevs.py" >> $HGRCPATH
732 736
733 737 $ hg help multirevs | tail
734 738 bookmark (this works because the last revision of the revset is used):
735 739
736 740 hg update :@
737 741
738 742 - Show diff between tags 1.3 and 1.5 (this works because the first and the
739 743 last revisions of the revset are used):
740 744
741 745 hg diff -r 1.3::1.5
742 746
743 747 use 'hg help -c multirevs' to see help for the multirevs command
744 748
745 749
746 750
747 751
748 752
749 753
750 754 $ hg help -c multirevs
751 755 hg multirevs ARG
752 756
753 757 multirevs command
754 758
755 759 (some details hidden, use --verbose to show complete help)
756 760
757 761
758 762
759 763 $ hg multirevs
760 764 hg multirevs: invalid arguments
761 765 hg multirevs ARG
762 766
763 767 multirevs command
764 768
765 769 (use 'hg multirevs -h' to show more help)
766 770 [255]
767 771
768 772
769 773
770 774 $ echo "multirevs = !" >> $HGRCPATH
771 775
772 776 Issue811: Problem loading extensions twice (by site and by user)
773 777
774 778 $ cat <<EOF >> $HGRCPATH
775 779 > mq =
776 780 > strip =
777 781 > hgext.mq =
778 782 > hgext/mq =
779 783 > EOF
780 784
781 785 Show extensions:
782 786 (note that mq force load strip, also checking it's not loaded twice)
783 787
784 788 $ hg debugextensions
785 789 mq
786 790 strip
787 791
788 792 For extensions, which name matches one of its commands, help
789 793 message should ask '-v -e' to get list of built-in aliases
790 794 along with extension help itself
791 795
792 796 $ mkdir $TESTTMP/d
793 797 $ cat > $TESTTMP/d/dodo.py <<EOF
794 798 > """
795 799 > This is an awesome 'dodo' extension. It does nothing and
796 800 > writes 'Foo foo'
797 801 > """
798 802 > from mercurial import cmdutil, commands
799 803 > cmdtable = {}
800 804 > command = cmdutil.command(cmdtable)
801 805 > @command('dodo', [], 'hg dodo')
802 806 > def dodo(ui, *args, **kwargs):
803 807 > """Does nothing"""
804 808 > ui.write("I do nothing. Yay\\n")
805 809 > @command('foofoo', [], 'hg foofoo')
806 810 > def foofoo(ui, *args, **kwargs):
807 811 > """Writes 'Foo foo'"""
808 812 > ui.write("Foo foo\\n")
809 813 > EOF
810 814 $ dodopath=$TESTTMP/d/dodo.py
811 815
812 816 $ echo "dodo = $dodopath" >> $HGRCPATH
813 817
814 818 Make sure that user is asked to enter '-v -e' to get list of built-in aliases
815 819 $ hg help -e dodo
816 820 dodo extension -
817 821
818 822 This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo'
819 823
820 824 list of commands:
821 825
822 826 dodo Does nothing
823 827 foofoo Writes 'Foo foo'
824 828
825 829 (use 'hg help -v -e dodo' to show built-in aliases and global options)
826 830
827 831 Make sure that '-v -e' prints list of built-in aliases along with
828 832 extension help itself
829 833 $ hg help -v -e dodo
830 834 dodo extension -
831 835
832 836 This is an awesome 'dodo' extension. It does nothing and writes 'Foo foo'
833 837
834 838 list of commands:
835 839
836 840 dodo Does nothing
837 841 foofoo Writes 'Foo foo'
838 842
839 843 global options ([+] can be repeated):
840 844
841 845 -R --repository REPO repository root directory or name of overlay bundle
842 846 file
843 847 --cwd DIR change working directory
844 848 -y --noninteractive do not prompt, automatically pick the first choice for
845 849 all prompts
846 850 -q --quiet suppress output
847 851 -v --verbose enable additional output
848 852 --config CONFIG [+] set/override config option (use 'section.name=value')
849 853 --debug enable debugging output
850 854 --debugger start debugger
851 855 --encoding ENCODE set the charset encoding (default: ascii)
852 856 --encodingmode MODE set the charset encoding mode (default: strict)
853 857 --traceback always print a traceback on exception
854 858 --time time how long the command takes
855 859 --profile print command execution profile
856 860 --version output version information and exit
857 861 -h --help display help and exit
858 862 --hidden consider hidden changesets
863 --pager TYPE when to paginate (boolean, always, auto, or never)
864 (default: auto)
859 865
860 866 Make sure that single '-v' option shows help and built-ins only for 'dodo' command
861 867 $ hg help -v dodo
862 868 hg dodo
863 869
864 870 Does nothing
865 871
866 872 (use 'hg help -e dodo' to show help for the dodo extension)
867 873
868 874 options:
869 875
870 876 --mq operate on patch repository
871 877
872 878 global options ([+] can be repeated):
873 879
874 880 -R --repository REPO repository root directory or name of overlay bundle
875 881 file
876 882 --cwd DIR change working directory
877 883 -y --noninteractive do not prompt, automatically pick the first choice for
878 884 all prompts
879 885 -q --quiet suppress output
880 886 -v --verbose enable additional output
881 887 --config CONFIG [+] set/override config option (use 'section.name=value')
882 888 --debug enable debugging output
883 889 --debugger start debugger
884 890 --encoding ENCODE set the charset encoding (default: ascii)
885 891 --encodingmode MODE set the charset encoding mode (default: strict)
886 892 --traceback always print a traceback on exception
887 893 --time time how long the command takes
888 894 --profile print command execution profile
889 895 --version output version information and exit
890 896 -h --help display help and exit
891 897 --hidden consider hidden changesets
898 --pager TYPE when to paginate (boolean, always, auto, or never)
899 (default: auto)
892 900
893 901 In case when extension name doesn't match any of its commands,
894 902 help message should ask for '-v' to get list of built-in aliases
895 903 along with extension help
896 904 $ cat > $TESTTMP/d/dudu.py <<EOF
897 905 > """
898 906 > This is an awesome 'dudu' extension. It does something and
899 907 > also writes 'Beep beep'
900 908 > """
901 909 > from mercurial import cmdutil, commands
902 910 > cmdtable = {}
903 911 > command = cmdutil.command(cmdtable)
904 912 > @command('something', [], 'hg something')
905 913 > def something(ui, *args, **kwargs):
906 914 > """Does something"""
907 915 > ui.write("I do something. Yaaay\\n")
908 916 > @command('beep', [], 'hg beep')
909 917 > def beep(ui, *args, **kwargs):
910 918 > """Writes 'Beep beep'"""
911 919 > ui.write("Beep beep\\n")
912 920 > EOF
913 921 $ dudupath=$TESTTMP/d/dudu.py
914 922
915 923 $ echo "dudu = $dudupath" >> $HGRCPATH
916 924
917 925 $ hg help -e dudu
918 926 dudu extension -
919 927
920 928 This is an awesome 'dudu' extension. It does something and also writes 'Beep
921 929 beep'
922 930
923 931 list of commands:
924 932
925 933 beep Writes 'Beep beep'
926 934 something Does something
927 935
928 936 (use 'hg help -v dudu' to show built-in aliases and global options)
929 937
930 938 In case when extension name doesn't match any of its commands,
931 939 help options '-v' and '-v -e' should be equivalent
932 940 $ hg help -v dudu
933 941 dudu extension -
934 942
935 943 This is an awesome 'dudu' extension. It does something and also writes 'Beep
936 944 beep'
937 945
938 946 list of commands:
939 947
940 948 beep Writes 'Beep beep'
941 949 something Does something
942 950
943 951 global options ([+] can be repeated):
944 952
945 953 -R --repository REPO repository root directory or name of overlay bundle
946 954 file
947 955 --cwd DIR change working directory
948 956 -y --noninteractive do not prompt, automatically pick the first choice for
949 957 all prompts
950 958 -q --quiet suppress output
951 959 -v --verbose enable additional output
952 960 --config CONFIG [+] set/override config option (use 'section.name=value')
953 961 --debug enable debugging output
954 962 --debugger start debugger
955 963 --encoding ENCODE set the charset encoding (default: ascii)
956 964 --encodingmode MODE set the charset encoding mode (default: strict)
957 965 --traceback always print a traceback on exception
958 966 --time time how long the command takes
959 967 --profile print command execution profile
960 968 --version output version information and exit
961 969 -h --help display help and exit
962 970 --hidden consider hidden changesets
971 --pager TYPE when to paginate (boolean, always, auto, or never)
972 (default: auto)
963 973
964 974 $ hg help -v -e dudu
965 975 dudu extension -
966 976
967 977 This is an awesome 'dudu' extension. It does something and also writes 'Beep
968 978 beep'
969 979
970 980 list of commands:
971 981
972 982 beep Writes 'Beep beep'
973 983 something Does something
974 984
975 985 global options ([+] can be repeated):
976 986
977 987 -R --repository REPO repository root directory or name of overlay bundle
978 988 file
979 989 --cwd DIR change working directory
980 990 -y --noninteractive do not prompt, automatically pick the first choice for
981 991 all prompts
982 992 -q --quiet suppress output
983 993 -v --verbose enable additional output
984 994 --config CONFIG [+] set/override config option (use 'section.name=value')
985 995 --debug enable debugging output
986 996 --debugger start debugger
987 997 --encoding ENCODE set the charset encoding (default: ascii)
988 998 --encodingmode MODE set the charset encoding mode (default: strict)
989 999 --traceback always print a traceback on exception
990 1000 --time time how long the command takes
991 1001 --profile print command execution profile
992 1002 --version output version information and exit
993 1003 -h --help display help and exit
994 1004 --hidden consider hidden changesets
1005 --pager TYPE when to paginate (boolean, always, auto, or never)
1006 (default: auto)
995 1007
996 1008 Disabled extension commands:
997 1009
998 1010 $ ORGHGRCPATH=$HGRCPATH
999 1011 $ HGRCPATH=
1000 1012 $ export HGRCPATH
1001 1013 $ hg help email
1002 1014 'email' is provided by the following extension:
1003 1015
1004 1016 patchbomb command to send changesets as (a series of) patch emails
1005 1017
1006 1018 (use 'hg help extensions' for information on enabling extensions)
1007 1019
1008 1020
1009 1021 $ hg qdel
1010 1022 hg: unknown command 'qdel'
1011 1023 'qdelete' is provided by the following extension:
1012 1024
1013 1025 mq manage a stack of patches
1014 1026
1015 1027 (use 'hg help extensions' for information on enabling extensions)
1016 1028 [255]
1017 1029
1018 1030
1019 1031 $ hg churn
1020 1032 hg: unknown command 'churn'
1021 1033 'churn' is provided by the following extension:
1022 1034
1023 1035 churn command to display statistics about repository history
1024 1036
1025 1037 (use 'hg help extensions' for information on enabling extensions)
1026 1038 [255]
1027 1039
1028 1040
1029 1041
1030 1042 Disabled extensions:
1031 1043
1032 1044 $ hg help churn
1033 1045 churn extension - command to display statistics about repository history
1034 1046
1035 1047 (use 'hg help extensions' for information on enabling extensions)
1036 1048
1037 1049 $ hg help patchbomb
1038 1050 patchbomb extension - command to send changesets as (a series of) patch emails
1039 1051
1040 1052 The series is started off with a "[PATCH 0 of N]" introduction, which
1041 1053 describes the series as a whole.
1042 1054
1043 1055 Each patch email has a Subject line of "[PATCH M of N] ...", using the first
1044 1056 line of the changeset description as the subject text. The message contains
1045 1057 two or three body parts:
1046 1058
1047 1059 - The changeset description.
1048 1060 - [Optional] The result of running diffstat on the patch.
1049 1061 - The patch itself, as generated by 'hg export'.
1050 1062
1051 1063 Each message refers to the first in the series using the In-Reply-To and
1052 1064 References headers, so they will show up as a sequence in threaded mail and
1053 1065 news readers, and in mail archives.
1054 1066
1055 1067 To configure other defaults, add a section like this to your configuration
1056 1068 file:
1057 1069
1058 1070 [email]
1059 1071 from = My Name <my@email>
1060 1072 to = recipient1, recipient2, ...
1061 1073 cc = cc1, cc2, ...
1062 1074 bcc = bcc1, bcc2, ...
1063 1075 reply-to = address1, address2, ...
1064 1076
1065 1077 Use "[patchbomb]" as configuration section name if you need to override global
1066 1078 "[email]" address settings.
1067 1079
1068 1080 Then you can use the 'hg email' command to mail a series of changesets as a
1069 1081 patchbomb.
1070 1082
1071 1083 You can also either configure the method option in the email section to be a
1072 1084 sendmail compatible mailer or fill out the [smtp] section so that the
1073 1085 patchbomb extension can automatically send patchbombs directly from the
1074 1086 commandline. See the [email] and [smtp] sections in hgrc(5) for details.
1075 1087
1076 1088 By default, 'hg email' will prompt for a "To" or "CC" header if you do not
1077 1089 supply one via configuration or the command line. You can override this to
1078 1090 never prompt by configuring an empty value:
1079 1091
1080 1092 [email]
1081 1093 cc =
1082 1094
1083 1095 You can control the default inclusion of an introduction message with the
1084 1096 "patchbomb.intro" configuration option. The configuration is always
1085 1097 overwritten by command line flags like --intro and --desc:
1086 1098
1087 1099 [patchbomb]
1088 1100 intro=auto # include introduction message if more than 1 patch (default)
1089 1101 intro=never # never include an introduction message
1090 1102 intro=always # always include an introduction message
1091 1103
1092 1104 You can set patchbomb to always ask for confirmation by setting
1093 1105 "patchbomb.confirm" to true.
1094 1106
1095 1107 (use 'hg help extensions' for information on enabling extensions)
1096 1108
1097 1109
1098 1110 Broken disabled extension and command:
1099 1111
1100 1112 $ mkdir hgext
1101 1113 $ echo > hgext/__init__.py
1102 1114 $ cat > hgext/broken.py <<EOF
1103 1115 > "broken extension'
1104 1116 > EOF
1105 1117 $ cat > path.py <<EOF
1106 1118 > import os, sys
1107 1119 > sys.path.insert(0, os.environ['HGEXTPATH'])
1108 1120 > EOF
1109 1121 $ HGEXTPATH=`pwd`
1110 1122 $ export HGEXTPATH
1111 1123
1112 1124 $ hg --config extensions.path=./path.py help broken
1113 1125 broken extension - (no help text available)
1114 1126
1115 1127 (use 'hg help extensions' for information on enabling extensions)
1116 1128
1117 1129
1118 1130 $ cat > hgext/forest.py <<EOF
1119 1131 > cmdtable = None
1120 1132 > EOF
1121 1133 $ hg --config extensions.path=./path.py help foo > /dev/null
1122 1134 warning: error finding commands in $TESTTMP/hgext/forest.py (glob)
1123 1135 abort: no such help topic: foo
1124 1136 (try 'hg help --keyword foo')
1125 1137 [255]
1126 1138
1127 1139 $ cat > throw.py <<EOF
1128 1140 > from mercurial import cmdutil, commands, util
1129 1141 > cmdtable = {}
1130 1142 > command = cmdutil.command(cmdtable)
1131 1143 > class Bogon(Exception): pass
1132 1144 > @command('throw', [], 'hg throw', norepo=True)
1133 1145 > def throw(ui, **opts):
1134 1146 > """throws an exception"""
1135 1147 > raise Bogon()
1136 1148 > EOF
1137 1149
1138 1150 No declared supported version, extension complains:
1139 1151 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1140 1152 ** Unknown exception encountered with possibly-broken third-party extension throw
1141 1153 ** which supports versions unknown of Mercurial.
1142 1154 ** Please disable throw and try your action again.
1143 1155 ** If that fixes the bug please report it to the extension author.
1144 1156 ** Python * (glob)
1145 1157 ** Mercurial Distributed SCM * (glob)
1146 1158 ** Extensions loaded: throw
1147 1159
1148 1160 empty declaration of supported version, extension complains:
1149 1161 $ echo "testedwith = ''" >> throw.py
1150 1162 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1151 1163 ** Unknown exception encountered with possibly-broken third-party extension throw
1152 1164 ** which supports versions unknown of Mercurial.
1153 1165 ** Please disable throw and try your action again.
1154 1166 ** If that fixes the bug please report it to the extension author.
1155 1167 ** Python * (glob)
1156 1168 ** Mercurial Distributed SCM (*) (glob)
1157 1169 ** Extensions loaded: throw
1158 1170
1159 1171 If the extension specifies a buglink, show that:
1160 1172 $ echo 'buglink = "http://example.com/bts"' >> throw.py
1161 1173 $ rm -f throw.pyc throw.pyo
1162 1174 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1163 1175 ** Unknown exception encountered with possibly-broken third-party extension throw
1164 1176 ** which supports versions unknown of Mercurial.
1165 1177 ** Please disable throw and try your action again.
1166 1178 ** If that fixes the bug please report it to http://example.com/bts
1167 1179 ** Python * (glob)
1168 1180 ** Mercurial Distributed SCM (*) (glob)
1169 1181 ** Extensions loaded: throw
1170 1182
1171 1183 If the extensions declare outdated versions, accuse the older extension first:
1172 1184 $ echo "from mercurial import util" >> older.py
1173 1185 $ echo "util.version = lambda:'2.2'" >> older.py
1174 1186 $ echo "testedwith = '1.9.3'" >> older.py
1175 1187 $ echo "testedwith = '2.1.1'" >> throw.py
1176 1188 $ rm -f throw.pyc throw.pyo
1177 1189 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1178 1190 > throw 2>&1 | egrep '^\*\*'
1179 1191 ** Unknown exception encountered with possibly-broken third-party extension older
1180 1192 ** which supports versions 1.9 of Mercurial.
1181 1193 ** Please disable older and try your action again.
1182 1194 ** If that fixes the bug please report it to the extension author.
1183 1195 ** Python * (glob)
1184 1196 ** Mercurial Distributed SCM (version 2.2)
1185 1197 ** Extensions loaded: throw, older
1186 1198
1187 1199 One extension only tested with older, one only with newer versions:
1188 1200 $ echo "util.version = lambda:'2.1'" >> older.py
1189 1201 $ rm -f older.pyc older.pyo
1190 1202 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1191 1203 > throw 2>&1 | egrep '^\*\*'
1192 1204 ** Unknown exception encountered with possibly-broken third-party extension older
1193 1205 ** which supports versions 1.9 of Mercurial.
1194 1206 ** Please disable older and try your action again.
1195 1207 ** If that fixes the bug please report it to the extension author.
1196 1208 ** Python * (glob)
1197 1209 ** Mercurial Distributed SCM (version 2.1)
1198 1210 ** Extensions loaded: throw, older
1199 1211
1200 1212 Older extension is tested with current version, the other only with newer:
1201 1213 $ echo "util.version = lambda:'1.9.3'" >> older.py
1202 1214 $ rm -f older.pyc older.pyo
1203 1215 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1204 1216 > throw 2>&1 | egrep '^\*\*'
1205 1217 ** Unknown exception encountered with possibly-broken third-party extension throw
1206 1218 ** which supports versions 2.1 of Mercurial.
1207 1219 ** Please disable throw and try your action again.
1208 1220 ** If that fixes the bug please report it to http://example.com/bts
1209 1221 ** Python * (glob)
1210 1222 ** Mercurial Distributed SCM (version 1.9.3)
1211 1223 ** Extensions loaded: throw, older
1212 1224
1213 1225 Ability to point to a different point
1214 1226 $ hg --config extensions.throw=throw.py --config extensions.older=older.py \
1215 1227 > --config ui.supportcontact='Your Local Goat Lenders' throw 2>&1 | egrep '^\*\*'
1216 1228 ** unknown exception encountered, please report by visiting
1217 1229 ** Your Local Goat Lenders
1218 1230 ** Python * (glob)
1219 1231 ** Mercurial Distributed SCM (*) (glob)
1220 1232 ** Extensions loaded: throw, older
1221 1233
1222 1234 Declare the version as supporting this hg version, show regular bts link:
1223 1235 $ hgver=`hg debuginstall -T '{hgver}'`
1224 1236 $ echo 'testedwith = """'"$hgver"'"""' >> throw.py
1225 1237 $ if [ -z "$hgver" ]; then
1226 1238 > echo "unable to fetch a mercurial version. Make sure __version__ is correct";
1227 1239 > fi
1228 1240 $ rm -f throw.pyc throw.pyo
1229 1241 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1230 1242 ** unknown exception encountered, please report by visiting
1231 1243 ** https://mercurial-scm.org/wiki/BugTracker
1232 1244 ** Python * (glob)
1233 1245 ** Mercurial Distributed SCM (*) (glob)
1234 1246 ** Extensions loaded: throw
1235 1247
1236 1248 Patch version is ignored during compatibility check
1237 1249 $ echo "testedwith = '3.2'" >> throw.py
1238 1250 $ echo "util.version = lambda:'3.2.2'" >> throw.py
1239 1251 $ rm -f throw.pyc throw.pyo
1240 1252 $ hg --config extensions.throw=throw.py throw 2>&1 | egrep '^\*\*'
1241 1253 ** unknown exception encountered, please report by visiting
1242 1254 ** https://mercurial-scm.org/wiki/BugTracker
1243 1255 ** Python * (glob)
1244 1256 ** Mercurial Distributed SCM (*) (glob)
1245 1257 ** Extensions loaded: throw
1246 1258
1247 1259 Test version number support in 'hg version':
1248 1260 $ echo '__version__ = (1, 2, 3)' >> throw.py
1249 1261 $ rm -f throw.pyc throw.pyo
1250 1262 $ hg version -v
1251 1263 Mercurial Distributed SCM (version *) (glob)
1252 1264 (see https://mercurial-scm.org for more information)
1253 1265
1254 1266 Copyright (C) 2005-* Matt Mackall and others (glob)
1255 1267 This is free software; see the source for copying conditions. There is NO
1256 1268 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1257 1269
1258 1270 Enabled extensions:
1259 1271
1260 1272
1261 1273 $ hg version -v --config extensions.throw=throw.py
1262 1274 Mercurial Distributed SCM (version *) (glob)
1263 1275 (see https://mercurial-scm.org for more information)
1264 1276
1265 1277 Copyright (C) 2005-* Matt Mackall and others (glob)
1266 1278 This is free software; see the source for copying conditions. There is NO
1267 1279 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1268 1280
1269 1281 Enabled extensions:
1270 1282
1271 1283 throw external 1.2.3
1272 1284 $ echo 'getversion = lambda: "1.twentythree"' >> throw.py
1273 1285 $ rm -f throw.pyc throw.pyo
1274 1286 $ hg version -v --config extensions.throw=throw.py --config extensions.strip=
1275 1287 Mercurial Distributed SCM (version *) (glob)
1276 1288 (see https://mercurial-scm.org for more information)
1277 1289
1278 1290 Copyright (C) 2005-* Matt Mackall and others (glob)
1279 1291 This is free software; see the source for copying conditions. There is NO
1280 1292 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1281 1293
1282 1294 Enabled extensions:
1283 1295
1284 1296 throw external 1.twentythree
1285 1297 strip internal
1286 1298
1287 1299 $ hg version -q --config extensions.throw=throw.py
1288 1300 Mercurial Distributed SCM (version *) (glob)
1289 1301
1290 1302 Test JSON output of version:
1291 1303
1292 1304 $ hg version -Tjson
1293 1305 [
1294 1306 {
1295 1307 "extensions": [],
1296 1308 "ver": "*" (glob)
1297 1309 }
1298 1310 ]
1299 1311
1300 1312 $ hg version --config extensions.throw=throw.py -Tjson
1301 1313 [
1302 1314 {
1303 1315 "extensions": [{"bundled": false, "name": "throw", "ver": "1.twentythree"}],
1304 1316 "ver": "3.2.2"
1305 1317 }
1306 1318 ]
1307 1319
1308 1320 $ hg version --config extensions.strip= -Tjson
1309 1321 [
1310 1322 {
1311 1323 "extensions": [{"bundled": true, "name": "strip", "ver": null}],
1312 1324 "ver": "*" (glob)
1313 1325 }
1314 1326 ]
1315 1327
1316 1328 Test template output of version:
1317 1329
1318 1330 $ hg version --config extensions.throw=throw.py --config extensions.strip= \
1319 1331 > -T'{extensions % "{name} {pad(ver, 16)} ({if(bundled, "internal", "external")})\n"}'
1320 1332 throw 1.twentythree (external)
1321 1333 strip (internal)
1322 1334
1323 1335 Refuse to load extensions with minimum version requirements
1324 1336
1325 1337 $ cat > minversion1.py << EOF
1326 1338 > from mercurial import util
1327 1339 > util.version = lambda: '3.5.2'
1328 1340 > minimumhgversion = '3.6'
1329 1341 > EOF
1330 1342 $ hg --config extensions.minversion=minversion1.py version
1331 1343 (third party extension minversion requires version 3.6 or newer of Mercurial; disabling)
1332 1344 Mercurial Distributed SCM (version 3.5.2)
1333 1345 (see https://mercurial-scm.org for more information)
1334 1346
1335 1347 Copyright (C) 2005-* Matt Mackall and others (glob)
1336 1348 This is free software; see the source for copying conditions. There is NO
1337 1349 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
1338 1350
1339 1351 $ cat > minversion2.py << EOF
1340 1352 > from mercurial import util
1341 1353 > util.version = lambda: '3.6'
1342 1354 > minimumhgversion = '3.7'
1343 1355 > EOF
1344 1356 $ hg --config extensions.minversion=minversion2.py version 2>&1 | egrep '\(third'
1345 1357 (third party extension minversion requires version 3.7 or newer of Mercurial; disabling)
1346 1358
1347 1359 Can load version that is only off by point release
1348 1360
1349 1361 $ cat > minversion2.py << EOF
1350 1362 > from mercurial import util
1351 1363 > util.version = lambda: '3.6.1'
1352 1364 > minimumhgversion = '3.6'
1353 1365 > EOF
1354 1366 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1355 1367 [1]
1356 1368
1357 1369 Can load minimum version identical to current
1358 1370
1359 1371 $ cat > minversion3.py << EOF
1360 1372 > from mercurial import util
1361 1373 > util.version = lambda: '3.5'
1362 1374 > minimumhgversion = '3.5'
1363 1375 > EOF
1364 1376 $ hg --config extensions.minversion=minversion3.py version 2>&1 | egrep '\(third'
1365 1377 [1]
1366 1378
1367 1379 Restore HGRCPATH
1368 1380
1369 1381 $ HGRCPATH=$ORGHGRCPATH
1370 1382 $ export HGRCPATH
1371 1383
1372 1384 Commands handling multiple repositories at a time should invoke only
1373 1385 "reposetup()" of extensions enabling in the target repository.
1374 1386
1375 1387 $ mkdir reposetup-test
1376 1388 $ cd reposetup-test
1377 1389
1378 1390 $ cat > $TESTTMP/reposetuptest.py <<EOF
1379 1391 > from mercurial import extensions
1380 1392 > def reposetup(ui, repo):
1381 1393 > ui.write('reposetup() for %s\n' % (repo.root))
1382 1394 > ui.flush()
1383 1395 > EOF
1384 1396 $ hg init src
1385 1397 $ echo a > src/a
1386 1398 $ hg -R src commit -Am '#0 at src/a'
1387 1399 adding a
1388 1400 $ echo '[extensions]' >> src/.hg/hgrc
1389 1401 $ echo '# enable extension locally' >> src/.hg/hgrc
1390 1402 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> src/.hg/hgrc
1391 1403 $ hg -R src status
1392 1404 reposetup() for $TESTTMP/reposetup-test/src (glob)
1393 1405
1394 1406 $ hg clone -U src clone-dst1
1395 1407 reposetup() for $TESTTMP/reposetup-test/src (glob)
1396 1408 $ hg init push-dst1
1397 1409 $ hg -q -R src push push-dst1
1398 1410 reposetup() for $TESTTMP/reposetup-test/src (glob)
1399 1411 $ hg init pull-src1
1400 1412 $ hg -q -R pull-src1 pull src
1401 1413 reposetup() for $TESTTMP/reposetup-test/src (glob)
1402 1414
1403 1415 $ cat <<EOF >> $HGRCPATH
1404 1416 > [extensions]
1405 1417 > # disable extension globally and explicitly
1406 1418 > reposetuptest = !
1407 1419 > EOF
1408 1420 $ hg clone -U src clone-dst2
1409 1421 reposetup() for $TESTTMP/reposetup-test/src (glob)
1410 1422 $ hg init push-dst2
1411 1423 $ hg -q -R src push push-dst2
1412 1424 reposetup() for $TESTTMP/reposetup-test/src (glob)
1413 1425 $ hg init pull-src2
1414 1426 $ hg -q -R pull-src2 pull src
1415 1427 reposetup() for $TESTTMP/reposetup-test/src (glob)
1416 1428
1417 1429 $ cat <<EOF >> $HGRCPATH
1418 1430 > [extensions]
1419 1431 > # enable extension globally
1420 1432 > reposetuptest = $TESTTMP/reposetuptest.py
1421 1433 > EOF
1422 1434 $ hg clone -U src clone-dst3
1423 1435 reposetup() for $TESTTMP/reposetup-test/src (glob)
1424 1436 reposetup() for $TESTTMP/reposetup-test/clone-dst3 (glob)
1425 1437 $ hg init push-dst3
1426 1438 reposetup() for $TESTTMP/reposetup-test/push-dst3 (glob)
1427 1439 $ hg -q -R src push push-dst3
1428 1440 reposetup() for $TESTTMP/reposetup-test/src (glob)
1429 1441 reposetup() for $TESTTMP/reposetup-test/push-dst3 (glob)
1430 1442 $ hg init pull-src3
1431 1443 reposetup() for $TESTTMP/reposetup-test/pull-src3 (glob)
1432 1444 $ hg -q -R pull-src3 pull src
1433 1445 reposetup() for $TESTTMP/reposetup-test/pull-src3 (glob)
1434 1446 reposetup() for $TESTTMP/reposetup-test/src (glob)
1435 1447
1436 1448 $ echo '[extensions]' >> src/.hg/hgrc
1437 1449 $ echo '# disable extension locally' >> src/.hg/hgrc
1438 1450 $ echo 'reposetuptest = !' >> src/.hg/hgrc
1439 1451 $ hg clone -U src clone-dst4
1440 1452 reposetup() for $TESTTMP/reposetup-test/clone-dst4 (glob)
1441 1453 $ hg init push-dst4
1442 1454 reposetup() for $TESTTMP/reposetup-test/push-dst4 (glob)
1443 1455 $ hg -q -R src push push-dst4
1444 1456 reposetup() for $TESTTMP/reposetup-test/push-dst4 (glob)
1445 1457 $ hg init pull-src4
1446 1458 reposetup() for $TESTTMP/reposetup-test/pull-src4 (glob)
1447 1459 $ hg -q -R pull-src4 pull src
1448 1460 reposetup() for $TESTTMP/reposetup-test/pull-src4 (glob)
1449 1461
1450 1462 disabling in command line overlays with all configuration
1451 1463 $ hg --config extensions.reposetuptest=! clone -U src clone-dst5
1452 1464 $ hg --config extensions.reposetuptest=! init push-dst5
1453 1465 $ hg --config extensions.reposetuptest=! -q -R src push push-dst5
1454 1466 $ hg --config extensions.reposetuptest=! init pull-src5
1455 1467 $ hg --config extensions.reposetuptest=! -q -R pull-src5 pull src
1456 1468
1457 1469 $ cat <<EOF >> $HGRCPATH
1458 1470 > [extensions]
1459 1471 > # disable extension globally and explicitly
1460 1472 > reposetuptest = !
1461 1473 > EOF
1462 1474 $ hg init parent
1463 1475 $ hg init parent/sub1
1464 1476 $ echo 1 > parent/sub1/1
1465 1477 $ hg -R parent/sub1 commit -Am '#0 at parent/sub1'
1466 1478 adding 1
1467 1479 $ hg init parent/sub2
1468 1480 $ hg init parent/sub2/sub21
1469 1481 $ echo 21 > parent/sub2/sub21/21
1470 1482 $ hg -R parent/sub2/sub21 commit -Am '#0 at parent/sub2/sub21'
1471 1483 adding 21
1472 1484 $ cat > parent/sub2/.hgsub <<EOF
1473 1485 > sub21 = sub21
1474 1486 > EOF
1475 1487 $ hg -R parent/sub2 commit -Am '#0 at parent/sub2'
1476 1488 adding .hgsub
1477 1489 $ hg init parent/sub3
1478 1490 $ echo 3 > parent/sub3/3
1479 1491 $ hg -R parent/sub3 commit -Am '#0 at parent/sub3'
1480 1492 adding 3
1481 1493 $ cat > parent/.hgsub <<EOF
1482 1494 > sub1 = sub1
1483 1495 > sub2 = sub2
1484 1496 > sub3 = sub3
1485 1497 > EOF
1486 1498 $ hg -R parent commit -Am '#0 at parent'
1487 1499 adding .hgsub
1488 1500 $ echo '[extensions]' >> parent/.hg/hgrc
1489 1501 $ echo '# enable extension locally' >> parent/.hg/hgrc
1490 1502 $ echo "reposetuptest = $TESTTMP/reposetuptest.py" >> parent/.hg/hgrc
1491 1503 $ cp parent/.hg/hgrc parent/sub2/.hg/hgrc
1492 1504 $ hg -R parent status -S -A
1493 1505 reposetup() for $TESTTMP/reposetup-test/parent (glob)
1494 1506 reposetup() for $TESTTMP/reposetup-test/parent/sub2 (glob)
1495 1507 C .hgsub
1496 1508 C .hgsubstate
1497 1509 C sub1/1
1498 1510 C sub2/.hgsub
1499 1511 C sub2/.hgsubstate
1500 1512 C sub2/sub21/21
1501 1513 C sub3/3
1502 1514
1503 1515 $ cd ..
1504 1516
1505 1517 Test synopsis and docstring extending
1506 1518
1507 1519 $ hg init exthelp
1508 1520 $ cat > exthelp.py <<EOF
1509 1521 > from mercurial import commands, extensions
1510 1522 > def exbookmarks(orig, *args, **opts):
1511 1523 > return orig(*args, **opts)
1512 1524 > def uisetup(ui):
1513 1525 > synopsis = ' GREPME [--foo] [-x]'
1514 1526 > docstring = '''
1515 1527 > GREPME make sure that this is in the help!
1516 1528 > '''
1517 1529 > extensions.wrapcommand(commands.table, 'bookmarks', exbookmarks,
1518 1530 > synopsis, docstring)
1519 1531 > EOF
1520 1532 $ abspath=`pwd`/exthelp.py
1521 1533 $ echo '[extensions]' >> $HGRCPATH
1522 1534 $ echo "exthelp = $abspath" >> $HGRCPATH
1523 1535 $ cd exthelp
1524 1536 $ hg help bookmarks | grep GREPME
1525 1537 hg bookmarks [OPTIONS]... [NAME]... GREPME [--foo] [-x]
1526 1538 GREPME make sure that this is in the help!
1527 1539
@@ -1,4 +1,9 b''
1 1 #require docutils gettext
2 2
3 Error: the current ro localization has some rst defects exposed by
4 moving pager to core. These two warnings about references are expected
5 until the localization is corrected.
3 6 $ $TESTDIR/check-gendoc ro
4 7 checking for parse errors
8 gendoc.txt:55: (WARNING/2) Inline interpreted text or phrase reference start-string without end-string.
9 gendoc.txt:55: (WARNING/2) Inline interpreted text or phrase reference start-string without end-string.
@@ -1,3174 +1,3184 b''
1 1 Short help:
2 2
3 3 $ hg
4 4 Mercurial Distributed SCM
5 5
6 6 basic commands:
7 7
8 8 add add the specified files on the next commit
9 9 annotate show changeset information by line for each file
10 10 clone make a copy of an existing repository
11 11 commit commit the specified files or all outstanding changes
12 12 diff diff repository (or selected files)
13 13 export dump the header and diffs for one or more changesets
14 14 forget forget the specified files on the next commit
15 15 init create a new repository in the given directory
16 16 log show revision history of entire repository or files
17 17 merge merge another revision into working directory
18 18 pull pull changes from the specified source
19 19 push push changes to the specified destination
20 20 remove remove the specified files on the next commit
21 21 serve start stand-alone webserver
22 22 status show changed files in the working directory
23 23 summary summarize working directory state
24 24 update update working directory (or switch revisions)
25 25
26 26 (use 'hg help' for the full list of commands or 'hg -v' for details)
27 27
28 28 $ hg -q
29 29 add add the specified files on the next commit
30 30 annotate show changeset information by line for each file
31 31 clone make a copy of an existing repository
32 32 commit commit the specified files or all outstanding changes
33 33 diff diff repository (or selected files)
34 34 export dump the header and diffs for one or more changesets
35 35 forget forget the specified files on the next commit
36 36 init create a new repository in the given directory
37 37 log show revision history of entire repository or files
38 38 merge merge another revision into working directory
39 39 pull pull changes from the specified source
40 40 push push changes to the specified destination
41 41 remove remove the specified files on the next commit
42 42 serve start stand-alone webserver
43 43 status show changed files in the working directory
44 44 summary summarize working directory state
45 45 update update working directory (or switch revisions)
46 46
47 47 $ hg help
48 48 Mercurial Distributed SCM
49 49
50 50 list of commands:
51 51
52 52 add add the specified files on the next commit
53 53 addremove add all new files, delete all missing files
54 54 annotate show changeset information by line for each file
55 55 archive create an unversioned archive of a repository revision
56 56 backout reverse effect of earlier changeset
57 57 bisect subdivision search of changesets
58 58 bookmarks create a new bookmark or list existing bookmarks
59 59 branch set or show the current branch name
60 60 branches list repository named branches
61 61 bundle create a changegroup file
62 62 cat output the current or given revision of files
63 63 clone make a copy of an existing repository
64 64 commit commit the specified files or all outstanding changes
65 65 config show combined config settings from all hgrc files
66 66 copy mark files as copied for the next commit
67 67 diff diff repository (or selected files)
68 68 export dump the header and diffs for one or more changesets
69 69 files list tracked files
70 70 forget forget the specified files on the next commit
71 71 graft copy changes from other branches onto the current branch
72 72 grep search revision history for a pattern in specified files
73 73 heads show branch heads
74 74 help show help for a given topic or a help overview
75 75 identify identify the working directory or specified revision
76 76 import import an ordered set of patches
77 77 incoming show new changesets found in source
78 78 init create a new repository in the given directory
79 79 log show revision history of entire repository or files
80 80 manifest output the current or given revision of the project manifest
81 81 merge merge another revision into working directory
82 82 outgoing show changesets not found in the destination
83 83 paths show aliases for remote repositories
84 84 phase set or show the current phase name
85 85 pull pull changes from the specified source
86 86 push push changes to the specified destination
87 87 recover roll back an interrupted transaction
88 88 remove remove the specified files on the next commit
89 89 rename rename files; equivalent of copy + remove
90 90 resolve redo merges or set/view the merge status of files
91 91 revert restore files to their checkout state
92 92 root print the root (top) of the current working directory
93 93 serve start stand-alone webserver
94 94 status show changed files in the working directory
95 95 summary summarize working directory state
96 96 tag add one or more tags for the current or given revision
97 97 tags list repository tags
98 98 unbundle apply one or more changegroup files
99 99 update update working directory (or switch revisions)
100 100 verify verify the integrity of the repository
101 101 version output version and copyright information
102 102
103 103 additional help topics:
104 104
105 105 config Configuration Files
106 106 dates Date Formats
107 107 diffs Diff Formats
108 108 environment Environment Variables
109 109 extensions Using Additional Features
110 110 filesets Specifying File Sets
111 111 glossary Glossary
112 112 hgignore Syntax for Mercurial Ignore Files
113 113 hgweb Configuring hgweb
114 114 internals Technical implementation topics
115 115 merge-tools Merge Tools
116 116 patterns File Name Patterns
117 117 phases Working with Phases
118 118 revisions Specifying Revisions
119 119 scripting Using Mercurial from scripts and automation
120 120 subrepos Subrepositories
121 121 templating Template Usage
122 122 urls URL Paths
123 123
124 124 (use 'hg help -v' to show built-in aliases and global options)
125 125
126 126 $ hg -q help
127 127 add add the specified files on the next commit
128 128 addremove add all new files, delete all missing files
129 129 annotate show changeset information by line for each file
130 130 archive create an unversioned archive of a repository revision
131 131 backout reverse effect of earlier changeset
132 132 bisect subdivision search of changesets
133 133 bookmarks create a new bookmark or list existing bookmarks
134 134 branch set or show the current branch name
135 135 branches list repository named branches
136 136 bundle create a changegroup file
137 137 cat output the current or given revision of files
138 138 clone make a copy of an existing repository
139 139 commit commit the specified files or all outstanding changes
140 140 config show combined config settings from all hgrc files
141 141 copy mark files as copied for the next commit
142 142 diff diff repository (or selected files)
143 143 export dump the header and diffs for one or more changesets
144 144 files list tracked files
145 145 forget forget the specified files on the next commit
146 146 graft copy changes from other branches onto the current branch
147 147 grep search revision history for a pattern in specified files
148 148 heads show branch heads
149 149 help show help for a given topic or a help overview
150 150 identify identify the working directory or specified revision
151 151 import import an ordered set of patches
152 152 incoming show new changesets found in source
153 153 init create a new repository in the given directory
154 154 log show revision history of entire repository or files
155 155 manifest output the current or given revision of the project manifest
156 156 merge merge another revision into working directory
157 157 outgoing show changesets not found in the destination
158 158 paths show aliases for remote repositories
159 159 phase set or show the current phase name
160 160 pull pull changes from the specified source
161 161 push push changes to the specified destination
162 162 recover roll back an interrupted transaction
163 163 remove remove the specified files on the next commit
164 164 rename rename files; equivalent of copy + remove
165 165 resolve redo merges or set/view the merge status of files
166 166 revert restore files to their checkout state
167 167 root print the root (top) of the current working directory
168 168 serve start stand-alone webserver
169 169 status show changed files in the working directory
170 170 summary summarize working directory state
171 171 tag add one or more tags for the current or given revision
172 172 tags list repository tags
173 173 unbundle apply one or more changegroup files
174 174 update update working directory (or switch revisions)
175 175 verify verify the integrity of the repository
176 176 version output version and copyright information
177 177
178 178 additional help topics:
179 179
180 180 config Configuration Files
181 181 dates Date Formats
182 182 diffs Diff Formats
183 183 environment Environment Variables
184 184 extensions Using Additional Features
185 185 filesets Specifying File Sets
186 186 glossary Glossary
187 187 hgignore Syntax for Mercurial Ignore Files
188 188 hgweb Configuring hgweb
189 189 internals Technical implementation topics
190 190 merge-tools Merge Tools
191 191 patterns File Name Patterns
192 192 phases Working with Phases
193 193 revisions Specifying Revisions
194 194 scripting Using Mercurial from scripts and automation
195 195 subrepos Subrepositories
196 196 templating Template Usage
197 197 urls URL Paths
198 198
199 199 Test extension help:
200 200 $ hg help extensions --config extensions.rebase= --config extensions.children=
201 201 Using Additional Features
202 202 """""""""""""""""""""""""
203 203
204 204 Mercurial has the ability to add new features through the use of
205 205 extensions. Extensions may add new commands, add options to existing
206 206 commands, change the default behavior of commands, or implement hooks.
207 207
208 208 To enable the "foo" extension, either shipped with Mercurial or in the
209 209 Python search path, create an entry for it in your configuration file,
210 210 like this:
211 211
212 212 [extensions]
213 213 foo =
214 214
215 215 You may also specify the full path to an extension:
216 216
217 217 [extensions]
218 218 myfeature = ~/.hgext/myfeature.py
219 219
220 220 See 'hg help config' for more information on configuration files.
221 221
222 222 Extensions are not loaded by default for a variety of reasons: they can
223 223 increase startup overhead; they may be meant for advanced usage only; they
224 224 may provide potentially dangerous abilities (such as letting you destroy
225 225 or modify history); they might not be ready for prime time; or they may
226 226 alter some usual behaviors of stock Mercurial. It is thus up to the user
227 227 to activate extensions as needed.
228 228
229 229 To explicitly disable an extension enabled in a configuration file of
230 230 broader scope, prepend its path with !:
231 231
232 232 [extensions]
233 233 # disabling extension bar residing in /path/to/extension/bar.py
234 234 bar = !/path/to/extension/bar.py
235 235 # ditto, but no path was supplied for extension baz
236 236 baz = !
237 237
238 238 enabled extensions:
239 239
240 240 children command to display child changesets (DEPRECATED)
241 241 rebase command to move sets of revisions to a different ancestor
242 242
243 243 disabled extensions:
244 244
245 245 acl hooks for controlling repository access
246 246 blackbox log repository events to a blackbox for debugging
247 247 bugzilla hooks for integrating with the Bugzilla bug tracker
248 248 censor erase file content at a given revision
249 249 churn command to display statistics about repository history
250 250 clonebundles advertise pre-generated bundles to seed clones
251 251 color colorize output from some commands
252 252 convert import revisions from foreign VCS repositories into
253 253 Mercurial
254 254 eol automatically manage newlines in repository files
255 255 extdiff command to allow external programs to compare revisions
256 256 factotum http authentication with factotum
257 257 gpg commands to sign and verify changesets
258 258 hgk browse the repository in a graphical way
259 259 highlight syntax highlighting for hgweb (requires Pygments)
260 260 histedit interactive history editing
261 261 keyword expand keywords in tracked files
262 262 largefiles track large binary files
263 263 mq manage a stack of patches
264 264 notify hooks for sending email push notifications
265 265 pager browse command output with an external pager
266 266 patchbomb command to send changesets as (a series of) patch emails
267 267 purge command to delete untracked files from the working
268 268 directory
269 269 relink recreates hardlinks between repository clones
270 270 schemes extend schemes with shortcuts to repository swarms
271 271 share share a common history between several working directories
272 272 shelve save and restore changes to the working directory
273 273 strip strip changesets and their descendants from history
274 274 transplant command to transplant changesets from another branch
275 275 win32mbcs allow the use of MBCS paths with problematic encodings
276 276 zeroconf discover and advertise repositories on the local network
277 277
278 278 Verify that extension keywords appear in help templates
279 279
280 280 $ hg help --config extensions.transplant= templating|grep transplant > /dev/null
281 281
282 282 Test short command list with verbose option
283 283
284 284 $ hg -v help shortlist
285 285 Mercurial Distributed SCM
286 286
287 287 basic commands:
288 288
289 289 add add the specified files on the next commit
290 290 annotate, blame
291 291 show changeset information by line for each file
292 292 clone make a copy of an existing repository
293 293 commit, ci commit the specified files or all outstanding changes
294 294 diff diff repository (or selected files)
295 295 export dump the header and diffs for one or more changesets
296 296 forget forget the specified files on the next commit
297 297 init create a new repository in the given directory
298 298 log, history show revision history of entire repository or files
299 299 merge merge another revision into working directory
300 300 pull pull changes from the specified source
301 301 push push changes to the specified destination
302 302 remove, rm remove the specified files on the next commit
303 303 serve start stand-alone webserver
304 304 status, st show changed files in the working directory
305 305 summary, sum summarize working directory state
306 306 update, up, checkout, co
307 307 update working directory (or switch revisions)
308 308
309 309 global options ([+] can be repeated):
310 310
311 311 -R --repository REPO repository root directory or name of overlay bundle
312 312 file
313 313 --cwd DIR change working directory
314 314 -y --noninteractive do not prompt, automatically pick the first choice for
315 315 all prompts
316 316 -q --quiet suppress output
317 317 -v --verbose enable additional output
318 318 --config CONFIG [+] set/override config option (use 'section.name=value')
319 319 --debug enable debugging output
320 320 --debugger start debugger
321 321 --encoding ENCODE set the charset encoding (default: ascii)
322 322 --encodingmode MODE set the charset encoding mode (default: strict)
323 323 --traceback always print a traceback on exception
324 324 --time time how long the command takes
325 325 --profile print command execution profile
326 326 --version output version information and exit
327 327 -h --help display help and exit
328 328 --hidden consider hidden changesets
329 --pager TYPE when to paginate (boolean, always, auto, or never)
330 (default: auto)
329 331
330 332 (use 'hg help' for the full list of commands)
331 333
332 334 $ hg add -h
333 335 hg add [OPTION]... [FILE]...
334 336
335 337 add the specified files on the next commit
336 338
337 339 Schedule files to be version controlled and added to the repository.
338 340
339 341 The files will be added to the repository at the next commit. To undo an
340 342 add before that, see 'hg forget'.
341 343
342 344 If no names are given, add all files to the repository (except files
343 345 matching ".hgignore").
344 346
345 347 Returns 0 if all files are successfully added.
346 348
347 349 options ([+] can be repeated):
348 350
349 351 -I --include PATTERN [+] include names matching the given patterns
350 352 -X --exclude PATTERN [+] exclude names matching the given patterns
351 353 -S --subrepos recurse into subrepositories
352 354 -n --dry-run do not perform actions, just print output
353 355
354 356 (some details hidden, use --verbose to show complete help)
355 357
356 358 Verbose help for add
357 359
358 360 $ hg add -hv
359 361 hg add [OPTION]... [FILE]...
360 362
361 363 add the specified files on the next commit
362 364
363 365 Schedule files to be version controlled and added to the repository.
364 366
365 367 The files will be added to the repository at the next commit. To undo an
366 368 add before that, see 'hg forget'.
367 369
368 370 If no names are given, add all files to the repository (except files
369 371 matching ".hgignore").
370 372
371 373 Examples:
372 374
373 375 - New (unknown) files are added automatically by 'hg add':
374 376
375 377 $ ls
376 378 foo.c
377 379 $ hg status
378 380 ? foo.c
379 381 $ hg add
380 382 adding foo.c
381 383 $ hg status
382 384 A foo.c
383 385
384 386 - Specific files to be added can be specified:
385 387
386 388 $ ls
387 389 bar.c foo.c
388 390 $ hg status
389 391 ? bar.c
390 392 ? foo.c
391 393 $ hg add bar.c
392 394 $ hg status
393 395 A bar.c
394 396 ? foo.c
395 397
396 398 Returns 0 if all files are successfully added.
397 399
398 400 options ([+] can be repeated):
399 401
400 402 -I --include PATTERN [+] include names matching the given patterns
401 403 -X --exclude PATTERN [+] exclude names matching the given patterns
402 404 -S --subrepos recurse into subrepositories
403 405 -n --dry-run do not perform actions, just print output
404 406
405 407 global options ([+] can be repeated):
406 408
407 409 -R --repository REPO repository root directory or name of overlay bundle
408 410 file
409 411 --cwd DIR change working directory
410 412 -y --noninteractive do not prompt, automatically pick the first choice for
411 413 all prompts
412 414 -q --quiet suppress output
413 415 -v --verbose enable additional output
414 416 --config CONFIG [+] set/override config option (use 'section.name=value')
415 417 --debug enable debugging output
416 418 --debugger start debugger
417 419 --encoding ENCODE set the charset encoding (default: ascii)
418 420 --encodingmode MODE set the charset encoding mode (default: strict)
419 421 --traceback always print a traceback on exception
420 422 --time time how long the command takes
421 423 --profile print command execution profile
422 424 --version output version information and exit
423 425 -h --help display help and exit
424 426 --hidden consider hidden changesets
427 --pager TYPE when to paginate (boolean, always, auto, or never)
428 (default: auto)
425 429
426 430 Test the textwidth config option
427 431
428 432 $ hg root -h --config ui.textwidth=50
429 433 hg root
430 434
431 435 print the root (top) of the current working
432 436 directory
433 437
434 438 Print the root directory of the current
435 439 repository.
436 440
437 441 Returns 0 on success.
438 442
439 443 (some details hidden, use --verbose to show
440 444 complete help)
441 445
442 446 Test help option with version option
443 447
444 448 $ hg add -h --version
445 449 Mercurial Distributed SCM (version *) (glob)
446 450 (see https://mercurial-scm.org for more information)
447 451
448 452 Copyright (C) 2005-* Matt Mackall and others (glob)
449 453 This is free software; see the source for copying conditions. There is NO
450 454 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
451 455
452 456 $ hg add --skjdfks
453 457 hg add: option --skjdfks not recognized
454 458 hg add [OPTION]... [FILE]...
455 459
456 460 add the specified files on the next commit
457 461
458 462 options ([+] can be repeated):
459 463
460 464 -I --include PATTERN [+] include names matching the given patterns
461 465 -X --exclude PATTERN [+] exclude names matching the given patterns
462 466 -S --subrepos recurse into subrepositories
463 467 -n --dry-run do not perform actions, just print output
464 468
465 469 (use 'hg add -h' to show more help)
466 470 [255]
467 471
468 472 Test ambiguous command help
469 473
470 474 $ hg help ad
471 475 list of commands:
472 476
473 477 add add the specified files on the next commit
474 478 addremove add all new files, delete all missing files
475 479
476 480 (use 'hg help -v ad' to show built-in aliases and global options)
477 481
478 482 Test command without options
479 483
480 484 $ hg help verify
481 485 hg verify
482 486
483 487 verify the integrity of the repository
484 488
485 489 Verify the integrity of the current repository.
486 490
487 491 This will perform an extensive check of the repository's integrity,
488 492 validating the hashes and checksums of each entry in the changelog,
489 493 manifest, and tracked files, as well as the integrity of their crosslinks
490 494 and indices.
491 495
492 496 Please see https://mercurial-scm.org/wiki/RepositoryCorruption for more
493 497 information about recovery from corruption of the repository.
494 498
495 499 Returns 0 on success, 1 if errors are encountered.
496 500
497 501 (some details hidden, use --verbose to show complete help)
498 502
499 503 $ hg help diff
500 504 hg diff [OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...
501 505
502 506 diff repository (or selected files)
503 507
504 508 Show differences between revisions for the specified files.
505 509
506 510 Differences between files are shown using the unified diff format.
507 511
508 512 Note:
509 513 'hg diff' may generate unexpected results for merges, as it will
510 514 default to comparing against the working directory's first parent
511 515 changeset if no revisions are specified.
512 516
513 517 When two revision arguments are given, then changes are shown between
514 518 those revisions. If only one revision is specified then that revision is
515 519 compared to the working directory, and, when no revisions are specified,
516 520 the working directory files are compared to its first parent.
517 521
518 522 Alternatively you can specify -c/--change with a revision to see the
519 523 changes in that changeset relative to its first parent.
520 524
521 525 Without the -a/--text option, diff will avoid generating diffs of files it
522 526 detects as binary. With -a, diff will generate a diff anyway, probably
523 527 with undesirable results.
524 528
525 529 Use the -g/--git option to generate diffs in the git extended diff format.
526 530 For more information, read 'hg help diffs'.
527 531
528 532 Returns 0 on success.
529 533
530 534 options ([+] can be repeated):
531 535
532 536 -r --rev REV [+] revision
533 537 -c --change REV change made by revision
534 538 -a --text treat all files as text
535 539 -g --git use git extended diff format
536 540 --nodates omit dates from diff headers
537 541 --noprefix omit a/ and b/ prefixes from filenames
538 542 -p --show-function show which function each change is in
539 543 --reverse produce a diff that undoes the changes
540 544 -w --ignore-all-space ignore white space when comparing lines
541 545 -b --ignore-space-change ignore changes in the amount of white space
542 546 -B --ignore-blank-lines ignore changes whose lines are all blank
543 547 -U --unified NUM number of lines of context to show
544 548 --stat output diffstat-style summary of changes
545 549 --root DIR produce diffs relative to subdirectory
546 550 -I --include PATTERN [+] include names matching the given patterns
547 551 -X --exclude PATTERN [+] exclude names matching the given patterns
548 552 -S --subrepos recurse into subrepositories
549 553
550 554 (some details hidden, use --verbose to show complete help)
551 555
552 556 $ hg help status
553 557 hg status [OPTION]... [FILE]...
554 558
555 559 aliases: st
556 560
557 561 show changed files in the working directory
558 562
559 563 Show status of files in the repository. If names are given, only files
560 564 that match are shown. Files that are clean or ignored or the source of a
561 565 copy/move operation, are not listed unless -c/--clean, -i/--ignored,
562 566 -C/--copies or -A/--all are given. Unless options described with "show
563 567 only ..." are given, the options -mardu are used.
564 568
565 569 Option -q/--quiet hides untracked (unknown and ignored) files unless
566 570 explicitly requested with -u/--unknown or -i/--ignored.
567 571
568 572 Note:
569 573 'hg status' may appear to disagree with diff if permissions have
570 574 changed or a merge has occurred. The standard diff format does not
571 575 report permission changes and diff only reports changes relative to one
572 576 merge parent.
573 577
574 578 If one revision is given, it is used as the base revision. If two
575 579 revisions are given, the differences between them are shown. The --change
576 580 option can also be used as a shortcut to list the changed files of a
577 581 revision from its first parent.
578 582
579 583 The codes used to show the status of files are:
580 584
581 585 M = modified
582 586 A = added
583 587 R = removed
584 588 C = clean
585 589 ! = missing (deleted by non-hg command, but still tracked)
586 590 ? = not tracked
587 591 I = ignored
588 592 = origin of the previous file (with --copies)
589 593
590 594 Returns 0 on success.
591 595
592 596 options ([+] can be repeated):
593 597
594 598 -A --all show status of all files
595 599 -m --modified show only modified files
596 600 -a --added show only added files
597 601 -r --removed show only removed files
598 602 -d --deleted show only deleted (but tracked) files
599 603 -c --clean show only files without changes
600 604 -u --unknown show only unknown (not tracked) files
601 605 -i --ignored show only ignored files
602 606 -n --no-status hide status prefix
603 607 -C --copies show source of copied files
604 608 -0 --print0 end filenames with NUL, for use with xargs
605 609 --rev REV [+] show difference from revision
606 610 --change REV list the changed files of a revision
607 611 -I --include PATTERN [+] include names matching the given patterns
608 612 -X --exclude PATTERN [+] exclude names matching the given patterns
609 613 -S --subrepos recurse into subrepositories
610 614
611 615 (some details hidden, use --verbose to show complete help)
612 616
613 617 $ hg -q help status
614 618 hg status [OPTION]... [FILE]...
615 619
616 620 show changed files in the working directory
617 621
618 622 $ hg help foo
619 623 abort: no such help topic: foo
620 624 (try 'hg help --keyword foo')
621 625 [255]
622 626
623 627 $ hg skjdfks
624 628 hg: unknown command 'skjdfks'
625 629 Mercurial Distributed SCM
626 630
627 631 basic commands:
628 632
629 633 add add the specified files on the next commit
630 634 annotate show changeset information by line for each file
631 635 clone make a copy of an existing repository
632 636 commit commit the specified files or all outstanding changes
633 637 diff diff repository (or selected files)
634 638 export dump the header and diffs for one or more changesets
635 639 forget forget the specified files on the next commit
636 640 init create a new repository in the given directory
637 641 log show revision history of entire repository or files
638 642 merge merge another revision into working directory
639 643 pull pull changes from the specified source
640 644 push push changes to the specified destination
641 645 remove remove the specified files on the next commit
642 646 serve start stand-alone webserver
643 647 status show changed files in the working directory
644 648 summary summarize working directory state
645 649 update update working directory (or switch revisions)
646 650
647 651 (use 'hg help' for the full list of commands or 'hg -v' for details)
648 652 [255]
649 653
650 654
651 655 Make sure that we don't run afoul of the help system thinking that
652 656 this is a section and erroring out weirdly.
653 657
654 658 $ hg .log
655 659 hg: unknown command '.log'
656 660 (did you mean log?)
657 661 [255]
658 662
659 663 $ hg log.
660 664 hg: unknown command 'log.'
661 665 (did you mean log?)
662 666 [255]
663 667 $ hg pu.lh
664 668 hg: unknown command 'pu.lh'
665 669 (did you mean one of pull, push?)
666 670 [255]
667 671
668 672 $ cat > helpext.py <<EOF
669 673 > import os
670 674 > from mercurial import cmdutil, commands
671 675 >
672 676 > cmdtable = {}
673 677 > command = cmdutil.command(cmdtable)
674 678 >
675 679 > @command('nohelp',
676 680 > [('', 'longdesc', 3, 'x'*90),
677 681 > ('n', '', None, 'normal desc'),
678 682 > ('', 'newline', '', 'line1\nline2')],
679 683 > 'hg nohelp',
680 684 > norepo=True)
681 685 > @command('debugoptDEP', [('', 'dopt', None, 'option is (DEPRECATED)')])
682 686 > @command('debugoptEXP', [('', 'eopt', None, 'option is (EXPERIMENTAL)')])
683 687 > def nohelp(ui, *args, **kwargs):
684 688 > pass
685 689 >
686 690 > def uisetup(ui):
687 691 > ui.setconfig('alias', 'shellalias', '!echo hi', 'helpext')
688 692 > ui.setconfig('alias', 'hgalias', 'summary', 'helpext')
689 693 >
690 694 > EOF
691 695 $ echo '[extensions]' >> $HGRCPATH
692 696 $ echo "helpext = `pwd`/helpext.py" >> $HGRCPATH
693 697
694 698 Test for aliases
695 699
696 700 $ hg help hgalias
697 701 hg hgalias [--remote]
698 702
699 703 alias for: hg summary
700 704
701 705 summarize working directory state
702 706
703 707 This generates a brief summary of the working directory state, including
704 708 parents, branch, commit status, phase and available updates.
705 709
706 710 With the --remote option, this will check the default paths for incoming
707 711 and outgoing changes. This can be time-consuming.
708 712
709 713 Returns 0 on success.
710 714
711 715 defined by: helpext
712 716
713 717 options:
714 718
715 719 --remote check for push and pull
716 720
717 721 (some details hidden, use --verbose to show complete help)
718 722
719 723 $ hg help shellalias
720 724 hg shellalias
721 725
722 726 shell alias for:
723 727
724 728 echo hi
725 729
726 730 defined by: helpext
727 731
728 732 (some details hidden, use --verbose to show complete help)
729 733
730 734 Test command with no help text
731 735
732 736 $ hg help nohelp
733 737 hg nohelp
734 738
735 739 (no help text available)
736 740
737 741 options:
738 742
739 743 --longdesc VALUE xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
740 744 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (default: 3)
741 745 -n -- normal desc
742 746 --newline VALUE line1 line2
743 747
744 748 (some details hidden, use --verbose to show complete help)
745 749
746 750 $ hg help -k nohelp
747 751 Commands:
748 752
749 753 nohelp hg nohelp
750 754
751 755 Extension Commands:
752 756
753 757 nohelp (no help text available)
754 758
755 759 Test that default list of commands omits extension commands
756 760
757 761 $ hg help
758 762 Mercurial Distributed SCM
759 763
760 764 list of commands:
761 765
762 766 add add the specified files on the next commit
763 767 addremove add all new files, delete all missing files
764 768 annotate show changeset information by line for each file
765 769 archive create an unversioned archive of a repository revision
766 770 backout reverse effect of earlier changeset
767 771 bisect subdivision search of changesets
768 772 bookmarks create a new bookmark or list existing bookmarks
769 773 branch set or show the current branch name
770 774 branches list repository named branches
771 775 bundle create a changegroup file
772 776 cat output the current or given revision of files
773 777 clone make a copy of an existing repository
774 778 commit commit the specified files or all outstanding changes
775 779 config show combined config settings from all hgrc files
776 780 copy mark files as copied for the next commit
777 781 diff diff repository (or selected files)
778 782 export dump the header and diffs for one or more changesets
779 783 files list tracked files
780 784 forget forget the specified files on the next commit
781 785 graft copy changes from other branches onto the current branch
782 786 grep search revision history for a pattern in specified files
783 787 heads show branch heads
784 788 help show help for a given topic or a help overview
785 789 identify identify the working directory or specified revision
786 790 import import an ordered set of patches
787 791 incoming show new changesets found in source
788 792 init create a new repository in the given directory
789 793 log show revision history of entire repository or files
790 794 manifest output the current or given revision of the project manifest
791 795 merge merge another revision into working directory
792 796 outgoing show changesets not found in the destination
793 797 paths show aliases for remote repositories
794 798 phase set or show the current phase name
795 799 pull pull changes from the specified source
796 800 push push changes to the specified destination
797 801 recover roll back an interrupted transaction
798 802 remove remove the specified files on the next commit
799 803 rename rename files; equivalent of copy + remove
800 804 resolve redo merges or set/view the merge status of files
801 805 revert restore files to their checkout state
802 806 root print the root (top) of the current working directory
803 807 serve start stand-alone webserver
804 808 status show changed files in the working directory
805 809 summary summarize working directory state
806 810 tag add one or more tags for the current or given revision
807 811 tags list repository tags
808 812 unbundle apply one or more changegroup files
809 813 update update working directory (or switch revisions)
810 814 verify verify the integrity of the repository
811 815 version output version and copyright information
812 816
813 817 enabled extensions:
814 818
815 819 helpext (no help text available)
816 820
817 821 additional help topics:
818 822
819 823 config Configuration Files
820 824 dates Date Formats
821 825 diffs Diff Formats
822 826 environment Environment Variables
823 827 extensions Using Additional Features
824 828 filesets Specifying File Sets
825 829 glossary Glossary
826 830 hgignore Syntax for Mercurial Ignore Files
827 831 hgweb Configuring hgweb
828 832 internals Technical implementation topics
829 833 merge-tools Merge Tools
830 834 patterns File Name Patterns
831 835 phases Working with Phases
832 836 revisions Specifying Revisions
833 837 scripting Using Mercurial from scripts and automation
834 838 subrepos Subrepositories
835 839 templating Template Usage
836 840 urls URL Paths
837 841
838 842 (use 'hg help -v' to show built-in aliases and global options)
839 843
840 844
841 845 Test list of internal help commands
842 846
843 847 $ hg help debug
844 848 debug commands (internal and unsupported):
845 849
846 850 debugancestor
847 851 find the ancestor revision of two revisions in a given index
848 852 debugapplystreamclonebundle
849 853 apply a stream clone bundle file
850 854 debugbuilddag
851 855 builds a repo with a given DAG from scratch in the current
852 856 empty repo
853 857 debugbundle lists the contents of a bundle
854 858 debugcheckstate
855 859 validate the correctness of the current dirstate
856 860 debugcommands
857 861 list all available commands and options
858 862 debugcomplete
859 863 returns the completion list associated with the given command
860 864 debugcreatestreamclonebundle
861 865 create a stream clone bundle file
862 866 debugdag format the changelog or an index DAG as a concise textual
863 867 description
864 868 debugdata dump the contents of a data file revision
865 869 debugdate parse and display a date
866 870 debugdeltachain
867 871 dump information about delta chains in a revlog
868 872 debugdirstate
869 873 show the contents of the current dirstate
870 874 debugdiscovery
871 875 runs the changeset discovery protocol in isolation
872 876 debugextensions
873 877 show information about active extensions
874 878 debugfileset parse and apply a fileset specification
875 879 debugfsinfo show information detected about current filesystem
876 880 debuggetbundle
877 881 retrieves a bundle from a repo
878 882 debugignore display the combined ignore pattern and information about
879 883 ignored files
880 884 debugindex dump the contents of an index file
881 885 debugindexdot
882 886 dump an index DAG as a graphviz dot file
883 887 debuginstall test Mercurial installation
884 888 debugknown test whether node ids are known to a repo
885 889 debuglocks show or modify state of locks
886 890 debugmergestate
887 891 print merge state
888 892 debugnamecomplete
889 893 complete "names" - tags, open branch names, bookmark names
890 894 debugobsolete
891 895 create arbitrary obsolete marker
892 896 debugoptDEP (no help text available)
893 897 debugoptEXP (no help text available)
894 898 debugpathcomplete
895 899 complete part or all of a tracked path
896 900 debugpushkey access the pushkey key/value protocol
897 901 debugpvec (no help text available)
898 902 debugrebuilddirstate
899 903 rebuild the dirstate as it would look like for the given
900 904 revision
901 905 debugrebuildfncache
902 906 rebuild the fncache file
903 907 debugrename dump rename information
904 908 debugrevlog show data and statistics about a revlog
905 909 debugrevspec parse and apply a revision specification
906 910 debugsetparents
907 911 manually set the parents of the current working directory
908 912 debugsub (no help text available)
909 913 debugsuccessorssets
910 914 show set of successors for revision
911 915 debugtemplate
912 916 parse and apply a template
913 917 debugupgraderepo
914 918 upgrade a repository to use different features
915 919 debugwalk show how files match on given patterns
916 920 debugwireargs
917 921 (no help text available)
918 922
919 923 (use 'hg help -v debug' to show built-in aliases and global options)
920 924
921 925 internals topic renders index of available sub-topics
922 926
923 927 $ hg help internals
924 928 Technical implementation topics
925 929 """""""""""""""""""""""""""""""
926 930
927 931 bundles Bundles
928 932 changegroups Changegroups
929 933 requirements Repository Requirements
930 934 revlogs Revision Logs
931 935 wireprotocol Wire Protocol
932 936
933 937 sub-topics can be accessed
934 938
935 939 $ hg help internals.changegroups
936 940 Changegroups
937 941 """"""""""""
938 942
939 943 Changegroups are representations of repository revlog data, specifically
940 944 the changelog, manifest, and filelogs.
941 945
942 946 There are 3 versions of changegroups: "1", "2", and "3". From a high-
943 947 level, versions "1" and "2" are almost exactly the same, with the only
944 948 difference being a header on entries in the changeset segment. Version "3"
945 949 adds support for exchanging treemanifests and includes revlog flags in the
946 950 delta header.
947 951
948 952 Changegroups consists of 3 logical segments:
949 953
950 954 +---------------------------------+
951 955 | | | |
952 956 | changeset | manifest | filelogs |
953 957 | | | |
954 958 +---------------------------------+
955 959
956 960 The principle building block of each segment is a *chunk*. A *chunk* is a
957 961 framed piece of data:
958 962
959 963 +---------------------------------------+
960 964 | | |
961 965 | length | data |
962 966 | (32 bits) | <length> bytes |
963 967 | | |
964 968 +---------------------------------------+
965 969
966 970 Each chunk starts with a 32-bit big-endian signed integer indicating the
967 971 length of the raw data that follows.
968 972
969 973 There is a special case chunk that has 0 length ("0x00000000"). We call
970 974 this an *empty chunk*.
971 975
972 976 Delta Groups
973 977 ============
974 978
975 979 A *delta group* expresses the content of a revlog as a series of deltas,
976 980 or patches against previous revisions.
977 981
978 982 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
979 983 to signal the end of the delta group:
980 984
981 985 +------------------------------------------------------------------------+
982 986 | | | | | |
983 987 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
984 988 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
985 989 | | | | | |
986 990 +------------------------------------------------------------+-----------+
987 991
988 992 Each *chunk*'s data consists of the following:
989 993
990 994 +-----------------------------------------+
991 995 | | | |
992 996 | delta header | mdiff header | delta |
993 997 | (various) | (12 bytes) | (various) |
994 998 | | | |
995 999 +-----------------------------------------+
996 1000
997 1001 The *length* field is the byte length of the remaining 3 logical pieces of
998 1002 data. The *delta* is a diff from an existing entry in the changelog.
999 1003
1000 1004 The *delta header* is different between versions "1", "2", and "3" of the
1001 1005 changegroup format.
1002 1006
1003 1007 Version 1:
1004 1008
1005 1009 +------------------------------------------------------+
1006 1010 | | | | |
1007 1011 | node | p1 node | p2 node | link node |
1008 1012 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1009 1013 | | | | |
1010 1014 +------------------------------------------------------+
1011 1015
1012 1016 Version 2:
1013 1017
1014 1018 +------------------------------------------------------------------+
1015 1019 | | | | | |
1016 1020 | node | p1 node | p2 node | base node | link node |
1017 1021 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
1018 1022 | | | | | |
1019 1023 +------------------------------------------------------------------+
1020 1024
1021 1025 Version 3:
1022 1026
1023 1027 +------------------------------------------------------------------------------+
1024 1028 | | | | | | |
1025 1029 | node | p1 node | p2 node | base node | link node | flags |
1026 1030 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
1027 1031 | | | | | | |
1028 1032 +------------------------------------------------------------------------------+
1029 1033
1030 1034 The *mdiff header* consists of 3 32-bit big-endian signed integers
1031 1035 describing offsets at which to apply the following delta content:
1032 1036
1033 1037 +-------------------------------------+
1034 1038 | | | |
1035 1039 | offset | old length | new length |
1036 1040 | (32 bits) | (32 bits) | (32 bits) |
1037 1041 | | | |
1038 1042 +-------------------------------------+
1039 1043
1040 1044 In version 1, the delta is always applied against the previous node from
1041 1045 the changegroup or the first parent if this is the first entry in the
1042 1046 changegroup.
1043 1047
1044 1048 In version 2, the delta base node is encoded in the entry in the
1045 1049 changegroup. This allows the delta to be expressed against any parent,
1046 1050 which can result in smaller deltas and more efficient encoding of data.
1047 1051
1048 1052 Changeset Segment
1049 1053 =================
1050 1054
1051 1055 The *changeset segment* consists of a single *delta group* holding
1052 1056 changelog data. It is followed by an *empty chunk* to denote the boundary
1053 1057 to the *manifests segment*.
1054 1058
1055 1059 Manifest Segment
1056 1060 ================
1057 1061
1058 1062 The *manifest segment* consists of a single *delta group* holding manifest
1059 1063 data. It is followed by an *empty chunk* to denote the boundary to the
1060 1064 *filelogs segment*.
1061 1065
1062 1066 Filelogs Segment
1063 1067 ================
1064 1068
1065 1069 The *filelogs* segment consists of multiple sub-segments, each
1066 1070 corresponding to an individual file whose data is being described:
1067 1071
1068 1072 +--------------------------------------+
1069 1073 | | | | |
1070 1074 | filelog0 | filelog1 | filelog2 | ... |
1071 1075 | | | | |
1072 1076 +--------------------------------------+
1073 1077
1074 1078 In version "3" of the changegroup format, filelogs may include directory
1075 1079 logs when treemanifests are in use. directory logs are identified by
1076 1080 having a trailing '/' on their filename (see below).
1077 1081
1078 1082 The final filelog sub-segment is followed by an *empty chunk* to denote
1079 1083 the end of the segment and the overall changegroup.
1080 1084
1081 1085 Each filelog sub-segment consists of the following:
1082 1086
1083 1087 +------------------------------------------+
1084 1088 | | | |
1085 1089 | filename size | filename | delta group |
1086 1090 | (32 bits) | (various) | (various) |
1087 1091 | | | |
1088 1092 +------------------------------------------+
1089 1093
1090 1094 That is, a *chunk* consisting of the filename (not terminated or padded)
1091 1095 followed by N chunks constituting the *delta group* for this file.
1092 1096
1093 1097 Test list of commands with command with no help text
1094 1098
1095 1099 $ hg help helpext
1096 1100 helpext extension - no help text available
1097 1101
1098 1102 list of commands:
1099 1103
1100 1104 nohelp (no help text available)
1101 1105
1102 1106 (use 'hg help -v helpext' to show built-in aliases and global options)
1103 1107
1104 1108
1105 1109 test deprecated and experimental options are hidden in command help
1106 1110 $ hg help debugoptDEP
1107 1111 hg debugoptDEP
1108 1112
1109 1113 (no help text available)
1110 1114
1111 1115 options:
1112 1116
1113 1117 (some details hidden, use --verbose to show complete help)
1114 1118
1115 1119 $ hg help debugoptEXP
1116 1120 hg debugoptEXP
1117 1121
1118 1122 (no help text available)
1119 1123
1120 1124 options:
1121 1125
1122 1126 (some details hidden, use --verbose to show complete help)
1123 1127
1124 1128 test deprecated and experimental options is shown with -v
1125 1129 $ hg help -v debugoptDEP | grep dopt
1126 1130 --dopt option is (DEPRECATED)
1127 1131 $ hg help -v debugoptEXP | grep eopt
1128 1132 --eopt option is (EXPERIMENTAL)
1129 1133
1130 1134 #if gettext
1131 1135 test deprecated option is hidden with translation with untranslated description
1132 1136 (use many globy for not failing on changed transaction)
1133 1137 $ LANGUAGE=sv hg help debugoptDEP
1134 1138 hg debugoptDEP
1135 1139
1136 1140 (*) (glob)
1137 1141
1138 1142 options:
1139 1143
1140 1144 (some details hidden, use --verbose to show complete help)
1141 1145 #endif
1142 1146
1143 1147 Test commands that collide with topics (issue4240)
1144 1148
1145 1149 $ hg config -hq
1146 1150 hg config [-u] [NAME]...
1147 1151
1148 1152 show combined config settings from all hgrc files
1149 1153 $ hg showconfig -hq
1150 1154 hg config [-u] [NAME]...
1151 1155
1152 1156 show combined config settings from all hgrc files
1153 1157
1154 1158 Test a help topic
1155 1159
1156 1160 $ hg help dates
1157 1161 Date Formats
1158 1162 """"""""""""
1159 1163
1160 1164 Some commands allow the user to specify a date, e.g.:
1161 1165
1162 1166 - backout, commit, import, tag: Specify the commit date.
1163 1167 - log, revert, update: Select revision(s) by date.
1164 1168
1165 1169 Many date formats are valid. Here are some examples:
1166 1170
1167 1171 - "Wed Dec 6 13:18:29 2006" (local timezone assumed)
1168 1172 - "Dec 6 13:18 -0600" (year assumed, time offset provided)
1169 1173 - "Dec 6 13:18 UTC" (UTC and GMT are aliases for +0000)
1170 1174 - "Dec 6" (midnight)
1171 1175 - "13:18" (today assumed)
1172 1176 - "3:39" (3:39AM assumed)
1173 1177 - "3:39pm" (15:39)
1174 1178 - "2006-12-06 13:18:29" (ISO 8601 format)
1175 1179 - "2006-12-6 13:18"
1176 1180 - "2006-12-6"
1177 1181 - "12-6"
1178 1182 - "12/6"
1179 1183 - "12/6/6" (Dec 6 2006)
1180 1184 - "today" (midnight)
1181 1185 - "yesterday" (midnight)
1182 1186 - "now" - right now
1183 1187
1184 1188 Lastly, there is Mercurial's internal format:
1185 1189
1186 1190 - "1165411109 0" (Wed Dec 6 13:18:29 2006 UTC)
1187 1191
1188 1192 This is the internal representation format for dates. The first number is
1189 1193 the number of seconds since the epoch (1970-01-01 00:00 UTC). The second
1190 1194 is the offset of the local timezone, in seconds west of UTC (negative if
1191 1195 the timezone is east of UTC).
1192 1196
1193 1197 The log command also accepts date ranges:
1194 1198
1195 1199 - "<DATE" - at or before a given date/time
1196 1200 - ">DATE" - on or after a given date/time
1197 1201 - "DATE to DATE" - a date range, inclusive
1198 1202 - "-DAYS" - within a given number of days of today
1199 1203
1200 1204 Test repeated config section name
1201 1205
1202 1206 $ hg help config.host
1203 1207 "http_proxy.host"
1204 1208 Host name and (optional) port of the proxy server, for example
1205 1209 "myproxy:8000".
1206 1210
1207 1211 "smtp.host"
1208 1212 Host name of mail server, e.g. "mail.example.com".
1209 1213
1210 1214 Unrelated trailing paragraphs shouldn't be included
1211 1215
1212 1216 $ hg help config.extramsg | grep '^$'
1213 1217
1214 1218
1215 1219 Test capitalized section name
1216 1220
1217 1221 $ hg help scripting.HGPLAIN > /dev/null
1218 1222
1219 1223 Help subsection:
1220 1224
1221 1225 $ hg help config.charsets |grep "Email example:" > /dev/null
1222 1226 [1]
1223 1227
1224 1228 Show nested definitions
1225 1229 ("profiling.type"[break]"ls"[break]"stat"[break])
1226 1230
1227 1231 $ hg help config.type | egrep '^$'|wc -l
1228 1232 \s*3 (re)
1229 1233
1230 1234 Separate sections from subsections
1231 1235
1232 1236 $ hg help config.format | egrep '^ ("|-)|^\s*$' | uniq
1233 1237 "format"
1234 1238 --------
1235 1239
1236 1240 "usegeneraldelta"
1237 1241
1238 1242 "dotencode"
1239 1243
1240 1244 "usefncache"
1241 1245
1242 1246 "usestore"
1243 1247
1244 1248 "profiling"
1245 1249 -----------
1246 1250
1247 1251 "format"
1248 1252
1249 1253 "progress"
1250 1254 ----------
1251 1255
1252 1256 "format"
1253 1257
1254 1258
1255 1259 Last item in help config.*:
1256 1260
1257 1261 $ hg help config.`hg help config|grep '^ "'| \
1258 1262 > tail -1|sed 's![ "]*!!g'`| \
1259 1263 > grep 'hg help -c config' > /dev/null
1260 1264 [1]
1261 1265
1262 1266 note to use help -c for general hg help config:
1263 1267
1264 1268 $ hg help config |grep 'hg help -c config' > /dev/null
1265 1269
1266 1270 Test templating help
1267 1271
1268 1272 $ hg help templating | egrep '(desc|diffstat|firstline|nonempty) '
1269 1273 desc String. The text of the changeset description.
1270 1274 diffstat String. Statistics of changes with the following format:
1271 1275 firstline Any text. Returns the first line of text.
1272 1276 nonempty Any text. Returns '(none)' if the string is empty.
1273 1277
1274 1278 Test deprecated items
1275 1279
1276 1280 $ hg help -v templating | grep currentbookmark
1277 1281 currentbookmark
1278 1282 $ hg help templating | (grep currentbookmark || true)
1279 1283
1280 1284 Test help hooks
1281 1285
1282 1286 $ cat > helphook1.py <<EOF
1283 1287 > from mercurial import help
1284 1288 >
1285 1289 > def rewrite(ui, topic, doc):
1286 1290 > return doc + '\nhelphook1\n'
1287 1291 >
1288 1292 > def extsetup(ui):
1289 1293 > help.addtopichook('revisions', rewrite)
1290 1294 > EOF
1291 1295 $ cat > helphook2.py <<EOF
1292 1296 > from mercurial import help
1293 1297 >
1294 1298 > def rewrite(ui, topic, doc):
1295 1299 > return doc + '\nhelphook2\n'
1296 1300 >
1297 1301 > def extsetup(ui):
1298 1302 > help.addtopichook('revisions', rewrite)
1299 1303 > EOF
1300 1304 $ echo '[extensions]' >> $HGRCPATH
1301 1305 $ echo "helphook1 = `pwd`/helphook1.py" >> $HGRCPATH
1302 1306 $ echo "helphook2 = `pwd`/helphook2.py" >> $HGRCPATH
1303 1307 $ hg help revsets | grep helphook
1304 1308 helphook1
1305 1309 helphook2
1306 1310
1307 1311 help -c should only show debug --debug
1308 1312
1309 1313 $ hg help -c --debug|egrep debug|wc -l|egrep '^\s*0\s*$'
1310 1314 [1]
1311 1315
1312 1316 help -c should only show deprecated for -v
1313 1317
1314 1318 $ hg help -c -v|egrep DEPRECATED|wc -l|egrep '^\s*0\s*$'
1315 1319 [1]
1316 1320
1317 1321 Test -s / --system
1318 1322
1319 1323 $ hg help config.files -s windows |grep 'etc/mercurial' | \
1320 1324 > wc -l | sed -e 's/ //g'
1321 1325 0
1322 1326 $ hg help config.files --system unix | grep 'USER' | \
1323 1327 > wc -l | sed -e 's/ //g'
1324 1328 0
1325 1329
1326 1330 Test -e / -c / -k combinations
1327 1331
1328 1332 $ hg help -c|egrep '^[A-Z].*:|^ debug'
1329 1333 Commands:
1330 1334 $ hg help -e|egrep '^[A-Z].*:|^ debug'
1331 1335 Extensions:
1332 1336 $ hg help -k|egrep '^[A-Z].*:|^ debug'
1333 1337 Topics:
1334 1338 Commands:
1335 1339 Extensions:
1336 1340 Extension Commands:
1337 1341 $ hg help -c schemes
1338 1342 abort: no such help topic: schemes
1339 1343 (try 'hg help --keyword schemes')
1340 1344 [255]
1341 1345 $ hg help -e schemes |head -1
1342 1346 schemes extension - extend schemes with shortcuts to repository swarms
1343 1347 $ hg help -c -k dates |egrep '^(Topics|Extensions|Commands):'
1344 1348 Commands:
1345 1349 $ hg help -e -k a |egrep '^(Topics|Extensions|Commands):'
1346 1350 Extensions:
1347 1351 $ hg help -e -c -k date |egrep '^(Topics|Extensions|Commands):'
1348 1352 Extensions:
1349 1353 Commands:
1350 1354 $ hg help -c commit > /dev/null
1351 1355 $ hg help -e -c commit > /dev/null
1352 1356 $ hg help -e commit > /dev/null
1353 1357 abort: no such help topic: commit
1354 1358 (try 'hg help --keyword commit')
1355 1359 [255]
1356 1360
1357 1361 Test keyword search help
1358 1362
1359 1363 $ cat > prefixedname.py <<EOF
1360 1364 > '''matched against word "clone"
1361 1365 > '''
1362 1366 > EOF
1363 1367 $ echo '[extensions]' >> $HGRCPATH
1364 1368 $ echo "dot.dot.prefixedname = `pwd`/prefixedname.py" >> $HGRCPATH
1365 1369 $ hg help -k clone
1366 1370 Topics:
1367 1371
1368 1372 config Configuration Files
1369 1373 extensions Using Additional Features
1370 1374 glossary Glossary
1371 1375 phases Working with Phases
1372 1376 subrepos Subrepositories
1373 1377 urls URL Paths
1374 1378
1375 1379 Commands:
1376 1380
1377 1381 bookmarks create a new bookmark or list existing bookmarks
1378 1382 clone make a copy of an existing repository
1379 1383 paths show aliases for remote repositories
1380 1384 update update working directory (or switch revisions)
1381 1385
1382 1386 Extensions:
1383 1387
1384 1388 clonebundles advertise pre-generated bundles to seed clones
1385 1389 prefixedname matched against word "clone"
1386 1390 relink recreates hardlinks between repository clones
1387 1391
1388 1392 Extension Commands:
1389 1393
1390 1394 qclone clone main and patch repository at same time
1391 1395
1392 1396 Test unfound topic
1393 1397
1394 1398 $ hg help nonexistingtopicthatwillneverexisteverever
1395 1399 abort: no such help topic: nonexistingtopicthatwillneverexisteverever
1396 1400 (try 'hg help --keyword nonexistingtopicthatwillneverexisteverever')
1397 1401 [255]
1398 1402
1399 1403 Test unfound keyword
1400 1404
1401 1405 $ hg help --keyword nonexistingwordthatwillneverexisteverever
1402 1406 abort: no matches
1403 1407 (try 'hg help' for a list of topics)
1404 1408 [255]
1405 1409
1406 1410 Test omit indicating for help
1407 1411
1408 1412 $ cat > addverboseitems.py <<EOF
1409 1413 > '''extension to test omit indicating.
1410 1414 >
1411 1415 > This paragraph is never omitted (for extension)
1412 1416 >
1413 1417 > .. container:: verbose
1414 1418 >
1415 1419 > This paragraph is omitted,
1416 1420 > if :hg:\`help\` is invoked without \`\`-v\`\` (for extension)
1417 1421 >
1418 1422 > This paragraph is never omitted, too (for extension)
1419 1423 > '''
1420 1424 >
1421 1425 > from mercurial import help, commands
1422 1426 > testtopic = """This paragraph is never omitted (for topic).
1423 1427 >
1424 1428 > .. container:: verbose
1425 1429 >
1426 1430 > This paragraph is omitted,
1427 1431 > if :hg:\`help\` is invoked without \`\`-v\`\` (for topic)
1428 1432 >
1429 1433 > This paragraph is never omitted, too (for topic)
1430 1434 > """
1431 1435 > def extsetup(ui):
1432 1436 > help.helptable.append((["topic-containing-verbose"],
1433 1437 > "This is the topic to test omit indicating.",
1434 1438 > lambda ui: testtopic))
1435 1439 > EOF
1436 1440 $ echo '[extensions]' >> $HGRCPATH
1437 1441 $ echo "addverboseitems = `pwd`/addverboseitems.py" >> $HGRCPATH
1438 1442 $ hg help addverboseitems
1439 1443 addverboseitems extension - extension to test omit indicating.
1440 1444
1441 1445 This paragraph is never omitted (for extension)
1442 1446
1443 1447 This paragraph is never omitted, too (for extension)
1444 1448
1445 1449 (some details hidden, use --verbose to show complete help)
1446 1450
1447 1451 no commands defined
1448 1452 $ hg help -v addverboseitems
1449 1453 addverboseitems extension - extension to test omit indicating.
1450 1454
1451 1455 This paragraph is never omitted (for extension)
1452 1456
1453 1457 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1454 1458 extension)
1455 1459
1456 1460 This paragraph is never omitted, too (for extension)
1457 1461
1458 1462 no commands defined
1459 1463 $ hg help topic-containing-verbose
1460 1464 This is the topic to test omit indicating.
1461 1465 """"""""""""""""""""""""""""""""""""""""""
1462 1466
1463 1467 This paragraph is never omitted (for topic).
1464 1468
1465 1469 This paragraph is never omitted, too (for topic)
1466 1470
1467 1471 (some details hidden, use --verbose to show complete help)
1468 1472 $ hg help -v topic-containing-verbose
1469 1473 This is the topic to test omit indicating.
1470 1474 """"""""""""""""""""""""""""""""""""""""""
1471 1475
1472 1476 This paragraph is never omitted (for topic).
1473 1477
1474 1478 This paragraph is omitted, if 'hg help' is invoked without "-v" (for
1475 1479 topic)
1476 1480
1477 1481 This paragraph is never omitted, too (for topic)
1478 1482
1479 1483 Test section lookup
1480 1484
1481 1485 $ hg help revset.merge
1482 1486 "merge()"
1483 1487 Changeset is a merge changeset.
1484 1488
1485 1489 $ hg help glossary.dag
1486 1490 DAG
1487 1491 The repository of changesets of a distributed version control system
1488 1492 (DVCS) can be described as a directed acyclic graph (DAG), consisting
1489 1493 of nodes and edges, where nodes correspond to changesets and edges
1490 1494 imply a parent -> child relation. This graph can be visualized by
1491 1495 graphical tools such as 'hg log --graph'. In Mercurial, the DAG is
1492 1496 limited by the requirement for children to have at most two parents.
1493 1497
1494 1498
1495 1499 $ hg help hgrc.paths
1496 1500 "paths"
1497 1501 -------
1498 1502
1499 1503 Assigns symbolic names and behavior to repositories.
1500 1504
1501 1505 Options are symbolic names defining the URL or directory that is the
1502 1506 location of the repository. Example:
1503 1507
1504 1508 [paths]
1505 1509 my_server = https://example.com/my_repo
1506 1510 local_path = /home/me/repo
1507 1511
1508 1512 These symbolic names can be used from the command line. To pull from
1509 1513 "my_server": 'hg pull my_server'. To push to "local_path": 'hg push
1510 1514 local_path'.
1511 1515
1512 1516 Options containing colons (":") denote sub-options that can influence
1513 1517 behavior for that specific path. Example:
1514 1518
1515 1519 [paths]
1516 1520 my_server = https://example.com/my_path
1517 1521 my_server:pushurl = ssh://example.com/my_path
1518 1522
1519 1523 The following sub-options can be defined:
1520 1524
1521 1525 "pushurl"
1522 1526 The URL to use for push operations. If not defined, the location
1523 1527 defined by the path's main entry is used.
1524 1528
1525 1529 "pushrev"
1526 1530 A revset defining which revisions to push by default.
1527 1531
1528 1532 When 'hg push' is executed without a "-r" argument, the revset defined
1529 1533 by this sub-option is evaluated to determine what to push.
1530 1534
1531 1535 For example, a value of "." will push the working directory's revision
1532 1536 by default.
1533 1537
1534 1538 Revsets specifying bookmarks will not result in the bookmark being
1535 1539 pushed.
1536 1540
1537 1541 The following special named paths exist:
1538 1542
1539 1543 "default"
1540 1544 The URL or directory to use when no source or remote is specified.
1541 1545
1542 1546 'hg clone' will automatically define this path to the location the
1543 1547 repository was cloned from.
1544 1548
1545 1549 "default-push"
1546 1550 (deprecated) The URL or directory for the default 'hg push' location.
1547 1551 "default:pushurl" should be used instead.
1548 1552
1549 1553 $ hg help glossary.mcguffin
1550 1554 abort: help section not found: glossary.mcguffin
1551 1555 [255]
1552 1556
1553 1557 $ hg help glossary.mc.guffin
1554 1558 abort: help section not found: glossary.mc.guffin
1555 1559 [255]
1556 1560
1557 1561 $ hg help template.files
1558 1562 files List of strings. All files modified, added, or removed by
1559 1563 this changeset.
1560 1564 files(pattern)
1561 1565 All files of the current changeset matching the pattern. See
1562 1566 'hg help patterns'.
1563 1567
1564 1568 Test section lookup by translated message
1565 1569
1566 1570 str.lower() instead of encoding.lower(str) on translated message might
1567 1571 make message meaningless, because some encoding uses 0x41(A) - 0x5a(Z)
1568 1572 as the second or later byte of multi-byte character.
1569 1573
1570 1574 For example, "\x8bL\x98^" (translation of "record" in ja_JP.cp932)
1571 1575 contains 0x4c (L). str.lower() replaces 0x4c(L) by 0x6c(l) and this
1572 1576 replacement makes message meaningless.
1573 1577
1574 1578 This tests that section lookup by translated string isn't broken by
1575 1579 such str.lower().
1576 1580
1577 1581 $ python <<EOF
1578 1582 > def escape(s):
1579 1583 > return ''.join('\u%x' % ord(uc) for uc in s.decode('cp932'))
1580 1584 > # translation of "record" in ja_JP.cp932
1581 1585 > upper = "\x8bL\x98^"
1582 1586 > # str.lower()-ed section name should be treated as different one
1583 1587 > lower = "\x8bl\x98^"
1584 1588 > with open('ambiguous.py', 'w') as fp:
1585 1589 > fp.write("""# ambiguous section names in ja_JP.cp932
1586 1590 > u'''summary of extension
1587 1591 >
1588 1592 > %s
1589 1593 > ----
1590 1594 >
1591 1595 > Upper name should show only this message
1592 1596 >
1593 1597 > %s
1594 1598 > ----
1595 1599 >
1596 1600 > Lower name should show only this message
1597 1601 >
1598 1602 > subsequent section
1599 1603 > ------------------
1600 1604 >
1601 1605 > This should be hidden at 'hg help ambiguous' with section name.
1602 1606 > '''
1603 1607 > """ % (escape(upper), escape(lower)))
1604 1608 > EOF
1605 1609
1606 1610 $ cat >> $HGRCPATH <<EOF
1607 1611 > [extensions]
1608 1612 > ambiguous = ./ambiguous.py
1609 1613 > EOF
1610 1614
1611 1615 $ python <<EOF | sh
1612 1616 > upper = "\x8bL\x98^"
1613 1617 > print "hg --encoding cp932 help -e ambiguous.%s" % upper
1614 1618 > EOF
1615 1619 \x8bL\x98^ (esc)
1616 1620 ----
1617 1621
1618 1622 Upper name should show only this message
1619 1623
1620 1624
1621 1625 $ python <<EOF | sh
1622 1626 > lower = "\x8bl\x98^"
1623 1627 > print "hg --encoding cp932 help -e ambiguous.%s" % lower
1624 1628 > EOF
1625 1629 \x8bl\x98^ (esc)
1626 1630 ----
1627 1631
1628 1632 Lower name should show only this message
1629 1633
1630 1634
1631 1635 $ cat >> $HGRCPATH <<EOF
1632 1636 > [extensions]
1633 1637 > ambiguous = !
1634 1638 > EOF
1635 1639
1636 1640 Show help content of disabled extensions
1637 1641
1638 1642 $ cat >> $HGRCPATH <<EOF
1639 1643 > [extensions]
1640 1644 > ambiguous = !./ambiguous.py
1641 1645 > EOF
1642 1646 $ hg help -e ambiguous
1643 1647 ambiguous extension - (no help text available)
1644 1648
1645 1649 (use 'hg help extensions' for information on enabling extensions)
1646 1650
1647 1651 Test dynamic list of merge tools only shows up once
1648 1652 $ hg help merge-tools
1649 1653 Merge Tools
1650 1654 """""""""""
1651 1655
1652 1656 To merge files Mercurial uses merge tools.
1653 1657
1654 1658 A merge tool combines two different versions of a file into a merged file.
1655 1659 Merge tools are given the two files and the greatest common ancestor of
1656 1660 the two file versions, so they can determine the changes made on both
1657 1661 branches.
1658 1662
1659 1663 Merge tools are used both for 'hg resolve', 'hg merge', 'hg update', 'hg
1660 1664 backout' and in several extensions.
1661 1665
1662 1666 Usually, the merge tool tries to automatically reconcile the files by
1663 1667 combining all non-overlapping changes that occurred separately in the two
1664 1668 different evolutions of the same initial base file. Furthermore, some
1665 1669 interactive merge programs make it easier to manually resolve conflicting
1666 1670 merges, either in a graphical way, or by inserting some conflict markers.
1667 1671 Mercurial does not include any interactive merge programs but relies on
1668 1672 external tools for that.
1669 1673
1670 1674 Available merge tools
1671 1675 =====================
1672 1676
1673 1677 External merge tools and their properties are configured in the merge-
1674 1678 tools configuration section - see hgrc(5) - but they can often just be
1675 1679 named by their executable.
1676 1680
1677 1681 A merge tool is generally usable if its executable can be found on the
1678 1682 system and if it can handle the merge. The executable is found if it is an
1679 1683 absolute or relative executable path or the name of an application in the
1680 1684 executable search path. The tool is assumed to be able to handle the merge
1681 1685 if it can handle symlinks if the file is a symlink, if it can handle
1682 1686 binary files if the file is binary, and if a GUI is available if the tool
1683 1687 requires a GUI.
1684 1688
1685 1689 There are some internal merge tools which can be used. The internal merge
1686 1690 tools are:
1687 1691
1688 1692 ":dump"
1689 1693 Creates three versions of the files to merge, containing the contents of
1690 1694 local, other and base. These files can then be used to perform a merge
1691 1695 manually. If the file to be merged is named "a.txt", these files will
1692 1696 accordingly be named "a.txt.local", "a.txt.other" and "a.txt.base" and
1693 1697 they will be placed in the same directory as "a.txt".
1694 1698
1695 1699 ":fail"
1696 1700 Rather than attempting to merge files that were modified on both
1697 1701 branches, it marks them as unresolved. The resolve command must be used
1698 1702 to resolve these conflicts.
1699 1703
1700 1704 ":local"
1701 1705 Uses the local 'p1()' version of files as the merged version.
1702 1706
1703 1707 ":merge"
1704 1708 Uses the internal non-interactive simple merge algorithm for merging
1705 1709 files. It will fail if there are any conflicts and leave markers in the
1706 1710 partially merged file. Markers will have two sections, one for each side
1707 1711 of merge.
1708 1712
1709 1713 ":merge-local"
1710 1714 Like :merge, but resolve all conflicts non-interactively in favor of the
1711 1715 local 'p1()' changes.
1712 1716
1713 1717 ":merge-other"
1714 1718 Like :merge, but resolve all conflicts non-interactively in favor of the
1715 1719 other 'p2()' changes.
1716 1720
1717 1721 ":merge3"
1718 1722 Uses the internal non-interactive simple merge algorithm for merging
1719 1723 files. It will fail if there are any conflicts and leave markers in the
1720 1724 partially merged file. Marker will have three sections, one from each
1721 1725 side of the merge and one for the base content.
1722 1726
1723 1727 ":other"
1724 1728 Uses the other 'p2()' version of files as the merged version.
1725 1729
1726 1730 ":prompt"
1727 1731 Asks the user which of the local 'p1()' or the other 'p2()' version to
1728 1732 keep as the merged version.
1729 1733
1730 1734 ":tagmerge"
1731 1735 Uses the internal tag merge algorithm (experimental).
1732 1736
1733 1737 ":union"
1734 1738 Uses the internal non-interactive simple merge algorithm for merging
1735 1739 files. It will use both left and right sides for conflict regions. No
1736 1740 markers are inserted.
1737 1741
1738 1742 Internal tools are always available and do not require a GUI but will by
1739 1743 default not handle symlinks or binary files.
1740 1744
1741 1745 Choosing a merge tool
1742 1746 =====================
1743 1747
1744 1748 Mercurial uses these rules when deciding which merge tool to use:
1745 1749
1746 1750 1. If a tool has been specified with the --tool option to merge or
1747 1751 resolve, it is used. If it is the name of a tool in the merge-tools
1748 1752 configuration, its configuration is used. Otherwise the specified tool
1749 1753 must be executable by the shell.
1750 1754 2. If the "HGMERGE" environment variable is present, its value is used and
1751 1755 must be executable by the shell.
1752 1756 3. If the filename of the file to be merged matches any of the patterns in
1753 1757 the merge-patterns configuration section, the first usable merge tool
1754 1758 corresponding to a matching pattern is used. Here, binary capabilities
1755 1759 of the merge tool are not considered.
1756 1760 4. If ui.merge is set it will be considered next. If the value is not the
1757 1761 name of a configured tool, the specified value is used and must be
1758 1762 executable by the shell. Otherwise the named tool is used if it is
1759 1763 usable.
1760 1764 5. If any usable merge tools are present in the merge-tools configuration
1761 1765 section, the one with the highest priority is used.
1762 1766 6. If a program named "hgmerge" can be found on the system, it is used -
1763 1767 but it will by default not be used for symlinks and binary files.
1764 1768 7. If the file to be merged is not binary and is not a symlink, then
1765 1769 internal ":merge" is used.
1766 1770 8. The merge of the file fails and must be resolved before commit.
1767 1771
1768 1772 Note:
1769 1773 After selecting a merge program, Mercurial will by default attempt to
1770 1774 merge the files using a simple merge algorithm first. Only if it
1771 1775 doesn't succeed because of conflicting changes Mercurial will actually
1772 1776 execute the merge program. Whether to use the simple merge algorithm
1773 1777 first can be controlled by the premerge setting of the merge tool.
1774 1778 Premerge is enabled by default unless the file is binary or a symlink.
1775 1779
1776 1780 See the merge-tools and ui sections of hgrc(5) for details on the
1777 1781 configuration of merge tools.
1778 1782
1779 1783 Test usage of section marks in help documents
1780 1784
1781 1785 $ cd "$TESTDIR"/../doc
1782 1786 $ python check-seclevel.py
1783 1787 $ cd $TESTTMP
1784 1788
1785 1789 #if serve
1786 1790
1787 1791 Test the help pages in hgweb.
1788 1792
1789 1793 Dish up an empty repo; serve it cold.
1790 1794
1791 1795 $ hg init "$TESTTMP/test"
1792 1796 $ hg serve -R "$TESTTMP/test" -n test -p $HGPORT -d --pid-file=hg.pid
1793 1797 $ cat hg.pid >> $DAEMON_PIDS
1794 1798
1795 1799 $ get-with-headers.py 127.0.0.1:$HGPORT "help"
1796 1800 200 Script output follows
1797 1801
1798 1802 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
1799 1803 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
1800 1804 <head>
1801 1805 <link rel="icon" href="/static/hgicon.png" type="image/png" />
1802 1806 <meta name="robots" content="index, nofollow" />
1803 1807 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
1804 1808 <script type="text/javascript" src="/static/mercurial.js"></script>
1805 1809
1806 1810 <title>Help: Index</title>
1807 1811 </head>
1808 1812 <body>
1809 1813
1810 1814 <div class="container">
1811 1815 <div class="menu">
1812 1816 <div class="logo">
1813 1817 <a href="https://mercurial-scm.org/">
1814 1818 <img src="/static/hglogo.png" alt="mercurial" /></a>
1815 1819 </div>
1816 1820 <ul>
1817 1821 <li><a href="/shortlog">log</a></li>
1818 1822 <li><a href="/graph">graph</a></li>
1819 1823 <li><a href="/tags">tags</a></li>
1820 1824 <li><a href="/bookmarks">bookmarks</a></li>
1821 1825 <li><a href="/branches">branches</a></li>
1822 1826 </ul>
1823 1827 <ul>
1824 1828 <li class="active">help</li>
1825 1829 </ul>
1826 1830 </div>
1827 1831
1828 1832 <div class="main">
1829 1833 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
1830 1834 <form class="search" action="/log">
1831 1835
1832 1836 <p><input name="rev" id="search1" type="text" size="30" /></p>
1833 1837 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
1834 1838 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
1835 1839 </form>
1836 1840 <table class="bigtable">
1837 1841 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
1838 1842
1839 1843 <tr><td>
1840 1844 <a href="/help/config">
1841 1845 config
1842 1846 </a>
1843 1847 </td><td>
1844 1848 Configuration Files
1845 1849 </td></tr>
1846 1850 <tr><td>
1847 1851 <a href="/help/dates">
1848 1852 dates
1849 1853 </a>
1850 1854 </td><td>
1851 1855 Date Formats
1852 1856 </td></tr>
1853 1857 <tr><td>
1854 1858 <a href="/help/diffs">
1855 1859 diffs
1856 1860 </a>
1857 1861 </td><td>
1858 1862 Diff Formats
1859 1863 </td></tr>
1860 1864 <tr><td>
1861 1865 <a href="/help/environment">
1862 1866 environment
1863 1867 </a>
1864 1868 </td><td>
1865 1869 Environment Variables
1866 1870 </td></tr>
1867 1871 <tr><td>
1868 1872 <a href="/help/extensions">
1869 1873 extensions
1870 1874 </a>
1871 1875 </td><td>
1872 1876 Using Additional Features
1873 1877 </td></tr>
1874 1878 <tr><td>
1875 1879 <a href="/help/filesets">
1876 1880 filesets
1877 1881 </a>
1878 1882 </td><td>
1879 1883 Specifying File Sets
1880 1884 </td></tr>
1881 1885 <tr><td>
1882 1886 <a href="/help/glossary">
1883 1887 glossary
1884 1888 </a>
1885 1889 </td><td>
1886 1890 Glossary
1887 1891 </td></tr>
1888 1892 <tr><td>
1889 1893 <a href="/help/hgignore">
1890 1894 hgignore
1891 1895 </a>
1892 1896 </td><td>
1893 1897 Syntax for Mercurial Ignore Files
1894 1898 </td></tr>
1895 1899 <tr><td>
1896 1900 <a href="/help/hgweb">
1897 1901 hgweb
1898 1902 </a>
1899 1903 </td><td>
1900 1904 Configuring hgweb
1901 1905 </td></tr>
1902 1906 <tr><td>
1903 1907 <a href="/help/internals">
1904 1908 internals
1905 1909 </a>
1906 1910 </td><td>
1907 1911 Technical implementation topics
1908 1912 </td></tr>
1909 1913 <tr><td>
1910 1914 <a href="/help/merge-tools">
1911 1915 merge-tools
1912 1916 </a>
1913 1917 </td><td>
1914 1918 Merge Tools
1915 1919 </td></tr>
1916 1920 <tr><td>
1917 1921 <a href="/help/patterns">
1918 1922 patterns
1919 1923 </a>
1920 1924 </td><td>
1921 1925 File Name Patterns
1922 1926 </td></tr>
1923 1927 <tr><td>
1924 1928 <a href="/help/phases">
1925 1929 phases
1926 1930 </a>
1927 1931 </td><td>
1928 1932 Working with Phases
1929 1933 </td></tr>
1930 1934 <tr><td>
1931 1935 <a href="/help/revisions">
1932 1936 revisions
1933 1937 </a>
1934 1938 </td><td>
1935 1939 Specifying Revisions
1936 1940 </td></tr>
1937 1941 <tr><td>
1938 1942 <a href="/help/scripting">
1939 1943 scripting
1940 1944 </a>
1941 1945 </td><td>
1942 1946 Using Mercurial from scripts and automation
1943 1947 </td></tr>
1944 1948 <tr><td>
1945 1949 <a href="/help/subrepos">
1946 1950 subrepos
1947 1951 </a>
1948 1952 </td><td>
1949 1953 Subrepositories
1950 1954 </td></tr>
1951 1955 <tr><td>
1952 1956 <a href="/help/templating">
1953 1957 templating
1954 1958 </a>
1955 1959 </td><td>
1956 1960 Template Usage
1957 1961 </td></tr>
1958 1962 <tr><td>
1959 1963 <a href="/help/urls">
1960 1964 urls
1961 1965 </a>
1962 1966 </td><td>
1963 1967 URL Paths
1964 1968 </td></tr>
1965 1969 <tr><td>
1966 1970 <a href="/help/topic-containing-verbose">
1967 1971 topic-containing-verbose
1968 1972 </a>
1969 1973 </td><td>
1970 1974 This is the topic to test omit indicating.
1971 1975 </td></tr>
1972 1976
1973 1977
1974 1978 <tr><td colspan="2"><h2><a name="main" href="#main">Main Commands</a></h2></td></tr>
1975 1979
1976 1980 <tr><td>
1977 1981 <a href="/help/add">
1978 1982 add
1979 1983 </a>
1980 1984 </td><td>
1981 1985 add the specified files on the next commit
1982 1986 </td></tr>
1983 1987 <tr><td>
1984 1988 <a href="/help/annotate">
1985 1989 annotate
1986 1990 </a>
1987 1991 </td><td>
1988 1992 show changeset information by line for each file
1989 1993 </td></tr>
1990 1994 <tr><td>
1991 1995 <a href="/help/clone">
1992 1996 clone
1993 1997 </a>
1994 1998 </td><td>
1995 1999 make a copy of an existing repository
1996 2000 </td></tr>
1997 2001 <tr><td>
1998 2002 <a href="/help/commit">
1999 2003 commit
2000 2004 </a>
2001 2005 </td><td>
2002 2006 commit the specified files or all outstanding changes
2003 2007 </td></tr>
2004 2008 <tr><td>
2005 2009 <a href="/help/diff">
2006 2010 diff
2007 2011 </a>
2008 2012 </td><td>
2009 2013 diff repository (or selected files)
2010 2014 </td></tr>
2011 2015 <tr><td>
2012 2016 <a href="/help/export">
2013 2017 export
2014 2018 </a>
2015 2019 </td><td>
2016 2020 dump the header and diffs for one or more changesets
2017 2021 </td></tr>
2018 2022 <tr><td>
2019 2023 <a href="/help/forget">
2020 2024 forget
2021 2025 </a>
2022 2026 </td><td>
2023 2027 forget the specified files on the next commit
2024 2028 </td></tr>
2025 2029 <tr><td>
2026 2030 <a href="/help/init">
2027 2031 init
2028 2032 </a>
2029 2033 </td><td>
2030 2034 create a new repository in the given directory
2031 2035 </td></tr>
2032 2036 <tr><td>
2033 2037 <a href="/help/log">
2034 2038 log
2035 2039 </a>
2036 2040 </td><td>
2037 2041 show revision history of entire repository or files
2038 2042 </td></tr>
2039 2043 <tr><td>
2040 2044 <a href="/help/merge">
2041 2045 merge
2042 2046 </a>
2043 2047 </td><td>
2044 2048 merge another revision into working directory
2045 2049 </td></tr>
2046 2050 <tr><td>
2047 2051 <a href="/help/pull">
2048 2052 pull
2049 2053 </a>
2050 2054 </td><td>
2051 2055 pull changes from the specified source
2052 2056 </td></tr>
2053 2057 <tr><td>
2054 2058 <a href="/help/push">
2055 2059 push
2056 2060 </a>
2057 2061 </td><td>
2058 2062 push changes to the specified destination
2059 2063 </td></tr>
2060 2064 <tr><td>
2061 2065 <a href="/help/remove">
2062 2066 remove
2063 2067 </a>
2064 2068 </td><td>
2065 2069 remove the specified files on the next commit
2066 2070 </td></tr>
2067 2071 <tr><td>
2068 2072 <a href="/help/serve">
2069 2073 serve
2070 2074 </a>
2071 2075 </td><td>
2072 2076 start stand-alone webserver
2073 2077 </td></tr>
2074 2078 <tr><td>
2075 2079 <a href="/help/status">
2076 2080 status
2077 2081 </a>
2078 2082 </td><td>
2079 2083 show changed files in the working directory
2080 2084 </td></tr>
2081 2085 <tr><td>
2082 2086 <a href="/help/summary">
2083 2087 summary
2084 2088 </a>
2085 2089 </td><td>
2086 2090 summarize working directory state
2087 2091 </td></tr>
2088 2092 <tr><td>
2089 2093 <a href="/help/update">
2090 2094 update
2091 2095 </a>
2092 2096 </td><td>
2093 2097 update working directory (or switch revisions)
2094 2098 </td></tr>
2095 2099
2096 2100
2097 2101
2098 2102 <tr><td colspan="2"><h2><a name="other" href="#other">Other Commands</a></h2></td></tr>
2099 2103
2100 2104 <tr><td>
2101 2105 <a href="/help/addremove">
2102 2106 addremove
2103 2107 </a>
2104 2108 </td><td>
2105 2109 add all new files, delete all missing files
2106 2110 </td></tr>
2107 2111 <tr><td>
2108 2112 <a href="/help/archive">
2109 2113 archive
2110 2114 </a>
2111 2115 </td><td>
2112 2116 create an unversioned archive of a repository revision
2113 2117 </td></tr>
2114 2118 <tr><td>
2115 2119 <a href="/help/backout">
2116 2120 backout
2117 2121 </a>
2118 2122 </td><td>
2119 2123 reverse effect of earlier changeset
2120 2124 </td></tr>
2121 2125 <tr><td>
2122 2126 <a href="/help/bisect">
2123 2127 bisect
2124 2128 </a>
2125 2129 </td><td>
2126 2130 subdivision search of changesets
2127 2131 </td></tr>
2128 2132 <tr><td>
2129 2133 <a href="/help/bookmarks">
2130 2134 bookmarks
2131 2135 </a>
2132 2136 </td><td>
2133 2137 create a new bookmark or list existing bookmarks
2134 2138 </td></tr>
2135 2139 <tr><td>
2136 2140 <a href="/help/branch">
2137 2141 branch
2138 2142 </a>
2139 2143 </td><td>
2140 2144 set or show the current branch name
2141 2145 </td></tr>
2142 2146 <tr><td>
2143 2147 <a href="/help/branches">
2144 2148 branches
2145 2149 </a>
2146 2150 </td><td>
2147 2151 list repository named branches
2148 2152 </td></tr>
2149 2153 <tr><td>
2150 2154 <a href="/help/bundle">
2151 2155 bundle
2152 2156 </a>
2153 2157 </td><td>
2154 2158 create a changegroup file
2155 2159 </td></tr>
2156 2160 <tr><td>
2157 2161 <a href="/help/cat">
2158 2162 cat
2159 2163 </a>
2160 2164 </td><td>
2161 2165 output the current or given revision of files
2162 2166 </td></tr>
2163 2167 <tr><td>
2164 2168 <a href="/help/config">
2165 2169 config
2166 2170 </a>
2167 2171 </td><td>
2168 2172 show combined config settings from all hgrc files
2169 2173 </td></tr>
2170 2174 <tr><td>
2171 2175 <a href="/help/copy">
2172 2176 copy
2173 2177 </a>
2174 2178 </td><td>
2175 2179 mark files as copied for the next commit
2176 2180 </td></tr>
2177 2181 <tr><td>
2178 2182 <a href="/help/files">
2179 2183 files
2180 2184 </a>
2181 2185 </td><td>
2182 2186 list tracked files
2183 2187 </td></tr>
2184 2188 <tr><td>
2185 2189 <a href="/help/graft">
2186 2190 graft
2187 2191 </a>
2188 2192 </td><td>
2189 2193 copy changes from other branches onto the current branch
2190 2194 </td></tr>
2191 2195 <tr><td>
2192 2196 <a href="/help/grep">
2193 2197 grep
2194 2198 </a>
2195 2199 </td><td>
2196 2200 search revision history for a pattern in specified files
2197 2201 </td></tr>
2198 2202 <tr><td>
2199 2203 <a href="/help/heads">
2200 2204 heads
2201 2205 </a>
2202 2206 </td><td>
2203 2207 show branch heads
2204 2208 </td></tr>
2205 2209 <tr><td>
2206 2210 <a href="/help/help">
2207 2211 help
2208 2212 </a>
2209 2213 </td><td>
2210 2214 show help for a given topic or a help overview
2211 2215 </td></tr>
2212 2216 <tr><td>
2213 2217 <a href="/help/hgalias">
2214 2218 hgalias
2215 2219 </a>
2216 2220 </td><td>
2217 2221 summarize working directory state
2218 2222 </td></tr>
2219 2223 <tr><td>
2220 2224 <a href="/help/identify">
2221 2225 identify
2222 2226 </a>
2223 2227 </td><td>
2224 2228 identify the working directory or specified revision
2225 2229 </td></tr>
2226 2230 <tr><td>
2227 2231 <a href="/help/import">
2228 2232 import
2229 2233 </a>
2230 2234 </td><td>
2231 2235 import an ordered set of patches
2232 2236 </td></tr>
2233 2237 <tr><td>
2234 2238 <a href="/help/incoming">
2235 2239 incoming
2236 2240 </a>
2237 2241 </td><td>
2238 2242 show new changesets found in source
2239 2243 </td></tr>
2240 2244 <tr><td>
2241 2245 <a href="/help/manifest">
2242 2246 manifest
2243 2247 </a>
2244 2248 </td><td>
2245 2249 output the current or given revision of the project manifest
2246 2250 </td></tr>
2247 2251 <tr><td>
2248 2252 <a href="/help/nohelp">
2249 2253 nohelp
2250 2254 </a>
2251 2255 </td><td>
2252 2256 (no help text available)
2253 2257 </td></tr>
2254 2258 <tr><td>
2255 2259 <a href="/help/outgoing">
2256 2260 outgoing
2257 2261 </a>
2258 2262 </td><td>
2259 2263 show changesets not found in the destination
2260 2264 </td></tr>
2261 2265 <tr><td>
2262 2266 <a href="/help/paths">
2263 2267 paths
2264 2268 </a>
2265 2269 </td><td>
2266 2270 show aliases for remote repositories
2267 2271 </td></tr>
2268 2272 <tr><td>
2269 2273 <a href="/help/phase">
2270 2274 phase
2271 2275 </a>
2272 2276 </td><td>
2273 2277 set or show the current phase name
2274 2278 </td></tr>
2275 2279 <tr><td>
2276 2280 <a href="/help/recover">
2277 2281 recover
2278 2282 </a>
2279 2283 </td><td>
2280 2284 roll back an interrupted transaction
2281 2285 </td></tr>
2282 2286 <tr><td>
2283 2287 <a href="/help/rename">
2284 2288 rename
2285 2289 </a>
2286 2290 </td><td>
2287 2291 rename files; equivalent of copy + remove
2288 2292 </td></tr>
2289 2293 <tr><td>
2290 2294 <a href="/help/resolve">
2291 2295 resolve
2292 2296 </a>
2293 2297 </td><td>
2294 2298 redo merges or set/view the merge status of files
2295 2299 </td></tr>
2296 2300 <tr><td>
2297 2301 <a href="/help/revert">
2298 2302 revert
2299 2303 </a>
2300 2304 </td><td>
2301 2305 restore files to their checkout state
2302 2306 </td></tr>
2303 2307 <tr><td>
2304 2308 <a href="/help/root">
2305 2309 root
2306 2310 </a>
2307 2311 </td><td>
2308 2312 print the root (top) of the current working directory
2309 2313 </td></tr>
2310 2314 <tr><td>
2311 2315 <a href="/help/shellalias">
2312 2316 shellalias
2313 2317 </a>
2314 2318 </td><td>
2315 2319 (no help text available)
2316 2320 </td></tr>
2317 2321 <tr><td>
2318 2322 <a href="/help/tag">
2319 2323 tag
2320 2324 </a>
2321 2325 </td><td>
2322 2326 add one or more tags for the current or given revision
2323 2327 </td></tr>
2324 2328 <tr><td>
2325 2329 <a href="/help/tags">
2326 2330 tags
2327 2331 </a>
2328 2332 </td><td>
2329 2333 list repository tags
2330 2334 </td></tr>
2331 2335 <tr><td>
2332 2336 <a href="/help/unbundle">
2333 2337 unbundle
2334 2338 </a>
2335 2339 </td><td>
2336 2340 apply one or more changegroup files
2337 2341 </td></tr>
2338 2342 <tr><td>
2339 2343 <a href="/help/verify">
2340 2344 verify
2341 2345 </a>
2342 2346 </td><td>
2343 2347 verify the integrity of the repository
2344 2348 </td></tr>
2345 2349 <tr><td>
2346 2350 <a href="/help/version">
2347 2351 version
2348 2352 </a>
2349 2353 </td><td>
2350 2354 output version and copyright information
2351 2355 </td></tr>
2352 2356
2353 2357
2354 2358 </table>
2355 2359 </div>
2356 2360 </div>
2357 2361
2358 2362
2359 2363
2360 2364 </body>
2361 2365 </html>
2362 2366
2363 2367
2364 2368 $ get-with-headers.py 127.0.0.1:$HGPORT "help/add"
2365 2369 200 Script output follows
2366 2370
2367 2371 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2368 2372 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2369 2373 <head>
2370 2374 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2371 2375 <meta name="robots" content="index, nofollow" />
2372 2376 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2373 2377 <script type="text/javascript" src="/static/mercurial.js"></script>
2374 2378
2375 2379 <title>Help: add</title>
2376 2380 </head>
2377 2381 <body>
2378 2382
2379 2383 <div class="container">
2380 2384 <div class="menu">
2381 2385 <div class="logo">
2382 2386 <a href="https://mercurial-scm.org/">
2383 2387 <img src="/static/hglogo.png" alt="mercurial" /></a>
2384 2388 </div>
2385 2389 <ul>
2386 2390 <li><a href="/shortlog">log</a></li>
2387 2391 <li><a href="/graph">graph</a></li>
2388 2392 <li><a href="/tags">tags</a></li>
2389 2393 <li><a href="/bookmarks">bookmarks</a></li>
2390 2394 <li><a href="/branches">branches</a></li>
2391 2395 </ul>
2392 2396 <ul>
2393 2397 <li class="active"><a href="/help">help</a></li>
2394 2398 </ul>
2395 2399 </div>
2396 2400
2397 2401 <div class="main">
2398 2402 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2399 2403 <h3>Help: add</h3>
2400 2404
2401 2405 <form class="search" action="/log">
2402 2406
2403 2407 <p><input name="rev" id="search1" type="text" size="30" /></p>
2404 2408 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2405 2409 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2406 2410 </form>
2407 2411 <div id="doc">
2408 2412 <p>
2409 2413 hg add [OPTION]... [FILE]...
2410 2414 </p>
2411 2415 <p>
2412 2416 add the specified files on the next commit
2413 2417 </p>
2414 2418 <p>
2415 2419 Schedule files to be version controlled and added to the
2416 2420 repository.
2417 2421 </p>
2418 2422 <p>
2419 2423 The files will be added to the repository at the next commit. To
2420 2424 undo an add before that, see 'hg forget'.
2421 2425 </p>
2422 2426 <p>
2423 2427 If no names are given, add all files to the repository (except
2424 2428 files matching &quot;.hgignore&quot;).
2425 2429 </p>
2426 2430 <p>
2427 2431 Examples:
2428 2432 </p>
2429 2433 <ul>
2430 2434 <li> New (unknown) files are added automatically by 'hg add':
2431 2435 <pre>
2432 2436 \$ ls (re)
2433 2437 foo.c
2434 2438 \$ hg status (re)
2435 2439 ? foo.c
2436 2440 \$ hg add (re)
2437 2441 adding foo.c
2438 2442 \$ hg status (re)
2439 2443 A foo.c
2440 2444 </pre>
2441 2445 <li> Specific files to be added can be specified:
2442 2446 <pre>
2443 2447 \$ ls (re)
2444 2448 bar.c foo.c
2445 2449 \$ hg status (re)
2446 2450 ? bar.c
2447 2451 ? foo.c
2448 2452 \$ hg add bar.c (re)
2449 2453 \$ hg status (re)
2450 2454 A bar.c
2451 2455 ? foo.c
2452 2456 </pre>
2453 2457 </ul>
2454 2458 <p>
2455 2459 Returns 0 if all files are successfully added.
2456 2460 </p>
2457 2461 <p>
2458 2462 options ([+] can be repeated):
2459 2463 </p>
2460 2464 <table>
2461 2465 <tr><td>-I</td>
2462 2466 <td>--include PATTERN [+]</td>
2463 2467 <td>include names matching the given patterns</td></tr>
2464 2468 <tr><td>-X</td>
2465 2469 <td>--exclude PATTERN [+]</td>
2466 2470 <td>exclude names matching the given patterns</td></tr>
2467 2471 <tr><td>-S</td>
2468 2472 <td>--subrepos</td>
2469 2473 <td>recurse into subrepositories</td></tr>
2470 2474 <tr><td>-n</td>
2471 2475 <td>--dry-run</td>
2472 2476 <td>do not perform actions, just print output</td></tr>
2473 2477 </table>
2474 2478 <p>
2475 2479 global options ([+] can be repeated):
2476 2480 </p>
2477 2481 <table>
2478 2482 <tr><td>-R</td>
2479 2483 <td>--repository REPO</td>
2480 2484 <td>repository root directory or name of overlay bundle file</td></tr>
2481 2485 <tr><td></td>
2482 2486 <td>--cwd DIR</td>
2483 2487 <td>change working directory</td></tr>
2484 2488 <tr><td>-y</td>
2485 2489 <td>--noninteractive</td>
2486 2490 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2487 2491 <tr><td>-q</td>
2488 2492 <td>--quiet</td>
2489 2493 <td>suppress output</td></tr>
2490 2494 <tr><td>-v</td>
2491 2495 <td>--verbose</td>
2492 2496 <td>enable additional output</td></tr>
2493 2497 <tr><td></td>
2494 2498 <td>--config CONFIG [+]</td>
2495 2499 <td>set/override config option (use 'section.name=value')</td></tr>
2496 2500 <tr><td></td>
2497 2501 <td>--debug</td>
2498 2502 <td>enable debugging output</td></tr>
2499 2503 <tr><td></td>
2500 2504 <td>--debugger</td>
2501 2505 <td>start debugger</td></tr>
2502 2506 <tr><td></td>
2503 2507 <td>--encoding ENCODE</td>
2504 2508 <td>set the charset encoding (default: ascii)</td></tr>
2505 2509 <tr><td></td>
2506 2510 <td>--encodingmode MODE</td>
2507 2511 <td>set the charset encoding mode (default: strict)</td></tr>
2508 2512 <tr><td></td>
2509 2513 <td>--traceback</td>
2510 2514 <td>always print a traceback on exception</td></tr>
2511 2515 <tr><td></td>
2512 2516 <td>--time</td>
2513 2517 <td>time how long the command takes</td></tr>
2514 2518 <tr><td></td>
2515 2519 <td>--profile</td>
2516 2520 <td>print command execution profile</td></tr>
2517 2521 <tr><td></td>
2518 2522 <td>--version</td>
2519 2523 <td>output version information and exit</td></tr>
2520 2524 <tr><td>-h</td>
2521 2525 <td>--help</td>
2522 2526 <td>display help and exit</td></tr>
2523 2527 <tr><td></td>
2524 2528 <td>--hidden</td>
2525 2529 <td>consider hidden changesets</td></tr>
2530 <tr><td></td>
2531 <td>--pager TYPE</td>
2532 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2526 2533 </table>
2527 2534
2528 2535 </div>
2529 2536 </div>
2530 2537 </div>
2531 2538
2532 2539
2533 2540
2534 2541 </body>
2535 2542 </html>
2536 2543
2537 2544
2538 2545 $ get-with-headers.py 127.0.0.1:$HGPORT "help/remove"
2539 2546 200 Script output follows
2540 2547
2541 2548 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2542 2549 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2543 2550 <head>
2544 2551 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2545 2552 <meta name="robots" content="index, nofollow" />
2546 2553 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2547 2554 <script type="text/javascript" src="/static/mercurial.js"></script>
2548 2555
2549 2556 <title>Help: remove</title>
2550 2557 </head>
2551 2558 <body>
2552 2559
2553 2560 <div class="container">
2554 2561 <div class="menu">
2555 2562 <div class="logo">
2556 2563 <a href="https://mercurial-scm.org/">
2557 2564 <img src="/static/hglogo.png" alt="mercurial" /></a>
2558 2565 </div>
2559 2566 <ul>
2560 2567 <li><a href="/shortlog">log</a></li>
2561 2568 <li><a href="/graph">graph</a></li>
2562 2569 <li><a href="/tags">tags</a></li>
2563 2570 <li><a href="/bookmarks">bookmarks</a></li>
2564 2571 <li><a href="/branches">branches</a></li>
2565 2572 </ul>
2566 2573 <ul>
2567 2574 <li class="active"><a href="/help">help</a></li>
2568 2575 </ul>
2569 2576 </div>
2570 2577
2571 2578 <div class="main">
2572 2579 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2573 2580 <h3>Help: remove</h3>
2574 2581
2575 2582 <form class="search" action="/log">
2576 2583
2577 2584 <p><input name="rev" id="search1" type="text" size="30" /></p>
2578 2585 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2579 2586 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2580 2587 </form>
2581 2588 <div id="doc">
2582 2589 <p>
2583 2590 hg remove [OPTION]... FILE...
2584 2591 </p>
2585 2592 <p>
2586 2593 aliases: rm
2587 2594 </p>
2588 2595 <p>
2589 2596 remove the specified files on the next commit
2590 2597 </p>
2591 2598 <p>
2592 2599 Schedule the indicated files for removal from the current branch.
2593 2600 </p>
2594 2601 <p>
2595 2602 This command schedules the files to be removed at the next commit.
2596 2603 To undo a remove before that, see 'hg revert'. To undo added
2597 2604 files, see 'hg forget'.
2598 2605 </p>
2599 2606 <p>
2600 2607 -A/--after can be used to remove only files that have already
2601 2608 been deleted, -f/--force can be used to force deletion, and -Af
2602 2609 can be used to remove files from the next revision without
2603 2610 deleting them from the working directory.
2604 2611 </p>
2605 2612 <p>
2606 2613 The following table details the behavior of remove for different
2607 2614 file states (columns) and option combinations (rows). The file
2608 2615 states are Added [A], Clean [C], Modified [M] and Missing [!]
2609 2616 (as reported by 'hg status'). The actions are Warn, Remove
2610 2617 (from branch) and Delete (from disk):
2611 2618 </p>
2612 2619 <table>
2613 2620 <tr><td>opt/state</td>
2614 2621 <td>A</td>
2615 2622 <td>C</td>
2616 2623 <td>M</td>
2617 2624 <td>!</td></tr>
2618 2625 <tr><td>none</td>
2619 2626 <td>W</td>
2620 2627 <td>RD</td>
2621 2628 <td>W</td>
2622 2629 <td>R</td></tr>
2623 2630 <tr><td>-f</td>
2624 2631 <td>R</td>
2625 2632 <td>RD</td>
2626 2633 <td>RD</td>
2627 2634 <td>R</td></tr>
2628 2635 <tr><td>-A</td>
2629 2636 <td>W</td>
2630 2637 <td>W</td>
2631 2638 <td>W</td>
2632 2639 <td>R</td></tr>
2633 2640 <tr><td>-Af</td>
2634 2641 <td>R</td>
2635 2642 <td>R</td>
2636 2643 <td>R</td>
2637 2644 <td>R</td></tr>
2638 2645 </table>
2639 2646 <p>
2640 2647 <b>Note:</b>
2641 2648 </p>
2642 2649 <p>
2643 2650 'hg remove' never deletes files in Added [A] state from the
2644 2651 working directory, not even if &quot;--force&quot; is specified.
2645 2652 </p>
2646 2653 <p>
2647 2654 Returns 0 on success, 1 if any warnings encountered.
2648 2655 </p>
2649 2656 <p>
2650 2657 options ([+] can be repeated):
2651 2658 </p>
2652 2659 <table>
2653 2660 <tr><td>-A</td>
2654 2661 <td>--after</td>
2655 2662 <td>record delete for missing files</td></tr>
2656 2663 <tr><td>-f</td>
2657 2664 <td>--force</td>
2658 2665 <td>forget added files, delete modified files</td></tr>
2659 2666 <tr><td>-S</td>
2660 2667 <td>--subrepos</td>
2661 2668 <td>recurse into subrepositories</td></tr>
2662 2669 <tr><td>-I</td>
2663 2670 <td>--include PATTERN [+]</td>
2664 2671 <td>include names matching the given patterns</td></tr>
2665 2672 <tr><td>-X</td>
2666 2673 <td>--exclude PATTERN [+]</td>
2667 2674 <td>exclude names matching the given patterns</td></tr>
2668 2675 </table>
2669 2676 <p>
2670 2677 global options ([+] can be repeated):
2671 2678 </p>
2672 2679 <table>
2673 2680 <tr><td>-R</td>
2674 2681 <td>--repository REPO</td>
2675 2682 <td>repository root directory or name of overlay bundle file</td></tr>
2676 2683 <tr><td></td>
2677 2684 <td>--cwd DIR</td>
2678 2685 <td>change working directory</td></tr>
2679 2686 <tr><td>-y</td>
2680 2687 <td>--noninteractive</td>
2681 2688 <td>do not prompt, automatically pick the first choice for all prompts</td></tr>
2682 2689 <tr><td>-q</td>
2683 2690 <td>--quiet</td>
2684 2691 <td>suppress output</td></tr>
2685 2692 <tr><td>-v</td>
2686 2693 <td>--verbose</td>
2687 2694 <td>enable additional output</td></tr>
2688 2695 <tr><td></td>
2689 2696 <td>--config CONFIG [+]</td>
2690 2697 <td>set/override config option (use 'section.name=value')</td></tr>
2691 2698 <tr><td></td>
2692 2699 <td>--debug</td>
2693 2700 <td>enable debugging output</td></tr>
2694 2701 <tr><td></td>
2695 2702 <td>--debugger</td>
2696 2703 <td>start debugger</td></tr>
2697 2704 <tr><td></td>
2698 2705 <td>--encoding ENCODE</td>
2699 2706 <td>set the charset encoding (default: ascii)</td></tr>
2700 2707 <tr><td></td>
2701 2708 <td>--encodingmode MODE</td>
2702 2709 <td>set the charset encoding mode (default: strict)</td></tr>
2703 2710 <tr><td></td>
2704 2711 <td>--traceback</td>
2705 2712 <td>always print a traceback on exception</td></tr>
2706 2713 <tr><td></td>
2707 2714 <td>--time</td>
2708 2715 <td>time how long the command takes</td></tr>
2709 2716 <tr><td></td>
2710 2717 <td>--profile</td>
2711 2718 <td>print command execution profile</td></tr>
2712 2719 <tr><td></td>
2713 2720 <td>--version</td>
2714 2721 <td>output version information and exit</td></tr>
2715 2722 <tr><td>-h</td>
2716 2723 <td>--help</td>
2717 2724 <td>display help and exit</td></tr>
2718 2725 <tr><td></td>
2719 2726 <td>--hidden</td>
2720 2727 <td>consider hidden changesets</td></tr>
2728 <tr><td></td>
2729 <td>--pager TYPE</td>
2730 <td>when to paginate (boolean, always, auto, or never) (default: auto)</td></tr>
2721 2731 </table>
2722 2732
2723 2733 </div>
2724 2734 </div>
2725 2735 </div>
2726 2736
2727 2737
2728 2738
2729 2739 </body>
2730 2740 </html>
2731 2741
2732 2742
2733 2743 $ get-with-headers.py 127.0.0.1:$HGPORT "help/dates"
2734 2744 200 Script output follows
2735 2745
2736 2746 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2737 2747 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2738 2748 <head>
2739 2749 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2740 2750 <meta name="robots" content="index, nofollow" />
2741 2751 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2742 2752 <script type="text/javascript" src="/static/mercurial.js"></script>
2743 2753
2744 2754 <title>Help: dates</title>
2745 2755 </head>
2746 2756 <body>
2747 2757
2748 2758 <div class="container">
2749 2759 <div class="menu">
2750 2760 <div class="logo">
2751 2761 <a href="https://mercurial-scm.org/">
2752 2762 <img src="/static/hglogo.png" alt="mercurial" /></a>
2753 2763 </div>
2754 2764 <ul>
2755 2765 <li><a href="/shortlog">log</a></li>
2756 2766 <li><a href="/graph">graph</a></li>
2757 2767 <li><a href="/tags">tags</a></li>
2758 2768 <li><a href="/bookmarks">bookmarks</a></li>
2759 2769 <li><a href="/branches">branches</a></li>
2760 2770 </ul>
2761 2771 <ul>
2762 2772 <li class="active"><a href="/help">help</a></li>
2763 2773 </ul>
2764 2774 </div>
2765 2775
2766 2776 <div class="main">
2767 2777 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2768 2778 <h3>Help: dates</h3>
2769 2779
2770 2780 <form class="search" action="/log">
2771 2781
2772 2782 <p><input name="rev" id="search1" type="text" size="30" /></p>
2773 2783 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2774 2784 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2775 2785 </form>
2776 2786 <div id="doc">
2777 2787 <h1>Date Formats</h1>
2778 2788 <p>
2779 2789 Some commands allow the user to specify a date, e.g.:
2780 2790 </p>
2781 2791 <ul>
2782 2792 <li> backout, commit, import, tag: Specify the commit date.
2783 2793 <li> log, revert, update: Select revision(s) by date.
2784 2794 </ul>
2785 2795 <p>
2786 2796 Many date formats are valid. Here are some examples:
2787 2797 </p>
2788 2798 <ul>
2789 2799 <li> &quot;Wed Dec 6 13:18:29 2006&quot; (local timezone assumed)
2790 2800 <li> &quot;Dec 6 13:18 -0600&quot; (year assumed, time offset provided)
2791 2801 <li> &quot;Dec 6 13:18 UTC&quot; (UTC and GMT are aliases for +0000)
2792 2802 <li> &quot;Dec 6&quot; (midnight)
2793 2803 <li> &quot;13:18&quot; (today assumed)
2794 2804 <li> &quot;3:39&quot; (3:39AM assumed)
2795 2805 <li> &quot;3:39pm&quot; (15:39)
2796 2806 <li> &quot;2006-12-06 13:18:29&quot; (ISO 8601 format)
2797 2807 <li> &quot;2006-12-6 13:18&quot;
2798 2808 <li> &quot;2006-12-6&quot;
2799 2809 <li> &quot;12-6&quot;
2800 2810 <li> &quot;12/6&quot;
2801 2811 <li> &quot;12/6/6&quot; (Dec 6 2006)
2802 2812 <li> &quot;today&quot; (midnight)
2803 2813 <li> &quot;yesterday&quot; (midnight)
2804 2814 <li> &quot;now&quot; - right now
2805 2815 </ul>
2806 2816 <p>
2807 2817 Lastly, there is Mercurial's internal format:
2808 2818 </p>
2809 2819 <ul>
2810 2820 <li> &quot;1165411109 0&quot; (Wed Dec 6 13:18:29 2006 UTC)
2811 2821 </ul>
2812 2822 <p>
2813 2823 This is the internal representation format for dates. The first number
2814 2824 is the number of seconds since the epoch (1970-01-01 00:00 UTC). The
2815 2825 second is the offset of the local timezone, in seconds west of UTC
2816 2826 (negative if the timezone is east of UTC).
2817 2827 </p>
2818 2828 <p>
2819 2829 The log command also accepts date ranges:
2820 2830 </p>
2821 2831 <ul>
2822 2832 <li> &quot;&lt;DATE&quot; - at or before a given date/time
2823 2833 <li> &quot;&gt;DATE&quot; - on or after a given date/time
2824 2834 <li> &quot;DATE to DATE&quot; - a date range, inclusive
2825 2835 <li> &quot;-DAYS&quot; - within a given number of days of today
2826 2836 </ul>
2827 2837
2828 2838 </div>
2829 2839 </div>
2830 2840 </div>
2831 2841
2832 2842
2833 2843
2834 2844 </body>
2835 2845 </html>
2836 2846
2837 2847
2838 2848 Sub-topic indexes rendered properly
2839 2849
2840 2850 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals"
2841 2851 200 Script output follows
2842 2852
2843 2853 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2844 2854 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2845 2855 <head>
2846 2856 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2847 2857 <meta name="robots" content="index, nofollow" />
2848 2858 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2849 2859 <script type="text/javascript" src="/static/mercurial.js"></script>
2850 2860
2851 2861 <title>Help: internals</title>
2852 2862 </head>
2853 2863 <body>
2854 2864
2855 2865 <div class="container">
2856 2866 <div class="menu">
2857 2867 <div class="logo">
2858 2868 <a href="https://mercurial-scm.org/">
2859 2869 <img src="/static/hglogo.png" alt="mercurial" /></a>
2860 2870 </div>
2861 2871 <ul>
2862 2872 <li><a href="/shortlog">log</a></li>
2863 2873 <li><a href="/graph">graph</a></li>
2864 2874 <li><a href="/tags">tags</a></li>
2865 2875 <li><a href="/bookmarks">bookmarks</a></li>
2866 2876 <li><a href="/branches">branches</a></li>
2867 2877 </ul>
2868 2878 <ul>
2869 2879 <li><a href="/help">help</a></li>
2870 2880 </ul>
2871 2881 </div>
2872 2882
2873 2883 <div class="main">
2874 2884 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2875 2885 <form class="search" action="/log">
2876 2886
2877 2887 <p><input name="rev" id="search1" type="text" size="30" /></p>
2878 2888 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2879 2889 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2880 2890 </form>
2881 2891 <table class="bigtable">
2882 2892 <tr><td colspan="2"><h2><a name="topics" href="#topics">Topics</a></h2></td></tr>
2883 2893
2884 2894 <tr><td>
2885 2895 <a href="/help/internals.bundles">
2886 2896 bundles
2887 2897 </a>
2888 2898 </td><td>
2889 2899 Bundles
2890 2900 </td></tr>
2891 2901 <tr><td>
2892 2902 <a href="/help/internals.changegroups">
2893 2903 changegroups
2894 2904 </a>
2895 2905 </td><td>
2896 2906 Changegroups
2897 2907 </td></tr>
2898 2908 <tr><td>
2899 2909 <a href="/help/internals.requirements">
2900 2910 requirements
2901 2911 </a>
2902 2912 </td><td>
2903 2913 Repository Requirements
2904 2914 </td></tr>
2905 2915 <tr><td>
2906 2916 <a href="/help/internals.revlogs">
2907 2917 revlogs
2908 2918 </a>
2909 2919 </td><td>
2910 2920 Revision Logs
2911 2921 </td></tr>
2912 2922 <tr><td>
2913 2923 <a href="/help/internals.wireprotocol">
2914 2924 wireprotocol
2915 2925 </a>
2916 2926 </td><td>
2917 2927 Wire Protocol
2918 2928 </td></tr>
2919 2929
2920 2930
2921 2931
2922 2932
2923 2933
2924 2934 </table>
2925 2935 </div>
2926 2936 </div>
2927 2937
2928 2938
2929 2939
2930 2940 </body>
2931 2941 </html>
2932 2942
2933 2943
2934 2944 Sub-topic topics rendered properly
2935 2945
2936 2946 $ get-with-headers.py 127.0.0.1:$HGPORT "help/internals.changegroups"
2937 2947 200 Script output follows
2938 2948
2939 2949 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
2940 2950 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
2941 2951 <head>
2942 2952 <link rel="icon" href="/static/hgicon.png" type="image/png" />
2943 2953 <meta name="robots" content="index, nofollow" />
2944 2954 <link rel="stylesheet" href="/static/style-paper.css" type="text/css" />
2945 2955 <script type="text/javascript" src="/static/mercurial.js"></script>
2946 2956
2947 2957 <title>Help: internals.changegroups</title>
2948 2958 </head>
2949 2959 <body>
2950 2960
2951 2961 <div class="container">
2952 2962 <div class="menu">
2953 2963 <div class="logo">
2954 2964 <a href="https://mercurial-scm.org/">
2955 2965 <img src="/static/hglogo.png" alt="mercurial" /></a>
2956 2966 </div>
2957 2967 <ul>
2958 2968 <li><a href="/shortlog">log</a></li>
2959 2969 <li><a href="/graph">graph</a></li>
2960 2970 <li><a href="/tags">tags</a></li>
2961 2971 <li><a href="/bookmarks">bookmarks</a></li>
2962 2972 <li><a href="/branches">branches</a></li>
2963 2973 </ul>
2964 2974 <ul>
2965 2975 <li class="active"><a href="/help">help</a></li>
2966 2976 </ul>
2967 2977 </div>
2968 2978
2969 2979 <div class="main">
2970 2980 <h2 class="breadcrumb"><a href="/">Mercurial</a> </h2>
2971 2981 <h3>Help: internals.changegroups</h3>
2972 2982
2973 2983 <form class="search" action="/log">
2974 2984
2975 2985 <p><input name="rev" id="search1" type="text" size="30" /></p>
2976 2986 <div id="hint">Find changesets by keywords (author, files, the commit message), revision
2977 2987 number or hash, or <a href="/help/revsets">revset expression</a>.</div>
2978 2988 </form>
2979 2989 <div id="doc">
2980 2990 <h1>Changegroups</h1>
2981 2991 <p>
2982 2992 Changegroups are representations of repository revlog data, specifically
2983 2993 the changelog, manifest, and filelogs.
2984 2994 </p>
2985 2995 <p>
2986 2996 There are 3 versions of changegroups: &quot;1&quot;, &quot;2&quot;, and &quot;3&quot;. From a
2987 2997 high-level, versions &quot;1&quot; and &quot;2&quot; are almost exactly the same, with
2988 2998 the only difference being a header on entries in the changeset
2989 2999 segment. Version &quot;3&quot; adds support for exchanging treemanifests and
2990 3000 includes revlog flags in the delta header.
2991 3001 </p>
2992 3002 <p>
2993 3003 Changegroups consists of 3 logical segments:
2994 3004 </p>
2995 3005 <pre>
2996 3006 +---------------------------------+
2997 3007 | | | |
2998 3008 | changeset | manifest | filelogs |
2999 3009 | | | |
3000 3010 +---------------------------------+
3001 3011 </pre>
3002 3012 <p>
3003 3013 The principle building block of each segment is a *chunk*. A *chunk*
3004 3014 is a framed piece of data:
3005 3015 </p>
3006 3016 <pre>
3007 3017 +---------------------------------------+
3008 3018 | | |
3009 3019 | length | data |
3010 3020 | (32 bits) | &lt;length&gt; bytes |
3011 3021 | | |
3012 3022 +---------------------------------------+
3013 3023 </pre>
3014 3024 <p>
3015 3025 Each chunk starts with a 32-bit big-endian signed integer indicating
3016 3026 the length of the raw data that follows.
3017 3027 </p>
3018 3028 <p>
3019 3029 There is a special case chunk that has 0 length (&quot;0x00000000&quot;). We
3020 3030 call this an *empty chunk*.
3021 3031 </p>
3022 3032 <h2>Delta Groups</h2>
3023 3033 <p>
3024 3034 A *delta group* expresses the content of a revlog as a series of deltas,
3025 3035 or patches against previous revisions.
3026 3036 </p>
3027 3037 <p>
3028 3038 Delta groups consist of 0 or more *chunks* followed by the *empty chunk*
3029 3039 to signal the end of the delta group:
3030 3040 </p>
3031 3041 <pre>
3032 3042 +------------------------------------------------------------------------+
3033 3043 | | | | | |
3034 3044 | chunk0 length | chunk0 data | chunk1 length | chunk1 data | 0x0 |
3035 3045 | (32 bits) | (various) | (32 bits) | (various) | (32 bits) |
3036 3046 | | | | | |
3037 3047 +------------------------------------------------------------+-----------+
3038 3048 </pre>
3039 3049 <p>
3040 3050 Each *chunk*'s data consists of the following:
3041 3051 </p>
3042 3052 <pre>
3043 3053 +-----------------------------------------+
3044 3054 | | | |
3045 3055 | delta header | mdiff header | delta |
3046 3056 | (various) | (12 bytes) | (various) |
3047 3057 | | | |
3048 3058 +-----------------------------------------+
3049 3059 </pre>
3050 3060 <p>
3051 3061 The *length* field is the byte length of the remaining 3 logical pieces
3052 3062 of data. The *delta* is a diff from an existing entry in the changelog.
3053 3063 </p>
3054 3064 <p>
3055 3065 The *delta header* is different between versions &quot;1&quot;, &quot;2&quot;, and
3056 3066 &quot;3&quot; of the changegroup format.
3057 3067 </p>
3058 3068 <p>
3059 3069 Version 1:
3060 3070 </p>
3061 3071 <pre>
3062 3072 +------------------------------------------------------+
3063 3073 | | | | |
3064 3074 | node | p1 node | p2 node | link node |
3065 3075 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3066 3076 | | | | |
3067 3077 +------------------------------------------------------+
3068 3078 </pre>
3069 3079 <p>
3070 3080 Version 2:
3071 3081 </p>
3072 3082 <pre>
3073 3083 +------------------------------------------------------------------+
3074 3084 | | | | | |
3075 3085 | node | p1 node | p2 node | base node | link node |
3076 3086 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) |
3077 3087 | | | | | |
3078 3088 +------------------------------------------------------------------+
3079 3089 </pre>
3080 3090 <p>
3081 3091 Version 3:
3082 3092 </p>
3083 3093 <pre>
3084 3094 +------------------------------------------------------------------------------+
3085 3095 | | | | | | |
3086 3096 | node | p1 node | p2 node | base node | link node | flags |
3087 3097 | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (20 bytes) | (2 bytes) |
3088 3098 | | | | | | |
3089 3099 +------------------------------------------------------------------------------+
3090 3100 </pre>
3091 3101 <p>
3092 3102 The *mdiff header* consists of 3 32-bit big-endian signed integers
3093 3103 describing offsets at which to apply the following delta content:
3094 3104 </p>
3095 3105 <pre>
3096 3106 +-------------------------------------+
3097 3107 | | | |
3098 3108 | offset | old length | new length |
3099 3109 | (32 bits) | (32 bits) | (32 bits) |
3100 3110 | | | |
3101 3111 +-------------------------------------+
3102 3112 </pre>
3103 3113 <p>
3104 3114 In version 1, the delta is always applied against the previous node from
3105 3115 the changegroup or the first parent if this is the first entry in the
3106 3116 changegroup.
3107 3117 </p>
3108 3118 <p>
3109 3119 In version 2, the delta base node is encoded in the entry in the
3110 3120 changegroup. This allows the delta to be expressed against any parent,
3111 3121 which can result in smaller deltas and more efficient encoding of data.
3112 3122 </p>
3113 3123 <h2>Changeset Segment</h2>
3114 3124 <p>
3115 3125 The *changeset segment* consists of a single *delta group* holding
3116 3126 changelog data. It is followed by an *empty chunk* to denote the
3117 3127 boundary to the *manifests segment*.
3118 3128 </p>
3119 3129 <h2>Manifest Segment</h2>
3120 3130 <p>
3121 3131 The *manifest segment* consists of a single *delta group* holding
3122 3132 manifest data. It is followed by an *empty chunk* to denote the boundary
3123 3133 to the *filelogs segment*.
3124 3134 </p>
3125 3135 <h2>Filelogs Segment</h2>
3126 3136 <p>
3127 3137 The *filelogs* segment consists of multiple sub-segments, each
3128 3138 corresponding to an individual file whose data is being described:
3129 3139 </p>
3130 3140 <pre>
3131 3141 +--------------------------------------+
3132 3142 | | | | |
3133 3143 | filelog0 | filelog1 | filelog2 | ... |
3134 3144 | | | | |
3135 3145 +--------------------------------------+
3136 3146 </pre>
3137 3147 <p>
3138 3148 In version &quot;3&quot; of the changegroup format, filelogs may include
3139 3149 directory logs when treemanifests are in use. directory logs are
3140 3150 identified by having a trailing '/' on their filename (see below).
3141 3151 </p>
3142 3152 <p>
3143 3153 The final filelog sub-segment is followed by an *empty chunk* to denote
3144 3154 the end of the segment and the overall changegroup.
3145 3155 </p>
3146 3156 <p>
3147 3157 Each filelog sub-segment consists of the following:
3148 3158 </p>
3149 3159 <pre>
3150 3160 +------------------------------------------+
3151 3161 | | | |
3152 3162 | filename size | filename | delta group |
3153 3163 | (32 bits) | (various) | (various) |
3154 3164 | | | |
3155 3165 +------------------------------------------+
3156 3166 </pre>
3157 3167 <p>
3158 3168 That is, a *chunk* consisting of the filename (not terminated or padded)
3159 3169 followed by N chunks constituting the *delta group* for this file.
3160 3170 </p>
3161 3171
3162 3172 </div>
3163 3173 </div>
3164 3174 </div>
3165 3175
3166 3176
3167 3177
3168 3178 </body>
3169 3179 </html>
3170 3180
3171 3181
3172 3182 $ killdaemons.py
3173 3183
3174 3184 #endif
General Comments 0
You need to be logged in to leave comments. Login now