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