PageRenderTime 50ms CodeModel.GetById 27ms 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
  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
  1096. - create a repository without changesets after a particular revision::
  1097. hg clone -r 04e544 experimental/ good/
  1098. - clone (and track) a particular named branch::
  1099. hg clone http://selenic.com/hg#stable
  1100. See :hg:`help urls` for details on specifying URLs.
  1101. Returns 0 on success.
  1102. """
  1103. if opts.get('noupdate') and opts.get('updaterev'):
  1104. raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
  1105. r = hg.clone(ui, opts, source, dest,
  1106. pull=opts.get('pull'),
  1107. stream=opts.get('uncompressed'),
  1108. rev=opts.get('rev'),
  1109. update=opts.get('updaterev') or not opts.get('noupdate'),
  1110. branch=opts.get('branch'))
  1111. return r is None
  1112. @command('^commit|ci',
  1113. [('A', 'addremove', None,
  1114. _('mark new/missing files as added/removed before committing')),
  1115. ('', 'close-branch', None,
  1116. _('mark a branch as closed, hiding it from the branch list')),
  1117. ('', 'amend', None, _('amend the parent of the working dir')),
  1118. ('s', 'secret', None, _('use the secret phase for committing')),
  1119. ('e', 'edit', None,
  1120. _('further edit commit message already specified')),
  1121. ] + walkopts + commitopts + commitopts2 + subrepoopts,
  1122. _('[OPTION]... [FILE]...'),
  1123. inferrepo=True)
  1124. def commit(ui, repo, *pats, **opts):
  1125. """commit the specified files or all outstanding changes
  1126. Commit changes to the given files into the repository. Unlike a
  1127. centralized SCM, this operation is a local operation. See
  1128. :hg:`push` for a way to actively distribute your changes.
  1129. If a list of files is omitted, all changes reported by :hg:`status`
  1130. will be committed.
  1131. If you are committing the result of a merge, do not provide any
  1132. filenames or -I/-X filters.
  1133. If no commit message is specified, Mercurial starts your
  1134. configured editor where you can enter a message. In case your
  1135. commit fails, you will find a backup of your message in
  1136. ``.hg/last-message.txt``.
  1137. The --amend flag can be used to amend the parent of the
  1138. working directory with a new commit that contains the changes
  1139. in the parent in addition to those currently reported by :hg:`status`,
  1140. if there are any. The old commit is stored in a backup bundle in
  1141. ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
  1142. on how to restore it).
  1143. Message, user and date are taken from the amended commit unless
  1144. specified. When a message isn't specified on the command line,
  1145. the editor will open with the message of the amended commit.
  1146. It is not possible to amend public changesets (see :hg:`help phases`)
  1147. or changesets that have children.
  1148. See :hg:`help dates` for a list of formats valid for -d/--date.
  1149. Returns 0 on success, 1 if nothing changed.
  1150. """
  1151. if opts.get('subrepos'):
  1152. if opts.get('amend'):
  1153. raise util.Abort(_('cannot amend with --subrepos'))
  1154. # Let --subrepos on the command line override config setting.
  1155. ui.setconfig('ui', 'commitsubrepos', True, 'commit')
  1156. # Save this for restoring it later
  1157. oldcommitphase = ui.config('phases', 'new-commit')
  1158. cmdutil.checkunfinished(repo, commit=True)
  1159. branch = repo[None].branch()
  1160. bheads = repo.branchheads(branch)
  1161. extra = {}
  1162. if opts.get('close_branch'):
  1163. extra['close'] = 1
  1164. if not bheads:
  1165. raise util.Abort(_('can only close branch heads'))
  1166. elif opts.get('amend'):
  1167. if repo.parents()[0].p1().branch() != branch and \
  1168. repo.parents()[0].p2().branch() != branch:
  1169. raise util.Abort(_('can only close branch heads'))
  1170. if opts.get('amend'):
  1171. if ui.configbool('ui', 'commitsubrepos'):
  1172. raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
  1173. old = repo['.']
  1174. if old.phase() == phases.public:
  1175. raise util.Abort(_('cannot amend public changesets'))
  1176. if len(repo[None].parents()) > 1:
  1177. raise util.Abort(_('cannot amend while merging'))
  1178. if (not obsolete._enabled) and old.children():
  1179. raise util.Abort(_('cannot amend changeset with children'))
  1180. # commitfunc is used only for temporary amend commit by cmdutil.amend
  1181. def commitfunc(ui, repo, message, match, opts):
  1182. return repo.commit(message,
  1183. opts.get('user') or old.user(),
  1184. opts.get('date') or old.date(),
  1185. match,
  1186. extra=extra)
  1187. current = repo._bookmarkcurrent
  1188. marks = old.bookmarks()
  1189. node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
  1190. if node == old.node():
  1191. ui.status(_("nothing changed\n"))
  1192. return 1
  1193. elif marks:
  1194. ui.debug('moving bookmarks %r from %s to %s\n' %
  1195. (marks, old.hex(), hex(node)))
  1196. newmarks = repo._bookmarks
  1197. for bm in marks:
  1198. newmarks[bm] = node
  1199. if bm == current:
  1200. bookmarks.setcurrent(repo, bm)
  1201. newmarks.write()
  1202. else:
  1203. def commitfunc(ui, repo, message, match, opts):
  1204. try:
  1205. if opts.get('secret'):
  1206. ui.setconfig('phases', 'new-commit', 'secret', 'commit')
  1207. # Propagate to subrepos
  1208. repo.baseui.setconfig('phases', 'new-commit', 'secret',
  1209. 'commit')
  1210. return repo.commit(message, opts.get('user'), opts.get('date'),
  1211. match,
  1212. editor=cmdutil.getcommiteditor(**opts),
  1213. extra=extra)
  1214. finally:
  1215. ui.setconfig('phases', 'new-commit', oldcommitphase, 'commit')
  1216. repo.baseui.setconfig('phases', 'new-commit', oldcommitphase,
  1217. 'commit')
  1218. node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
  1219. if not node:
  1220. stat = repo.status(match=scmutil.match(repo[None], pats, opts))
  1221. if stat[3]:
  1222. ui.status(_("nothing changed (%d missing files, see "
  1223. "'hg status')\n") % len(stat[3]))
  1224. else:
  1225. ui.status(_("nothing changed\n"))
  1226. return 1
  1227. cmdutil.commitstatus(repo, node, branch, bheads, opts)
  1228. @command('config|showconfig|debugconfig',
  1229. [('u', 'untrusted', None, _('show untrusted configuration options')),
  1230. ('e', 'edit', None, _('edit user config')),
  1231. ('l', 'local', None, _('edit repository config')),
  1232. ('g', 'global', None, _('edit global config'))],
  1233. _('[-u] [NAME]...'),
  1234. optionalrepo=True)
  1235. def config(ui, repo, *values, **opts):
  1236. """show combined config settings from all hgrc files
  1237. With no arguments, print names and values of all config items.
  1238. With one argument of the form section.name, print just the value
  1239. of that config item.
  1240. With multiple arguments, print names and values of all config
  1241. items with matching section names.
  1242. With --edit, start an editor on the user-level config file. With
  1243. --global, edit the system-wide config file. With --local, edit the
  1244. repository-level config file.
  1245. With --debug, the source (filename and line number) is printed
  1246. for each config item.
  1247. See :hg:`help config` for more information about config files.
  1248. Returns 0 on success.
  1249. """
  1250. if opts.get('edit') or opts.get('local') or opts.get('global'):
  1251. if opts.get('local') and opts.get('global'):
  1252. raise util.Abort(_("can't use --local and --global together"))
  1253. if opts.get('local'):
  1254. if not repo:
  1255. raise util.Abort(_("can't use --local outside a repository"))
  1256. paths = [repo.join('hgrc')]
  1257. elif opts.get('global'):
  1258. paths = scmutil.systemrcpath()
  1259. else:
  1260. paths = scmutil.userrcpath()
  1261. for f in paths:
  1262. if os.path.exists(f):
  1263. break
  1264. else:
  1265. f = paths[0]
  1266. fp = open(f, "w")
  1267. fp.write(
  1268. '# example config (see "hg help config" for more info)\n'
  1269. '\n'
  1270. '[ui]\n'
  1271. '# name and email, e.g.\n'
  1272. '# username = Jane Doe <jdoe@example.com>\n'
  1273. 'username =\n'
  1274. '\n'
  1275. '[extensions]\n'
  1276. '# uncomment these lines to enable some popular extensions\n'
  1277. '# (see "hg help extensions" for more info)\n'
  1278. '# pager =\n'
  1279. '# progress =\n'
  1280. '# color =\n')
  1281. fp.close()
  1282. editor = ui.geteditor()
  1283. util.system("%s \"%s\"" % (editor, f),
  1284. onerr=util.Abort, errprefix=_("edit failed"),
  1285. out=ui.fout)
  1286. return
  1287. for f in scmutil.rcpath():
  1288. ui.debug('read config from: %s\n' % f)
  1289. untrusted = bool(opts.get('untrusted'))
  1290. if values:
  1291. sections = [v for v in values if '.' not in v]
  1292. items = [v for v in values if '.' in v]
  1293. if len(items) > 1 or items and sections:
  1294. raise util.Abort(_('only one config item permitted'))
  1295. for section, name, value in ui.walkconfig(untrusted=untrusted):
  1296. value = str(value).replace('\n', '\\n')
  1297. sectname = section + '.' + name
  1298. if values:
  1299. for v in values:
  1300. if v == section:
  1301. ui.debug('%s: ' %
  1302. ui.configsource(section, name, untrusted))
  1303. ui.write('%s=%s\n' % (sectname, value))
  1304. elif v == sectname:
  1305. ui.debug('%s: ' %
  1306. ui.configsource(section, name, untrusted))
  1307. ui.write(value, '\n')
  1308. else:
  1309. ui.debug('%s: ' %
  1310. ui.configsource(section, name, untrusted))
  1311. ui.write('%s=%s\n' % (sectname, value))
  1312. @command('copy|cp',
  1313. [('A', 'after', None, _('record a copy that has already occurred')),
  1314. ('f', 'force', None, _('forcibly copy over an existing managed file')),
  1315. ] + walkopts + dryrunopts,
  1316. _('[OPTION]... [SOURCE]... DEST'))
  1317. def copy(ui, repo, *pats, **opts):
  1318. """mark files as copied for the next commit
  1319. Mark dest as having copies of source files. If dest is a
  1320. directory, copies are put in that directory. If dest is a file,
  1321. the source must be a single file.
  1322. By default, this command copies the contents of files as they
  1323. exist in the working directory. If invoked with -A/--after, the
  1324. operation is recorded, but no copying is performed.
  1325. This command takes effect with the next commit. To undo a copy
  1326. before that, see :hg:`revert`.
  1327. Returns 0 on success, 1 if errors are encountered.
  1328. """
  1329. wlock = repo.wlock(False)
  1330. try:
  1331. return cmdutil.copy(ui, repo, pats, opts)
  1332. finally:
  1333. wlock.release()
  1334. @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
  1335. def debugancestor(ui, repo, *args):
  1336. """find the ancestor revision of two revisions in a given index"""
  1337. if len(args) == 3:
  1338. index, rev1, rev2 = args
  1339. r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
  1340. lookup = r.lookup
  1341. elif len(args) == 2:
  1342. if not repo:
  1343. raise util.Abort(_("there is no Mercurial repository here "
  1344. "(.hg not found)"))
  1345. rev1, rev2 = args
  1346. r = repo.changelog
  1347. lookup = repo.lookup
  1348. else:
  1349. raise util.Abort(_('either two or three arguments required'))
  1350. a = r.ancestor(lookup(rev1), lookup(rev2))
  1351. ui.write("%d:%s\n" % (r.rev(a), hex(a)))
  1352. @command('debugbuilddag',
  1353. [('m', 'mergeable-file', None, _('add single file mergeable changes')),
  1354. ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
  1355. ('n', 'new-file', None, _('add new file at each rev'))],
  1356. _('[OPTION]... [TEXT]'))
  1357. def debugbuilddag(ui, repo, text=None,
  1358. mergeable_file=False,
  1359. overwritten_file=False,
  1360. new_file=False):
  1361. """builds a repo with a given DAG from scratch in the current empty repo
  1362. The description of the DAG is read from stdin if not given on the
  1363. command line.
  1364. Elements:
  1365. - "+n" is a linear run of n nodes based on the current default parent
  1366. - "." is a single node based on the current default parent
  1367. - "$" resets the default parent to null (implied at the start);
  1368. otherwise the default parent is always the last node created
  1369. - "<p" sets the default parent to the backref p
  1370. - "*p" is a fork at parent p, which is a backref
  1371. - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
  1372. - "/p2" is a merge of the preceding node and p2
  1373. - ":tag" defines a local tag for the preceding node
  1374. - "@branch" sets the named branch for subsequent nodes
  1375. - "#...\\n" is a comment up to the end of the line
  1376. Whitespace between the above elements is ignored.
  1377. A backref is either
  1378. - a number n, which references the node curr-n, where curr is the current
  1379. node, or
  1380. - the name of a local tag you placed earlier using ":tag", or
  1381. - empty to denote the default parent.
  1382. All string valued-elements are either strictly alphanumeric, or must
  1383. be enclosed in double quotes ("..."), with "\\" as escape character.
  1384. """
  1385. if text is None:
  1386. ui.status(_("reading DAG from stdin\n"))
  1387. text = ui.fin.read()
  1388. cl = repo.changelog
  1389. if len(cl) > 0:
  1390. raise util.Abort(_('repository is not empty'))
  1391. # determine number of revs in DAG
  1392. total = 0
  1393. for type, data in dagparser.parsedag(text):
  1394. if type == 'n':
  1395. total += 1
  1396. if mergeable_file:
  1397. linesperrev = 2
  1398. # make a file with k lines per rev
  1399. initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
  1400. initialmergedlines.append("")
  1401. tags = []
  1402. lock = tr = None
  1403. try:
  1404. lock = repo.lock()
  1405. tr = repo.transaction("builddag")
  1406. at = -1
  1407. atbranch = 'default'
  1408. nodeids = []
  1409. id = 0
  1410. ui.progress(_('building'), id, unit=_('revisions'), total=total)
  1411. for type, data in dagparser.parsedag(text):
  1412. if type == 'n':
  1413. ui.note(('node %s\n' % str(data)))
  1414. id, ps = data
  1415. files = []
  1416. fctxs = {}
  1417. p2 = None
  1418. if mergeable_file:
  1419. fn = "mf"
  1420. p1 = repo[ps[0]]
  1421. if len(ps) > 1:
  1422. p2 = repo[ps[1]]
  1423. pa = p1.ancestor(p2)
  1424. base, local, other = [x[fn].data() for x in (pa, p1,
  1425. p2)]
  1426. m3 = simplemerge.Merge3Text(base, local, other)
  1427. ml = [l.strip() for l in m3.merge_lines()]
  1428. ml.append("")
  1429. elif at > 0:
  1430. ml = p1[fn].data().split("\n")
  1431. else:
  1432. ml = initialmergedlines
  1433. ml[id * linesperrev] += " r%i" % id
  1434. mergedtext = "\n".join(ml)
  1435. files.append(fn)
  1436. fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
  1437. if overwritten_file:
  1438. fn = "of"
  1439. files.append(fn)
  1440. fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
  1441. if new_file:
  1442. fn = "nf%i" % id
  1443. files.append(fn)
  1444. fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
  1445. if len(ps) > 1:
  1446. if not p2:
  1447. p2 = repo[ps[1]]
  1448. for fn in p2:
  1449. if fn.startswith("nf"):
  1450. files.append(fn)
  1451. fctxs[fn] = p2[fn]
  1452. def fctxfn(repo, cx, path):
  1453. return fctxs.get(path)
  1454. if len(ps) == 0 or ps[0] < 0:
  1455. pars = [None, None]
  1456. elif len(ps) == 1:
  1457. pars = [nodeids[ps[0]], None]
  1458. else:
  1459. pars = [nodeids[p] for p in ps]
  1460. cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
  1461. date=(id, 0),
  1462. user="debugbuilddag",
  1463. extra={'branch': atbranch})
  1464. nodeid = repo.commitctx(cx)
  1465. nodeids.append(nodeid)
  1466. at = id
  1467. elif type == 'l':
  1468. id, name = data
  1469. ui.note(('tag %s\n' % name))
  1470. tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
  1471. elif type == 'a':
  1472. ui.note(('branch %s\n' % data))
  1473. atbranch = data
  1474. ui.progress(_('building'), id, unit=_('revisions'), total=total)
  1475. tr.close()
  1476. if tags:
  1477. repo.opener.write("localtags", "".join(tags))
  1478. finally:
  1479. ui.progress(_('building'), None)
  1480. release(tr, lock)
  1481. @command('debugbundle',
  1482. [('a', 'all', None, _('show all details'))],
  1483. _('FILE'),
  1484. norepo=True)
  1485. def debugbundle(ui, bundlepath, all=None, **opts):
  1486. """lists the contents of a bundle"""
  1487. f = hg.openpath(ui, bundlepath)
  1488. try:
  1489. gen = exchange.readbundle(ui, f, bundlepath)
  1490. if all:
  1491. ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
  1492. def showchunks(named):
  1493. ui.write("\n%s\n" % named)
  1494. chain = None
  1495. while True:
  1496. chunkdata = gen.deltachunk(chain)
  1497. if not chunkdata:
  1498. break
  1499. node = chunkdata['node']
  1500. p1 = chunkdata['p1']
  1501. p2 = chunkdata['p2']
  1502. cs = chunkdata['cs']
  1503. deltabase = chunkdata['deltabase']
  1504. delta = chunkdata['delta']
  1505. ui.write("%s %s %s %s %s %s\n" %
  1506. (hex(node), hex(p1), hex(p2),
  1507. hex(cs), hex(deltabase), len(delta)))
  1508. chain = node
  1509. chunkdata = gen.changelogheader()
  1510. showchunks("changelog")
  1511. chunkdata = gen.manifestheader()
  1512. showchunks("manifest")
  1513. while True:
  1514. chunkdata = gen.filelogheader()
  1515. if not chunkdata:
  1516. break
  1517. fname = chunkdata['filename']
  1518. showchunks(fname)
  1519. else:
  1520. chunkdata = gen.changelogheader()
  1521. chain = None
  1522. while True:
  1523. chunkdata = gen.deltachunk(chain)
  1524. if not chunkdata:
  1525. break
  1526. node = chunkdata['node']
  1527. ui.write("%s\n" % hex(node))
  1528. chain = node
  1529. finally:
  1530. f.close()
  1531. @command('debugcheckstate', [], '')
  1532. def debugcheckstate(ui, repo):
  1533. """validate the correctness of the current dirstate"""
  1534. parent1, parent2 = repo.dirstate.parents()
  1535. m1 = repo[parent1].manifest()
  1536. m2 = repo[parent2].manifest()
  1537. errors = 0
  1538. for f in repo.dirstate:
  1539. state = repo.dirstate[f]
  1540. if state in "nr" and f not in m1:
  1541. ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
  1542. errors += 1
  1543. if state in "a" and f in m1:
  1544. ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
  1545. errors += 1
  1546. if state in "m" and f not in m1 and f not in m2:
  1547. ui.warn(_("%s in state %s, but not in either manifest\n") %
  1548. (f, state))
  1549. errors += 1
  1550. for f in m1:
  1551. state = repo.dirstate[f]
  1552. if state not in "nrm":
  1553. ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
  1554. errors += 1
  1555. if errors:
  1556. error = _(".hg/dirstate inconsistent with current parent's manifest")
  1557. raise util.Abort(error)
  1558. @command('debugcommands', [], _('[COMMAND]'), norepo=True)
  1559. def debugcommands(ui, cmd='', *args):
  1560. """list all available commands and options"""
  1561. for cmd, vals in sorted(table.iteritems()):
  1562. cmd = cmd.split('|')[0].strip('^')
  1563. opts = ', '.join([i[1] for i in vals[1]])
  1564. ui.write('%s: %s\n' % (cmd, opts))
  1565. @command('debugcomplete',
  1566. [('o', 'options', None, _('show the command options'))],
  1567. _('[-o] CMD'),
  1568. norepo=True)
  1569. def debugcomplete(ui, cmd='', **opts):
  1570. """returns the completion list associated with the given command"""
  1571. if opts.get('options'):
  1572. options = []
  1573. otables = [globalopts]
  1574. if cmd:
  1575. aliases, entry = cmdutil.findcmd(cmd, table, False)
  1576. otables.append(entry[1])
  1577. for t in otables:
  1578. for o in t:
  1579. if "(DEPRECATED)" in o[3]:
  1580. continue
  1581. if o[0]:
  1582. options.append('-%s' % o[0])
  1583. options.append('--%s' % o[1])
  1584. ui.write("%s\n" % "\n".join(options))
  1585. return
  1586. cmdlist = cmdutil.findpossible(cmd, table)
  1587. if ui.verbose:
  1588. cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
  1589. ui.write("%s\n" % "\n".join(sorted(cmdlist)))
  1590. @command('debugdag',
  1591. [('t', 'tags', None, _('use tags as labels')),
  1592. ('b', 'branches', None, _('annotate with branch names')),
  1593. ('', 'dots', None, _('use dots for runs')),
  1594. ('s', 'spaces', None, _('separate elements by spaces'))],
  1595. _('[OPTION]... [FILE [REV]...]'),
  1596. optionalrepo=True)
  1597. def debugdag(ui, repo, file_=None, *revs, **opts):
  1598. """format the changelog or an index DAG as a concise textual description
  1599. If you pass a revlog index, the revlog's DAG is emitted. If you list
  1600. revision numbers, they get labeled in the output as rN.
  1601. Otherwise, the changelog DAG of the current repo is emitted.
  1602. """
  1603. spaces = opts.get('spaces')
  1604. dots = opts.get('dots')
  1605. if file_:
  1606. rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
  1607. revs = set((int(r) for r in revs))
  1608. def events():
  1609. for r in rlog:
  1610. yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
  1611. if p != -1)))
  1612. if r in revs:
  1613. yield 'l', (r, "r%i" % r)
  1614. elif repo:
  1615. cl = repo.changelog
  1616. tags = opts.get('tags')
  1617. branches = opts.get('branches')
  1618. if tags:
  1619. labels = {}
  1620. for l, n in repo.tags().items():
  1621. labels.setdefault(cl.rev(n), []).append(l)
  1622. def events():
  1623. b = "default"
  1624. for r in cl:
  1625. if branches:
  1626. newb = cl.read(cl.node(r))[5]['branch']
  1627. if newb != b:
  1628. yield 'a', newb
  1629. b = newb
  1630. yield 'n', (r, list(set(p for p in cl.parentrevs(r)
  1631. if p != -1)))
  1632. if tags:
  1633. ls = labels.get(r)
  1634. if ls:
  1635. for l in ls:
  1636. yield 'l', (r, l)
  1637. else:
  1638. raise util.Abort(_('need repo for changelog dag'))
  1639. for line in dagparser.dagtextlines(events(),
  1640. addspaces=spaces,
  1641. wraplabels=True,
  1642. wrapannotations=True,
  1643. wrapnonlinear=dots,
  1644. usedots=dots,
  1645. maxlinewidth=70):
  1646. ui.write(line)
  1647. ui.write("\n")
  1648. @command('debugdata',
  1649. [('c', 'changelog', False, _('open changelog')),
  1650. ('m', 'manifest', False, _('open manifest'))],
  1651. _('-c|-m|FILE REV'))
  1652. def debugdata(ui, repo, file_, rev=None, **opts):
  1653. """dump the contents of a data file revision"""
  1654. if opts.get('changelog') or opts.get('manifest'):
  1655. file_, rev = None, file_
  1656. elif rev is None:
  1657. raise error.CommandError('debugdata', _('invalid arguments'))
  1658. r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
  1659. try:
  1660. ui.write(r.revision(r.lookup(rev)))
  1661. except KeyError:
  1662. raise util.Abort(_('invalid revision identifier %s') % rev)
  1663. @command('debugdate',
  1664. [('e', 'extended', None, _('try extended date formats'))],
  1665. _('[-e] DATE [RANGE]'),
  1666. norepo=True, optionalrepo=True)
  1667. def debugdate(ui, date, range=None, **opts):
  1668. """parse and display a date"""
  1669. if opts["extended"]:
  1670. d = util.parsedate(date, util.extendeddateformats)
  1671. else:
  1672. d = util.parsedate(date)
  1673. ui.write(("internal: %s %s\n") % d)
  1674. ui.write(("standard: %s\n") % util.datestr(d))
  1675. if range:
  1676. m = util.matchdate(range)
  1677. ui.write(("match: %s\n") % m(d[0]))
  1678. @command('debugdiscovery',
  1679. [('', 'old', None, _('use old-style discovery')),
  1680. ('', 'nonheads', None,
  1681. _('use old-style discovery with non-heads included')),
  1682. ] + remoteopts,
  1683. _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
  1684. def debugdiscovery(ui, repo, remoteurl="default", **opts):
  1685. """runs the changeset discovery protocol in isolation"""
  1686. remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
  1687. opts.get('branch'))
  1688. remote = hg.peer(repo, opts, remoteurl)
  1689. ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
  1690. # make sure tests are repeatable
  1691. random.seed(12323)
  1692. def doit(localheads, remoteheads, remote=remote):
  1693. if opts.get('old'):
  1694. if localheads:
  1695. raise util.Abort('cannot use localheads with old style '
  1696. 'discovery')
  1697. if not util.safehasattr(remote, 'branches'):
  1698. # enable in-client legacy support
  1699. remote = localrepo.locallegacypeer(remote.local())
  1700. common, _in, hds = treediscovery.findcommonincoming(repo, remote,
  1701. force=True)
  1702. common = set(common)
  1703. if not opts.get('nonheads'):
  1704. ui.write(("unpruned common: %s\n") %
  1705. " ".join(sorted(short(n) for n in common)))
  1706. dag = dagutil.revlogdag(repo.changelog)
  1707. all = dag.ancestorset(dag.internalizeall(common))
  1708. common = dag.externalizeall(dag.headsetofconnecteds(all))
  1709. else:
  1710. common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
  1711. common = set(common)
  1712. rheads = set(hds)
  1713. lheads = set(repo.heads())
  1714. ui.write(("common heads: %s\n") %
  1715. " ".join(sorted(short(n) for n in common)))
  1716. if lheads <= common:
  1717. ui.write(("local is subset\n"))
  1718. elif rheads <= common:
  1719. ui.write(("remote is subset\n"))
  1720. serverlogs = opts.get('serverlog')
  1721. if serverlogs:
  1722. for filename in serverlogs:
  1723. logfile = open(filename, 'r')
  1724. try:
  1725. line = logfile.readline()
  1726. while line:
  1727. parts = line.strip().split(';')
  1728. op = parts[1]
  1729. if op == 'cg':
  1730. pass
  1731. elif op == 'cgss':
  1732. doit(parts[2].split(' '), parts[3].split(' '))
  1733. elif op == 'unb':
  1734. doit(parts[3].split(' '), parts[2].split(' '))
  1735. line = logfile.readline()
  1736. finally:
  1737. logfile.close()
  1738. else:
  1739. remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
  1740. opts.get('remote_head'))
  1741. localrevs = opts.get('local_head')
  1742. doit(localrevs, remoterevs)
  1743. @command('debugfileset',
  1744. [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
  1745. _('[-r REV] FILESPEC'))
  1746. def debugfileset(ui, repo, expr, **opts):
  1747. '''parse and apply a fileset specification'''
  1748. ctx = scmutil.revsingle(repo, opts.get('rev'), None)
  1749. if ui.verbose:
  1750. tree = fileset.parse(expr)[0]
  1751. ui.note(tree, "\n")
  1752. for f in ctx.getfileset(expr):
  1753. ui.write("%s\n" % f)
  1754. @command('debugfsinfo', [], _('[PATH]'), norepo=True)
  1755. def debugfsinfo(ui, path="."):
  1756. """show information detected about current filesystem"""
  1757. util.writefile('.debugfsinfo', '')
  1758. ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
  1759. ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
  1760. ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
  1761. ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
  1762. and 'yes' or 'no'))
  1763. os.unlink('.debugfsinfo')
  1764. @command('debuggetbundle',
  1765. [('H', 'head', [], _('id of head node'), _('ID')),
  1766. ('C', 'common', [], _('id of common node'), _('ID')),
  1767. ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
  1768. _('REPO FILE [-H|-C ID]...'),
  1769. norepo=True)
  1770. def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
  1771. """retrieves a bundle from a repo
  1772. Every ID must be a full-length hex node id string. Saves the bundle to the
  1773. given file.
  1774. """
  1775. repo = hg.peer(ui, opts, repopath)
  1776. if not repo.capable('getbundle'):
  1777. raise util.Abort("getbundle() not supported by target repository")
  1778. args = {}
  1779. if common:
  1780. args['common'] = [bin(s) for s in common]
  1781. if head:
  1782. args['heads'] = [bin(s) for s in head]
  1783. # TODO: get desired bundlecaps from command line.
  1784. args['bundlecaps'] = None
  1785. bundle = repo.getbundle('debug', **args)
  1786. bundletype = opts.get('type', 'bzip2').lower()
  1787. btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
  1788. bundletype = btypes.get(bundletype)
  1789. if bundletype not in changegroup.bundletypes:
  1790. raise util.Abort(_('unknown bundle type specified with --type'))
  1791. changegroup.writebundle(bundle, bundlepath, bundletype)
  1792. @command('debugignore', [], '')
  1793. def debugignore(ui, repo, *values, **opts):
  1794. """display the combined ignore pattern"""
  1795. ignore = repo.dirstate._ignore
  1796. includepat = getattr(ignore, 'includepat', None)
  1797. if includepat is not None:
  1798. ui.write("%s\n" % includepat)
  1799. else:
  1800. raise util.Abort(_("no ignore patterns found"))
  1801. @command('debugindex',
  1802. [('c', 'changelog', False, _('open changelog')),
  1803. ('m', 'manifest', False, _('open manifest')),
  1804. ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
  1805. _('[-f FORMAT] -c|-m|FILE'),
  1806. optionalrepo=True)
  1807. def debugindex(ui, repo, file_=None, **opts):
  1808. """dump the contents of an index file"""
  1809. r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
  1810. format = opts.get('format', 0)
  1811. if format not in (0, 1):
  1812. raise util.Abort(_("unknown format %d") % format)
  1813. generaldelta = r.version & revlog.REVLOGGENERALDELTA
  1814. if generaldelta:
  1815. basehdr = ' delta'
  1816. else:
  1817. basehdr = ' base'
  1818. if format == 0:
  1819. ui.write(" rev offset length " + basehdr + " linkrev"
  1820. " nodeid p1 p2\n")
  1821. elif format == 1:
  1822. ui.write(" rev flag offset length"
  1823. " size " + basehdr + " link p1 p2"
  1824. " nodeid\n")
  1825. for i in r:
  1826. node = r.node(i)
  1827. if generaldelta:
  1828. base = r.deltaparent(i)
  1829. else:
  1830. base = r.chainbase(i)
  1831. if format == 0:
  1832. try:
  1833. pp = r.parents(node)
  1834. except Exception:
  1835. pp = [nullid, nullid]
  1836. ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
  1837. i, r.start(i), r.length(i), base, r.linkrev(i),
  1838. short(node), short(pp[0]), short(pp[1])))
  1839. elif format == 1:
  1840. pr = r.parentrevs(i)
  1841. ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
  1842. i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
  1843. base, r.linkrev(i), pr[0], pr[1], short(node)))
  1844. @command('debugindexdot', [], _('FILE'), optionalrepo=True)
  1845. def debugindexdot(ui, repo, file_):
  1846. """dump an index DAG as a graphviz dot file"""
  1847. r = None
  1848. if repo:
  1849. filelog = repo.file(file_)
  1850. if len(filelog):
  1851. r = filelog
  1852. if not r:
  1853. r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
  1854. ui.write(("digraph G {\n"))
  1855. for i in r:
  1856. node = r.node(i)
  1857. pp = r.parents(node)
  1858. ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
  1859. if pp[1] != nullid:
  1860. ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
  1861. ui.write("}\n")
  1862. @command('debuginstall', [], '', norepo=True)
  1863. def debuginstall(ui):
  1864. '''test Mercurial installation
  1865. Returns 0 on success.
  1866. '''
  1867. def writetemp(contents):
  1868. (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
  1869. f = os.fdopen(fd, "wb")
  1870. f.write(contents)
  1871. f.close()
  1872. return name
  1873. problems = 0
  1874. # encoding
  1875. ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
  1876. try:
  1877. encoding.fromlocal("test")
  1878. except util.Abort, inst:
  1879. ui.write(" %s\n" % inst)
  1880. ui.write(_(" (check that your locale is properly set)\n"))
  1881. problems += 1
  1882. # Python
  1883. ui.status(_("checking Python executable (%s)\n") % sys.executable)
  1884. ui.status(_("checking Python version (%s)\n")
  1885. % ("%s.%s.%s" % sys.version_info[:3]))
  1886. ui.status(_("checking Python lib (%s)...\n")
  1887. % os.path.dirname(os.__file__))
  1888. # compiled modules
  1889. ui.status(_("checking installed modules (%s)...\n")
  1890. % os.path.dirname(__file__))
  1891. try:
  1892. import bdiff, mpatch, base85, osutil
  1893. dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
  1894. except Exception, inst:
  1895. ui.write(" %s\n" % inst)
  1896. ui.write(_(" One or more extensions could not be found"))
  1897. ui.write(_(" (check that you compiled the extensions)\n"))
  1898. problems += 1
  1899. # templates
  1900. import templater
  1901. p = templater.templatepath()
  1902. ui.status(_("checking templates (%s)...\n") % ' '.join(p))
  1903. if p:
  1904. m = templater.templatepath("map-cmdline.default")
  1905. if m:
  1906. # template found, check if it is working
  1907. try:
  1908. templater.templater(m)
  1909. except Exception, inst:
  1910. ui.write(" %s\n" % inst)
  1911. p = None
  1912. else:
  1913. ui.write(_(" template 'default' not found\n"))
  1914. p = None
  1915. else:
  1916. ui.write(_(" no template directories found\n"))
  1917. if not p:
  1918. ui.write(_(" (templates seem to have been installed incorrectly)\n"))
  1919. problems += 1
  1920. # editor
  1921. ui.status(_("checking commit editor...\n"))
  1922. editor = ui.geteditor()
  1923. cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
  1924. if not cmdpath:
  1925. if editor == 'vi':
  1926. ui.write(_(" No commit editor set and can't find vi in PATH\n"))
  1927. ui.write(_(" (specify a commit editor in your configuration"
  1928. " file)\n"))
  1929. else:
  1930. ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
  1931. ui.write(_(" (specify a commit editor in your configuration"
  1932. " file)\n"))
  1933. problems += 1
  1934. # check username
  1935. ui.status(_("checking username...\n"))
  1936. try:
  1937. ui.username()
  1938. except util.Abort, e:
  1939. ui.write(" %s\n" % e)
  1940. ui.write(_(" (specify a username in your configuration file)\n"))
  1941. problems += 1
  1942. if not problems:
  1943. ui.status(_("no problems detected\n"))
  1944. else:
  1945. ui.write(_("%s problems detected,"
  1946. " please check your install!\n") % problems)
  1947. return problems
  1948. @command('debugknown', [], _('REPO ID...'), norepo=True)
  1949. def debugknown(ui, repopath, *ids, **opts):
  1950. """test whether node ids are known to a repo
  1951. Every ID must be a full-length hex node id string. Returns a list of 0s
  1952. and 1s indicating unknown/known.
  1953. """
  1954. repo = hg.peer(ui, opts, repopath)
  1955. if not repo.capable('known'):
  1956. raise util.Abort("known() not supported by target repository")
  1957. flags = repo.known([bin(s) for s in ids])
  1958. ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
  1959. @command('debuglabelcomplete', [], _('LABEL...'))
  1960. def debuglabelcomplete(ui, repo, *args):
  1961. '''complete "labels" - tags, open branch names, bookmark names'''
  1962. labels = set()
  1963. labels.update(t[0] for t in repo.tagslist())
  1964. labels.update(repo._bookmarks.keys())
  1965. labels.update(tag for (tag, heads, tip, closed)
  1966. in repo.branchmap().iterbranches() if not closed)
  1967. completions = set()
  1968. if not args:
  1969. args = ['']
  1970. for a in args:
  1971. completions.update(l for l in labels if l.startswith(a))
  1972. ui.write('\n'.join(sorted(completions)))
  1973. ui.write('\n')
  1974. @command('debugobsolete',
  1975. [('', 'flags', 0, _('markers flag')),
  1976. ] + commitopts2,
  1977. _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
  1978. def debugobsolete(ui, repo, precursor=None, *successors, **opts):
  1979. """create arbitrary obsolete marker
  1980. With no arguments, displays the list of obsolescence markers."""
  1981. def parsenodeid(s):
  1982. try:
  1983. # We do not use revsingle/revrange functions here to accept
  1984. # arbitrary node identifiers, possibly not present in the
  1985. # local repository.
  1986. n = bin(s)
  1987. if len(n) != len(nullid):
  1988. raise TypeError()
  1989. return n
  1990. except TypeError:
  1991. raise util.Abort('changeset references must be full hexadecimal '
  1992. 'node identifiers')
  1993. if precursor is not None:
  1994. metadata = {}
  1995. if 'date' in opts:
  1996. metadata['date'] = opts['date']
  1997. metadata['user'] = opts['user'] or ui.username()
  1998. succs = tuple(parsenodeid(succ) for succ in successors)
  1999. l = repo.lock()
  2000. try:
  2001. tr = repo.transaction('debugobsolete')
  2002. try:
  2003. repo.obsstore.create(tr, parsenodeid(precursor), succs,
  2004. opts['flags'], metadata)
  2005. tr.close()
  2006. finally:
  2007. tr.release()
  2008. finally:
  2009. l.release()
  2010. else:
  2011. for m in obsolete.allmarkers(repo):
  2012. cmdutil.showmarker(ui, m)
  2013. @command('debugpathcomplete',
  2014. [('f', 'full', None, _('complete an entire path')),
  2015. ('n', 'normal', None, _('show only normal files')),
  2016. ('a', 'added', None, _('show only added files')),
  2017. ('r', 'removed', None, _('show only removed files'))],
  2018. _('FILESPEC...'))
  2019. def debugpathcomplete(ui, repo, *specs, **opts):
  2020. '''complete part or all of a tracked path
  2021. This command supports shells that offer path name completion. It
  2022. currently completes only files already known to the dirstate.
  2023. Completion extends only to the next path segment unless
  2024. --full is specified, in which case entire paths are used.'''
  2025. def complete(path, acceptable):
  2026. dirstate = repo.dirstate
  2027. spec = os.path.normpath(os.path.join(os.getcwd(), path))
  2028. rootdir = repo.root + os.sep
  2029. if spec != repo.root and not spec.startswith(rootdir):
  2030. return [], []
  2031. if os.path.isdir(spec):
  2032. spec += '/'
  2033. spec = spec[len(rootdir):]
  2034. fixpaths = os.sep != '/'
  2035. if fixpaths:
  2036. spec = spec.replace(os.sep, '/')
  2037. speclen = len(spec)
  2038. fullpaths = opts['full']
  2039. files, dirs = set(), set()
  2040. adddir, addfile = dirs.add, files.add
  2041. for f, st in dirstate.iteritems():
  2042. if f.startswith(spec) and st[0] in acceptable:
  2043. if fixpaths:
  2044. f = f.replace('/', os.sep)
  2045. if fullpaths:
  2046. addfile(f)
  2047. continue
  2048. s = f.find(os.sep, speclen)
  2049. if s >= 0:
  2050. adddir(f[:s])
  2051. else:
  2052. addfile(f)
  2053. return files, dirs
  2054. acceptable = ''
  2055. if opts['normal']:
  2056. acceptable += 'nm'
  2057. if opts['added']:
  2058. acceptable += 'a'
  2059. if opts['removed']:
  2060. acceptable += 'r'
  2061. cwd = repo.getcwd()
  2062. if not specs:
  2063. specs = ['.']
  2064. files, dirs = set(), set()
  2065. for spec in specs:
  2066. f, d = complete(spec, acceptable or 'nmar')
  2067. files.update(f)
  2068. dirs.update(d)
  2069. files.update(dirs)
  2070. ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
  2071. ui.write('\n')
  2072. @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
  2073. def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
  2074. '''access the pushkey key/value protocol
  2075. With two args, list the keys in the given namespace.
  2076. With five args, set a key to new if it currently is set to old.
  2077. Reports success or failure.
  2078. '''
  2079. target = hg.peer(ui, {}, repopath)
  2080. if keyinfo:
  2081. key, old, new = keyinfo
  2082. r = target.pushkey(namespace, key, old, new)
  2083. ui.status(str(r) + '\n')
  2084. return not r
  2085. else:
  2086. for k, v in sorted(target.listkeys(namespace).iteritems()):
  2087. ui.write("%s\t%s\n" % (k.encode('string-escape'),
  2088. v.encode('string-escape')))
  2089. @command('debugpvec', [], _('A B'))
  2090. def debugpvec(ui, repo, a, b=None):
  2091. ca = scmutil.revsingle(repo, a)
  2092. cb = scmutil.revsingle(repo, b)
  2093. pa = pvec.ctxpvec(ca)
  2094. pb = pvec.ctxpvec(cb)
  2095. if pa == pb:
  2096. rel = "="
  2097. elif pa > pb:
  2098. rel = ">"
  2099. elif pa < pb:
  2100. rel = "<"
  2101. elif pa | pb:
  2102. rel = "|"
  2103. ui.write(_("a: %s\n") % pa)
  2104. ui.write(_("b: %s\n") % pb)
  2105. ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
  2106. ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
  2107. (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
  2108. pa.distance(pb), rel))
  2109. @command('debugrebuilddirstate|debugrebuildstate',
  2110. [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
  2111. _('[-r REV]'))
  2112. def debugrebuilddirstate(ui, repo, rev):
  2113. """rebuild the dirstate as it would look like for the given revision
  2114. If no revision is specified the first current parent will be used.
  2115. The dirstate will be set to the files of the given revision.
  2116. The actual working directory content or existing dirstate
  2117. information such as adds or removes is not considered.
  2118. One use of this command is to make the next :hg:`status` invocation
  2119. check the actual file content.
  2120. """
  2121. ctx = scmutil.revsingle(repo, rev)
  2122. wlock = repo.wlock()
  2123. try:
  2124. repo.dirstate.rebuild(ctx.node(), ctx.manifest())
  2125. finally:
  2126. wlock.release()
  2127. @command('debugrename',
  2128. [('r', 'rev', '', _('revision to debug'), _('REV'))],
  2129. _('[-r REV] FILE'))
  2130. def debugrename(ui, repo, file1, *pats, **opts):
  2131. """dump rename information"""
  2132. ctx = scmutil.revsingle(repo, opts.get('rev'))
  2133. m = scmutil.match(ctx, (file1,) + pats, opts)
  2134. for abs in ctx.walk(m):
  2135. fctx = ctx[abs]
  2136. o = fctx.filelog().renamed(fctx.filenode())
  2137. rel = m.rel(abs)
  2138. if o:
  2139. ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
  2140. else:
  2141. ui.write(_("%s not renamed\n") % rel)
  2142. @command('debugrevlog',
  2143. [('c', 'changelog', False, _('open changelog')),
  2144. ('m', 'manifest', False, _('open manifest')),
  2145. ('d', 'dump', False, _('dump index data'))],
  2146. _('-c|-m|FILE'),
  2147. optionalrepo=True)
  2148. def debugrevlog(ui, repo, file_=None, **opts):
  2149. """show data and statistics about a revlog"""
  2150. r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
  2151. if opts.get("dump"):
  2152. numrevs = len(r)
  2153. ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
  2154. " rawsize totalsize compression heads\n")
  2155. ts = 0
  2156. heads = set()
  2157. for rev in xrange(numrevs):
  2158. dbase = r.deltaparent(rev)
  2159. if dbase == -1:
  2160. dbase = rev
  2161. cbase = r.chainbase(rev)
  2162. p1, p2 = r.parentrevs(rev)
  2163. rs = r.rawsize(rev)
  2164. ts = ts + rs
  2165. heads -= set(r.parentrevs(rev))
  2166. heads.add(rev)
  2167. ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d %11d %5d\n" %
  2168. (rev, p1, p2, r.start(rev), r.end(rev),
  2169. r.start(dbase), r.start(cbase),
  2170. r.start(p1), r.start(p2),
  2171. rs, ts, ts / r.end(rev), len(heads)))
  2172. return 0
  2173. v = r.version
  2174. format = v & 0xFFFF
  2175. flags = []
  2176. gdelta = False
  2177. if v & revlog.REVLOGNGINLINEDATA:
  2178. flags.append('inline')
  2179. if v & revlog.REVLOGGENERALDELTA:
  2180. gdelta = True
  2181. flags.append('generaldelta')
  2182. if not flags:
  2183. flags = ['(none)']
  2184. nummerges = 0
  2185. numfull = 0
  2186. numprev = 0
  2187. nump1 = 0
  2188. nump2 = 0
  2189. numother = 0
  2190. nump1prev = 0
  2191. nump2prev = 0
  2192. chainlengths = []
  2193. datasize = [None, 0, 0L]
  2194. fullsize = [None, 0, 0L]
  2195. deltasize = [None, 0, 0L]
  2196. def addsize(size, l):
  2197. if l[0] is None or size < l[0]:
  2198. l[0] = size
  2199. if size > l[1]:
  2200. l[1] = size
  2201. l[2] += size
  2202. numrevs = len(r)
  2203. for rev in xrange(numrevs):
  2204. p1, p2 = r.parentrevs(rev)
  2205. delta = r.deltaparent(rev)
  2206. if format > 0:
  2207. addsize(r.rawsize(rev), datasize)
  2208. if p2 != nullrev:
  2209. nummerges += 1
  2210. size = r.length(rev)
  2211. if delta == nullrev:
  2212. chainlengths.append(0)
  2213. numfull += 1
  2214. addsize(size, fullsize)
  2215. else:
  2216. chainlengths.append(chainlengths[delta] + 1)
  2217. addsize(size, deltasize)
  2218. if delta == rev - 1:
  2219. numprev += 1
  2220. if delta == p1:
  2221. nump1prev += 1
  2222. elif delta == p2:
  2223. nump2prev += 1
  2224. elif delta == p1:
  2225. nump1 += 1
  2226. elif delta == p2:
  2227. nump2 += 1
  2228. elif delta != nullrev:
  2229. numother += 1
  2230. # Adjust size min value for empty cases
  2231. for size in (datasize, fullsize, deltasize):
  2232. if size[0] is None:
  2233. size[0] = 0
  2234. numdeltas = numrevs - numfull
  2235. numoprev = numprev - nump1prev - nump2prev
  2236. totalrawsize = datasize[2]
  2237. datasize[2] /= numrevs
  2238. fulltotal = fullsize[2]
  2239. fullsize[2] /= numfull
  2240. deltatotal = deltasize[2]
  2241. if numrevs - numfull > 0:
  2242. deltasize[2] /= numrevs - numfull
  2243. totalsize = fulltotal + deltatotal
  2244. avgchainlen = sum(chainlengths) / numrevs
  2245. compratio = totalrawsize / totalsize
  2246. basedfmtstr = '%%%dd\n'
  2247. basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
  2248. def dfmtstr(max):
  2249. return basedfmtstr % len(str(max))
  2250. def pcfmtstr(max, padding=0):
  2251. return basepcfmtstr % (len(str(max)), ' ' * padding)
  2252. def pcfmt(value, total):
  2253. return (value, 100 * float(value) / total)
  2254. ui.write(('format : %d\n') % format)
  2255. ui.write(('flags : %s\n') % ', '.join(flags))
  2256. ui.write('\n')
  2257. fmt = pcfmtstr(totalsize)
  2258. fmt2 = dfmtstr(totalsize)
  2259. ui.write(('revisions : ') + fmt2 % numrevs)
  2260. ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
  2261. ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
  2262. ui.write(('revisions : ') + fmt2 % numrevs)
  2263. ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
  2264. ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
  2265. ui.write(('revision size : ') + fmt2 % totalsize)
  2266. ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
  2267. ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
  2268. ui.write('\n')
  2269. fmt = dfmtstr(max(avgchainlen, compratio))
  2270. ui.write(('avg chain length : ') + fmt % avgchainlen)
  2271. ui.write(('compression ratio : ') + fmt % compratio)
  2272. if format > 0:
  2273. ui.write('\n')
  2274. ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
  2275. % tuple(datasize))
  2276. ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
  2277. % tuple(fullsize))
  2278. ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
  2279. % tuple(deltasize))
  2280. if numdeltas > 0:
  2281. ui.write('\n')
  2282. fmt = pcfmtstr(numdeltas)
  2283. fmt2 = pcfmtstr(numdeltas, 4)
  2284. ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
  2285. if numprev > 0:
  2286. ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
  2287. numprev))
  2288. ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
  2289. numprev))
  2290. ui.write((' other : ') + fmt2 % pcfmt(numoprev,
  2291. numprev))
  2292. if gdelta:
  2293. ui.write(('deltas against p1 : ')
  2294. + fmt % pcfmt(nump1, numdeltas))
  2295. ui.write(('deltas against p2 : ')
  2296. + fmt % pcfmt(nump2, numdeltas))
  2297. ui.write(('deltas against other : ') + fmt % pcfmt(numother,
  2298. numdeltas))
  2299. @command('debugrevspec',
  2300. [('', 'optimize', None, _('print parsed tree after optimizing'))],
  2301. ('REVSPEC'))
  2302. def debugrevspec(ui, repo, expr, **opts):
  2303. """parse and apply a revision specification
  2304. Use --verbose to print the parsed tree before and after aliases
  2305. expansion.
  2306. """
  2307. if ui.verbose:
  2308. tree = revset.parse(expr)[0]
  2309. ui.note(revset.prettyformat(tree), "\n")
  2310. newtree = revset.findaliases(ui, tree)
  2311. if newtree != tree:
  2312. ui.note(revset.prettyformat(newtree), "\n")
  2313. if opts["optimize"]:
  2314. weight, optimizedtree = revset.optimize(newtree, True)
  2315. ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
  2316. func = revset.match(ui, expr)
  2317. for c in func(repo, revset.spanset(repo)):
  2318. ui.write("%s\n" % c)
  2319. @command('debugsetparents', [], _('REV1 [REV2]'))
  2320. def debugsetparents(ui, repo, rev1, rev2=None):
  2321. """manually set the parents of the current working directory
  2322. This is useful for writing repository conversion tools, but should
  2323. be used with care.
  2324. Returns 0 on success.
  2325. """
  2326. r1 = scmutil.revsingle(repo, rev1).node()
  2327. r2 = scmutil.revsingle(repo, rev2, 'null').node()
  2328. wlock = repo.wlock()
  2329. try:
  2330. repo.setparents(r1, r2)
  2331. finally:
  2332. wlock.release()
  2333. @command('debugdirstate|debugstate',
  2334. [('', 'nodates', None, _('do not display the saved mtime')),
  2335. ('', 'datesort', None, _('sort by saved mtime'))],
  2336. _('[OPTION]...'))
  2337. def debugstate(ui, repo, nodates=None, datesort=None):
  2338. """show the contents of the current dirstate"""
  2339. timestr = ""
  2340. showdate = not nodates
  2341. if datesort:
  2342. keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
  2343. else:
  2344. keyfunc = None # sort by filename
  2345. for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
  2346. if showdate:
  2347. if ent[3] == -1:
  2348. # Pad or slice to locale representation
  2349. locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
  2350. time.localtime(0)))
  2351. timestr = 'unset'
  2352. timestr = (timestr[:locale_len] +
  2353. ' ' * (locale_len - len(timestr)))
  2354. else:
  2355. timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
  2356. time.localtime(ent[3]))
  2357. if ent[1] & 020000:
  2358. mode = 'lnk'
  2359. else:
  2360. mode = '%3o' % (ent[1] & 0777 & ~util.umask)
  2361. ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
  2362. for f in repo.dirstate.copies():
  2363. ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
  2364. @command('debugsub',
  2365. [('r', 'rev', '',
  2366. _('revision to check'), _('REV'))],
  2367. _('[-r REV] [REV]'))
  2368. def debugsub(ui, repo, rev=None):
  2369. ctx = scmutil.revsingle(repo, rev, None)
  2370. for k, v in sorted(ctx.substate.items()):
  2371. ui.write(('path %s\n') % k)
  2372. ui.write((' source %s\n') % v[0])
  2373. ui.write((' revision %s\n') % v[1])
  2374. @command('debugsuccessorssets',
  2375. [],
  2376. _('[REV]'))
  2377. def debugsuccessorssets(ui, repo, *revs):
  2378. """show set of successors for revision
  2379. A successors set of changeset A is a consistent group of revisions that
  2380. succeed A. It contains non-obsolete changesets only.
  2381. In most cases a changeset A has a single successors set containing a single
  2382. successor (changeset A replaced by A').
  2383. A changeset that is made obsolete with no successors are called "pruned".
  2384. Such changesets have no successors sets at all.
  2385. A changeset that has been "split" will have a successors set containing
  2386. more than one successor.
  2387. A changeset that has been rewritten in multiple different ways is called
  2388. "divergent". Such changesets have multiple successor sets (each of which
  2389. may also be split, i.e. have multiple successors).
  2390. Results are displayed as follows::
  2391. <rev1>
  2392. <successors-1A>
  2393. <rev2>
  2394. <successors-2A>
  2395. <successors-2B1> <successors-2B2> <successors-2B3>
  2396. Here rev2 has two possible (i.e. divergent) successors sets. The first
  2397. holds one element, whereas the second holds three (i.e. the changeset has
  2398. been split).
  2399. """
  2400. # passed to successorssets caching computation from one call to another
  2401. cache = {}
  2402. ctx2str = str
  2403. node2str = short
  2404. if ui.debug():
  2405. def ctx2str(ctx):
  2406. return ctx.hex()
  2407. node2str = hex
  2408. for rev in scmutil.revrange(repo, revs):
  2409. ctx = repo[rev]
  2410. ui.write('%s\n'% ctx2str(ctx))
  2411. for succsset in obsolete.successorssets(repo, ctx.node(), cache):
  2412. if succsset:
  2413. ui.write(' ')
  2414. ui.write(node2str(succsset[0]))
  2415. for node in succsset[1:]:
  2416. ui.write(' ')
  2417. ui.write(node2str(node))
  2418. ui.write('\n')
  2419. @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
  2420. def debugwalk(ui, repo, *pats, **opts):
  2421. """show how files match on given patterns"""
  2422. m = scmutil.match(repo[None], pats, opts)
  2423. items = list(repo.walk(m))
  2424. if not items:
  2425. return
  2426. f = lambda fn: fn
  2427. if ui.configbool('ui', 'slash') and os.sep != '/':
  2428. f = lambda fn: util.normpath(fn)
  2429. fmt = 'f %%-%ds %%-%ds %%s' % (
  2430. max([len(abs) for abs in items]),
  2431. max([len(m.rel(abs)) for abs in items]))
  2432. for abs in items:
  2433. line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
  2434. ui.write("%s\n" % line.rstrip())
  2435. @command('debugwireargs',
  2436. [('', 'three', '', 'three'),
  2437. ('', 'four', '', 'four'),
  2438. ('', 'five', '', 'five'),
  2439. ] + remoteopts,
  2440. _('REPO [OPTIONS]... [ONE [TWO]]'),
  2441. norepo=True)
  2442. def debugwireargs(ui, repopath, *vals, **opts):
  2443. repo = hg.peer(ui, opts, repopath)
  2444. for opt in remoteopts:
  2445. del opts[opt[1]]
  2446. args = {}
  2447. for k, v in opts.iteritems():
  2448. if v:
  2449. args[k] = v
  2450. # run twice to check that we don't mess up the stream for the next command
  2451. res1 = repo.debugwireargs(*vals, **args)
  2452. res2 = repo.debugwireargs(*vals, **args)
  2453. ui.write("%s\n" % res1)
  2454. if res1 != res2:
  2455. ui.warn("%s\n" % res2)
  2456. @command('^diff',
  2457. [('r', 'rev', [], _('revision'), _('REV')),
  2458. ('c', 'change', '', _('change made by revision'), _('REV'))
  2459. ] + diffopts + diffopts2 + walkopts + subrepoopts,
  2460. _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
  2461. inferrepo=True)
  2462. def diff(ui, repo, *pats, **opts):
  2463. """diff repository (or selected files)
  2464. Show differences between revisions for the specified files.
  2465. Differences between files are shown using the unified diff format.
  2466. .. note::
  2467. diff may generate unexpected results for merges, as it will
  2468. default to comparing against the working directory's first
  2469. parent changeset if no revisions are specified.
  2470. When two revision arguments are given, then changes are shown
  2471. between those revisions. If only one revision is specified then
  2472. that revision is compared to the working directory, and, when no
  2473. revisions are specified, the working directory files are compared
  2474. to its parent.
  2475. Alternatively you can specify -c/--change with a revision to see
  2476. the changes in that changeset relative to its first parent.
  2477. Without the -a/--text option, diff will avoid generating diffs of
  2478. files it detects as binary. With -a, diff will generate a diff
  2479. anyway, probably with undesirable results.
  2480. Use the -g/--git option to generate diffs in the git extended diff
  2481. format. For more information, read :hg:`help diffs`.
  2482. .. container:: verbose
  2483. Examples:
  2484. - compare a file in the current working directory to its parent::
  2485. hg diff foo.c
  2486. - compare two historical versions of a directory, with rename info::
  2487. hg diff --git -r 1.0:1.2 lib/
  2488. - get change stats relative to the last change on some date::
  2489. hg diff --stat -r "date('may 2')"
  2490. - diff all newly-added files that contain a keyword::
  2491. hg diff "set:added() and grep(GNU)"
  2492. - compare a revision and its parents::
  2493. hg diff -c 9353 # compare against first parent
  2494. hg diff -r 9353^:9353 # same using revset syntax
  2495. hg diff -r 9353^2:9353 # compare against the second parent
  2496. Returns 0 on success.
  2497. """
  2498. revs = opts.get('rev')
  2499. change = opts.get('change')
  2500. stat = opts.get('stat')
  2501. reverse = opts.get('reverse')
  2502. if revs and change:
  2503. msg = _('cannot specify --rev and --change at the same time')
  2504. raise util.Abort(msg)
  2505. elif change:
  2506. node2 = scmutil.revsingle(repo, change, None).node()
  2507. node1 = repo[node2].p1().node()
  2508. else:
  2509. node1, node2 = scmutil.revpair(repo, revs)
  2510. if reverse:
  2511. node1, node2 = node2, node1
  2512. diffopts = patch.diffopts(ui, opts)
  2513. m = scmutil.match(repo[node2], pats, opts)
  2514. cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
  2515. listsubrepos=opts.get('subrepos'))
  2516. @command('^export',
  2517. [('o', 'output', '',
  2518. _('print output to file with formatted name'), _('FORMAT')),
  2519. ('', 'switch-parent', None, _('diff against the second parent')),
  2520. ('r', 'rev', [], _('revisions to export'), _('REV')),
  2521. ] + diffopts,
  2522. _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
  2523. def export(ui, repo, *changesets, **opts):
  2524. """dump the header and diffs for one or more changesets
  2525. Print the changeset header and diffs for one or more revisions.
  2526. If no revision is given, the parent of the working directory is used.
  2527. The information shown in the changeset header is: author, date,
  2528. branch name (if non-default), changeset hash, parent(s) and commit
  2529. comment.
  2530. .. note::
  2531. export may generate unexpected diff output for merge
  2532. changesets, as it will compare the merge changeset against its
  2533. first parent only.
  2534. Output may be to a file, in which case the name of the file is
  2535. given using a format string. The formatting rules are as follows:
  2536. :``%%``: literal "%" character
  2537. :``%H``: changeset hash (40 hexadecimal digits)
  2538. :``%N``: number of patches being generated
  2539. :``%R``: changeset revision number
  2540. :``%b``: basename of the exporting repository
  2541. :``%h``: short-form changeset hash (12 hexadecimal digits)
  2542. :``%m``: first line of the commit message (only alphanumeric characters)
  2543. :``%n``: zero-padded sequence number, starting at 1
  2544. :``%r``: zero-padded changeset revision number
  2545. Without the -a/--text option, export will avoid generating diffs
  2546. of files it detects as binary. With -a, export will generate a
  2547. diff anyway, probably with undesirable results.
  2548. Use the -g/--git option to generate diffs in the git extended diff
  2549. format. See :hg:`help diffs` for more information.
  2550. With the --switch-parent option, the diff will be against the
  2551. second parent. It can be useful to review a merge.
  2552. .. container:: verbose
  2553. Examples:
  2554. - use export and import to transplant a bugfix to the current
  2555. branch::
  2556. hg export -r 9353 | hg import -
  2557. - export all the changesets between two revisions to a file with
  2558. rename information::
  2559. hg export --git -r 123:150 > changes.txt
  2560. - split outgoing changes into a series of patches with
  2561. descriptive names::
  2562. hg export -r "outgoing()" -o "%n-%m.patch"
  2563. Returns 0 on success.
  2564. """
  2565. changesets += tuple(opts.get('rev', []))
  2566. if not changesets:
  2567. changesets = ['.']
  2568. revs = scmutil.revrange(repo, changesets)
  2569. if not revs:
  2570. raise util.Abort(_("export requires at least one changeset"))
  2571. if len(revs) > 1:
  2572. ui.note(_('exporting patches:\n'))
  2573. else:
  2574. ui.note(_('exporting patch:\n'))
  2575. cmdutil.export(repo, revs, template=opts.get('output'),
  2576. switch_parent=opts.get('switch_parent'),
  2577. opts=patch.diffopts(ui, opts))
  2578. @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
  2579. def forget(ui, repo, *pats, **opts):
  2580. """forget the specified files on the next commit
  2581. Mark the specified files so they will no longer be tracked
  2582. after the next commit.
  2583. This only removes files from the current branch, not from the
  2584. entire project history, and it does not delete them from the
  2585. working directory.
  2586. To undo a forget before the next commit, see :hg:`add`.
  2587. .. container:: verbose
  2588. Examples:
  2589. - forget newly-added binary files::
  2590. hg forget "set:added() and binary()"
  2591. - forget files that would be excluded by .hgignore::
  2592. hg forget "set:hgignore()"
  2593. Returns 0 on success.
  2594. """
  2595. if not pats:
  2596. raise util.Abort(_('no files specified'))
  2597. m = scmutil.match(repo[None], pats, opts)
  2598. rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
  2599. return rejected and 1 or 0
  2600. @command(
  2601. 'graft',
  2602. [('r', 'rev', [], _('revisions to graft'), _('REV')),
  2603. ('c', 'continue', False, _('resume interrupted graft')),
  2604. ('e', 'edit', False, _('invoke editor on commit messages')),
  2605. ('', 'log', None, _('append graft info to log message')),
  2606. ('D', 'currentdate', False,
  2607. _('record the current date as commit date')),
  2608. ('U', 'currentuser', False,
  2609. _('record the current user as committer'), _('DATE'))]
  2610. + commitopts2 + mergetoolopts + dryrunopts,
  2611. _('[OPTION]... [-r] REV...'))
  2612. def graft(ui, repo, *revs, **opts):
  2613. '''copy changes from other branches onto the current branch
  2614. This command uses Mercurial's merge logic to copy individual
  2615. changes from other branches without merging branches in the
  2616. history graph. This is sometimes known as 'backporting' or
  2617. 'cherry-picking'. By default, graft will copy user, date, and
  2618. description from the source changesets.
  2619. Changesets that are ancestors of the current revision, that have
  2620. already been grafted, or that are merges will be skipped.
  2621. If --log is specified, log messages will have a comment appended
  2622. of the form::
  2623. (grafted from CHANGESETHASH)
  2624. If a graft merge results in conflicts, the graft process is
  2625. interrupted so that the current merge can be manually resolved.
  2626. Once all conflicts are addressed, the graft process can be
  2627. continued with the -c/--continue option.
  2628. .. note::
  2629. The -c/--continue option does not reapply earlier options.
  2630. .. container:: verbose
  2631. Examples:
  2632. - copy a single change to the stable branch and edit its description::
  2633. hg update stable
  2634. hg graft --edit 9393
  2635. - graft a range of changesets with one exception, updating dates::
  2636. hg graft -D "2085::2093 and not 2091"
  2637. - continue a graft after resolving conflicts::
  2638. hg graft -c
  2639. - show the source of a grafted changeset::
  2640. hg log --debug -r .
  2641. Returns 0 on successful completion.
  2642. '''
  2643. revs = list(revs)
  2644. revs.extend(opts['rev'])
  2645. if not opts.get('user') and opts.get('currentuser'):
  2646. opts['user'] = ui.username()
  2647. if not opts.get('date') and opts.get('currentdate'):
  2648. opts['date'] = "%d %d" % util.makedate()
  2649. editor = cmdutil.getcommiteditor(**opts)
  2650. cont = False
  2651. if opts['continue']:
  2652. cont = True
  2653. if revs:
  2654. raise util.Abort(_("can't specify --continue and revisions"))
  2655. # read in unfinished revisions
  2656. try:
  2657. nodes = repo.opener.read('graftstate').splitlines()
  2658. revs = [repo[node].rev() for node in nodes]
  2659. except IOError, inst:
  2660. if inst.errno != errno.ENOENT:
  2661. raise
  2662. raise util.Abort(_("no graft state found, can't continue"))
  2663. else:
  2664. cmdutil.checkunfinished(repo)
  2665. cmdutil.bailifchanged(repo)
  2666. if not revs:
  2667. raise util.Abort(_('no revisions specified'))
  2668. revs = scmutil.revrange(repo, revs)
  2669. # check for merges
  2670. for rev in repo.revs('%ld and merge()', revs):
  2671. ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
  2672. revs.remove(rev)
  2673. if not revs:
  2674. return -1
  2675. # check for ancestors of dest branch
  2676. crev = repo['.'].rev()
  2677. ancestors = repo.changelog.ancestors([crev], inclusive=True)
  2678. # Cannot use x.remove(y) on smart set, this has to be a list.
  2679. # XXX make this lazy in the future
  2680. revs = list(revs)
  2681. # don't mutate while iterating, create a copy
  2682. for rev in list(revs):
  2683. if rev in ancestors:
  2684. ui.warn(_('skipping ancestor revision %s\n') % rev)
  2685. # XXX remove on list is slow
  2686. revs.remove(rev)
  2687. if not revs:
  2688. return -1
  2689. # analyze revs for earlier grafts
  2690. ids = {}
  2691. for ctx in repo.set("%ld", revs):
  2692. ids[ctx.hex()] = ctx.rev()
  2693. n = ctx.extra().get('source')
  2694. if n:
  2695. ids[n] = ctx.rev()
  2696. # check ancestors for earlier grafts
  2697. ui.debug('scanning for duplicate grafts\n')
  2698. for rev in repo.changelog.findmissingrevs(revs, [crev]):
  2699. ctx = repo[rev]
  2700. n = ctx.extra().get('source')
  2701. if n in ids:
  2702. r = repo[n].rev()
  2703. if r in revs:
  2704. ui.warn(_('skipping revision %s (already grafted to %s)\n')
  2705. % (r, rev))
  2706. revs.remove(r)
  2707. elif ids[n] in revs:
  2708. ui.warn(_('skipping already grafted revision %s '
  2709. '(%s also has origin %d)\n') % (ids[n], rev, r))
  2710. revs.remove(ids[n])
  2711. elif ctx.hex() in ids:
  2712. r = ids[ctx.hex()]
  2713. ui.warn(_('skipping already grafted revision %s '
  2714. '(was grafted from %d)\n') % (r, rev))
  2715. revs.remove(r)
  2716. if not revs:
  2717. return -1
  2718. wlock = repo.wlock()
  2719. try:
  2720. current = repo['.']
  2721. for pos, ctx in enumerate(repo.set("%ld", revs)):
  2722. ui.status(_('grafting revision %s\n') % ctx.rev())
  2723. if opts.get('dry_run'):
  2724. continue
  2725. source = ctx.extra().get('source')
  2726. if not source:
  2727. source = ctx.hex()
  2728. extra = {'source': source}
  2729. user = ctx.user()
  2730. if opts.get('user'):
  2731. user = opts['user']
  2732. date = ctx.date()
  2733. if opts.get('date'):
  2734. date = opts['date']
  2735. message = ctx.description()
  2736. if opts.get('log'):
  2737. message += '\n(grafted from %s)' % ctx.hex()
  2738. # we don't merge the first commit when continuing
  2739. if not cont:
  2740. # perform the graft merge with p1(rev) as 'ancestor'
  2741. try:
  2742. # ui.forcemerge is an internal variable, do not document
  2743. repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
  2744. 'graft')
  2745. stats = mergemod.update(repo, ctx.node(), True, True, False,
  2746. ctx.p1().node(),
  2747. labels=['local', 'graft'])
  2748. finally:
  2749. repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
  2750. # report any conflicts
  2751. if stats and stats[3] > 0:
  2752. # write out state for --continue
  2753. nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
  2754. repo.opener.write('graftstate', ''.join(nodelines))
  2755. raise util.Abort(
  2756. _("unresolved conflicts, can't continue"),
  2757. hint=_('use hg resolve and hg graft --continue'))
  2758. else:
  2759. cont = False
  2760. # drop the second merge parent
  2761. repo.setparents(current.node(), nullid)
  2762. repo.dirstate.write()
  2763. # fix up dirstate for copies and renames
  2764. cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
  2765. # commit
  2766. node = repo.commit(text=message, user=user,
  2767. date=date, extra=extra, editor=editor)
  2768. if node is None:
  2769. ui.status(_('graft for revision %s is empty\n') % ctx.rev())
  2770. else:
  2771. current = repo[node]
  2772. finally:
  2773. wlock.release()
  2774. # remove state when we complete successfully
  2775. if not opts.get('dry_run'):
  2776. util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
  2777. return 0
  2778. @command('grep',
  2779. [('0', 'print0', None, _('end fields with NUL')),
  2780. ('', 'all', None, _('print all revisions that match')),
  2781. ('a', 'text', None, _('treat all files as text')),
  2782. ('f', 'follow', None,
  2783. _('follow changeset history,'
  2784. ' or file history across copies and renames')),
  2785. ('i', 'ignore-case', None, _('ignore case when matching')),
  2786. ('l', 'files-with-matches', None,
  2787. _('print only filenames and revisions that match')),
  2788. ('n', 'line-number', None, _('print matching line numbers')),
  2789. ('r', 'rev', [],
  2790. _('only search files changed within revision range'), _('REV')),
  2791. ('u', 'user', None, _('list the author (long with -v)')),
  2792. ('d', 'date', None, _('list the date (short with -q)')),
  2793. ] + walkopts,
  2794. _('[OPTION]... PATTERN [FILE]...'),
  2795. inferrepo=True)
  2796. def grep(ui, repo, pattern, *pats, **opts):
  2797. """search for a pattern in specified files and revisions
  2798. Search revisions of files for a regular expression.
  2799. This command behaves differently than Unix grep. It only accepts
  2800. Python/Perl regexps. It searches repository history, not the
  2801. working directory. It always prints the revision number in which a
  2802. match appears.
  2803. By default, grep only prints output for the first revision of a
  2804. file in which it finds a match. To get it to print every revision
  2805. that contains a change in match status ("-" for a match that
  2806. becomes a non-match, or "+" for a non-match that becomes a match),
  2807. use the --all flag.
  2808. Returns 0 if a match is found, 1 otherwise.
  2809. """
  2810. reflags = re.M
  2811. if opts.get('ignore_case'):
  2812. reflags |= re.I
  2813. try:
  2814. regexp = util.compilere(pattern, reflags)
  2815. except re.error, inst:
  2816. ui.warn(_("grep: invalid match pattern: %s\n") % inst)
  2817. return 1
  2818. sep, eol = ':', '\n'
  2819. if opts.get('print0'):
  2820. sep = eol = '\0'
  2821. getfile = util.lrucachefunc(repo.file)
  2822. def matchlines(body):
  2823. begin = 0
  2824. linenum = 0
  2825. while begin < len(body):
  2826. match = regexp.search(body, begin)
  2827. if not match:
  2828. break
  2829. mstart, mend = match.span()
  2830. linenum += body.count('\n', begin, mstart) + 1
  2831. lstart = body.rfind('\n', begin, mstart) + 1 or begin
  2832. begin = body.find('\n', mend) + 1 or len(body) + 1
  2833. lend = begin - 1
  2834. yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
  2835. class linestate(object):
  2836. def __init__(self, line, linenum, colstart, colend):
  2837. self.line = line
  2838. self.linenum = linenum
  2839. self.colstart = colstart
  2840. self.colend = colend
  2841. def __hash__(self):
  2842. return hash((self.linenum, self.line))
  2843. def __eq__(self, other):
  2844. return self.line == other.line
  2845. def __iter__(self):
  2846. yield (self.line[:self.colstart], '')
  2847. yield (self.line[self.colstart:self.colend], 'grep.match')
  2848. rest = self.line[self.colend:]
  2849. while rest != '':
  2850. match = regexp.search(rest)
  2851. if not match:
  2852. yield (rest, '')
  2853. break
  2854. mstart, mend = match.span()
  2855. yield (rest[:mstart], '')
  2856. yield (rest[mstart:mend], 'grep.match')
  2857. rest = rest[mend:]
  2858. matches = {}
  2859. copies = {}
  2860. def grepbody(fn, rev, body):
  2861. matches[rev].setdefault(fn, [])
  2862. m = matches[rev][fn]
  2863. for lnum, cstart, cend, line in matchlines(body):
  2864. s = linestate(line, lnum, cstart, cend)
  2865. m.append(s)
  2866. def difflinestates(a, b):
  2867. sm = difflib.SequenceMatcher(None, a, b)
  2868. for tag, alo, ahi, blo, bhi in sm.get_opcodes():
  2869. if tag == 'insert':
  2870. for i in xrange(blo, bhi):
  2871. yield ('+', b[i])
  2872. elif tag == 'delete':
  2873. for i in xrange(alo, ahi):
  2874. yield ('-', a[i])
  2875. elif tag == 'replace':
  2876. for i in xrange(alo, ahi):
  2877. yield ('-', a[i])
  2878. for i in xrange(blo, bhi):
  2879. yield ('+', b[i])
  2880. def display(fn, ctx, pstates, states):
  2881. rev = ctx.rev()
  2882. datefunc = ui.quiet and util.shortdate or util.datestr
  2883. found = False
  2884. @util.cachefunc
  2885. def binary():
  2886. flog = getfile(fn)
  2887. return util.binary(flog.read(ctx.filenode(fn)))
  2888. if opts.get('all'):
  2889. iter = difflinestates(pstates, states)
  2890. else:
  2891. iter = [('', l) for l in states]
  2892. for change, l in iter:
  2893. cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
  2894. if opts.get('line_number'):
  2895. cols.append((str(l.linenum), 'grep.linenumber'))
  2896. if opts.get('all'):
  2897. cols.append((change, 'grep.change'))
  2898. if opts.get('user'):
  2899. cols.append((ui.shortuser(ctx.user()), 'grep.user'))
  2900. if opts.get('date'):
  2901. cols.append((datefunc(ctx.date()), 'grep.date'))
  2902. for col, label in cols[:-1]:
  2903. ui.write(col, label=label)
  2904. ui.write(sep, label='grep.sep')
  2905. ui.write(cols[-1][0], label=cols[-1][1])
  2906. if not opts.get('files_with_matches'):
  2907. ui.write(sep, label='grep.sep')
  2908. if not opts.get('text') and binary():
  2909. ui.write(" Binary file matches")
  2910. else:
  2911. for s, label in l:
  2912. ui.write(s, label=label)
  2913. ui.write(eol)
  2914. found = True
  2915. if opts.get('files_with_matches'):
  2916. break
  2917. return found
  2918. skip = {}
  2919. revfiles = {}
  2920. matchfn = scmutil.match(repo[None], pats, opts)
  2921. found = False
  2922. follow = opts.get('follow')
  2923. def prep(ctx, fns):
  2924. rev = ctx.rev()
  2925. pctx = ctx.p1()
  2926. parent = pctx.rev()
  2927. matches.setdefault(rev, {})
  2928. matches.setdefault(parent, {})
  2929. files = revfiles.setdefault(rev, [])
  2930. for fn in fns:
  2931. flog = getfile(fn)
  2932. try:
  2933. fnode = ctx.filenode(fn)
  2934. except error.LookupError:
  2935. continue
  2936. copied = flog.renamed(fnode)
  2937. copy = follow and copied and copied[0]
  2938. if copy:
  2939. copies.setdefault(rev, {})[fn] = copy
  2940. if fn in skip:
  2941. if copy:
  2942. skip[copy] = True
  2943. continue
  2944. files.append(fn)
  2945. if fn not in matches[rev]:
  2946. grepbody(fn, rev, flog.read(fnode))
  2947. pfn = copy or fn
  2948. if pfn not in matches[parent]:
  2949. try:
  2950. fnode = pctx.filenode(pfn)
  2951. grepbody(pfn, parent, flog.read(fnode))
  2952. except error.LookupError:
  2953. pass
  2954. for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
  2955. rev = ctx.rev()
  2956. parent = ctx.p1().rev()
  2957. for fn in sorted(revfiles.get(rev, [])):
  2958. states = matches[rev][fn]
  2959. copy = copies.get(rev, {}).get(fn)
  2960. if fn in skip:
  2961. if copy:
  2962. skip[copy] = True
  2963. continue
  2964. pstates = matches.get(parent, {}).get(copy or fn, [])
  2965. if pstates or states:
  2966. r = display(fn, ctx, pstates, states)
  2967. found = found or r
  2968. if r and not opts.get('all'):
  2969. skip[fn] = True
  2970. if copy:
  2971. skip[copy] = True
  2972. del matches[rev]
  2973. del revfiles[rev]
  2974. return not found
  2975. @command('heads',
  2976. [('r', 'rev', '',
  2977. _('show only heads which are descendants of STARTREV'), _('STARTREV')),
  2978. ('t', 'topo', False, _('show topological heads only')),
  2979. ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
  2980. ('c', 'closed', False, _('show normal and closed branch heads')),
  2981. ] + templateopts,
  2982. _('[-ct] [-r STARTREV] [REV]...'))
  2983. def heads(ui, repo, *branchrevs, **opts):
  2984. """show branch heads
  2985. With no arguments, show all open branch heads in the repository.
  2986. Branch heads are changesets that have no descendants on the
  2987. same branch. They are where development generally takes place and
  2988. are the usual targets for update and merge operations.
  2989. If one or more REVs are given, only open branch heads on the
  2990. branches associated with the specified changesets are shown. This
  2991. means that you can use :hg:`heads .` to see the heads on the
  2992. currently checked-out branch.
  2993. If -c/--closed is specified, also show branch heads marked closed
  2994. (see :hg:`commit --close-branch`).
  2995. If STARTREV is specified, only those heads that are descendants of
  2996. STARTREV will be displayed.
  2997. If -t/--topo is specified, named branch mechanics will be ignored and only
  2998. topological heads (changesets with no children) will be shown.
  2999. Returns 0 if matching heads are found, 1 if not.
  3000. """
  3001. start = None
  3002. if 'rev' in opts:
  3003. start = scmutil.revsingle(repo, opts['rev'], None).node()
  3004. if opts.get('topo'):
  3005. heads = [repo[h] for h in repo.heads(start)]
  3006. else:
  3007. heads = []
  3008. for branch in repo.branchmap():
  3009. heads += repo.branchheads(branch, start, opts.get('closed'))
  3010. heads = [repo[h] for h in heads]
  3011. if branchrevs:
  3012. branches = set(repo[br].branch() for br in branchrevs)
  3013. heads = [h for h in heads if h.branch() in branches]
  3014. if opts.get('active') and branchrevs:
  3015. dagheads = repo.heads(start)
  3016. heads = [h for h in heads if h.node() in dagheads]
  3017. if branchrevs:
  3018. haveheads = set(h.branch() for h in heads)
  3019. if branches - haveheads:
  3020. headless = ', '.join(b for b in branches - haveheads)
  3021. msg = _('no open branch heads found on branches %s')
  3022. if opts.get('rev'):
  3023. msg += _(' (started at %s)') % opts['rev']
  3024. ui.warn((msg + '\n') % headless)
  3025. if not heads:
  3026. return 1
  3027. heads = sorted(heads, key=lambda x: -x.rev())
  3028. displayer = cmdutil.show_changeset(ui, repo, opts)
  3029. for ctx in heads:
  3030. displayer.show(ctx)
  3031. displayer.close()
  3032. @command('help',
  3033. [('e', 'extension', None, _('show only help for extensions')),
  3034. ('c', 'command', None, _('show only help for commands')),
  3035. ('k', 'keyword', '', _('show topics matching keyword')),
  3036. ],
  3037. _('[-ec] [TOPIC]'),
  3038. norepo=True)
  3039. def help_(ui, name=None, **opts):
  3040. """show help for a given topic or a help overview
  3041. With no arguments, print a list of commands with short help messages.
  3042. Given a topic, extension, or command name, print help for that
  3043. topic.
  3044. Returns 0 if successful.
  3045. """
  3046. textwidth = min(ui.termwidth(), 80) - 2
  3047. keep = ui.verbose and ['verbose'] or []
  3048. text = help.help_(ui, name, **opts)
  3049. formatted, pruned = minirst.format(text, textwidth, keep=keep)
  3050. if 'verbose' in pruned:
  3051. keep.append('omitted')
  3052. else:
  3053. keep.append('notomitted')
  3054. formatted, pruned = minirst.format(text, textwidth, keep=keep)
  3055. ui.write(formatted)
  3056. @command('identify|id',
  3057. [('r', 'rev', '',
  3058. _('identify the specified revision'), _('REV')),
  3059. ('n', 'num', None, _('show local revision number')),
  3060. ('i', 'id', None, _('show global revision id')),
  3061. ('b', 'branch', None, _('show branch')),
  3062. ('t', 'tags', None, _('show tags')),
  3063. ('B', 'bookmarks', None, _('show bookmarks')),
  3064. ] + remoteopts,
  3065. _('[-nibtB] [-r REV] [SOURCE]'),
  3066. optionalrepo=True)
  3067. def identify(ui, repo, source=None, rev=None,
  3068. num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
  3069. """identify the working copy or specified revision
  3070. Print a summary identifying the repository state at REV using one or
  3071. two parent hash identifiers, followed by a "+" if the working
  3072. directory has uncommitted changes, the branch name (if not default),
  3073. a list of tags, and a list of bookmarks.
  3074. When REV is not given, print a summary of the current state of the
  3075. repository.
  3076. Specifying a path to a repository root or Mercurial bundle will
  3077. cause lookup to operate on that repository/bundle.
  3078. .. container:: verbose
  3079. Examples:
  3080. - generate a build identifier for the working directory::
  3081. hg id --id > build-id.dat
  3082. - find the revision corresponding to a tag::
  3083. hg id -n -r 1.3
  3084. - check the most recent revision of a remote repository::
  3085. hg id -r tip http://selenic.com/hg/
  3086. Returns 0 if successful.
  3087. """
  3088. if not repo and not source:
  3089. raise util.Abort(_("there is no Mercurial repository here "
  3090. "(.hg not found)"))
  3091. hexfunc = ui.debugflag and hex or short
  3092. default = not (num or id or branch or tags or bookmarks)
  3093. output = []
  3094. revs = []
  3095. if source:
  3096. source, branches = hg.parseurl(ui.expandpath(source))
  3097. peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
  3098. repo = peer.local()
  3099. revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
  3100. if not repo:
  3101. if num or branch or tags:
  3102. raise util.Abort(
  3103. _("can't query remote revision number, branch, or tags"))
  3104. if not rev and revs:
  3105. rev = revs[0]
  3106. if not rev:
  3107. rev = "tip"
  3108. remoterev = peer.lookup(rev)
  3109. if default or id:
  3110. output = [hexfunc(remoterev)]
  3111. def getbms():
  3112. bms = []
  3113. if 'bookmarks' in peer.listkeys('namespaces'):
  3114. hexremoterev = hex(remoterev)
  3115. bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
  3116. if bmr == hexremoterev]
  3117. return sorted(bms)
  3118. if bookmarks:
  3119. output.extend(getbms())
  3120. elif default and not ui.quiet:
  3121. # multiple bookmarks for a single parent separated by '/'
  3122. bm = '/'.join(getbms())
  3123. if bm:
  3124. output.append(bm)
  3125. else:
  3126. if not rev:
  3127. ctx = repo[None]
  3128. parents = ctx.parents()
  3129. changed = ""
  3130. if default or id or num:
  3131. if (util.any(repo.status())
  3132. or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
  3133. changed = '+'
  3134. if default or id:
  3135. output = ["%s%s" %
  3136. ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
  3137. if num:
  3138. output.append("%s%s" %
  3139. ('+'.join([str(p.rev()) for p in parents]), changed))
  3140. else:
  3141. ctx = scmutil.revsingle(repo, rev)
  3142. if default or id:
  3143. output = [hexfunc(ctx.node())]
  3144. if num:
  3145. output.append(str(ctx.rev()))
  3146. if default and not ui.quiet:
  3147. b = ctx.branch()
  3148. if b != 'default':
  3149. output.append("(%s)" % b)
  3150. # multiple tags for a single parent separated by '/'
  3151. t = '/'.join(ctx.tags())
  3152. if t:
  3153. output.append(t)
  3154. # multiple bookmarks for a single parent separated by '/'
  3155. bm = '/'.join(ctx.bookmarks())
  3156. if bm:
  3157. output.append(bm)
  3158. else:
  3159. if branch:
  3160. output.append(ctx.branch())
  3161. if tags:
  3162. output.extend(ctx.tags())
  3163. if bookmarks:
  3164. output.extend(ctx.bookmarks())
  3165. ui.write("%s\n" % ' '.join(output))
  3166. @command('import|patch',
  3167. [('p', 'strip', 1,
  3168. _('directory strip option for patch. This has the same '
  3169. 'meaning as the corresponding patch option'), _('NUM')),
  3170. ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
  3171. ('e', 'edit', False, _('invoke editor on commit messages')),
  3172. ('f', 'force', None,
  3173. _('skip check for outstanding uncommitted changes (DEPRECATED)')),
  3174. ('', 'no-commit', None,
  3175. _("don't commit, just update the working directory")),
  3176. ('', 'bypass', None,
  3177. _("apply patch without touching the working directory")),
  3178. ('', 'partial', None,
  3179. _('commit even if some hunks fail')),
  3180. ('', 'exact', None,
  3181. _('apply patch to the nodes from which it was generated')),
  3182. ('', 'import-branch', None,
  3183. _('use any branch information in patch (implied by --exact)'))] +
  3184. commitopts + commitopts2 + similarityopts,
  3185. _('[OPTION]... PATCH...'))
  3186. def import_(ui, repo, patch1=None, *patches, **opts):
  3187. """import an ordered set of patches
  3188. Import a list of patches and commit them individually (unless
  3189. --no-commit is specified).
  3190. Because import first applies changes to the working directory,
  3191. import will abort if there are outstanding changes.
  3192. You can import a patch straight from a mail message. Even patches
  3193. as attachments work (to use the body part, it must have type
  3194. text/plain or text/x-patch). From and Subject headers of email
  3195. message are used as default committer and commit message. All
  3196. text/plain body parts before first diff are added to commit
  3197. message.
  3198. If the imported patch was generated by :hg:`export`, user and
  3199. description from patch override values from message headers and
  3200. body. Values given on command line with -m/--message and -u/--user
  3201. override these.
  3202. If --exact is specified, import will set the working directory to
  3203. the parent of each patch before applying it, and will abort if the
  3204. resulting changeset has a different ID than the one recorded in
  3205. the patch. This may happen due to character set problems or other
  3206. deficiencies in the text patch format.
  3207. Use --bypass to apply and commit patches directly to the
  3208. repository, not touching the working directory. Without --exact,
  3209. patches will be applied on top of the working directory parent
  3210. revision.
  3211. With -s/--similarity, hg will attempt to discover renames and
  3212. copies in the patch in the same way as :hg:`addremove`.
  3213. Use --partial to ensure a changeset will be created from the patch
  3214. even if some hunks fail to apply. Hunks that fail to apply will be
  3215. written to a <target-file>.rej file. Conflicts can then be resolved
  3216. by hand before :hg:`commit --amend` is run to update the created
  3217. changeset. This flag exists to let people import patches that
  3218. partially apply without losing the associated metadata (author,
  3219. date, description, ...), Note that when none of the hunk applies
  3220. cleanly, :hg:`import --partial` will create an empty changeset,
  3221. importing only the patch metadata.
  3222. To read a patch from standard input, use "-" as the patch name. If
  3223. a URL is specified, the patch will be downloaded from it.
  3224. See :hg:`help dates` for a list of formats valid for -d/--date.
  3225. .. container:: verbose
  3226. Examples:
  3227. - import a traditional patch from a website and detect renames::
  3228. hg import -s 80 http://example.com/bugfix.patch
  3229. - import a changeset from an hgweb server::
  3230. hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
  3231. - import all the patches in an Unix-style mbox::
  3232. hg import incoming-patches.mbox
  3233. - attempt to exactly restore an exported changeset (not always
  3234. possible)::
  3235. hg import --exact proposed-fix.patch
  3236. Returns 0 on success, 1 on partial success (see --partial).
  3237. """
  3238. if not patch1:
  3239. raise util.Abort(_('need at least one patch to import'))
  3240. patches = (patch1,) + patches
  3241. date = opts.get('date')
  3242. if date:
  3243. opts['date'] = util.parsedate(date)
  3244. update = not opts.get('bypass')
  3245. if not update and opts.get('no_commit'):
  3246. raise util.Abort(_('cannot use --no-commit with --bypass'))
  3247. try:
  3248. sim = float(opts.get('similarity') or 0)
  3249. except ValueError:
  3250. raise util.Abort(_('similarity must be a number'))
  3251. if sim < 0 or sim > 100:
  3252. raise util.Abort(_('similarity must be between 0 and 100'))
  3253. if sim and not update:
  3254. raise util.Abort(_('cannot use --similarity with --bypass'))
  3255. if update:
  3256. cmdutil.checkunfinished(repo)
  3257. if (opts.get('exact') or not opts.get('force')) and update:
  3258. cmdutil.bailifchanged(repo)
  3259. base = opts["base"]
  3260. wlock = lock = tr = None
  3261. msgs = []
  3262. ret = 0
  3263. try:
  3264. try:
  3265. wlock = repo.wlock()
  3266. if not opts.get('no_commit'):
  3267. lock = repo.lock()
  3268. tr = repo.transaction('import')
  3269. parents = repo.parents()
  3270. for patchurl in patches:
  3271. if patchurl == '-':
  3272. ui.status(_('applying patch from stdin\n'))
  3273. patchfile = ui.fin
  3274. patchurl = 'stdin' # for error message
  3275. else:
  3276. patchurl = os.path.join(base, patchurl)
  3277. ui.status(_('applying %s\n') % patchurl)
  3278. patchfile = hg.openpath(ui, patchurl)
  3279. haspatch = False
  3280. for hunk in patch.split(patchfile):
  3281. (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
  3282. parents, opts,
  3283. msgs, hg.clean)
  3284. if msg:
  3285. haspatch = True
  3286. ui.note(msg + '\n')
  3287. if update or opts.get('exact'):
  3288. parents = repo.parents()
  3289. else:
  3290. parents = [repo[node]]
  3291. if rej:
  3292. ui.write_err(_("patch applied partially\n"))
  3293. ui.write_err(("(fix the .rej files and run "
  3294. "`hg commit --amend`)\n"))
  3295. ret = 1
  3296. break
  3297. if not haspatch:
  3298. raise util.Abort(_('%s: no diffs found') % patchurl)
  3299. if tr:
  3300. tr.close()
  3301. if msgs:
  3302. repo.savecommitmessage('\n* * *\n'.join(msgs))
  3303. return ret
  3304. except: # re-raises
  3305. # wlock.release() indirectly calls dirstate.write(): since
  3306. # we're crashing, we do not want to change the working dir
  3307. # parent after all, so make sure it writes nothing
  3308. repo.dirstate.invalidate()
  3309. raise
  3310. finally:
  3311. if tr:
  3312. tr.release()
  3313. release(lock, wlock)
  3314. @command('incoming|in',
  3315. [('f', 'force', None,
  3316. _('run even if remote repository is unrelated')),
  3317. ('n', 'newest-first', None, _('show newest record first')),
  3318. ('', 'bundle', '',
  3319. _('file to store the bundles into'), _('FILE')),
  3320. ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
  3321. ('B', 'bookmarks', False, _("compare bookmarks")),
  3322. ('b', 'branch', [],
  3323. _('a specific branch you would like to pull'), _('BRANCH')),
  3324. ] + logopts + remoteopts + subrepoopts,
  3325. _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
  3326. def incoming(ui, repo, source="default", **opts):
  3327. """show new changesets found in source
  3328. Show new changesets found in the specified path/URL or the default
  3329. pull location. These are the changesets that would have been pulled
  3330. if a pull at the time you issued this command.
  3331. For remote repository, using --bundle avoids downloading the
  3332. changesets twice if the incoming is followed by a pull.
  3333. See pull for valid source format details.
  3334. .. container:: verbose
  3335. Examples:
  3336. - show incoming changes with patches and full description::
  3337. hg incoming -vp
  3338. - show incoming changes excluding merges, store a bundle::
  3339. hg in -vpM --bundle incoming.hg
  3340. hg pull incoming.hg
  3341. - briefly list changes inside a bundle::
  3342. hg in changes.hg -T "{desc|firstline}\\n"
  3343. Returns 0 if there are incoming changes, 1 otherwise.
  3344. """
  3345. if opts.get('graph'):
  3346. cmdutil.checkunsupportedgraphflags([], opts)
  3347. def display(other, chlist, displayer):
  3348. revdag = cmdutil.graphrevs(other, chlist, opts)
  3349. showparents = [ctx.node() for ctx in repo[None].parents()]
  3350. cmdutil.displaygraph(ui, revdag, displayer, showparents,
  3351. graphmod.asciiedges)
  3352. hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
  3353. return 0
  3354. if opts.get('bundle') and opts.get('subrepos'):
  3355. raise util.Abort(_('cannot combine --bundle and --subrepos'))
  3356. if opts.get('bookmarks'):
  3357. source, branches = hg.parseurl(ui.expandpath(source),
  3358. opts.get('branch'))
  3359. other = hg.peer(repo, opts, source)
  3360. if 'bookmarks' not in other.listkeys('namespaces'):
  3361. ui.warn(_("remote doesn't support bookmarks\n"))
  3362. return 0
  3363. ui.status(_('comparing with %s\n') % util.hidepassword(source))
  3364. return bookmarks.diff(ui, repo, other)
  3365. repo._subtoppath = ui.expandpath(source)
  3366. try:
  3367. return hg.incoming(ui, repo, source, opts)
  3368. finally:
  3369. del repo._subtoppath
  3370. @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
  3371. norepo=True)
  3372. def init(ui, dest=".", **opts):
  3373. """create a new repository in the given directory
  3374. Initialize a new repository in the given directory. If the given
  3375. directory does not exist, it will be created.
  3376. If no directory is given, the current directory is used.
  3377. It is possible to specify an ``ssh://`` URL as the destination.
  3378. See :hg:`help urls` for more information.
  3379. Returns 0 on success.
  3380. """
  3381. hg.peer(ui, opts, ui.expandpath(dest), create=True)
  3382. @command('locate',
  3383. [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
  3384. ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
  3385. ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
  3386. ] + walkopts,
  3387. _('[OPTION]... [PATTERN]...'))
  3388. def locate(ui, repo, *pats, **opts):
  3389. """locate files matching specific patterns
  3390. Print files under Mercurial control in the working directory whose
  3391. names match the given patterns.
  3392. By default, this command searches all directories in the working
  3393. directory. To search just the current directory and its
  3394. subdirectories, use "--include .".
  3395. If no patterns are given to match, this command prints the names
  3396. of all files under Mercurial control in the working directory.
  3397. If you want to feed the output of this command into the "xargs"
  3398. command, use the -0 option to both this command and "xargs". This
  3399. will avoid the problem of "xargs" treating single filenames that
  3400. contain whitespace as multiple filenames.
  3401. Returns 0 if a match is found, 1 otherwise.
  3402. """
  3403. end = opts.get('print0') and '\0' or '\n'
  3404. rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
  3405. ret = 1
  3406. m = scmutil.match(repo[rev], pats, opts, default='relglob')
  3407. m.bad = lambda x, y: False
  3408. for abs in repo[rev].walk(m):
  3409. if not rev and abs not in repo.dirstate:
  3410. continue
  3411. if opts.get('fullpath'):
  3412. ui.write(repo.wjoin(abs), end)
  3413. else:
  3414. ui.write(((pats and m.rel(abs)) or abs), end)
  3415. ret = 0
  3416. return ret
  3417. @command('^log|history',
  3418. [('f', 'follow', None,
  3419. _('follow changeset history, or file history across copies and renames')),
  3420. ('', 'follow-first', None,
  3421. _('only follow the first parent of merge changesets (DEPRECATED)')),
  3422. ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
  3423. ('C', 'copies', None, _('show copied files')),
  3424. ('k', 'keyword', [],
  3425. _('do case-insensitive search for a given text'), _('TEXT')),
  3426. ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
  3427. ('', 'removed', None, _('include revisions where files were removed')),
  3428. ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
  3429. ('u', 'user', [], _('revisions committed by user'), _('USER')),
  3430. ('', 'only-branch', [],
  3431. _('show only changesets within the given named branch (DEPRECATED)'),
  3432. _('BRANCH')),
  3433. ('b', 'branch', [],
  3434. _('show changesets within the given named branch'), _('BRANCH')),
  3435. ('P', 'prune', [],
  3436. _('do not display revision or any of its ancestors'), _('REV')),
  3437. ] + logopts + walkopts,
  3438. _('[OPTION]... [FILE]'),
  3439. inferrepo=True)
  3440. def log(ui, repo, *pats, **opts):
  3441. """show revision history of entire repository or files
  3442. Print the revision history of the specified files or the entire
  3443. project.
  3444. If no revision range is specified, the default is ``tip:0`` unless
  3445. --follow is set, in which case the working directory parent is
  3446. used as the starting revision.
  3447. File history is shown without following rename or copy history of
  3448. files. Use -f/--follow with a filename to follow history across
  3449. renames and copies. --follow without a filename will only show
  3450. ancestors or descendants of the starting revision.
  3451. By default this command prints revision number and changeset id,
  3452. tags, non-trivial parents, user, date and time, and a summary for
  3453. each commit. When the -v/--verbose switch is used, the list of
  3454. changed files and full commit message are shown.
  3455. With --graph the revisions are shown as an ASCII art DAG with the most
  3456. recent changeset at the top.
  3457. 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
  3458. and '+' represents a fork where the changeset from the lines below is a
  3459. parent of the 'o' merge on the same line.
  3460. .. note::
  3461. log -p/--patch may generate unexpected diff output for merge
  3462. changesets, as it will only compare the merge changeset against
  3463. its first parent. Also, only files different from BOTH parents
  3464. will appear in files:.
  3465. .. note::
  3466. for performance reasons, log FILE may omit duplicate changes
  3467. made on branches and will not show deletions. To see all
  3468. changes including duplicates and deletions, use the --removed
  3469. switch.
  3470. .. container:: verbose
  3471. Some examples:
  3472. - changesets with full descriptions and file lists::
  3473. hg log -v
  3474. - changesets ancestral to the working directory::
  3475. hg log -f
  3476. - last 10 commits on the current branch::
  3477. hg log -l 10 -b .
  3478. - changesets showing all modifications of a file, including removals::
  3479. hg log --removed file.c
  3480. - all changesets that touch a directory, with diffs, excluding merges::
  3481. hg log -Mp lib/
  3482. - all revision numbers that match a keyword::
  3483. hg log -k bug --template "{rev}\\n"
  3484. - check if a given changeset is included is a tagged release::
  3485. hg log -r "a21ccf and ancestor(1.9)"
  3486. - find all changesets by some user in a date range::
  3487. hg log -k alice -d "may 2008 to jul 2008"
  3488. - summary of all changesets after the last tag::
  3489. hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
  3490. See :hg:`help dates` for a list of formats valid for -d/--date.
  3491. See :hg:`help revisions` and :hg:`help revsets` for more about
  3492. specifying revisions.
  3493. See :hg:`help templates` for more about pre-packaged styles and
  3494. specifying custom templates.
  3495. Returns 0 on success.
  3496. """
  3497. if opts.get('graph'):
  3498. return cmdutil.graphlog(ui, repo, *pats, **opts)
  3499. revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
  3500. limit = cmdutil.loglimit(opts)
  3501. count = 0
  3502. getrenamed = None
  3503. if opts.get('copies'):
  3504. endrev = None
  3505. if opts.get('rev'):
  3506. endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
  3507. getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
  3508. displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
  3509. for rev in revs:
  3510. if count == limit:
  3511. break
  3512. ctx = repo[rev]
  3513. copies = None
  3514. if getrenamed is not None and rev:
  3515. copies = []
  3516. for fn in ctx.files():
  3517. rename = getrenamed(fn, rev)
  3518. if rename:
  3519. copies.append((fn, rename[0]))
  3520. revmatchfn = filematcher and filematcher(ctx.rev()) or None
  3521. displayer.show(ctx, copies=copies, matchfn=revmatchfn)
  3522. if displayer.flush(rev):
  3523. count += 1
  3524. displayer.close()
  3525. @command('manifest',
  3526. [('r', 'rev', '', _('revision to display'), _('REV')),
  3527. ('', 'all', False, _("list files from all revisions"))],
  3528. _('[-r REV]'))
  3529. def manifest(ui, repo, node=None, rev=None, **opts):
  3530. """output the current or given revision of the project manifest
  3531. Print a list of version controlled files for the given revision.
  3532. If no revision is given, the first parent of the working directory
  3533. is used, or the null revision if no revision is checked out.
  3534. With -v, print file permissions, symlink and executable bits.
  3535. With --debug, print file revision hashes.
  3536. If option --all is specified, the list of all files from all revisions
  3537. is printed. This includes deleted and renamed files.
  3538. Returns 0 on success.
  3539. """
  3540. fm = ui.formatter('manifest', opts)
  3541. if opts.get('all'):
  3542. if rev or node:
  3543. raise util.Abort(_("can't specify a revision with --all"))
  3544. res = []
  3545. prefix = "data/"
  3546. suffix = ".i"
  3547. plen = len(prefix)
  3548. slen = len(suffix)
  3549. lock = repo.lock()
  3550. try:
  3551. for fn, b, size in repo.store.datafiles():
  3552. if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
  3553. res.append(fn[plen:-slen])
  3554. finally:
  3555. lock.release()
  3556. for f in res:
  3557. fm.startitem()
  3558. fm.write("path", '%s\n', f)
  3559. fm.end()
  3560. return
  3561. if rev and node:
  3562. raise util.Abort(_("please specify just one revision"))
  3563. if not node:
  3564. node = rev
  3565. char = {'l': '@', 'x': '*', '': ''}
  3566. mode = {'l': '644', 'x': '755', '': '644'}
  3567. ctx = scmutil.revsingle(repo, node)
  3568. mf = ctx.manifest()
  3569. for f in ctx:
  3570. fm.startitem()
  3571. fl = ctx[f].flags()
  3572. fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
  3573. fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
  3574. fm.write('path', '%s\n', f)
  3575. fm.end()
  3576. @command('^merge',
  3577. [('f', 'force', None,
  3578. _('force a merge including outstanding changes (DEPRECATED)')),
  3579. ('r', 'rev', '', _('revision to merge'), _('REV')),
  3580. ('P', 'preview', None,
  3581. _('review revisions to merge (no merge is performed)'))
  3582. ] + mergetoolopts,
  3583. _('[-P] [-f] [[-r] REV]'))
  3584. def merge(ui, repo, node=None, **opts):
  3585. """merge working directory with another revision
  3586. The current working directory is updated with all changes made in
  3587. the requested revision since the last common predecessor revision.
  3588. Files that changed between either parent are marked as changed for
  3589. the next commit and a commit must be performed before any further
  3590. updates to the repository are allowed. The next commit will have
  3591. two parents.
  3592. ``--tool`` can be used to specify the merge tool used for file
  3593. merges. It overrides the HGMERGE environment variable and your
  3594. configuration files. See :hg:`help merge-tools` for options.
  3595. If no revision is specified, the working directory's parent is a
  3596. head revision, and the current branch contains exactly one other
  3597. head, the other head is merged with by default. Otherwise, an
  3598. explicit revision with which to merge with must be provided.
  3599. :hg:`resolve` must be used to resolve unresolved files.
  3600. To undo an uncommitted merge, use :hg:`update --clean .` which
  3601. will check out a clean copy of the original merge parent, losing
  3602. all changes.
  3603. Returns 0 on success, 1 if there are unresolved files.
  3604. """
  3605. if opts.get('rev') and node:
  3606. raise util.Abort(_("please specify just one revision"))
  3607. if not node:
  3608. node = opts.get('rev')
  3609. if node:
  3610. node = scmutil.revsingle(repo, node).node()
  3611. if not node and repo._bookmarkcurrent:
  3612. bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
  3613. curhead = repo[repo._bookmarkcurrent].node()
  3614. if len(bmheads) == 2:
  3615. if curhead == bmheads[0]:
  3616. node = bmheads[1]
  3617. else:
  3618. node = bmheads[0]
  3619. elif len(bmheads) > 2:
  3620. raise util.Abort(_("multiple matching bookmarks to merge - "
  3621. "please merge with an explicit rev or bookmark"),
  3622. hint=_("run 'hg heads' to see all heads"))
  3623. elif len(bmheads) <= 1:
  3624. raise util.Abort(_("no matching bookmark to merge - "
  3625. "please merge with an explicit rev or bookmark"),
  3626. hint=_("run 'hg heads' to see all heads"))
  3627. if not node and not repo._bookmarkcurrent:
  3628. branch = repo[None].branch()
  3629. bheads = repo.branchheads(branch)
  3630. nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
  3631. if len(nbhs) > 2:
  3632. raise util.Abort(_("branch '%s' has %d heads - "
  3633. "please merge with an explicit rev")
  3634. % (branch, len(bheads)),
  3635. hint=_("run 'hg heads .' to see heads"))
  3636. parent = repo.dirstate.p1()
  3637. if len(nbhs) <= 1:
  3638. if len(bheads) > 1:
  3639. raise util.Abort(_("heads are bookmarked - "
  3640. "please merge with an explicit rev"),
  3641. hint=_("run 'hg heads' to see all heads"))
  3642. if len(repo.heads()) > 1:
  3643. raise util.Abort(_("branch '%s' has one head - "
  3644. "please merge with an explicit rev")
  3645. % branch,
  3646. hint=_("run 'hg heads' to see all heads"))
  3647. msg, hint = _('nothing to merge'), None
  3648. if parent != repo.lookup(branch):
  3649. hint = _("use 'hg update' instead")
  3650. raise util.Abort(msg, hint=hint)
  3651. if parent not in bheads:
  3652. raise util.Abort(_('working directory not at a head revision'),
  3653. hint=_("use 'hg update' or merge with an "
  3654. "explicit revision"))
  3655. if parent == nbhs[0]:
  3656. node = nbhs[-1]
  3657. else:
  3658. node = nbhs[0]
  3659. if opts.get('preview'):
  3660. # find nodes that are ancestors of p2 but not of p1
  3661. p1 = repo.lookup('.')
  3662. p2 = repo.lookup(node)
  3663. nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
  3664. displayer = cmdutil.show_changeset(ui, repo, opts)
  3665. for node in nodes:
  3666. displayer.show(repo[node])
  3667. displayer.close()
  3668. return 0
  3669. try:
  3670. # ui.forcemerge is an internal variable, do not document
  3671. repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
  3672. return hg.merge(repo, node, force=opts.get('force'))
  3673. finally:
  3674. ui.setconfig('ui', 'forcemerge', '', 'merge')
  3675. @command('outgoing|out',
  3676. [('f', 'force', None, _('run even when the destination is unrelated')),
  3677. ('r', 'rev', [],
  3678. _('a changeset intended to be included in the destination'), _('REV')),
  3679. ('n', 'newest-first', None, _('show newest record first')),
  3680. ('B', 'bookmarks', False, _('compare bookmarks')),
  3681. ('b', 'branch', [], _('a specific branch you would like to push'),
  3682. _('BRANCH')),
  3683. ] + logopts + remoteopts + subrepoopts,
  3684. _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
  3685. def outgoing(ui, repo, dest=None, **opts):
  3686. """show changesets not found in the destination
  3687. Show changesets not found in the specified destination repository
  3688. or the default push location. These are the changesets that would
  3689. be pushed if a push was requested.
  3690. See pull for details of valid destination formats.
  3691. Returns 0 if there are outgoing changes, 1 otherwise.
  3692. """
  3693. if opts.get('graph'):
  3694. cmdutil.checkunsupportedgraphflags([], opts)
  3695. o, other = hg._outgoing(ui, repo, dest, opts)
  3696. if not o:
  3697. cmdutil.outgoinghooks(ui, repo, other, opts, o)
  3698. return
  3699. revdag = cmdutil.graphrevs(repo, o, opts)
  3700. displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
  3701. showparents = [ctx.node() for ctx in repo[None].parents()]
  3702. cmdutil.displaygraph(ui, revdag, displayer, showparents,
  3703. graphmod.asciiedges)
  3704. cmdutil.outgoinghooks(ui, repo, other, opts, o)
  3705. return 0
  3706. if opts.get('bookmarks'):
  3707. dest = ui.expandpath(dest or 'default-push', dest or 'default')
  3708. dest, branches = hg.parseurl(dest, opts.get('branch'))
  3709. other = hg.peer(repo, opts, dest)
  3710. if 'bookmarks' not in other.listkeys('namespaces'):
  3711. ui.warn(_("remote doesn't support bookmarks\n"))
  3712. return 0
  3713. ui.status(_('comparing with %s\n') % util.hidepassword(dest))
  3714. return bookmarks.diff(ui, other, repo)
  3715. repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
  3716. try:
  3717. return hg.outgoing(ui, repo, dest, opts)
  3718. finally:
  3719. del repo._subtoppath
  3720. @command('parents',
  3721. [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
  3722. ] + templateopts,
  3723. _('[-r REV] [FILE]'),
  3724. inferrepo=True)
  3725. def parents(ui, repo, file_=None, **opts):
  3726. """show the parents of the working directory or revision
  3727. Print the working directory's parent revisions. If a revision is
  3728. given via -r/--rev, the parent of that revision will be printed.
  3729. If a file argument is given, the revision in which the file was
  3730. last changed (before the working directory revision or the
  3731. argument to --rev if given) is printed.
  3732. Returns 0 on success.
  3733. """
  3734. ctx = scmutil.revsingle(repo, opts.get('rev'), None)
  3735. if file_:
  3736. m = scmutil.match(ctx, (file_,), opts)
  3737. if m.anypats() or len(m.files()) != 1:
  3738. raise util.Abort(_('can only specify an explicit filename'))
  3739. file_ = m.files()[0]
  3740. filenodes = []
  3741. for cp in ctx.parents():
  3742. if not cp:
  3743. continue
  3744. try:
  3745. filenodes.append(cp.filenode(file_))
  3746. except error.LookupError:
  3747. pass
  3748. if not filenodes:
  3749. raise util.Abort(_("'%s' not found in manifest!") % file_)
  3750. p = []
  3751. for fn in filenodes:
  3752. fctx = repo.filectx(file_, fileid=fn)
  3753. p.append(fctx.node())
  3754. else:
  3755. p = [cp.node() for cp in ctx.parents()]
  3756. displayer = cmdutil.show_changeset(ui, repo, opts)
  3757. for n in p:
  3758. if n != nullid:
  3759. displayer.show(repo[n])
  3760. displayer.close()
  3761. @command('paths', [], _('[NAME]'), optionalrepo=True)
  3762. def paths(ui, repo, search=None):
  3763. """show aliases for remote repositories
  3764. Show definition of symbolic path name NAME. If no name is given,
  3765. show definition of all available names.
  3766. Option -q/--quiet suppresses all output when searching for NAME
  3767. and shows only the path names when listing all definitions.
  3768. Path names are defined in the [paths] section of your
  3769. configuration file and in ``/etc/mercurial/hgrc``. If run inside a
  3770. repository, ``.hg/hgrc`` is used, too.
  3771. The path names ``default`` and ``default-push`` have a special
  3772. meaning. When performing a push or pull operation, they are used
  3773. as fallbacks if no location is specified on the command-line.
  3774. When ``default-push`` is set, it will be used for push and
  3775. ``default`` will be used for pull; otherwise ``default`` is used
  3776. as the fallback for both. When cloning a repository, the clone
  3777. source is written as ``default`` in ``.hg/hgrc``. Note that
  3778. ``default`` and ``default-push`` apply to all inbound (e.g.
  3779. :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
  3780. :hg:`bundle`) operations.
  3781. See :hg:`help urls` for more information.
  3782. Returns 0 on success.
  3783. """
  3784. if search:
  3785. for name, path in ui.configitems("paths"):
  3786. if name == search:
  3787. ui.status("%s\n" % util.hidepassword(path))
  3788. return
  3789. if not ui.quiet:
  3790. ui.warn(_("not found!\n"))
  3791. return 1
  3792. else:
  3793. for name, path in ui.configitems("paths"):
  3794. if ui.quiet:
  3795. ui.write("%s\n" % name)
  3796. else:
  3797. ui.write("%s = %s\n" % (name, util.hidepassword(path)))
  3798. @command('phase',
  3799. [('p', 'public', False, _('set changeset phase to public')),
  3800. ('d', 'draft', False, _('set changeset phase to draft')),
  3801. ('s', 'secret', False, _('set changeset phase to secret')),
  3802. ('f', 'force', False, _('allow to move boundary backward')),
  3803. ('r', 'rev', [], _('target revision'), _('REV')),
  3804. ],
  3805. _('[-p|-d|-s] [-f] [-r] REV...'))
  3806. def phase(ui, repo, *revs, **opts):
  3807. """set or show the current phase name
  3808. With no argument, show the phase name of specified revisions.
  3809. With one of -p/--public, -d/--draft or -s/--secret, change the
  3810. phase value of the specified revisions.
  3811. Unless -f/--force is specified, :hg:`phase` won't move changeset from a
  3812. lower phase to an higher phase. Phases are ordered as follows::
  3813. public < draft < secret
  3814. Returns 0 on success, 1 if no phases were changed or some could not
  3815. be changed.
  3816. """
  3817. # search for a unique phase argument
  3818. targetphase = None
  3819. for idx, name in enumerate(phases.phasenames):
  3820. if opts[name]:
  3821. if targetphase is not None:
  3822. raise util.Abort(_('only one phase can be specified'))
  3823. targetphase = idx
  3824. # look for specified revision
  3825. revs = list(revs)
  3826. revs.extend(opts['rev'])
  3827. if not revs:
  3828. raise util.Abort(_('no revisions specified'))
  3829. revs = scmutil.revrange(repo, revs)
  3830. lock = None
  3831. ret = 0
  3832. if targetphase is None:
  3833. # display
  3834. for r in revs:
  3835. ctx = repo[r]
  3836. ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
  3837. else:
  3838. lock = repo.lock()
  3839. try:
  3840. # set phase
  3841. if not revs:
  3842. raise util.Abort(_('empty revision set'))
  3843. nodes = [repo[r].node() for r in revs]
  3844. olddata = repo._phasecache.getphaserevs(repo)[:]
  3845. phases.advanceboundary(repo, targetphase, nodes)
  3846. if opts['force']:
  3847. phases.retractboundary(repo, targetphase, nodes)
  3848. finally:
  3849. lock.release()
  3850. # moving revision from public to draft may hide them
  3851. # We have to check result on an unfiltered repository
  3852. unfi = repo.unfiltered()
  3853. newdata = repo._phasecache.getphaserevs(unfi)
  3854. changes = sum(o != newdata[i] for i, o in enumerate(olddata))
  3855. cl = unfi.changelog
  3856. rejected = [n for n in nodes
  3857. if newdata[cl.rev(n)] < targetphase]
  3858. if rejected:
  3859. ui.warn(_('cannot move %i changesets to a higher '
  3860. 'phase, use --force\n') % len(rejected))
  3861. ret = 1
  3862. if changes:
  3863. msg = _('phase changed for %i changesets\n') % changes
  3864. if ret:
  3865. ui.status(msg)
  3866. else:
  3867. ui.note(msg)
  3868. else:
  3869. ui.warn(_('no phases changed\n'))
  3870. ret = 1
  3871. return ret
  3872. def postincoming(ui, repo, modheads, optupdate, checkout):
  3873. if modheads == 0:
  3874. return
  3875. if optupdate:
  3876. checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
  3877. try:
  3878. ret = hg.update(repo, checkout)
  3879. except util.Abort, inst:
  3880. ui.warn(_("not updating: %s\n") % str(inst))
  3881. if inst.hint:
  3882. ui.warn(_("(%s)\n") % inst.hint)
  3883. return 0
  3884. if not ret and not checkout:
  3885. if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
  3886. ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
  3887. return ret
  3888. if modheads > 1:
  3889. currentbranchheads = len(repo.branchheads())
  3890. if currentbranchheads == modheads:
  3891. ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
  3892. elif currentbranchheads > 1:
  3893. ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
  3894. "merge)\n"))
  3895. else:
  3896. ui.status(_("(run 'hg heads' to see heads)\n"))
  3897. else:
  3898. ui.status(_("(run 'hg update' to get a working copy)\n"))
  3899. @command('^pull',
  3900. [('u', 'update', None,
  3901. _('update to new branch head if changesets were pulled')),
  3902. ('f', 'force', None, _('run even when remote repository is unrelated')),
  3903. ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
  3904. ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
  3905. ('b', 'branch', [], _('a specific branch you would like to pull'),
  3906. _('BRANCH')),
  3907. ] + remoteopts,
  3908. _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
  3909. def pull(ui, repo, source="default", **opts):
  3910. """pull changes from the specified source
  3911. Pull changes from a remote repository to a local one.
  3912. This finds all changes from the repository at the specified path
  3913. or URL and adds them to a local repository (the current one unless
  3914. -R is specified). By default, this does not update the copy of the
  3915. project in the working directory.
  3916. Use :hg:`incoming` if you want to see what would have been added
  3917. by a pull at the time you issued this command. If you then decide
  3918. to add those changes to the repository, you should use :hg:`pull
  3919. -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
  3920. If SOURCE is omitted, the 'default' path will be used.
  3921. See :hg:`help urls` for more information.
  3922. Returns 0 on success, 1 if an update had unresolved files.
  3923. """
  3924. source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
  3925. other = hg.peer(repo, opts, source)
  3926. try:
  3927. ui.status(_('pulling from %s\n') % util.hidepassword(source))
  3928. revs, checkout = hg.addbranchrevs(repo, other, branches,
  3929. opts.get('rev'))
  3930. remotebookmarks = other.listkeys('bookmarks')
  3931. if opts.get('bookmark'):
  3932. if not revs:
  3933. revs = []
  3934. for b in opts['bookmark']:
  3935. if b not in remotebookmarks:
  3936. raise util.Abort(_('remote bookmark %s not found!') % b)
  3937. revs.append(remotebookmarks[b])
  3938. if revs:
  3939. try:
  3940. revs = [other.lookup(rev) for rev in revs]
  3941. except error.CapabilityError:
  3942. err = _("other repository doesn't support revision lookup, "
  3943. "so a rev cannot be specified.")
  3944. raise util.Abort(err)
  3945. modheads = repo.pull(other, heads=revs, force=opts.get('force'))
  3946. bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
  3947. if checkout:
  3948. checkout = str(repo.changelog.rev(other.lookup(checkout)))
  3949. repo._subtoppath = source
  3950. try:
  3951. ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
  3952. finally:
  3953. del repo._subtoppath
  3954. # update specified bookmarks
  3955. if opts.get('bookmark'):
  3956. marks = repo._bookmarks
  3957. for b in opts['bookmark']:
  3958. # explicit pull overrides local bookmark if any
  3959. ui.status(_("importing bookmark %s\n") % b)
  3960. marks[b] = repo[remotebookmarks[b]].node()
  3961. marks.write()
  3962. finally:
  3963. other.close()
  3964. return ret
  3965. @command('^push',
  3966. [('f', 'force', None, _('force push')),
  3967. ('r', 'rev', [],
  3968. _('a changeset intended to be included in the destination'),
  3969. _('REV')),
  3970. ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
  3971. ('b', 'branch', [],
  3972. _('a specific branch you would like to push'), _('BRANCH')),
  3973. ('', 'new-branch', False, _('allow pushing a new branch')),
  3974. ] + remoteopts,
  3975. _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
  3976. def push(ui, repo, dest=None, **opts):
  3977. """push changes to the specified destination
  3978. Push changesets from the local repository to the specified
  3979. destination.
  3980. This operation is symmetrical to pull: it is identical to a pull
  3981. in the destination repository from the current one.
  3982. By default, push will not allow creation of new heads at the
  3983. destination, since multiple heads would make it unclear which head
  3984. to use. In this situation, it is recommended to pull and merge
  3985. before pushing.
  3986. Use --new-branch if you want to allow push to create a new named
  3987. branch that is not present at the destination. This allows you to
  3988. only create a new branch without forcing other changes.
  3989. .. note::
  3990. Extra care should be taken with the -f/--force option,
  3991. which will push all new heads on all branches, an action which will
  3992. almost always cause confusion for collaborators.
  3993. If -r/--rev is used, the specified revision and all its ancestors
  3994. will be pushed to the remote repository.
  3995. If -B/--bookmark is used, the specified bookmarked revision, its
  3996. ancestors, and the bookmark will be pushed to the remote
  3997. repository.
  3998. Please see :hg:`help urls` for important details about ``ssh://``
  3999. URLs. If DESTINATION is omitted, a default path will be used.
  4000. Returns 0 if push was successful, 1 if nothing to push.
  4001. """
  4002. if opts.get('bookmark'):
  4003. ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
  4004. for b in opts['bookmark']:
  4005. # translate -B options to -r so changesets get pushed
  4006. if b in repo._bookmarks:
  4007. opts.setdefault('rev', []).append(b)
  4008. else:
  4009. # if we try to push a deleted bookmark, translate it to null
  4010. # this lets simultaneous -r, -b options continue working
  4011. opts.setdefault('rev', []).append("null")
  4012. dest = ui.expandpath(dest or 'default-push', dest or 'default')
  4013. dest, branches = hg.parseurl(dest, opts.get('branch'))
  4014. ui.status(_('pushing to %s\n') % util.hidepassword(dest))
  4015. revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
  4016. try:
  4017. other = hg.peer(repo, opts, dest)
  4018. except error.RepoError:
  4019. if dest == "default-push":
  4020. raise util.Abort(_("default repository not configured!"),
  4021. hint=_('see the "path" section in "hg help config"'))
  4022. else:
  4023. raise
  4024. if revs:
  4025. revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
  4026. repo._subtoppath = dest
  4027. try:
  4028. # push subrepos depth-first for coherent ordering
  4029. c = repo['']
  4030. subs = c.substate # only repos that are committed
  4031. for s in sorted(subs):
  4032. result = c.sub(s).push(opts)
  4033. if result == 0:
  4034. return not result
  4035. finally:
  4036. del repo._subtoppath
  4037. result = repo.push(other, opts.get('force'), revs=revs,
  4038. newbranch=opts.get('new_branch'))
  4039. result = not result
  4040. if opts.get('bookmark'):
  4041. bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
  4042. if bresult == 2:
  4043. return 2
  4044. if not result and bresult:
  4045. result = 2
  4046. return result
  4047. @command('recover', [])
  4048. def recover(ui, repo):
  4049. """roll back an interrupted transaction
  4050. Recover from an interrupted commit or pull.
  4051. This command tries to fix the repository status after an
  4052. interrupted operation. It should only be necessary when Mercurial
  4053. suggests it.
  4054. Returns 0 if successful, 1 if nothing to recover or verify fails.
  4055. """
  4056. if repo.recover():
  4057. return hg.verify(repo)
  4058. return 1
  4059. @command('^remove|rm',
  4060. [('A', 'after', None, _('record delete for missing files')),
  4061. ('f', 'force', None,
  4062. _('remove (and delete) file even if added or modified')),
  4063. ] + walkopts,
  4064. _('[OPTION]... FILE...'),
  4065. inferrepo=True)
  4066. def remove(ui, repo, *pats, **opts):
  4067. """remove the specified files on the next commit
  4068. Schedule the indicated files for removal from the current branch.
  4069. This command schedules the files to be removed at the next commit.
  4070. To undo a remove before that, see :hg:`revert`. To undo added
  4071. files, see :hg:`forget`.
  4072. .. container:: verbose
  4073. -A/--after can be used to remove only files that have already
  4074. been deleted, -f/--force can be used to force deletion, and -Af
  4075. can be used to remove files from the next revision without
  4076. deleting them from the working directory.
  4077. The following table details the behavior of remove for different
  4078. file states (columns) and option combinations (rows). The file
  4079. states are Added [A], Clean [C], Modified [M] and Missing [!]
  4080. (as reported by :hg:`status`). The actions are Warn, Remove
  4081. (from branch) and Delete (from disk):
  4082. ========= == == == ==
  4083. opt/state A C M !
  4084. ========= == == == ==
  4085. none W RD W R
  4086. -f R RD RD R
  4087. -A W W W R
  4088. -Af R R R R
  4089. ========= == == == ==
  4090. Note that remove never deletes files in Added [A] state from the
  4091. working directory, not even if option --force is specified.
  4092. Returns 0 on success, 1 if any warnings encountered.
  4093. """
  4094. ret = 0
  4095. after, force = opts.get('after'), opts.get('force')
  4096. if not pats and not after:
  4097. raise util.Abort(_('no files specified'))
  4098. m = scmutil.match(repo[None], pats, opts)
  4099. s = repo.status(match=m, clean=True)
  4100. modified, added, deleted, clean = s[0], s[1], s[3], s[6]
  4101. # warn about failure to delete explicit files/dirs
  4102. wctx = repo[None]
  4103. for f in m.files():
  4104. if f in repo.dirstate or f in wctx.dirs():
  4105. continue
  4106. if os.path.exists(m.rel(f)):
  4107. if os.path.isdir(m.rel(f)):
  4108. ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
  4109. else:
  4110. ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
  4111. # missing files will generate a warning elsewhere
  4112. ret = 1
  4113. if force:
  4114. list = modified + deleted + clean + added
  4115. elif after:
  4116. list = deleted
  4117. for f in modified + added + clean:
  4118. ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
  4119. ret = 1
  4120. else:
  4121. list = deleted + clean
  4122. for f in modified:
  4123. ui.warn(_('not removing %s: file is modified (use -f'
  4124. ' to force removal)\n') % m.rel(f))
  4125. ret = 1
  4126. for f in added:
  4127. ui.warn(_('not removing %s: file has been marked for add'
  4128. ' (use forget to undo)\n') % m.rel(f))
  4129. ret = 1
  4130. for f in sorted(list):
  4131. if ui.verbose or not m.exact(f):
  4132. ui.status(_('removing %s\n') % m.rel(f))
  4133. wlock = repo.wlock()
  4134. try:
  4135. if not after:
  4136. for f in list:
  4137. if f in added:
  4138. continue # we never unlink added files on remove
  4139. util.unlinkpath(repo.wjoin(f), ignoremissing=True)
  4140. repo[None].forget(list)
  4141. finally:
  4142. wlock.release()
  4143. return ret
  4144. @command('rename|move|mv',
  4145. [('A', 'after', None, _('record a rename that has already occurred')),
  4146. ('f', 'force', None, _('forcibly copy over an existing managed file')),
  4147. ] + walkopts + dryrunopts,
  4148. _('[OPTION]... SOURCE... DEST'))
  4149. def rename(ui, repo, *pats, **opts):
  4150. """rename files; equivalent of copy + remove
  4151. Mark dest as copies of sources; mark sources for deletion. If dest
  4152. is a directory, copies are put in that directory. If dest is a
  4153. file, there can only be one source.
  4154. By default, this command copies the contents of files as they
  4155. exist in the working directory. If invoked with -A/--after, the
  4156. operation is recorded, but no copying is performed.
  4157. This command takes effect at the next commit. To undo a rename
  4158. before that, see :hg:`revert`.
  4159. Returns 0 on success, 1 if errors are encountered.
  4160. """
  4161. wlock = repo.wlock(False)
  4162. try:
  4163. return cmdutil.copy(ui, repo, pats, opts, rename=True)
  4164. finally:
  4165. wlock.release()
  4166. @command('resolve',
  4167. [('a', 'all', None, _('select all unresolved files')),
  4168. ('l', 'list', None, _('list state of files needing merge')),
  4169. ('m', 'mark', None, _('mark files as resolved')),
  4170. ('u', 'unmark', None, _('mark files as unresolved')),
  4171. ('n', 'no-status', None, _('hide status prefix'))]
  4172. + mergetoolopts + walkopts,
  4173. _('[OPTION]... [FILE]...'),
  4174. inferrepo=True)
  4175. def resolve(ui, repo, *pats, **opts):
  4176. """redo merges or set/view the merge status of files
  4177. Merges with unresolved conflicts are often the result of
  4178. non-interactive merging using the ``internal:merge`` configuration
  4179. setting, or a command-line merge tool like ``diff3``. The resolve
  4180. command is used to manage the files involved in a merge, after
  4181. :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
  4182. working directory must have two parents). See :hg:`help
  4183. merge-tools` for information on configuring merge tools.
  4184. The resolve command can be used in the following ways:
  4185. - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
  4186. files, discarding any previous merge attempts. Re-merging is not
  4187. performed for files already marked as resolved. Use ``--all/-a``
  4188. to select all unresolved files. ``--tool`` can be used to specify
  4189. the merge tool used for the given files. It overrides the HGMERGE
  4190. environment variable and your configuration files. Previous file
  4191. contents are saved with a ``.orig`` suffix.
  4192. - :hg:`resolve -m [FILE]`: mark a file as having been resolved
  4193. (e.g. after having manually fixed-up the files). The default is
  4194. to mark all unresolved files.
  4195. - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
  4196. default is to mark all resolved files.
  4197. - :hg:`resolve -l`: list files which had or still have conflicts.
  4198. In the printed list, ``U`` = unresolved and ``R`` = resolved.
  4199. Note that Mercurial will not let you commit files with unresolved
  4200. merge conflicts. You must use :hg:`resolve -m ...` before you can
  4201. commit after a conflicting merge.
  4202. Returns 0 on success, 1 if any files fail a resolve attempt.
  4203. """
  4204. all, mark, unmark, show, nostatus = \
  4205. [opts.get(o) for o in 'all mark unmark list no_status'.split()]
  4206. if (show and (mark or unmark)) or (mark and unmark):
  4207. raise util.Abort(_("too many options specified"))
  4208. if pats and all:
  4209. raise util.Abort(_("can't specify --all and patterns"))
  4210. if not (all or pats or show or mark or unmark):
  4211. raise util.Abort(_('no files or directories specified; '
  4212. 'use --all to remerge all files'))
  4213. wlock = repo.wlock()
  4214. try:
  4215. ms = mergemod.mergestate(repo)
  4216. if not ms.active() and not show:
  4217. raise util.Abort(
  4218. _('resolve command not applicable when not merging'))
  4219. m = scmutil.match(repo[None], pats, opts)
  4220. ret = 0
  4221. didwork = False
  4222. for f in ms:
  4223. if not m(f):
  4224. continue
  4225. didwork = True
  4226. if show:
  4227. if nostatus:
  4228. ui.write("%s\n" % f)
  4229. else:
  4230. ui.write("%s %s\n" % (ms[f].upper(), f),
  4231. label='resolve.' +
  4232. {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
  4233. elif mark:
  4234. ms.mark(f, "r")
  4235. elif unmark:
  4236. ms.mark(f, "u")
  4237. else:
  4238. wctx = repo[None]
  4239. # backup pre-resolve (merge uses .orig for its own purposes)
  4240. a = repo.wjoin(f)
  4241. util.copyfile(a, a + ".resolve")
  4242. try:
  4243. # resolve file
  4244. ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
  4245. 'resolve')
  4246. if ms.resolve(f, wctx):
  4247. ret = 1
  4248. finally:
  4249. ui.setconfig('ui', 'forcemerge', '', 'resolve')
  4250. ms.commit()
  4251. # replace filemerge's .orig file with our resolve file
  4252. util.rename(a + ".resolve", a + ".orig")
  4253. ms.commit()
  4254. if not didwork and pats:
  4255. ui.warn(_("arguments do not match paths that need resolving\n"))
  4256. finally:
  4257. wlock.release()
  4258. # Nudge users into finishing an unfinished operation. We don't print
  4259. # this with the list/show operation because we want list/show to remain
  4260. # machine readable.
  4261. if not list(ms.unresolved()) and not show:
  4262. ui.status(_('no more unresolved files\n'))
  4263. return ret
  4264. @command('revert',
  4265. [('a', 'all', None, _('revert all changes when no arguments given')),
  4266. ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
  4267. ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
  4268. ('C', 'no-backup', None, _('do not save backup copies of files')),
  4269. ] + walkopts + dryrunopts,
  4270. _('[OPTION]... [-r REV] [NAME]...'))
  4271. def revert(ui, repo, *pats, **opts):
  4272. """restore files to their checkout state
  4273. .. note::
  4274. To check out earlier revisions, you should use :hg:`update REV`.
  4275. To cancel an uncommitted merge (and lose your changes),
  4276. use :hg:`update --clean .`.
  4277. With no revision specified, revert the specified files or directories
  4278. to the contents they had in the parent of the working directory.
  4279. This restores the contents of files to an unmodified
  4280. state and unschedules adds, removes, copies, and renames. If the
  4281. working directory has two parents, you must explicitly specify a
  4282. revision.
  4283. Using the -r/--rev or -d/--date options, revert the given files or
  4284. directories to their states as of a specific revision. Because
  4285. revert does not change the working directory parents, this will
  4286. cause these files to appear modified. This can be helpful to "back
  4287. out" some or all of an earlier change. See :hg:`backout` for a
  4288. related method.
  4289. Modified files are saved with a .orig suffix before reverting.
  4290. To disable these backups, use --no-backup.
  4291. See :hg:`help dates` for a list of formats valid for -d/--date.
  4292. Returns 0 on success.
  4293. """
  4294. if opts.get("date"):
  4295. if opts.get("rev"):
  4296. raise util.Abort(_("you can't specify a revision and a date"))
  4297. opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
  4298. parent, p2 = repo.dirstate.parents()
  4299. if not opts.get('rev') and p2 != nullid:
  4300. # revert after merge is a trap for new users (issue2915)
  4301. raise util.Abort(_('uncommitted merge with no revision specified'),
  4302. hint=_('use "hg update" or see "hg help revert"'))
  4303. ctx = scmutil.revsingle(repo, opts.get('rev'))
  4304. if not pats and not opts.get('all'):
  4305. msg = _("no files or directories specified")
  4306. if p2 != nullid:
  4307. hint = _("uncommitted merge, use --all to discard all changes,"
  4308. " or 'hg update -C .' to abort the merge")
  4309. raise util.Abort(msg, hint=hint)
  4310. dirty = util.any(repo.status())
  4311. node = ctx.node()
  4312. if node != parent:
  4313. if dirty:
  4314. hint = _("uncommitted changes, use --all to discard all"
  4315. " changes, or 'hg update %s' to update") % ctx.rev()
  4316. else:
  4317. hint = _("use --all to revert all files,"
  4318. " or 'hg update %s' to update") % ctx.rev()
  4319. elif dirty:
  4320. hint = _("uncommitted changes, use --all to discard all changes")
  4321. else:
  4322. hint = _("use --all to revert all files")
  4323. raise util.Abort(msg, hint=hint)
  4324. return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
  4325. @command('rollback', dryrunopts +
  4326. [('f', 'force', False, _('ignore safety measures'))])
  4327. def rollback(ui, repo, **opts):
  4328. """roll back the last transaction (DANGEROUS) (DEPRECATED)
  4329. Please use :hg:`commit --amend` instead of rollback to correct
  4330. mistakes in the last commit.
  4331. This command should be used with care. There is only one level of
  4332. rollback, and there is no way to undo a rollback. It will also
  4333. restore the dirstate at the time of the last transaction, losing
  4334. any dirstate changes since that time. This command does not alter
  4335. the working directory.
  4336. Transactions are used to encapsulate the effects of all commands
  4337. that create new changesets or propagate existing changesets into a
  4338. repository.
  4339. .. container:: verbose
  4340. For example, the following commands are transactional, and their
  4341. effects can be rolled back:
  4342. - commit
  4343. - import
  4344. - pull
  4345. - push (with this repository as the destination)
  4346. - unbundle
  4347. To avoid permanent data loss, rollback will refuse to rollback a
  4348. commit transaction if it isn't checked out. Use --force to
  4349. override this protection.
  4350. This command is not intended for use on public repositories. Once
  4351. changes are visible for pull by other users, rolling a transaction
  4352. back locally is ineffective (someone else may already have pulled
  4353. the changes). Furthermore, a race is possible with readers of the
  4354. repository; for example an in-progress pull from the repository
  4355. may fail if a rollback is performed.
  4356. Returns 0 on success, 1 if no rollback data is available.
  4357. """
  4358. return repo.rollback(dryrun=opts.get('dry_run'),
  4359. force=opts.get('force'))
  4360. @command('root', [])
  4361. def root(ui, repo):
  4362. """print the root (top) of the current working directory
  4363. Print the root directory of the current repository.
  4364. Returns 0 on success.
  4365. """
  4366. ui.write(repo.root + "\n")
  4367. @command('^serve',
  4368. [('A', 'accesslog', '', _('name of access log file to write to'),
  4369. _('FILE')),
  4370. ('d', 'daemon', None, _('run server in background')),
  4371. ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
  4372. ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
  4373. # use string type, then we can check if something was passed
  4374. ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
  4375. ('a', 'address', '', _('address to listen on (default: all interfaces)'),
  4376. _('ADDR')),
  4377. ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
  4378. _('PREFIX')),
  4379. ('n', 'name', '',
  4380. _('name to show in web pages (default: working directory)'), _('NAME')),
  4381. ('', 'web-conf', '',
  4382. _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
  4383. ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
  4384. _('FILE')),
  4385. ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
  4386. ('', 'stdio', None, _('for remote clients')),
  4387. ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
  4388. ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
  4389. ('', 'style', '', _('template style to use'), _('STYLE')),
  4390. ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
  4391. ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
  4392. _('[OPTION]...'),
  4393. optionalrepo=True)
  4394. def serve(ui, repo, **opts):
  4395. """start stand-alone webserver
  4396. Start a local HTTP repository browser and pull server. You can use
  4397. this for ad-hoc sharing and browsing of repositories. It is
  4398. recommended to use a real web server to serve a repository for
  4399. longer periods of time.
  4400. Please note that the server does not implement access control.
  4401. This means that, by default, anybody can read from the server and
  4402. nobody can write to it by default. Set the ``web.allow_push``
  4403. option to ``*`` to allow everybody to push to the server. You
  4404. should use a real web server if you need to authenticate users.
  4405. By default, the server logs accesses to stdout and errors to
  4406. stderr. Use the -A/--accesslog and -E/--errorlog options to log to
  4407. files.
  4408. To have the server choose a free port number to listen on, specify
  4409. a port number of 0; in this case, the server will print the port
  4410. number it uses.
  4411. Returns 0 on success.
  4412. """
  4413. if opts["stdio"] and opts["cmdserver"]:
  4414. raise util.Abort(_("cannot use --stdio with --cmdserver"))
  4415. if opts["stdio"]:
  4416. if repo is None:
  4417. raise error.RepoError(_("there is no Mercurial repository here"
  4418. " (.hg not found)"))
  4419. s = sshserver.sshserver(ui, repo)
  4420. s.serve_forever()
  4421. if opts["cmdserver"]:
  4422. s = commandserver.server(ui, repo, opts["cmdserver"])
  4423. return s.serve()
  4424. # this way we can check if something was given in the command-line
  4425. if opts.get('port'):
  4426. opts['port'] = util.getport(opts.get('port'))
  4427. baseui = repo and repo.baseui or ui
  4428. optlist = ("name templates style address port prefix ipv6"
  4429. " accesslog errorlog certificate encoding")
  4430. for o in optlist.split():
  4431. val = opts.get(o, '')
  4432. if val in (None, ''): # should check against default options instead
  4433. continue
  4434. baseui.setconfig("web", o, val, 'serve')
  4435. if repo and repo.ui != baseui:
  4436. repo.ui.setconfig("web", o, val, 'serve')
  4437. o = opts.get('web_conf') or opts.get('webdir_conf')
  4438. if not o:
  4439. if not repo:
  4440. raise error.RepoError(_("there is no Mercurial repository"
  4441. " here (.hg not found)"))
  4442. o = repo
  4443. app = hgweb.hgweb(o, baseui=baseui)
  4444. service = httpservice(ui, app, opts)
  4445. cmdutil.service(opts, initfn=service.init, runfn=service.run)
  4446. class httpservice(object):
  4447. def __init__(self, ui, app, opts):
  4448. self.ui = ui
  4449. self.app = app
  4450. self.opts = opts
  4451. def init(self):
  4452. util.setsignalhandler()
  4453. self.httpd = hgweb_server.create_server(self.ui, self.app)
  4454. if self.opts['port'] and not self.ui.verbose:
  4455. return
  4456. if self.httpd.prefix:
  4457. prefix = self.httpd.prefix.strip('/') + '/'
  4458. else:
  4459. prefix = ''
  4460. port = ':%d' % self.httpd.port
  4461. if port == ':80':
  4462. port = ''
  4463. bindaddr = self.httpd.addr
  4464. if bindaddr == '0.0.0.0':
  4465. bindaddr = '*'
  4466. elif ':' in bindaddr: # IPv6
  4467. bindaddr = '[%s]' % bindaddr
  4468. fqaddr = self.httpd.fqaddr
  4469. if ':' in fqaddr:
  4470. fqaddr = '[%s]' % fqaddr
  4471. if self.opts['port']:
  4472. write = self.ui.status
  4473. else:
  4474. write = self.ui.write
  4475. write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
  4476. (fqaddr, port, prefix, bindaddr, self.httpd.port))
  4477. self.ui.flush() # avoid buffering of status message
  4478. def run(self):
  4479. self.httpd.serve_forever()
  4480. @command('^status|st',
  4481. [('A', 'all', None, _('show status of all files')),
  4482. ('m', 'modified', None, _('show only modified files')),
  4483. ('a', 'added', None, _('show only added files')),
  4484. ('r', 'removed', None, _('show only removed files')),
  4485. ('d', 'deleted', None, _('show only deleted (but tracked) files')),
  4486. ('c', 'clean', None, _('show only files without changes')),
  4487. ('u', 'unknown', None, _('show only unknown (not tracked) files')),
  4488. ('i', 'ignored', None, _('show only ignored files')),
  4489. ('n', 'no-status', None, _('hide status prefix')),
  4490. ('C', 'copies', None, _('show source of copied files')),
  4491. ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
  4492. ('', 'rev', [], _('show difference from revision'), _('REV')),
  4493. ('', 'change', '', _('list the changed files of a revision'), _('REV')),
  4494. ] + walkopts + subrepoopts,
  4495. _('[OPTION]... [FILE]...'),
  4496. inferrepo=True)
  4497. def status(ui, repo, *pats, **opts):
  4498. """show changed files in the working directory
  4499. Show status of files in the repository. If names are given, only
  4500. files that match are shown. Files that are clean or ignored or
  4501. the source of a copy/move operation, are not listed unless
  4502. -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
  4503. Unless options described with "show only ..." are given, the
  4504. options -mardu are used.
  4505. Option -q/--quiet hides untracked (unknown and ignored) files
  4506. unless explicitly requested with -u/--unknown or -i/--ignored.
  4507. .. note::
  4508. status may appear to disagree with diff if permissions have
  4509. changed or a merge has occurred. The standard diff format does
  4510. not report permission changes and diff only reports changes
  4511. relative to one merge parent.
  4512. If one revision is given, it is used as the base revision.
  4513. If two revisions are given, the differences between them are
  4514. shown. The --change option can also be used as a shortcut to list
  4515. the changed files of a revision from its first parent.
  4516. The codes used to show the status of files are::
  4517. M = modified
  4518. A = added
  4519. R = removed
  4520. C = clean
  4521. ! = missing (deleted by non-hg command, but still tracked)
  4522. ? = not tracked
  4523. I = ignored
  4524. = origin of the previous file (with --copies)
  4525. .. container:: verbose
  4526. Examples:
  4527. - show changes in the working directory relative to a
  4528. changeset::
  4529. hg status --rev 9353
  4530. - show all changes including copies in an existing changeset::
  4531. hg status --copies --change 9353
  4532. - get a NUL separated list of added files, suitable for xargs::
  4533. hg status -an0
  4534. Returns 0 on success.
  4535. """
  4536. revs = opts.get('rev')
  4537. change = opts.get('change')
  4538. if revs and change:
  4539. msg = _('cannot specify --rev and --change at the same time')
  4540. raise util.Abort(msg)
  4541. elif change:
  4542. node2 = scmutil.revsingle(repo, change, None).node()
  4543. node1 = repo[node2].p1().node()
  4544. else:
  4545. node1, node2 = scmutil.revpair(repo, revs)
  4546. cwd = (pats and repo.getcwd()) or ''
  4547. end = opts.get('print0') and '\0' or '\n'
  4548. copy = {}
  4549. states = 'modified added removed deleted unknown ignored clean'.split()
  4550. show = [k for k in states if opts.get(k)]
  4551. if opts.get('all'):
  4552. show += ui.quiet and (states[:4] + ['clean']) or states
  4553. if not show:
  4554. show = ui.quiet and states[:4] or states[:5]
  4555. stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
  4556. 'ignored' in show, 'clean' in show, 'unknown' in show,
  4557. opts.get('subrepos'))
  4558. changestates = zip(states, 'MAR!?IC', stat)
  4559. if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
  4560. copy = copies.pathcopies(repo[node1], repo[node2])
  4561. fm = ui.formatter('status', opts)
  4562. fmt = '%s' + end
  4563. showchar = not opts.get('no_status')
  4564. for state, char, files in changestates:
  4565. if state in show:
  4566. label = 'status.' + state
  4567. for f in files:
  4568. fm.startitem()
  4569. fm.condwrite(showchar, 'status', '%s ', char, label=label)
  4570. fm.write('path', fmt, repo.pathto(f, cwd), label=label)
  4571. if f in copy:
  4572. fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
  4573. label='status.copied')
  4574. fm.end()
  4575. @command('^summary|sum',
  4576. [('', 'remote', None, _('check for push and pull'))], '[--remote]')
  4577. def summary(ui, repo, **opts):
  4578. """summarize working directory state
  4579. This generates a brief summary of the working directory state,
  4580. including parents, branch, commit status, and available updates.
  4581. With the --remote option, this will check the default paths for
  4582. incoming and outgoing changes. This can be time-consuming.
  4583. Returns 0 on success.
  4584. """
  4585. ctx = repo[None]
  4586. parents = ctx.parents()
  4587. pnode = parents[0].node()
  4588. marks = []
  4589. for p in parents:
  4590. # label with log.changeset (instead of log.parent) since this
  4591. # shows a working directory parent *changeset*:
  4592. # i18n: column positioning for "hg summary"
  4593. ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
  4594. label='log.changeset changeset.%s' % p.phasestr())
  4595. ui.write(' '.join(p.tags()), label='log.tag')
  4596. if p.bookmarks():
  4597. marks.extend(p.bookmarks())
  4598. if p.rev() == -1:
  4599. if not len(repo):
  4600. ui.write(_(' (empty repository)'))
  4601. else:
  4602. ui.write(_(' (no revision checked out)'))
  4603. ui.write('\n')
  4604. if p.description():
  4605. ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
  4606. label='log.summary')
  4607. branch = ctx.branch()
  4608. bheads = repo.branchheads(branch)
  4609. # i18n: column positioning for "hg summary"
  4610. m = _('branch: %s\n') % branch
  4611. if branch != 'default':
  4612. ui.write(m, label='log.branch')
  4613. else:
  4614. ui.status(m, label='log.branch')
  4615. if marks:
  4616. current = repo._bookmarkcurrent
  4617. # i18n: column positioning for "hg summary"
  4618. ui.write(_('bookmarks:'), label='log.bookmark')
  4619. if current is not None:
  4620. if current in marks:
  4621. ui.write(' *' + current, label='bookmarks.current')
  4622. marks.remove(current)
  4623. else:
  4624. ui.write(' [%s]' % current, label='bookmarks.current')
  4625. for m in marks:
  4626. ui.write(' ' + m, label='log.bookmark')
  4627. ui.write('\n', label='log.bookmark')
  4628. st = list(repo.status(unknown=True))[:6]
  4629. c = repo.dirstate.copies()
  4630. copied, renamed = [], []
  4631. for d, s in c.iteritems():
  4632. if s in st[2]:
  4633. st[2].remove(s)
  4634. renamed.append(d)
  4635. else:
  4636. copied.append(d)
  4637. if d in st[1]:
  4638. st[1].remove(d)
  4639. st.insert(3, renamed)
  4640. st.insert(4, copied)
  4641. ms = mergemod.mergestate(repo)
  4642. st.append([f for f in ms if ms[f] == 'u'])
  4643. subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
  4644. st.append(subs)
  4645. labels = [ui.label(_('%d modified'), 'status.modified'),
  4646. ui.label(_('%d added'), 'status.added'),
  4647. ui.label(_('%d removed'), 'status.removed'),
  4648. ui.label(_('%d renamed'), 'status.copied'),
  4649. ui.label(_('%d copied'), 'status.copied'),
  4650. ui.label(_('%d deleted'), 'status.deleted'),
  4651. ui.label(_('%d unknown'), 'status.unknown'),
  4652. ui.label(_('%d ignored'), 'status.ignored'),
  4653. ui.label(_('%d unresolved'), 'resolve.unresolved'),
  4654. ui.label(_('%d subrepos'), 'status.modified')]
  4655. t = []
  4656. for s, l in zip(st, labels):
  4657. if s:
  4658. t.append(l % len(s))
  4659. t = ', '.join(t)
  4660. cleanworkdir = False
  4661. if repo.vfs.exists('updatestate'):
  4662. t += _(' (interrupted update)')
  4663. elif len(parents) > 1:
  4664. t += _(' (merge)')
  4665. elif branch != parents[0].branch():
  4666. t += _(' (new branch)')
  4667. elif (parents[0].closesbranch() and
  4668. pnode in repo.branchheads(branch, closed=True)):
  4669. t += _(' (head closed)')
  4670. elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
  4671. t += _(' (clean)')
  4672. cleanworkdir = True
  4673. elif pnode not in bheads:
  4674. t += _(' (new branch head)')
  4675. if cleanworkdir:
  4676. # i18n: column positioning for "hg summary"
  4677. ui.status(_('commit: %s\n') % t.strip())
  4678. else:
  4679. # i18n: column positioning for "hg summary"
  4680. ui.write(_('commit: %s\n') % t.strip())
  4681. # all ancestors of branch heads - all ancestors of parent = new csets
  4682. new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
  4683. bheads))
  4684. if new == 0:
  4685. # i18n: column positioning for "hg summary"
  4686. ui.status(_('update: (current)\n'))
  4687. elif pnode not in bheads:
  4688. # i18n: column positioning for "hg summary"
  4689. ui.write(_('update: %d new changesets (update)\n') % new)
  4690. else:
  4691. # i18n: column positioning for "hg summary"
  4692. ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
  4693. (new, len(bheads)))
  4694. cmdutil.summaryhooks(ui, repo)
  4695. if opts.get('remote'):
  4696. needsincoming, needsoutgoing = True, True
  4697. else:
  4698. needsincoming, needsoutgoing = False, False
  4699. for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
  4700. if i:
  4701. needsincoming = True
  4702. if o:
  4703. needsoutgoing = True
  4704. if not needsincoming and not needsoutgoing:
  4705. return
  4706. def getincoming():
  4707. source, branches = hg.parseurl(ui.expandpath('default'))
  4708. sbranch = branches[0]
  4709. try:
  4710. other = hg.peer(repo, {}, source)
  4711. except error.RepoError:
  4712. if opts.get('remote'):
  4713. raise
  4714. return source, sbranch, None, None, None
  4715. revs, checkout = hg.addbranchrevs(repo, other, branches, None)
  4716. if revs:
  4717. revs = [other.lookup(rev) for rev in revs]
  4718. ui.debug('comparing with %s\n' % util.hidepassword(source))
  4719. repo.ui.pushbuffer()
  4720. commoninc = discovery.findcommonincoming(repo, other, heads=revs)
  4721. repo.ui.popbuffer()
  4722. return source, sbranch, other, commoninc, commoninc[1]
  4723. if needsincoming:
  4724. source, sbranch, sother, commoninc, incoming = getincoming()
  4725. else:
  4726. source = sbranch = sother = commoninc = incoming = None
  4727. def getoutgoing():
  4728. dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
  4729. dbranch = branches[0]
  4730. revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
  4731. if source != dest:
  4732. try:
  4733. dother = hg.peer(repo, {}, dest)
  4734. except error.RepoError:
  4735. if opts.get('remote'):
  4736. raise
  4737. return dest, dbranch, None, None
  4738. ui.debug('comparing with %s\n' % util.hidepassword(dest))
  4739. elif sother is None:
  4740. # there is no explicit destination peer, but source one is invalid
  4741. return dest, dbranch, None, None
  4742. else:
  4743. dother = sother
  4744. if (source != dest or (sbranch is not None and sbranch != dbranch)):
  4745. common = None
  4746. else:
  4747. common = commoninc
  4748. if revs:
  4749. revs = [repo.lookup(rev) for rev in revs]
  4750. repo.ui.pushbuffer()
  4751. outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
  4752. commoninc=common)
  4753. repo.ui.popbuffer()
  4754. return dest, dbranch, dother, outgoing
  4755. if needsoutgoing:
  4756. dest, dbranch, dother, outgoing = getoutgoing()
  4757. else:
  4758. dest = dbranch = dother = outgoing = None
  4759. if opts.get('remote'):
  4760. t = []
  4761. if incoming:
  4762. t.append(_('1 or more incoming'))
  4763. o = outgoing.missing
  4764. if o:
  4765. t.append(_('%d outgoing') % len(o))
  4766. other = dother or sother
  4767. if 'bookmarks' in other.listkeys('namespaces'):
  4768. lmarks = repo.listkeys('bookmarks')
  4769. rmarks = other.listkeys('bookmarks')
  4770. diff = set(rmarks) - set(lmarks)
  4771. if len(diff) > 0:
  4772. t.append(_('%d incoming bookmarks') % len(diff))
  4773. diff = set(lmarks) - set(rmarks)
  4774. if len(diff) > 0:
  4775. t.append(_('%d outgoing bookmarks') % len(diff))
  4776. if t:
  4777. # i18n: column positioning for "hg summary"
  4778. ui.write(_('remote: %s\n') % (', '.join(t)))
  4779. else:
  4780. # i18n: column positioning for "hg summary"
  4781. ui.status(_('remote: (synced)\n'))
  4782. cmdutil.summaryremotehooks(ui, repo, opts,
  4783. ((source, sbranch, sother, commoninc),
  4784. (dest, dbranch, dother, outgoing)))
  4785. @command('tag',
  4786. [('f', 'force', None, _('force tag')),
  4787. ('l', 'local', None, _('make the tag local')),
  4788. ('r', 'rev', '', _('revision to tag'), _('REV')),
  4789. ('', 'remove', None, _('remove a tag')),
  4790. # -l/--local is already there, commitopts cannot be used
  4791. ('e', 'edit', None, _('edit commit message')),
  4792. ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
  4793. ] + commitopts2,
  4794. _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
  4795. def tag(ui, repo, name1, *names, **opts):
  4796. """add one or more tags for the current or given revision
  4797. Name a particular revision using <name>.
  4798. Tags are used to name particular revisions of the repository and are
  4799. very useful to compare different revisions, to go back to significant
  4800. earlier versions or to mark branch points as releases, etc. Changing
  4801. an existing tag is normally disallowed; use -f/--force to override.
  4802. If no revision is given, the parent of the working directory is
  4803. used.
  4804. To facilitate version control, distribution, and merging of tags,
  4805. they are stored as a file named ".hgtags" which is managed similarly
  4806. to other project files and can be hand-edited if necessary. This
  4807. also means that tagging creates a new commit. The file
  4808. ".hg/localtags" is used for local tags (not shared among
  4809. repositories).
  4810. Tag commits are usually made at the head of a branch. If the parent
  4811. of the working directory is not a branch head, :hg:`tag` aborts; use
  4812. -f/--force to force the tag commit to be based on a non-head
  4813. changeset.
  4814. See :hg:`help dates` for a list of formats valid for -d/--date.
  4815. Since tag names have priority over branch names during revision
  4816. lookup, using an existing branch name as a tag name is discouraged.
  4817. Returns 0 on success.
  4818. """
  4819. wlock = lock = None
  4820. try:
  4821. wlock = repo.wlock()
  4822. lock = repo.lock()
  4823. rev_ = "."
  4824. names = [t.strip() for t in (name1,) + names]
  4825. if len(names) != len(set(names)):
  4826. raise util.Abort(_('tag names must be unique'))
  4827. for n in names:
  4828. scmutil.checknewlabel(repo, n, 'tag')
  4829. if not n:
  4830. raise util.Abort(_('tag names cannot consist entirely of '
  4831. 'whitespace'))
  4832. if opts.get('rev') and opts.get('remove'):
  4833. raise util.Abort(_("--rev and --remove are incompatible"))
  4834. if opts.get('rev'):
  4835. rev_ = opts['rev']
  4836. message = opts.get('message')
  4837. if opts.get('remove'):
  4838. expectedtype = opts.get('local') and 'local' or 'global'
  4839. for n in names:
  4840. if not repo.tagtype(n):
  4841. raise util.Abort(_("tag '%s' does not exist") % n)
  4842. if repo.tagtype(n) != expectedtype:
  4843. if expectedtype == 'global':
  4844. raise util.Abort(_("tag '%s' is not a global tag") % n)
  4845. else:
  4846. raise util.Abort(_("tag '%s' is not a local tag") % n)
  4847. rev_ = nullid
  4848. if not message:
  4849. # we don't translate commit messages
  4850. message = 'Removed tag %s' % ', '.join(names)
  4851. elif not opts.get('force'):
  4852. for n in names:
  4853. if n in repo.tags():
  4854. raise util.Abort(_("tag '%s' already exists "
  4855. "(use -f to force)") % n)
  4856. if not opts.get('local'):
  4857. p1, p2 = repo.dirstate.parents()
  4858. if p2 != nullid:
  4859. raise util.Abort(_('uncommitted merge'))
  4860. bheads = repo.branchheads()
  4861. if not opts.get('force') and bheads and p1 not in bheads:
  4862. raise util.Abort(_('not at a branch head (use -f to force)'))
  4863. r = scmutil.revsingle(repo, rev_).node()
  4864. if not message:
  4865. # we don't translate commit messages
  4866. message = ('Added tag %s for changeset %s' %
  4867. (', '.join(names), short(r)))
  4868. date = opts.get('date')
  4869. if date:
  4870. date = util.parsedate(date)
  4871. editor = cmdutil.getcommiteditor(**opts)
  4872. # don't allow tagging the null rev
  4873. if (not opts.get('remove') and
  4874. scmutil.revsingle(repo, rev_).rev() == nullrev):
  4875. raise util.Abort(_("cannot tag null revision"))
  4876. repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
  4877. editor=editor)
  4878. finally:
  4879. release(lock, wlock)
  4880. @command('tags', [], '')
  4881. def tags(ui, repo, **opts):
  4882. """list repository tags
  4883. This lists both regular and local tags. When the -v/--verbose
  4884. switch is used, a third column "local" is printed for local tags.
  4885. Returns 0 on success.
  4886. """
  4887. fm = ui.formatter('tags', opts)
  4888. hexfunc = ui.debugflag and hex or short
  4889. tagtype = ""
  4890. for t, n in reversed(repo.tagslist()):
  4891. hn = hexfunc(n)
  4892. label = 'tags.normal'
  4893. tagtype = ''
  4894. if repo.tagtype(t) == 'local':
  4895. label = 'tags.local'
  4896. tagtype = 'local'
  4897. fm.startitem()
  4898. fm.write('tag', '%s', t, label=label)
  4899. fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
  4900. fm.condwrite(not ui.quiet, 'rev id', fmt,
  4901. repo.changelog.rev(n), hn, label=label)
  4902. fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
  4903. tagtype, label=label)
  4904. fm.plain('\n')
  4905. fm.end()
  4906. @command('tip',
  4907. [('p', 'patch', None, _('show patch')),
  4908. ('g', 'git', None, _('use git extended diff format')),
  4909. ] + templateopts,
  4910. _('[-p] [-g]'))
  4911. def tip(ui, repo, **opts):
  4912. """show the tip revision (DEPRECATED)
  4913. The tip revision (usually just called the tip) is the changeset
  4914. most recently added to the repository (and therefore the most
  4915. recently changed head).
  4916. If you have just made a commit, that commit will be the tip. If
  4917. you have just pulled changes from another repository, the tip of
  4918. that repository becomes the current tip. The "tip" tag is special
  4919. and cannot be renamed or assigned to a different changeset.
  4920. This command is deprecated, please use :hg:`heads` instead.
  4921. Returns 0 on success.
  4922. """
  4923. displayer = cmdutil.show_changeset(ui, repo, opts)
  4924. displayer.show(repo['tip'])
  4925. displayer.close()
  4926. @command('unbundle',
  4927. [('u', 'update', None,
  4928. _('update to new branch head if changesets were unbundled'))],
  4929. _('[-u] FILE...'))
  4930. def unbundle(ui, repo, fname1, *fnames, **opts):
  4931. """apply one or more changegroup files
  4932. Apply one or more compressed changegroup files generated by the
  4933. bundle command.
  4934. Returns 0 on success, 1 if an update has unresolved files.
  4935. """
  4936. fnames = (fname1,) + fnames
  4937. lock = repo.lock()
  4938. wc = repo['.']
  4939. try:
  4940. for fname in fnames:
  4941. f = hg.openpath(ui, fname)
  4942. gen = exchange.readbundle(ui, f, fname)
  4943. modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
  4944. 'bundle:' + fname)
  4945. finally:
  4946. lock.release()
  4947. bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
  4948. return postincoming(ui, repo, modheads, opts.get('update'), None)
  4949. @command('^update|up|checkout|co',
  4950. [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
  4951. ('c', 'check', None,
  4952. _('update across branches if no uncommitted changes')),
  4953. ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
  4954. ('r', 'rev', '', _('revision'), _('REV'))
  4955. ] + mergetoolopts,
  4956. _('[-c] [-C] [-d DATE] [[-r] REV]'))
  4957. def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
  4958. tool=None):
  4959. """update working directory (or switch revisions)
  4960. Update the repository's working directory to the specified
  4961. changeset. If no changeset is specified, update to the tip of the
  4962. current named branch and move the current bookmark (see :hg:`help
  4963. bookmarks`).
  4964. Update sets the working directory's parent revision to the specified
  4965. changeset (see :hg:`help parents`).
  4966. If the changeset is not a descendant or ancestor of the working
  4967. directory's parent, the update is aborted. With the -c/--check
  4968. option, the working directory is checked for uncommitted changes; if
  4969. none are found, the working directory is updated to the specified
  4970. changeset.
  4971. .. container:: verbose
  4972. The following rules apply when the working directory contains
  4973. uncommitted changes:
  4974. 1. If neither -c/--check nor -C/--clean is specified, and if
  4975. the requested changeset is an ancestor or descendant of
  4976. the working directory's parent, the uncommitted changes
  4977. are merged into the requested changeset and the merged
  4978. result is left uncommitted. If the requested changeset is
  4979. not an ancestor or descendant (that is, it is on another
  4980. branch), the update is aborted and the uncommitted changes
  4981. are preserved.
  4982. 2. With the -c/--check option, the update is aborted and the
  4983. uncommitted changes are preserved.
  4984. 3. With the -C/--clean option, uncommitted changes are discarded and
  4985. the working directory is updated to the requested changeset.
  4986. To cancel an uncommitted merge (and lose your changes), use
  4987. :hg:`update --clean .`.
  4988. Use null as the changeset to remove the working directory (like
  4989. :hg:`clone -U`).
  4990. If you want to revert just one file to an older revision, use
  4991. :hg:`revert [-r REV] NAME`.
  4992. See :hg:`help dates` for a list of formats valid for -d/--date.
  4993. Returns 0 on success, 1 if there are unresolved files.
  4994. """
  4995. if rev and node:
  4996. raise util.Abort(_("please specify just one revision"))
  4997. if rev is None or rev == '':
  4998. rev = node
  4999. cmdutil.clearunfinished(repo)
  5000. # with no argument, we also move the current bookmark, if any
  5001. rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
  5002. # if we defined a bookmark, we have to remember the original bookmark name
  5003. brev = rev
  5004. rev = scmutil.revsingle(repo, rev, rev).rev()
  5005. if check and clean:
  5006. raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
  5007. if date:
  5008. if rev is not None:
  5009. raise util.Abort(_("you can't specify a revision and a date"))
  5010. rev = cmdutil.finddate(ui, repo, date)
  5011. if check:
  5012. c = repo[None]
  5013. if c.dirty(merge=False, branch=False, missing=True):
  5014. raise util.Abort(_("uncommitted changes"))
  5015. if rev is None:
  5016. rev = repo[repo[None].branch()].rev()
  5017. mergemod._checkunknown(repo, repo[None], repo[rev])
  5018. repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
  5019. if clean:
  5020. ret = hg.clean(repo, rev)
  5021. else:
  5022. ret = hg.update(repo, rev)
  5023. if not ret and movemarkfrom:
  5024. if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
  5025. ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
  5026. elif brev in repo._bookmarks:
  5027. bookmarks.setcurrent(repo, brev)
  5028. ui.status(_("(activating bookmark %s)\n") % brev)
  5029. elif brev:
  5030. if repo._bookmarkcurrent:
  5031. ui.status(_("(leaving bookmark %s)\n") %
  5032. repo._bookmarkcurrent)
  5033. bookmarks.unsetcurrent(repo)
  5034. return ret
  5035. @command('verify', [])
  5036. def verify(ui, repo):
  5037. """verify the integrity of the repository
  5038. Verify the integrity of the current repository.
  5039. This will perform an extensive check of the repository's
  5040. integrity, validating the hashes and checksums of each entry in
  5041. the changelog, manifest, and tracked files, as well as the
  5042. integrity of their crosslinks and indices.
  5043. Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
  5044. for more information about recovery from corruption of the
  5045. repository.
  5046. Returns 0 on success, 1 if errors are encountered.
  5047. """
  5048. return hg.verify(repo)
  5049. @command('version', [], norepo=True)
  5050. def version_(ui):
  5051. """output version and copyright information"""
  5052. ui.write(_("Mercurial Distributed SCM (version %s)\n")
  5053. % util.version())
  5054. ui.status(_(
  5055. "(see http://mercurial.selenic.com for more information)\n"
  5056. "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
  5057. "This is free software; see the source for copying conditions. "
  5058. "There is NO\nwarranty; "
  5059. "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
  5060. ))
  5061. ui.note(_("\nEnabled extensions:\n\n"))
  5062. if ui.verbose:
  5063. # format names and versions into columns
  5064. names = []
  5065. vers = []
  5066. for name, module in extensions.extensions():
  5067. names.append(name)
  5068. vers.append(extensions.moduleversion(module))
  5069. maxnamelen = max(len(n) for n in names)
  5070. for i, name in enumerate(names):
  5071. ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))