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