PageRenderTime 64ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/mercurial/commands.py

https://bitbucket.org/mirror/mercurial/
Python | 6031 lines | 5849 code | 94 blank | 88 comment | 167 complexity | 3fc03cff89d81608bde73ee2eb8b4e16 MD5 | raw file
Possible License(s): GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. # commands.py - command processing for mercurial
  2. #
  3. # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
  4. #
  5. # This software may be used and distributed according to the terms of the
  6. # GNU General Public License version 2 or any later version.
  7. from node import hex, bin, nullid, nullrev, short
  8. from lock import release
  9. from i18n import _
  10. import os, re, difflib, time, tempfile, errno
  11. import sys
  12. import hg, scmutil, util, revlog, copies, error, bookmarks
  13. import patch, help, encoding, templatekw, discovery
  14. import archival, changegroup, cmdutil, hbisect
  15. import sshserver, hgweb, commandserver
  16. import extensions
  17. from hgweb import server as hgweb_server
  18. import merge as mergemod
  19. import minirst, revset, fileset
  20. import dagparser, context, simplemerge, graphmod
  21. import random
  22. import setdiscovery, treediscovery, dagutil, pvec, localrepo
  23. import phases, obsolete, exchange
  24. table = {}
  25. command = cmdutil.command(table)
  26. # Space delimited list of commands that don't require local repositories.
  27. # This should be populated by passing norepo=True into the @command decorator.
  28. norepo = ''
  29. # Space delimited list of commands that optionally require local repositories.
  30. # This should be populated by passing optionalrepo=True into the @command
  31. # decorator.
  32. optionalrepo = ''
  33. # Space delimited list of commands that will examine arguments looking for
  34. # a repository. This should be populated by passing inferrepo=True into the
  35. # @command decorator.
  36. inferrepo = ''
  37. # common command options
  38. globalopts = [
  39. ('R', 'repository', '',
  40. _('repository root directory or name of overlay bundle file'),
  41. _('REPO')),
  42. ('', 'cwd', '',
  43. _('change working directory'), _('DIR')),
  44. ('y', 'noninteractive', None,
  45. _('do not prompt, automatically pick the first choice for all prompts')),
  46. ('q', 'quiet', None, _('suppress output')),
  47. ('v', 'verbose', None, _('enable additional output')),
  48. ('', 'config', [],
  49. _('set/override config option (use \'section.name=value\')'),
  50. _('CONFIG')),
  51. ('', 'debug', None, _('enable debugging output')),
  52. ('', 'debugger', None, _('start debugger')),
  53. ('', 'encoding', encoding.encoding, _('set the charset encoding'),
  54. _('ENCODE')),
  55. ('', 'encodingmode', encoding.encodingmode,
  56. _('set the charset encoding mode'), _('MODE')),
  57. ('', 'traceback', None, _('always print a traceback on exception')),
  58. ('', 'time', None, _('time how long the command takes')),
  59. ('', 'profile', None, _('print command execution profile')),
  60. ('', 'version', None, _('output version information and exit')),
  61. ('h', 'help', None, _('display help and exit')),
  62. ('', 'hidden', False, _('consider hidden changesets')),
  63. ]
  64. dryrunopts = [('n', 'dry-run', None,
  65. _('do not perform actions, just print output'))]
  66. remoteopts = [
  67. ('e', 'ssh', '',
  68. _('specify ssh command to use'), _('CMD')),
  69. ('', 'remotecmd', '',
  70. _('specify hg command to run on the remote side'), _('CMD')),
  71. ('', 'insecure', None,
  72. _('do not verify server certificate (ignoring web.cacerts config)')),
  73. ]
  74. walkopts = [
  75. ('I', 'include', [],
  76. _('include names matching the given patterns'), _('PATTERN')),
  77. ('X', 'exclude', [],
  78. _('exclude names matching the given patterns'), _('PATTERN')),
  79. ]
  80. commitopts = [
  81. ('m', 'message', '',
  82. _('use text as commit message'), _('TEXT')),
  83. ('l', 'logfile', '',
  84. _('read commit message from file'), _('FILE')),
  85. ]
  86. commitopts2 = [
  87. ('d', 'date', '',
  88. _('record the specified date as commit date'), _('DATE')),
  89. ('u', 'user', '',
  90. _('record the specified user as committer'), _('USER')),
  91. ]
  92. templateopts = [
  93. ('', 'style', '',
  94. _('display using template map file (DEPRECATED)'), _('STYLE')),
  95. ('T', 'template', '',
  96. _('display with template'), _('TEMPLATE')),
  97. ]
  98. logopts = [
  99. ('p', 'patch', None, _('show patch')),
  100. ('g', 'git', None, _('use git extended diff format')),
  101. ('l', 'limit', '',
  102. _('limit number of changes displayed'), _('NUM')),
  103. ('M', 'no-merges', None, _('do not show merges')),
  104. ('', 'stat', None, _('output diffstat-style summary of changes')),
  105. ('G', 'graph', None, _("show the revision DAG")),
  106. ] + templateopts
  107. diffopts = [
  108. ('a', 'text', None, _('treat all files as text')),
  109. ('g', 'git', None, _('use git extended diff format')),
  110. ('', 'nodates', None, _('omit dates from diff headers'))
  111. ]
  112. diffwsopts = [
  113. ('w', 'ignore-all-space', None,
  114. _('ignore white space when comparing lines')),
  115. ('b', 'ignore-space-change', None,
  116. _('ignore changes in the amount of white space')),
  117. ('B', 'ignore-blank-lines', None,
  118. _('ignore changes whose lines are all blank')),
  119. ]
  120. diffopts2 = [
  121. ('p', 'show-function', None, _('show which function each change is in')),
  122. ('', 'reverse', None, _('produce a diff that undoes the changes')),
  123. ] + diffwsopts + [
  124. ('U', 'unified', '',
  125. _('number of lines of context to show'), _('NUM')),
  126. ('', 'stat', None, _('output diffstat-style summary of changes')),
  127. ]
  128. mergetoolopts = [
  129. ('t', 'tool', '', _('specify merge tool')),
  130. ]
  131. similarityopts = [
  132. ('s', 'similarity', '',
  133. _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
  134. ]
  135. subrepoopts = [
  136. ('S', 'subrepos', None,
  137. _('recurse into subrepositories'))
  138. ]
  139. # Commands start here, listed alphabetically
  140. @command('^add',
  141. walkopts + subrepoopts + dryrunopts,
  142. _('[OPTION]... [FILE]...'),
  143. inferrepo=True)
  144. def add(ui, repo, *pats, **opts):
  145. """add the specified files on the next commit
  146. Schedule files to be version controlled and added to the
  147. repository.
  148. The files will be added to the repository at the next commit. To
  149. undo an add before that, see :hg:`forget`.
  150. If no names are given, add all files to the repository.
  151. .. container:: verbose
  152. An example showing how new (unknown) files are added
  153. automatically by :hg:`add`::
  154. $ ls
  155. foo.c
  156. $ hg status
  157. ? foo.c
  158. $ hg add
  159. adding foo.c
  160. $ hg status
  161. A foo.c
  162. Returns 0 if all files are successfully added.
  163. """
  164. m = scmutil.match(repo[None], pats, opts)
  165. rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
  166. opts.get('subrepos'), prefix="", explicitonly=False)
  167. return rejected and 1 or 0
  168. @command('addremove',
  169. similarityopts + walkopts + dryrunopts,
  170. _('[OPTION]... [FILE]...'),
  171. inferrepo=True)
  172. def addremove(ui, repo, *pats, **opts):
  173. """add all new files, delete all missing files
  174. Add all new files and remove all missing files from the
  175. repository.
  176. New files are ignored if they match any of the patterns in
  177. ``.hgignore``. As with add, these changes take effect at the next
  178. commit.
  179. Use the -s/--similarity option to detect renamed files. This
  180. option takes a percentage between 0 (disabled) and 100 (files must
  181. be identical) as its parameter. With a parameter greater than 0,
  182. this compares every removed file with every added file and records
  183. those similar enough as renames. Detecting renamed files this way
  184. can be expensive. After using this option, :hg:`status -C` can be
  185. used to check which files were identified as moved or renamed. If
  186. not specified, -s/--similarity defaults to 100 and only renames of
  187. identical files are detected.
  188. Returns 0 if all files are successfully added.
  189. """
  190. try:
  191. sim = float(opts.get('similarity') or 100)
  192. except ValueError:
  193. raise util.Abort(_('similarity must be a number'))
  194. if sim < 0 or sim > 100:
  195. raise util.Abort(_('similarity must be between 0 and 100'))
  196. return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
  197. @command('^annotate|blame',
  198. [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
  199. ('', 'follow', None,
  200. _('follow copies/renames and list the filename (DEPRECATED)')),
  201. ('', 'no-follow', None, _("don't follow copies and renames")),
  202. ('a', 'text', None, _('treat all files as text')),
  203. ('u', 'user', None, _('list the author (long with -v)')),
  204. ('f', 'file', None, _('list the filename')),
  205. ('d', 'date', None, _('list the date (short with -q)')),
  206. ('n', 'number', None, _('list the revision number (default)')),
  207. ('c', 'changeset', None, _('list the changeset')),
  208. ('l', 'line-number', None, _('show line number at the first appearance'))
  209. ] + diffwsopts + walkopts,
  210. _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
  211. inferrepo=True)
  212. def annotate(ui, repo, *pats, **opts):
  213. """show changeset information by line for each file
  214. List changes in files, showing the revision id responsible for
  215. each line
  216. This command is useful for discovering when a change was made and
  217. by whom.
  218. Without the -a/--text option, annotate will avoid processing files
  219. it detects as binary. With -a, annotate will annotate the file
  220. anyway, although the results will probably be neither useful
  221. nor desirable.
  222. Returns 0 on success.
  223. """
  224. if opts.get('follow'):
  225. # --follow is deprecated and now just an alias for -f/--file
  226. # to mimic the behavior of Mercurial before version 1.5
  227. opts['file'] = True
  228. datefunc = ui.quiet and util.shortdate or util.datestr
  229. getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
  230. if not pats:
  231. raise util.Abort(_('at least one filename or pattern is required'))
  232. hexfn = ui.debugflag and hex or short
  233. opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
  234. ('number', ' ', lambda x: str(x[0].rev())),
  235. ('changeset', ' ', lambda x: hexfn(x[0].node())),
  236. ('date', ' ', getdate),
  237. ('file', ' ', lambda x: x[0].path()),
  238. ('line_number', ':', lambda x: str(x[1])),
  239. ]
  240. if (not opts.get('user') and not opts.get('changeset')
  241. and not opts.get('date') and not opts.get('file')):
  242. opts['number'] = True
  243. linenumber = opts.get('line_number') is not None
  244. if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
  245. raise util.Abort(_('at least one of -n/-c is required for -l'))
  246. funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
  247. funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
  248. def bad(x, y):
  249. raise util.Abort("%s: %s" % (x, y))
  250. ctx = scmutil.revsingle(repo, opts.get('rev'))
  251. m = scmutil.match(ctx, pats, opts)
  252. m.bad = bad
  253. follow = not opts.get('no_follow')
  254. diffopts = patch.diffopts(ui, opts, section='annotate')
  255. for abs in ctx.walk(m):
  256. fctx = ctx[abs]
  257. if not opts.get('text') and util.binary(fctx.data()):
  258. ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
  259. continue
  260. lines = fctx.annotate(follow=follow, linenumber=linenumber,
  261. diffopts=diffopts)
  262. pieces = []
  263. for f, sep in funcmap:
  264. l = [f(n) for n, dummy in lines]
  265. if l:
  266. sized = [(x, encoding.colwidth(x)) for x in l]
  267. ml = max([w for x, w in sized])
  268. pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
  269. for x, w in sized])
  270. if pieces:
  271. for p, l in zip(zip(*pieces), lines):
  272. ui.write("%s: %s" % ("".join(p), l[1]))
  273. if lines and not lines[-1][1].endswith('\n'):
  274. ui.write('\n')
  275. @command('archive',
  276. [('', 'no-decode', None, _('do not pass files through decoders')),
  277. ('p', 'prefix', '', _('directory prefix for files in archive'),
  278. _('PREFIX')),
  279. ('r', 'rev', '', _('revision to distribute'), _('REV')),
  280. ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
  281. ] + subrepoopts + walkopts,
  282. _('[OPTION]... DEST'))
  283. def archive(ui, repo, dest, **opts):
  284. '''create an unversioned archive of a repository revision
  285. By default, the revision used is the parent of the working
  286. directory; use -r/--rev to specify a different revision.
  287. The archive type is automatically detected based on file
  288. extension (or override using -t/--type).
  289. .. container:: verbose
  290. Examples:
  291. - create a zip file containing the 1.0 release::
  292. hg archive -r 1.0 project-1.0.zip
  293. - create a tarball excluding .hg files::
  294. hg archive project.tar.gz -X ".hg*"
  295. Valid types are:
  296. :``files``: a directory full of files (default)
  297. :``tar``: tar archive, uncompressed
  298. :``tbz2``: tar archive, compressed using bzip2
  299. :``tgz``: tar archive, compressed using gzip
  300. :``uzip``: zip archive, uncompressed
  301. :``zip``: zip archive, compressed using deflate
  302. The exact name of the destination archive or directory is given
  303. using a format string; see :hg:`help export` for details.
  304. Each member added to an archive file has a directory prefix
  305. prepended. Use -p/--prefix to specify a format string for the
  306. prefix. The default is the basename of the archive, with suffixes
  307. removed.
  308. Returns 0 on success.
  309. '''
  310. ctx = scmutil.revsingle(repo, opts.get('rev'))
  311. if not ctx:
  312. raise util.Abort(_('no working directory: please specify a revision'))
  313. node = ctx.node()
  314. dest = cmdutil.makefilename(repo, dest, node)
  315. if os.path.realpath(dest) == repo.root:
  316. raise util.Abort(_('repository root cannot be destination'))
  317. kind = opts.get('type') or archival.guesskind(dest) or 'files'
  318. prefix = opts.get('prefix')
  319. if dest == '-':
  320. if kind == 'files':
  321. raise util.Abort(_('cannot archive plain files to stdout'))
  322. dest = cmdutil.makefileobj(repo, dest)
  323. if not prefix:
  324. prefix = os.path.basename(repo.root) + '-%h'
  325. prefix = cmdutil.makefilename(repo, prefix, node)
  326. matchfn = scmutil.match(ctx, [], opts)
  327. archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
  328. matchfn, prefix, subrepos=opts.get('subrepos'))
  329. @command('backout',
  330. [('', 'merge', None, _('merge with old dirstate parent after backout')),
  331. ('', 'parent', '',
  332. _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
  333. ('r', 'rev', '', _('revision to backout'), _('REV')),
  334. ('e', 'edit', False, _('invoke editor on commit messages')),
  335. ] + mergetoolopts + walkopts + commitopts + commitopts2,
  336. _('[OPTION]... [-r] REV'))
  337. def backout(ui, repo, node=None, rev=None, **opts):
  338. '''reverse effect of earlier changeset
  339. Prepare a new changeset with the effect of REV undone in the
  340. current working directory.
  341. If REV is the parent of the working directory, then this new changeset
  342. is committed automatically. Otherwise, hg needs to merge the
  343. changes and the merged result is left uncommitted.
  344. .. note::
  345. backout cannot be used to fix either an unwanted or
  346. incorrect merge.
  347. .. container:: verbose
  348. By default, the pending changeset will have one parent,
  349. maintaining a linear history. With --merge, the pending
  350. changeset will instead have two parents: the old parent of the
  351. working directory and a new child of REV that simply undoes REV.
  352. Before version 1.7, the behavior without --merge was equivalent
  353. to specifying --merge followed by :hg:`update --clean .` to
  354. cancel the merge and leave the child of REV as a head to be
  355. merged separately.
  356. See :hg:`help dates` for a list of formats valid for -d/--date.
  357. Returns 0 on success, 1 if nothing to backout or there are unresolved
  358. files.
  359. '''
  360. if rev and node:
  361. raise util.Abort(_("please specify just one revision"))
  362. if not rev:
  363. rev = node
  364. if not rev:
  365. raise util.Abort(_("please specify a revision to backout"))
  366. date = opts.get('date')
  367. if date:
  368. opts['date'] = util.parsedate(date)
  369. cmdutil.checkunfinished(repo)
  370. cmdutil.bailifchanged(repo)
  371. node = scmutil.revsingle(repo, rev).node()
  372. op1, op2 = repo.dirstate.parents()
  373. if node not in repo.changelog.commonancestorsheads(op1, node):
  374. raise util.Abort(_('cannot backout change that is not an ancestor'))
  375. p1, p2 = repo.changelog.parents(node)
  376. if p1 == nullid:
  377. raise util.Abort(_('cannot backout a change with no parents'))
  378. if p2 != nullid:
  379. if not opts.get('parent'):
  380. raise util.Abort(_('cannot backout a merge changeset'))
  381. p = repo.lookup(opts['parent'])
  382. if p not in (p1, p2):
  383. raise util.Abort(_('%s is not a parent of %s') %
  384. (short(p), short(node)))
  385. parent = p
  386. else:
  387. if opts.get('parent'):
  388. raise util.Abort(_('cannot use --parent on non-merge changeset'))
  389. parent = p1
  390. # the backout should appear on the same branch
  391. wlock = repo.wlock()
  392. try:
  393. branch = repo.dirstate.branch()
  394. bheads = repo.branchheads(branch)
  395. rctx = scmutil.revsingle(repo, hex(parent))
  396. if not opts.get('merge') and op1 != node:
  397. try:
  398. ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
  399. 'backout')
  400. stats = mergemod.update(repo, parent, True, True, False,
  401. node, False)
  402. repo.setparents(op1, op2)
  403. hg._showstats(repo, stats)
  404. if stats[3]:
  405. repo.ui.status(_("use 'hg resolve' to retry unresolved "
  406. "file merges\n"))
  407. else:
  408. msg = _("changeset %s backed out, "
  409. "don't forget to commit.\n")
  410. ui.status(msg % short(node))
  411. return stats[3] > 0
  412. finally:
  413. ui.setconfig('ui', 'forcemerge', '', '')
  414. else:
  415. hg.clean(repo, node, show_stats=False)
  416. repo.dirstate.setbranch(branch)
  417. cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
  418. def commitfunc(ui, repo, message, match, opts):
  419. e = cmdutil.getcommiteditor(**opts)
  420. if not message:
  421. # we don't translate commit messages
  422. message = "Backed out changeset %s" % short(node)
  423. e = cmdutil.getcommiteditor(edit=True)
  424. return repo.commit(message, opts.get('user'), opts.get('date'),
  425. match, editor=e)
  426. newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
  427. if not newnode:
  428. ui.status(_("nothing changed\n"))
  429. return 1
  430. cmdutil.commitstatus(repo, newnode, branch, bheads)
  431. def nice(node):
  432. return '%d:%s' % (repo.changelog.rev(node), short(node))
  433. ui.status(_('changeset %s backs out changeset %s\n') %
  434. (nice(repo.changelog.tip()), nice(node)))
  435. if opts.get('merge') and op1 != node:
  436. hg.clean(repo, op1, show_stats=False)
  437. ui.status(_('merging with changeset %s\n')
  438. % nice(repo.changelog.tip()))
  439. try:
  440. ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
  441. 'backout')
  442. return hg.merge(repo, hex(repo.changelog.tip()))
  443. finally:
  444. ui.setconfig('ui', 'forcemerge', '', '')
  445. finally:
  446. wlock.release()
  447. return 0
  448. @command('bisect',
  449. [('r', 'reset', False, _('reset bisect state')),
  450. ('g', 'good', False, _('mark changeset good')),
  451. ('b', 'bad', False, _('mark changeset bad')),
  452. ('s', 'skip', False, _('skip testing changeset')),
  453. ('e', 'extend', False, _('extend the bisect range')),
  454. ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
  455. ('U', 'noupdate', False, _('do not update to target'))],
  456. _("[-gbsr] [-U] [-c CMD] [REV]"))
  457. def bisect(ui, repo, rev=None, extra=None, command=None,
  458. reset=None, good=None, bad=None, skip=None, extend=None,
  459. noupdate=None):
  460. """subdivision search of changesets
  461. This command helps to find changesets which introduce problems. To
  462. use, mark the earliest changeset you know exhibits the problem as
  463. bad, then mark the latest changeset which is free from the problem
  464. as good. Bisect will update your working directory to a revision
  465. for testing (unless the -U/--noupdate option is specified). Once
  466. you have performed tests, mark the working directory as good or
  467. bad, and bisect will either update to another candidate changeset
  468. or announce that it has found the bad revision.
  469. As a shortcut, you can also use the revision argument to mark a
  470. revision as good or bad without checking it out first.
  471. If you supply a command, it will be used for automatic bisection.
  472. The environment variable HG_NODE will contain the ID of the
  473. changeset being tested. The exit status of the command will be
  474. used to mark revisions as good or bad: status 0 means good, 125
  475. means to skip the revision, 127 (command not found) will abort the
  476. bisection, and any other non-zero exit status means the revision
  477. is bad.
  478. .. container:: verbose
  479. Some examples:
  480. - start a bisection with known bad revision 34, and good revision 12::
  481. hg bisect --bad 34
  482. hg bisect --good 12
  483. - advance the current bisection by marking current revision as good or
  484. bad::
  485. hg bisect --good
  486. hg bisect --bad
  487. - mark the current revision, or a known revision, to be skipped (e.g. if
  488. that revision is not usable because of another issue)::
  489. hg bisect --skip
  490. hg bisect --skip 23
  491. - skip all revisions that do not touch directories ``foo`` or ``bar``::
  492. hg bisect --skip "!( file('path:foo') & file('path:bar') )"
  493. - forget the current bisection::
  494. hg bisect --reset
  495. - use 'make && make tests' to automatically find the first broken
  496. revision::
  497. hg bisect --reset
  498. hg bisect --bad 34
  499. hg bisect --good 12
  500. hg bisect --command "make && make tests"
  501. - see all changesets whose states are already known in the current
  502. bisection::
  503. hg log -r "bisect(pruned)"
  504. - see the changeset currently being bisected (especially useful
  505. if running with -U/--noupdate)::
  506. hg log -r "bisect(current)"
  507. - see all changesets that took part in the current bisection::
  508. hg log -r "bisect(range)"
  509. - you can even get a nice graph::
  510. hg log --graph -r "bisect(range)"
  511. See :hg:`help revsets` for more about the `bisect()` keyword.
  512. Returns 0 on success.
  513. """
  514. def extendbisectrange(nodes, good):
  515. # bisect is incomplete when it ends on a merge node and
  516. # one of the parent was not checked.
  517. parents = repo[nodes[0]].parents()
  518. if len(parents) > 1:
  519. side = good and state['bad'] or state['good']
  520. num = len(set(i.node() for i in parents) & set(side))
  521. if num == 1:
  522. return parents[0].ancestor(parents[1])
  523. return None
  524. def print_result(nodes, good):
  525. displayer = cmdutil.show_changeset(ui, repo, {})
  526. if len(nodes) == 1:
  527. # narrowed it down to a single revision
  528. if good:
  529. ui.write(_("The first good revision is:\n"))
  530. else:
  531. ui.write(_("The first bad revision is:\n"))
  532. displayer.show(repo[nodes[0]])
  533. extendnode = extendbisectrange(nodes, good)
  534. if extendnode is not None:
  535. ui.write(_('Not all ancestors of this changeset have been'
  536. ' checked.\nUse bisect --extend to continue the '
  537. 'bisection from\nthe common ancestor, %s.\n')
  538. % extendnode)
  539. else:
  540. # multiple possible revisions
  541. if good:
  542. ui.write(_("Due to skipped revisions, the first "
  543. "good revision could be any of:\n"))
  544. else:
  545. ui.write(_("Due to skipped revisions, the first "
  546. "bad revision could be any of:\n"))
  547. for n in nodes:
  548. displayer.show(repo[n])
  549. displayer.close()
  550. def check_state(state, interactive=True):
  551. if not state['good'] or not state['bad']:
  552. if (good or bad or skip or reset) and interactive:
  553. return
  554. if not state['good']:
  555. raise util.Abort(_('cannot bisect (no known good revisions)'))
  556. else:
  557. raise util.Abort(_('cannot bisect (no known bad revisions)'))
  558. return True
  559. # backward compatibility
  560. if rev in "good bad reset init".split():
  561. ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
  562. cmd, rev, extra = rev, extra, None
  563. if cmd == "good":
  564. good = True
  565. elif cmd == "bad":
  566. bad = True
  567. else:
  568. reset = True
  569. elif extra or good + bad + skip + reset + extend + bool(command) > 1:
  570. raise util.Abort(_('incompatible arguments'))
  571. cmdutil.checkunfinished(repo)
  572. if reset:
  573. p = repo.join("bisect.state")
  574. if os.path.exists(p):
  575. os.unlink(p)
  576. return
  577. state = hbisect.load_state(repo)
  578. if command:
  579. changesets = 1
  580. if noupdate:
  581. try:
  582. node = state['current'][0]
  583. except LookupError:
  584. raise util.Abort(_('current bisect revision is unknown - '
  585. 'start a new bisect to fix'))
  586. else:
  587. node, p2 = repo.dirstate.parents()
  588. if p2 != nullid:
  589. raise util.Abort(_('current bisect revision is a merge'))
  590. try:
  591. while changesets:
  592. # update state
  593. state['current'] = [node]
  594. hbisect.save_state(repo, state)
  595. status = util.system(command,
  596. environ={'HG_NODE': hex(node)},
  597. out=ui.fout)
  598. if status == 125:
  599. transition = "skip"
  600. elif status == 0:
  601. transition = "good"
  602. # status < 0 means process was killed
  603. elif status == 127:
  604. raise util.Abort(_("failed to execute %s") % command)
  605. elif status < 0:
  606. raise util.Abort(_("%s killed") % command)
  607. else:
  608. transition = "bad"
  609. ctx = scmutil.revsingle(repo, rev, node)
  610. rev = None # clear for future iterations
  611. state[transition].append(ctx.node())
  612. ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
  613. check_state(state, interactive=False)
  614. # bisect
  615. nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
  616. # update to next check
  617. node = nodes[0]
  618. if not noupdate:
  619. cmdutil.bailifchanged(repo)
  620. hg.clean(repo, node, show_stats=False)
  621. finally:
  622. state['current'] = [node]
  623. hbisect.save_state(repo, state)
  624. print_result(nodes, bgood)
  625. return
  626. # update state
  627. if rev:
  628. nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
  629. else:
  630. nodes = [repo.lookup('.')]
  631. if good or bad or skip:
  632. if good:
  633. state['good'] += nodes
  634. elif bad:
  635. state['bad'] += nodes
  636. elif skip:
  637. state['skip'] += nodes
  638. hbisect.save_state(repo, state)
  639. if not check_state(state):
  640. return
  641. # actually bisect
  642. nodes, changesets, good = hbisect.bisect(repo.changelog, state)
  643. if extend:
  644. if not changesets:
  645. extendnode = extendbisectrange(nodes, good)
  646. if extendnode is not None:
  647. ui.write(_("Extending search to changeset %d:%s\n")
  648. % (extendnode.rev(), extendnode))
  649. state['current'] = [extendnode.node()]
  650. hbisect.save_state(repo, state)
  651. if noupdate:
  652. return
  653. cmdutil.bailifchanged(repo)
  654. return hg.clean(repo, extendnode.node())
  655. raise util.Abort(_("nothing to extend"))
  656. if changesets == 0:
  657. print_result(nodes, good)
  658. else:
  659. assert len(nodes) == 1 # only a single node can be tested next
  660. node = nodes[0]
  661. # compute the approximate number of remaining tests
  662. tests, size = 0, 2
  663. while size <= changesets:
  664. tests, size = tests + 1, size * 2
  665. rev = repo.changelog.rev(node)
  666. ui.write(_("Testing changeset %d:%s "
  667. "(%d changesets remaining, ~%d tests)\n")
  668. % (rev, short(node), changesets, tests))
  669. state['current'] = [node]
  670. hbisect.save_state(repo, state)
  671. if not noupdate:
  672. cmdutil.bailifchanged(repo)
  673. return hg.clean(repo, node)
  674. @command('bookmarks|bookmark',
  675. [('f', 'force', False, _('force')),
  676. ('r', 'rev', '', _('revision'), _('REV')),
  677. ('d', 'delete', False, _('delete a given bookmark')),
  678. ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
  679. ('i', 'inactive', False, _('mark a bookmark inactive'))],
  680. _('hg bookmarks [OPTIONS]... [NAME]...'))
  681. def bookmark(ui, repo, *names, **opts):
  682. '''create a new bookmark or list existing bookmarks
  683. Bookmarks are labels on changesets to help track lines of development.
  684. Bookmarks are unversioned and can be moved, renamed and deleted.
  685. Deleting or moving a bookmark has no effect on the associated changesets.
  686. Creating or updating to a bookmark causes it to be marked as 'active'.
  687. Active bookmarks are indicated with a '*'.
  688. When a commit is made, an active bookmark will advance to the new commit.
  689. A plain :hg:`update` will also advance an active bookmark, if possible.
  690. Updating away from a bookmark will cause it to be deactivated.
  691. Bookmarks can be pushed and pulled between repositories (see
  692. :hg:`help push` and :hg:`help pull`). If a shared bookmark has
  693. diverged, a new 'divergent bookmark' of the form 'name@path' will
  694. be created. Using :hg:'merge' will resolve the divergence.
  695. A bookmark named '@' has the special property that :hg:`clone` will
  696. check it out by default if it exists.
  697. .. container:: verbose
  698. Examples:
  699. - create an active bookmark for a new line of development::
  700. hg book new-feature
  701. - create an inactive bookmark as a place marker::
  702. hg book -i reviewed
  703. - create an inactive bookmark on another changeset::
  704. hg book -r .^ tested
  705. - move the '@' bookmark from another branch::
  706. hg book -f @
  707. '''
  708. force = opts.get('force')
  709. rev = opts.get('rev')
  710. delete = opts.get('delete')
  711. rename = opts.get('rename')
  712. inactive = opts.get('inactive')
  713. def checkformat(mark):
  714. mark = mark.strip()
  715. if not mark:
  716. raise util.Abort(_("bookmark names cannot consist entirely of "
  717. "whitespace"))
  718. scmutil.checknewlabel(repo, mark, 'bookmark')
  719. return mark
  720. def checkconflict(repo, mark, cur, force=False, target=None):
  721. if mark in marks and not force:
  722. if target:
  723. if marks[mark] == target and target == cur:
  724. # re-activating a bookmark
  725. return
  726. anc = repo.changelog.ancestors([repo[target].rev()])
  727. bmctx = repo[marks[mark]]
  728. divs = [repo[b].node() for b in marks
  729. if b.split('@', 1)[0] == mark.split('@', 1)[0]]
  730. # allow resolving a single divergent bookmark even if moving
  731. # the bookmark across branches when a revision is specified
  732. # that contains a divergent bookmark
  733. if bmctx.rev() not in anc and target in divs:
  734. bookmarks.deletedivergent(repo, [target], mark)
  735. return
  736. deletefrom = [b for b in divs
  737. if repo[b].rev() in anc or b == target]
  738. bookmarks.deletedivergent(repo, deletefrom, mark)
  739. if bookmarks.validdest(repo, bmctx, repo[target]):
  740. ui.status(_("moving bookmark '%s' forward from %s\n") %
  741. (mark, short(bmctx.node())))
  742. return
  743. raise util.Abort(_("bookmark '%s' already exists "
  744. "(use -f to force)") % mark)
  745. if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
  746. and not force):
  747. raise util.Abort(
  748. _("a bookmark cannot have the name of an existing branch"))
  749. if delete and rename:
  750. raise util.Abort(_("--delete and --rename are incompatible"))
  751. if delete and rev:
  752. raise util.Abort(_("--rev is incompatible with --delete"))
  753. if rename and rev:
  754. raise util.Abort(_("--rev is incompatible with --rename"))
  755. if not names and (delete or rev):
  756. raise util.Abort(_("bookmark name required"))
  757. if delete or rename or names or inactive:
  758. wlock = repo.wlock()
  759. try:
  760. cur = repo.changectx('.').node()
  761. marks = repo._bookmarks
  762. if delete:
  763. for mark in names:
  764. if mark not in marks:
  765. raise util.Abort(_("bookmark '%s' does not exist") %
  766. mark)
  767. if mark == repo._bookmarkcurrent:
  768. bookmarks.unsetcurrent(repo)
  769. del marks[mark]
  770. marks.write()
  771. elif rename:
  772. if not names:
  773. raise util.Abort(_("new bookmark name required"))
  774. elif len(names) > 1:
  775. raise util.Abort(_("only one new bookmark name allowed"))
  776. mark = checkformat(names[0])
  777. if rename not in marks:
  778. raise util.Abort(_("bookmark '%s' does not exist") % rename)
  779. checkconflict(repo, mark, cur, force)
  780. marks[mark] = marks[rename]
  781. if repo._bookmarkcurrent == rename and not inactive:
  782. bookmarks.setcurrent(repo, mark)
  783. del marks[rename]
  784. marks.write()
  785. elif names:
  786. newact = None
  787. for mark in names:
  788. mark = checkformat(mark)
  789. if newact is None:
  790. newact = mark
  791. if inactive and mark == repo._bookmarkcurrent:
  792. bookmarks.unsetcurrent(repo)
  793. return
  794. tgt = cur
  795. if rev:
  796. tgt = scmutil.revsingle(repo, rev).node()
  797. checkconflict(repo, mark, cur, force, tgt)
  798. marks[mark] = tgt
  799. if not inactive and cur == marks[newact] and not rev:
  800. bookmarks.setcurrent(repo, newact)
  801. elif cur != tgt and newact == repo._bookmarkcurrent:
  802. bookmarks.unsetcurrent(repo)
  803. marks.write()
  804. elif inactive:
  805. if len(marks) == 0:
  806. ui.status(_("no bookmarks set\n"))
  807. elif not repo._bookmarkcurrent:
  808. ui.status(_("no active bookmark\n"))
  809. else:
  810. bookmarks.unsetcurrent(repo)
  811. finally:
  812. wlock.release()
  813. else: # show bookmarks
  814. hexfn = ui.debugflag and hex or short
  815. marks = repo._bookmarks
  816. if len(marks) == 0:
  817. ui.status(_("no bookmarks set\n"))
  818. else:
  819. for bmark, n in sorted(marks.iteritems()):
  820. current = repo._bookmarkcurrent
  821. if bmark == current:
  822. prefix, label = '*', 'bookmarks.current'
  823. else:
  824. prefix, label = ' ', ''
  825. if ui.quiet:
  826. ui.write("%s\n" % bmark, label=label)
  827. else:
  828. pad = " " * (25 - encoding.colwidth(bmark))
  829. ui.write(" %s %s%s %d:%s\n" % (
  830. prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
  831. label=label)
  832. @command('branch',
  833. [('f', 'force', None,
  834. _('set branch name even if it shadows an existing branch')),
  835. ('C', 'clean', None, _('reset branch name to parent branch name'))],
  836. _('[-fC] [NAME]'))
  837. def branch(ui, repo, label=None, **opts):
  838. """set or show the current branch name
  839. .. note::
  840. Branch names are permanent and global. Use :hg:`bookmark` to create a
  841. light-weight bookmark instead. See :hg:`help glossary` for more
  842. information about named branches and bookmarks.
  843. With no argument, show the current branch name. With one argument,
  844. set the working directory branch name (the branch will not exist
  845. in the repository until the next commit). Standard practice
  846. recommends that primary development take place on the 'default'
  847. branch.
  848. Unless -f/--force is specified, branch will not let you set a
  849. branch name that already exists, even if it's inactive.
  850. Use -C/--clean to reset the working directory branch to that of
  851. the parent of the working directory, negating a previous branch
  852. change.
  853. Use the command :hg:`update` to switch to an existing branch. Use
  854. :hg:`commit --close-branch` to mark this branch as closed.
  855. Returns 0 on success.
  856. """
  857. if label:
  858. label = label.strip()
  859. if not opts.get('clean') and not label:
  860. ui.write("%s\n" % repo.dirstate.branch())
  861. return
  862. wlock = repo.wlock()
  863. try:
  864. if opts.get('clean'):
  865. label = repo[None].p1().branch()
  866. repo.dirstate.setbranch(label)
  867. ui.status(_('reset working directory to branch %s\n') % label)
  868. elif label:
  869. if not opts.get('force') and label in repo.branchmap():
  870. if label not in [p.branch() for p in repo.parents()]:
  871. raise util.Abort(_('a branch of the same name already'
  872. ' exists'),
  873. # i18n: "it" refers to an existing branch
  874. hint=_("use 'hg update' to switch to it"))
  875. scmutil.checknewlabel(repo, label, 'branch')
  876. repo.dirstate.setbranch(label)
  877. ui.status(_('marked working directory as branch %s\n') % label)
  878. ui.status(_('(branches are permanent and global, '
  879. 'did you want a bookmark?)\n'))
  880. finally:
  881. wlock.release()
  882. @command('branches',
  883. [('a', 'active', False, _('show only branches that have unmerged heads')),
  884. ('c', 'closed', False, _('show normal and closed branches'))],
  885. _('[-ac]'))
  886. def branches(ui, repo, active=False, closed=False):
  887. """list repository named branches
  888. List the repository's named branches, indicating which ones are
  889. inactive. If -c/--closed is specified, also list branches which have
  890. been marked closed (see :hg:`commit --close-branch`).
  891. If -a/--active is specified, only show active branches. A branch
  892. is considered active if it contains repository heads.
  893. Use the command :hg:`update` to switch to an existing branch.
  894. Returns 0.
  895. """
  896. hexfunc = ui.debugflag and hex or short
  897. allheads = set(repo.heads())
  898. branches = []
  899. for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
  900. isactive = not isclosed and bool(set(heads) & allheads)
  901. branches.append((tag, repo[tip], isactive, not isclosed))
  902. branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
  903. reverse=True)
  904. for tag, ctx, isactive, isopen in branches:
  905. if (not active) or isactive:
  906. if isactive:
  907. label = 'branches.active'
  908. notice = ''
  909. elif not isopen:
  910. if not closed:
  911. continue
  912. label = 'branches.closed'
  913. notice = _(' (closed)')
  914. else:
  915. label = 'branches.inactive'
  916. notice = _(' (inactive)')
  917. if tag == repo.dirstate.branch():
  918. label = 'branches.current'
  919. rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
  920. rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
  921. 'log.changeset changeset.%s' % ctx.phasestr())
  922. labeledtag = ui.label(tag, label)
  923. if ui.quiet:
  924. ui.write("%s\n" % labeledtag)
  925. else:
  926. ui.write("%s %s%s\n" % (labeledtag, rev, notice))
  927. @command('bundle',
  928. [('f', 'force', None, _('run even when the destination is unrelated')),
  929. ('r', 'rev', [], _('a changeset intended to be added to the destination'),
  930. _('REV')),
  931. ('b', 'branch', [], _('a specific branch you would like to bundle'),
  932. _('BRANCH')),
  933. ('', 'base', [],
  934. _('a base changeset assumed to be available at the destination'),
  935. _('REV')),
  936. ('a', 'all', None, _('bundle all changesets in the repository')),
  937. ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
  938. ] + remoteopts,
  939. _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
  940. def bundle(ui, repo, fname, dest=None, **opts):
  941. """create a changegroup file
  942. Generate a compressed changegroup file collecting changesets not
  943. known to be in another repository.
  944. If you omit the destination repository, then hg assumes the
  945. destination will have all the nodes you specify with --base
  946. parameters. To create a bundle containing all changesets, use
  947. -a/--all (or --base null).
  948. You can change compression method with the -t/--type option.
  949. The available compression methods are: none, bzip2, and
  950. gzip (by default, bundles are compressed using bzip2).
  951. The bundle file can then be transferred using conventional means
  952. and applied to another repository with the unbundle or pull
  953. command. This is useful when direct push and pull are not
  954. available or when exporting an entire repository is undesirable.
  955. Applying bundles preserves all changeset contents including
  956. permissions, copy/rename information, and revision history.
  957. Returns 0 on success, 1 if no changes found.
  958. """
  959. revs = None
  960. if 'rev' in opts:
  961. revs = scmutil.revrange(repo, opts['rev'])
  962. bundletype = opts.get('type', 'bzip2').lower()
  963. btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
  964. bundletype = btypes.get(bundletype)
  965. if bundletype not in changegroup.bundletypes:
  966. raise util.Abort(_('unknown bundle type specified with --type'))
  967. if opts.get('all'):
  968. base = ['null']
  969. else:
  970. base = scmutil.revrange(repo, opts.get('base'))
  971. # TODO: get desired bundlecaps from command line.
  972. bundlecaps = None
  973. if base:
  974. if dest:
  975. raise util.Abort(_("--base is incompatible with specifying "
  976. "a destination"))
  977. common = [repo.lookup(rev) for rev in base]
  978. heads = revs and map(repo.lookup, revs) or revs
  979. cg = changegroup.getbundle(repo, 'bundle', heads=heads, common=common,
  980. bundlecaps=bundlecaps)
  981. outgoing = None
  982. else:
  983. dest = ui.expandpath(dest or 'default-push', dest or 'default')
  984. dest, branches = hg.parseurl(dest, opts.get('branch'))
  985. other = hg.peer(repo, opts, dest)
  986. revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
  987. heads = revs and map(repo.lookup, revs) or revs
  988. outgoing = discovery.findcommonoutgoing(repo, other,
  989. onlyheads=heads,
  990. force=opts.get('force'),
  991. portable=True)
  992. cg = changegroup.getlocalbundle(repo, 'bundle', outgoing, bundlecaps)
  993. if not cg:
  994. scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
  995. return 1
  996. changegroup.writebundle(cg, fname, bundletype)
  997. @command('cat',
  998. [('o', 'output', '',
  999. _('print output to file with formatted name'), _('FORMAT')),
  1000. ('r', 'rev', '', _('print the given revision'), _('REV')),
  1001. ('', 'decode', None, _('apply any matching decode filter')),
  1002. ] + walkopts,
  1003. _('[OPTION]... FILE...'),
  1004. inferrepo=True)
  1005. def cat(ui, repo, file1, *pats, **opts):
  1006. """output the current or given revision of files
  1007. Print the specified files as they were at the given revision. If
  1008. no revision is given, the parent of the working directory is used.
  1009. Output may be to a file, in which case the name of the file is
  1010. given using a format string. The formatting rules as follows:
  1011. :``%%``: literal "%" character
  1012. :``%s``: basename of file being printed
  1013. :``%d``: dirname of file being printed, or '.' if in repository root
  1014. :``%p``: root-relative path name of file being printed
  1015. :``%H``: changeset hash (40 hexadecimal digits)
  1016. :``%R``: changeset revision number
  1017. :``%h``: short-form changeset hash (12 hexadecimal digits)
  1018. :``%r``: zero-padded changeset revision number
  1019. :``%b``: basename of the exporting repository
  1020. Returns 0 on success.
  1021. """
  1022. ctx = scmutil.revsingle(repo, opts.get('rev'))
  1023. m = scmutil.match(ctx, (file1,) + pats, opts)
  1024. return cmdutil.cat(ui, repo, ctx, m, '', **opts)
  1025. @command('^clone',
  1026. [('U', 'noupdate', None,
  1027. _('the clone will include an empty working copy (only a repository)')),
  1028. ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
  1029. ('r', 'rev', [], _('include the specified changeset'), _('REV')),
  1030. ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
  1031. ('', 'pull', None, _('use pull protocol to copy metadata')),
  1032. ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
  1033. ] + remoteopts,
  1034. _('[OPTION]... SOURCE [DEST]'),
  1035. norepo=True)
  1036. def clone(ui, source, dest=None, **opts):
  1037. """make a copy of an existing repository
  1038. Create a copy of an existing repository in a new directory.
  1039. If no destination directory name is specified, it defaults to the
  1040. basename of the source.
  1041. The location of the source is added to the new repository's
  1042. ``.hg/hgrc`` file, as the default to be used for future pulls.
  1043. Only local paths and ``ssh://`` URLs are supported as
  1044. destinations. For ``ssh://`` destinations, no working directory or
  1045. ``.hg/hgrc`` will be created on the remote side.
  1046. To pull only a subset of changesets, specify one or more revisions
  1047. identifiers with -r/--rev or branches with -b/--branch. The
  1048. resulting clone will contain only the specified changesets and
  1049. their ancestors. These options (or 'clone src#rev dest') imply
  1050. --pull, even for local source repositories. Note that specifying a
  1051. tag will include the tagged changeset but not the changeset
  1052. containing the tag.
  1053. If the source repository has a bookmark called '@' set, that
  1054. revision will be checked out in the new repository by default.
  1055. To check out a particular version, use -u/--update, or
  1056. -U/--noupdate to create a clone with no working directory.
  1057. .. container:: verbose
  1058. For efficiency, hardlinks are used for cloning whenever the
  1059. source and destination are on the same filesystem (note this
  1060. applies only to the repository data, not to the working
  1061. directory). Some filesystems, such as AFS, implement hardlinking
  1062. incorrectly, but do not report errors. In these cases, use the
  1063. --pull option to avoid hardlinking.
  1064. In some cases, you can clone repositories and the working
  1065. directory using full hardlinks with ::
  1066. $ cp -al REPO REPOCLONE
  1067. This is the fastest way to clone, but it is not always safe. The
  1068. operation is not atomic (making sure REPO is not modified during
  1069. the operation is up to you) and you have to make sure your
  1070. editor breaks hardlinks (Emacs and most Linux Kernel tools do
  1071. so). Also, this is not compatible with certain extensions that
  1072. place their metadata under the .hg directory, such as mq.
  1073. Mercurial will update the working directory to the first applicable
  1074. revision from this list:
  1075. a) null if -U or the source repository has no changesets
  1076. b) if -u . and the source repository is local, the first parent of
  1077. the source repository's working directory
  1078. c) the changeset specified with -u (if a branch name, this means the
  1079. latest head of that branch)
  1080. d) the changeset specified with -r
  1081. e) the tipmost head specified with -b
  1082. f) the tipmost head specified with the url#branch source syntax
  1083. g) the revision marked with the '@' bookmark, if present
  1084. h) the tipmost head of the default branch
  1085. i) tip
  1086. Examples:
  1087. - clone a remote repository to a new directory named hg/::
  1088. hg clone http://selenic.com/hg
  1089. - create a lightweight local clone::
  1090. hg clone project/ project-feature/
  1091. - clone from an absolute path on an ssh server (note double-slash)::
  1092. hg clone ssh://user@server//home/projects/alpha/
  1093. - do a high-speed clone over a LAN while checking out a
  1094. specified version::
  1095. hg clone --uncompressed http://server/repo -u 1.5…

Large files files are truncated, but you can click here to view the full file