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