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