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