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