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