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