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