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