##// END OF EJS Templates
import docstring from doc/hg.1.txt
Benoit Boissinot -
r1437:ea51d296 default
parent child Browse files
Show More
This diff has been collapsed as it changes many lines, (642 lines changed) Show them Hide them
@@ -1,2258 +1,2626
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")
13 13 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
14 14 demandload(globals(), "errno socket version struct atexit sets bz2")
15 15
16 16 class UnknownCommand(Exception):
17 17 """Exception raised if command is not in the command table."""
18 18
19 19 def filterfiles(filters, files):
20 20 l = [x for x in files if x in filters]
21 21
22 22 for t in filters:
23 23 if t and t[-1] != "/":
24 24 t += "/"
25 25 l += [x for x in files if x.startswith(t)]
26 26 return l
27 27
28 28 def relpath(repo, args):
29 29 cwd = repo.getcwd()
30 30 if cwd:
31 31 return [util.normpath(os.path.join(cwd, x)) for x in args]
32 32 return args
33 33
34 34 def matchpats(repo, cwd, pats=[], opts={}, head=''):
35 35 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
36 36 opts.get('exclude'), head)
37 37
38 38 def makewalk(repo, pats, opts, head=''):
39 39 cwd = repo.getcwd()
40 40 files, matchfn, anypats = matchpats(repo, cwd, pats, opts, head)
41 41 exact = dict(zip(files, files))
42 42 def walk():
43 43 for src, fn in repo.walk(files=files, match=matchfn):
44 44 yield src, fn, util.pathto(cwd, fn), fn in exact
45 45 return files, matchfn, walk()
46 46
47 47 def walk(repo, pats, opts, head=''):
48 48 files, matchfn, results = makewalk(repo, pats, opts, head)
49 49 for r in results:
50 50 yield r
51 51
52 52 def walkchangerevs(ui, repo, cwd, pats, opts):
53 53 '''Iterate over files and the revs they changed in.
54 54
55 55 Callers most commonly need to iterate backwards over the history
56 56 it is interested in. Doing so has awful (quadratic-looking)
57 57 performance, so we use iterators in a "windowed" way.
58 58
59 59 We walk a window of revisions in the desired order. Within the
60 60 window, we first walk forwards to gather data, then in the desired
61 61 order (usually backwards) to display it.
62 62
63 63 This function returns an (iterator, getchange) pair. The
64 64 getchange function returns the changelog entry for a numeric
65 65 revision. The iterator yields 3-tuples. They will be of one of
66 66 the following forms:
67 67
68 68 "window", incrementing, lastrev: stepping through a window,
69 69 positive if walking forwards through revs, last rev in the
70 70 sequence iterated over - use to reset state for the current window
71 71
72 72 "add", rev, fns: out-of-order traversal of the given file names
73 73 fns, which changed during revision rev - use to gather data for
74 74 possible display
75 75
76 76 "iter", rev, None: in-order traversal of the revs earlier iterated
77 77 over with "add" - use to display data'''
78 78
79 79 if repo.changelog.count() == 0:
80 80 return [], False
81 81
82 82 cwd = repo.getcwd()
83 83 if not pats and cwd:
84 84 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
85 85 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
86 86 files, matchfn, anypats = matchpats(repo, (pats and cwd) or '',
87 87 pats, opts)
88 88 revs = map(int, revrange(ui, repo, opts['rev'] or ['tip:0']))
89 89 wanted = {}
90 90 slowpath = anypats
91 91 window = 300
92 92 fncache = {}
93 93
94 94 chcache = {}
95 95 def getchange(rev):
96 96 ch = chcache.get(rev)
97 97 if ch is None:
98 98 chcache[rev] = ch = repo.changelog.read(repo.lookup(str(rev)))
99 99 return ch
100 100
101 101 if not slowpath and not files:
102 102 # No files, no patterns. Display all revs.
103 103 wanted = dict(zip(revs, revs))
104 104 if not slowpath:
105 105 # Only files, no patterns. Check the history of each file.
106 106 def filerevgen(filelog):
107 107 for i in xrange(filelog.count() - 1, -1, -window):
108 108 revs = []
109 109 for j in xrange(max(0, i - window), i + 1):
110 110 revs.append(filelog.linkrev(filelog.node(j)))
111 111 revs.reverse()
112 112 for rev in revs:
113 113 yield rev
114 114
115 115 minrev, maxrev = min(revs), max(revs)
116 116 for file in files:
117 117 filelog = repo.file(file)
118 118 # A zero count may be a directory or deleted file, so
119 119 # try to find matching entries on the slow path.
120 120 if filelog.count() == 0:
121 121 slowpath = True
122 122 break
123 123 for rev in filerevgen(filelog):
124 124 if rev <= maxrev:
125 125 if rev < minrev:
126 126 break
127 127 fncache.setdefault(rev, [])
128 128 fncache[rev].append(file)
129 129 wanted[rev] = 1
130 130 if slowpath:
131 131 # The slow path checks files modified in every changeset.
132 132 def changerevgen():
133 133 for i in xrange(repo.changelog.count() - 1, -1, -window):
134 134 for j in xrange(max(0, i - window), i + 1):
135 135 yield j, getchange(j)[3]
136 136
137 137 for rev, changefiles in changerevgen():
138 138 matches = filter(matchfn, changefiles)
139 139 if matches:
140 140 fncache[rev] = matches
141 141 wanted[rev] = 1
142 142
143 143 def iterate():
144 144 for i in xrange(0, len(revs), window):
145 145 yield 'window', revs[0] < revs[-1], revs[-1]
146 146 nrevs = [rev for rev in revs[i:min(i+window, len(revs))]
147 147 if rev in wanted]
148 148 srevs = list(nrevs)
149 149 srevs.sort()
150 150 for rev in srevs:
151 151 fns = fncache.get(rev) or filter(matchfn, getchange(rev)[3])
152 152 yield 'add', rev, fns
153 153 for rev in nrevs:
154 154 yield 'iter', rev, None
155 155 return iterate(), getchange
156 156
157 157 revrangesep = ':'
158 158
159 159 def revrange(ui, repo, revs, revlog=None):
160 160 """Yield revision as strings from a list of revision specifications."""
161 161 if revlog is None:
162 162 revlog = repo.changelog
163 163 revcount = revlog.count()
164 164 def fix(val, defval):
165 165 if not val:
166 166 return defval
167 167 try:
168 168 num = int(val)
169 169 if str(num) != val:
170 170 raise ValueError
171 171 if num < 0: num += revcount
172 172 if num < 0: num = 0
173 173 elif num >= revcount:
174 174 raise ValueError
175 175 except ValueError:
176 176 try:
177 177 num = repo.changelog.rev(repo.lookup(val))
178 178 except KeyError:
179 179 try:
180 180 num = revlog.rev(revlog.lookup(val))
181 181 except KeyError:
182 182 raise util.Abort(_('invalid revision identifier %s'), val)
183 183 return num
184 184 seen = {}
185 185 for spec in revs:
186 186 if spec.find(revrangesep) >= 0:
187 187 start, end = spec.split(revrangesep, 1)
188 188 start = fix(start, 0)
189 189 end = fix(end, revcount - 1)
190 190 step = start > end and -1 or 1
191 191 for rev in xrange(start, end+step, step):
192 192 if rev in seen: continue
193 193 seen[rev] = 1
194 194 yield str(rev)
195 195 else:
196 196 rev = fix(spec, None)
197 197 if rev in seen: continue
198 198 seen[rev] = 1
199 199 yield str(rev)
200 200
201 201 def make_filename(repo, r, pat, node=None,
202 202 total=None, seqno=None, revwidth=None, pathname=None):
203 203 node_expander = {
204 204 'H': lambda: hex(node),
205 205 'R': lambda: str(r.rev(node)),
206 206 'h': lambda: short(node),
207 207 }
208 208 expander = {
209 209 '%': lambda: '%',
210 210 'b': lambda: os.path.basename(repo.root),
211 211 }
212 212
213 213 try:
214 214 if node:
215 215 expander.update(node_expander)
216 216 if node and revwidth is not None:
217 217 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
218 218 if total is not None:
219 219 expander['N'] = lambda: str(total)
220 220 if seqno is not None:
221 221 expander['n'] = lambda: str(seqno)
222 222 if total is not None and seqno is not None:
223 223 expander['n'] = lambda:str(seqno).zfill(len(str(total)))
224 224 if pathname is not None:
225 225 expander['s'] = lambda: os.path.basename(pathname)
226 226 expander['d'] = lambda: os.path.dirname(pathname) or '.'
227 227 expander['p'] = lambda: pathname
228 228
229 229 newname = []
230 230 patlen = len(pat)
231 231 i = 0
232 232 while i < patlen:
233 233 c = pat[i]
234 234 if c == '%':
235 235 i += 1
236 236 c = pat[i]
237 237 c = expander[c]()
238 238 newname.append(c)
239 239 i += 1
240 240 return ''.join(newname)
241 241 except KeyError, inst:
242 242 raise util.Abort(_("invalid format spec '%%%s' in output file name"),
243 243 inst.args[0])
244 244
245 245 def make_file(repo, r, pat, node=None,
246 246 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
247 247 if not pat or pat == '-':
248 248 return 'w' in mode and sys.stdout or sys.stdin
249 249 if hasattr(pat, 'write') and 'w' in mode:
250 250 return pat
251 251 if hasattr(pat, 'read') and 'r' in mode:
252 252 return pat
253 253 return open(make_filename(repo, r, pat, node, total, seqno, revwidth,
254 254 pathname),
255 255 mode)
256 256
257 257 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
258 258 changes=None, text=False):
259 259 if not changes:
260 260 (c, a, d, u) = repo.changes(node1, node2, files, match=match)
261 261 else:
262 262 (c, a, d, u) = changes
263 263 if files:
264 264 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
265 265
266 266 if not c and not a and not d:
267 267 return
268 268
269 269 if node2:
270 270 change = repo.changelog.read(node2)
271 271 mmap2 = repo.manifest.read(change[0])
272 272 date2 = util.datestr(change[2])
273 273 def read(f):
274 274 return repo.file(f).read(mmap2[f])
275 275 else:
276 276 date2 = util.datestr()
277 277 if not node1:
278 278 node1 = repo.dirstate.parents()[0]
279 279 def read(f):
280 280 return repo.wfile(f).read()
281 281
282 282 if ui.quiet:
283 283 r = None
284 284 else:
285 285 hexfunc = ui.verbose and hex or short
286 286 r = [hexfunc(node) for node in [node1, node2] if node]
287 287
288 288 change = repo.changelog.read(node1)
289 289 mmap = repo.manifest.read(change[0])
290 290 date1 = util.datestr(change[2])
291 291
292 292 for f in c:
293 293 to = None
294 294 if f in mmap:
295 295 to = repo.file(f).read(mmap[f])
296 296 tn = read(f)
297 297 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text))
298 298 for f in a:
299 299 to = None
300 300 tn = read(f)
301 301 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text))
302 302 for f in d:
303 303 to = repo.file(f).read(mmap[f])
304 304 tn = None
305 305 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text))
306 306
307 307 def trimuser(ui, name, rev, revcache):
308 308 """trim the name of the user who committed a change"""
309 309 user = revcache.get(rev)
310 310 if user is None:
311 311 user = revcache[rev] = ui.shortuser(name)
312 312 return user
313 313
314 314 def show_changeset(ui, repo, rev=0, changenode=None, brinfo=None):
315 315 """show a single changeset or file revision"""
316 316 log = repo.changelog
317 317 if changenode is None:
318 318 changenode = log.node(rev)
319 319 elif not rev:
320 320 rev = log.rev(changenode)
321 321
322 322 if ui.quiet:
323 323 ui.write("%d:%s\n" % (rev, short(changenode)))
324 324 return
325 325
326 326 changes = log.read(changenode)
327 327 date = util.datestr(changes[2])
328 328
329 329 parents = [(log.rev(p), ui.verbose and hex(p) or short(p))
330 330 for p in log.parents(changenode)
331 331 if ui.debugflag or p != nullid]
332 332 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
333 333 parents = []
334 334
335 335 if ui.verbose:
336 336 ui.write(_("changeset: %d:%s\n") % (rev, hex(changenode)))
337 337 else:
338 338 ui.write(_("changeset: %d:%s\n") % (rev, short(changenode)))
339 339
340 340 for tag in repo.nodetags(changenode):
341 341 ui.status(_("tag: %s\n") % tag)
342 342 for parent in parents:
343 343 ui.write(_("parent: %d:%s\n") % parent)
344 344
345 345 if brinfo and changenode in brinfo:
346 346 br = brinfo[changenode]
347 347 ui.write(_("branch: %s\n") % " ".join(br))
348 348
349 349 ui.debug(_("manifest: %d:%s\n") % (repo.manifest.rev(changes[0]),
350 350 hex(changes[0])))
351 351 ui.status(_("user: %s\n") % changes[1])
352 352 ui.status(_("date: %s\n") % date)
353 353
354 354 if ui.debugflag:
355 355 files = repo.changes(log.parents(changenode)[0], changenode)
356 356 for key, value in zip([_("files:"), _("files+:"), _("files-:")], files):
357 357 if value:
358 358 ui.note("%-12s %s\n" % (key, " ".join(value)))
359 359 else:
360 360 ui.note(_("files: %s\n") % " ".join(changes[3]))
361 361
362 362 description = changes[4].strip()
363 363 if description:
364 364 if ui.verbose:
365 365 ui.status(_("description:\n"))
366 366 ui.status(description)
367 367 ui.status("\n\n")
368 368 else:
369 369 ui.status(_("summary: %s\n") % description.splitlines()[0])
370 370 ui.status("\n")
371 371
372 372 def show_version(ui):
373 373 """output version and copyright information"""
374 374 ui.write(_("Mercurial Distributed SCM (version %s)\n")
375 375 % version.get_version())
376 376 ui.status(_(
377 377 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
378 378 "This is free software; see the source for copying conditions. "
379 379 "There is NO\nwarranty; "
380 380 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
381 381 ))
382 382
383 383 def help_(ui, cmd=None, with_version=False):
384 384 """show help for a given command or all commands"""
385 385 option_lists = []
386 386 if cmd and cmd != 'shortlist':
387 387 if with_version:
388 388 show_version(ui)
389 389 ui.write('\n')
390 390 key, i = find(cmd)
391 391 # synopsis
392 392 ui.write("%s\n\n" % i[2])
393 393
394 394 # description
395 395 doc = i[0].__doc__
396 396 if ui.quiet:
397 397 doc = doc.splitlines(0)[0]
398 398 ui.write("%s\n" % doc.rstrip())
399 399
400 400 if not ui.quiet:
401 401 # aliases
402 402 aliases = ', '.join(key.split('|')[1:])
403 403 if aliases:
404 404 ui.write(_("\naliases: %s\n") % aliases)
405 405
406 406 # options
407 407 if i[1]:
408 408 option_lists.append(("options", i[1]))
409 409
410 410 else:
411 411 # program name
412 412 if ui.verbose or with_version:
413 413 show_version(ui)
414 414 else:
415 415 ui.status(_("Mercurial Distributed SCM\n"))
416 416 ui.status('\n')
417 417
418 418 # list of commands
419 419 if cmd == "shortlist":
420 420 ui.status(_('basic commands (use "hg help" '
421 421 'for the full list or option "-v" for details):\n\n'))
422 422 elif ui.verbose:
423 423 ui.status(_('list of commands:\n\n'))
424 424 else:
425 425 ui.status(_('list of commands (use "hg help -v" '
426 426 'to show aliases and global options):\n\n'))
427 427
428 428 h = {}
429 429 cmds = {}
430 430 for c, e in table.items():
431 431 f = c.split("|")[0]
432 432 if cmd == "shortlist" and not f.startswith("^"):
433 433 continue
434 434 f = f.lstrip("^")
435 435 if not ui.debugflag and f.startswith("debug"):
436 436 continue
437 437 d = ""
438 438 if e[0].__doc__:
439 439 d = e[0].__doc__.splitlines(0)[0].rstrip()
440 440 h[f] = d
441 441 cmds[f]=c.lstrip("^")
442 442
443 443 fns = h.keys()
444 444 fns.sort()
445 445 m = max(map(len, fns))
446 446 for f in fns:
447 447 if ui.verbose:
448 448 commands = cmds[f].replace("|",", ")
449 449 ui.write(" %s:\n %s\n"%(commands,h[f]))
450 450 else:
451 451 ui.write(' %-*s %s\n' % (m, f, h[f]))
452 452
453 453 # global options
454 454 if ui.verbose:
455 455 option_lists.append(("global options", globalopts))
456 456
457 457 # list all option lists
458 458 opt_output = []
459 459 for title, options in option_lists:
460 460 opt_output.append(("\n%s:\n" % title, None))
461 461 for shortopt, longopt, default, desc in options:
462 462 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
463 463 longopt and " --%s" % longopt),
464 464 "%s%s" % (desc,
465 465 default and _(" (default: %s)") % default
466 466 or "")))
467 467
468 468 if opt_output:
469 469 opts_len = max([len(line[0]) for line in opt_output if line[1]])
470 470 for first, second in opt_output:
471 471 if second:
472 472 ui.write(" %-*s %s\n" % (opts_len, first, second))
473 473 else:
474 474 ui.write("%s\n" % first)
475 475
476 476 # Commands start here, listed alphabetically
477 477
478 478 def add(ui, repo, *pats, **opts):
479 '''add the specified files on the next commit'''
479 """add the specified files on the next commit
480
481 Schedule files to be version controlled and added to the repository.
482
483 The files will be added to the repository at the next commit.
484
485 If no names are given, add all files in the current directory and
486 its subdirectories.
487 """
488
480 489 names = []
481 490 for src, abs, rel, exact in walk(repo, pats, opts):
482 491 if exact:
483 492 if ui.verbose: ui.status(_('adding %s\n') % rel)
484 493 names.append(abs)
485 494 elif repo.dirstate.state(abs) == '?':
486 495 ui.status(_('adding %s\n') % rel)
487 496 names.append(abs)
488 497 repo.add(names)
489 498
490 499 def addremove(ui, repo, *pats, **opts):
491 """add all new files, delete all missing files"""
500 """add all new files, delete all missing files
501
502 Add all new files and remove all missing files from the repository.
503
504 New files are ignored if they match any of the patterns in .hgignore. As
505 with add, these changes take effect at the next commit.
506 """
492 507 add, remove = [], []
493 508 for src, abs, rel, exact in walk(repo, pats, opts):
494 509 if src == 'f' and repo.dirstate.state(abs) == '?':
495 510 add.append(abs)
496 511 if ui.verbose or not exact:
497 512 ui.status(_('adding %s\n') % rel)
498 513 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
499 514 remove.append(abs)
500 515 if ui.verbose or not exact:
501 516 ui.status(_('removing %s\n') % rel)
502 517 repo.add(add)
503 518 repo.remove(remove)
504 519
505 520 def annotate(ui, repo, *pats, **opts):
506 """show changeset information per file line"""
521 """show changeset information per file line
522
523 List changes in files, showing the revision id responsible for each line
524
525 This command is useful to discover who did a change or when a change took
526 place.
527
528 Without the -a option, annotate will avoid processing files it
529 detects as binary. With -a, annotate will generate an annotation
530 anyway, probably with undesirable results.
531 """
507 532 def getnode(rev):
508 533 return short(repo.changelog.node(rev))
509 534
510 535 ucache = {}
511 536 def getname(rev):
512 537 cl = repo.changelog.read(repo.changelog.node(rev))
513 538 return trimuser(ui, cl[1], rev, ucache)
514 539
515 540 if not pats:
516 541 raise util.Abort(_('at least one file name or pattern required'))
517 542
518 543 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
519 544 if not opts['user'] and not opts['changeset']:
520 545 opts['number'] = 1
521 546
522 547 if opts['rev']:
523 548 node = repo.changelog.lookup(opts['rev'])
524 549 else:
525 550 node = repo.dirstate.parents()[0]
526 551 change = repo.changelog.read(node)
527 552 mmap = repo.manifest.read(change[0])
528 553
529 554 for src, abs, rel, exact in walk(repo, pats, opts):
530 555 if abs not in mmap:
531 556 ui.warn(_("warning: %s is not in the repository!\n") % rel)
532 557 continue
533 558
534 559 f = repo.file(abs)
535 560 if not opts['text'] and util.binary(f.read(mmap[abs])):
536 561 ui.write(_("%s: binary file\n") % rel)
537 562 continue
538 563
539 564 lines = f.annotate(mmap[abs])
540 565 pieces = []
541 566
542 567 for o, f in opmap:
543 568 if opts[o]:
544 569 l = [f(n) for n, dummy in lines]
545 570 if l:
546 571 m = max(map(len, l))
547 572 pieces.append(["%*s" % (m, x) for x in l])
548 573
549 574 if pieces:
550 575 for p, l in zip(zip(*pieces), lines):
551 576 ui.write("%s: %s" % (" ".join(p), l[1]))
552 577
553 578 def bundle(ui, repo, fname, dest="default-push", **opts):
554 """create a changegroup file"""
579 """create a changegroup file
580
581 Generate a compressed changegroup file collecting all changesets
582 not found in the other repository.
583
584 This file can then be transferred using conventional means and
585 applied to another repository with the unbundle command. This is
586 useful when native push and pull are not available or when
587 exporting an entire repository is undesirable. The standard file
588 extension is ".hg".
589
590 Unlike import/export, this exactly preserves all changeset
591 contents including permissions, rename data, and revision history.
592 """
555 593 f = open(fname, "wb")
556 594 dest = ui.expandpath(dest)
557 595 other = hg.repository(ui, dest)
558 596 o = repo.findoutgoing(other)
559 597 cg = repo.changegroup(o)
560 598
561 599 try:
562 600 f.write("HG10")
563 601 z = bz2.BZ2Compressor(9)
564 602 while 1:
565 603 chunk = cg.read(4096)
566 604 if not chunk:
567 605 break
568 606 f.write(z.compress(chunk))
569 607 f.write(z.flush())
570 608 except:
571 609 os.unlink(fname)
572 610 raise
573 611
574 612 def cat(ui, repo, file1, *pats, **opts):
575 """output the latest or given revisions of files"""
613 """output the latest or given revisions of files
614
615 Print the specified files as they were at the given revision.
616 If no revision is given then the tip is used.
617
618 Output may be to a file, in which case the name of the file is
619 given using a format string. The formatting rules are the same as
620 for the export command, with the following additions:
621
622 %s basename of file being printed
623 %d dirname of file being printed, or '.' if in repo root
624 %p root-relative path name of file being printed
625 """
576 626 mf = {}
577 627 if opts['rev']:
578 628 change = repo.changelog.read(repo.lookup(opts['rev']))
579 629 mf = repo.manifest.read(change[0])
580 630 for src, abs, rel, exact in walk(repo, (file1,) + pats, opts):
581 631 r = repo.file(abs)
582 632 if opts['rev']:
583 633 try:
584 634 n = mf[abs]
585 635 except (hg.RepoError, KeyError):
586 636 try:
587 637 n = r.lookup(rev)
588 638 except KeyError, inst:
589 639 raise util.Abort(_('cannot find file %s in rev %s'), rel, rev)
590 640 else:
591 641 n = r.tip()
592 642 fp = make_file(repo, r, opts['output'], node=n, pathname=abs)
593 643 fp.write(r.read(n))
594 644
595 645 def clone(ui, source, dest=None, **opts):
596 """make a copy of an existing repository"""
646 """make a copy of an existing repository
647
648 Create a copy of an existing repository in a new directory.
649
650 If no destination directory name is specified, it defaults to the
651 basename of the source.
652
653 The location of the source is added to the new repository's
654 .hg/hgrc file, as the default to be used for future pulls.
655
656 For efficiency, hardlinks are used for cloning whenever the source
657 and destination are on the same filesystem. Some filesystems,
658 such as AFS, implement hardlinking incorrectly, but do not report
659 errors. In these cases, use the --pull option to avoid
660 hardlinking.
661 """
597 662 if dest is None:
598 663 dest = os.path.basename(os.path.normpath(source))
599 664
600 665 if os.path.exists(dest):
601 666 raise util.Abort(_("destination '%s' already exists"), dest)
602 667
603 668 dest = os.path.realpath(dest)
604 669
605 670 class Dircleanup:
606 671 def __init__(self, dir_):
607 672 self.rmtree = shutil.rmtree
608 673 self.dir_ = dir_
609 674 os.mkdir(dir_)
610 675 def close(self):
611 676 self.dir_ = None
612 677 def __del__(self):
613 678 if self.dir_:
614 679 self.rmtree(self.dir_, True)
615 680
616 681 if opts['ssh']:
617 682 ui.setconfig("ui", "ssh", opts['ssh'])
618 683 if opts['remotecmd']:
619 684 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
620 685
621 686 if not os.path.exists(source):
622 687 source = ui.expandpath(source)
623 688
624 689 d = Dircleanup(dest)
625 690 abspath = source
626 691 other = hg.repository(ui, source)
627 692
628 693 copy = False
629 694 if other.dev() != -1:
630 695 abspath = os.path.abspath(source)
631 696 if not opts['pull']:
632 697 copy = True
633 698
634 699 if copy:
635 700 try:
636 701 # we use a lock here because if we race with commit, we
637 702 # can end up with extra data in the cloned revlogs that's
638 703 # not pointed to by changesets, thus causing verify to
639 704 # fail
640 705 l1 = lock.lock(os.path.join(source, ".hg", "lock"))
641 706 except OSError:
642 707 copy = False
643 708
644 709 if copy:
645 710 # we lock here to avoid premature writing to the target
646 711 os.mkdir(os.path.join(dest, ".hg"))
647 712 l2 = lock.lock(os.path.join(dest, ".hg", "lock"))
648 713
649 714 files = "data 00manifest.d 00manifest.i 00changelog.d 00changelog.i"
650 715 for f in files.split():
651 716 src = os.path.join(source, ".hg", f)
652 717 dst = os.path.join(dest, ".hg", f)
653 718 util.copyfiles(src, dst)
654 719
655 720 repo = hg.repository(ui, dest)
656 721
657 722 else:
658 723 repo = hg.repository(ui, dest, create=1)
659 724 repo.pull(other)
660 725
661 726 f = repo.opener("hgrc", "w", text=True)
662 727 f.write("[paths]\n")
663 728 f.write("default = %s\n" % abspath)
664 729
665 730 if not opts['noupdate']:
666 731 update(ui, repo)
667 732
668 733 d.close()
669 734
670 735 def commit(ui, repo, *pats, **opts):
671 """commit the specified files or all outstanding changes"""
736 """commit the specified files or all outstanding changes
737
738 Commit changes to the given files into the repository.
739
740 If a list of files is omitted, all changes reported by "hg status"
741 from the root of the repository will be commited.
742
743 The HGEDITOR or EDITOR environment variables are used to start an
744 editor to add a commit comment.
745 """
672 746 if opts['text']:
673 747 ui.warn(_("Warning: -t and --text is deprecated,"
674 748 " please use -m or --message instead.\n"))
675 749 message = opts['message'] or opts['text']
676 750 logfile = opts['logfile']
677 751
678 752 if message and logfile:
679 753 raise util.Abort(_('options --message and --logfile are mutually '
680 754 'exclusive'))
681 755 if not message and logfile:
682 756 try:
683 757 if logfile == '-':
684 758 message = sys.stdin.read()
685 759 else:
686 760 message = open(logfile).read()
687 761 except IOError, inst:
688 762 raise util.Abort(_("can't read commit message '%s': %s") %
689 763 (logfile, inst.strerror))
690 764
691 765 if opts['addremove']:
692 766 addremove(ui, repo, *pats, **opts)
693 767 cwd = repo.getcwd()
694 768 if not pats and cwd:
695 769 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
696 770 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
697 771 fns, match, anypats = matchpats(repo, (pats and repo.getcwd()) or '',
698 772 pats, opts)
699 773 if pats:
700 774 c, a, d, u = repo.changes(files=fns, match=match)
701 775 files = c + a + [fn for fn in d if repo.dirstate.state(fn) == 'r']
702 776 else:
703 777 files = []
704 778 try:
705 779 repo.commit(files, message, opts['user'], opts['date'], match)
706 780 except ValueError, inst:
707 781 raise util.Abort(str(inst))
708 782
709 783 def docopy(ui, repo, pats, opts):
710 784 if not pats:
711 785 raise util.Abort(_('no source or destination specified'))
712 786 elif len(pats) == 1:
713 787 raise util.Abort(_('no destination specified'))
714 788 pats = list(pats)
715 789 dest = pats.pop()
716 790 sources = []
717 791
718 792 def okaytocopy(abs, rel, exact):
719 793 reasons = {'?': _('is not managed'),
720 794 'a': _('has been marked for add')}
721 795 reason = reasons.get(repo.dirstate.state(abs))
722 796 if reason:
723 797 if exact: ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
724 798 else:
725 799 return True
726 800
727 801 for src, abs, rel, exact in walk(repo, pats, opts):
728 802 if okaytocopy(abs, rel, exact):
729 803 sources.append((abs, rel, exact))
730 804 if not sources:
731 805 raise util.Abort(_('no files to copy'))
732 806
733 807 cwd = repo.getcwd()
734 808 absdest = util.canonpath(repo.root, cwd, dest)
735 809 reldest = util.pathto(cwd, absdest)
736 810 if os.path.exists(reldest):
737 811 destisfile = not os.path.isdir(reldest)
738 812 else:
739 813 destisfile = len(sources) == 1 or repo.dirstate.state(absdest) != '?'
740 814
741 815 if destisfile:
742 816 if opts['parents']:
743 817 raise util.Abort(_('with --parents, destination must be a directory'))
744 818 elif len(sources) > 1:
745 819 raise util.Abort(_('with multiple sources, destination must be a '
746 820 'directory'))
747 821 errs, copied = 0, []
748 822 for abs, rel, exact in sources:
749 823 if opts['parents']:
750 824 mydest = os.path.join(dest, rel)
751 825 elif destisfile:
752 826 mydest = reldest
753 827 else:
754 828 mydest = os.path.join(dest, os.path.basename(rel))
755 829 myabsdest = util.canonpath(repo.root, cwd, mydest)
756 830 myreldest = util.pathto(cwd, myabsdest)
757 831 if not opts['force'] and repo.dirstate.state(myabsdest) not in 'a?':
758 832 ui.warn(_('%s: not overwriting - file already managed\n') % myreldest)
759 833 continue
760 834 mydestdir = os.path.dirname(myreldest) or '.'
761 835 if not opts['after']:
762 836 try:
763 837 if opts['parents']: os.makedirs(mydestdir)
764 838 elif not destisfile: os.mkdir(mydestdir)
765 839 except OSError, inst:
766 840 if inst.errno != errno.EEXIST: raise
767 841 if ui.verbose or not exact:
768 842 ui.status(_('copying %s to %s\n') % (rel, myreldest))
769 843 if not opts['after']:
770 844 try:
771 845 shutil.copyfile(rel, myreldest)
772 846 shutil.copymode(rel, myreldest)
773 847 except shutil.Error, inst:
774 848 raise util.Abort(str(inst))
775 849 except IOError, inst:
776 850 if inst.errno == errno.ENOENT:
777 851 ui.warn(_('%s: deleted in working copy\n') % rel)
778 852 else:
779 853 ui.warn(_('%s: cannot copy - %s\n') % (rel, inst.strerror))
780 854 errs += 1
781 855 continue
782 856 repo.copy(abs, myabsdest)
783 857 copied.append((abs, rel, exact))
784 858 if errs:
785 859 ui.warn(_('(consider using --after)\n'))
786 860 return errs, copied
787 861
788 862 def copy(ui, repo, *pats, **opts):
789 """mark files as copied for the next commit"""
863 """mark files as copied for the next commit
864
865 Mark dest as having copies of source files. If dest is a
866 directory, copies are put in that directory. If dest is a file,
867 there can only be one source.
868
869 By default, this command copies the contents of files as they
870 stand in the working directory. If invoked with --after, the
871 operation is recorded, but no copying is performed.
872
873 This command takes effect in the next commit.
874
875 NOTE: This command should be treated as experimental. While it
876 should properly record copied files, this information is not yet
877 fully used by merge, nor fully reported by log.
878 """
790 879 errs, copied = docopy(ui, repo, pats, opts)
791 880 return errs
792 881
793 882 def debugancestor(ui, index, rev1, rev2):
794 883 """find the ancestor revision of two revisions in a given index"""
795 884 r = revlog.revlog(file, index, "")
796 885 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
797 886 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
798 887
799 888 def debugcheckstate(ui, repo):
800 889 """validate the correctness of the current dirstate"""
801 890 parent1, parent2 = repo.dirstate.parents()
802 891 repo.dirstate.read()
803 892 dc = repo.dirstate.map
804 893 keys = dc.keys()
805 894 keys.sort()
806 895 m1n = repo.changelog.read(parent1)[0]
807 896 m2n = repo.changelog.read(parent2)[0]
808 897 m1 = repo.manifest.read(m1n)
809 898 m2 = repo.manifest.read(m2n)
810 899 errors = 0
811 900 for f in dc:
812 901 state = repo.dirstate.state(f)
813 902 if state in "nr" and f not in m1:
814 903 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
815 904 errors += 1
816 905 if state in "a" and f in m1:
817 906 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
818 907 errors += 1
819 908 if state in "m" and f not in m1 and f not in m2:
820 909 ui.warn(_("%s in state %s, but not in either manifest\n") %
821 910 (f, state))
822 911 errors += 1
823 912 for f in m1:
824 913 state = repo.dirstate.state(f)
825 914 if state not in "nrm":
826 915 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
827 916 errors += 1
828 917 if errors:
829 918 raise util.Abort(_(".hg/dirstate inconsistent with current parent's manifest"))
830 919
831 920 def debugconfig(ui):
832 921 """show combined config settings from all hgrc files"""
833 922 try:
834 923 repo = hg.repository(ui)
835 924 except hg.RepoError:
836 925 pass
837 926 for section, name, value in ui.walkconfig():
838 927 ui.write('%s.%s=%s\n' % (section, name, value))
839 928
840 929 def debugsetparents(ui, repo, rev1, rev2=None):
841 930 """
842 931 manually set the parents of the current working directory
843 932
844 933 This is useful for writing repository conversion tools, but should
845 934 be used with care.
846 935 """
847 936
848 937 if not rev2:
849 938 rev2 = hex(nullid)
850 939
851 940 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
852 941
853 942 def debugstate(ui, repo):
854 943 """show the contents of the current dirstate"""
855 944 repo.dirstate.read()
856 945 dc = repo.dirstate.map
857 946 keys = dc.keys()
858 947 keys.sort()
859 948 for file_ in keys:
860 949 ui.write("%c %3o %10d %s %s\n"
861 950 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
862 951 time.strftime("%x %X",
863 952 time.localtime(dc[file_][3])), file_))
864 953 for f in repo.dirstate.copies:
865 954 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copies[f], f))
866 955
867 956 def debugdata(ui, file_, rev):
868 957 """dump the contents of an data file revision"""
869 958 r = revlog.revlog(file, file_[:-2] + ".i", file_)
870 959 try:
871 960 ui.write(r.revision(r.lookup(rev)))
872 961 except KeyError:
873 962 raise util.Abort(_('invalid revision identifier %s'), rev)
874 963
875 964 def debugindex(ui, file_):
876 965 """dump the contents of an index file"""
877 966 r = revlog.revlog(file, file_, "")
878 967 ui.write(" rev offset length base linkrev" +
879 968 " nodeid p1 p2\n")
880 969 for i in range(r.count()):
881 970 e = r.index[i]
882 971 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
883 972 i, e[0], e[1], e[2], e[3],
884 973 short(e[6]), short(e[4]), short(e[5])))
885 974
886 975 def debugindexdot(ui, file_):
887 976 """dump an index DAG as a .dot file"""
888 977 r = revlog.revlog(file, file_, "")
889 978 ui.write("digraph G {\n")
890 979 for i in range(r.count()):
891 980 e = r.index[i]
892 981 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
893 982 if e[5] != nullid:
894 983 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
895 984 ui.write("}\n")
896 985
897 986 def debugrename(ui, repo, file, rev=None):
898 987 """dump rename information"""
899 988 r = repo.file(relpath(repo, [file])[0])
900 989 if rev:
901 990 try:
902 991 # assume all revision numbers are for changesets
903 992 n = repo.lookup(rev)
904 993 change = repo.changelog.read(n)
905 994 m = repo.manifest.read(change[0])
906 995 n = m[relpath(repo, [file])[0]]
907 996 except hg.RepoError, KeyError:
908 997 n = r.lookup(rev)
909 998 else:
910 999 n = r.tip()
911 1000 m = r.renamed(n)
912 1001 if m:
913 1002 ui.write(_("renamed from %s:%s\n") % (m[0], hex(m[1])))
914 1003 else:
915 1004 ui.write(_("not renamed\n"))
916 1005
917 1006 def debugwalk(ui, repo, *pats, **opts):
918 1007 """show how files match on given patterns"""
919 1008 items = list(walk(repo, pats, opts))
920 1009 if not items:
921 1010 return
922 1011 fmt = '%%s %%-%ds %%-%ds %%s' % (
923 1012 max([len(abs) for (src, abs, rel, exact) in items]),
924 1013 max([len(rel) for (src, abs, rel, exact) in items]))
925 1014 for src, abs, rel, exact in items:
926 1015 line = fmt % (src, abs, rel, exact and 'exact' or '')
927 1016 ui.write("%s\n" % line.rstrip())
928 1017
929 1018 def diff(ui, repo, *pats, **opts):
930 """diff working directory (or selected files)"""
1019 """diff working directory (or selected files)
1020
1021 Show differences between revisions for the specified files.
1022
1023 Differences between files are shown using the unified diff format.
1024
1025 When two revision arguments are given, then changes are shown
1026 between those revisions. If only one revision is specified then
1027 that revision is compared to the working directory, and, when no
1028 revisions are specified, the working directory files are compared
1029 to its parent.
1030
1031 Without the -a option, diff will avoid generating diffs of files
1032 it detects as binary. With -a, diff will generate a diff anyway,
1033 probably with undesirable results.
1034 """
931 1035 node1, node2 = None, None
932 1036 revs = [repo.lookup(x) for x in opts['rev']]
933 1037
934 1038 if len(revs) > 0:
935 1039 node1 = revs[0]
936 1040 if len(revs) > 1:
937 1041 node2 = revs[1]
938 1042 if len(revs) > 2:
939 1043 raise util.Abort(_("too many revisions to diff"))
940 1044
941 1045 fns, matchfn, anypats = matchpats(repo, repo.getcwd(), pats, opts)
942 1046
943 1047 dodiff(sys.stdout, ui, repo, node1, node2, fns, match=matchfn,
944 1048 text=opts['text'])
945 1049
946 1050 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
947 1051 node = repo.lookup(changeset)
948 1052 prev, other = repo.changelog.parents(node)
949 1053 change = repo.changelog.read(node)
950 1054
951 1055 fp = make_file(repo, repo.changelog, opts['output'],
952 1056 node=node, total=total, seqno=seqno,
953 1057 revwidth=revwidth)
954 1058 if fp != sys.stdout:
955 1059 ui.note("%s\n" % fp.name)
956 1060
957 1061 fp.write("# HG changeset patch\n")
958 1062 fp.write("# User %s\n" % change[1])
959 1063 fp.write("# Node ID %s\n" % hex(node))
960 1064 fp.write("# Parent %s\n" % hex(prev))
961 1065 if other != nullid:
962 1066 fp.write("# Parent %s\n" % hex(other))
963 1067 fp.write(change[4].rstrip())
964 1068 fp.write("\n\n")
965 1069
966 1070 dodiff(fp, ui, repo, prev, node, text=opts['text'])
967 1071 if fp != sys.stdout:
968 1072 fp.close()
969 1073
970 1074 def export(ui, repo, *changesets, **opts):
971 """dump the header and diffs for one or more changesets"""
1075 """dump the header and diffs for one or more changesets
1076
1077 Print the changeset header and diffs for one or more revisions.
1078
1079 The information shown in the changeset header is: author,
1080 changeset hash, parent and commit comment.
1081
1082 Output may be to a file, in which case the name of the file is
1083 given using a format string. The formatting rules are as follows:
1084
1085 %% literal "%" character
1086 %H changeset hash (40 bytes of hexadecimal)
1087 %N number of patches being generated
1088 %R changeset revision number
1089 %b basename of the exporting repository
1090 %h short-form changeset hash (12 bytes of hexadecimal)
1091 %n zero-padded sequence number, starting at 1
1092 %r zero-padded changeset revision number
1093
1094 Without the -a option, export will avoid generating diffs of files
1095 it detects as binary. With -a, export will generate a diff anyway,
1096 probably with undesirable results.
1097 """
972 1098 if not changesets:
973 1099 raise util.Abort(_("export requires at least one changeset"))
974 1100 seqno = 0
975 1101 revs = list(revrange(ui, repo, changesets))
976 1102 total = len(revs)
977 1103 revwidth = max(map(len, revs))
978 1104 ui.note(len(revs) > 1 and _("Exporting patches:\n") or _("Exporting patch:\n"))
979 1105 for cset in revs:
980 1106 seqno += 1
981 1107 doexport(ui, repo, cset, seqno, total, revwidth, opts)
982 1108
983 1109 def forget(ui, repo, *pats, **opts):
984 """don't add the specified files on the next commit"""
1110 """don't add the specified files on the next commit
1111
1112 Undo an 'hg add' scheduled for the next commit.
1113 """
985 1114 forget = []
986 1115 for src, abs, rel, exact in walk(repo, pats, opts):
987 1116 if repo.dirstate.state(abs) == 'a':
988 1117 forget.append(abs)
989 1118 if ui.verbose or not exact:
990 1119 ui.status(_('forgetting %s\n') % rel)
991 1120 repo.forget(forget)
992 1121
993 1122 def grep(ui, repo, pattern, *pats, **opts):
994 """search for a pattern in specified files and revisions"""
1123 """search for a pattern in specified files and revisions
1124
1125 Search revisions of files for a regular expression.
1126
1127 This command behaves differently than Unix grep. It only accepts
1128 Python/Perl regexps. It searches repository history, not the
1129 working directory. It always prints the revision number in which
1130 a match appears.
1131
1132 By default, grep only prints output for the first revision of a
1133 file in which it finds a match. To get it to print every revision
1134 that contains a change in match status ("-" for a match that
1135 becomes a non-match, or "+" for a non-match that becomes a match),
1136 use the --all flag.
1137 """
995 1138 reflags = 0
996 1139 if opts['ignore_case']:
997 1140 reflags |= re.I
998 1141 regexp = re.compile(pattern, reflags)
999 1142 sep, eol = ':', '\n'
1000 1143 if opts['print0']:
1001 1144 sep = eol = '\0'
1002 1145
1003 1146 fcache = {}
1004 1147 def getfile(fn):
1005 1148 if fn not in fcache:
1006 1149 fcache[fn] = repo.file(fn)
1007 1150 return fcache[fn]
1008 1151
1009 1152 def matchlines(body):
1010 1153 begin = 0
1011 1154 linenum = 0
1012 1155 while True:
1013 1156 match = regexp.search(body, begin)
1014 1157 if not match:
1015 1158 break
1016 1159 mstart, mend = match.span()
1017 1160 linenum += body.count('\n', begin, mstart) + 1
1018 1161 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1019 1162 lend = body.find('\n', mend)
1020 1163 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1021 1164 begin = lend + 1
1022 1165
1023 1166 class linestate:
1024 1167 def __init__(self, line, linenum, colstart, colend):
1025 1168 self.line = line
1026 1169 self.linenum = linenum
1027 1170 self.colstart = colstart
1028 1171 self.colend = colend
1029 1172 def __eq__(self, other):
1030 1173 return self.line == other.line
1031 1174 def __hash__(self):
1032 1175 return hash(self.line)
1033 1176
1034 1177 matches = {}
1035 1178 def grepbody(fn, rev, body):
1036 1179 matches[rev].setdefault(fn, {})
1037 1180 m = matches[rev][fn]
1038 1181 for lnum, cstart, cend, line in matchlines(body):
1039 1182 s = linestate(line, lnum, cstart, cend)
1040 1183 m[s] = s
1041 1184
1042 1185 prev = {}
1043 1186 ucache = {}
1044 1187 def display(fn, rev, states, prevstates):
1045 1188 diff = list(sets.Set(states).symmetric_difference(sets.Set(prevstates)))
1046 1189 diff.sort(lambda x, y: cmp(x.linenum, y.linenum))
1047 1190 counts = {'-': 0, '+': 0}
1048 1191 filerevmatches = {}
1049 1192 for l in diff:
1050 1193 if incrementing or not opts['all']:
1051 1194 change = ((l in prevstates) and '-') or '+'
1052 1195 r = rev
1053 1196 else:
1054 1197 change = ((l in states) and '-') or '+'
1055 1198 r = prev[fn]
1056 1199 cols = [fn, str(rev)]
1057 1200 if opts['line_number']: cols.append(str(l.linenum))
1058 1201 if opts['all']: cols.append(change)
1059 1202 if opts['user']: cols.append(trimuser(ui, getchange(rev)[1], rev,
1060 1203 ucache))
1061 1204 if opts['files_with_matches']:
1062 1205 c = (fn, rev)
1063 1206 if c in filerevmatches: continue
1064 1207 filerevmatches[c] = 1
1065 1208 else:
1066 1209 cols.append(l.line)
1067 1210 ui.write(sep.join(cols), eol)
1068 1211 counts[change] += 1
1069 1212 return counts['+'], counts['-']
1070 1213
1071 1214 fstate = {}
1072 1215 skip = {}
1073 1216 changeiter, getchange = walkchangerevs(ui, repo, repo.getcwd(), pats, opts)
1074 1217 count = 0
1075 1218 incrementing = False
1076 1219 for st, rev, fns in changeiter:
1077 1220 if st == 'window':
1078 1221 incrementing = rev
1079 1222 matches.clear()
1080 1223 elif st == 'add':
1081 1224 change = repo.changelog.read(repo.lookup(str(rev)))
1082 1225 mf = repo.manifest.read(change[0])
1083 1226 matches[rev] = {}
1084 1227 for fn in fns:
1085 1228 if fn in skip: continue
1086 1229 fstate.setdefault(fn, {})
1087 1230 try:
1088 1231 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1089 1232 except KeyError:
1090 1233 pass
1091 1234 elif st == 'iter':
1092 1235 states = matches[rev].items()
1093 1236 states.sort()
1094 1237 for fn, m in states:
1095 1238 if fn in skip: continue
1096 1239 if incrementing or not opts['all'] or fstate[fn]:
1097 1240 pos, neg = display(fn, rev, m, fstate[fn])
1098 1241 count += pos + neg
1099 1242 if pos and not opts['all']:
1100 1243 skip[fn] = True
1101 1244 fstate[fn] = m
1102 1245 prev[fn] = rev
1103 1246
1104 1247 if not incrementing:
1105 1248 fstate = fstate.items()
1106 1249 fstate.sort()
1107 1250 for fn, state in fstate:
1108 1251 if fn in skip: continue
1109 1252 display(fn, rev, {}, state)
1110 1253 return (count == 0 and 1) or 0
1111 1254
1112 1255 def heads(ui, repo, **opts):
1113 """show current repository heads"""
1256 """show current repository heads
1257
1258 Show all repository head changesets.
1259
1260 Repository "heads" are changesets that don't have children
1261 changesets. They are where development generally takes place and
1262 are the usual targets for update and merge operations.
1263 """
1114 1264 heads = repo.changelog.heads()
1115 1265 br = None
1116 1266 if opts['branches']:
1117 1267 br = repo.branchlookup(heads)
1118 1268 for n in repo.changelog.heads():
1119 1269 show_changeset(ui, repo, changenode=n, brinfo=br)
1120 1270
1121 1271 def identify(ui, repo):
1122 """print information about the working copy"""
1272 """print information about the working copy
1273 Print a short summary of the current state of the repo.
1274
1275 This summary identifies the repository state using one or two parent
1276 hash identifiers, followed by a "+" if there are uncommitted changes
1277 in the working directory, followed by a list of tags for this revision.
1278 """
1123 1279 parents = [p for p in repo.dirstate.parents() if p != nullid]
1124 1280 if not parents:
1125 1281 ui.write(_("unknown\n"))
1126 1282 return
1127 1283
1128 1284 hexfunc = ui.verbose and hex or short
1129 1285 (c, a, d, u) = repo.changes()
1130 1286 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
1131 1287 (c or a or d) and "+" or "")]
1132 1288
1133 1289 if not ui.quiet:
1134 1290 # multiple tags for a single parent separated by '/'
1135 1291 parenttags = ['/'.join(tags)
1136 1292 for tags in map(repo.nodetags, parents) if tags]
1137 1293 # tags for multiple parents separated by ' + '
1138 1294 if parenttags:
1139 1295 output.append(' + '.join(parenttags))
1140 1296
1141 1297 ui.write("%s\n" % ' '.join(output))
1142 1298
1143 1299 def import_(ui, repo, patch1, *patches, **opts):
1144 """import an ordered set of patches"""
1300 """import an ordered set of patches
1301
1302 Import a list of patches and commit them individually.
1303
1304 If there are outstanding changes in the working directory, import
1305 will abort unless given the -f flag.
1306
1307 If a patch looks like a mail message (its first line starts with
1308 "From " or looks like an RFC822 header), it will not be applied
1309 unless the -f option is used. The importer neither parses nor
1310 discards mail headers, so use -f only to override the "mailness"
1311 safety check, not to import a real mail message.
1312 """
1145 1313 patches = (patch1,) + patches
1146 1314
1147 1315 if not opts['force']:
1148 1316 (c, a, d, u) = repo.changes()
1149 1317 if c or a or d:
1150 1318 raise util.Abort(_("outstanding uncommitted changes"))
1151 1319
1152 1320 d = opts["base"]
1153 1321 strip = opts["strip"]
1154 1322
1155 1323 mailre = re.compile(r'(?:From |[\w-]+:)')
1156 1324
1157 1325 # attempt to detect the start of a patch
1158 1326 # (this heuristic is borrowed from quilt)
1159 1327 diffre = re.compile(r'(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1160 1328 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1161 1329 '(---|\*\*\*)[ \t])')
1162 1330
1163 1331 for patch in patches:
1164 1332 ui.status(_("applying %s\n") % patch)
1165 1333 pf = os.path.join(d, patch)
1166 1334
1167 1335 message = []
1168 1336 user = None
1169 1337 hgpatch = False
1170 1338 for line in file(pf):
1171 1339 line = line.rstrip()
1172 1340 if (not message and not hgpatch and
1173 1341 mailre.match(line) and not opts['force']):
1174 1342 if len(line) > 35: line = line[:32] + '...'
1175 1343 raise util.Abort(_('first line looks like a '
1176 1344 'mail header: ') + line)
1177 1345 if diffre.match(line):
1178 1346 break
1179 1347 elif hgpatch:
1180 1348 # parse values when importing the result of an hg export
1181 1349 if line.startswith("# User "):
1182 1350 user = line[7:]
1183 1351 ui.debug(_('User: %s\n') % user)
1184 1352 elif not line.startswith("# ") and line:
1185 1353 message.append(line)
1186 1354 hgpatch = False
1187 1355 elif line == '# HG changeset patch':
1188 1356 hgpatch = True
1189 1357 message = [] # We may have collected garbage
1190 1358 else:
1191 1359 message.append(line)
1192 1360
1193 1361 # make sure message isn't empty
1194 1362 if not message:
1195 1363 message = _("imported patch %s\n") % patch
1196 1364 else:
1197 1365 message = "%s\n" % '\n'.join(message)
1198 1366 ui.debug(_('message:\n%s\n') % message)
1199 1367
1200 1368 files = util.patch(strip, pf, ui)
1201 1369
1202 1370 if len(files) > 0:
1203 1371 addremove(ui, repo, *files)
1204 1372 repo.commit(files, message, user)
1205 1373
1206 1374 def incoming(ui, repo, source="default", **opts):
1207 """show new changesets found in source"""
1375 """show new changesets found in source
1376
1377 Show new changesets found in the specified repo or the default
1378 pull repo. These are the changesets that would be pulled if a pull
1379 was requested.
1380
1381 Currently only local repositories are supported.
1382 """
1208 1383 source = ui.expandpath(source)
1209 1384 other = hg.repository(ui, source)
1210 1385 if not other.local():
1211 1386 raise util.Abort(_("incoming doesn't work for remote repositories yet"))
1212 1387 o = repo.findincoming(other)
1213 1388 if not o:
1214 1389 return
1215 1390 o = other.newer(o)
1216 1391 for n in o:
1217 1392 parents = [p for p in other.changelog.parents(n) if p != nullid]
1218 1393 if opts['no_merges'] and len(parents) == 2:
1219 1394 continue
1220 1395 show_changeset(ui, other, changenode=n)
1221 1396 if opts['patch']:
1222 1397 prev = (parents and parents[0]) or nullid
1223 1398 dodiff(ui, ui, other, prev, n)
1224 1399 ui.write("\n")
1225 1400
1226 1401 def init(ui, dest="."):
1227 """create a new repository in the given directory"""
1402 """create a new repository in the given directory
1403
1404 Initialize a new repository in the given directory. If the given
1405 directory does not exist, it is created.
1406
1407 If no directory is given, the current directory is used.
1408 """
1228 1409 if not os.path.exists(dest):
1229 1410 os.mkdir(dest)
1230 1411 hg.repository(ui, dest, create=1)
1231 1412
1232 1413 def locate(ui, repo, *pats, **opts):
1233 """locate files matching specific patterns"""
1414 """locate files matching specific patterns
1415
1416 Print all files under Mercurial control whose names match the
1417 given patterns.
1418
1419 This command searches the current directory and its
1420 subdirectories. To search an entire repository, move to the root
1421 of the repository.
1422
1423 If no patterns are given to match, this command prints all file
1424 names.
1425
1426 If you want to feed the output of this command into the "xargs"
1427 command, use the "-0" option to both this command and "xargs".
1428 This will avoid the problem of "xargs" treating single filenames
1429 that contain white space as multiple filenames.
1430 """
1234 1431 end = opts['print0'] and '\0' or '\n'
1235 1432
1236 1433 for src, abs, rel, exact in walk(repo, pats, opts, '(?:.*/|)'):
1237 1434 if repo.dirstate.state(abs) == '?':
1238 1435 continue
1239 1436 if opts['fullpath']:
1240 1437 ui.write(os.path.join(repo.root, abs), end)
1241 1438 else:
1242 1439 ui.write(rel, end)
1243 1440
1244 1441 def log(ui, repo, *pats, **opts):
1245 """show revision history of entire repository or files"""
1442 """show revision history of entire repository or files
1443
1444 Print the revision history of the specified files or the entire project.
1445
1446 By default this command outputs: changeset id and hash, tags,
1447 parents, user, date and time, and a summary for each commit. The
1448 -v switch adds some more detail, such as changed files, manifest
1449 hashes or message signatures.
1450 """
1246 1451 class dui:
1247 1452 # Implement and delegate some ui protocol. Save hunks of
1248 1453 # output for later display in the desired order.
1249 1454 def __init__(self, ui):
1250 1455 self.ui = ui
1251 1456 self.hunk = {}
1252 1457 def bump(self, rev):
1253 1458 self.rev = rev
1254 1459 self.hunk[rev] = []
1255 1460 def note(self, *args):
1256 1461 if self.verbose:
1257 1462 self.write(*args)
1258 1463 def status(self, *args):
1259 1464 if not self.quiet:
1260 1465 self.write(*args)
1261 1466 def write(self, *args):
1262 1467 self.hunk[self.rev].append(args)
1263 1468 def debug(self, *args):
1264 1469 if self.debugflag:
1265 1470 self.write(*args)
1266 1471 def __getattr__(self, key):
1267 1472 return getattr(self.ui, key)
1268 1473 cwd = repo.getcwd()
1269 1474 if not pats and cwd:
1270 1475 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
1271 1476 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
1272 1477 changeiter, getchange = walkchangerevs(ui, repo, (pats and cwd) or '',
1273 1478 pats, opts)
1274 1479 for st, rev, fns in changeiter:
1275 1480 if st == 'window':
1276 1481 du = dui(ui)
1277 1482 elif st == 'add':
1278 1483 du.bump(rev)
1279 1484 changenode = repo.changelog.node(rev)
1280 1485 parents = [p for p in repo.changelog.parents(changenode)
1281 1486 if p != nullid]
1282 1487 if opts['no_merges'] and len(parents) == 2:
1283 1488 continue
1284 1489 if opts['only_merges'] and len(parents) != 2:
1285 1490 continue
1286 1491
1287 1492 br = None
1288 1493 if opts['keyword']:
1289 1494 changes = repo.changelog.read(repo.changelog.node(rev))
1290 1495 miss = 0
1291 1496 for k in [kw.lower() for kw in opts['keyword']]:
1292 1497 if not (k in changes[1].lower() or
1293 1498 k in changes[4].lower() or
1294 1499 k in " ".join(changes[3][:20]).lower()):
1295 1500 miss = 1
1296 1501 break
1297 1502 if miss:
1298 1503 continue
1299 1504
1300 1505 if opts['branch']:
1301 1506 br = repo.branchlookup([repo.changelog.node(rev)])
1302 1507
1303 1508 show_changeset(du, repo, rev, brinfo=br)
1304 1509 if opts['patch']:
1305 1510 prev = (parents and parents[0]) or nullid
1306 1511 dodiff(du, du, repo, prev, changenode, fns)
1307 1512 du.write("\n\n")
1308 1513 elif st == 'iter':
1309 1514 for args in du.hunk[rev]:
1310 1515 ui.write(*args)
1311 1516
1312 1517 def manifest(ui, repo, rev=None):
1313 """output the latest or given revision of the project manifest"""
1518 """output the latest or given revision of the project manifest
1519
1520 Print a list of version controlled files for the given revision.
1521
1522 The manifest is the list of files being version controlled. If no revision
1523 is given then the tip is used.
1524 """
1314 1525 if rev:
1315 1526 try:
1316 1527 # assume all revision numbers are for changesets
1317 1528 n = repo.lookup(rev)
1318 1529 change = repo.changelog.read(n)
1319 1530 n = change[0]
1320 1531 except hg.RepoError:
1321 1532 n = repo.manifest.lookup(rev)
1322 1533 else:
1323 1534 n = repo.manifest.tip()
1324 1535 m = repo.manifest.read(n)
1325 1536 mf = repo.manifest.readflags(n)
1326 1537 files = m.keys()
1327 1538 files.sort()
1328 1539
1329 1540 for f in files:
1330 1541 ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
1331 1542
1332 1543 def outgoing(ui, repo, dest="default-push", **opts):
1333 """show changesets not found in destination"""
1544 """show changesets not found in destination
1545
1546 Show changesets not found in the specified destination repo or the
1547 default push repo. These are the changesets that would be pushed
1548 if a push was requested.
1549 """
1334 1550 dest = ui.expandpath(dest)
1335 1551 other = hg.repository(ui, dest)
1336 1552 o = repo.findoutgoing(other)
1337 1553 o = repo.newer(o)
1338 1554 for n in o:
1339 1555 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1340 1556 if opts['no_merges'] and len(parents) == 2:
1341 1557 continue
1342 1558 show_changeset(ui, repo, changenode=n)
1343 1559 if opts['patch']:
1344 1560 prev = (parents and parents[0]) or nullid
1345 1561 dodiff(ui, ui, repo, prev, n)
1346 1562 ui.write("\n")
1347 1563
1348 1564 def parents(ui, repo, rev=None):
1349 """show the parents of the working dir or revision"""
1565 """show the parents of the working dir or revision
1566
1567 Print the working directory's parent revisions.
1568 """
1350 1569 if rev:
1351 1570 p = repo.changelog.parents(repo.lookup(rev))
1352 1571 else:
1353 1572 p = repo.dirstate.parents()
1354 1573
1355 1574 for n in p:
1356 1575 if n != nullid:
1357 1576 show_changeset(ui, repo, changenode=n)
1358 1577
1359 1578 def paths(ui, search=None):
1360 """show definition of symbolic path names"""
1579 """show definition of symbolic path names
1580
1581 Show definition of symbolic path name NAME. If no name is given, show
1582 definition of available names.
1583
1584 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1585 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1586 """
1361 1587 try:
1362 1588 repo = hg.repository(ui=ui)
1363 1589 except hg.RepoError:
1364 1590 pass
1365 1591
1366 1592 if search:
1367 1593 for name, path in ui.configitems("paths"):
1368 1594 if name == search:
1369 1595 ui.write("%s\n" % path)
1370 1596 return
1371 1597 ui.warn(_("not found!\n"))
1372 1598 return 1
1373 1599 else:
1374 1600 for name, path in ui.configitems("paths"):
1375 1601 ui.write("%s = %s\n" % (name, path))
1376 1602
1377 1603 def pull(ui, repo, source="default", **opts):
1378 """pull changes from the specified source"""
1604 """pull changes from the specified source
1605
1606 Pull changes from a remote repository to a local one.
1607
1608 This finds all changes from the repository at the specified path
1609 or URL and adds them to the local repository. By default, this
1610 does not update the copy of the project in the working directory.
1611
1612 Valid URLs are of the form:
1613
1614 local/filesystem/path
1615 http://[user@]host[:port][/path]
1616 https://[user@]host[:port][/path]
1617 ssh://[user@]host[:port][/path]
1618
1619 SSH requires an accessible shell account on the destination machine
1620 and a copy of hg in the remote path. With SSH, paths are relative
1621 to the remote user's home directory by default; use two slashes at
1622 the start of a path to specify it as relative to the filesystem root.
1623 """
1379 1624 source = ui.expandpath(source)
1380 1625 ui.status(_('pulling from %s\n') % (source))
1381 1626
1382 1627 if opts['ssh']:
1383 1628 ui.setconfig("ui", "ssh", opts['ssh'])
1384 1629 if opts['remotecmd']:
1385 1630 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
1386 1631
1387 1632 other = hg.repository(ui, source)
1388 1633 r = repo.pull(other)
1389 1634 if not r:
1390 1635 if opts['update']:
1391 1636 return update(ui, repo)
1392 1637 else:
1393 1638 ui.status(_("(run 'hg update' to get a working copy)\n"))
1394 1639
1395 1640 return r
1396 1641
1397 1642 def push(ui, repo, dest="default-push", force=False, ssh=None, remotecmd=None):
1398 """push changes to the specified destination"""
1643 """push changes to the specified destination
1644
1645 Push changes from the local repository to the given destination.
1646
1647 This is the symmetrical operation for pull. It helps to move
1648 changes from the current repository to a different one. If the
1649 destination is local this is identical to a pull in that directory
1650 from the current one.
1651
1652 By default, push will refuse to run if it detects the result would
1653 increase the number of remote heads. This generally indicates the
1654 the client has forgotten to sync and merge before pushing.
1655
1656 Valid URLs are of the form:
1657
1658 local/filesystem/path
1659 ssh://[user@]host[:port][/path]
1660
1661 SSH requires an accessible shell account on the destination
1662 machine and a copy of hg in the remote path.
1663 """
1399 1664 dest = ui.expandpath(dest)
1400 1665 ui.status('pushing to %s\n' % (dest))
1401 1666
1402 1667 if ssh:
1403 1668 ui.setconfig("ui", "ssh", ssh)
1404 1669 if remotecmd:
1405 1670 ui.setconfig("ui", "remotecmd", remotecmd)
1406 1671
1407 1672 other = hg.repository(ui, dest)
1408 1673 r = repo.push(other, force)
1409 1674 return r
1410 1675
1411 1676 def rawcommit(ui, repo, *flist, **rc):
1412 "raw commit interface"
1677 """raw commit interface
1678
1679 Lowlevel commit, for use in helper scripts.
1680
1681 This command is not intended to be used by normal users, as it is
1682 primarily useful for importing from other SCMs.
1683 """
1413 1684 if rc['text']:
1414 1685 ui.warn(_("Warning: -t and --text is deprecated,"
1415 1686 " please use -m or --message instead.\n"))
1416 1687 message = rc['message'] or rc['text']
1417 1688 if not message and rc['logfile']:
1418 1689 try:
1419 1690 message = open(rc['logfile']).read()
1420 1691 except IOError:
1421 1692 pass
1422 1693 if not message and not rc['logfile']:
1423 1694 raise util.Abort(_("missing commit message"))
1424 1695
1425 1696 files = relpath(repo, list(flist))
1426 1697 if rc['files']:
1427 1698 files += open(rc['files']).read().splitlines()
1428 1699
1429 1700 rc['parent'] = map(repo.lookup, rc['parent'])
1430 1701
1431 1702 try:
1432 1703 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
1433 1704 except ValueError, inst:
1434 1705 raise util.Abort(str(inst))
1435 1706
1436 1707 def recover(ui, repo):
1437 """roll back an interrupted transaction"""
1708 """roll back an interrupted transaction
1709
1710 Recover from an interrupted commit or pull.
1711
1712 This command tries to fix the repository status after an interrupted
1713 operation. It should only be necessary when Mercurial suggests it.
1714 """
1438 1715 repo.recover()
1439 1716
1440 1717 def remove(ui, repo, pat, *pats, **opts):
1441 """remove the specified files on the next commit"""
1718 """remove the specified files on the next commit
1719
1720 Schedule the indicated files for removal from the repository.
1721
1722 This command schedules the files to be removed at the next commit.
1723 This only removes files from the current branch, not from the
1724 entire project history. If the files still exist in the working
1725 directory, they will be deleted from it.
1726 """
1442 1727 names = []
1443 1728 def okaytoremove(abs, rel, exact):
1444 1729 c, a, d, u = repo.changes(files = [abs])
1445 1730 reason = None
1446 1731 if c: reason = _('is modified')
1447 1732 elif a: reason = _('has been marked for add')
1448 1733 elif u: reason = _('is not managed')
1449 1734 if reason:
1450 1735 if exact: ui.warn(_('not removing %s: file %s\n') % (rel, reason))
1451 1736 else:
1452 1737 return True
1453 1738 for src, abs, rel, exact in walk(repo, (pat,) + pats, opts):
1454 1739 if okaytoremove(abs, rel, exact):
1455 1740 if ui.verbose or not exact: ui.status(_('removing %s\n') % rel)
1456 1741 names.append(abs)
1457 1742 repo.remove(names, unlink=True)
1458 1743
1459 1744 def rename(ui, repo, *pats, **opts):
1460 """rename files; equivalent of copy + remove"""
1745 """rename files; equivalent of copy + remove
1746
1747 Mark dest as copies of sources; mark sources for deletion. If
1748 dest is a directory, copies are put in that directory. If dest is
1749 a file, there can only be one source.
1750
1751 By default, this command copies the contents of files as they
1752 stand in the working directory. If invoked with --after, the
1753 operation is recorded, but no copying is performed.
1754
1755 This command takes effect in the next commit.
1756
1757 NOTE: This command should be treated as experimental. While it
1758 should properly record rename files, this information is not yet
1759 fully used by merge, nor fully reported by log.
1760 """
1461 1761 errs, copied = docopy(ui, repo, pats, opts)
1462 1762 names = []
1463 1763 for abs, rel, exact in copied:
1464 1764 if ui.verbose or not exact: ui.status(_('removing %s\n') % rel)
1465 1765 names.append(abs)
1466 1766 repo.remove(names, unlink=True)
1467 1767 return errs
1468 1768
1469 1769 def revert(ui, repo, *names, **opts):
1470 """revert modified files or dirs back to their unmodified states"""
1770 """revert modified files or dirs back to their unmodified states
1771
1772 Revert any uncommitted modifications made to the named files or
1773 directories. This restores the contents of the affected files to
1774 an unmodified state.
1775
1776 If a file has been deleted, it is recreated. If the executable
1777 mode of a file was changed, it is reset.
1778
1779 If a directory is given, all files in that directory and its
1780 subdirectories are reverted.
1781
1782 If no arguments are given, all files in the current directory and
1783 its subdirectories are reverted.
1784 """
1471 1785 node = opts['rev'] and repo.lookup(opts['rev']) or \
1472 1786 repo.dirstate.parents()[0]
1473 1787 root = os.path.realpath(repo.root)
1474 1788
1475 1789 def trimpath(p):
1476 1790 p = os.path.realpath(p)
1477 1791 if p.startswith(root):
1478 1792 rest = p[len(root):]
1479 1793 if not rest:
1480 1794 return rest
1481 1795 if p.startswith(os.sep):
1482 1796 return rest[1:]
1483 1797 return p
1484 1798
1485 1799 relnames = map(trimpath, names or [os.getcwd()])
1486 1800 chosen = {}
1487 1801
1488 1802 def choose(name):
1489 1803 def body(name):
1490 1804 for r in relnames:
1491 1805 if not name.startswith(r):
1492 1806 continue
1493 1807 rest = name[len(r):]
1494 1808 if not rest:
1495 1809 return r, True
1496 1810 depth = rest.count(os.sep)
1497 1811 if not r:
1498 1812 if depth == 0 or not opts['nonrecursive']:
1499 1813 return r, True
1500 1814 elif rest[0] == os.sep:
1501 1815 if depth == 1 or not opts['nonrecursive']:
1502 1816 return r, True
1503 1817 return None, False
1504 1818 relname, ret = body(name)
1505 1819 if ret:
1506 1820 chosen[relname] = 1
1507 1821 return ret
1508 1822
1509 1823 r = repo.update(node, False, True, choose, False)
1510 1824 for n in relnames:
1511 1825 if n not in chosen:
1512 1826 ui.warn(_('error: no matches for %s\n') % n)
1513 1827 r = 1
1514 1828 sys.stdout.flush()
1515 1829 return r
1516 1830
1517 1831 def root(ui, repo):
1518 """print the root (top) of the current working dir"""
1832 """print the root (top) of the current working dir
1833
1834 Print the root directory of the current repository.
1835 """
1519 1836 ui.write(repo.root + "\n")
1520 1837
1521 1838 def serve(ui, repo, **opts):
1522 """export the repository via HTTP"""
1839 """export the repository via HTTP
1840
1841 Start a local HTTP repository browser and pull server.
1842
1843 By default, the server logs accesses to stdout and errors to
1844 stderr. Use the "-A" and "-E" options to log to files.
1845 """
1523 1846
1524 1847 if opts["stdio"]:
1525 1848 fin, fout = sys.stdin, sys.stdout
1526 1849 sys.stdout = sys.stderr
1527 1850
1528 1851 # Prevent insertion/deletion of CRs
1529 1852 util.set_binary(fin)
1530 1853 util.set_binary(fout)
1531 1854
1532 1855 def getarg():
1533 1856 argline = fin.readline()[:-1]
1534 1857 arg, l = argline.split()
1535 1858 val = fin.read(int(l))
1536 1859 return arg, val
1537 1860 def respond(v):
1538 1861 fout.write("%d\n" % len(v))
1539 1862 fout.write(v)
1540 1863 fout.flush()
1541 1864
1542 1865 lock = None
1543 1866
1544 1867 while 1:
1545 1868 cmd = fin.readline()[:-1]
1546 1869 if cmd == '':
1547 1870 return
1548 1871 if cmd == "heads":
1549 1872 h = repo.heads()
1550 1873 respond(" ".join(map(hex, h)) + "\n")
1551 1874 if cmd == "lock":
1552 1875 lock = repo.lock()
1553 1876 respond("")
1554 1877 if cmd == "unlock":
1555 1878 if lock:
1556 1879 lock.release()
1557 1880 lock = None
1558 1881 respond("")
1559 1882 elif cmd == "branches":
1560 1883 arg, nodes = getarg()
1561 1884 nodes = map(bin, nodes.split(" "))
1562 1885 r = []
1563 1886 for b in repo.branches(nodes):
1564 1887 r.append(" ".join(map(hex, b)) + "\n")
1565 1888 respond("".join(r))
1566 1889 elif cmd == "between":
1567 1890 arg, pairs = getarg()
1568 1891 pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
1569 1892 r = []
1570 1893 for b in repo.between(pairs):
1571 1894 r.append(" ".join(map(hex, b)) + "\n")
1572 1895 respond("".join(r))
1573 1896 elif cmd == "changegroup":
1574 1897 nodes = []
1575 1898 arg, roots = getarg()
1576 1899 nodes = map(bin, roots.split(" "))
1577 1900
1578 1901 cg = repo.changegroup(nodes)
1579 1902 while 1:
1580 1903 d = cg.read(4096)
1581 1904 if not d:
1582 1905 break
1583 1906 fout.write(d)
1584 1907
1585 1908 fout.flush()
1586 1909
1587 1910 elif cmd == "addchangegroup":
1588 1911 if not lock:
1589 1912 respond("not locked")
1590 1913 continue
1591 1914 respond("")
1592 1915
1593 1916 r = repo.addchangegroup(fin)
1594 1917 respond("")
1595 1918
1596 1919 optlist = "name templates style address port ipv6 accesslog errorlog"
1597 1920 for o in optlist.split():
1598 1921 if opts[o]:
1599 1922 ui.setconfig("web", o, opts[o])
1600 1923
1601 1924 try:
1602 1925 httpd = hgweb.create_server(repo)
1603 1926 except socket.error, inst:
1604 1927 raise util.Abort('cannot start server: ' + inst.args[1])
1605 1928
1606 1929 if ui.verbose:
1607 1930 addr, port = httpd.socket.getsockname()
1608 1931 if addr == '0.0.0.0':
1609 1932 addr = socket.gethostname()
1610 1933 else:
1611 1934 try:
1612 1935 addr = socket.gethostbyaddr(addr)[0]
1613 1936 except socket.error:
1614 1937 pass
1615 1938 if port != 80:
1616 1939 ui.status(_('listening at http://%s:%d/\n') % (addr, port))
1617 1940 else:
1618 1941 ui.status(_('listening at http://%s/\n') % addr)
1619 1942 httpd.serve_forever()
1620 1943
1621 1944 def status(ui, repo, *pats, **opts):
1622 '''show changed files in the working directory
1945 """show changed files in the working directory
1623 1946
1947 Show changed files in the working directory. If no names are
1948 given, all files are shown. Otherwise, only files matching the
1949 given names are shown.
1950
1951 The codes used to show the status of files are:
1624 1952 M = modified
1625 1953 A = added
1626 1954 R = removed
1627 1955 ? = not tracked
1628 '''
1956 """
1629 1957
1630 1958 cwd = repo.getcwd()
1631 1959 files, matchfn, anypats = matchpats(repo, cwd, pats, opts)
1632 1960 (c, a, d, u) = [[util.pathto(cwd, x) for x in n]
1633 1961 for n in repo.changes(files=files, match=matchfn)]
1634 1962
1635 1963 changetypes = [(_('modified'), 'M', c),
1636 1964 (_('added'), 'A', a),
1637 1965 (_('removed'), 'R', d),
1638 1966 (_('unknown'), '?', u)]
1639 1967
1640 1968 end = opts['print0'] and '\0' or '\n'
1641 1969
1642 1970 for opt, char, changes in ([ct for ct in changetypes if opts[ct[0]]]
1643 1971 or changetypes):
1644 1972 if opts['no_status']:
1645 1973 format = "%%s%s" % end
1646 1974 else:
1647 1975 format = "%s %%s%s" % (char, end);
1648 1976
1649 1977 for f in changes:
1650 1978 ui.write(format % f)
1651 1979
1652 1980 def tag(ui, repo, name, rev=None, **opts):
1653 """add a tag for the current tip or a given revision"""
1981 """add a tag for the current tip or a given revision
1982
1983 Name a particular revision using <name>.
1984
1985 Tags are used to name particular revisions of the repository and are
1986 very useful to compare different revision, to go back to significant
1987 earlier versions or to mark branch points as releases, etc.
1988
1989 If no revision is given, the tip is used.
1990
1991 To facilitate version control, distribution, and merging of tags,
1992 they are stored as a file named ".hgtags" which is managed
1993 similarly to other project files and can be hand-edited if
1994 necessary.
1995 """
1654 1996 if opts['text']:
1655 1997 ui.warn(_("Warning: -t and --text is deprecated,"
1656 1998 " please use -m or --message instead.\n"))
1657 1999 if name == "tip":
1658 2000 raise util.Abort(_("the name 'tip' is reserved"))
1659 2001 if rev:
1660 2002 r = hex(repo.lookup(rev))
1661 2003 else:
1662 2004 r = hex(repo.changelog.tip())
1663 2005
1664 2006 if name.find(revrangesep) >= 0:
1665 2007 raise util.Abort(_("'%s' cannot be used in a tag name") % revrangesep)
1666 2008
1667 2009 if opts['local']:
1668 2010 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
1669 2011 return
1670 2012
1671 2013 (c, a, d, u) = repo.changes()
1672 2014 for x in (c, a, d, u):
1673 2015 if ".hgtags" in x:
1674 2016 raise util.Abort(_("working copy of .hgtags is changed "
1675 2017 "(please commit .hgtags manually)"))
1676 2018
1677 2019 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
1678 2020 if repo.dirstate.state(".hgtags") == '?':
1679 2021 repo.add([".hgtags"])
1680 2022
1681 2023 message = (opts['message'] or opts['text'] or
1682 2024 _("Added tag %s for changeset %s") % (name, r))
1683 2025 try:
1684 2026 repo.commit([".hgtags"], message, opts['user'], opts['date'])
1685 2027 except ValueError, inst:
1686 2028 raise util.Abort(str(inst))
1687 2029
1688 2030 def tags(ui, repo):
1689 """list repository tags"""
2031 """list repository tags
2032
2033 List the repository tags.
2034
2035 This lists both regular and local tags.
2036 """
1690 2037
1691 2038 l = repo.tagslist()
1692 2039 l.reverse()
1693 2040 for t, n in l:
1694 2041 try:
1695 2042 r = "%5d:%s" % (repo.changelog.rev(n), hex(n))
1696 2043 except KeyError:
1697 2044 r = " ?:?"
1698 2045 ui.write("%-30s %s\n" % (t, r))
1699 2046
1700 2047 def tip(ui, repo):
1701 """show the tip revision"""
2048 """show the tip revision
2049
2050 Show the tip revision.
2051 """
1702 2052 n = repo.changelog.tip()
1703 2053 show_changeset(ui, repo, changenode=n)
1704 2054
1705 2055 def unbundle(ui, repo, fname):
1706 """apply a changegroup file"""
2056 """apply a changegroup file
2057
2058 Apply a compressed changegroup file generated by the bundle
2059 command.
2060 """
1707 2061 f = urllib.urlopen(fname)
1708 2062
1709 2063 if f.read(4) != "HG10":
1710 2064 raise util.Abort(_("%s: not a Mercurial bundle file") % fname)
1711 2065
1712 2066 def bzgenerator(f):
1713 2067 zd = bz2.BZ2Decompressor()
1714 2068 for chunk in f:
1715 2069 yield zd.decompress(chunk)
1716 2070
1717 2071 bzgen = bzgenerator(util.filechunkiter(f, 4096))
1718 2072 repo.addchangegroup(util.chunkbuffer(bzgen))
1719 2073
1720 2074 def undo(ui, repo):
1721 2075 """undo the last commit or pull
1722 2076
1723 2077 Roll back the last pull or commit transaction on the
1724 2078 repository, restoring the project to its earlier state.
1725 2079
1726 2080 This command should be used with care. There is only one level of
1727 2081 undo and there is no redo.
1728 2082
1729 2083 This command is not intended for use on public repositories. Once
1730 2084 a change is visible for pull by other users, undoing it locally is
1731 2085 ineffective.
1732 2086 """
1733 2087 repo.undo()
1734 2088
1735 2089 def update(ui, repo, node=None, merge=False, clean=False, branch=None):
1736 '''update or merge working directory
2090 """update or merge working directory
2091
2092 Update the working directory to the specified revision.
1737 2093
1738 2094 If there are no outstanding changes in the working directory and
1739 2095 there is a linear relationship between the current version and the
1740 2096 requested version, the result is the requested version.
1741 2097
1742 2098 Otherwise the result is a merge between the contents of the
1743 2099 current working directory and the requested version. Files that
1744 2100 changed between either parent are marked as changed for the next
1745 2101 commit and a commit must be performed before any further updates
1746 2102 are allowed.
1747 '''
2103
2104 By default, update will refuse to run if doing so would require
2105 merging or discarding local changes.
2106 """
1748 2107 if branch:
1749 2108 br = repo.branchlookup(branch=branch)
1750 2109 found = []
1751 2110 for x in br:
1752 2111 if branch in br[x]:
1753 2112 found.append(x)
1754 2113 if len(found) > 1:
1755 2114 ui.warn(_("Found multiple heads for %s\n") % branch)
1756 2115 for x in found:
1757 2116 show_changeset(ui, repo, changenode=x, brinfo=br)
1758 2117 return 1
1759 2118 if len(found) == 1:
1760 2119 node = found[0]
1761 2120 ui.warn(_("Using head %s for branch %s\n") % (short(node), branch))
1762 2121 else:
1763 2122 ui.warn(_("branch %s not found\n") % (branch))
1764 2123 return 1
1765 2124 else:
1766 2125 node = node and repo.lookup(node) or repo.changelog.tip()
1767 2126 return repo.update(node, allow=merge, force=clean)
1768 2127
1769 2128 def verify(ui, repo):
1770 """verify the integrity of the repository"""
2129 """verify the integrity of the repository
2130
2131 Verify the integrity of the current repository.
2132
2133 This will perform an extensive check of the repository's
2134 integrity, validating the hashes and checksums of each entry in
2135 the changelog, manifest, and tracked files, as well as the
2136 integrity of their crosslinks and indices.
2137 """
1771 2138 return repo.verify()
1772 2139
1773 2140 # Command options and aliases are listed here, alphabetically
1774 2141
1775 2142 table = {
1776 2143 "^add":
1777 2144 (add,
1778 [('I', 'include', [], _('include path in search')),
1779 ('X', 'exclude', [], _('exclude path from search'))],
2145 [('I', 'include', [], _('include names matching the given patterns')),
2146 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
1780 2147 "hg add [OPTION]... [FILE]..."),
1781 2148 "addremove":
1782 2149 (addremove,
1783 [('I', 'include', [], _('include path in search')),
1784 ('X', 'exclude', [], _('exclude path from search'))],
1785 _("hg addremove [OPTION]... [FILE]...")),
2150 [('I', 'include', [], _('include names matching the given patterns')),
2151 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2152 "hg addremove [OPTION]... [FILE]..."),
1786 2153 "^annotate":
1787 2154 (annotate,
1788 [('r', 'rev', '', _('revision')),
2155 [('r', 'rev', '', _('annotate the specified revision')),
1789 2156 ('a', 'text', None, _('treat all files as text')),
1790 ('u', 'user', None, _('show user')),
1791 ('n', 'number', None, _('show revision number')),
1792 ('c', 'changeset', None, _('show changeset')),
1793 ('I', 'include', [], _('include path in search')),
1794 ('X', 'exclude', [], _('exclude path from search'))],
2157 ('u', 'user', None, _('list the author')),
2158 ('n', 'number', None, _('list the revision number (default)')),
2159 ('c', 'changeset', None, _('list the changeset')),
2160 ('I', 'include', [], _('include names matching the given patterns')),
2161 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
1795 2162 _('hg annotate [OPTION]... FILE...')),
1796 2163 "bundle":
1797 2164 (bundle,
1798 2165 [],
1799 2166 _('hg bundle FILE DEST')),
1800 2167 "cat":
1801 2168 (cat,
1802 [('I', 'include', [], _('include path in search')),
1803 ('X', 'exclude', [], _('exclude path from search')),
1804 ('o', 'output', "", _('output to file')),
1805 ('r', 'rev', '', _('revision'))],
2169 [('I', 'include', [], _('include names matching the given patterns')),
2170 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2171 ('o', 'output', "", _('print output to file with formatted name')),
2172 ('r', 'rev', '', _('print the given revision'))],
1806 2173 _('hg cat [OPTION]... FILE...')),
1807 2174 "^clone":
1808 2175 (clone,
1809 [('U', 'noupdate', None, _('skip update after cloning')),
1810 ('e', 'ssh', "", _('ssh command')),
2176 [('U', 'noupdate', None, _('do not update the new working directory')),
2177 ('e', 'ssh', "", _('specify ssh command to use')),
1811 2178 ('', 'pull', None, _('use pull protocol to copy metadata')),
1812 ('', 'remotecmd', "", _('remote hg command'))],
2179 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
1813 2180 _('hg clone [OPTION]... SOURCE [DEST]')),
1814 2181 "^commit|ci":
1815 2182 (commit,
1816 [('A', 'addremove', None, _('run add/remove during commit')),
1817 ('I', 'include', [], _('include path in search')),
1818 ('X', 'exclude', [], _('exclude path from search')),
1819 ('m', 'message', "", _('commit message')),
2183 [('A', 'addremove', None, _('run addremove during commit')),
2184 ('I', 'include', [], _('include names matching the given patterns')),
2185 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2186 ('m', 'message', "", _('use <text> as commit message')),
1820 2187 ('t', 'text', "", _('commit message (deprecated: use -m)')),
1821 ('l', 'logfile', "", _('commit message file')),
1822 ('d', 'date', "", _('date code')),
1823 ('u', 'user', "", _('user'))],
2188 ('l', 'logfile', "", _('read the commit message from <file>')),
2189 ('d', 'date', "", _('record datecode as commit date')),
2190 ('u', 'user', "", _('record user as commiter'))],
1824 2191 _('hg commit [OPTION]... [FILE]...')),
1825 2192 "copy|cp": (copy,
1826 [('I', 'include', [], _('include path in search')),
1827 ('X', 'exclude', [], _('exclude path from search')),
1828 ('A', 'after', None, _('record a copy after it has happened')),
1829 ('f', 'force', None, _('replace destination if it exists')),
2193 [('I', 'include', [], _('include names matching the given patterns')),
2194 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2195 ('A', 'after', None, _('record a copy that has already occurred')),
2196 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1830 2197 ('p', 'parents', None, _('append source path to dest'))],
1831 2198 _('hg copy [OPTION]... [SOURCE]... DEST')),
1832 2199 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
1833 2200 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
1834 2201 "debugconfig": (debugconfig, [], _('debugconfig')),
1835 2202 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
1836 2203 "debugstate": (debugstate, [], _('debugstate')),
1837 2204 "debugdata": (debugdata, [], _('debugdata FILE REV')),
1838 2205 "debugindex": (debugindex, [], _('debugindex FILE')),
1839 2206 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
1840 2207 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
1841 2208 "debugwalk":
1842 2209 (debugwalk,
1843 [('I', 'include', [], _('include path in search')),
1844 ('X', 'exclude', [], _('exclude path from search'))],
2210 [('I', 'include', [], _('include names matching the given patterns')),
2211 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
1845 2212 _('debugwalk [OPTION]... [FILE]...')),
1846 2213 "^diff":
1847 2214 (diff,
1848 2215 [('r', 'rev', [], _('revision')),
1849 2216 ('a', 'text', None, _('treat all files as text')),
1850 ('I', 'include', [], _('include path in search')),
1851 ('X', 'exclude', [], _('exclude path from search'))],
2217 ('I', 'include', [], _('include names matching the given patterns')),
2218 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
1852 2219 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
1853 2220 "^export":
1854 2221 (export,
1855 [('o', 'output', "", _('output to file')),
2222 [('o', 'output', "", _('print output to file with formatted name')),
1856 2223 ('a', 'text', None, _('treat all files as text'))],
1857 _("hg export [-a] [-o OUTFILE] REV...")),
2224 "hg export [-a] [-o OUTFILE] REV..."),
1858 2225 "forget":
1859 2226 (forget,
1860 [('I', 'include', [], _('include path in search')),
1861 ('X', 'exclude', [], _('exclude path from search'))],
1862 _("hg forget [OPTION]... FILE...")),
2227 [('I', 'include', [], _('include names matching the given patterns')),
2228 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2229 "hg forget [OPTION]... FILE..."),
1863 2230 "grep":
1864 2231 (grep,
1865 2232 [('0', 'print0', None, _('end fields with NUL')),
1866 ('I', 'include', [], _('include path in search')),
1867 ('X', 'exclude', [], _('include path in search')),
1868 ('', 'all', None, _('print all revisions with matches')),
2233 ('I', 'include', [], _('include names matching the given patterns')),
2234 ('X', 'exclude', [], _('include names matching the given patterns')),
2235 ('', 'all', None, _('print all revisions that match')),
1869 2236 ('i', 'ignore-case', None, _('ignore case when matching')),
1870 ('l', 'files-with-matches', None, _('print names of files and revs with matches')),
1871 ('n', 'line-number', None, _('print line numbers')),
1872 ('r', 'rev', [], _('search in revision rev')),
1873 ('u', 'user', None, _('print user who made change'))],
1874 _("hg grep [OPTION]... PATTERN [FILE]...")),
2237 ('l', 'files-with-matches', None, _('print only filenames and revs that match')),
2238 ('n', 'line-number', None, _('print matching line numbers')),
2239 ('r', 'rev', [], _('search in given revision range')),
2240 ('u', 'user', None, _('print user who committed change'))],
2241 "hg grep [OPTION]... PATTERN [FILE]..."),
1875 2242 "heads":
1876 2243 (heads,
1877 2244 [('b', 'branches', None, _('find branch info'))],
1878 2245 _('hg heads [-b]')),
1879 2246 "help": (help_, [], _('hg help [COMMAND]')),
1880 2247 "identify|id": (identify, [], _('hg identify')),
1881 2248 "import|patch":
1882 2249 (import_,
1883 [('p', 'strip', 1, _('path strip')),
1884 ('f', 'force', None, _('skip check for outstanding changes')),
2250 [('p', 'strip', 1, _('directory strip option for patch. This has the same\n') +
2251 _('meaning as the corresponding patch option')),
2252 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
1885 2253 ('b', 'base', "", _('base path'))],
1886 _("hg import [-f] [-p NUM] [-b BASE] PATCH...")),
2254 "hg import [-f] [-p NUM] [-b BASE] PATCH..."),
1887 2255 "incoming|in": (incoming,
1888 2256 [('M', 'no-merges', None, _("do not show merges")),
1889 2257 ('p', 'patch', None, _('show patch'))],
1890 2258 _('hg incoming [-p] [SOURCE]')),
1891 2259 "^init": (init, [], _('hg init [DEST]')),
1892 2260 "locate":
1893 2261 (locate,
1894 [('r', 'rev', '', _('revision')),
1895 ('0', 'print0', None, _('end filenames with NUL')),
1896 ('f', 'fullpath', None, _('print complete paths')),
1897 ('I', 'include', [], _('include path in search')),
1898 ('X', 'exclude', [], _('exclude path from search'))],
2262 [('r', 'rev', '', _('search the repository as it stood at rev')),
2263 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2264 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
2265 ('I', 'include', [], _('include names matching the given patterns')),
2266 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
1899 2267 _('hg locate [OPTION]... [PATTERN]...')),
1900 2268 "^log|history":
1901 2269 (log,
1902 [('I', 'include', [], _('include path in search')),
1903 ('X', 'exclude', [], _('exclude path from search')),
2270 [('I', 'include', [], _('include names matching the given patterns')),
2271 ('X', 'exclude', [], _('exclude names matching the given patterns')),
1904 2272 ('b', 'branch', None, _('show branches')),
1905 2273 ('k', 'keyword', [], _('search for a keyword')),
1906 ('r', 'rev', [], _('revision')),
2274 ('r', 'rev', [], _('show the specified revision or range')),
1907 2275 ('M', 'no-merges', None, _("do not show merges")),
1908 2276 ('m', 'only-merges', None, _("show only merges")),
1909 2277 ('p', 'patch', None, _('show patch'))],
1910 2278 _('hg log [-I] [-X] [-r REV]... [-p] [FILE]')),
1911 2279 "manifest": (manifest, [], _('hg manifest [REV]')),
1912 2280 "outgoing|out": (outgoing,
1913 2281 [('M', 'no-merges', None, _("do not show merges")),
1914 2282 ('p', 'patch', None, _('show patch'))],
1915 2283 _('hg outgoing [-p] [DEST]')),
1916 2284 "parents": (parents, [], _('hg parents [REV]')),
1917 2285 "paths": (paths, [], _('hg paths [NAME]')),
1918 2286 "^pull":
1919 2287 (pull,
1920 [('u', 'update', None, _('update working directory')),
1921 ('e', 'ssh', "", _('ssh command')),
1922 ('', 'remotecmd', "", _('remote hg command'))],
2288 [('u', 'update', None, _('update the working directory to tip after pull')),
2289 ('e', 'ssh', "", _('specify ssh command to use')),
2290 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
1923 2291 _('hg pull [-u] [-e FILE] [--remotecmd FILE] [SOURCE]')),
1924 2292 "^push":
1925 2293 (push,
1926 2294 [('f', 'force', None, _('force push')),
1927 ('e', 'ssh', "", _('ssh command')),
1928 ('', 'remotecmd', "", _('remote hg command'))],
2295 ('e', 'ssh', "", _('specify ssh command to use')),
2296 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
1929 2297 _('hg push [-f] [-e FILE] [--remotecmd FILE] [DEST]')),
1930 2298 "rawcommit":
1931 2299 (rawcommit,
1932 2300 [('p', 'parent', [], _('parent')),
1933 2301 ('d', 'date', "", _('date code')),
1934 2302 ('u', 'user', "", _('user')),
1935 2303 ('F', 'files', "", _('file list')),
1936 2304 ('m', 'message', "", _('commit message')),
1937 2305 ('t', 'text', "", _('commit message (deprecated: use -m)')),
1938 2306 ('l', 'logfile', "", _('commit message file'))],
1939 2307 _('hg rawcommit [OPTION]... [FILE]...')),
1940 2308 "recover": (recover, [], _("hg recover")),
1941 2309 "^remove|rm": (remove,
1942 [('I', 'include', [], _('include path in search')),
1943 ('X', 'exclude', [], _('exclude path from search'))],
2310 [('I', 'include', [], _('include names matching the given patterns')),
2311 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
1944 2312 _("hg remove [OPTION]... FILE...")),
1945 2313 "rename|mv": (rename,
1946 [('I', 'include', [], _('include path in search')),
1947 ('X', 'exclude', [], _('exclude path from search')),
1948 ('A', 'after', None, _('record a copy after it has happened')),
1949 ('f', 'force', None, _('replace destination if it exists')),
2314 [('I', 'include', [], _('include names matching the given patterns')),
2315 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2316 ('A', 'after', None, _('record a rename that has already occurred')),
2317 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1950 2318 ('p', 'parents', None, _('append source path to dest'))],
1951 2319 _('hg rename [OPTION]... [SOURCE]... DEST')),
1952 2320 "^revert":
1953 2321 (revert,
1954 [("n", "nonrecursive", None, _("don't recurse into subdirs")),
1955 ("r", "rev", "", _("revision"))],
2322 [("n", "nonrecursive", None, _("do not recurse into subdirectories")),
2323 ("r", "rev", "", _("revision to revert to"))],
1956 2324 _("hg revert [-n] [-r REV] [NAME]...")),
1957 2325 "root": (root, [], _("hg root")),
1958 2326 "^serve":
1959 2327 (serve,
1960 [('A', 'accesslog', '', _('access log file')),
1961 ('E', 'errorlog', '', _('error log file')),
1962 ('p', 'port', 0, _('listen port')),
1963 ('a', 'address', '', _('interface address')),
1964 ('n', 'name', "", _('repository name')),
2328 [('A', 'accesslog', '', _('name of access log file to write to')),
2329 ('E', 'errorlog', '', _('name of error log file to write to')),
2330 ('p', 'port', 0, _('port to use (default: 8000)')),
2331 ('a', 'address', '', _('address to use')),
2332 ('n', 'name', "", _('name to show in web pages (default: working dir)')),
1965 2333 ('', 'stdio', None, _('for remote clients')),
1966 ('t', 'templates', "", _('template directory')),
1967 ('', 'style', "", _('template style')),
2334 ('t', 'templates', "", _('web templates to use')),
2335 ('', 'style', "", _('template style to use')),
1968 2336 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
1969 2337 _("hg serve [OPTION]...")),
1970 2338 "^status":
1971 2339 (status,
1972 2340 [('m', 'modified', None, _('show only modified files')),
1973 2341 ('a', 'added', None, _('show only added files')),
1974 2342 ('r', 'removed', None, _('show only removed files')),
1975 2343 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
1976 2344 ('n', 'no-status', None, _('hide status prefix')),
1977 ('0', 'print0', None, _('end filenames with NUL')),
1978 ('I', 'include', [], _('include path in search')),
1979 ('X', 'exclude', [], _('exclude path from search'))],
2345 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2346 ('I', 'include', [], _('include names matching the given patterns')),
2347 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
1980 2348 _("hg status [OPTION]... [FILE]...")),
1981 2349 "tag":
1982 2350 (tag,
1983 2351 [('l', 'local', None, _('make the tag local')),
1984 ('m', 'message', "", _('commit message')),
2352 ('m', 'message', "", _('message for tag commit log entry')),
1985 2353 ('t', 'text', "", _('commit message (deprecated: use -m)')),
1986 ('d', 'date', "", _('date code')),
1987 ('u', 'user', "", _('user'))],
2354 ('d', 'date', "", _('record datecode as commit date')),
2355 ('u', 'user', "", _('record user as commiter'))],
1988 2356 _('hg tag [OPTION]... NAME [REV]')),
1989 2357 "tags": (tags, [], _('hg tags')),
1990 2358 "tip": (tip, [], _('hg tip')),
1991 2359 "unbundle":
1992 2360 (unbundle,
1993 2361 [],
1994 2362 _('hg unbundle FILE')),
1995 2363 "undo": (undo, [], _('hg undo')),
1996 2364 "^update|up|checkout|co":
1997 2365 (update,
1998 2366 [('b', 'branch', "", _('checkout the head of a specific branch')),
1999 ('m', 'merge', None, _('allow merging of conflicts')),
2367 ('m', 'merge', None, _('allow merging of branches')),
2000 2368 ('C', 'clean', None, _('overwrite locally modified files'))],
2001 2369 _('hg update [-b TAG] [-m] [-C] [REV]')),
2002 2370 "verify": (verify, [], _('hg verify')),
2003 2371 "version": (show_version, [], _('hg version')),
2004 2372 }
2005 2373
2006 2374 globalopts = [
2007 ('R', 'repository', "", _('repository root directory')),
2008 ('', 'cwd', '', _('change working directory')),
2009 ('y', 'noninteractive', None, _('run non-interactively')),
2010 ('q', 'quiet', None, _('quiet mode')),
2011 ('v', 'verbose', None, _('verbose mode')),
2012 ('', 'debug', None, _('debug mode')),
2013 ('', 'debugger', None, _('start debugger')),
2014 ('', 'traceback', None, _('print traceback on exception')),
2015 ('', 'time', None, _('time how long the command takes')),
2016 ('', 'profile', None, _('profile')),
2017 ('', 'version', None, _('output version information and exit')),
2018 ('h', 'help', None, _('display help and exit')),
2375 ('R', 'repository', "", _("repository root directory")),
2376 ('', 'cwd', '', _("change working directory")),
2377 ('y', 'noninteractive', None, _("do not prompt, assume 'yes' for any required answers")),
2378 ('q', 'quiet', None, _("suppress output")),
2379 ('v', 'verbose', None, _("enable additional output")),
2380 ('', 'debug', None, _("enable debugging output")),
2381 ('', 'debugger', None, _("start debugger")),
2382 ('', 'traceback', None, _("print traceback on exception")),
2383 ('', 'time', None, _("time how long the command takes")),
2384 ('', 'profile', None, _("print command execution profile")),
2385 ('', 'version', None, _("output version information and exit")),
2386 ('h', 'help', None, _("display help and exit")),
2019 2387 ]
2020 2388
2021 2389 norepo = ("clone init version help debugancestor debugconfig debugdata"
2022 2390 " debugindex debugindexdot paths")
2023 2391
2024 2392 def find(cmd):
2025 2393 for e in table.keys():
2026 2394 if re.match("(%s)$" % e, cmd):
2027 2395 return e, table[e]
2028 2396
2029 2397 raise UnknownCommand(cmd)
2030 2398
2031 2399 class SignalInterrupt(Exception):
2032 2400 """Exception raised on SIGTERM and SIGHUP."""
2033 2401
2034 2402 def catchterm(*args):
2035 2403 raise SignalInterrupt
2036 2404
2037 2405 def run():
2038 2406 sys.exit(dispatch(sys.argv[1:]))
2039 2407
2040 2408 class ParseError(Exception):
2041 2409 """Exception raised on errors in parsing the command line."""
2042 2410
2043 2411 def parse(args):
2044 2412 options = {}
2045 2413 cmdoptions = {}
2046 2414
2047 2415 try:
2048 2416 args = fancyopts.fancyopts(args, globalopts, options)
2049 2417 except fancyopts.getopt.GetoptError, inst:
2050 2418 raise ParseError(None, inst)
2051 2419
2052 2420 if args:
2053 2421 cmd, args = args[0], args[1:]
2054 2422 i = find(cmd)[1]
2055 2423 c = list(i[1])
2056 2424 else:
2057 2425 cmd = None
2058 2426 c = []
2059 2427
2060 2428 # combine global options into local
2061 2429 for o in globalopts:
2062 2430 c.append((o[0], o[1], options[o[1]], o[3]))
2063 2431
2064 2432 try:
2065 2433 args = fancyopts.fancyopts(args, c, cmdoptions)
2066 2434 except fancyopts.getopt.GetoptError, inst:
2067 2435 raise ParseError(cmd, inst)
2068 2436
2069 2437 # separate global options back out
2070 2438 for o in globalopts:
2071 2439 n = o[1]
2072 2440 options[n] = cmdoptions[n]
2073 2441 del cmdoptions[n]
2074 2442
2075 2443 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
2076 2444
2077 2445 def dispatch(args):
2078 2446 signal.signal(signal.SIGTERM, catchterm)
2079 2447 try:
2080 2448 signal.signal(signal.SIGHUP, catchterm)
2081 2449 except AttributeError:
2082 2450 pass
2083 2451
2084 2452 u = ui.ui()
2085 2453 external = []
2086 2454 for x in u.extensions():
2087 2455 def on_exception(Exception, inst):
2088 2456 u.warn(_("*** failed to import extension %s\n") % x[1])
2089 2457 u.warn("%s\n" % inst)
2090 2458 if "--traceback" in sys.argv[1:]:
2091 2459 traceback.print_exc()
2092 2460 if x[1]:
2093 2461 try:
2094 2462 mod = imp.load_source(x[0], x[1])
2095 2463 except Exception, inst:
2096 2464 on_exception(Exception, inst)
2097 2465 continue
2098 2466 else:
2099 2467 def importh(name):
2100 2468 mod = __import__(name)
2101 2469 components = name.split('.')
2102 2470 for comp in components[1:]:
2103 2471 mod = getattr(mod, comp)
2104 2472 return mod
2105 2473 try:
2106 2474 mod = importh(x[0])
2107 2475 except Exception, inst:
2108 2476 on_exception(Exception, inst)
2109 2477 continue
2110 2478
2111 2479 external.append(mod)
2112 2480 for x in external:
2113 2481 cmdtable = getattr(x, 'cmdtable', {})
2114 2482 for t in cmdtable:
2115 2483 if t in table:
2116 2484 u.warn(_("module %s overrides %s\n") % (x.__name__, t))
2117 2485 table.update(cmdtable)
2118 2486
2119 2487 try:
2120 2488 cmd, func, args, options, cmdoptions = parse(args)
2121 2489 except ParseError, inst:
2122 2490 if inst.args[0]:
2123 2491 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
2124 2492 help_(u, inst.args[0])
2125 2493 else:
2126 2494 u.warn(_("hg: %s\n") % inst.args[1])
2127 2495 help_(u, 'shortlist')
2128 2496 sys.exit(-1)
2129 2497 except UnknownCommand, inst:
2130 2498 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2131 2499 help_(u, 'shortlist')
2132 2500 sys.exit(1)
2133 2501
2134 2502 if options["time"]:
2135 2503 def get_times():
2136 2504 t = os.times()
2137 2505 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
2138 2506 t = (t[0], t[1], t[2], t[3], time.clock())
2139 2507 return t
2140 2508 s = get_times()
2141 2509 def print_time():
2142 2510 t = get_times()
2143 2511 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
2144 2512 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
2145 2513 atexit.register(print_time)
2146 2514
2147 2515 u.updateopts(options["verbose"], options["debug"], options["quiet"],
2148 2516 not options["noninteractive"])
2149 2517
2150 2518 # enter the debugger before command execution
2151 2519 if options['debugger']:
2152 2520 pdb.set_trace()
2153 2521
2154 2522 try:
2155 2523 try:
2156 2524 if options['help']:
2157 2525 help_(u, cmd, options['version'])
2158 2526 sys.exit(0)
2159 2527 elif options['version']:
2160 2528 show_version(u)
2161 2529 sys.exit(0)
2162 2530 elif not cmd:
2163 2531 help_(u, 'shortlist')
2164 2532 sys.exit(0)
2165 2533
2166 2534 if options['cwd']:
2167 2535 try:
2168 2536 os.chdir(options['cwd'])
2169 2537 except OSError, inst:
2170 2538 raise util.Abort('%s: %s' %
2171 2539 (options['cwd'], inst.strerror))
2172 2540
2173 2541 if cmd not in norepo.split():
2174 2542 path = options["repository"] or ""
2175 2543 repo = hg.repository(ui=u, path=path)
2176 2544 for x in external:
2177 2545 if hasattr(x, 'reposetup'): x.reposetup(u, repo)
2178 2546 d = lambda: func(u, repo, *args, **cmdoptions)
2179 2547 else:
2180 2548 d = lambda: func(u, *args, **cmdoptions)
2181 2549
2182 2550 if options['profile']:
2183 2551 import hotshot, hotshot.stats
2184 2552 prof = hotshot.Profile("hg.prof")
2185 2553 r = prof.runcall(d)
2186 2554 prof.close()
2187 2555 stats = hotshot.stats.load("hg.prof")
2188 2556 stats.strip_dirs()
2189 2557 stats.sort_stats('time', 'calls')
2190 2558 stats.print_stats(40)
2191 2559 return r
2192 2560 else:
2193 2561 return d()
2194 2562 except:
2195 2563 # enter the debugger when we hit an exception
2196 2564 if options['debugger']:
2197 2565 pdb.post_mortem(sys.exc_info()[2])
2198 2566 if options['traceback']:
2199 2567 traceback.print_exc()
2200 2568 raise
2201 2569 except hg.RepoError, inst:
2202 2570 u.warn(_("abort: "), inst, "!\n")
2203 2571 except revlog.RevlogError, inst:
2204 2572 u.warn(_("abort: "), inst, "!\n")
2205 2573 except SignalInterrupt:
2206 2574 u.warn(_("killed!\n"))
2207 2575 except KeyboardInterrupt:
2208 2576 try:
2209 2577 u.warn(_("interrupted!\n"))
2210 2578 except IOError, inst:
2211 2579 if inst.errno == errno.EPIPE:
2212 2580 if u.debugflag:
2213 2581 u.warn(_("\nbroken pipe\n"))
2214 2582 else:
2215 2583 raise
2216 2584 except IOError, inst:
2217 2585 if hasattr(inst, "code"):
2218 2586 u.warn(_("abort: %s\n") % inst)
2219 2587 elif hasattr(inst, "reason"):
2220 2588 u.warn(_("abort: error: %s\n") % inst.reason[1])
2221 2589 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
2222 2590 if u.debugflag:
2223 2591 u.warn(_("broken pipe\n"))
2224 2592 elif getattr(inst, "strerror", None):
2225 2593 if getattr(inst, "filename", None):
2226 2594 u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename))
2227 2595 else:
2228 2596 u.warn(_("abort: %s\n") % inst.strerror)
2229 2597 else:
2230 2598 raise
2231 2599 except OSError, inst:
2232 2600 if hasattr(inst, "filename"):
2233 2601 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
2234 2602 else:
2235 2603 u.warn(_("abort: %s\n") % inst.strerror)
2236 2604 except util.Abort, inst:
2237 2605 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
2238 2606 sys.exit(1)
2239 2607 except TypeError, inst:
2240 2608 # was this an argument error?
2241 2609 tb = traceback.extract_tb(sys.exc_info()[2])
2242 2610 if len(tb) > 2: # no
2243 2611 raise
2244 2612 u.debug(inst, "\n")
2245 2613 u.warn(_("%s: invalid arguments\n") % cmd)
2246 2614 help_(u, cmd)
2247 2615 except UnknownCommand, inst:
2248 2616 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2249 2617 help_(u, 'shortlist')
2250 2618 except SystemExit:
2251 2619 # don't catch this in the catch-all below
2252 2620 raise
2253 2621 except:
2254 2622 u.warn(_("** unknown exception encountered, details follow\n"))
2255 2623 u.warn(_("** report bug details to mercurial@selenic.com\n"))
2256 2624 raise
2257 2625
2258 2626 sys.exit(-1)
@@ -1,211 +1,244
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 working directory (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 pull pull changes from the specified source
14 14 push push changes to the specified destination
15 15 remove remove the specified files on the next commit
16 16 revert revert modified files or dirs back to their unmodified states
17 17 serve export the repository via HTTP
18 18 status show changed files in the working directory
19 19 update update or merge working directory
20 20 add add the specified files on the next commit
21 21 annotate show changeset information per file line
22 22 clone make a copy of an existing repository
23 23 commit commit the specified files or all outstanding changes
24 24 diff diff working directory (or selected files)
25 25 export dump the header and diffs for one or more changesets
26 26 init create a new repository in the given directory
27 27 log show revision history of entire repository or files
28 28 pull pull changes from the specified source
29 29 push push changes to the specified destination
30 30 remove remove the specified files on the next commit
31 31 revert revert modified files or dirs back to their unmodified states
32 32 serve export the repository via HTTP
33 33 status show changed files in the working directory
34 34 update update or merge working directory
35 35 Mercurial Distributed SCM
36 36
37 37 list of commands (use "hg help -v" to show aliases and global options):
38 38
39 39 add add the specified files on the next commit
40 40 addremove add all new files, delete all missing files
41 41 annotate show changeset information per file line
42 42 bundle create a changegroup file
43 43 cat output the latest or given revisions of files
44 44 clone make a copy of an existing repository
45 45 commit commit the specified files or all outstanding changes
46 46 copy mark files as copied for the next commit
47 47 diff diff working directory (or selected files)
48 48 export dump the header and diffs for one or more changesets
49 49 forget don't add the specified files on the next commit
50 50 grep search for a pattern in specified files and revisions
51 51 heads show current repository heads
52 52 help show help for a given command or all commands
53 53 identify print information about the working copy
54 54 import import an ordered set of patches
55 55 incoming show new changesets found in source
56 56 init create a new repository in the given directory
57 57 locate locate files matching specific patterns
58 58 log show revision history of entire repository or files
59 59 manifest output the latest or given revision of the project manifest
60 60 outgoing show changesets not found in destination
61 61 parents show the parents of the working dir or revision
62 62 paths show definition of symbolic path names
63 63 pull pull changes from the specified source
64 64 push push changes to the specified destination
65 65 rawcommit raw commit interface
66 66 recover roll back an interrupted transaction
67 67 remove remove the specified files on the next commit
68 68 rename rename files; equivalent of copy + remove
69 69 revert revert modified files or dirs back to their unmodified states
70 70 root print the root (top) of the current working dir
71 71 serve export the repository via HTTP
72 72 status show changed files in the working directory
73 73 tag add a tag for the current tip or a given revision
74 74 tags list repository tags
75 75 tip show the tip revision
76 76 unbundle apply a changegroup file
77 77 undo undo the last commit or pull
78 78 update update or merge working directory
79 79 verify verify the integrity of the repository
80 80 version output version and copyright information
81 81 add add the specified files on the next commit
82 82 addremove add all new files, delete all missing files
83 83 annotate show changeset information per file line
84 84 bundle create a changegroup file
85 85 cat output the latest or given revisions of files
86 86 clone make a copy of an existing repository
87 87 commit commit the specified files or all outstanding changes
88 88 copy mark files as copied for the next commit
89 89 diff diff working directory (or selected files)
90 90 export dump the header and diffs for one or more changesets
91 91 forget don't add the specified files on the next commit
92 92 grep search for a pattern in specified files and revisions
93 93 heads show current repository heads
94 94 help show help for a given command or all commands
95 95 identify print information about the working copy
96 96 import import an ordered set of patches
97 97 incoming show new changesets found in source
98 98 init create a new repository in the given directory
99 99 locate locate files matching specific patterns
100 100 log show revision history of entire repository or files
101 101 manifest output the latest or given revision of the project manifest
102 102 outgoing show changesets not found in destination
103 103 parents show the parents of the working dir or revision
104 104 paths show definition of symbolic path names
105 105 pull pull changes from the specified source
106 106 push push changes to the specified destination
107 107 rawcommit raw commit interface
108 108 recover roll back an interrupted transaction
109 109 remove remove the specified files on the next commit
110 110 rename rename files; equivalent of copy + remove
111 111 revert revert modified files or dirs back to their unmodified states
112 112 root print the root (top) of the current working dir
113 113 serve export the repository via HTTP
114 114 status show changed files in the working directory
115 115 tag add a tag for the current tip or a given revision
116 116 tags list repository tags
117 117 tip show the tip revision
118 118 unbundle apply a changegroup file
119 119 undo undo the last commit or pull
120 120 update update or merge working directory
121 121 verify verify the integrity of the repository
122 122 version output version and copyright information
123 123 hg add [OPTION]... [FILE]...
124 124
125 125 add the specified files on the next commit
126 126
127 Schedule files to be version controlled and added to the repository.
128
129 The files will be added to the repository at the next commit.
130
131 If no names are given, add all files in the current directory and
132 its subdirectories.
133
127 134 options:
128 135
129 -I --include include path in search
130 -X --exclude exclude path from search
136 -I --include include names matching the given patterns
137 -X --exclude exclude names matching the given patterns
131 138 hg add: option --skjdfks not recognized
132 139 hg add [OPTION]... [FILE]...
133 140
134 141 add the specified files on the next commit
135 142
143 Schedule files to be version controlled and added to the repository.
144
145 The files will be added to the repository at the next commit.
146
147 If no names are given, add all files in the current directory and
148 its subdirectories.
149
136 150 options:
137 151
138 -I --include include path in search
139 -X --exclude exclude path from search
152 -I --include include names matching the given patterns
153 -X --exclude exclude names matching the given patterns
140 154 hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...
141 155
142 156 diff working directory (or selected files)
143 157
158 Show differences between revisions for the specified files.
159
160 Differences between files are shown using the unified diff format.
161
162 When two revision arguments are given, then changes are shown
163 between those revisions. If only one revision is specified then
164 that revision is compared to the working directory, and, when no
165 revisions are specified, the working directory files are compared
166 to its parent.
167
168 Without the -a option, diff will avoid generating diffs of files
169 it detects as binary. With -a, diff will generate a diff anyway,
170 probably with undesirable results.
171
144 172 options:
145 173
146 174 -r --rev revision
147 175 -a --text treat all files as text
148 -I --include include path in search
149 -X --exclude exclude path from search
176 -I --include include names matching the given patterns
177 -X --exclude exclude names matching the given patterns
150 178 hg status [OPTION]... [FILE]...
151 179
152 180 show changed files in the working directory
153 181
182 Show changed files in the working directory. If no names are
183 given, all files are shown. Otherwise, only files matching the
184 given names are shown.
185
186 The codes used to show the status of files are:
154 187 M = modified
155 188 A = added
156 189 R = removed
157 190 ? = not tracked
158 191
159 192 options:
160 193
161 194 -m --modified show only modified files
162 195 -a --added show only added files
163 196 -r --removed show only removed files
164 197 -u --unknown show only unknown (not tracked) files
165 198 -n --no-status hide status prefix
166 -0 --print0 end filenames with NUL
167 -I --include include path in search
168 -X --exclude exclude path from search
199 -0 --print0 end filenames with NUL, for use with xargs
200 -I --include include names matching the given patterns
201 -X --exclude exclude names matching the given patterns
169 202 hg status [OPTION]... [FILE]...
170 203
171 204 show changed files in the working directory
172 205 hg: unknown command 'foo'
173 206 Mercurial Distributed SCM
174 207
175 208 basic commands (use "hg help" for the full list or option "-v" for details):
176 209
177 210 add add the specified files on the next commit
178 211 annotate show changeset information per file line
179 212 clone make a copy of an existing repository
180 213 commit commit the specified files or all outstanding changes
181 214 diff diff working directory (or selected files)
182 215 export dump the header and diffs for one or more changesets
183 216 init create a new repository in the given directory
184 217 log show revision history of entire repository or files
185 218 pull pull changes from the specified source
186 219 push push changes to the specified destination
187 220 remove remove the specified files on the next commit
188 221 revert revert modified files or dirs back to their unmodified states
189 222 serve export the repository via HTTP
190 223 status show changed files in the working directory
191 224 update update or merge working directory
192 225 hg: unknown command 'skjdfks'
193 226 Mercurial Distributed SCM
194 227
195 228 basic commands (use "hg help" for the full list or option "-v" for details):
196 229
197 230 add add the specified files on the next commit
198 231 annotate show changeset information per file line
199 232 clone make a copy of an existing repository
200 233 commit commit the specified files or all outstanding changes
201 234 diff diff working directory (or selected files)
202 235 export dump the header and diffs for one or more changesets
203 236 init create a new repository in the given directory
204 237 log show revision history of entire repository or files
205 238 pull pull changes from the specified source
206 239 push push changes to the specified destination
207 240 remove remove the specified files on the next commit
208 241 revert revert modified files or dirs back to their unmodified states
209 242 serve export the repository via HTTP
210 243 status show changed files in the working directory
211 244 update update or merge working directory
General Comments 0
You need to be logged in to leave comments. Login now