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