##// END OF EJS Templates
bookmarks: merge current tracking on update into core
Matt Mackall -
r13367:cef73cd9 default
parent child Browse files
Show More
@@ -1,232 +1,216 b''
1 # Mercurial extension to provide the 'hg bookmark' command
1 # Mercurial extension to provide the 'hg bookmark' command
2 #
2 #
3 # Copyright 2008 David Soria Parra <dsp@php.net>
3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
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.
6 # GNU General Public License version 2 or any later version.
7
7
8 '''track a line of development with movable markers
8 '''track a line of development with movable markers
9
9
10 Bookmarks are local movable markers to changesets. Every bookmark
10 Bookmarks are local movable markers to changesets. Every bookmark
11 points to a changeset identified by its hash. If you commit a
11 points to a changeset identified by its hash. If you commit a
12 changeset that is based on a changeset that has a bookmark on it, the
12 changeset that is based on a changeset that has a bookmark on it, the
13 bookmark shifts to the new changeset.
13 bookmark shifts to the new changeset.
14
14
15 It is possible to use bookmark names in every revision lookup (e.g.
15 It is possible to use bookmark names in every revision lookup (e.g.
16 :hg:`merge`, :hg:`update`).
16 :hg:`merge`, :hg:`update`).
17
17
18 By default, when several bookmarks point to the same changeset, they
18 By default, when several bookmarks point to the same changeset, they
19 will all move forward together. It is possible to obtain a more
19 will all move forward together. It is possible to obtain a more
20 git-like experience by adding the following configuration option to
20 git-like experience by adding the following configuration option to
21 your configuration file::
21 your configuration file::
22
22
23 [bookmarks]
23 [bookmarks]
24 track.current = True
24 track.current = True
25
25
26 This will cause Mercurial to track the bookmark that you are currently
26 This will cause Mercurial to track the bookmark that you are currently
27 using, and only update it. This is similar to git's approach to
27 using, and only update it. This is similar to git's approach to
28 branching.
28 branching.
29 '''
29 '''
30
30
31 from mercurial.i18n import _
31 from mercurial.i18n import _
32 from mercurial.node import nullid, nullrev, bin, hex, short
32 from mercurial.node import nullid, nullrev, bin, hex, short
33 from mercurial import util, commands, repair, extensions, pushkey, hg, url
33 from mercurial import util, commands, repair, extensions, pushkey, hg, url
34 from mercurial import encoding
34 from mercurial import encoding
35 from mercurial import bookmarks
35 from mercurial import bookmarks
36 import os
36 import os
37
37
38 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None):
38 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None):
39 '''track a line of development with movable markers
39 '''track a line of development with movable markers
40
40
41 Bookmarks are pointers to certain commits that move when
41 Bookmarks are pointers to certain commits that move when
42 committing. Bookmarks are local. They can be renamed, copied and
42 committing. Bookmarks are local. They can be renamed, copied and
43 deleted. It is possible to use bookmark names in :hg:`merge` and
43 deleted. It is possible to use bookmark names in :hg:`merge` and
44 :hg:`update` to merge and update respectively to a given bookmark.
44 :hg:`update` to merge and update respectively to a given bookmark.
45
45
46 You can use :hg:`bookmark NAME` to set a bookmark on the working
46 You can use :hg:`bookmark NAME` to set a bookmark on the working
47 directory's parent revision with the given name. If you specify
47 directory's parent revision with the given name. If you specify
48 a revision using -r REV (where REV may be an existing bookmark),
48 a revision using -r REV (where REV may be an existing bookmark),
49 the bookmark is assigned to that revision.
49 the bookmark is assigned to that revision.
50
50
51 Bookmarks can be pushed and pulled between repositories (see :hg:`help
51 Bookmarks can be pushed and pulled between repositories (see :hg:`help
52 push` and :hg:`help pull`). This requires the bookmark extension to be
52 push` and :hg:`help pull`). This requires the bookmark extension to be
53 enabled for both the local and remote repositories.
53 enabled for both the local and remote repositories.
54 '''
54 '''
55 hexfn = ui.debugflag and hex or short
55 hexfn = ui.debugflag and hex or short
56 marks = repo._bookmarks
56 marks = repo._bookmarks
57 cur = repo.changectx('.').node()
57 cur = repo.changectx('.').node()
58
58
59 if rename:
59 if rename:
60 if rename not in marks:
60 if rename not in marks:
61 raise util.Abort(_("a bookmark of this name does not exist"))
61 raise util.Abort(_("a bookmark of this name does not exist"))
62 if mark in marks and not force:
62 if mark in marks and not force:
63 raise util.Abort(_("a bookmark of the same name already exists"))
63 raise util.Abort(_("a bookmark of the same name already exists"))
64 if mark is None:
64 if mark is None:
65 raise util.Abort(_("new bookmark name required"))
65 raise util.Abort(_("new bookmark name required"))
66 marks[mark] = marks[rename]
66 marks[mark] = marks[rename]
67 del marks[rename]
67 del marks[rename]
68 if repo._bookmarkcurrent == rename:
68 if repo._bookmarkcurrent == rename:
69 bookmarks.setcurrent(repo, mark)
69 bookmarks.setcurrent(repo, mark)
70 bookmarks.write(repo)
70 bookmarks.write(repo)
71 return
71 return
72
72
73 if delete:
73 if delete:
74 if mark is None:
74 if mark is None:
75 raise util.Abort(_("bookmark name required"))
75 raise util.Abort(_("bookmark name required"))
76 if mark not in marks:
76 if mark not in marks:
77 raise util.Abort(_("a bookmark of this name does not exist"))
77 raise util.Abort(_("a bookmark of this name does not exist"))
78 if mark == repo._bookmarkcurrent:
78 if mark == repo._bookmarkcurrent:
79 bookmarks.setcurrent(repo, None)
79 bookmarks.setcurrent(repo, None)
80 del marks[mark]
80 del marks[mark]
81 bookmarks.write(repo)
81 bookmarks.write(repo)
82 return
82 return
83
83
84 if mark is not None:
84 if mark is not None:
85 if "\n" in mark:
85 if "\n" in mark:
86 raise util.Abort(_("bookmark name cannot contain newlines"))
86 raise util.Abort(_("bookmark name cannot contain newlines"))
87 mark = mark.strip()
87 mark = mark.strip()
88 if not mark:
88 if not mark:
89 raise util.Abort(_("bookmark names cannot consist entirely of "
89 raise util.Abort(_("bookmark names cannot consist entirely of "
90 "whitespace"))
90 "whitespace"))
91 if mark in marks and not force:
91 if mark in marks and not force:
92 raise util.Abort(_("a bookmark of the same name already exists"))
92 raise util.Abort(_("a bookmark of the same name already exists"))
93 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
93 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
94 and not force):
94 and not force):
95 raise util.Abort(
95 raise util.Abort(
96 _("a bookmark cannot have the name of an existing branch"))
96 _("a bookmark cannot have the name of an existing branch"))
97 if rev:
97 if rev:
98 marks[mark] = repo.lookup(rev)
98 marks[mark] = repo.lookup(rev)
99 else:
99 else:
100 marks[mark] = repo.changectx('.').node()
100 marks[mark] = repo.changectx('.').node()
101 bookmarks.setcurrent(repo, mark)
101 bookmarks.setcurrent(repo, mark)
102 bookmarks.write(repo)
102 bookmarks.write(repo)
103 return
103 return
104
104
105 if mark is None:
105 if mark is None:
106 if rev:
106 if rev:
107 raise util.Abort(_("bookmark name required"))
107 raise util.Abort(_("bookmark name required"))
108 if len(marks) == 0:
108 if len(marks) == 0:
109 ui.status(_("no bookmarks set\n"))
109 ui.status(_("no bookmarks set\n"))
110 else:
110 else:
111 for bmark, n in marks.iteritems():
111 for bmark, n in marks.iteritems():
112 if ui.configbool('bookmarks', 'track.current'):
112 if ui.configbool('bookmarks', 'track.current'):
113 current = repo._bookmarkcurrent
113 current = repo._bookmarkcurrent
114 if bmark == current and n == cur:
114 if bmark == current and n == cur:
115 prefix, label = '*', 'bookmarks.current'
115 prefix, label = '*', 'bookmarks.current'
116 else:
116 else:
117 prefix, label = ' ', ''
117 prefix, label = ' ', ''
118 else:
118 else:
119 if n == cur:
119 if n == cur:
120 prefix, label = '*', 'bookmarks.current'
120 prefix, label = '*', 'bookmarks.current'
121 else:
121 else:
122 prefix, label = ' ', ''
122 prefix, label = ' ', ''
123
123
124 if ui.quiet:
124 if ui.quiet:
125 ui.write("%s\n" % bmark, label=label)
125 ui.write("%s\n" % bmark, label=label)
126 else:
126 else:
127 ui.write(" %s %-25s %d:%s\n" % (
127 ui.write(" %s %-25s %d:%s\n" % (
128 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
128 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
129 label=label)
129 label=label)
130 return
130 return
131
131
132 def pull(oldpull, ui, repo, source="default", **opts):
132 def pull(oldpull, ui, repo, source="default", **opts):
133 # translate bookmark args to rev args for actual pull
133 # translate bookmark args to rev args for actual pull
134 if opts.get('bookmark'):
134 if opts.get('bookmark'):
135 # this is an unpleasant hack as pull will do this internally
135 # this is an unpleasant hack as pull will do this internally
136 source, branches = hg.parseurl(ui.expandpath(source),
136 source, branches = hg.parseurl(ui.expandpath(source),
137 opts.get('branch'))
137 opts.get('branch'))
138 other = hg.repository(hg.remoteui(repo, opts), source)
138 other = hg.repository(hg.remoteui(repo, opts), source)
139 rb = other.listkeys('bookmarks')
139 rb = other.listkeys('bookmarks')
140
140
141 for b in opts['bookmark']:
141 for b in opts['bookmark']:
142 if b not in rb:
142 if b not in rb:
143 raise util.Abort(_('remote bookmark %s not found!') % b)
143 raise util.Abort(_('remote bookmark %s not found!') % b)
144 opts.setdefault('rev', []).append(b)
144 opts.setdefault('rev', []).append(b)
145
145
146 result = oldpull(ui, repo, source, **opts)
146 result = oldpull(ui, repo, source, **opts)
147
147
148 # update specified bookmarks
148 # update specified bookmarks
149 if opts.get('bookmark'):
149 if opts.get('bookmark'):
150 for b in opts['bookmark']:
150 for b in opts['bookmark']:
151 # explicit pull overrides local bookmark if any
151 # explicit pull overrides local bookmark if any
152 ui.status(_("importing bookmark %s\n") % b)
152 ui.status(_("importing bookmark %s\n") % b)
153 repo._bookmarks[b] = repo[rb[b]].node()
153 repo._bookmarks[b] = repo[rb[b]].node()
154 bookmarks.write(repo)
154 bookmarks.write(repo)
155
155
156 return result
156 return result
157
157
158 def push(oldpush, ui, repo, dest=None, **opts):
158 def push(oldpush, ui, repo, dest=None, **opts):
159 dopush = True
159 dopush = True
160 if opts.get('bookmark'):
160 if opts.get('bookmark'):
161 dopush = False
161 dopush = False
162 for b in opts['bookmark']:
162 for b in opts['bookmark']:
163 if b in repo._bookmarks:
163 if b in repo._bookmarks:
164 dopush = True
164 dopush = True
165 opts.setdefault('rev', []).append(b)
165 opts.setdefault('rev', []).append(b)
166
166
167 result = 0
167 result = 0
168 if dopush:
168 if dopush:
169 result = oldpush(ui, repo, dest, **opts)
169 result = oldpush(ui, repo, dest, **opts)
170
170
171 if opts.get('bookmark'):
171 if opts.get('bookmark'):
172 # this is an unpleasant hack as push will do this internally
172 # this is an unpleasant hack as push will do this internally
173 dest = ui.expandpath(dest or 'default-push', dest or 'default')
173 dest = ui.expandpath(dest or 'default-push', dest or 'default')
174 dest, branches = hg.parseurl(dest, opts.get('branch'))
174 dest, branches = hg.parseurl(dest, opts.get('branch'))
175 other = hg.repository(hg.remoteui(repo, opts), dest)
175 other = hg.repository(hg.remoteui(repo, opts), dest)
176 rb = other.listkeys('bookmarks')
176 rb = other.listkeys('bookmarks')
177 for b in opts['bookmark']:
177 for b in opts['bookmark']:
178 # explicit push overrides remote bookmark if any
178 # explicit push overrides remote bookmark if any
179 if b in repo._bookmarks:
179 if b in repo._bookmarks:
180 ui.status(_("exporting bookmark %s\n") % b)
180 ui.status(_("exporting bookmark %s\n") % b)
181 new = repo[b].hex()
181 new = repo[b].hex()
182 elif b in rb:
182 elif b in rb:
183 ui.status(_("deleting remote bookmark %s\n") % b)
183 ui.status(_("deleting remote bookmark %s\n") % b)
184 new = '' # delete
184 new = '' # delete
185 else:
185 else:
186 ui.warn(_('bookmark %s does not exist on the local '
186 ui.warn(_('bookmark %s does not exist on the local '
187 'or remote repository!\n') % b)
187 'or remote repository!\n') % b)
188 return 2
188 return 2
189 old = rb.get(b, '')
189 old = rb.get(b, '')
190 r = other.pushkey('bookmarks', b, old, new)
190 r = other.pushkey('bookmarks', b, old, new)
191 if not r:
191 if not r:
192 ui.warn(_('updating bookmark %s failed!\n') % b)
192 ui.warn(_('updating bookmark %s failed!\n') % b)
193 if not result:
193 if not result:
194 result = 2
194 result = 2
195
195
196 return result
196 return result
197
197
198 def uisetup(ui):
198 def uisetup(ui):
199 if ui.configbool('bookmarks', 'track.current'):
200 extensions.wrapcommand(commands.table, 'update', updatecurbookmark)
201
202 entry = extensions.wrapcommand(commands.table, 'pull', pull)
199 entry = extensions.wrapcommand(commands.table, 'pull', pull)
203 entry[1].append(('B', 'bookmark', [],
200 entry[1].append(('B', 'bookmark', [],
204 _("bookmark to import"),
201 _("bookmark to import"),
205 _('BOOKMARK')))
202 _('BOOKMARK')))
206 entry = extensions.wrapcommand(commands.table, 'push', push)
203 entry = extensions.wrapcommand(commands.table, 'push', push)
207 entry[1].append(('B', 'bookmark', [],
204 entry[1].append(('B', 'bookmark', [],
208 _("bookmark to export"),
205 _("bookmark to export"),
209 _('BOOKMARK')))
206 _('BOOKMARK')))
210
207
211 def updatecurbookmark(orig, ui, repo, *args, **opts):
212 '''Set the current bookmark
213
214 If the user updates to a bookmark we update the .hg/bookmarks.current
215 file.
216 '''
217 res = orig(ui, repo, *args, **opts)
218 rev = opts['rev']
219 if not rev and len(args) > 0:
220 rev = args[0]
221 bookmarks.setcurrent(repo, rev)
222 return res
223
224 cmdtable = {
208 cmdtable = {
225 "bookmarks":
209 "bookmarks":
226 (bookmark,
210 (bookmark,
227 [('f', 'force', False, _('force')),
211 [('f', 'force', False, _('force')),
228 ('r', 'rev', '', _('revision'), _('REV')),
212 ('r', 'rev', '', _('revision'), _('REV')),
229 ('d', 'delete', False, _('delete a given bookmark')),
213 ('d', 'delete', False, _('delete a given bookmark')),
230 ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))],
214 ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))],
231 _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
215 _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
232 }
216 }
@@ -1,4550 +1,4555 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
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.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
12 import hg, util, revlog, extensions, copies, error, bookmarks
12 import hg, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, mdiff, url, encoding, templatekw, discovery
13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset
16 import minirst, revset
17 import dagparser
17 import dagparser
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see :hg:`forget`.
28 undo an add before that, see :hg:`forget`.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31
31
32 .. container:: verbose
32 .. container:: verbose
33
33
34 An example showing how new (unknown) files are added
34 An example showing how new (unknown) files are added
35 automatically by :hg:`add`::
35 automatically by :hg:`add`::
36
36
37 $ ls
37 $ ls
38 foo.c
38 foo.c
39 $ hg status
39 $ hg status
40 ? foo.c
40 ? foo.c
41 $ hg add
41 $ hg add
42 adding foo.c
42 adding foo.c
43 $ hg status
43 $ hg status
44 A foo.c
44 A foo.c
45
45
46 Returns 0 if all files are successfully added.
46 Returns 0 if all files are successfully added.
47 """
47 """
48
48
49 m = cmdutil.match(repo, pats, opts)
49 m = cmdutil.match(repo, pats, opts)
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
51 opts.get('subrepos'), prefix="")
51 opts.get('subrepos'), prefix="")
52 return rejected and 1 or 0
52 return rejected and 1 or 0
53
53
54 def addremove(ui, repo, *pats, **opts):
54 def addremove(ui, repo, *pats, **opts):
55 """add all new files, delete all missing files
55 """add all new files, delete all missing files
56
56
57 Add all new files and remove all missing files from the
57 Add all new files and remove all missing files from the
58 repository.
58 repository.
59
59
60 New files are ignored if they match any of the patterns in
60 New files are ignored if they match any of the patterns in
61 ``.hgignore``. As with add, these changes take effect at the next
61 ``.hgignore``. As with add, these changes take effect at the next
62 commit.
62 commit.
63
63
64 Use the -s/--similarity option to detect renamed files. With a
64 Use the -s/--similarity option to detect renamed files. With a
65 parameter greater than 0, this compares every removed file with
65 parameter greater than 0, this compares every removed file with
66 every added file and records those similar enough as renames. This
66 every added file and records those similar enough as renames. This
67 option takes a percentage between 0 (disabled) and 100 (files must
67 option takes a percentage between 0 (disabled) and 100 (files must
68 be identical) as its parameter. Detecting renamed files this way
68 be identical) as its parameter. Detecting renamed files this way
69 can be expensive. After using this option, :hg:`status -C` can be
69 can be expensive. After using this option, :hg:`status -C` can be
70 used to check which files were identified as moved or renamed.
70 used to check which files were identified as moved or renamed.
71
71
72 Returns 0 if all files are successfully added.
72 Returns 0 if all files are successfully added.
73 """
73 """
74 try:
74 try:
75 sim = float(opts.get('similarity') or 100)
75 sim = float(opts.get('similarity') or 100)
76 except ValueError:
76 except ValueError:
77 raise util.Abort(_('similarity must be a number'))
77 raise util.Abort(_('similarity must be a number'))
78 if sim < 0 or sim > 100:
78 if sim < 0 or sim > 100:
79 raise util.Abort(_('similarity must be between 0 and 100'))
79 raise util.Abort(_('similarity must be between 0 and 100'))
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
81
81
82 def annotate(ui, repo, *pats, **opts):
82 def annotate(ui, repo, *pats, **opts):
83 """show changeset information by line for each file
83 """show changeset information by line for each file
84
84
85 List changes in files, showing the revision id responsible for
85 List changes in files, showing the revision id responsible for
86 each line
86 each line
87
87
88 This command is useful for discovering when a change was made and
88 This command is useful for discovering when a change was made and
89 by whom.
89 by whom.
90
90
91 Without the -a/--text option, annotate will avoid processing files
91 Without the -a/--text option, annotate will avoid processing files
92 it detects as binary. With -a, annotate will annotate the file
92 it detects as binary. With -a, annotate will annotate the file
93 anyway, although the results will probably be neither useful
93 anyway, although the results will probably be neither useful
94 nor desirable.
94 nor desirable.
95
95
96 Returns 0 on success.
96 Returns 0 on success.
97 """
97 """
98 if opts.get('follow'):
98 if opts.get('follow'):
99 # --follow is deprecated and now just an alias for -f/--file
99 # --follow is deprecated and now just an alias for -f/--file
100 # to mimic the behavior of Mercurial before version 1.5
100 # to mimic the behavior of Mercurial before version 1.5
101 opts['file'] = 1
101 opts['file'] = 1
102
102
103 datefunc = ui.quiet and util.shortdate or util.datestr
103 datefunc = ui.quiet and util.shortdate or util.datestr
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
105
105
106 if not pats:
106 if not pats:
107 raise util.Abort(_('at least one filename or pattern is required'))
107 raise util.Abort(_('at least one filename or pattern is required'))
108
108
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
110 ('number', lambda x: str(x[0].rev())),
110 ('number', lambda x: str(x[0].rev())),
111 ('changeset', lambda x: short(x[0].node())),
111 ('changeset', lambda x: short(x[0].node())),
112 ('date', getdate),
112 ('date', getdate),
113 ('file', lambda x: x[0].path()),
113 ('file', lambda x: x[0].path()),
114 ]
114 ]
115
115
116 if (not opts.get('user') and not opts.get('changeset')
116 if (not opts.get('user') and not opts.get('changeset')
117 and not opts.get('date') and not opts.get('file')):
117 and not opts.get('date') and not opts.get('file')):
118 opts['number'] = 1
118 opts['number'] = 1
119
119
120 linenumber = opts.get('line_number') is not None
120 linenumber = opts.get('line_number') is not None
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
123
123
124 funcmap = [func for op, func in opmap if opts.get(op)]
124 funcmap = [func for op, func in opmap if opts.get(op)]
125 if linenumber:
125 if linenumber:
126 lastfunc = funcmap[-1]
126 lastfunc = funcmap[-1]
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
128
128
129 ctx = cmdutil.revsingle(repo, opts.get('rev'))
129 ctx = cmdutil.revsingle(repo, opts.get('rev'))
130 m = cmdutil.match(repo, pats, opts)
130 m = cmdutil.match(repo, pats, opts)
131 follow = not opts.get('no_follow')
131 follow = not opts.get('no_follow')
132 for abs in ctx.walk(m):
132 for abs in ctx.walk(m):
133 fctx = ctx[abs]
133 fctx = ctx[abs]
134 if not opts.get('text') and util.binary(fctx.data()):
134 if not opts.get('text') and util.binary(fctx.data()):
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
136 continue
136 continue
137
137
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
139 pieces = []
139 pieces = []
140
140
141 for f in funcmap:
141 for f in funcmap:
142 l = [f(n) for n, dummy in lines]
142 l = [f(n) for n, dummy in lines]
143 if l:
143 if l:
144 sized = [(x, encoding.colwidth(x)) for x in l]
144 sized = [(x, encoding.colwidth(x)) for x in l]
145 ml = max([w for x, w in sized])
145 ml = max([w for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
147
147
148 if pieces:
148 if pieces:
149 for p, l in zip(zip(*pieces), lines):
149 for p, l in zip(zip(*pieces), lines):
150 ui.write("%s: %s" % (" ".join(p), l[1]))
150 ui.write("%s: %s" % (" ".join(p), l[1]))
151
151
152 def archive(ui, repo, dest, **opts):
152 def archive(ui, repo, dest, **opts):
153 '''create an unversioned archive of a repository revision
153 '''create an unversioned archive of a repository revision
154
154
155 By default, the revision used is the parent of the working
155 By default, the revision used is the parent of the working
156 directory; use -r/--rev to specify a different revision.
156 directory; use -r/--rev to specify a different revision.
157
157
158 The archive type is automatically detected based on file
158 The archive type is automatically detected based on file
159 extension (or override using -t/--type).
159 extension (or override using -t/--type).
160
160
161 Valid types are:
161 Valid types are:
162
162
163 :``files``: a directory full of files (default)
163 :``files``: a directory full of files (default)
164 :``tar``: tar archive, uncompressed
164 :``tar``: tar archive, uncompressed
165 :``tbz2``: tar archive, compressed using bzip2
165 :``tbz2``: tar archive, compressed using bzip2
166 :``tgz``: tar archive, compressed using gzip
166 :``tgz``: tar archive, compressed using gzip
167 :``uzip``: zip archive, uncompressed
167 :``uzip``: zip archive, uncompressed
168 :``zip``: zip archive, compressed using deflate
168 :``zip``: zip archive, compressed using deflate
169
169
170 The exact name of the destination archive or directory is given
170 The exact name of the destination archive or directory is given
171 using a format string; see :hg:`help export` for details.
171 using a format string; see :hg:`help export` for details.
172
172
173 Each member added to an archive file has a directory prefix
173 Each member added to an archive file has a directory prefix
174 prepended. Use -p/--prefix to specify a format string for the
174 prepended. Use -p/--prefix to specify a format string for the
175 prefix. The default is the basename of the archive, with suffixes
175 prefix. The default is the basename of the archive, with suffixes
176 removed.
176 removed.
177
177
178 Returns 0 on success.
178 Returns 0 on success.
179 '''
179 '''
180
180
181 ctx = cmdutil.revsingle(repo, opts.get('rev'))
181 ctx = cmdutil.revsingle(repo, opts.get('rev'))
182 if not ctx:
182 if not ctx:
183 raise util.Abort(_('no working directory: please specify a revision'))
183 raise util.Abort(_('no working directory: please specify a revision'))
184 node = ctx.node()
184 node = ctx.node()
185 dest = cmdutil.make_filename(repo, dest, node)
185 dest = cmdutil.make_filename(repo, dest, node)
186 if os.path.realpath(dest) == repo.root:
186 if os.path.realpath(dest) == repo.root:
187 raise util.Abort(_('repository root cannot be destination'))
187 raise util.Abort(_('repository root cannot be destination'))
188
188
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
190 prefix = opts.get('prefix')
190 prefix = opts.get('prefix')
191
191
192 if dest == '-':
192 if dest == '-':
193 if kind == 'files':
193 if kind == 'files':
194 raise util.Abort(_('cannot archive plain files to stdout'))
194 raise util.Abort(_('cannot archive plain files to stdout'))
195 dest = sys.stdout
195 dest = sys.stdout
196 if not prefix:
196 if not prefix:
197 prefix = os.path.basename(repo.root) + '-%h'
197 prefix = os.path.basename(repo.root) + '-%h'
198
198
199 prefix = cmdutil.make_filename(repo, prefix, node)
199 prefix = cmdutil.make_filename(repo, prefix, node)
200 matchfn = cmdutil.match(repo, [], opts)
200 matchfn = cmdutil.match(repo, [], opts)
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
202 matchfn, prefix, subrepos=opts.get('subrepos'))
202 matchfn, prefix, subrepos=opts.get('subrepos'))
203
203
204 def backout(ui, repo, node=None, rev=None, **opts):
204 def backout(ui, repo, node=None, rev=None, **opts):
205 '''reverse effect of earlier changeset
205 '''reverse effect of earlier changeset
206
206
207 Prepare a new changeset with the effect of REV undone in the
207 Prepare a new changeset with the effect of REV undone in the
208 current working directory.
208 current working directory.
209
209
210 If REV is the parent of the working directory, then this changeset
210 If REV is the parent of the working directory, then this changeset
211 is committed automatically. Otherwise, hg needs to merge the
211 is committed automatically. Otherwise, hg needs to merge the
212 changes and the merged result is left uncommitted.
212 changes and the merged result is left uncommitted.
213
213
214 By default, the pending changeset will have one parent,
214 By default, the pending changeset will have one parent,
215 maintaining a linear history. With --merge, the pending changeset
215 maintaining a linear history. With --merge, the pending changeset
216 will instead have two parents: the old parent of the working
216 will instead have two parents: the old parent of the working
217 directory and a child of REV that simply undoes REV.
217 directory and a child of REV that simply undoes REV.
218
218
219 Before version 1.7, the default behavior was equivalent to
219 Before version 1.7, the default behavior was equivalent to
220 specifying --merge followed by :hg:`update --clean .` to cancel
220 specifying --merge followed by :hg:`update --clean .` to cancel
221 the merge and leave the child of REV as a head to be merged
221 the merge and leave the child of REV as a head to be merged
222 separately.
222 separately.
223
223
224 See :hg:`help dates` for a list of formats valid for -d/--date.
224 See :hg:`help dates` for a list of formats valid for -d/--date.
225
225
226 Returns 0 on success.
226 Returns 0 on success.
227 '''
227 '''
228 if rev and node:
228 if rev and node:
229 raise util.Abort(_("please specify just one revision"))
229 raise util.Abort(_("please specify just one revision"))
230
230
231 if not rev:
231 if not rev:
232 rev = node
232 rev = node
233
233
234 if not rev:
234 if not rev:
235 raise util.Abort(_("please specify a revision to backout"))
235 raise util.Abort(_("please specify a revision to backout"))
236
236
237 date = opts.get('date')
237 date = opts.get('date')
238 if date:
238 if date:
239 opts['date'] = util.parsedate(date)
239 opts['date'] = util.parsedate(date)
240
240
241 cmdutil.bail_if_changed(repo)
241 cmdutil.bail_if_changed(repo)
242 node = cmdutil.revsingle(repo, rev).node()
242 node = cmdutil.revsingle(repo, rev).node()
243
243
244 op1, op2 = repo.dirstate.parents()
244 op1, op2 = repo.dirstate.parents()
245 a = repo.changelog.ancestor(op1, node)
245 a = repo.changelog.ancestor(op1, node)
246 if a != node:
246 if a != node:
247 raise util.Abort(_('cannot backout change on a different branch'))
247 raise util.Abort(_('cannot backout change on a different branch'))
248
248
249 p1, p2 = repo.changelog.parents(node)
249 p1, p2 = repo.changelog.parents(node)
250 if p1 == nullid:
250 if p1 == nullid:
251 raise util.Abort(_('cannot backout a change with no parents'))
251 raise util.Abort(_('cannot backout a change with no parents'))
252 if p2 != nullid:
252 if p2 != nullid:
253 if not opts.get('parent'):
253 if not opts.get('parent'):
254 raise util.Abort(_('cannot backout a merge changeset without '
254 raise util.Abort(_('cannot backout a merge changeset without '
255 '--parent'))
255 '--parent'))
256 p = repo.lookup(opts['parent'])
256 p = repo.lookup(opts['parent'])
257 if p not in (p1, p2):
257 if p not in (p1, p2):
258 raise util.Abort(_('%s is not a parent of %s') %
258 raise util.Abort(_('%s is not a parent of %s') %
259 (short(p), short(node)))
259 (short(p), short(node)))
260 parent = p
260 parent = p
261 else:
261 else:
262 if opts.get('parent'):
262 if opts.get('parent'):
263 raise util.Abort(_('cannot use --parent on non-merge changeset'))
263 raise util.Abort(_('cannot use --parent on non-merge changeset'))
264 parent = p1
264 parent = p1
265
265
266 # the backout should appear on the same branch
266 # the backout should appear on the same branch
267 branch = repo.dirstate.branch()
267 branch = repo.dirstate.branch()
268 hg.clean(repo, node, show_stats=False)
268 hg.clean(repo, node, show_stats=False)
269 repo.dirstate.setbranch(branch)
269 repo.dirstate.setbranch(branch)
270 revert_opts = opts.copy()
270 revert_opts = opts.copy()
271 revert_opts['date'] = None
271 revert_opts['date'] = None
272 revert_opts['all'] = True
272 revert_opts['all'] = True
273 revert_opts['rev'] = hex(parent)
273 revert_opts['rev'] = hex(parent)
274 revert_opts['no_backup'] = None
274 revert_opts['no_backup'] = None
275 revert(ui, repo, **revert_opts)
275 revert(ui, repo, **revert_opts)
276 if not opts.get('merge') and op1 != node:
276 if not opts.get('merge') and op1 != node:
277 try:
277 try:
278 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
278 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
279 return hg.update(repo, op1)
279 return hg.update(repo, op1)
280 finally:
280 finally:
281 ui.setconfig('ui', 'forcemerge', '')
281 ui.setconfig('ui', 'forcemerge', '')
282
282
283 commit_opts = opts.copy()
283 commit_opts = opts.copy()
284 commit_opts['addremove'] = False
284 commit_opts['addremove'] = False
285 if not commit_opts['message'] and not commit_opts['logfile']:
285 if not commit_opts['message'] and not commit_opts['logfile']:
286 # we don't translate commit messages
286 # we don't translate commit messages
287 commit_opts['message'] = "Backed out changeset %s" % short(node)
287 commit_opts['message'] = "Backed out changeset %s" % short(node)
288 commit_opts['force_editor'] = True
288 commit_opts['force_editor'] = True
289 commit(ui, repo, **commit_opts)
289 commit(ui, repo, **commit_opts)
290 def nice(node):
290 def nice(node):
291 return '%d:%s' % (repo.changelog.rev(node), short(node))
291 return '%d:%s' % (repo.changelog.rev(node), short(node))
292 ui.status(_('changeset %s backs out changeset %s\n') %
292 ui.status(_('changeset %s backs out changeset %s\n') %
293 (nice(repo.changelog.tip()), nice(node)))
293 (nice(repo.changelog.tip()), nice(node)))
294 if opts.get('merge') and op1 != node:
294 if opts.get('merge') and op1 != node:
295 hg.clean(repo, op1, show_stats=False)
295 hg.clean(repo, op1, show_stats=False)
296 ui.status(_('merging with changeset %s\n')
296 ui.status(_('merging with changeset %s\n')
297 % nice(repo.changelog.tip()))
297 % nice(repo.changelog.tip()))
298 try:
298 try:
299 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
299 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
300 return hg.merge(repo, hex(repo.changelog.tip()))
300 return hg.merge(repo, hex(repo.changelog.tip()))
301 finally:
301 finally:
302 ui.setconfig('ui', 'forcemerge', '')
302 ui.setconfig('ui', 'forcemerge', '')
303 return 0
303 return 0
304
304
305 def bisect(ui, repo, rev=None, extra=None, command=None,
305 def bisect(ui, repo, rev=None, extra=None, command=None,
306 reset=None, good=None, bad=None, skip=None, noupdate=None):
306 reset=None, good=None, bad=None, skip=None, noupdate=None):
307 """subdivision search of changesets
307 """subdivision search of changesets
308
308
309 This command helps to find changesets which introduce problems. To
309 This command helps to find changesets which introduce problems. To
310 use, mark the earliest changeset you know exhibits the problem as
310 use, mark the earliest changeset you know exhibits the problem as
311 bad, then mark the latest changeset which is free from the problem
311 bad, then mark the latest changeset which is free from the problem
312 as good. Bisect will update your working directory to a revision
312 as good. Bisect will update your working directory to a revision
313 for testing (unless the -U/--noupdate option is specified). Once
313 for testing (unless the -U/--noupdate option is specified). Once
314 you have performed tests, mark the working directory as good or
314 you have performed tests, mark the working directory as good or
315 bad, and bisect will either update to another candidate changeset
315 bad, and bisect will either update to another candidate changeset
316 or announce that it has found the bad revision.
316 or announce that it has found the bad revision.
317
317
318 As a shortcut, you can also use the revision argument to mark a
318 As a shortcut, you can also use the revision argument to mark a
319 revision as good or bad without checking it out first.
319 revision as good or bad without checking it out first.
320
320
321 If you supply a command, it will be used for automatic bisection.
321 If you supply a command, it will be used for automatic bisection.
322 Its exit status will be used to mark revisions as good or bad:
322 Its exit status will be used to mark revisions as good or bad:
323 status 0 means good, 125 means to skip the revision, 127
323 status 0 means good, 125 means to skip the revision, 127
324 (command not found) will abort the bisection, and any other
324 (command not found) will abort the bisection, and any other
325 non-zero exit status means the revision is bad.
325 non-zero exit status means the revision is bad.
326
326
327 Returns 0 on success.
327 Returns 0 on success.
328 """
328 """
329 def print_result(nodes, good):
329 def print_result(nodes, good):
330 displayer = cmdutil.show_changeset(ui, repo, {})
330 displayer = cmdutil.show_changeset(ui, repo, {})
331 if len(nodes) == 1:
331 if len(nodes) == 1:
332 # narrowed it down to a single revision
332 # narrowed it down to a single revision
333 if good:
333 if good:
334 ui.write(_("The first good revision is:\n"))
334 ui.write(_("The first good revision is:\n"))
335 else:
335 else:
336 ui.write(_("The first bad revision is:\n"))
336 ui.write(_("The first bad revision is:\n"))
337 displayer.show(repo[nodes[0]])
337 displayer.show(repo[nodes[0]])
338 parents = repo[nodes[0]].parents()
338 parents = repo[nodes[0]].parents()
339 if len(parents) > 1:
339 if len(parents) > 1:
340 side = good and state['bad'] or state['good']
340 side = good and state['bad'] or state['good']
341 num = len(set(i.node() for i in parents) & set(side))
341 num = len(set(i.node() for i in parents) & set(side))
342 if num == 1:
342 if num == 1:
343 common = parents[0].ancestor(parents[1])
343 common = parents[0].ancestor(parents[1])
344 ui.write(_('Not all ancestors of this changeset have been'
344 ui.write(_('Not all ancestors of this changeset have been'
345 ' checked.\nTo check the other ancestors, start'
345 ' checked.\nTo check the other ancestors, start'
346 ' from the common ancestor, %s.\n' % common))
346 ' from the common ancestor, %s.\n' % common))
347 else:
347 else:
348 # multiple possible revisions
348 # multiple possible revisions
349 if good:
349 if good:
350 ui.write(_("Due to skipped revisions, the first "
350 ui.write(_("Due to skipped revisions, the first "
351 "good revision could be any of:\n"))
351 "good revision could be any of:\n"))
352 else:
352 else:
353 ui.write(_("Due to skipped revisions, the first "
353 ui.write(_("Due to skipped revisions, the first "
354 "bad revision could be any of:\n"))
354 "bad revision could be any of:\n"))
355 for n in nodes:
355 for n in nodes:
356 displayer.show(repo[n])
356 displayer.show(repo[n])
357 displayer.close()
357 displayer.close()
358
358
359 def check_state(state, interactive=True):
359 def check_state(state, interactive=True):
360 if not state['good'] or not state['bad']:
360 if not state['good'] or not state['bad']:
361 if (good or bad or skip or reset) and interactive:
361 if (good or bad or skip or reset) and interactive:
362 return
362 return
363 if not state['good']:
363 if not state['good']:
364 raise util.Abort(_('cannot bisect (no known good revisions)'))
364 raise util.Abort(_('cannot bisect (no known good revisions)'))
365 else:
365 else:
366 raise util.Abort(_('cannot bisect (no known bad revisions)'))
366 raise util.Abort(_('cannot bisect (no known bad revisions)'))
367 return True
367 return True
368
368
369 # backward compatibility
369 # backward compatibility
370 if rev in "good bad reset init".split():
370 if rev in "good bad reset init".split():
371 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
371 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
372 cmd, rev, extra = rev, extra, None
372 cmd, rev, extra = rev, extra, None
373 if cmd == "good":
373 if cmd == "good":
374 good = True
374 good = True
375 elif cmd == "bad":
375 elif cmd == "bad":
376 bad = True
376 bad = True
377 else:
377 else:
378 reset = True
378 reset = True
379 elif extra or good + bad + skip + reset + bool(command) > 1:
379 elif extra or good + bad + skip + reset + bool(command) > 1:
380 raise util.Abort(_('incompatible arguments'))
380 raise util.Abort(_('incompatible arguments'))
381
381
382 if reset:
382 if reset:
383 p = repo.join("bisect.state")
383 p = repo.join("bisect.state")
384 if os.path.exists(p):
384 if os.path.exists(p):
385 os.unlink(p)
385 os.unlink(p)
386 return
386 return
387
387
388 state = hbisect.load_state(repo)
388 state = hbisect.load_state(repo)
389
389
390 if command:
390 if command:
391 changesets = 1
391 changesets = 1
392 try:
392 try:
393 while changesets:
393 while changesets:
394 # update state
394 # update state
395 status = util.system(command)
395 status = util.system(command)
396 if status == 125:
396 if status == 125:
397 transition = "skip"
397 transition = "skip"
398 elif status == 0:
398 elif status == 0:
399 transition = "good"
399 transition = "good"
400 # status < 0 means process was killed
400 # status < 0 means process was killed
401 elif status == 127:
401 elif status == 127:
402 raise util.Abort(_("failed to execute %s") % command)
402 raise util.Abort(_("failed to execute %s") % command)
403 elif status < 0:
403 elif status < 0:
404 raise util.Abort(_("%s killed") % command)
404 raise util.Abort(_("%s killed") % command)
405 else:
405 else:
406 transition = "bad"
406 transition = "bad"
407 ctx = cmdutil.revsingle(repo, rev)
407 ctx = cmdutil.revsingle(repo, rev)
408 rev = None # clear for future iterations
408 rev = None # clear for future iterations
409 state[transition].append(ctx.node())
409 state[transition].append(ctx.node())
410 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
410 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
411 check_state(state, interactive=False)
411 check_state(state, interactive=False)
412 # bisect
412 # bisect
413 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
413 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
414 # update to next check
414 # update to next check
415 cmdutil.bail_if_changed(repo)
415 cmdutil.bail_if_changed(repo)
416 hg.clean(repo, nodes[0], show_stats=False)
416 hg.clean(repo, nodes[0], show_stats=False)
417 finally:
417 finally:
418 hbisect.save_state(repo, state)
418 hbisect.save_state(repo, state)
419 print_result(nodes, good)
419 print_result(nodes, good)
420 return
420 return
421
421
422 # update state
422 # update state
423
423
424 if rev:
424 if rev:
425 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
425 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
426 else:
426 else:
427 nodes = [repo.lookup('.')]
427 nodes = [repo.lookup('.')]
428
428
429 if good or bad or skip:
429 if good or bad or skip:
430 if good:
430 if good:
431 state['good'] += nodes
431 state['good'] += nodes
432 elif bad:
432 elif bad:
433 state['bad'] += nodes
433 state['bad'] += nodes
434 elif skip:
434 elif skip:
435 state['skip'] += nodes
435 state['skip'] += nodes
436 hbisect.save_state(repo, state)
436 hbisect.save_state(repo, state)
437
437
438 if not check_state(state):
438 if not check_state(state):
439 return
439 return
440
440
441 # actually bisect
441 # actually bisect
442 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
442 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
443 if changesets == 0:
443 if changesets == 0:
444 print_result(nodes, good)
444 print_result(nodes, good)
445 else:
445 else:
446 assert len(nodes) == 1 # only a single node can be tested next
446 assert len(nodes) == 1 # only a single node can be tested next
447 node = nodes[0]
447 node = nodes[0]
448 # compute the approximate number of remaining tests
448 # compute the approximate number of remaining tests
449 tests, size = 0, 2
449 tests, size = 0, 2
450 while size <= changesets:
450 while size <= changesets:
451 tests, size = tests + 1, size * 2
451 tests, size = tests + 1, size * 2
452 rev = repo.changelog.rev(node)
452 rev = repo.changelog.rev(node)
453 ui.write(_("Testing changeset %d:%s "
453 ui.write(_("Testing changeset %d:%s "
454 "(%d changesets remaining, ~%d tests)\n")
454 "(%d changesets remaining, ~%d tests)\n")
455 % (rev, short(node), changesets, tests))
455 % (rev, short(node), changesets, tests))
456 if not noupdate:
456 if not noupdate:
457 cmdutil.bail_if_changed(repo)
457 cmdutil.bail_if_changed(repo)
458 return hg.clean(repo, node)
458 return hg.clean(repo, node)
459
459
460 def branch(ui, repo, label=None, **opts):
460 def branch(ui, repo, label=None, **opts):
461 """set or show the current branch name
461 """set or show the current branch name
462
462
463 With no argument, show the current branch name. With one argument,
463 With no argument, show the current branch name. With one argument,
464 set the working directory branch name (the branch will not exist
464 set the working directory branch name (the branch will not exist
465 in the repository until the next commit). Standard practice
465 in the repository until the next commit). Standard practice
466 recommends that primary development take place on the 'default'
466 recommends that primary development take place on the 'default'
467 branch.
467 branch.
468
468
469 Unless -f/--force is specified, branch will not let you set a
469 Unless -f/--force is specified, branch will not let you set a
470 branch name that already exists, even if it's inactive.
470 branch name that already exists, even if it's inactive.
471
471
472 Use -C/--clean to reset the working directory branch to that of
472 Use -C/--clean to reset the working directory branch to that of
473 the parent of the working directory, negating a previous branch
473 the parent of the working directory, negating a previous branch
474 change.
474 change.
475
475
476 Use the command :hg:`update` to switch to an existing branch. Use
476 Use the command :hg:`update` to switch to an existing branch. Use
477 :hg:`commit --close-branch` to mark this branch as closed.
477 :hg:`commit --close-branch` to mark this branch as closed.
478
478
479 Returns 0 on success.
479 Returns 0 on success.
480 """
480 """
481
481
482 if opts.get('clean'):
482 if opts.get('clean'):
483 label = repo[None].parents()[0].branch()
483 label = repo[None].parents()[0].branch()
484 repo.dirstate.setbranch(label)
484 repo.dirstate.setbranch(label)
485 ui.status(_('reset working directory to branch %s\n') % label)
485 ui.status(_('reset working directory to branch %s\n') % label)
486 elif label:
486 elif label:
487 if not opts.get('force') and label in repo.branchtags():
487 if not opts.get('force') and label in repo.branchtags():
488 if label not in [p.branch() for p in repo.parents()]:
488 if label not in [p.branch() for p in repo.parents()]:
489 raise util.Abort(_('a branch of the same name already exists'
489 raise util.Abort(_('a branch of the same name already exists'
490 " (use 'hg update' to switch to it)"))
490 " (use 'hg update' to switch to it)"))
491 repo.dirstate.setbranch(label)
491 repo.dirstate.setbranch(label)
492 ui.status(_('marked working directory as branch %s\n') % label)
492 ui.status(_('marked working directory as branch %s\n') % label)
493 else:
493 else:
494 ui.write("%s\n" % repo.dirstate.branch())
494 ui.write("%s\n" % repo.dirstate.branch())
495
495
496 def branches(ui, repo, active=False, closed=False):
496 def branches(ui, repo, active=False, closed=False):
497 """list repository named branches
497 """list repository named branches
498
498
499 List the repository's named branches, indicating which ones are
499 List the repository's named branches, indicating which ones are
500 inactive. If -c/--closed is specified, also list branches which have
500 inactive. If -c/--closed is specified, also list branches which have
501 been marked closed (see :hg:`commit --close-branch`).
501 been marked closed (see :hg:`commit --close-branch`).
502
502
503 If -a/--active is specified, only show active branches. A branch
503 If -a/--active is specified, only show active branches. A branch
504 is considered active if it contains repository heads.
504 is considered active if it contains repository heads.
505
505
506 Use the command :hg:`update` to switch to an existing branch.
506 Use the command :hg:`update` to switch to an existing branch.
507
507
508 Returns 0.
508 Returns 0.
509 """
509 """
510
510
511 hexfunc = ui.debugflag and hex or short
511 hexfunc = ui.debugflag and hex or short
512 activebranches = [repo[n].branch() for n in repo.heads()]
512 activebranches = [repo[n].branch() for n in repo.heads()]
513 def testactive(tag, node):
513 def testactive(tag, node):
514 realhead = tag in activebranches
514 realhead = tag in activebranches
515 open = node in repo.branchheads(tag, closed=False)
515 open = node in repo.branchheads(tag, closed=False)
516 return realhead and open
516 return realhead and open
517 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
517 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
518 for tag, node in repo.branchtags().items()],
518 for tag, node in repo.branchtags().items()],
519 reverse=True)
519 reverse=True)
520
520
521 for isactive, node, tag in branches:
521 for isactive, node, tag in branches:
522 if (not active) or isactive:
522 if (not active) or isactive:
523 if ui.quiet:
523 if ui.quiet:
524 ui.write("%s\n" % tag)
524 ui.write("%s\n" % tag)
525 else:
525 else:
526 hn = repo.lookup(node)
526 hn = repo.lookup(node)
527 if isactive:
527 if isactive:
528 label = 'branches.active'
528 label = 'branches.active'
529 notice = ''
529 notice = ''
530 elif hn not in repo.branchheads(tag, closed=False):
530 elif hn not in repo.branchheads(tag, closed=False):
531 if not closed:
531 if not closed:
532 continue
532 continue
533 label = 'branches.closed'
533 label = 'branches.closed'
534 notice = _(' (closed)')
534 notice = _(' (closed)')
535 else:
535 else:
536 label = 'branches.inactive'
536 label = 'branches.inactive'
537 notice = _(' (inactive)')
537 notice = _(' (inactive)')
538 if tag == repo.dirstate.branch():
538 if tag == repo.dirstate.branch():
539 label = 'branches.current'
539 label = 'branches.current'
540 rev = str(node).rjust(31 - encoding.colwidth(tag))
540 rev = str(node).rjust(31 - encoding.colwidth(tag))
541 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
541 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
542 tag = ui.label(tag, label)
542 tag = ui.label(tag, label)
543 ui.write("%s %s%s\n" % (tag, rev, notice))
543 ui.write("%s %s%s\n" % (tag, rev, notice))
544
544
545 def bundle(ui, repo, fname, dest=None, **opts):
545 def bundle(ui, repo, fname, dest=None, **opts):
546 """create a changegroup file
546 """create a changegroup file
547
547
548 Generate a compressed changegroup file collecting changesets not
548 Generate a compressed changegroup file collecting changesets not
549 known to be in another repository.
549 known to be in another repository.
550
550
551 If you omit the destination repository, then hg assumes the
551 If you omit the destination repository, then hg assumes the
552 destination will have all the nodes you specify with --base
552 destination will have all the nodes you specify with --base
553 parameters. To create a bundle containing all changesets, use
553 parameters. To create a bundle containing all changesets, use
554 -a/--all (or --base null).
554 -a/--all (or --base null).
555
555
556 You can change compression method with the -t/--type option.
556 You can change compression method with the -t/--type option.
557 The available compression methods are: none, bzip2, and
557 The available compression methods are: none, bzip2, and
558 gzip (by default, bundles are compressed using bzip2).
558 gzip (by default, bundles are compressed using bzip2).
559
559
560 The bundle file can then be transferred using conventional means
560 The bundle file can then be transferred using conventional means
561 and applied to another repository with the unbundle or pull
561 and applied to another repository with the unbundle or pull
562 command. This is useful when direct push and pull are not
562 command. This is useful when direct push and pull are not
563 available or when exporting an entire repository is undesirable.
563 available or when exporting an entire repository is undesirable.
564
564
565 Applying bundles preserves all changeset contents including
565 Applying bundles preserves all changeset contents including
566 permissions, copy/rename information, and revision history.
566 permissions, copy/rename information, and revision history.
567
567
568 Returns 0 on success, 1 if no changes found.
568 Returns 0 on success, 1 if no changes found.
569 """
569 """
570 revs = None
570 revs = None
571 if 'rev' in opts:
571 if 'rev' in opts:
572 revs = cmdutil.revrange(repo, opts['rev'])
572 revs = cmdutil.revrange(repo, opts['rev'])
573
573
574 if opts.get('all'):
574 if opts.get('all'):
575 base = ['null']
575 base = ['null']
576 else:
576 else:
577 base = cmdutil.revrange(repo, opts.get('base'))
577 base = cmdutil.revrange(repo, opts.get('base'))
578 if base:
578 if base:
579 if dest:
579 if dest:
580 raise util.Abort(_("--base is incompatible with specifying "
580 raise util.Abort(_("--base is incompatible with specifying "
581 "a destination"))
581 "a destination"))
582 base = [repo.lookup(rev) for rev in base]
582 base = [repo.lookup(rev) for rev in base]
583 # create the right base
583 # create the right base
584 # XXX: nodesbetween / changegroup* should be "fixed" instead
584 # XXX: nodesbetween / changegroup* should be "fixed" instead
585 o = []
585 o = []
586 has = set((nullid,))
586 has = set((nullid,))
587 for n in base:
587 for n in base:
588 has.update(repo.changelog.reachable(n))
588 has.update(repo.changelog.reachable(n))
589 if revs:
589 if revs:
590 revs = [repo.lookup(rev) for rev in revs]
590 revs = [repo.lookup(rev) for rev in revs]
591 visit = revs[:]
591 visit = revs[:]
592 has.difference_update(visit)
592 has.difference_update(visit)
593 else:
593 else:
594 visit = repo.changelog.heads()
594 visit = repo.changelog.heads()
595 seen = {}
595 seen = {}
596 while visit:
596 while visit:
597 n = visit.pop(0)
597 n = visit.pop(0)
598 parents = [p for p in repo.changelog.parents(n) if p not in has]
598 parents = [p for p in repo.changelog.parents(n) if p not in has]
599 if len(parents) == 0:
599 if len(parents) == 0:
600 if n not in has:
600 if n not in has:
601 o.append(n)
601 o.append(n)
602 else:
602 else:
603 for p in parents:
603 for p in parents:
604 if p not in seen:
604 if p not in seen:
605 seen[p] = 1
605 seen[p] = 1
606 visit.append(p)
606 visit.append(p)
607 else:
607 else:
608 dest = ui.expandpath(dest or 'default-push', dest or 'default')
608 dest = ui.expandpath(dest or 'default-push', dest or 'default')
609 dest, branches = hg.parseurl(dest, opts.get('branch'))
609 dest, branches = hg.parseurl(dest, opts.get('branch'))
610 other = hg.repository(hg.remoteui(repo, opts), dest)
610 other = hg.repository(hg.remoteui(repo, opts), dest)
611 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
611 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
612 if revs:
612 if revs:
613 revs = [repo.lookup(rev) for rev in revs]
613 revs = [repo.lookup(rev) for rev in revs]
614 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
614 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
615
615
616 if not o:
616 if not o:
617 ui.status(_("no changes found\n"))
617 ui.status(_("no changes found\n"))
618 return 1
618 return 1
619
619
620 if revs:
620 if revs:
621 cg = repo.changegroupsubset(o, revs, 'bundle')
621 cg = repo.changegroupsubset(o, revs, 'bundle')
622 else:
622 else:
623 cg = repo.changegroup(o, 'bundle')
623 cg = repo.changegroup(o, 'bundle')
624
624
625 bundletype = opts.get('type', 'bzip2').lower()
625 bundletype = opts.get('type', 'bzip2').lower()
626 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
626 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
627 bundletype = btypes.get(bundletype)
627 bundletype = btypes.get(bundletype)
628 if bundletype not in changegroup.bundletypes:
628 if bundletype not in changegroup.bundletypes:
629 raise util.Abort(_('unknown bundle type specified with --type'))
629 raise util.Abort(_('unknown bundle type specified with --type'))
630
630
631 changegroup.writebundle(cg, fname, bundletype)
631 changegroup.writebundle(cg, fname, bundletype)
632
632
633 def cat(ui, repo, file1, *pats, **opts):
633 def cat(ui, repo, file1, *pats, **opts):
634 """output the current or given revision of files
634 """output the current or given revision of files
635
635
636 Print the specified files as they were at the given revision. If
636 Print the specified files as they were at the given revision. If
637 no revision is given, the parent of the working directory is used,
637 no revision is given, the parent of the working directory is used,
638 or tip if no revision is checked out.
638 or tip if no revision is checked out.
639
639
640 Output may be to a file, in which case the name of the file is
640 Output may be to a file, in which case the name of the file is
641 given using a format string. The formatting rules are the same as
641 given using a format string. The formatting rules are the same as
642 for the export command, with the following additions:
642 for the export command, with the following additions:
643
643
644 :``%s``: basename of file being printed
644 :``%s``: basename of file being printed
645 :``%d``: dirname of file being printed, or '.' if in repository root
645 :``%d``: dirname of file being printed, or '.' if in repository root
646 :``%p``: root-relative path name of file being printed
646 :``%p``: root-relative path name of file being printed
647
647
648 Returns 0 on success.
648 Returns 0 on success.
649 """
649 """
650 ctx = cmdutil.revsingle(repo, opts.get('rev'))
650 ctx = cmdutil.revsingle(repo, opts.get('rev'))
651 err = 1
651 err = 1
652 m = cmdutil.match(repo, (file1,) + pats, opts)
652 m = cmdutil.match(repo, (file1,) + pats, opts)
653 for abs in ctx.walk(m):
653 for abs in ctx.walk(m):
654 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
654 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
655 data = ctx[abs].data()
655 data = ctx[abs].data()
656 if opts.get('decode'):
656 if opts.get('decode'):
657 data = repo.wwritedata(abs, data)
657 data = repo.wwritedata(abs, data)
658 fp.write(data)
658 fp.write(data)
659 err = 0
659 err = 0
660 return err
660 return err
661
661
662 def clone(ui, source, dest=None, **opts):
662 def clone(ui, source, dest=None, **opts):
663 """make a copy of an existing repository
663 """make a copy of an existing repository
664
664
665 Create a copy of an existing repository in a new directory.
665 Create a copy of an existing repository in a new directory.
666
666
667 If no destination directory name is specified, it defaults to the
667 If no destination directory name is specified, it defaults to the
668 basename of the source.
668 basename of the source.
669
669
670 The location of the source is added to the new repository's
670 The location of the source is added to the new repository's
671 ``.hg/hgrc`` file, as the default to be used for future pulls.
671 ``.hg/hgrc`` file, as the default to be used for future pulls.
672
672
673 See :hg:`help urls` for valid source format details.
673 See :hg:`help urls` for valid source format details.
674
674
675 It is possible to specify an ``ssh://`` URL as the destination, but no
675 It is possible to specify an ``ssh://`` URL as the destination, but no
676 ``.hg/hgrc`` and working directory will be created on the remote side.
676 ``.hg/hgrc`` and working directory will be created on the remote side.
677 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
677 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
678
678
679 A set of changesets (tags, or branch names) to pull may be specified
679 A set of changesets (tags, or branch names) to pull may be specified
680 by listing each changeset (tag, or branch name) with -r/--rev.
680 by listing each changeset (tag, or branch name) with -r/--rev.
681 If -r/--rev is used, the cloned repository will contain only a subset
681 If -r/--rev is used, the cloned repository will contain only a subset
682 of the changesets of the source repository. Only the set of changesets
682 of the changesets of the source repository. Only the set of changesets
683 defined by all -r/--rev options (including all their ancestors)
683 defined by all -r/--rev options (including all their ancestors)
684 will be pulled into the destination repository.
684 will be pulled into the destination repository.
685 No subsequent changesets (including subsequent tags) will be present
685 No subsequent changesets (including subsequent tags) will be present
686 in the destination.
686 in the destination.
687
687
688 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
688 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
689 local source repositories.
689 local source repositories.
690
690
691 For efficiency, hardlinks are used for cloning whenever the source
691 For efficiency, hardlinks are used for cloning whenever the source
692 and destination are on the same filesystem (note this applies only
692 and destination are on the same filesystem (note this applies only
693 to the repository data, not to the working directory). Some
693 to the repository data, not to the working directory). Some
694 filesystems, such as AFS, implement hardlinking incorrectly, but
694 filesystems, such as AFS, implement hardlinking incorrectly, but
695 do not report errors. In these cases, use the --pull option to
695 do not report errors. In these cases, use the --pull option to
696 avoid hardlinking.
696 avoid hardlinking.
697
697
698 In some cases, you can clone repositories and the working directory
698 In some cases, you can clone repositories and the working directory
699 using full hardlinks with ::
699 using full hardlinks with ::
700
700
701 $ cp -al REPO REPOCLONE
701 $ cp -al REPO REPOCLONE
702
702
703 This is the fastest way to clone, but it is not always safe. The
703 This is the fastest way to clone, but it is not always safe. The
704 operation is not atomic (making sure REPO is not modified during
704 operation is not atomic (making sure REPO is not modified during
705 the operation is up to you) and you have to make sure your editor
705 the operation is up to you) and you have to make sure your editor
706 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
706 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
707 this is not compatible with certain extensions that place their
707 this is not compatible with certain extensions that place their
708 metadata under the .hg directory, such as mq.
708 metadata under the .hg directory, such as mq.
709
709
710 Mercurial will update the working directory to the first applicable
710 Mercurial will update the working directory to the first applicable
711 revision from this list:
711 revision from this list:
712
712
713 a) null if -U or the source repository has no changesets
713 a) null if -U or the source repository has no changesets
714 b) if -u . and the source repository is local, the first parent of
714 b) if -u . and the source repository is local, the first parent of
715 the source repository's working directory
715 the source repository's working directory
716 c) the changeset specified with -u (if a branch name, this means the
716 c) the changeset specified with -u (if a branch name, this means the
717 latest head of that branch)
717 latest head of that branch)
718 d) the changeset specified with -r
718 d) the changeset specified with -r
719 e) the tipmost head specified with -b
719 e) the tipmost head specified with -b
720 f) the tipmost head specified with the url#branch source syntax
720 f) the tipmost head specified with the url#branch source syntax
721 g) the tipmost head of the default branch
721 g) the tipmost head of the default branch
722 h) tip
722 h) tip
723
723
724 Returns 0 on success.
724 Returns 0 on success.
725 """
725 """
726 if opts.get('noupdate') and opts.get('updaterev'):
726 if opts.get('noupdate') and opts.get('updaterev'):
727 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
727 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
728
728
729 r = hg.clone(hg.remoteui(ui, opts), source, dest,
729 r = hg.clone(hg.remoteui(ui, opts), source, dest,
730 pull=opts.get('pull'),
730 pull=opts.get('pull'),
731 stream=opts.get('uncompressed'),
731 stream=opts.get('uncompressed'),
732 rev=opts.get('rev'),
732 rev=opts.get('rev'),
733 update=opts.get('updaterev') or not opts.get('noupdate'),
733 update=opts.get('updaterev') or not opts.get('noupdate'),
734 branch=opts.get('branch'))
734 branch=opts.get('branch'))
735
735
736 return r is None
736 return r is None
737
737
738 def commit(ui, repo, *pats, **opts):
738 def commit(ui, repo, *pats, **opts):
739 """commit the specified files or all outstanding changes
739 """commit the specified files or all outstanding changes
740
740
741 Commit changes to the given files into the repository. Unlike a
741 Commit changes to the given files into the repository. Unlike a
742 centralized SCM, this operation is a local operation. See
742 centralized SCM, this operation is a local operation. See
743 :hg:`push` for a way to actively distribute your changes.
743 :hg:`push` for a way to actively distribute your changes.
744
744
745 If a list of files is omitted, all changes reported by :hg:`status`
745 If a list of files is omitted, all changes reported by :hg:`status`
746 will be committed.
746 will be committed.
747
747
748 If you are committing the result of a merge, do not provide any
748 If you are committing the result of a merge, do not provide any
749 filenames or -I/-X filters.
749 filenames or -I/-X filters.
750
750
751 If no commit message is specified, Mercurial starts your
751 If no commit message is specified, Mercurial starts your
752 configured editor where you can enter a message. In case your
752 configured editor where you can enter a message. In case your
753 commit fails, you will find a backup of your message in
753 commit fails, you will find a backup of your message in
754 ``.hg/last-message.txt``.
754 ``.hg/last-message.txt``.
755
755
756 See :hg:`help dates` for a list of formats valid for -d/--date.
756 See :hg:`help dates` for a list of formats valid for -d/--date.
757
757
758 Returns 0 on success, 1 if nothing changed.
758 Returns 0 on success, 1 if nothing changed.
759 """
759 """
760 extra = {}
760 extra = {}
761 if opts.get('close_branch'):
761 if opts.get('close_branch'):
762 if repo['.'].node() not in repo.branchheads():
762 if repo['.'].node() not in repo.branchheads():
763 # The topo heads set is included in the branch heads set of the
763 # The topo heads set is included in the branch heads set of the
764 # current branch, so it's sufficient to test branchheads
764 # current branch, so it's sufficient to test branchheads
765 raise util.Abort(_('can only close branch heads'))
765 raise util.Abort(_('can only close branch heads'))
766 extra['close'] = 1
766 extra['close'] = 1
767 e = cmdutil.commiteditor
767 e = cmdutil.commiteditor
768 if opts.get('force_editor'):
768 if opts.get('force_editor'):
769 e = cmdutil.commitforceeditor
769 e = cmdutil.commitforceeditor
770
770
771 def commitfunc(ui, repo, message, match, opts):
771 def commitfunc(ui, repo, message, match, opts):
772 return repo.commit(message, opts.get('user'), opts.get('date'), match,
772 return repo.commit(message, opts.get('user'), opts.get('date'), match,
773 editor=e, extra=extra)
773 editor=e, extra=extra)
774
774
775 branch = repo[None].branch()
775 branch = repo[None].branch()
776 bheads = repo.branchheads(branch)
776 bheads = repo.branchheads(branch)
777
777
778 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
778 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
779 if not node:
779 if not node:
780 ui.status(_("nothing changed\n"))
780 ui.status(_("nothing changed\n"))
781 return 1
781 return 1
782
782
783 ctx = repo[node]
783 ctx = repo[node]
784 parents = ctx.parents()
784 parents = ctx.parents()
785
785
786 if bheads and not [x for x in parents
786 if bheads and not [x for x in parents
787 if x.node() in bheads and x.branch() == branch]:
787 if x.node() in bheads and x.branch() == branch]:
788 ui.status(_('created new head\n'))
788 ui.status(_('created new head\n'))
789 # The message is not printed for initial roots. For the other
789 # The message is not printed for initial roots. For the other
790 # changesets, it is printed in the following situations:
790 # changesets, it is printed in the following situations:
791 #
791 #
792 # Par column: for the 2 parents with ...
792 # Par column: for the 2 parents with ...
793 # N: null or no parent
793 # N: null or no parent
794 # B: parent is on another named branch
794 # B: parent is on another named branch
795 # C: parent is a regular non head changeset
795 # C: parent is a regular non head changeset
796 # H: parent was a branch head of the current branch
796 # H: parent was a branch head of the current branch
797 # Msg column: whether we print "created new head" message
797 # Msg column: whether we print "created new head" message
798 # In the following, it is assumed that there already exists some
798 # In the following, it is assumed that there already exists some
799 # initial branch heads of the current branch, otherwise nothing is
799 # initial branch heads of the current branch, otherwise nothing is
800 # printed anyway.
800 # printed anyway.
801 #
801 #
802 # Par Msg Comment
802 # Par Msg Comment
803 # NN y additional topo root
803 # NN y additional topo root
804 #
804 #
805 # BN y additional branch root
805 # BN y additional branch root
806 # CN y additional topo head
806 # CN y additional topo head
807 # HN n usual case
807 # HN n usual case
808 #
808 #
809 # BB y weird additional branch root
809 # BB y weird additional branch root
810 # CB y branch merge
810 # CB y branch merge
811 # HB n merge with named branch
811 # HB n merge with named branch
812 #
812 #
813 # CC y additional head from merge
813 # CC y additional head from merge
814 # CH n merge with a head
814 # CH n merge with a head
815 #
815 #
816 # HH n head merge: head count decreases
816 # HH n head merge: head count decreases
817
817
818 if not opts.get('close_branch'):
818 if not opts.get('close_branch'):
819 for r in parents:
819 for r in parents:
820 if r.extra().get('close') and r.branch() == branch:
820 if r.extra().get('close') and r.branch() == branch:
821 ui.status(_('reopening closed branch head %d\n') % r)
821 ui.status(_('reopening closed branch head %d\n') % r)
822
822
823 if ui.debugflag:
823 if ui.debugflag:
824 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
824 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
825 elif ui.verbose:
825 elif ui.verbose:
826 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
826 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
827
827
828 def copy(ui, repo, *pats, **opts):
828 def copy(ui, repo, *pats, **opts):
829 """mark files as copied for the next commit
829 """mark files as copied for the next commit
830
830
831 Mark dest as having copies of source files. If dest is a
831 Mark dest as having copies of source files. If dest is a
832 directory, copies are put in that directory. If dest is a file,
832 directory, copies are put in that directory. If dest is a file,
833 the source must be a single file.
833 the source must be a single file.
834
834
835 By default, this command copies the contents of files as they
835 By default, this command copies the contents of files as they
836 exist in the working directory. If invoked with -A/--after, the
836 exist in the working directory. If invoked with -A/--after, the
837 operation is recorded, but no copying is performed.
837 operation is recorded, but no copying is performed.
838
838
839 This command takes effect with the next commit. To undo a copy
839 This command takes effect with the next commit. To undo a copy
840 before that, see :hg:`revert`.
840 before that, see :hg:`revert`.
841
841
842 Returns 0 on success, 1 if errors are encountered.
842 Returns 0 on success, 1 if errors are encountered.
843 """
843 """
844 wlock = repo.wlock(False)
844 wlock = repo.wlock(False)
845 try:
845 try:
846 return cmdutil.copy(ui, repo, pats, opts)
846 return cmdutil.copy(ui, repo, pats, opts)
847 finally:
847 finally:
848 wlock.release()
848 wlock.release()
849
849
850 def debugancestor(ui, repo, *args):
850 def debugancestor(ui, repo, *args):
851 """find the ancestor revision of two revisions in a given index"""
851 """find the ancestor revision of two revisions in a given index"""
852 if len(args) == 3:
852 if len(args) == 3:
853 index, rev1, rev2 = args
853 index, rev1, rev2 = args
854 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
854 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
855 lookup = r.lookup
855 lookup = r.lookup
856 elif len(args) == 2:
856 elif len(args) == 2:
857 if not repo:
857 if not repo:
858 raise util.Abort(_("there is no Mercurial repository here "
858 raise util.Abort(_("there is no Mercurial repository here "
859 "(.hg not found)"))
859 "(.hg not found)"))
860 rev1, rev2 = args
860 rev1, rev2 = args
861 r = repo.changelog
861 r = repo.changelog
862 lookup = repo.lookup
862 lookup = repo.lookup
863 else:
863 else:
864 raise util.Abort(_('either two or three arguments required'))
864 raise util.Abort(_('either two or three arguments required'))
865 a = r.ancestor(lookup(rev1), lookup(rev2))
865 a = r.ancestor(lookup(rev1), lookup(rev2))
866 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
866 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
867
867
868 def debugbuilddag(ui, repo, text,
868 def debugbuilddag(ui, repo, text,
869 mergeable_file=False,
869 mergeable_file=False,
870 appended_file=False,
870 appended_file=False,
871 overwritten_file=False,
871 overwritten_file=False,
872 new_file=False):
872 new_file=False):
873 """builds a repo with a given dag from scratch in the current empty repo
873 """builds a repo with a given dag from scratch in the current empty repo
874
874
875 Elements:
875 Elements:
876
876
877 - "+n" is a linear run of n nodes based on the current default parent
877 - "+n" is a linear run of n nodes based on the current default parent
878 - "." is a single node based on the current default parent
878 - "." is a single node based on the current default parent
879 - "$" resets the default parent to null (implied at the start);
879 - "$" resets the default parent to null (implied at the start);
880 otherwise the default parent is always the last node created
880 otherwise the default parent is always the last node created
881 - "<p" sets the default parent to the backref p
881 - "<p" sets the default parent to the backref p
882 - "*p" is a fork at parent p, which is a backref
882 - "*p" is a fork at parent p, which is a backref
883 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
883 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
884 - "/p2" is a merge of the preceding node and p2
884 - "/p2" is a merge of the preceding node and p2
885 - ":tag" defines a local tag for the preceding node
885 - ":tag" defines a local tag for the preceding node
886 - "@branch" sets the named branch for subsequent nodes
886 - "@branch" sets the named branch for subsequent nodes
887 - "!command" runs the command using your shell
887 - "!command" runs the command using your shell
888 - "!!my command\\n" is like "!", but to the end of the line
888 - "!!my command\\n" is like "!", but to the end of the line
889 - "#...\\n" is a comment up to the end of the line
889 - "#...\\n" is a comment up to the end of the line
890
890
891 Whitespace between the above elements is ignored.
891 Whitespace between the above elements is ignored.
892
892
893 A backref is either
893 A backref is either
894
894
895 - a number n, which references the node curr-n, where curr is the current
895 - a number n, which references the node curr-n, where curr is the current
896 node, or
896 node, or
897 - the name of a local tag you placed earlier using ":tag", or
897 - the name of a local tag you placed earlier using ":tag", or
898 - empty to denote the default parent.
898 - empty to denote the default parent.
899
899
900 All string valued-elements are either strictly alphanumeric, or must
900 All string valued-elements are either strictly alphanumeric, or must
901 be enclosed in double quotes ("..."), with "\\" as escape character.
901 be enclosed in double quotes ("..."), with "\\" as escape character.
902
902
903 Note that the --overwritten-file and --appended-file options imply the
903 Note that the --overwritten-file and --appended-file options imply the
904 use of "HGMERGE=internal:local" during DAG buildup.
904 use of "HGMERGE=internal:local" during DAG buildup.
905 """
905 """
906
906
907 if not (mergeable_file or appended_file or overwritten_file or new_file):
907 if not (mergeable_file or appended_file or overwritten_file or new_file):
908 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
908 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
909
909
910 if len(repo.changelog) > 0:
910 if len(repo.changelog) > 0:
911 raise util.Abort(_('repository is not empty'))
911 raise util.Abort(_('repository is not empty'))
912
912
913 if overwritten_file or appended_file:
913 if overwritten_file or appended_file:
914 # we don't want to fail in merges during buildup
914 # we don't want to fail in merges during buildup
915 os.environ['HGMERGE'] = 'internal:local'
915 os.environ['HGMERGE'] = 'internal:local'
916
916
917 def writefile(fname, text, fmode="wb"):
917 def writefile(fname, text, fmode="wb"):
918 f = open(fname, fmode)
918 f = open(fname, fmode)
919 try:
919 try:
920 f.write(text)
920 f.write(text)
921 finally:
921 finally:
922 f.close()
922 f.close()
923
923
924 if mergeable_file:
924 if mergeable_file:
925 linesperrev = 2
925 linesperrev = 2
926 # determine number of revs in DAG
926 # determine number of revs in DAG
927 n = 0
927 n = 0
928 for type, data in dagparser.parsedag(text):
928 for type, data in dagparser.parsedag(text):
929 if type == 'n':
929 if type == 'n':
930 n += 1
930 n += 1
931 # make a file with k lines per rev
931 # make a file with k lines per rev
932 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
932 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
933 + "\n")
933 + "\n")
934
934
935 at = -1
935 at = -1
936 atbranch = 'default'
936 atbranch = 'default'
937 for type, data in dagparser.parsedag(text):
937 for type, data in dagparser.parsedag(text):
938 if type == 'n':
938 if type == 'n':
939 ui.status('node %s\n' % str(data))
939 ui.status('node %s\n' % str(data))
940 id, ps = data
940 id, ps = data
941 p1 = ps[0]
941 p1 = ps[0]
942 if p1 != at:
942 if p1 != at:
943 update(ui, repo, node=str(p1), clean=True)
943 update(ui, repo, node=str(p1), clean=True)
944 at = p1
944 at = p1
945 if repo.dirstate.branch() != atbranch:
945 if repo.dirstate.branch() != atbranch:
946 branch(ui, repo, atbranch, force=True)
946 branch(ui, repo, atbranch, force=True)
947 if len(ps) > 1:
947 if len(ps) > 1:
948 p2 = ps[1]
948 p2 = ps[1]
949 merge(ui, repo, node=p2)
949 merge(ui, repo, node=p2)
950
950
951 if mergeable_file:
951 if mergeable_file:
952 f = open("mf", "rb+")
952 f = open("mf", "rb+")
953 try:
953 try:
954 lines = f.read().split("\n")
954 lines = f.read().split("\n")
955 lines[id * linesperrev] += " r%i" % id
955 lines[id * linesperrev] += " r%i" % id
956 f.seek(0)
956 f.seek(0)
957 f.write("\n".join(lines))
957 f.write("\n".join(lines))
958 finally:
958 finally:
959 f.close()
959 f.close()
960
960
961 if appended_file:
961 if appended_file:
962 writefile("af", "r%i\n" % id, "ab")
962 writefile("af", "r%i\n" % id, "ab")
963
963
964 if overwritten_file:
964 if overwritten_file:
965 writefile("of", "r%i\n" % id)
965 writefile("of", "r%i\n" % id)
966
966
967 if new_file:
967 if new_file:
968 writefile("nf%i" % id, "r%i\n" % id)
968 writefile("nf%i" % id, "r%i\n" % id)
969
969
970 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
970 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
971 at = id
971 at = id
972 elif type == 'l':
972 elif type == 'l':
973 id, name = data
973 id, name = data
974 ui.status('tag %s\n' % name)
974 ui.status('tag %s\n' % name)
975 tag(ui, repo, name, local=True)
975 tag(ui, repo, name, local=True)
976 elif type == 'a':
976 elif type == 'a':
977 ui.status('branch %s\n' % data)
977 ui.status('branch %s\n' % data)
978 atbranch = data
978 atbranch = data
979 elif type in 'cC':
979 elif type in 'cC':
980 r = util.system(data, cwd=repo.root)
980 r = util.system(data, cwd=repo.root)
981 if r:
981 if r:
982 desc, r = util.explain_exit(r)
982 desc, r = util.explain_exit(r)
983 raise util.Abort(_('%s command %s') % (data, desc))
983 raise util.Abort(_('%s command %s') % (data, desc))
984
984
985 def debugcommands(ui, cmd='', *args):
985 def debugcommands(ui, cmd='', *args):
986 """list all available commands and options"""
986 """list all available commands and options"""
987 for cmd, vals in sorted(table.iteritems()):
987 for cmd, vals in sorted(table.iteritems()):
988 cmd = cmd.split('|')[0].strip('^')
988 cmd = cmd.split('|')[0].strip('^')
989 opts = ', '.join([i[1] for i in vals[1]])
989 opts = ', '.join([i[1] for i in vals[1]])
990 ui.write('%s: %s\n' % (cmd, opts))
990 ui.write('%s: %s\n' % (cmd, opts))
991
991
992 def debugcomplete(ui, cmd='', **opts):
992 def debugcomplete(ui, cmd='', **opts):
993 """returns the completion list associated with the given command"""
993 """returns the completion list associated with the given command"""
994
994
995 if opts.get('options'):
995 if opts.get('options'):
996 options = []
996 options = []
997 otables = [globalopts]
997 otables = [globalopts]
998 if cmd:
998 if cmd:
999 aliases, entry = cmdutil.findcmd(cmd, table, False)
999 aliases, entry = cmdutil.findcmd(cmd, table, False)
1000 otables.append(entry[1])
1000 otables.append(entry[1])
1001 for t in otables:
1001 for t in otables:
1002 for o in t:
1002 for o in t:
1003 if "(DEPRECATED)" in o[3]:
1003 if "(DEPRECATED)" in o[3]:
1004 continue
1004 continue
1005 if o[0]:
1005 if o[0]:
1006 options.append('-%s' % o[0])
1006 options.append('-%s' % o[0])
1007 options.append('--%s' % o[1])
1007 options.append('--%s' % o[1])
1008 ui.write("%s\n" % "\n".join(options))
1008 ui.write("%s\n" % "\n".join(options))
1009 return
1009 return
1010
1010
1011 cmdlist = cmdutil.findpossible(cmd, table)
1011 cmdlist = cmdutil.findpossible(cmd, table)
1012 if ui.verbose:
1012 if ui.verbose:
1013 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1013 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1014 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1014 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1015
1015
1016 def debugfsinfo(ui, path = "."):
1016 def debugfsinfo(ui, path = "."):
1017 """show information detected about current filesystem"""
1017 """show information detected about current filesystem"""
1018 open('.debugfsinfo', 'w').write('')
1018 open('.debugfsinfo', 'w').write('')
1019 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1019 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1020 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1020 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1021 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1021 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1022 and 'yes' or 'no'))
1022 and 'yes' or 'no'))
1023 os.unlink('.debugfsinfo')
1023 os.unlink('.debugfsinfo')
1024
1024
1025 def debugrebuildstate(ui, repo, rev="tip"):
1025 def debugrebuildstate(ui, repo, rev="tip"):
1026 """rebuild the dirstate as it would look like for the given revision"""
1026 """rebuild the dirstate as it would look like for the given revision"""
1027 ctx = cmdutil.revsingle(repo, rev)
1027 ctx = cmdutil.revsingle(repo, rev)
1028 wlock = repo.wlock()
1028 wlock = repo.wlock()
1029 try:
1029 try:
1030 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1030 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1031 finally:
1031 finally:
1032 wlock.release()
1032 wlock.release()
1033
1033
1034 def debugcheckstate(ui, repo):
1034 def debugcheckstate(ui, repo):
1035 """validate the correctness of the current dirstate"""
1035 """validate the correctness of the current dirstate"""
1036 parent1, parent2 = repo.dirstate.parents()
1036 parent1, parent2 = repo.dirstate.parents()
1037 m1 = repo[parent1].manifest()
1037 m1 = repo[parent1].manifest()
1038 m2 = repo[parent2].manifest()
1038 m2 = repo[parent2].manifest()
1039 errors = 0
1039 errors = 0
1040 for f in repo.dirstate:
1040 for f in repo.dirstate:
1041 state = repo.dirstate[f]
1041 state = repo.dirstate[f]
1042 if state in "nr" and f not in m1:
1042 if state in "nr" and f not in m1:
1043 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1043 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1044 errors += 1
1044 errors += 1
1045 if state in "a" and f in m1:
1045 if state in "a" and f in m1:
1046 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1046 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1047 errors += 1
1047 errors += 1
1048 if state in "m" and f not in m1 and f not in m2:
1048 if state in "m" and f not in m1 and f not in m2:
1049 ui.warn(_("%s in state %s, but not in either manifest\n") %
1049 ui.warn(_("%s in state %s, but not in either manifest\n") %
1050 (f, state))
1050 (f, state))
1051 errors += 1
1051 errors += 1
1052 for f in m1:
1052 for f in m1:
1053 state = repo.dirstate[f]
1053 state = repo.dirstate[f]
1054 if state not in "nrm":
1054 if state not in "nrm":
1055 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1055 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1056 errors += 1
1056 errors += 1
1057 if errors:
1057 if errors:
1058 error = _(".hg/dirstate inconsistent with current parent's manifest")
1058 error = _(".hg/dirstate inconsistent with current parent's manifest")
1059 raise util.Abort(error)
1059 raise util.Abort(error)
1060
1060
1061 def showconfig(ui, repo, *values, **opts):
1061 def showconfig(ui, repo, *values, **opts):
1062 """show combined config settings from all hgrc files
1062 """show combined config settings from all hgrc files
1063
1063
1064 With no arguments, print names and values of all config items.
1064 With no arguments, print names and values of all config items.
1065
1065
1066 With one argument of the form section.name, print just the value
1066 With one argument of the form section.name, print just the value
1067 of that config item.
1067 of that config item.
1068
1068
1069 With multiple arguments, print names and values of all config
1069 With multiple arguments, print names and values of all config
1070 items with matching section names.
1070 items with matching section names.
1071
1071
1072 With --debug, the source (filename and line number) is printed
1072 With --debug, the source (filename and line number) is printed
1073 for each config item.
1073 for each config item.
1074
1074
1075 Returns 0 on success.
1075 Returns 0 on success.
1076 """
1076 """
1077
1077
1078 for f in util.rcpath():
1078 for f in util.rcpath():
1079 ui.debug(_('read config from: %s\n') % f)
1079 ui.debug(_('read config from: %s\n') % f)
1080 untrusted = bool(opts.get('untrusted'))
1080 untrusted = bool(opts.get('untrusted'))
1081 if values:
1081 if values:
1082 sections = [v for v in values if '.' not in v]
1082 sections = [v for v in values if '.' not in v]
1083 items = [v for v in values if '.' in v]
1083 items = [v for v in values if '.' in v]
1084 if len(items) > 1 or items and sections:
1084 if len(items) > 1 or items and sections:
1085 raise util.Abort(_('only one config item permitted'))
1085 raise util.Abort(_('only one config item permitted'))
1086 for section, name, value in ui.walkconfig(untrusted=untrusted):
1086 for section, name, value in ui.walkconfig(untrusted=untrusted):
1087 sectname = section + '.' + name
1087 sectname = section + '.' + name
1088 if values:
1088 if values:
1089 for v in values:
1089 for v in values:
1090 if v == section:
1090 if v == section:
1091 ui.debug('%s: ' %
1091 ui.debug('%s: ' %
1092 ui.configsource(section, name, untrusted))
1092 ui.configsource(section, name, untrusted))
1093 ui.write('%s=%s\n' % (sectname, value))
1093 ui.write('%s=%s\n' % (sectname, value))
1094 elif v == sectname:
1094 elif v == sectname:
1095 ui.debug('%s: ' %
1095 ui.debug('%s: ' %
1096 ui.configsource(section, name, untrusted))
1096 ui.configsource(section, name, untrusted))
1097 ui.write(value, '\n')
1097 ui.write(value, '\n')
1098 else:
1098 else:
1099 ui.debug('%s: ' %
1099 ui.debug('%s: ' %
1100 ui.configsource(section, name, untrusted))
1100 ui.configsource(section, name, untrusted))
1101 ui.write('%s=%s\n' % (sectname, value))
1101 ui.write('%s=%s\n' % (sectname, value))
1102
1102
1103 def debugpushkey(ui, repopath, namespace, *keyinfo):
1103 def debugpushkey(ui, repopath, namespace, *keyinfo):
1104 '''access the pushkey key/value protocol
1104 '''access the pushkey key/value protocol
1105
1105
1106 With two args, list the keys in the given namespace.
1106 With two args, list the keys in the given namespace.
1107
1107
1108 With five args, set a key to new if it currently is set to old.
1108 With five args, set a key to new if it currently is set to old.
1109 Reports success or failure.
1109 Reports success or failure.
1110 '''
1110 '''
1111
1111
1112 target = hg.repository(ui, repopath)
1112 target = hg.repository(ui, repopath)
1113 if keyinfo:
1113 if keyinfo:
1114 key, old, new = keyinfo
1114 key, old, new = keyinfo
1115 r = target.pushkey(namespace, key, old, new)
1115 r = target.pushkey(namespace, key, old, new)
1116 ui.status(str(r) + '\n')
1116 ui.status(str(r) + '\n')
1117 return not r
1117 return not r
1118 else:
1118 else:
1119 for k, v in target.listkeys(namespace).iteritems():
1119 for k, v in target.listkeys(namespace).iteritems():
1120 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1120 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1121 v.encode('string-escape')))
1121 v.encode('string-escape')))
1122
1122
1123 def debugrevspec(ui, repo, expr):
1123 def debugrevspec(ui, repo, expr):
1124 '''parse and apply a revision specification'''
1124 '''parse and apply a revision specification'''
1125 if ui.verbose:
1125 if ui.verbose:
1126 tree = revset.parse(expr)
1126 tree = revset.parse(expr)
1127 ui.note(tree, "\n")
1127 ui.note(tree, "\n")
1128 func = revset.match(expr)
1128 func = revset.match(expr)
1129 for c in func(repo, range(len(repo))):
1129 for c in func(repo, range(len(repo))):
1130 ui.write("%s\n" % c)
1130 ui.write("%s\n" % c)
1131
1131
1132 def debugsetparents(ui, repo, rev1, rev2=None):
1132 def debugsetparents(ui, repo, rev1, rev2=None):
1133 """manually set the parents of the current working directory
1133 """manually set the parents of the current working directory
1134
1134
1135 This is useful for writing repository conversion tools, but should
1135 This is useful for writing repository conversion tools, but should
1136 be used with care.
1136 be used with care.
1137
1137
1138 Returns 0 on success.
1138 Returns 0 on success.
1139 """
1139 """
1140
1140
1141 r1 = cmdutil.revsingle(repo, rev1).node()
1141 r1 = cmdutil.revsingle(repo, rev1).node()
1142 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1142 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1143
1143
1144 wlock = repo.wlock()
1144 wlock = repo.wlock()
1145 try:
1145 try:
1146 repo.dirstate.setparents(r1, r2)
1146 repo.dirstate.setparents(r1, r2)
1147 finally:
1147 finally:
1148 wlock.release()
1148 wlock.release()
1149
1149
1150 def debugstate(ui, repo, nodates=None):
1150 def debugstate(ui, repo, nodates=None):
1151 """show the contents of the current dirstate"""
1151 """show the contents of the current dirstate"""
1152 timestr = ""
1152 timestr = ""
1153 showdate = not nodates
1153 showdate = not nodates
1154 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1154 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1155 if showdate:
1155 if showdate:
1156 if ent[3] == -1:
1156 if ent[3] == -1:
1157 # Pad or slice to locale representation
1157 # Pad or slice to locale representation
1158 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1158 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1159 time.localtime(0)))
1159 time.localtime(0)))
1160 timestr = 'unset'
1160 timestr = 'unset'
1161 timestr = (timestr[:locale_len] +
1161 timestr = (timestr[:locale_len] +
1162 ' ' * (locale_len - len(timestr)))
1162 ' ' * (locale_len - len(timestr)))
1163 else:
1163 else:
1164 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1164 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1165 time.localtime(ent[3]))
1165 time.localtime(ent[3]))
1166 if ent[1] & 020000:
1166 if ent[1] & 020000:
1167 mode = 'lnk'
1167 mode = 'lnk'
1168 else:
1168 else:
1169 mode = '%3o' % (ent[1] & 0777)
1169 mode = '%3o' % (ent[1] & 0777)
1170 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1170 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1171 for f in repo.dirstate.copies():
1171 for f in repo.dirstate.copies():
1172 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1172 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1173
1173
1174 def debugsub(ui, repo, rev=None):
1174 def debugsub(ui, repo, rev=None):
1175 ctx = cmdutil.revsingle(repo, rev, None)
1175 ctx = cmdutil.revsingle(repo, rev, None)
1176 for k, v in sorted(ctx.substate.items()):
1176 for k, v in sorted(ctx.substate.items()):
1177 ui.write('path %s\n' % k)
1177 ui.write('path %s\n' % k)
1178 ui.write(' source %s\n' % v[0])
1178 ui.write(' source %s\n' % v[0])
1179 ui.write(' revision %s\n' % v[1])
1179 ui.write(' revision %s\n' % v[1])
1180
1180
1181 def debugdag(ui, repo, file_=None, *revs, **opts):
1181 def debugdag(ui, repo, file_=None, *revs, **opts):
1182 """format the changelog or an index DAG as a concise textual description
1182 """format the changelog or an index DAG as a concise textual description
1183
1183
1184 If you pass a revlog index, the revlog's DAG is emitted. If you list
1184 If you pass a revlog index, the revlog's DAG is emitted. If you list
1185 revision numbers, they get labelled in the output as rN.
1185 revision numbers, they get labelled in the output as rN.
1186
1186
1187 Otherwise, the changelog DAG of the current repo is emitted.
1187 Otherwise, the changelog DAG of the current repo is emitted.
1188 """
1188 """
1189 spaces = opts.get('spaces')
1189 spaces = opts.get('spaces')
1190 dots = opts.get('dots')
1190 dots = opts.get('dots')
1191 if file_:
1191 if file_:
1192 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1192 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1193 revs = set((int(r) for r in revs))
1193 revs = set((int(r) for r in revs))
1194 def events():
1194 def events():
1195 for r in rlog:
1195 for r in rlog:
1196 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1196 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1197 if r in revs:
1197 if r in revs:
1198 yield 'l', (r, "r%i" % r)
1198 yield 'l', (r, "r%i" % r)
1199 elif repo:
1199 elif repo:
1200 cl = repo.changelog
1200 cl = repo.changelog
1201 tags = opts.get('tags')
1201 tags = opts.get('tags')
1202 branches = opts.get('branches')
1202 branches = opts.get('branches')
1203 if tags:
1203 if tags:
1204 labels = {}
1204 labels = {}
1205 for l, n in repo.tags().items():
1205 for l, n in repo.tags().items():
1206 labels.setdefault(cl.rev(n), []).append(l)
1206 labels.setdefault(cl.rev(n), []).append(l)
1207 def events():
1207 def events():
1208 b = "default"
1208 b = "default"
1209 for r in cl:
1209 for r in cl:
1210 if branches:
1210 if branches:
1211 newb = cl.read(cl.node(r))[5]['branch']
1211 newb = cl.read(cl.node(r))[5]['branch']
1212 if newb != b:
1212 if newb != b:
1213 yield 'a', newb
1213 yield 'a', newb
1214 b = newb
1214 b = newb
1215 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1215 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1216 if tags:
1216 if tags:
1217 ls = labels.get(r)
1217 ls = labels.get(r)
1218 if ls:
1218 if ls:
1219 for l in ls:
1219 for l in ls:
1220 yield 'l', (r, l)
1220 yield 'l', (r, l)
1221 else:
1221 else:
1222 raise util.Abort(_('need repo for changelog dag'))
1222 raise util.Abort(_('need repo for changelog dag'))
1223
1223
1224 for line in dagparser.dagtextlines(events(),
1224 for line in dagparser.dagtextlines(events(),
1225 addspaces=spaces,
1225 addspaces=spaces,
1226 wraplabels=True,
1226 wraplabels=True,
1227 wrapannotations=True,
1227 wrapannotations=True,
1228 wrapnonlinear=dots,
1228 wrapnonlinear=dots,
1229 usedots=dots,
1229 usedots=dots,
1230 maxlinewidth=70):
1230 maxlinewidth=70):
1231 ui.write(line)
1231 ui.write(line)
1232 ui.write("\n")
1232 ui.write("\n")
1233
1233
1234 def debugdata(ui, repo, file_, rev):
1234 def debugdata(ui, repo, file_, rev):
1235 """dump the contents of a data file revision"""
1235 """dump the contents of a data file revision"""
1236 r = None
1236 r = None
1237 if repo:
1237 if repo:
1238 filelog = repo.file(file_)
1238 filelog = repo.file(file_)
1239 if len(filelog):
1239 if len(filelog):
1240 r = filelog
1240 r = filelog
1241 if not r:
1241 if not r:
1242 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1242 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1243 try:
1243 try:
1244 ui.write(r.revision(r.lookup(rev)))
1244 ui.write(r.revision(r.lookup(rev)))
1245 except KeyError:
1245 except KeyError:
1246 raise util.Abort(_('invalid revision identifier %s') % rev)
1246 raise util.Abort(_('invalid revision identifier %s') % rev)
1247
1247
1248 def debugdate(ui, date, range=None, **opts):
1248 def debugdate(ui, date, range=None, **opts):
1249 """parse and display a date"""
1249 """parse and display a date"""
1250 if opts["extended"]:
1250 if opts["extended"]:
1251 d = util.parsedate(date, util.extendeddateformats)
1251 d = util.parsedate(date, util.extendeddateformats)
1252 else:
1252 else:
1253 d = util.parsedate(date)
1253 d = util.parsedate(date)
1254 ui.write("internal: %s %s\n" % d)
1254 ui.write("internal: %s %s\n" % d)
1255 ui.write("standard: %s\n" % util.datestr(d))
1255 ui.write("standard: %s\n" % util.datestr(d))
1256 if range:
1256 if range:
1257 m = util.matchdate(range)
1257 m = util.matchdate(range)
1258 ui.write("match: %s\n" % m(d[0]))
1258 ui.write("match: %s\n" % m(d[0]))
1259
1259
1260 def debugindex(ui, repo, file_, **opts):
1260 def debugindex(ui, repo, file_, **opts):
1261 """dump the contents of an index file"""
1261 """dump the contents of an index file"""
1262 r = None
1262 r = None
1263 if repo:
1263 if repo:
1264 filelog = repo.file(file_)
1264 filelog = repo.file(file_)
1265 if len(filelog):
1265 if len(filelog):
1266 r = filelog
1266 r = filelog
1267
1267
1268 format = opts.get('format', 0)
1268 format = opts.get('format', 0)
1269 if format not in (0, 1):
1269 if format not in (0, 1):
1270 raise util.Abort("unknown format %d" % format)
1270 raise util.Abort("unknown format %d" % format)
1271
1271
1272 if not r:
1272 if not r:
1273 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1273 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1274
1274
1275 if format == 0:
1275 if format == 0:
1276 ui.write(" rev offset length base linkrev"
1276 ui.write(" rev offset length base linkrev"
1277 " nodeid p1 p2\n")
1277 " nodeid p1 p2\n")
1278 elif format == 1:
1278 elif format == 1:
1279 ui.write(" rev flag offset length"
1279 ui.write(" rev flag offset length"
1280 " size base link p1 p2 nodeid\n")
1280 " size base link p1 p2 nodeid\n")
1281
1281
1282 for i in r:
1282 for i in r:
1283 node = r.node(i)
1283 node = r.node(i)
1284 if format == 0:
1284 if format == 0:
1285 try:
1285 try:
1286 pp = r.parents(node)
1286 pp = r.parents(node)
1287 except:
1287 except:
1288 pp = [nullid, nullid]
1288 pp = [nullid, nullid]
1289 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1289 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1290 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1290 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1291 short(node), short(pp[0]), short(pp[1])))
1291 short(node), short(pp[0]), short(pp[1])))
1292 elif format == 1:
1292 elif format == 1:
1293 pr = r.parentrevs(i)
1293 pr = r.parentrevs(i)
1294 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1294 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1295 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1295 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1296 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1296 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1297
1297
1298 def debugindexdot(ui, repo, file_):
1298 def debugindexdot(ui, repo, file_):
1299 """dump an index DAG as a graphviz dot file"""
1299 """dump an index DAG as a graphviz dot file"""
1300 r = None
1300 r = None
1301 if repo:
1301 if repo:
1302 filelog = repo.file(file_)
1302 filelog = repo.file(file_)
1303 if len(filelog):
1303 if len(filelog):
1304 r = filelog
1304 r = filelog
1305 if not r:
1305 if not r:
1306 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1306 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1307 ui.write("digraph G {\n")
1307 ui.write("digraph G {\n")
1308 for i in r:
1308 for i in r:
1309 node = r.node(i)
1309 node = r.node(i)
1310 pp = r.parents(node)
1310 pp = r.parents(node)
1311 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1311 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1312 if pp[1] != nullid:
1312 if pp[1] != nullid:
1313 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1313 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1314 ui.write("}\n")
1314 ui.write("}\n")
1315
1315
1316 def debuginstall(ui):
1316 def debuginstall(ui):
1317 '''test Mercurial installation
1317 '''test Mercurial installation
1318
1318
1319 Returns 0 on success.
1319 Returns 0 on success.
1320 '''
1320 '''
1321
1321
1322 def writetemp(contents):
1322 def writetemp(contents):
1323 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1323 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1324 f = os.fdopen(fd, "wb")
1324 f = os.fdopen(fd, "wb")
1325 f.write(contents)
1325 f.write(contents)
1326 f.close()
1326 f.close()
1327 return name
1327 return name
1328
1328
1329 problems = 0
1329 problems = 0
1330
1330
1331 # encoding
1331 # encoding
1332 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1332 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1333 try:
1333 try:
1334 encoding.fromlocal("test")
1334 encoding.fromlocal("test")
1335 except util.Abort, inst:
1335 except util.Abort, inst:
1336 ui.write(" %s\n" % inst)
1336 ui.write(" %s\n" % inst)
1337 ui.write(_(" (check that your locale is properly set)\n"))
1337 ui.write(_(" (check that your locale is properly set)\n"))
1338 problems += 1
1338 problems += 1
1339
1339
1340 # compiled modules
1340 # compiled modules
1341 ui.status(_("Checking installed modules (%s)...\n")
1341 ui.status(_("Checking installed modules (%s)...\n")
1342 % os.path.dirname(__file__))
1342 % os.path.dirname(__file__))
1343 try:
1343 try:
1344 import bdiff, mpatch, base85, osutil
1344 import bdiff, mpatch, base85, osutil
1345 except Exception, inst:
1345 except Exception, inst:
1346 ui.write(" %s\n" % inst)
1346 ui.write(" %s\n" % inst)
1347 ui.write(_(" One or more extensions could not be found"))
1347 ui.write(_(" One or more extensions could not be found"))
1348 ui.write(_(" (check that you compiled the extensions)\n"))
1348 ui.write(_(" (check that you compiled the extensions)\n"))
1349 problems += 1
1349 problems += 1
1350
1350
1351 # templates
1351 # templates
1352 ui.status(_("Checking templates...\n"))
1352 ui.status(_("Checking templates...\n"))
1353 try:
1353 try:
1354 import templater
1354 import templater
1355 templater.templater(templater.templatepath("map-cmdline.default"))
1355 templater.templater(templater.templatepath("map-cmdline.default"))
1356 except Exception, inst:
1356 except Exception, inst:
1357 ui.write(" %s\n" % inst)
1357 ui.write(" %s\n" % inst)
1358 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1358 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1359 problems += 1
1359 problems += 1
1360
1360
1361 # patch
1361 # patch
1362 ui.status(_("Checking patch...\n"))
1362 ui.status(_("Checking patch...\n"))
1363 patchproblems = 0
1363 patchproblems = 0
1364 a = "1\n2\n3\n4\n"
1364 a = "1\n2\n3\n4\n"
1365 b = "1\n2\n3\ninsert\n4\n"
1365 b = "1\n2\n3\ninsert\n4\n"
1366 fa = writetemp(a)
1366 fa = writetemp(a)
1367 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1367 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1368 os.path.basename(fa))
1368 os.path.basename(fa))
1369 fd = writetemp(d)
1369 fd = writetemp(d)
1370
1370
1371 files = {}
1371 files = {}
1372 try:
1372 try:
1373 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1373 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1374 except util.Abort, e:
1374 except util.Abort, e:
1375 ui.write(_(" patch call failed:\n"))
1375 ui.write(_(" patch call failed:\n"))
1376 ui.write(" " + str(e) + "\n")
1376 ui.write(" " + str(e) + "\n")
1377 patchproblems += 1
1377 patchproblems += 1
1378 else:
1378 else:
1379 if list(files) != [os.path.basename(fa)]:
1379 if list(files) != [os.path.basename(fa)]:
1380 ui.write(_(" unexpected patch output!\n"))
1380 ui.write(_(" unexpected patch output!\n"))
1381 patchproblems += 1
1381 patchproblems += 1
1382 a = open(fa).read()
1382 a = open(fa).read()
1383 if a != b:
1383 if a != b:
1384 ui.write(_(" patch test failed!\n"))
1384 ui.write(_(" patch test failed!\n"))
1385 patchproblems += 1
1385 patchproblems += 1
1386
1386
1387 if patchproblems:
1387 if patchproblems:
1388 if ui.config('ui', 'patch'):
1388 if ui.config('ui', 'patch'):
1389 ui.write(_(" (Current patch tool may be incompatible with patch,"
1389 ui.write(_(" (Current patch tool may be incompatible with patch,"
1390 " or misconfigured. Please check your configuration"
1390 " or misconfigured. Please check your configuration"
1391 " file)\n"))
1391 " file)\n"))
1392 else:
1392 else:
1393 ui.write(_(" Internal patcher failure, please report this error"
1393 ui.write(_(" Internal patcher failure, please report this error"
1394 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1394 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1395 problems += patchproblems
1395 problems += patchproblems
1396
1396
1397 os.unlink(fa)
1397 os.unlink(fa)
1398 os.unlink(fd)
1398 os.unlink(fd)
1399
1399
1400 # editor
1400 # editor
1401 ui.status(_("Checking commit editor...\n"))
1401 ui.status(_("Checking commit editor...\n"))
1402 editor = ui.geteditor()
1402 editor = ui.geteditor()
1403 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1403 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1404 if not cmdpath:
1404 if not cmdpath:
1405 if editor == 'vi':
1405 if editor == 'vi':
1406 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1406 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1407 ui.write(_(" (specify a commit editor in your configuration"
1407 ui.write(_(" (specify a commit editor in your configuration"
1408 " file)\n"))
1408 " file)\n"))
1409 else:
1409 else:
1410 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1410 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1411 ui.write(_(" (specify a commit editor in your configuration"
1411 ui.write(_(" (specify a commit editor in your configuration"
1412 " file)\n"))
1412 " file)\n"))
1413 problems += 1
1413 problems += 1
1414
1414
1415 # check username
1415 # check username
1416 ui.status(_("Checking username...\n"))
1416 ui.status(_("Checking username...\n"))
1417 try:
1417 try:
1418 ui.username()
1418 ui.username()
1419 except util.Abort, e:
1419 except util.Abort, e:
1420 ui.write(" %s\n" % e)
1420 ui.write(" %s\n" % e)
1421 ui.write(_(" (specify a username in your configuration file)\n"))
1421 ui.write(_(" (specify a username in your configuration file)\n"))
1422 problems += 1
1422 problems += 1
1423
1423
1424 if not problems:
1424 if not problems:
1425 ui.status(_("No problems detected\n"))
1425 ui.status(_("No problems detected\n"))
1426 else:
1426 else:
1427 ui.write(_("%s problems detected,"
1427 ui.write(_("%s problems detected,"
1428 " please check your install!\n") % problems)
1428 " please check your install!\n") % problems)
1429
1429
1430 return problems
1430 return problems
1431
1431
1432 def debugrename(ui, repo, file1, *pats, **opts):
1432 def debugrename(ui, repo, file1, *pats, **opts):
1433 """dump rename information"""
1433 """dump rename information"""
1434
1434
1435 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1435 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1436 m = cmdutil.match(repo, (file1,) + pats, opts)
1436 m = cmdutil.match(repo, (file1,) + pats, opts)
1437 for abs in ctx.walk(m):
1437 for abs in ctx.walk(m):
1438 fctx = ctx[abs]
1438 fctx = ctx[abs]
1439 o = fctx.filelog().renamed(fctx.filenode())
1439 o = fctx.filelog().renamed(fctx.filenode())
1440 rel = m.rel(abs)
1440 rel = m.rel(abs)
1441 if o:
1441 if o:
1442 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1442 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1443 else:
1443 else:
1444 ui.write(_("%s not renamed\n") % rel)
1444 ui.write(_("%s not renamed\n") % rel)
1445
1445
1446 def debugwalk(ui, repo, *pats, **opts):
1446 def debugwalk(ui, repo, *pats, **opts):
1447 """show how files match on given patterns"""
1447 """show how files match on given patterns"""
1448 m = cmdutil.match(repo, pats, opts)
1448 m = cmdutil.match(repo, pats, opts)
1449 items = list(repo.walk(m))
1449 items = list(repo.walk(m))
1450 if not items:
1450 if not items:
1451 return
1451 return
1452 fmt = 'f %%-%ds %%-%ds %%s' % (
1452 fmt = 'f %%-%ds %%-%ds %%s' % (
1453 max([len(abs) for abs in items]),
1453 max([len(abs) for abs in items]),
1454 max([len(m.rel(abs)) for abs in items]))
1454 max([len(m.rel(abs)) for abs in items]))
1455 for abs in items:
1455 for abs in items:
1456 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1456 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1457 ui.write("%s\n" % line.rstrip())
1457 ui.write("%s\n" % line.rstrip())
1458
1458
1459 def diff(ui, repo, *pats, **opts):
1459 def diff(ui, repo, *pats, **opts):
1460 """diff repository (or selected files)
1460 """diff repository (or selected files)
1461
1461
1462 Show differences between revisions for the specified files.
1462 Show differences between revisions for the specified files.
1463
1463
1464 Differences between files are shown using the unified diff format.
1464 Differences between files are shown using the unified diff format.
1465
1465
1466 .. note::
1466 .. note::
1467 diff may generate unexpected results for merges, as it will
1467 diff may generate unexpected results for merges, as it will
1468 default to comparing against the working directory's first
1468 default to comparing against the working directory's first
1469 parent changeset if no revisions are specified.
1469 parent changeset if no revisions are specified.
1470
1470
1471 When two revision arguments are given, then changes are shown
1471 When two revision arguments are given, then changes are shown
1472 between those revisions. If only one revision is specified then
1472 between those revisions. If only one revision is specified then
1473 that revision is compared to the working directory, and, when no
1473 that revision is compared to the working directory, and, when no
1474 revisions are specified, the working directory files are compared
1474 revisions are specified, the working directory files are compared
1475 to its parent.
1475 to its parent.
1476
1476
1477 Alternatively you can specify -c/--change with a revision to see
1477 Alternatively you can specify -c/--change with a revision to see
1478 the changes in that changeset relative to its first parent.
1478 the changes in that changeset relative to its first parent.
1479
1479
1480 Without the -a/--text option, diff will avoid generating diffs of
1480 Without the -a/--text option, diff will avoid generating diffs of
1481 files it detects as binary. With -a, diff will generate a diff
1481 files it detects as binary. With -a, diff will generate a diff
1482 anyway, probably with undesirable results.
1482 anyway, probably with undesirable results.
1483
1483
1484 Use the -g/--git option to generate diffs in the git extended diff
1484 Use the -g/--git option to generate diffs in the git extended diff
1485 format. For more information, read :hg:`help diffs`.
1485 format. For more information, read :hg:`help diffs`.
1486
1486
1487 Returns 0 on success.
1487 Returns 0 on success.
1488 """
1488 """
1489
1489
1490 revs = opts.get('rev')
1490 revs = opts.get('rev')
1491 change = opts.get('change')
1491 change = opts.get('change')
1492 stat = opts.get('stat')
1492 stat = opts.get('stat')
1493 reverse = opts.get('reverse')
1493 reverse = opts.get('reverse')
1494
1494
1495 if revs and change:
1495 if revs and change:
1496 msg = _('cannot specify --rev and --change at the same time')
1496 msg = _('cannot specify --rev and --change at the same time')
1497 raise util.Abort(msg)
1497 raise util.Abort(msg)
1498 elif change:
1498 elif change:
1499 node2 = repo.lookup(change)
1499 node2 = repo.lookup(change)
1500 node1 = repo[node2].parents()[0].node()
1500 node1 = repo[node2].parents()[0].node()
1501 else:
1501 else:
1502 node1, node2 = cmdutil.revpair(repo, revs)
1502 node1, node2 = cmdutil.revpair(repo, revs)
1503
1503
1504 if reverse:
1504 if reverse:
1505 node1, node2 = node2, node1
1505 node1, node2 = node2, node1
1506
1506
1507 diffopts = patch.diffopts(ui, opts)
1507 diffopts = patch.diffopts(ui, opts)
1508 m = cmdutil.match(repo, pats, opts)
1508 m = cmdutil.match(repo, pats, opts)
1509 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1509 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1510 listsubrepos=opts.get('subrepos'))
1510 listsubrepos=opts.get('subrepos'))
1511
1511
1512 def export(ui, repo, *changesets, **opts):
1512 def export(ui, repo, *changesets, **opts):
1513 """dump the header and diffs for one or more changesets
1513 """dump the header and diffs for one or more changesets
1514
1514
1515 Print the changeset header and diffs for one or more revisions.
1515 Print the changeset header and diffs for one or more revisions.
1516
1516
1517 The information shown in the changeset header is: author, date,
1517 The information shown in the changeset header is: author, date,
1518 branch name (if non-default), changeset hash, parent(s) and commit
1518 branch name (if non-default), changeset hash, parent(s) and commit
1519 comment.
1519 comment.
1520
1520
1521 .. note::
1521 .. note::
1522 export may generate unexpected diff output for merge
1522 export may generate unexpected diff output for merge
1523 changesets, as it will compare the merge changeset against its
1523 changesets, as it will compare the merge changeset against its
1524 first parent only.
1524 first parent only.
1525
1525
1526 Output may be to a file, in which case the name of the file is
1526 Output may be to a file, in which case the name of the file is
1527 given using a format string. The formatting rules are as follows:
1527 given using a format string. The formatting rules are as follows:
1528
1528
1529 :``%%``: literal "%" character
1529 :``%%``: literal "%" character
1530 :``%H``: changeset hash (40 hexadecimal digits)
1530 :``%H``: changeset hash (40 hexadecimal digits)
1531 :``%N``: number of patches being generated
1531 :``%N``: number of patches being generated
1532 :``%R``: changeset revision number
1532 :``%R``: changeset revision number
1533 :``%b``: basename of the exporting repository
1533 :``%b``: basename of the exporting repository
1534 :``%h``: short-form changeset hash (12 hexadecimal digits)
1534 :``%h``: short-form changeset hash (12 hexadecimal digits)
1535 :``%n``: zero-padded sequence number, starting at 1
1535 :``%n``: zero-padded sequence number, starting at 1
1536 :``%r``: zero-padded changeset revision number
1536 :``%r``: zero-padded changeset revision number
1537
1537
1538 Without the -a/--text option, export will avoid generating diffs
1538 Without the -a/--text option, export will avoid generating diffs
1539 of files it detects as binary. With -a, export will generate a
1539 of files it detects as binary. With -a, export will generate a
1540 diff anyway, probably with undesirable results.
1540 diff anyway, probably with undesirable results.
1541
1541
1542 Use the -g/--git option to generate diffs in the git extended diff
1542 Use the -g/--git option to generate diffs in the git extended diff
1543 format. See :hg:`help diffs` for more information.
1543 format. See :hg:`help diffs` for more information.
1544
1544
1545 With the --switch-parent option, the diff will be against the
1545 With the --switch-parent option, the diff will be against the
1546 second parent. It can be useful to review a merge.
1546 second parent. It can be useful to review a merge.
1547
1547
1548 Returns 0 on success.
1548 Returns 0 on success.
1549 """
1549 """
1550 changesets += tuple(opts.get('rev', []))
1550 changesets += tuple(opts.get('rev', []))
1551 if not changesets:
1551 if not changesets:
1552 raise util.Abort(_("export requires at least one changeset"))
1552 raise util.Abort(_("export requires at least one changeset"))
1553 revs = cmdutil.revrange(repo, changesets)
1553 revs = cmdutil.revrange(repo, changesets)
1554 if len(revs) > 1:
1554 if len(revs) > 1:
1555 ui.note(_('exporting patches:\n'))
1555 ui.note(_('exporting patches:\n'))
1556 else:
1556 else:
1557 ui.note(_('exporting patch:\n'))
1557 ui.note(_('exporting patch:\n'))
1558 cmdutil.export(repo, revs, template=opts.get('output'),
1558 cmdutil.export(repo, revs, template=opts.get('output'),
1559 switch_parent=opts.get('switch_parent'),
1559 switch_parent=opts.get('switch_parent'),
1560 opts=patch.diffopts(ui, opts))
1560 opts=patch.diffopts(ui, opts))
1561
1561
1562 def forget(ui, repo, *pats, **opts):
1562 def forget(ui, repo, *pats, **opts):
1563 """forget the specified files on the next commit
1563 """forget the specified files on the next commit
1564
1564
1565 Mark the specified files so they will no longer be tracked
1565 Mark the specified files so they will no longer be tracked
1566 after the next commit.
1566 after the next commit.
1567
1567
1568 This only removes files from the current branch, not from the
1568 This only removes files from the current branch, not from the
1569 entire project history, and it does not delete them from the
1569 entire project history, and it does not delete them from the
1570 working directory.
1570 working directory.
1571
1571
1572 To undo a forget before the next commit, see :hg:`add`.
1572 To undo a forget before the next commit, see :hg:`add`.
1573
1573
1574 Returns 0 on success.
1574 Returns 0 on success.
1575 """
1575 """
1576
1576
1577 if not pats:
1577 if not pats:
1578 raise util.Abort(_('no files specified'))
1578 raise util.Abort(_('no files specified'))
1579
1579
1580 m = cmdutil.match(repo, pats, opts)
1580 m = cmdutil.match(repo, pats, opts)
1581 s = repo.status(match=m, clean=True)
1581 s = repo.status(match=m, clean=True)
1582 forget = sorted(s[0] + s[1] + s[3] + s[6])
1582 forget = sorted(s[0] + s[1] + s[3] + s[6])
1583 errs = 0
1583 errs = 0
1584
1584
1585 for f in m.files():
1585 for f in m.files():
1586 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1586 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1587 ui.warn(_('not removing %s: file is already untracked\n')
1587 ui.warn(_('not removing %s: file is already untracked\n')
1588 % m.rel(f))
1588 % m.rel(f))
1589 errs = 1
1589 errs = 1
1590
1590
1591 for f in forget:
1591 for f in forget:
1592 if ui.verbose or not m.exact(f):
1592 if ui.verbose or not m.exact(f):
1593 ui.status(_('removing %s\n') % m.rel(f))
1593 ui.status(_('removing %s\n') % m.rel(f))
1594
1594
1595 repo[None].remove(forget, unlink=False)
1595 repo[None].remove(forget, unlink=False)
1596 return errs
1596 return errs
1597
1597
1598 def grep(ui, repo, pattern, *pats, **opts):
1598 def grep(ui, repo, pattern, *pats, **opts):
1599 """search for a pattern in specified files and revisions
1599 """search for a pattern in specified files and revisions
1600
1600
1601 Search revisions of files for a regular expression.
1601 Search revisions of files for a regular expression.
1602
1602
1603 This command behaves differently than Unix grep. It only accepts
1603 This command behaves differently than Unix grep. It only accepts
1604 Python/Perl regexps. It searches repository history, not the
1604 Python/Perl regexps. It searches repository history, not the
1605 working directory. It always prints the revision number in which a
1605 working directory. It always prints the revision number in which a
1606 match appears.
1606 match appears.
1607
1607
1608 By default, grep only prints output for the first revision of a
1608 By default, grep only prints output for the first revision of a
1609 file in which it finds a match. To get it to print every revision
1609 file in which it finds a match. To get it to print every revision
1610 that contains a change in match status ("-" for a match that
1610 that contains a change in match status ("-" for a match that
1611 becomes a non-match, or "+" for a non-match that becomes a match),
1611 becomes a non-match, or "+" for a non-match that becomes a match),
1612 use the --all flag.
1612 use the --all flag.
1613
1613
1614 Returns 0 if a match is found, 1 otherwise.
1614 Returns 0 if a match is found, 1 otherwise.
1615 """
1615 """
1616 reflags = 0
1616 reflags = 0
1617 if opts.get('ignore_case'):
1617 if opts.get('ignore_case'):
1618 reflags |= re.I
1618 reflags |= re.I
1619 try:
1619 try:
1620 regexp = re.compile(pattern, reflags)
1620 regexp = re.compile(pattern, reflags)
1621 except re.error, inst:
1621 except re.error, inst:
1622 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1622 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1623 return 1
1623 return 1
1624 sep, eol = ':', '\n'
1624 sep, eol = ':', '\n'
1625 if opts.get('print0'):
1625 if opts.get('print0'):
1626 sep = eol = '\0'
1626 sep = eol = '\0'
1627
1627
1628 getfile = util.lrucachefunc(repo.file)
1628 getfile = util.lrucachefunc(repo.file)
1629
1629
1630 def matchlines(body):
1630 def matchlines(body):
1631 begin = 0
1631 begin = 0
1632 linenum = 0
1632 linenum = 0
1633 while True:
1633 while True:
1634 match = regexp.search(body, begin)
1634 match = regexp.search(body, begin)
1635 if not match:
1635 if not match:
1636 break
1636 break
1637 mstart, mend = match.span()
1637 mstart, mend = match.span()
1638 linenum += body.count('\n', begin, mstart) + 1
1638 linenum += body.count('\n', begin, mstart) + 1
1639 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1639 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1640 begin = body.find('\n', mend) + 1 or len(body)
1640 begin = body.find('\n', mend) + 1 or len(body)
1641 lend = begin - 1
1641 lend = begin - 1
1642 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1642 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1643
1643
1644 class linestate(object):
1644 class linestate(object):
1645 def __init__(self, line, linenum, colstart, colend):
1645 def __init__(self, line, linenum, colstart, colend):
1646 self.line = line
1646 self.line = line
1647 self.linenum = linenum
1647 self.linenum = linenum
1648 self.colstart = colstart
1648 self.colstart = colstart
1649 self.colend = colend
1649 self.colend = colend
1650
1650
1651 def __hash__(self):
1651 def __hash__(self):
1652 return hash((self.linenum, self.line))
1652 return hash((self.linenum, self.line))
1653
1653
1654 def __eq__(self, other):
1654 def __eq__(self, other):
1655 return self.line == other.line
1655 return self.line == other.line
1656
1656
1657 matches = {}
1657 matches = {}
1658 copies = {}
1658 copies = {}
1659 def grepbody(fn, rev, body):
1659 def grepbody(fn, rev, body):
1660 matches[rev].setdefault(fn, [])
1660 matches[rev].setdefault(fn, [])
1661 m = matches[rev][fn]
1661 m = matches[rev][fn]
1662 for lnum, cstart, cend, line in matchlines(body):
1662 for lnum, cstart, cend, line in matchlines(body):
1663 s = linestate(line, lnum, cstart, cend)
1663 s = linestate(line, lnum, cstart, cend)
1664 m.append(s)
1664 m.append(s)
1665
1665
1666 def difflinestates(a, b):
1666 def difflinestates(a, b):
1667 sm = difflib.SequenceMatcher(None, a, b)
1667 sm = difflib.SequenceMatcher(None, a, b)
1668 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1668 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1669 if tag == 'insert':
1669 if tag == 'insert':
1670 for i in xrange(blo, bhi):
1670 for i in xrange(blo, bhi):
1671 yield ('+', b[i])
1671 yield ('+', b[i])
1672 elif tag == 'delete':
1672 elif tag == 'delete':
1673 for i in xrange(alo, ahi):
1673 for i in xrange(alo, ahi):
1674 yield ('-', a[i])
1674 yield ('-', a[i])
1675 elif tag == 'replace':
1675 elif tag == 'replace':
1676 for i in xrange(alo, ahi):
1676 for i in xrange(alo, ahi):
1677 yield ('-', a[i])
1677 yield ('-', a[i])
1678 for i in xrange(blo, bhi):
1678 for i in xrange(blo, bhi):
1679 yield ('+', b[i])
1679 yield ('+', b[i])
1680
1680
1681 def display(fn, ctx, pstates, states):
1681 def display(fn, ctx, pstates, states):
1682 rev = ctx.rev()
1682 rev = ctx.rev()
1683 datefunc = ui.quiet and util.shortdate or util.datestr
1683 datefunc = ui.quiet and util.shortdate or util.datestr
1684 found = False
1684 found = False
1685 filerevmatches = {}
1685 filerevmatches = {}
1686 if opts.get('all'):
1686 if opts.get('all'):
1687 iter = difflinestates(pstates, states)
1687 iter = difflinestates(pstates, states)
1688 else:
1688 else:
1689 iter = [('', l) for l in states]
1689 iter = [('', l) for l in states]
1690 for change, l in iter:
1690 for change, l in iter:
1691 cols = [fn, str(rev)]
1691 cols = [fn, str(rev)]
1692 before, match, after = None, None, None
1692 before, match, after = None, None, None
1693 if opts.get('line_number'):
1693 if opts.get('line_number'):
1694 cols.append(str(l.linenum))
1694 cols.append(str(l.linenum))
1695 if opts.get('all'):
1695 if opts.get('all'):
1696 cols.append(change)
1696 cols.append(change)
1697 if opts.get('user'):
1697 if opts.get('user'):
1698 cols.append(ui.shortuser(ctx.user()))
1698 cols.append(ui.shortuser(ctx.user()))
1699 if opts.get('date'):
1699 if opts.get('date'):
1700 cols.append(datefunc(ctx.date()))
1700 cols.append(datefunc(ctx.date()))
1701 if opts.get('files_with_matches'):
1701 if opts.get('files_with_matches'):
1702 c = (fn, rev)
1702 c = (fn, rev)
1703 if c in filerevmatches:
1703 if c in filerevmatches:
1704 continue
1704 continue
1705 filerevmatches[c] = 1
1705 filerevmatches[c] = 1
1706 else:
1706 else:
1707 before = l.line[:l.colstart]
1707 before = l.line[:l.colstart]
1708 match = l.line[l.colstart:l.colend]
1708 match = l.line[l.colstart:l.colend]
1709 after = l.line[l.colend:]
1709 after = l.line[l.colend:]
1710 ui.write(sep.join(cols))
1710 ui.write(sep.join(cols))
1711 if before is not None:
1711 if before is not None:
1712 ui.write(sep + before)
1712 ui.write(sep + before)
1713 ui.write(match, label='grep.match')
1713 ui.write(match, label='grep.match')
1714 ui.write(after)
1714 ui.write(after)
1715 ui.write(eol)
1715 ui.write(eol)
1716 found = True
1716 found = True
1717 return found
1717 return found
1718
1718
1719 skip = {}
1719 skip = {}
1720 revfiles = {}
1720 revfiles = {}
1721 matchfn = cmdutil.match(repo, pats, opts)
1721 matchfn = cmdutil.match(repo, pats, opts)
1722 found = False
1722 found = False
1723 follow = opts.get('follow')
1723 follow = opts.get('follow')
1724
1724
1725 def prep(ctx, fns):
1725 def prep(ctx, fns):
1726 rev = ctx.rev()
1726 rev = ctx.rev()
1727 pctx = ctx.parents()[0]
1727 pctx = ctx.parents()[0]
1728 parent = pctx.rev()
1728 parent = pctx.rev()
1729 matches.setdefault(rev, {})
1729 matches.setdefault(rev, {})
1730 matches.setdefault(parent, {})
1730 matches.setdefault(parent, {})
1731 files = revfiles.setdefault(rev, [])
1731 files = revfiles.setdefault(rev, [])
1732 for fn in fns:
1732 for fn in fns:
1733 flog = getfile(fn)
1733 flog = getfile(fn)
1734 try:
1734 try:
1735 fnode = ctx.filenode(fn)
1735 fnode = ctx.filenode(fn)
1736 except error.LookupError:
1736 except error.LookupError:
1737 continue
1737 continue
1738
1738
1739 copied = flog.renamed(fnode)
1739 copied = flog.renamed(fnode)
1740 copy = follow and copied and copied[0]
1740 copy = follow and copied and copied[0]
1741 if copy:
1741 if copy:
1742 copies.setdefault(rev, {})[fn] = copy
1742 copies.setdefault(rev, {})[fn] = copy
1743 if fn in skip:
1743 if fn in skip:
1744 if copy:
1744 if copy:
1745 skip[copy] = True
1745 skip[copy] = True
1746 continue
1746 continue
1747 files.append(fn)
1747 files.append(fn)
1748
1748
1749 if fn not in matches[rev]:
1749 if fn not in matches[rev]:
1750 grepbody(fn, rev, flog.read(fnode))
1750 grepbody(fn, rev, flog.read(fnode))
1751
1751
1752 pfn = copy or fn
1752 pfn = copy or fn
1753 if pfn not in matches[parent]:
1753 if pfn not in matches[parent]:
1754 try:
1754 try:
1755 fnode = pctx.filenode(pfn)
1755 fnode = pctx.filenode(pfn)
1756 grepbody(pfn, parent, flog.read(fnode))
1756 grepbody(pfn, parent, flog.read(fnode))
1757 except error.LookupError:
1757 except error.LookupError:
1758 pass
1758 pass
1759
1759
1760 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1760 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1761 rev = ctx.rev()
1761 rev = ctx.rev()
1762 parent = ctx.parents()[0].rev()
1762 parent = ctx.parents()[0].rev()
1763 for fn in sorted(revfiles.get(rev, [])):
1763 for fn in sorted(revfiles.get(rev, [])):
1764 states = matches[rev][fn]
1764 states = matches[rev][fn]
1765 copy = copies.get(rev, {}).get(fn)
1765 copy = copies.get(rev, {}).get(fn)
1766 if fn in skip:
1766 if fn in skip:
1767 if copy:
1767 if copy:
1768 skip[copy] = True
1768 skip[copy] = True
1769 continue
1769 continue
1770 pstates = matches.get(parent, {}).get(copy or fn, [])
1770 pstates = matches.get(parent, {}).get(copy or fn, [])
1771 if pstates or states:
1771 if pstates or states:
1772 r = display(fn, ctx, pstates, states)
1772 r = display(fn, ctx, pstates, states)
1773 found = found or r
1773 found = found or r
1774 if r and not opts.get('all'):
1774 if r and not opts.get('all'):
1775 skip[fn] = True
1775 skip[fn] = True
1776 if copy:
1776 if copy:
1777 skip[copy] = True
1777 skip[copy] = True
1778 del matches[rev]
1778 del matches[rev]
1779 del revfiles[rev]
1779 del revfiles[rev]
1780
1780
1781 return not found
1781 return not found
1782
1782
1783 def heads(ui, repo, *branchrevs, **opts):
1783 def heads(ui, repo, *branchrevs, **opts):
1784 """show current repository heads or show branch heads
1784 """show current repository heads or show branch heads
1785
1785
1786 With no arguments, show all repository branch heads.
1786 With no arguments, show all repository branch heads.
1787
1787
1788 Repository "heads" are changesets with no child changesets. They are
1788 Repository "heads" are changesets with no child changesets. They are
1789 where development generally takes place and are the usual targets
1789 where development generally takes place and are the usual targets
1790 for update and merge operations. Branch heads are changesets that have
1790 for update and merge operations. Branch heads are changesets that have
1791 no child changeset on the same branch.
1791 no child changeset on the same branch.
1792
1792
1793 If one or more REVs are given, only branch heads on the branches
1793 If one or more REVs are given, only branch heads on the branches
1794 associated with the specified changesets are shown.
1794 associated with the specified changesets are shown.
1795
1795
1796 If -c/--closed is specified, also show branch heads marked closed
1796 If -c/--closed is specified, also show branch heads marked closed
1797 (see :hg:`commit --close-branch`).
1797 (see :hg:`commit --close-branch`).
1798
1798
1799 If STARTREV is specified, only those heads that are descendants of
1799 If STARTREV is specified, only those heads that are descendants of
1800 STARTREV will be displayed.
1800 STARTREV will be displayed.
1801
1801
1802 If -t/--topo is specified, named branch mechanics will be ignored and only
1802 If -t/--topo is specified, named branch mechanics will be ignored and only
1803 changesets without children will be shown.
1803 changesets without children will be shown.
1804
1804
1805 Returns 0 if matching heads are found, 1 if not.
1805 Returns 0 if matching heads are found, 1 if not.
1806 """
1806 """
1807
1807
1808 start = None
1808 start = None
1809 if 'rev' in opts:
1809 if 'rev' in opts:
1810 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1810 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1811
1811
1812 if opts.get('topo'):
1812 if opts.get('topo'):
1813 heads = [repo[h] for h in repo.heads(start)]
1813 heads = [repo[h] for h in repo.heads(start)]
1814 else:
1814 else:
1815 heads = []
1815 heads = []
1816 for b, ls in repo.branchmap().iteritems():
1816 for b, ls in repo.branchmap().iteritems():
1817 if start is None:
1817 if start is None:
1818 heads += [repo[h] for h in ls]
1818 heads += [repo[h] for h in ls]
1819 continue
1819 continue
1820 startrev = repo.changelog.rev(start)
1820 startrev = repo.changelog.rev(start)
1821 descendants = set(repo.changelog.descendants(startrev))
1821 descendants = set(repo.changelog.descendants(startrev))
1822 descendants.add(startrev)
1822 descendants.add(startrev)
1823 rev = repo.changelog.rev
1823 rev = repo.changelog.rev
1824 heads += [repo[h] for h in ls if rev(h) in descendants]
1824 heads += [repo[h] for h in ls if rev(h) in descendants]
1825
1825
1826 if branchrevs:
1826 if branchrevs:
1827 branches = set(repo[br].branch() for br in branchrevs)
1827 branches = set(repo[br].branch() for br in branchrevs)
1828 heads = [h for h in heads if h.branch() in branches]
1828 heads = [h for h in heads if h.branch() in branches]
1829
1829
1830 if not opts.get('closed'):
1830 if not opts.get('closed'):
1831 heads = [h for h in heads if not h.extra().get('close')]
1831 heads = [h for h in heads if not h.extra().get('close')]
1832
1832
1833 if opts.get('active') and branchrevs:
1833 if opts.get('active') and branchrevs:
1834 dagheads = repo.heads(start)
1834 dagheads = repo.heads(start)
1835 heads = [h for h in heads if h.node() in dagheads]
1835 heads = [h for h in heads if h.node() in dagheads]
1836
1836
1837 if branchrevs:
1837 if branchrevs:
1838 haveheads = set(h.branch() for h in heads)
1838 haveheads = set(h.branch() for h in heads)
1839 if branches - haveheads:
1839 if branches - haveheads:
1840 headless = ', '.join(b for b in branches - haveheads)
1840 headless = ', '.join(b for b in branches - haveheads)
1841 msg = _('no open branch heads found on branches %s')
1841 msg = _('no open branch heads found on branches %s')
1842 if opts.get('rev'):
1842 if opts.get('rev'):
1843 msg += _(' (started at %s)' % opts['rev'])
1843 msg += _(' (started at %s)' % opts['rev'])
1844 ui.warn((msg + '\n') % headless)
1844 ui.warn((msg + '\n') % headless)
1845
1845
1846 if not heads:
1846 if not heads:
1847 return 1
1847 return 1
1848
1848
1849 heads = sorted(heads, key=lambda x: -x.rev())
1849 heads = sorted(heads, key=lambda x: -x.rev())
1850 displayer = cmdutil.show_changeset(ui, repo, opts)
1850 displayer = cmdutil.show_changeset(ui, repo, opts)
1851 for ctx in heads:
1851 for ctx in heads:
1852 displayer.show(ctx)
1852 displayer.show(ctx)
1853 displayer.close()
1853 displayer.close()
1854
1854
1855 def help_(ui, name=None, with_version=False, unknowncmd=False):
1855 def help_(ui, name=None, with_version=False, unknowncmd=False):
1856 """show help for a given topic or a help overview
1856 """show help for a given topic or a help overview
1857
1857
1858 With no arguments, print a list of commands with short help messages.
1858 With no arguments, print a list of commands with short help messages.
1859
1859
1860 Given a topic, extension, or command name, print help for that
1860 Given a topic, extension, or command name, print help for that
1861 topic.
1861 topic.
1862
1862
1863 Returns 0 if successful.
1863 Returns 0 if successful.
1864 """
1864 """
1865 option_lists = []
1865 option_lists = []
1866 textwidth = ui.termwidth() - 2
1866 textwidth = ui.termwidth() - 2
1867
1867
1868 def addglobalopts(aliases):
1868 def addglobalopts(aliases):
1869 if ui.verbose:
1869 if ui.verbose:
1870 option_lists.append((_("global options:"), globalopts))
1870 option_lists.append((_("global options:"), globalopts))
1871 if name == 'shortlist':
1871 if name == 'shortlist':
1872 option_lists.append((_('use "hg help" for the full list '
1872 option_lists.append((_('use "hg help" for the full list '
1873 'of commands'), ()))
1873 'of commands'), ()))
1874 else:
1874 else:
1875 if name == 'shortlist':
1875 if name == 'shortlist':
1876 msg = _('use "hg help" for the full list of commands '
1876 msg = _('use "hg help" for the full list of commands '
1877 'or "hg -v" for details')
1877 'or "hg -v" for details')
1878 elif aliases:
1878 elif aliases:
1879 msg = _('use "hg -v help%s" to show builtin aliases and '
1879 msg = _('use "hg -v help%s" to show builtin aliases and '
1880 'global options') % (name and " " + name or "")
1880 'global options') % (name and " " + name or "")
1881 else:
1881 else:
1882 msg = _('use "hg -v help %s" to show global options') % name
1882 msg = _('use "hg -v help %s" to show global options') % name
1883 option_lists.append((msg, ()))
1883 option_lists.append((msg, ()))
1884
1884
1885 def helpcmd(name):
1885 def helpcmd(name):
1886 if with_version:
1886 if with_version:
1887 version_(ui)
1887 version_(ui)
1888 ui.write('\n')
1888 ui.write('\n')
1889
1889
1890 try:
1890 try:
1891 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1891 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1892 except error.AmbiguousCommand, inst:
1892 except error.AmbiguousCommand, inst:
1893 # py3k fix: except vars can't be used outside the scope of the
1893 # py3k fix: except vars can't be used outside the scope of the
1894 # except block, nor can be used inside a lambda. python issue4617
1894 # except block, nor can be used inside a lambda. python issue4617
1895 prefix = inst.args[0]
1895 prefix = inst.args[0]
1896 select = lambda c: c.lstrip('^').startswith(prefix)
1896 select = lambda c: c.lstrip('^').startswith(prefix)
1897 helplist(_('list of commands:\n\n'), select)
1897 helplist(_('list of commands:\n\n'), select)
1898 return
1898 return
1899
1899
1900 # check if it's an invalid alias and display its error if it is
1900 # check if it's an invalid alias and display its error if it is
1901 if getattr(entry[0], 'badalias', False):
1901 if getattr(entry[0], 'badalias', False):
1902 if not unknowncmd:
1902 if not unknowncmd:
1903 entry[0](ui)
1903 entry[0](ui)
1904 return
1904 return
1905
1905
1906 # synopsis
1906 # synopsis
1907 if len(entry) > 2:
1907 if len(entry) > 2:
1908 if entry[2].startswith('hg'):
1908 if entry[2].startswith('hg'):
1909 ui.write("%s\n" % entry[2])
1909 ui.write("%s\n" % entry[2])
1910 else:
1910 else:
1911 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1911 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
1912 else:
1912 else:
1913 ui.write('hg %s\n' % aliases[0])
1913 ui.write('hg %s\n' % aliases[0])
1914
1914
1915 # aliases
1915 # aliases
1916 if not ui.quiet and len(aliases) > 1:
1916 if not ui.quiet and len(aliases) > 1:
1917 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1917 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
1918
1918
1919 # description
1919 # description
1920 doc = gettext(entry[0].__doc__)
1920 doc = gettext(entry[0].__doc__)
1921 if not doc:
1921 if not doc:
1922 doc = _("(no help text available)")
1922 doc = _("(no help text available)")
1923 if hasattr(entry[0], 'definition'): # aliased command
1923 if hasattr(entry[0], 'definition'): # aliased command
1924 if entry[0].definition.startswith('!'): # shell alias
1924 if entry[0].definition.startswith('!'): # shell alias
1925 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1925 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
1926 else:
1926 else:
1927 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1927 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
1928 if ui.quiet:
1928 if ui.quiet:
1929 doc = doc.splitlines()[0]
1929 doc = doc.splitlines()[0]
1930 keep = ui.verbose and ['verbose'] or []
1930 keep = ui.verbose and ['verbose'] or []
1931 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1931 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
1932 ui.write("\n%s\n" % formatted)
1932 ui.write("\n%s\n" % formatted)
1933 if pruned:
1933 if pruned:
1934 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1934 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
1935
1935
1936 if not ui.quiet:
1936 if not ui.quiet:
1937 # options
1937 # options
1938 if entry[1]:
1938 if entry[1]:
1939 option_lists.append((_("options:\n"), entry[1]))
1939 option_lists.append((_("options:\n"), entry[1]))
1940
1940
1941 addglobalopts(False)
1941 addglobalopts(False)
1942
1942
1943 def helplist(header, select=None):
1943 def helplist(header, select=None):
1944 h = {}
1944 h = {}
1945 cmds = {}
1945 cmds = {}
1946 for c, e in table.iteritems():
1946 for c, e in table.iteritems():
1947 f = c.split("|", 1)[0]
1947 f = c.split("|", 1)[0]
1948 if select and not select(f):
1948 if select and not select(f):
1949 continue
1949 continue
1950 if (not select and name != 'shortlist' and
1950 if (not select and name != 'shortlist' and
1951 e[0].__module__ != __name__):
1951 e[0].__module__ != __name__):
1952 continue
1952 continue
1953 if name == "shortlist" and not f.startswith("^"):
1953 if name == "shortlist" and not f.startswith("^"):
1954 continue
1954 continue
1955 f = f.lstrip("^")
1955 f = f.lstrip("^")
1956 if not ui.debugflag and f.startswith("debug"):
1956 if not ui.debugflag and f.startswith("debug"):
1957 continue
1957 continue
1958 doc = e[0].__doc__
1958 doc = e[0].__doc__
1959 if doc and 'DEPRECATED' in doc and not ui.verbose:
1959 if doc and 'DEPRECATED' in doc and not ui.verbose:
1960 continue
1960 continue
1961 doc = gettext(doc)
1961 doc = gettext(doc)
1962 if not doc:
1962 if not doc:
1963 doc = _("(no help text available)")
1963 doc = _("(no help text available)")
1964 h[f] = doc.splitlines()[0].rstrip()
1964 h[f] = doc.splitlines()[0].rstrip()
1965 cmds[f] = c.lstrip("^")
1965 cmds[f] = c.lstrip("^")
1966
1966
1967 if not h:
1967 if not h:
1968 ui.status(_('no commands defined\n'))
1968 ui.status(_('no commands defined\n'))
1969 return
1969 return
1970
1970
1971 ui.status(header)
1971 ui.status(header)
1972 fns = sorted(h)
1972 fns = sorted(h)
1973 m = max(map(len, fns))
1973 m = max(map(len, fns))
1974 for f in fns:
1974 for f in fns:
1975 if ui.verbose:
1975 if ui.verbose:
1976 commands = cmds[f].replace("|",", ")
1976 commands = cmds[f].replace("|",", ")
1977 ui.write(" %s:\n %s\n"%(commands, h[f]))
1977 ui.write(" %s:\n %s\n"%(commands, h[f]))
1978 else:
1978 else:
1979 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1979 ui.write('%s\n' % (util.wrap(h[f], textwidth,
1980 initindent=' %-*s ' % (m, f),
1980 initindent=' %-*s ' % (m, f),
1981 hangindent=' ' * (m + 4))))
1981 hangindent=' ' * (m + 4))))
1982
1982
1983 if not ui.quiet:
1983 if not ui.quiet:
1984 addglobalopts(True)
1984 addglobalopts(True)
1985
1985
1986 def helptopic(name):
1986 def helptopic(name):
1987 for names, header, doc in help.helptable:
1987 for names, header, doc in help.helptable:
1988 if name in names:
1988 if name in names:
1989 break
1989 break
1990 else:
1990 else:
1991 raise error.UnknownCommand(name)
1991 raise error.UnknownCommand(name)
1992
1992
1993 # description
1993 # description
1994 if not doc:
1994 if not doc:
1995 doc = _("(no help text available)")
1995 doc = _("(no help text available)")
1996 if hasattr(doc, '__call__'):
1996 if hasattr(doc, '__call__'):
1997 doc = doc()
1997 doc = doc()
1998
1998
1999 ui.write("%s\n\n" % header)
1999 ui.write("%s\n\n" % header)
2000 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2000 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2001
2001
2002 def helpext(name):
2002 def helpext(name):
2003 try:
2003 try:
2004 mod = extensions.find(name)
2004 mod = extensions.find(name)
2005 doc = gettext(mod.__doc__) or _('no help text available')
2005 doc = gettext(mod.__doc__) or _('no help text available')
2006 except KeyError:
2006 except KeyError:
2007 mod = None
2007 mod = None
2008 doc = extensions.disabledext(name)
2008 doc = extensions.disabledext(name)
2009 if not doc:
2009 if not doc:
2010 raise error.UnknownCommand(name)
2010 raise error.UnknownCommand(name)
2011
2011
2012 if '\n' not in doc:
2012 if '\n' not in doc:
2013 head, tail = doc, ""
2013 head, tail = doc, ""
2014 else:
2014 else:
2015 head, tail = doc.split('\n', 1)
2015 head, tail = doc.split('\n', 1)
2016 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2016 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2017 if tail:
2017 if tail:
2018 ui.write(minirst.format(tail, textwidth))
2018 ui.write(minirst.format(tail, textwidth))
2019 ui.status('\n\n')
2019 ui.status('\n\n')
2020
2020
2021 if mod:
2021 if mod:
2022 try:
2022 try:
2023 ct = mod.cmdtable
2023 ct = mod.cmdtable
2024 except AttributeError:
2024 except AttributeError:
2025 ct = {}
2025 ct = {}
2026 modcmds = set([c.split('|', 1)[0] for c in ct])
2026 modcmds = set([c.split('|', 1)[0] for c in ct])
2027 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2027 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2028 else:
2028 else:
2029 ui.write(_('use "hg help extensions" for information on enabling '
2029 ui.write(_('use "hg help extensions" for information on enabling '
2030 'extensions\n'))
2030 'extensions\n'))
2031
2031
2032 def helpextcmd(name):
2032 def helpextcmd(name):
2033 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2033 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2034 doc = gettext(mod.__doc__).splitlines()[0]
2034 doc = gettext(mod.__doc__).splitlines()[0]
2035
2035
2036 msg = help.listexts(_("'%s' is provided by the following "
2036 msg = help.listexts(_("'%s' is provided by the following "
2037 "extension:") % cmd, {ext: doc}, len(ext),
2037 "extension:") % cmd, {ext: doc}, len(ext),
2038 indent=4)
2038 indent=4)
2039 ui.write(minirst.format(msg, textwidth))
2039 ui.write(minirst.format(msg, textwidth))
2040 ui.write('\n\n')
2040 ui.write('\n\n')
2041 ui.write(_('use "hg help extensions" for information on enabling '
2041 ui.write(_('use "hg help extensions" for information on enabling '
2042 'extensions\n'))
2042 'extensions\n'))
2043
2043
2044 help.addtopichook('revsets', revset.makedoc)
2044 help.addtopichook('revsets', revset.makedoc)
2045
2045
2046 if name and name != 'shortlist':
2046 if name and name != 'shortlist':
2047 i = None
2047 i = None
2048 if unknowncmd:
2048 if unknowncmd:
2049 queries = (helpextcmd,)
2049 queries = (helpextcmd,)
2050 else:
2050 else:
2051 queries = (helptopic, helpcmd, helpext, helpextcmd)
2051 queries = (helptopic, helpcmd, helpext, helpextcmd)
2052 for f in queries:
2052 for f in queries:
2053 try:
2053 try:
2054 f(name)
2054 f(name)
2055 i = None
2055 i = None
2056 break
2056 break
2057 except error.UnknownCommand, inst:
2057 except error.UnknownCommand, inst:
2058 i = inst
2058 i = inst
2059 if i:
2059 if i:
2060 raise i
2060 raise i
2061
2061
2062 else:
2062 else:
2063 # program name
2063 # program name
2064 if ui.verbose or with_version:
2064 if ui.verbose or with_version:
2065 version_(ui)
2065 version_(ui)
2066 else:
2066 else:
2067 ui.status(_("Mercurial Distributed SCM\n"))
2067 ui.status(_("Mercurial Distributed SCM\n"))
2068 ui.status('\n')
2068 ui.status('\n')
2069
2069
2070 # list of commands
2070 # list of commands
2071 if name == "shortlist":
2071 if name == "shortlist":
2072 header = _('basic commands:\n\n')
2072 header = _('basic commands:\n\n')
2073 else:
2073 else:
2074 header = _('list of commands:\n\n')
2074 header = _('list of commands:\n\n')
2075
2075
2076 helplist(header)
2076 helplist(header)
2077 if name != 'shortlist':
2077 if name != 'shortlist':
2078 exts, maxlength = extensions.enabled()
2078 exts, maxlength = extensions.enabled()
2079 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2079 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2080 if text:
2080 if text:
2081 ui.write("\n%s\n" % minirst.format(text, textwidth))
2081 ui.write("\n%s\n" % minirst.format(text, textwidth))
2082
2082
2083 # list all option lists
2083 # list all option lists
2084 opt_output = []
2084 opt_output = []
2085 multioccur = False
2085 multioccur = False
2086 for title, options in option_lists:
2086 for title, options in option_lists:
2087 opt_output.append(("\n%s" % title, None))
2087 opt_output.append(("\n%s" % title, None))
2088 for option in options:
2088 for option in options:
2089 if len(option) == 5:
2089 if len(option) == 5:
2090 shortopt, longopt, default, desc, optlabel = option
2090 shortopt, longopt, default, desc, optlabel = option
2091 else:
2091 else:
2092 shortopt, longopt, default, desc = option
2092 shortopt, longopt, default, desc = option
2093 optlabel = _("VALUE") # default label
2093 optlabel = _("VALUE") # default label
2094
2094
2095 if _("DEPRECATED") in desc and not ui.verbose:
2095 if _("DEPRECATED") in desc and not ui.verbose:
2096 continue
2096 continue
2097 if isinstance(default, list):
2097 if isinstance(default, list):
2098 numqualifier = " %s [+]" % optlabel
2098 numqualifier = " %s [+]" % optlabel
2099 multioccur = True
2099 multioccur = True
2100 elif (default is not None) and not isinstance(default, bool):
2100 elif (default is not None) and not isinstance(default, bool):
2101 numqualifier = " %s" % optlabel
2101 numqualifier = " %s" % optlabel
2102 else:
2102 else:
2103 numqualifier = ""
2103 numqualifier = ""
2104 opt_output.append(("%2s%s" %
2104 opt_output.append(("%2s%s" %
2105 (shortopt and "-%s" % shortopt,
2105 (shortopt and "-%s" % shortopt,
2106 longopt and " --%s%s" %
2106 longopt and " --%s%s" %
2107 (longopt, numqualifier)),
2107 (longopt, numqualifier)),
2108 "%s%s" % (desc,
2108 "%s%s" % (desc,
2109 default
2109 default
2110 and _(" (default: %s)") % default
2110 and _(" (default: %s)") % default
2111 or "")))
2111 or "")))
2112 if multioccur:
2112 if multioccur:
2113 msg = _("\n[+] marked option can be specified multiple times")
2113 msg = _("\n[+] marked option can be specified multiple times")
2114 if ui.verbose and name != 'shortlist':
2114 if ui.verbose and name != 'shortlist':
2115 opt_output.append((msg, None))
2115 opt_output.append((msg, None))
2116 else:
2116 else:
2117 opt_output.insert(-1, (msg, None))
2117 opt_output.insert(-1, (msg, None))
2118
2118
2119 if not name:
2119 if not name:
2120 ui.write(_("\nadditional help topics:\n\n"))
2120 ui.write(_("\nadditional help topics:\n\n"))
2121 topics = []
2121 topics = []
2122 for names, header, doc in help.helptable:
2122 for names, header, doc in help.helptable:
2123 topics.append((sorted(names, key=len, reverse=True)[0], header))
2123 topics.append((sorted(names, key=len, reverse=True)[0], header))
2124 topics_len = max([len(s[0]) for s in topics])
2124 topics_len = max([len(s[0]) for s in topics])
2125 for t, desc in topics:
2125 for t, desc in topics:
2126 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2126 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2127
2127
2128 if opt_output:
2128 if opt_output:
2129 colwidth = encoding.colwidth
2129 colwidth = encoding.colwidth
2130 # normalize: (opt or message, desc or None, width of opt)
2130 # normalize: (opt or message, desc or None, width of opt)
2131 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2131 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2132 for opt, desc in opt_output]
2132 for opt, desc in opt_output]
2133 hanging = max([e[2] for e in entries])
2133 hanging = max([e[2] for e in entries])
2134 for opt, desc, width in entries:
2134 for opt, desc, width in entries:
2135 if desc:
2135 if desc:
2136 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2136 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2137 hangindent = ' ' * (hanging + 3)
2137 hangindent = ' ' * (hanging + 3)
2138 ui.write('%s\n' % (util.wrap(desc, textwidth,
2138 ui.write('%s\n' % (util.wrap(desc, textwidth,
2139 initindent=initindent,
2139 initindent=initindent,
2140 hangindent=hangindent)))
2140 hangindent=hangindent)))
2141 else:
2141 else:
2142 ui.write("%s\n" % opt)
2142 ui.write("%s\n" % opt)
2143
2143
2144 def identify(ui, repo, source=None,
2144 def identify(ui, repo, source=None,
2145 rev=None, num=None, id=None, branch=None, tags=None):
2145 rev=None, num=None, id=None, branch=None, tags=None):
2146 """identify the working copy or specified revision
2146 """identify the working copy or specified revision
2147
2147
2148 With no revision, print a summary of the current state of the
2148 With no revision, print a summary of the current state of the
2149 repository.
2149 repository.
2150
2150
2151 Specifying a path to a repository root or Mercurial bundle will
2151 Specifying a path to a repository root or Mercurial bundle will
2152 cause lookup to operate on that repository/bundle.
2152 cause lookup to operate on that repository/bundle.
2153
2153
2154 This summary identifies the repository state using one or two
2154 This summary identifies the repository state using one or two
2155 parent hash identifiers, followed by a "+" if there are
2155 parent hash identifiers, followed by a "+" if there are
2156 uncommitted changes in the working directory, a list of tags for
2156 uncommitted changes in the working directory, a list of tags for
2157 this revision and a branch name for non-default branches.
2157 this revision and a branch name for non-default branches.
2158
2158
2159 Returns 0 if successful.
2159 Returns 0 if successful.
2160 """
2160 """
2161
2161
2162 if not repo and not source:
2162 if not repo and not source:
2163 raise util.Abort(_("there is no Mercurial repository here "
2163 raise util.Abort(_("there is no Mercurial repository here "
2164 "(.hg not found)"))
2164 "(.hg not found)"))
2165
2165
2166 hexfunc = ui.debugflag and hex or short
2166 hexfunc = ui.debugflag and hex or short
2167 default = not (num or id or branch or tags)
2167 default = not (num or id or branch or tags)
2168 output = []
2168 output = []
2169
2169
2170 revs = []
2170 revs = []
2171 if source:
2171 if source:
2172 source, branches = hg.parseurl(ui.expandpath(source))
2172 source, branches = hg.parseurl(ui.expandpath(source))
2173 repo = hg.repository(ui, source)
2173 repo = hg.repository(ui, source)
2174 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2174 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2175
2175
2176 if not repo.local():
2176 if not repo.local():
2177 if not rev and revs:
2177 if not rev and revs:
2178 rev = revs[0]
2178 rev = revs[0]
2179 if not rev:
2179 if not rev:
2180 rev = "tip"
2180 rev = "tip"
2181 if num or branch or tags:
2181 if num or branch or tags:
2182 raise util.Abort(
2182 raise util.Abort(
2183 "can't query remote revision number, branch, or tags")
2183 "can't query remote revision number, branch, or tags")
2184 output = [hexfunc(repo.lookup(rev))]
2184 output = [hexfunc(repo.lookup(rev))]
2185 elif not rev:
2185 elif not rev:
2186 ctx = repo[None]
2186 ctx = repo[None]
2187 parents = ctx.parents()
2187 parents = ctx.parents()
2188 changed = False
2188 changed = False
2189 if default or id or num:
2189 if default or id or num:
2190 changed = util.any(repo.status())
2190 changed = util.any(repo.status())
2191 if default or id:
2191 if default or id:
2192 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2192 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2193 (changed) and "+" or "")]
2193 (changed) and "+" or "")]
2194 if num:
2194 if num:
2195 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2195 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2196 (changed) and "+" or ""))
2196 (changed) and "+" or ""))
2197 else:
2197 else:
2198 ctx = cmdutil.revsingle(repo, rev)
2198 ctx = cmdutil.revsingle(repo, rev)
2199 if default or id:
2199 if default or id:
2200 output = [hexfunc(ctx.node())]
2200 output = [hexfunc(ctx.node())]
2201 if num:
2201 if num:
2202 output.append(str(ctx.rev()))
2202 output.append(str(ctx.rev()))
2203
2203
2204 if repo.local() and default and not ui.quiet:
2204 if repo.local() and default and not ui.quiet:
2205 b = ctx.branch()
2205 b = ctx.branch()
2206 if b != 'default':
2206 if b != 'default':
2207 output.append("(%s)" % b)
2207 output.append("(%s)" % b)
2208
2208
2209 # multiple tags for a single parent separated by '/'
2209 # multiple tags for a single parent separated by '/'
2210 t = "/".join(ctx.tags())
2210 t = "/".join(ctx.tags())
2211 if t:
2211 if t:
2212 output.append(t)
2212 output.append(t)
2213
2213
2214 if branch:
2214 if branch:
2215 output.append(ctx.branch())
2215 output.append(ctx.branch())
2216
2216
2217 if tags:
2217 if tags:
2218 output.extend(ctx.tags())
2218 output.extend(ctx.tags())
2219
2219
2220 ui.write("%s\n" % ' '.join(output))
2220 ui.write("%s\n" % ' '.join(output))
2221
2221
2222 def import_(ui, repo, patch1, *patches, **opts):
2222 def import_(ui, repo, patch1, *patches, **opts):
2223 """import an ordered set of patches
2223 """import an ordered set of patches
2224
2224
2225 Import a list of patches and commit them individually (unless
2225 Import a list of patches and commit them individually (unless
2226 --no-commit is specified).
2226 --no-commit is specified).
2227
2227
2228 If there are outstanding changes in the working directory, import
2228 If there are outstanding changes in the working directory, import
2229 will abort unless given the -f/--force flag.
2229 will abort unless given the -f/--force flag.
2230
2230
2231 You can import a patch straight from a mail message. Even patches
2231 You can import a patch straight from a mail message. Even patches
2232 as attachments work (to use the body part, it must have type
2232 as attachments work (to use the body part, it must have type
2233 text/plain or text/x-patch). From and Subject headers of email
2233 text/plain or text/x-patch). From and Subject headers of email
2234 message are used as default committer and commit message. All
2234 message are used as default committer and commit message. All
2235 text/plain body parts before first diff are added to commit
2235 text/plain body parts before first diff are added to commit
2236 message.
2236 message.
2237
2237
2238 If the imported patch was generated by :hg:`export`, user and
2238 If the imported patch was generated by :hg:`export`, user and
2239 description from patch override values from message headers and
2239 description from patch override values from message headers and
2240 body. Values given on command line with -m/--message and -u/--user
2240 body. Values given on command line with -m/--message and -u/--user
2241 override these.
2241 override these.
2242
2242
2243 If --exact is specified, import will set the working directory to
2243 If --exact is specified, import will set the working directory to
2244 the parent of each patch before applying it, and will abort if the
2244 the parent of each patch before applying it, and will abort if the
2245 resulting changeset has a different ID than the one recorded in
2245 resulting changeset has a different ID than the one recorded in
2246 the patch. This may happen due to character set problems or other
2246 the patch. This may happen due to character set problems or other
2247 deficiencies in the text patch format.
2247 deficiencies in the text patch format.
2248
2248
2249 With -s/--similarity, hg will attempt to discover renames and
2249 With -s/--similarity, hg will attempt to discover renames and
2250 copies in the patch in the same way as 'addremove'.
2250 copies in the patch in the same way as 'addremove'.
2251
2251
2252 To read a patch from standard input, use "-" as the patch name. If
2252 To read a patch from standard input, use "-" as the patch name. If
2253 a URL is specified, the patch will be downloaded from it.
2253 a URL is specified, the patch will be downloaded from it.
2254 See :hg:`help dates` for a list of formats valid for -d/--date.
2254 See :hg:`help dates` for a list of formats valid for -d/--date.
2255
2255
2256 Returns 0 on success.
2256 Returns 0 on success.
2257 """
2257 """
2258 patches = (patch1,) + patches
2258 patches = (patch1,) + patches
2259
2259
2260 date = opts.get('date')
2260 date = opts.get('date')
2261 if date:
2261 if date:
2262 opts['date'] = util.parsedate(date)
2262 opts['date'] = util.parsedate(date)
2263
2263
2264 try:
2264 try:
2265 sim = float(opts.get('similarity') or 0)
2265 sim = float(opts.get('similarity') or 0)
2266 except ValueError:
2266 except ValueError:
2267 raise util.Abort(_('similarity must be a number'))
2267 raise util.Abort(_('similarity must be a number'))
2268 if sim < 0 or sim > 100:
2268 if sim < 0 or sim > 100:
2269 raise util.Abort(_('similarity must be between 0 and 100'))
2269 raise util.Abort(_('similarity must be between 0 and 100'))
2270
2270
2271 if opts.get('exact') or not opts.get('force'):
2271 if opts.get('exact') or not opts.get('force'):
2272 cmdutil.bail_if_changed(repo)
2272 cmdutil.bail_if_changed(repo)
2273
2273
2274 d = opts["base"]
2274 d = opts["base"]
2275 strip = opts["strip"]
2275 strip = opts["strip"]
2276 wlock = lock = None
2276 wlock = lock = None
2277 msgs = []
2277 msgs = []
2278
2278
2279 def tryone(ui, hunk):
2279 def tryone(ui, hunk):
2280 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2280 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2281 patch.extract(ui, hunk)
2281 patch.extract(ui, hunk)
2282
2282
2283 if not tmpname:
2283 if not tmpname:
2284 return None
2284 return None
2285 commitid = _('to working directory')
2285 commitid = _('to working directory')
2286
2286
2287 try:
2287 try:
2288 cmdline_message = cmdutil.logmessage(opts)
2288 cmdline_message = cmdutil.logmessage(opts)
2289 if cmdline_message:
2289 if cmdline_message:
2290 # pickup the cmdline msg
2290 # pickup the cmdline msg
2291 message = cmdline_message
2291 message = cmdline_message
2292 elif message:
2292 elif message:
2293 # pickup the patch msg
2293 # pickup the patch msg
2294 message = message.strip()
2294 message = message.strip()
2295 else:
2295 else:
2296 # launch the editor
2296 # launch the editor
2297 message = None
2297 message = None
2298 ui.debug('message:\n%s\n' % message)
2298 ui.debug('message:\n%s\n' % message)
2299
2299
2300 wp = repo.parents()
2300 wp = repo.parents()
2301 if opts.get('exact'):
2301 if opts.get('exact'):
2302 if not nodeid or not p1:
2302 if not nodeid or not p1:
2303 raise util.Abort(_('not a Mercurial patch'))
2303 raise util.Abort(_('not a Mercurial patch'))
2304 p1 = repo.lookup(p1)
2304 p1 = repo.lookup(p1)
2305 p2 = repo.lookup(p2 or hex(nullid))
2305 p2 = repo.lookup(p2 or hex(nullid))
2306
2306
2307 if p1 != wp[0].node():
2307 if p1 != wp[0].node():
2308 hg.clean(repo, p1)
2308 hg.clean(repo, p1)
2309 repo.dirstate.setparents(p1, p2)
2309 repo.dirstate.setparents(p1, p2)
2310 elif p2:
2310 elif p2:
2311 try:
2311 try:
2312 p1 = repo.lookup(p1)
2312 p1 = repo.lookup(p1)
2313 p2 = repo.lookup(p2)
2313 p2 = repo.lookup(p2)
2314 if p1 == wp[0].node():
2314 if p1 == wp[0].node():
2315 repo.dirstate.setparents(p1, p2)
2315 repo.dirstate.setparents(p1, p2)
2316 except error.RepoError:
2316 except error.RepoError:
2317 pass
2317 pass
2318 if opts.get('exact') or opts.get('import_branch'):
2318 if opts.get('exact') or opts.get('import_branch'):
2319 repo.dirstate.setbranch(branch or 'default')
2319 repo.dirstate.setbranch(branch or 'default')
2320
2320
2321 files = {}
2321 files = {}
2322 try:
2322 try:
2323 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2323 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2324 files=files, eolmode=None)
2324 files=files, eolmode=None)
2325 finally:
2325 finally:
2326 files = cmdutil.updatedir(ui, repo, files,
2326 files = cmdutil.updatedir(ui, repo, files,
2327 similarity=sim / 100.0)
2327 similarity=sim / 100.0)
2328 if opts.get('no_commit'):
2328 if opts.get('no_commit'):
2329 if message:
2329 if message:
2330 msgs.append(message)
2330 msgs.append(message)
2331 else:
2331 else:
2332 if opts.get('exact'):
2332 if opts.get('exact'):
2333 m = None
2333 m = None
2334 else:
2334 else:
2335 m = cmdutil.matchfiles(repo, files or [])
2335 m = cmdutil.matchfiles(repo, files or [])
2336 n = repo.commit(message, opts.get('user') or user,
2336 n = repo.commit(message, opts.get('user') or user,
2337 opts.get('date') or date, match=m,
2337 opts.get('date') or date, match=m,
2338 editor=cmdutil.commiteditor)
2338 editor=cmdutil.commiteditor)
2339 if opts.get('exact'):
2339 if opts.get('exact'):
2340 if hex(n) != nodeid:
2340 if hex(n) != nodeid:
2341 repo.rollback()
2341 repo.rollback()
2342 raise util.Abort(_('patch is damaged'
2342 raise util.Abort(_('patch is damaged'
2343 ' or loses information'))
2343 ' or loses information'))
2344 # Force a dirstate write so that the next transaction
2344 # Force a dirstate write so that the next transaction
2345 # backups an up-do-date file.
2345 # backups an up-do-date file.
2346 repo.dirstate.write()
2346 repo.dirstate.write()
2347 if n:
2347 if n:
2348 commitid = short(n)
2348 commitid = short(n)
2349
2349
2350 return commitid
2350 return commitid
2351 finally:
2351 finally:
2352 os.unlink(tmpname)
2352 os.unlink(tmpname)
2353
2353
2354 try:
2354 try:
2355 wlock = repo.wlock()
2355 wlock = repo.wlock()
2356 lock = repo.lock()
2356 lock = repo.lock()
2357 lastcommit = None
2357 lastcommit = None
2358 for p in patches:
2358 for p in patches:
2359 pf = os.path.join(d, p)
2359 pf = os.path.join(d, p)
2360
2360
2361 if pf == '-':
2361 if pf == '-':
2362 ui.status(_("applying patch from stdin\n"))
2362 ui.status(_("applying patch from stdin\n"))
2363 pf = sys.stdin
2363 pf = sys.stdin
2364 else:
2364 else:
2365 ui.status(_("applying %s\n") % p)
2365 ui.status(_("applying %s\n") % p)
2366 pf = url.open(ui, pf)
2366 pf = url.open(ui, pf)
2367
2367
2368 haspatch = False
2368 haspatch = False
2369 for hunk in patch.split(pf):
2369 for hunk in patch.split(pf):
2370 commitid = tryone(ui, hunk)
2370 commitid = tryone(ui, hunk)
2371 if commitid:
2371 if commitid:
2372 haspatch = True
2372 haspatch = True
2373 if lastcommit:
2373 if lastcommit:
2374 ui.status(_('applied %s\n') % lastcommit)
2374 ui.status(_('applied %s\n') % lastcommit)
2375 lastcommit = commitid
2375 lastcommit = commitid
2376
2376
2377 if not haspatch:
2377 if not haspatch:
2378 raise util.Abort(_('no diffs found'))
2378 raise util.Abort(_('no diffs found'))
2379
2379
2380 if msgs:
2380 if msgs:
2381 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2381 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2382 finally:
2382 finally:
2383 release(lock, wlock)
2383 release(lock, wlock)
2384
2384
2385 def incoming(ui, repo, source="default", **opts):
2385 def incoming(ui, repo, source="default", **opts):
2386 """show new changesets found in source
2386 """show new changesets found in source
2387
2387
2388 Show new changesets found in the specified path/URL or the default
2388 Show new changesets found in the specified path/URL or the default
2389 pull location. These are the changesets that would have been pulled
2389 pull location. These are the changesets that would have been pulled
2390 if a pull at the time you issued this command.
2390 if a pull at the time you issued this command.
2391
2391
2392 For remote repository, using --bundle avoids downloading the
2392 For remote repository, using --bundle avoids downloading the
2393 changesets twice if the incoming is followed by a pull.
2393 changesets twice if the incoming is followed by a pull.
2394
2394
2395 See pull for valid source format details.
2395 See pull for valid source format details.
2396
2396
2397 Returns 0 if there are incoming changes, 1 otherwise.
2397 Returns 0 if there are incoming changes, 1 otherwise.
2398 """
2398 """
2399 if opts.get('bundle') and opts.get('subrepos'):
2399 if opts.get('bundle') and opts.get('subrepos'):
2400 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2400 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2401
2401
2402 if opts.get('bookmarks'):
2402 if opts.get('bookmarks'):
2403 source, branches = hg.parseurl(ui.expandpath(source),
2403 source, branches = hg.parseurl(ui.expandpath(source),
2404 opts.get('branch'))
2404 opts.get('branch'))
2405 other = hg.repository(hg.remoteui(repo, opts), source)
2405 other = hg.repository(hg.remoteui(repo, opts), source)
2406 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2406 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2407 return bookmarks.diff(ui, repo, other)
2407 return bookmarks.diff(ui, repo, other)
2408
2408
2409 ret = hg.incoming(ui, repo, source, opts)
2409 ret = hg.incoming(ui, repo, source, opts)
2410 return ret
2410 return ret
2411
2411
2412 def init(ui, dest=".", **opts):
2412 def init(ui, dest=".", **opts):
2413 """create a new repository in the given directory
2413 """create a new repository in the given directory
2414
2414
2415 Initialize a new repository in the given directory. If the given
2415 Initialize a new repository in the given directory. If the given
2416 directory does not exist, it will be created.
2416 directory does not exist, it will be created.
2417
2417
2418 If no directory is given, the current directory is used.
2418 If no directory is given, the current directory is used.
2419
2419
2420 It is possible to specify an ``ssh://`` URL as the destination.
2420 It is possible to specify an ``ssh://`` URL as the destination.
2421 See :hg:`help urls` for more information.
2421 See :hg:`help urls` for more information.
2422
2422
2423 Returns 0 on success.
2423 Returns 0 on success.
2424 """
2424 """
2425 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2425 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2426
2426
2427 def locate(ui, repo, *pats, **opts):
2427 def locate(ui, repo, *pats, **opts):
2428 """locate files matching specific patterns
2428 """locate files matching specific patterns
2429
2429
2430 Print files under Mercurial control in the working directory whose
2430 Print files under Mercurial control in the working directory whose
2431 names match the given patterns.
2431 names match the given patterns.
2432
2432
2433 By default, this command searches all directories in the working
2433 By default, this command searches all directories in the working
2434 directory. To search just the current directory and its
2434 directory. To search just the current directory and its
2435 subdirectories, use "--include .".
2435 subdirectories, use "--include .".
2436
2436
2437 If no patterns are given to match, this command prints the names
2437 If no patterns are given to match, this command prints the names
2438 of all files under Mercurial control in the working directory.
2438 of all files under Mercurial control in the working directory.
2439
2439
2440 If you want to feed the output of this command into the "xargs"
2440 If you want to feed the output of this command into the "xargs"
2441 command, use the -0 option to both this command and "xargs". This
2441 command, use the -0 option to both this command and "xargs". This
2442 will avoid the problem of "xargs" treating single filenames that
2442 will avoid the problem of "xargs" treating single filenames that
2443 contain whitespace as multiple filenames.
2443 contain whitespace as multiple filenames.
2444
2444
2445 Returns 0 if a match is found, 1 otherwise.
2445 Returns 0 if a match is found, 1 otherwise.
2446 """
2446 """
2447 end = opts.get('print0') and '\0' or '\n'
2447 end = opts.get('print0') and '\0' or '\n'
2448 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2448 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2449
2449
2450 ret = 1
2450 ret = 1
2451 m = cmdutil.match(repo, pats, opts, default='relglob')
2451 m = cmdutil.match(repo, pats, opts, default='relglob')
2452 m.bad = lambda x, y: False
2452 m.bad = lambda x, y: False
2453 for abs in repo[rev].walk(m):
2453 for abs in repo[rev].walk(m):
2454 if not rev and abs not in repo.dirstate:
2454 if not rev and abs not in repo.dirstate:
2455 continue
2455 continue
2456 if opts.get('fullpath'):
2456 if opts.get('fullpath'):
2457 ui.write(repo.wjoin(abs), end)
2457 ui.write(repo.wjoin(abs), end)
2458 else:
2458 else:
2459 ui.write(((pats and m.rel(abs)) or abs), end)
2459 ui.write(((pats and m.rel(abs)) or abs), end)
2460 ret = 0
2460 ret = 0
2461
2461
2462 return ret
2462 return ret
2463
2463
2464 def log(ui, repo, *pats, **opts):
2464 def log(ui, repo, *pats, **opts):
2465 """show revision history of entire repository or files
2465 """show revision history of entire repository or files
2466
2466
2467 Print the revision history of the specified files or the entire
2467 Print the revision history of the specified files or the entire
2468 project.
2468 project.
2469
2469
2470 File history is shown without following rename or copy history of
2470 File history is shown without following rename or copy history of
2471 files. Use -f/--follow with a filename to follow history across
2471 files. Use -f/--follow with a filename to follow history across
2472 renames and copies. --follow without a filename will only show
2472 renames and copies. --follow without a filename will only show
2473 ancestors or descendants of the starting revision. --follow-first
2473 ancestors or descendants of the starting revision. --follow-first
2474 only follows the first parent of merge revisions.
2474 only follows the first parent of merge revisions.
2475
2475
2476 If no revision range is specified, the default is ``tip:0`` unless
2476 If no revision range is specified, the default is ``tip:0`` unless
2477 --follow is set, in which case the working directory parent is
2477 --follow is set, in which case the working directory parent is
2478 used as the starting revision. You can specify a revision set for
2478 used as the starting revision. You can specify a revision set for
2479 log, see :hg:`help revsets` for more information.
2479 log, see :hg:`help revsets` for more information.
2480
2480
2481 See :hg:`help dates` for a list of formats valid for -d/--date.
2481 See :hg:`help dates` for a list of formats valid for -d/--date.
2482
2482
2483 By default this command prints revision number and changeset id,
2483 By default this command prints revision number and changeset id,
2484 tags, non-trivial parents, user, date and time, and a summary for
2484 tags, non-trivial parents, user, date and time, and a summary for
2485 each commit. When the -v/--verbose switch is used, the list of
2485 each commit. When the -v/--verbose switch is used, the list of
2486 changed files and full commit message are shown.
2486 changed files and full commit message are shown.
2487
2487
2488 .. note::
2488 .. note::
2489 log -p/--patch may generate unexpected diff output for merge
2489 log -p/--patch may generate unexpected diff output for merge
2490 changesets, as it will only compare the merge changeset against
2490 changesets, as it will only compare the merge changeset against
2491 its first parent. Also, only files different from BOTH parents
2491 its first parent. Also, only files different from BOTH parents
2492 will appear in files:.
2492 will appear in files:.
2493
2493
2494 Returns 0 on success.
2494 Returns 0 on success.
2495 """
2495 """
2496
2496
2497 matchfn = cmdutil.match(repo, pats, opts)
2497 matchfn = cmdutil.match(repo, pats, opts)
2498 limit = cmdutil.loglimit(opts)
2498 limit = cmdutil.loglimit(opts)
2499 count = 0
2499 count = 0
2500
2500
2501 endrev = None
2501 endrev = None
2502 if opts.get('copies') and opts.get('rev'):
2502 if opts.get('copies') and opts.get('rev'):
2503 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2503 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2504
2504
2505 df = False
2505 df = False
2506 if opts["date"]:
2506 if opts["date"]:
2507 df = util.matchdate(opts["date"])
2507 df = util.matchdate(opts["date"])
2508
2508
2509 branches = opts.get('branch', []) + opts.get('only_branch', [])
2509 branches = opts.get('branch', []) + opts.get('only_branch', [])
2510 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2510 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2511
2511
2512 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2512 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2513 def prep(ctx, fns):
2513 def prep(ctx, fns):
2514 rev = ctx.rev()
2514 rev = ctx.rev()
2515 parents = [p for p in repo.changelog.parentrevs(rev)
2515 parents = [p for p in repo.changelog.parentrevs(rev)
2516 if p != nullrev]
2516 if p != nullrev]
2517 if opts.get('no_merges') and len(parents) == 2:
2517 if opts.get('no_merges') and len(parents) == 2:
2518 return
2518 return
2519 if opts.get('only_merges') and len(parents) != 2:
2519 if opts.get('only_merges') and len(parents) != 2:
2520 return
2520 return
2521 if opts.get('branch') and ctx.branch() not in opts['branch']:
2521 if opts.get('branch') and ctx.branch() not in opts['branch']:
2522 return
2522 return
2523 if df and not df(ctx.date()[0]):
2523 if df and not df(ctx.date()[0]):
2524 return
2524 return
2525 if opts['user'] and not [k for k in opts['user']
2525 if opts['user'] and not [k for k in opts['user']
2526 if k.lower() in ctx.user().lower()]:
2526 if k.lower() in ctx.user().lower()]:
2527 return
2527 return
2528 if opts.get('keyword'):
2528 if opts.get('keyword'):
2529 for k in [kw.lower() for kw in opts['keyword']]:
2529 for k in [kw.lower() for kw in opts['keyword']]:
2530 if (k in ctx.user().lower() or
2530 if (k in ctx.user().lower() or
2531 k in ctx.description().lower() or
2531 k in ctx.description().lower() or
2532 k in " ".join(ctx.files()).lower()):
2532 k in " ".join(ctx.files()).lower()):
2533 break
2533 break
2534 else:
2534 else:
2535 return
2535 return
2536
2536
2537 copies = None
2537 copies = None
2538 if opts.get('copies') and rev:
2538 if opts.get('copies') and rev:
2539 copies = []
2539 copies = []
2540 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2540 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2541 for fn in ctx.files():
2541 for fn in ctx.files():
2542 rename = getrenamed(fn, rev)
2542 rename = getrenamed(fn, rev)
2543 if rename:
2543 if rename:
2544 copies.append((fn, rename[0]))
2544 copies.append((fn, rename[0]))
2545
2545
2546 revmatchfn = None
2546 revmatchfn = None
2547 if opts.get('patch') or opts.get('stat'):
2547 if opts.get('patch') or opts.get('stat'):
2548 if opts.get('follow') or opts.get('follow_first'):
2548 if opts.get('follow') or opts.get('follow_first'):
2549 # note: this might be wrong when following through merges
2549 # note: this might be wrong when following through merges
2550 revmatchfn = cmdutil.match(repo, fns, default='path')
2550 revmatchfn = cmdutil.match(repo, fns, default='path')
2551 else:
2551 else:
2552 revmatchfn = matchfn
2552 revmatchfn = matchfn
2553
2553
2554 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2554 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2555
2555
2556 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2556 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2557 if count == limit:
2557 if count == limit:
2558 break
2558 break
2559 if displayer.flush(ctx.rev()):
2559 if displayer.flush(ctx.rev()):
2560 count += 1
2560 count += 1
2561 displayer.close()
2561 displayer.close()
2562
2562
2563 def manifest(ui, repo, node=None, rev=None):
2563 def manifest(ui, repo, node=None, rev=None):
2564 """output the current or given revision of the project manifest
2564 """output the current or given revision of the project manifest
2565
2565
2566 Print a list of version controlled files for the given revision.
2566 Print a list of version controlled files for the given revision.
2567 If no revision is given, the first parent of the working directory
2567 If no revision is given, the first parent of the working directory
2568 is used, or the null revision if no revision is checked out.
2568 is used, or the null revision if no revision is checked out.
2569
2569
2570 With -v, print file permissions, symlink and executable bits.
2570 With -v, print file permissions, symlink and executable bits.
2571 With --debug, print file revision hashes.
2571 With --debug, print file revision hashes.
2572
2572
2573 Returns 0 on success.
2573 Returns 0 on success.
2574 """
2574 """
2575
2575
2576 if rev and node:
2576 if rev and node:
2577 raise util.Abort(_("please specify just one revision"))
2577 raise util.Abort(_("please specify just one revision"))
2578
2578
2579 if not node:
2579 if not node:
2580 node = rev
2580 node = rev
2581
2581
2582 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2582 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2583 ctx = cmdutil.revsingle(repo, node)
2583 ctx = cmdutil.revsingle(repo, node)
2584 for f in ctx:
2584 for f in ctx:
2585 if ui.debugflag:
2585 if ui.debugflag:
2586 ui.write("%40s " % hex(ctx.manifest()[f]))
2586 ui.write("%40s " % hex(ctx.manifest()[f]))
2587 if ui.verbose:
2587 if ui.verbose:
2588 ui.write(decor[ctx.flags(f)])
2588 ui.write(decor[ctx.flags(f)])
2589 ui.write("%s\n" % f)
2589 ui.write("%s\n" % f)
2590
2590
2591 def merge(ui, repo, node=None, **opts):
2591 def merge(ui, repo, node=None, **opts):
2592 """merge working directory with another revision
2592 """merge working directory with another revision
2593
2593
2594 The current working directory is updated with all changes made in
2594 The current working directory is updated with all changes made in
2595 the requested revision since the last common predecessor revision.
2595 the requested revision since the last common predecessor revision.
2596
2596
2597 Files that changed between either parent are marked as changed for
2597 Files that changed between either parent are marked as changed for
2598 the next commit and a commit must be performed before any further
2598 the next commit and a commit must be performed before any further
2599 updates to the repository are allowed. The next commit will have
2599 updates to the repository are allowed. The next commit will have
2600 two parents.
2600 two parents.
2601
2601
2602 ``--tool`` can be used to specify the merge tool used for file
2602 ``--tool`` can be used to specify the merge tool used for file
2603 merges. It overrides the HGMERGE environment variable and your
2603 merges. It overrides the HGMERGE environment variable and your
2604 configuration files.
2604 configuration files.
2605
2605
2606 If no revision is specified, the working directory's parent is a
2606 If no revision is specified, the working directory's parent is a
2607 head revision, and the current branch contains exactly one other
2607 head revision, and the current branch contains exactly one other
2608 head, the other head is merged with by default. Otherwise, an
2608 head, the other head is merged with by default. Otherwise, an
2609 explicit revision with which to merge with must be provided.
2609 explicit revision with which to merge with must be provided.
2610
2610
2611 :hg:`resolve` must be used to resolve unresolved files.
2611 :hg:`resolve` must be used to resolve unresolved files.
2612
2612
2613 To undo an uncommitted merge, use :hg:`update --clean .` which
2613 To undo an uncommitted merge, use :hg:`update --clean .` which
2614 will check out a clean copy of the original merge parent, losing
2614 will check out a clean copy of the original merge parent, losing
2615 all changes.
2615 all changes.
2616
2616
2617 Returns 0 on success, 1 if there are unresolved files.
2617 Returns 0 on success, 1 if there are unresolved files.
2618 """
2618 """
2619
2619
2620 if opts.get('rev') and node:
2620 if opts.get('rev') and node:
2621 raise util.Abort(_("please specify just one revision"))
2621 raise util.Abort(_("please specify just one revision"))
2622 if not node:
2622 if not node:
2623 node = opts.get('rev')
2623 node = opts.get('rev')
2624
2624
2625 if not node:
2625 if not node:
2626 branch = repo[None].branch()
2626 branch = repo[None].branch()
2627 bheads = repo.branchheads(branch)
2627 bheads = repo.branchheads(branch)
2628 if len(bheads) > 2:
2628 if len(bheads) > 2:
2629 raise util.Abort(_(
2629 raise util.Abort(_(
2630 'branch \'%s\' has %d heads - '
2630 'branch \'%s\' has %d heads - '
2631 'please merge with an explicit rev\n'
2631 'please merge with an explicit rev\n'
2632 '(run \'hg heads .\' to see heads)')
2632 '(run \'hg heads .\' to see heads)')
2633 % (branch, len(bheads)))
2633 % (branch, len(bheads)))
2634
2634
2635 parent = repo.dirstate.parents()[0]
2635 parent = repo.dirstate.parents()[0]
2636 if len(bheads) == 1:
2636 if len(bheads) == 1:
2637 if len(repo.heads()) > 1:
2637 if len(repo.heads()) > 1:
2638 raise util.Abort(_(
2638 raise util.Abort(_(
2639 'branch \'%s\' has one head - '
2639 'branch \'%s\' has one head - '
2640 'please merge with an explicit rev\n'
2640 'please merge with an explicit rev\n'
2641 '(run \'hg heads\' to see all heads)')
2641 '(run \'hg heads\' to see all heads)')
2642 % branch)
2642 % branch)
2643 msg = _('there is nothing to merge')
2643 msg = _('there is nothing to merge')
2644 if parent != repo.lookup(repo[None].branch()):
2644 if parent != repo.lookup(repo[None].branch()):
2645 msg = _('%s - use "hg update" instead') % msg
2645 msg = _('%s - use "hg update" instead') % msg
2646 raise util.Abort(msg)
2646 raise util.Abort(msg)
2647
2647
2648 if parent not in bheads:
2648 if parent not in bheads:
2649 raise util.Abort(_('working dir not at a head rev - '
2649 raise util.Abort(_('working dir not at a head rev - '
2650 'use "hg update" or merge with an explicit rev'))
2650 'use "hg update" or merge with an explicit rev'))
2651 node = parent == bheads[0] and bheads[-1] or bheads[0]
2651 node = parent == bheads[0] and bheads[-1] or bheads[0]
2652 else:
2652 else:
2653 node = cmdutil.revsingle(repo, node).node()
2653 node = cmdutil.revsingle(repo, node).node()
2654
2654
2655 if opts.get('preview'):
2655 if opts.get('preview'):
2656 # find nodes that are ancestors of p2 but not of p1
2656 # find nodes that are ancestors of p2 but not of p1
2657 p1 = repo.lookup('.')
2657 p1 = repo.lookup('.')
2658 p2 = repo.lookup(node)
2658 p2 = repo.lookup(node)
2659 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2659 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2660
2660
2661 displayer = cmdutil.show_changeset(ui, repo, opts)
2661 displayer = cmdutil.show_changeset(ui, repo, opts)
2662 for node in nodes:
2662 for node in nodes:
2663 displayer.show(repo[node])
2663 displayer.show(repo[node])
2664 displayer.close()
2664 displayer.close()
2665 return 0
2665 return 0
2666
2666
2667 try:
2667 try:
2668 # ui.forcemerge is an internal variable, do not document
2668 # ui.forcemerge is an internal variable, do not document
2669 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2669 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2670 return hg.merge(repo, node, force=opts.get('force'))
2670 return hg.merge(repo, node, force=opts.get('force'))
2671 finally:
2671 finally:
2672 ui.setconfig('ui', 'forcemerge', '')
2672 ui.setconfig('ui', 'forcemerge', '')
2673
2673
2674 def outgoing(ui, repo, dest=None, **opts):
2674 def outgoing(ui, repo, dest=None, **opts):
2675 """show changesets not found in the destination
2675 """show changesets not found in the destination
2676
2676
2677 Show changesets not found in the specified destination repository
2677 Show changesets not found in the specified destination repository
2678 or the default push location. These are the changesets that would
2678 or the default push location. These are the changesets that would
2679 be pushed if a push was requested.
2679 be pushed if a push was requested.
2680
2680
2681 See pull for details of valid destination formats.
2681 See pull for details of valid destination formats.
2682
2682
2683 Returns 0 if there are outgoing changes, 1 otherwise.
2683 Returns 0 if there are outgoing changes, 1 otherwise.
2684 """
2684 """
2685
2685
2686 if opts.get('bookmarks'):
2686 if opts.get('bookmarks'):
2687 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2687 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2688 dest, branches = hg.parseurl(dest, opts.get('branch'))
2688 dest, branches = hg.parseurl(dest, opts.get('branch'))
2689 other = hg.repository(hg.remoteui(repo, opts), dest)
2689 other = hg.repository(hg.remoteui(repo, opts), dest)
2690 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2690 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2691 return bookmarks.diff(ui, other, repo)
2691 return bookmarks.diff(ui, other, repo)
2692
2692
2693 ret = hg.outgoing(ui, repo, dest, opts)
2693 ret = hg.outgoing(ui, repo, dest, opts)
2694 return ret
2694 return ret
2695
2695
2696 def parents(ui, repo, file_=None, **opts):
2696 def parents(ui, repo, file_=None, **opts):
2697 """show the parents of the working directory or revision
2697 """show the parents of the working directory or revision
2698
2698
2699 Print the working directory's parent revisions. If a revision is
2699 Print the working directory's parent revisions. If a revision is
2700 given via -r/--rev, the parent of that revision will be printed.
2700 given via -r/--rev, the parent of that revision will be printed.
2701 If a file argument is given, the revision in which the file was
2701 If a file argument is given, the revision in which the file was
2702 last changed (before the working directory revision or the
2702 last changed (before the working directory revision or the
2703 argument to --rev if given) is printed.
2703 argument to --rev if given) is printed.
2704
2704
2705 Returns 0 on success.
2705 Returns 0 on success.
2706 """
2706 """
2707
2707
2708 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2708 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2709
2709
2710 if file_:
2710 if file_:
2711 m = cmdutil.match(repo, (file_,), opts)
2711 m = cmdutil.match(repo, (file_,), opts)
2712 if m.anypats() or len(m.files()) != 1:
2712 if m.anypats() or len(m.files()) != 1:
2713 raise util.Abort(_('can only specify an explicit filename'))
2713 raise util.Abort(_('can only specify an explicit filename'))
2714 file_ = m.files()[0]
2714 file_ = m.files()[0]
2715 filenodes = []
2715 filenodes = []
2716 for cp in ctx.parents():
2716 for cp in ctx.parents():
2717 if not cp:
2717 if not cp:
2718 continue
2718 continue
2719 try:
2719 try:
2720 filenodes.append(cp.filenode(file_))
2720 filenodes.append(cp.filenode(file_))
2721 except error.LookupError:
2721 except error.LookupError:
2722 pass
2722 pass
2723 if not filenodes:
2723 if not filenodes:
2724 raise util.Abort(_("'%s' not found in manifest!") % file_)
2724 raise util.Abort(_("'%s' not found in manifest!") % file_)
2725 fl = repo.file(file_)
2725 fl = repo.file(file_)
2726 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2726 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2727 else:
2727 else:
2728 p = [cp.node() for cp in ctx.parents()]
2728 p = [cp.node() for cp in ctx.parents()]
2729
2729
2730 displayer = cmdutil.show_changeset(ui, repo, opts)
2730 displayer = cmdutil.show_changeset(ui, repo, opts)
2731 for n in p:
2731 for n in p:
2732 if n != nullid:
2732 if n != nullid:
2733 displayer.show(repo[n])
2733 displayer.show(repo[n])
2734 displayer.close()
2734 displayer.close()
2735
2735
2736 def paths(ui, repo, search=None):
2736 def paths(ui, repo, search=None):
2737 """show aliases for remote repositories
2737 """show aliases for remote repositories
2738
2738
2739 Show definition of symbolic path name NAME. If no name is given,
2739 Show definition of symbolic path name NAME. If no name is given,
2740 show definition of all available names.
2740 show definition of all available names.
2741
2741
2742 Path names are defined in the [paths] section of your
2742 Path names are defined in the [paths] section of your
2743 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2743 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2744 repository, ``.hg/hgrc`` is used, too.
2744 repository, ``.hg/hgrc`` is used, too.
2745
2745
2746 The path names ``default`` and ``default-push`` have a special
2746 The path names ``default`` and ``default-push`` have a special
2747 meaning. When performing a push or pull operation, they are used
2747 meaning. When performing a push or pull operation, they are used
2748 as fallbacks if no location is specified on the command-line.
2748 as fallbacks if no location is specified on the command-line.
2749 When ``default-push`` is set, it will be used for push and
2749 When ``default-push`` is set, it will be used for push and
2750 ``default`` will be used for pull; otherwise ``default`` is used
2750 ``default`` will be used for pull; otherwise ``default`` is used
2751 as the fallback for both. When cloning a repository, the clone
2751 as the fallback for both. When cloning a repository, the clone
2752 source is written as ``default`` in ``.hg/hgrc``. Note that
2752 source is written as ``default`` in ``.hg/hgrc``. Note that
2753 ``default`` and ``default-push`` apply to all inbound (e.g.
2753 ``default`` and ``default-push`` apply to all inbound (e.g.
2754 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2754 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2755 :hg:`bundle`) operations.
2755 :hg:`bundle`) operations.
2756
2756
2757 See :hg:`help urls` for more information.
2757 See :hg:`help urls` for more information.
2758
2758
2759 Returns 0 on success.
2759 Returns 0 on success.
2760 """
2760 """
2761 if search:
2761 if search:
2762 for name, path in ui.configitems("paths"):
2762 for name, path in ui.configitems("paths"):
2763 if name == search:
2763 if name == search:
2764 ui.write("%s\n" % url.hidepassword(path))
2764 ui.write("%s\n" % url.hidepassword(path))
2765 return
2765 return
2766 ui.warn(_("not found!\n"))
2766 ui.warn(_("not found!\n"))
2767 return 1
2767 return 1
2768 else:
2768 else:
2769 for name, path in ui.configitems("paths"):
2769 for name, path in ui.configitems("paths"):
2770 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2770 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2771
2771
2772 def postincoming(ui, repo, modheads, optupdate, checkout):
2772 def postincoming(ui, repo, modheads, optupdate, checkout):
2773 if modheads == 0:
2773 if modheads == 0:
2774 return
2774 return
2775 if optupdate:
2775 if optupdate:
2776 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2776 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2777 return hg.update(repo, checkout)
2777 return hg.update(repo, checkout)
2778 else:
2778 else:
2779 ui.status(_("not updating, since new heads added\n"))
2779 ui.status(_("not updating, since new heads added\n"))
2780 if modheads > 1:
2780 if modheads > 1:
2781 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2781 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2782 else:
2782 else:
2783 ui.status(_("(run 'hg update' to get a working copy)\n"))
2783 ui.status(_("(run 'hg update' to get a working copy)\n"))
2784
2784
2785 def pull(ui, repo, source="default", **opts):
2785 def pull(ui, repo, source="default", **opts):
2786 """pull changes from the specified source
2786 """pull changes from the specified source
2787
2787
2788 Pull changes from a remote repository to a local one.
2788 Pull changes from a remote repository to a local one.
2789
2789
2790 This finds all changes from the repository at the specified path
2790 This finds all changes from the repository at the specified path
2791 or URL and adds them to a local repository (the current one unless
2791 or URL and adds them to a local repository (the current one unless
2792 -R is specified). By default, this does not update the copy of the
2792 -R is specified). By default, this does not update the copy of the
2793 project in the working directory.
2793 project in the working directory.
2794
2794
2795 Use :hg:`incoming` if you want to see what would have been added
2795 Use :hg:`incoming` if you want to see what would have been added
2796 by a pull at the time you issued this command. If you then decide
2796 by a pull at the time you issued this command. If you then decide
2797 to add those changes to the repository, you should use :hg:`pull
2797 to add those changes to the repository, you should use :hg:`pull
2798 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2798 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2799
2799
2800 If SOURCE is omitted, the 'default' path will be used.
2800 If SOURCE is omitted, the 'default' path will be used.
2801 See :hg:`help urls` for more information.
2801 See :hg:`help urls` for more information.
2802
2802
2803 Returns 0 on success, 1 if an update had unresolved files.
2803 Returns 0 on success, 1 if an update had unresolved files.
2804 """
2804 """
2805 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2805 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2806 other = hg.repository(hg.remoteui(repo, opts), source)
2806 other = hg.repository(hg.remoteui(repo, opts), source)
2807 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2807 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2808 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2808 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2809 if revs:
2809 if revs:
2810 try:
2810 try:
2811 revs = [other.lookup(rev) for rev in revs]
2811 revs = [other.lookup(rev) for rev in revs]
2812 except error.CapabilityError:
2812 except error.CapabilityError:
2813 err = _("other repository doesn't support revision lookup, "
2813 err = _("other repository doesn't support revision lookup, "
2814 "so a rev cannot be specified.")
2814 "so a rev cannot be specified.")
2815 raise util.Abort(err)
2815 raise util.Abort(err)
2816
2816
2817 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2817 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2818 if checkout:
2818 if checkout:
2819 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2819 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2820 repo._subtoppath = source
2820 repo._subtoppath = source
2821 try:
2821 try:
2822 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2822 return postincoming(ui, repo, modheads, opts.get('update'), checkout)
2823 finally:
2823 finally:
2824 del repo._subtoppath
2824 del repo._subtoppath
2825
2825
2826 def push(ui, repo, dest=None, **opts):
2826 def push(ui, repo, dest=None, **opts):
2827 """push changes to the specified destination
2827 """push changes to the specified destination
2828
2828
2829 Push changesets from the local repository to the specified
2829 Push changesets from the local repository to the specified
2830 destination.
2830 destination.
2831
2831
2832 This operation is symmetrical to pull: it is identical to a pull
2832 This operation is symmetrical to pull: it is identical to a pull
2833 in the destination repository from the current one.
2833 in the destination repository from the current one.
2834
2834
2835 By default, push will not allow creation of new heads at the
2835 By default, push will not allow creation of new heads at the
2836 destination, since multiple heads would make it unclear which head
2836 destination, since multiple heads would make it unclear which head
2837 to use. In this situation, it is recommended to pull and merge
2837 to use. In this situation, it is recommended to pull and merge
2838 before pushing.
2838 before pushing.
2839
2839
2840 Use --new-branch if you want to allow push to create a new named
2840 Use --new-branch if you want to allow push to create a new named
2841 branch that is not present at the destination. This allows you to
2841 branch that is not present at the destination. This allows you to
2842 only create a new branch without forcing other changes.
2842 only create a new branch without forcing other changes.
2843
2843
2844 Use -f/--force to override the default behavior and push all
2844 Use -f/--force to override the default behavior and push all
2845 changesets on all branches.
2845 changesets on all branches.
2846
2846
2847 If -r/--rev is used, the specified revision and all its ancestors
2847 If -r/--rev is used, the specified revision and all its ancestors
2848 will be pushed to the remote repository.
2848 will be pushed to the remote repository.
2849
2849
2850 Please see :hg:`help urls` for important details about ``ssh://``
2850 Please see :hg:`help urls` for important details about ``ssh://``
2851 URLs. If DESTINATION is omitted, a default path will be used.
2851 URLs. If DESTINATION is omitted, a default path will be used.
2852
2852
2853 Returns 0 if push was successful, 1 if nothing to push.
2853 Returns 0 if push was successful, 1 if nothing to push.
2854 """
2854 """
2855 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2855 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2856 dest, branches = hg.parseurl(dest, opts.get('branch'))
2856 dest, branches = hg.parseurl(dest, opts.get('branch'))
2857 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2857 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2858 other = hg.repository(hg.remoteui(repo, opts), dest)
2858 other = hg.repository(hg.remoteui(repo, opts), dest)
2859 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2859 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2860 if revs:
2860 if revs:
2861 revs = [repo.lookup(rev) for rev in revs]
2861 revs = [repo.lookup(rev) for rev in revs]
2862
2862
2863 repo._subtoppath = dest
2863 repo._subtoppath = dest
2864 try:
2864 try:
2865 # push subrepos depth-first for coherent ordering
2865 # push subrepos depth-first for coherent ordering
2866 c = repo['']
2866 c = repo['']
2867 subs = c.substate # only repos that are committed
2867 subs = c.substate # only repos that are committed
2868 for s in sorted(subs):
2868 for s in sorted(subs):
2869 if not c.sub(s).push(opts.get('force')):
2869 if not c.sub(s).push(opts.get('force')):
2870 return False
2870 return False
2871 finally:
2871 finally:
2872 del repo._subtoppath
2872 del repo._subtoppath
2873 r = repo.push(other, opts.get('force'), revs=revs,
2873 r = repo.push(other, opts.get('force'), revs=revs,
2874 newbranch=opts.get('new_branch'))
2874 newbranch=opts.get('new_branch'))
2875 return r == 0
2875 return r == 0
2876
2876
2877 def recover(ui, repo):
2877 def recover(ui, repo):
2878 """roll back an interrupted transaction
2878 """roll back an interrupted transaction
2879
2879
2880 Recover from an interrupted commit or pull.
2880 Recover from an interrupted commit or pull.
2881
2881
2882 This command tries to fix the repository status after an
2882 This command tries to fix the repository status after an
2883 interrupted operation. It should only be necessary when Mercurial
2883 interrupted operation. It should only be necessary when Mercurial
2884 suggests it.
2884 suggests it.
2885
2885
2886 Returns 0 if successful, 1 if nothing to recover or verify fails.
2886 Returns 0 if successful, 1 if nothing to recover or verify fails.
2887 """
2887 """
2888 if repo.recover():
2888 if repo.recover():
2889 return hg.verify(repo)
2889 return hg.verify(repo)
2890 return 1
2890 return 1
2891
2891
2892 def remove(ui, repo, *pats, **opts):
2892 def remove(ui, repo, *pats, **opts):
2893 """remove the specified files on the next commit
2893 """remove the specified files on the next commit
2894
2894
2895 Schedule the indicated files for removal from the repository.
2895 Schedule the indicated files for removal from the repository.
2896
2896
2897 This only removes files from the current branch, not from the
2897 This only removes files from the current branch, not from the
2898 entire project history. -A/--after can be used to remove only
2898 entire project history. -A/--after can be used to remove only
2899 files that have already been deleted, -f/--force can be used to
2899 files that have already been deleted, -f/--force can be used to
2900 force deletion, and -Af can be used to remove files from the next
2900 force deletion, and -Af can be used to remove files from the next
2901 revision without deleting them from the working directory.
2901 revision without deleting them from the working directory.
2902
2902
2903 The following table details the behavior of remove for different
2903 The following table details the behavior of remove for different
2904 file states (columns) and option combinations (rows). The file
2904 file states (columns) and option combinations (rows). The file
2905 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2905 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
2906 reported by :hg:`status`). The actions are Warn, Remove (from
2906 reported by :hg:`status`). The actions are Warn, Remove (from
2907 branch) and Delete (from disk)::
2907 branch) and Delete (from disk)::
2908
2908
2909 A C M !
2909 A C M !
2910 none W RD W R
2910 none W RD W R
2911 -f R RD RD R
2911 -f R RD RD R
2912 -A W W W R
2912 -A W W W R
2913 -Af R R R R
2913 -Af R R R R
2914
2914
2915 This command schedules the files to be removed at the next commit.
2915 This command schedules the files to be removed at the next commit.
2916 To undo a remove before that, see :hg:`revert`.
2916 To undo a remove before that, see :hg:`revert`.
2917
2917
2918 Returns 0 on success, 1 if any warnings encountered.
2918 Returns 0 on success, 1 if any warnings encountered.
2919 """
2919 """
2920
2920
2921 ret = 0
2921 ret = 0
2922 after, force = opts.get('after'), opts.get('force')
2922 after, force = opts.get('after'), opts.get('force')
2923 if not pats and not after:
2923 if not pats and not after:
2924 raise util.Abort(_('no files specified'))
2924 raise util.Abort(_('no files specified'))
2925
2925
2926 m = cmdutil.match(repo, pats, opts)
2926 m = cmdutil.match(repo, pats, opts)
2927 s = repo.status(match=m, clean=True)
2927 s = repo.status(match=m, clean=True)
2928 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2928 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
2929
2929
2930 for f in m.files():
2930 for f in m.files():
2931 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2931 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
2932 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2932 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
2933 ret = 1
2933 ret = 1
2934
2934
2935 if force:
2935 if force:
2936 remove, forget = modified + deleted + clean, added
2936 remove, forget = modified + deleted + clean, added
2937 elif after:
2937 elif after:
2938 remove, forget = deleted, []
2938 remove, forget = deleted, []
2939 for f in modified + added + clean:
2939 for f in modified + added + clean:
2940 ui.warn(_('not removing %s: file still exists (use -f'
2940 ui.warn(_('not removing %s: file still exists (use -f'
2941 ' to force removal)\n') % m.rel(f))
2941 ' to force removal)\n') % m.rel(f))
2942 ret = 1
2942 ret = 1
2943 else:
2943 else:
2944 remove, forget = deleted + clean, []
2944 remove, forget = deleted + clean, []
2945 for f in modified:
2945 for f in modified:
2946 ui.warn(_('not removing %s: file is modified (use -f'
2946 ui.warn(_('not removing %s: file is modified (use -f'
2947 ' to force removal)\n') % m.rel(f))
2947 ' to force removal)\n') % m.rel(f))
2948 ret = 1
2948 ret = 1
2949 for f in added:
2949 for f in added:
2950 ui.warn(_('not removing %s: file has been marked for add (use -f'
2950 ui.warn(_('not removing %s: file has been marked for add (use -f'
2951 ' to force removal)\n') % m.rel(f))
2951 ' to force removal)\n') % m.rel(f))
2952 ret = 1
2952 ret = 1
2953
2953
2954 for f in sorted(remove + forget):
2954 for f in sorted(remove + forget):
2955 if ui.verbose or not m.exact(f):
2955 if ui.verbose or not m.exact(f):
2956 ui.status(_('removing %s\n') % m.rel(f))
2956 ui.status(_('removing %s\n') % m.rel(f))
2957
2957
2958 repo[None].forget(forget)
2958 repo[None].forget(forget)
2959 repo[None].remove(remove, unlink=not after)
2959 repo[None].remove(remove, unlink=not after)
2960 return ret
2960 return ret
2961
2961
2962 def rename(ui, repo, *pats, **opts):
2962 def rename(ui, repo, *pats, **opts):
2963 """rename files; equivalent of copy + remove
2963 """rename files; equivalent of copy + remove
2964
2964
2965 Mark dest as copies of sources; mark sources for deletion. If dest
2965 Mark dest as copies of sources; mark sources for deletion. If dest
2966 is a directory, copies are put in that directory. If dest is a
2966 is a directory, copies are put in that directory. If dest is a
2967 file, there can only be one source.
2967 file, there can only be one source.
2968
2968
2969 By default, this command copies the contents of files as they
2969 By default, this command copies the contents of files as they
2970 exist in the working directory. If invoked with -A/--after, the
2970 exist in the working directory. If invoked with -A/--after, the
2971 operation is recorded, but no copying is performed.
2971 operation is recorded, but no copying is performed.
2972
2972
2973 This command takes effect at the next commit. To undo a rename
2973 This command takes effect at the next commit. To undo a rename
2974 before that, see :hg:`revert`.
2974 before that, see :hg:`revert`.
2975
2975
2976 Returns 0 on success, 1 if errors are encountered.
2976 Returns 0 on success, 1 if errors are encountered.
2977 """
2977 """
2978 wlock = repo.wlock(False)
2978 wlock = repo.wlock(False)
2979 try:
2979 try:
2980 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2980 return cmdutil.copy(ui, repo, pats, opts, rename=True)
2981 finally:
2981 finally:
2982 wlock.release()
2982 wlock.release()
2983
2983
2984 def resolve(ui, repo, *pats, **opts):
2984 def resolve(ui, repo, *pats, **opts):
2985 """redo merges or set/view the merge status of files
2985 """redo merges or set/view the merge status of files
2986
2986
2987 Merges with unresolved conflicts are often the result of
2987 Merges with unresolved conflicts are often the result of
2988 non-interactive merging using the ``internal:merge`` configuration
2988 non-interactive merging using the ``internal:merge`` configuration
2989 setting, or a command-line merge tool like ``diff3``. The resolve
2989 setting, or a command-line merge tool like ``diff3``. The resolve
2990 command is used to manage the files involved in a merge, after
2990 command is used to manage the files involved in a merge, after
2991 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2991 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
2992 working directory must have two parents).
2992 working directory must have two parents).
2993
2993
2994 The resolve command can be used in the following ways:
2994 The resolve command can be used in the following ways:
2995
2995
2996 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2996 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
2997 files, discarding any previous merge attempts. Re-merging is not
2997 files, discarding any previous merge attempts. Re-merging is not
2998 performed for files already marked as resolved. Use ``--all/-a``
2998 performed for files already marked as resolved. Use ``--all/-a``
2999 to selects all unresolved files. ``--tool`` can be used to specify
2999 to selects all unresolved files. ``--tool`` can be used to specify
3000 the merge tool used for the given files. It overrides the HGMERGE
3000 the merge tool used for the given files. It overrides the HGMERGE
3001 environment variable and your configuration files.
3001 environment variable and your configuration files.
3002
3002
3003 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3003 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3004 (e.g. after having manually fixed-up the files). The default is
3004 (e.g. after having manually fixed-up the files). The default is
3005 to mark all unresolved files.
3005 to mark all unresolved files.
3006
3006
3007 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3007 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3008 default is to mark all resolved files.
3008 default is to mark all resolved files.
3009
3009
3010 - :hg:`resolve -l`: list files which had or still have conflicts.
3010 - :hg:`resolve -l`: list files which had or still have conflicts.
3011 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3011 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3012
3012
3013 Note that Mercurial will not let you commit files with unresolved
3013 Note that Mercurial will not let you commit files with unresolved
3014 merge conflicts. You must use :hg:`resolve -m ...` before you can
3014 merge conflicts. You must use :hg:`resolve -m ...` before you can
3015 commit after a conflicting merge.
3015 commit after a conflicting merge.
3016
3016
3017 Returns 0 on success, 1 if any files fail a resolve attempt.
3017 Returns 0 on success, 1 if any files fail a resolve attempt.
3018 """
3018 """
3019
3019
3020 all, mark, unmark, show, nostatus = \
3020 all, mark, unmark, show, nostatus = \
3021 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3021 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3022
3022
3023 if (show and (mark or unmark)) or (mark and unmark):
3023 if (show and (mark or unmark)) or (mark and unmark):
3024 raise util.Abort(_("too many options specified"))
3024 raise util.Abort(_("too many options specified"))
3025 if pats and all:
3025 if pats and all:
3026 raise util.Abort(_("can't specify --all and patterns"))
3026 raise util.Abort(_("can't specify --all and patterns"))
3027 if not (all or pats or show or mark or unmark):
3027 if not (all or pats or show or mark or unmark):
3028 raise util.Abort(_('no files or directories specified; '
3028 raise util.Abort(_('no files or directories specified; '
3029 'use --all to remerge all files'))
3029 'use --all to remerge all files'))
3030
3030
3031 ms = mergemod.mergestate(repo)
3031 ms = mergemod.mergestate(repo)
3032 m = cmdutil.match(repo, pats, opts)
3032 m = cmdutil.match(repo, pats, opts)
3033 ret = 0
3033 ret = 0
3034
3034
3035 for f in ms:
3035 for f in ms:
3036 if m(f):
3036 if m(f):
3037 if show:
3037 if show:
3038 if nostatus:
3038 if nostatus:
3039 ui.write("%s\n" % f)
3039 ui.write("%s\n" % f)
3040 else:
3040 else:
3041 ui.write("%s %s\n" % (ms[f].upper(), f),
3041 ui.write("%s %s\n" % (ms[f].upper(), f),
3042 label='resolve.' +
3042 label='resolve.' +
3043 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3043 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3044 elif mark:
3044 elif mark:
3045 ms.mark(f, "r")
3045 ms.mark(f, "r")
3046 elif unmark:
3046 elif unmark:
3047 ms.mark(f, "u")
3047 ms.mark(f, "u")
3048 else:
3048 else:
3049 wctx = repo[None]
3049 wctx = repo[None]
3050 mctx = wctx.parents()[-1]
3050 mctx = wctx.parents()[-1]
3051
3051
3052 # backup pre-resolve (merge uses .orig for its own purposes)
3052 # backup pre-resolve (merge uses .orig for its own purposes)
3053 a = repo.wjoin(f)
3053 a = repo.wjoin(f)
3054 util.copyfile(a, a + ".resolve")
3054 util.copyfile(a, a + ".resolve")
3055
3055
3056 try:
3056 try:
3057 # resolve file
3057 # resolve file
3058 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3058 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3059 if ms.resolve(f, wctx, mctx):
3059 if ms.resolve(f, wctx, mctx):
3060 ret = 1
3060 ret = 1
3061 finally:
3061 finally:
3062 ui.setconfig('ui', 'forcemerge', '')
3062 ui.setconfig('ui', 'forcemerge', '')
3063
3063
3064 # replace filemerge's .orig file with our resolve file
3064 # replace filemerge's .orig file with our resolve file
3065 util.rename(a + ".resolve", a + ".orig")
3065 util.rename(a + ".resolve", a + ".orig")
3066
3066
3067 ms.commit()
3067 ms.commit()
3068 return ret
3068 return ret
3069
3069
3070 def revert(ui, repo, *pats, **opts):
3070 def revert(ui, repo, *pats, **opts):
3071 """restore individual files or directories to an earlier state
3071 """restore individual files or directories to an earlier state
3072
3072
3073 .. note::
3073 .. note::
3074 This command is most likely not what you are looking for.
3074 This command is most likely not what you are looking for.
3075 Revert will partially overwrite content in the working
3075 Revert will partially overwrite content in the working
3076 directory without changing the working directory parents. Use
3076 directory without changing the working directory parents. Use
3077 :hg:`update -r rev` to check out earlier revisions, or
3077 :hg:`update -r rev` to check out earlier revisions, or
3078 :hg:`update --clean .` to undo a merge which has added another
3078 :hg:`update --clean .` to undo a merge which has added another
3079 parent.
3079 parent.
3080
3080
3081 With no revision specified, revert the named files or directories
3081 With no revision specified, revert the named files or directories
3082 to the contents they had in the parent of the working directory.
3082 to the contents they had in the parent of the working directory.
3083 This restores the contents of the affected files to an unmodified
3083 This restores the contents of the affected files to an unmodified
3084 state and unschedules adds, removes, copies, and renames. If the
3084 state and unschedules adds, removes, copies, and renames. If the
3085 working directory has two parents, you must explicitly specify a
3085 working directory has two parents, you must explicitly specify a
3086 revision.
3086 revision.
3087
3087
3088 Using the -r/--rev option, revert the given files or directories
3088 Using the -r/--rev option, revert the given files or directories
3089 to their contents as of a specific revision. This can be helpful
3089 to their contents as of a specific revision. This can be helpful
3090 to "roll back" some or all of an earlier change. See :hg:`help
3090 to "roll back" some or all of an earlier change. See :hg:`help
3091 dates` for a list of formats valid for -d/--date.
3091 dates` for a list of formats valid for -d/--date.
3092
3092
3093 Revert modifies the working directory. It does not commit any
3093 Revert modifies the working directory. It does not commit any
3094 changes, or change the parent of the working directory. If you
3094 changes, or change the parent of the working directory. If you
3095 revert to a revision other than the parent of the working
3095 revert to a revision other than the parent of the working
3096 directory, the reverted files will thus appear modified
3096 directory, the reverted files will thus appear modified
3097 afterwards.
3097 afterwards.
3098
3098
3099 If a file has been deleted, it is restored. If the executable mode
3099 If a file has been deleted, it is restored. If the executable mode
3100 of a file was changed, it is reset.
3100 of a file was changed, it is reset.
3101
3101
3102 If names are given, all files matching the names are reverted.
3102 If names are given, all files matching the names are reverted.
3103 If no arguments are given, no files are reverted.
3103 If no arguments are given, no files are reverted.
3104
3104
3105 Modified files are saved with a .orig suffix before reverting.
3105 Modified files are saved with a .orig suffix before reverting.
3106 To disable these backups, use --no-backup.
3106 To disable these backups, use --no-backup.
3107
3107
3108 Returns 0 on success.
3108 Returns 0 on success.
3109 """
3109 """
3110
3110
3111 if opts.get("date"):
3111 if opts.get("date"):
3112 if opts.get("rev"):
3112 if opts.get("rev"):
3113 raise util.Abort(_("you can't specify a revision and a date"))
3113 raise util.Abort(_("you can't specify a revision and a date"))
3114 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3114 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3115
3115
3116 parent, p2 = repo.dirstate.parents()
3116 parent, p2 = repo.dirstate.parents()
3117 if not opts.get('rev') and p2 != nullid:
3117 if not opts.get('rev') and p2 != nullid:
3118 raise util.Abort(_('uncommitted merge - '
3118 raise util.Abort(_('uncommitted merge - '
3119 'use "hg update", see "hg help revert"'))
3119 'use "hg update", see "hg help revert"'))
3120
3120
3121 if not pats and not opts.get('all'):
3121 if not pats and not opts.get('all'):
3122 raise util.Abort(_('no files or directories specified; '
3122 raise util.Abort(_('no files or directories specified; '
3123 'use --all to revert the whole repo'))
3123 'use --all to revert the whole repo'))
3124
3124
3125 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3125 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3126 node = ctx.node()
3126 node = ctx.node()
3127 mf = ctx.manifest()
3127 mf = ctx.manifest()
3128 if node == parent:
3128 if node == parent:
3129 pmf = mf
3129 pmf = mf
3130 else:
3130 else:
3131 pmf = None
3131 pmf = None
3132
3132
3133 # need all matching names in dirstate and manifest of target rev,
3133 # need all matching names in dirstate and manifest of target rev,
3134 # so have to walk both. do not print errors if files exist in one
3134 # so have to walk both. do not print errors if files exist in one
3135 # but not other.
3135 # but not other.
3136
3136
3137 names = {}
3137 names = {}
3138
3138
3139 wlock = repo.wlock()
3139 wlock = repo.wlock()
3140 try:
3140 try:
3141 # walk dirstate.
3141 # walk dirstate.
3142
3142
3143 m = cmdutil.match(repo, pats, opts)
3143 m = cmdutil.match(repo, pats, opts)
3144 m.bad = lambda x, y: False
3144 m.bad = lambda x, y: False
3145 for abs in repo.walk(m):
3145 for abs in repo.walk(m):
3146 names[abs] = m.rel(abs), m.exact(abs)
3146 names[abs] = m.rel(abs), m.exact(abs)
3147
3147
3148 # walk target manifest.
3148 # walk target manifest.
3149
3149
3150 def badfn(path, msg):
3150 def badfn(path, msg):
3151 if path in names:
3151 if path in names:
3152 return
3152 return
3153 path_ = path + '/'
3153 path_ = path + '/'
3154 for f in names:
3154 for f in names:
3155 if f.startswith(path_):
3155 if f.startswith(path_):
3156 return
3156 return
3157 ui.warn("%s: %s\n" % (m.rel(path), msg))
3157 ui.warn("%s: %s\n" % (m.rel(path), msg))
3158
3158
3159 m = cmdutil.match(repo, pats, opts)
3159 m = cmdutil.match(repo, pats, opts)
3160 m.bad = badfn
3160 m.bad = badfn
3161 for abs in repo[node].walk(m):
3161 for abs in repo[node].walk(m):
3162 if abs not in names:
3162 if abs not in names:
3163 names[abs] = m.rel(abs), m.exact(abs)
3163 names[abs] = m.rel(abs), m.exact(abs)
3164
3164
3165 m = cmdutil.matchfiles(repo, names)
3165 m = cmdutil.matchfiles(repo, names)
3166 changes = repo.status(match=m)[:4]
3166 changes = repo.status(match=m)[:4]
3167 modified, added, removed, deleted = map(set, changes)
3167 modified, added, removed, deleted = map(set, changes)
3168
3168
3169 # if f is a rename, also revert the source
3169 # if f is a rename, also revert the source
3170 cwd = repo.getcwd()
3170 cwd = repo.getcwd()
3171 for f in added:
3171 for f in added:
3172 src = repo.dirstate.copied(f)
3172 src = repo.dirstate.copied(f)
3173 if src and src not in names and repo.dirstate[src] == 'r':
3173 if src and src not in names and repo.dirstate[src] == 'r':
3174 removed.add(src)
3174 removed.add(src)
3175 names[src] = (repo.pathto(src, cwd), True)
3175 names[src] = (repo.pathto(src, cwd), True)
3176
3176
3177 def removeforget(abs):
3177 def removeforget(abs):
3178 if repo.dirstate[abs] == 'a':
3178 if repo.dirstate[abs] == 'a':
3179 return _('forgetting %s\n')
3179 return _('forgetting %s\n')
3180 return _('removing %s\n')
3180 return _('removing %s\n')
3181
3181
3182 revert = ([], _('reverting %s\n'))
3182 revert = ([], _('reverting %s\n'))
3183 add = ([], _('adding %s\n'))
3183 add = ([], _('adding %s\n'))
3184 remove = ([], removeforget)
3184 remove = ([], removeforget)
3185 undelete = ([], _('undeleting %s\n'))
3185 undelete = ([], _('undeleting %s\n'))
3186
3186
3187 disptable = (
3187 disptable = (
3188 # dispatch table:
3188 # dispatch table:
3189 # file state
3189 # file state
3190 # action if in target manifest
3190 # action if in target manifest
3191 # action if not in target manifest
3191 # action if not in target manifest
3192 # make backup if in target manifest
3192 # make backup if in target manifest
3193 # make backup if not in target manifest
3193 # make backup if not in target manifest
3194 (modified, revert, remove, True, True),
3194 (modified, revert, remove, True, True),
3195 (added, revert, remove, True, False),
3195 (added, revert, remove, True, False),
3196 (removed, undelete, None, False, False),
3196 (removed, undelete, None, False, False),
3197 (deleted, revert, remove, False, False),
3197 (deleted, revert, remove, False, False),
3198 )
3198 )
3199
3199
3200 for abs, (rel, exact) in sorted(names.items()):
3200 for abs, (rel, exact) in sorted(names.items()):
3201 mfentry = mf.get(abs)
3201 mfentry = mf.get(abs)
3202 target = repo.wjoin(abs)
3202 target = repo.wjoin(abs)
3203 def handle(xlist, dobackup):
3203 def handle(xlist, dobackup):
3204 xlist[0].append(abs)
3204 xlist[0].append(abs)
3205 if (dobackup and not opts.get('no_backup') and
3205 if (dobackup and not opts.get('no_backup') and
3206 os.path.lexists(target)):
3206 os.path.lexists(target)):
3207 bakname = "%s.orig" % rel
3207 bakname = "%s.orig" % rel
3208 ui.note(_('saving current version of %s as %s\n') %
3208 ui.note(_('saving current version of %s as %s\n') %
3209 (rel, bakname))
3209 (rel, bakname))
3210 if not opts.get('dry_run'):
3210 if not opts.get('dry_run'):
3211 util.rename(target, bakname)
3211 util.rename(target, bakname)
3212 if ui.verbose or not exact:
3212 if ui.verbose or not exact:
3213 msg = xlist[1]
3213 msg = xlist[1]
3214 if not isinstance(msg, basestring):
3214 if not isinstance(msg, basestring):
3215 msg = msg(abs)
3215 msg = msg(abs)
3216 ui.status(msg % rel)
3216 ui.status(msg % rel)
3217 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3217 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3218 if abs not in table:
3218 if abs not in table:
3219 continue
3219 continue
3220 # file has changed in dirstate
3220 # file has changed in dirstate
3221 if mfentry:
3221 if mfentry:
3222 handle(hitlist, backuphit)
3222 handle(hitlist, backuphit)
3223 elif misslist is not None:
3223 elif misslist is not None:
3224 handle(misslist, backupmiss)
3224 handle(misslist, backupmiss)
3225 break
3225 break
3226 else:
3226 else:
3227 if abs not in repo.dirstate:
3227 if abs not in repo.dirstate:
3228 if mfentry:
3228 if mfentry:
3229 handle(add, True)
3229 handle(add, True)
3230 elif exact:
3230 elif exact:
3231 ui.warn(_('file not managed: %s\n') % rel)
3231 ui.warn(_('file not managed: %s\n') % rel)
3232 continue
3232 continue
3233 # file has not changed in dirstate
3233 # file has not changed in dirstate
3234 if node == parent:
3234 if node == parent:
3235 if exact:
3235 if exact:
3236 ui.warn(_('no changes needed to %s\n') % rel)
3236 ui.warn(_('no changes needed to %s\n') % rel)
3237 continue
3237 continue
3238 if pmf is None:
3238 if pmf is None:
3239 # only need parent manifest in this unlikely case,
3239 # only need parent manifest in this unlikely case,
3240 # so do not read by default
3240 # so do not read by default
3241 pmf = repo[parent].manifest()
3241 pmf = repo[parent].manifest()
3242 if abs in pmf:
3242 if abs in pmf:
3243 if mfentry:
3243 if mfentry:
3244 # if version of file is same in parent and target
3244 # if version of file is same in parent and target
3245 # manifests, do nothing
3245 # manifests, do nothing
3246 if (pmf[abs] != mfentry or
3246 if (pmf[abs] != mfentry or
3247 pmf.flags(abs) != mf.flags(abs)):
3247 pmf.flags(abs) != mf.flags(abs)):
3248 handle(revert, False)
3248 handle(revert, False)
3249 else:
3249 else:
3250 handle(remove, False)
3250 handle(remove, False)
3251
3251
3252 if not opts.get('dry_run'):
3252 if not opts.get('dry_run'):
3253 def checkout(f):
3253 def checkout(f):
3254 fc = ctx[f]
3254 fc = ctx[f]
3255 repo.wwrite(f, fc.data(), fc.flags())
3255 repo.wwrite(f, fc.data(), fc.flags())
3256
3256
3257 audit_path = util.path_auditor(repo.root)
3257 audit_path = util.path_auditor(repo.root)
3258 for f in remove[0]:
3258 for f in remove[0]:
3259 if repo.dirstate[f] == 'a':
3259 if repo.dirstate[f] == 'a':
3260 repo.dirstate.forget(f)
3260 repo.dirstate.forget(f)
3261 continue
3261 continue
3262 audit_path(f)
3262 audit_path(f)
3263 try:
3263 try:
3264 util.unlinkpath(repo.wjoin(f))
3264 util.unlinkpath(repo.wjoin(f))
3265 except OSError:
3265 except OSError:
3266 pass
3266 pass
3267 repo.dirstate.remove(f)
3267 repo.dirstate.remove(f)
3268
3268
3269 normal = None
3269 normal = None
3270 if node == parent:
3270 if node == parent:
3271 # We're reverting to our parent. If possible, we'd like status
3271 # We're reverting to our parent. If possible, we'd like status
3272 # to report the file as clean. We have to use normallookup for
3272 # to report the file as clean. We have to use normallookup for
3273 # merges to avoid losing information about merged/dirty files.
3273 # merges to avoid losing information about merged/dirty files.
3274 if p2 != nullid:
3274 if p2 != nullid:
3275 normal = repo.dirstate.normallookup
3275 normal = repo.dirstate.normallookup
3276 else:
3276 else:
3277 normal = repo.dirstate.normal
3277 normal = repo.dirstate.normal
3278 for f in revert[0]:
3278 for f in revert[0]:
3279 checkout(f)
3279 checkout(f)
3280 if normal:
3280 if normal:
3281 normal(f)
3281 normal(f)
3282
3282
3283 for f in add[0]:
3283 for f in add[0]:
3284 checkout(f)
3284 checkout(f)
3285 repo.dirstate.add(f)
3285 repo.dirstate.add(f)
3286
3286
3287 normal = repo.dirstate.normallookup
3287 normal = repo.dirstate.normallookup
3288 if node == parent and p2 == nullid:
3288 if node == parent and p2 == nullid:
3289 normal = repo.dirstate.normal
3289 normal = repo.dirstate.normal
3290 for f in undelete[0]:
3290 for f in undelete[0]:
3291 checkout(f)
3291 checkout(f)
3292 normal(f)
3292 normal(f)
3293
3293
3294 finally:
3294 finally:
3295 wlock.release()
3295 wlock.release()
3296
3296
3297 def rollback(ui, repo, **opts):
3297 def rollback(ui, repo, **opts):
3298 """roll back the last transaction (dangerous)
3298 """roll back the last transaction (dangerous)
3299
3299
3300 This command should be used with care. There is only one level of
3300 This command should be used with care. There is only one level of
3301 rollback, and there is no way to undo a rollback. It will also
3301 rollback, and there is no way to undo a rollback. It will also
3302 restore the dirstate at the time of the last transaction, losing
3302 restore the dirstate at the time of the last transaction, losing
3303 any dirstate changes since that time. This command does not alter
3303 any dirstate changes since that time. This command does not alter
3304 the working directory.
3304 the working directory.
3305
3305
3306 Transactions are used to encapsulate the effects of all commands
3306 Transactions are used to encapsulate the effects of all commands
3307 that create new changesets or propagate existing changesets into a
3307 that create new changesets or propagate existing changesets into a
3308 repository. For example, the following commands are transactional,
3308 repository. For example, the following commands are transactional,
3309 and their effects can be rolled back:
3309 and their effects can be rolled back:
3310
3310
3311 - commit
3311 - commit
3312 - import
3312 - import
3313 - pull
3313 - pull
3314 - push (with this repository as the destination)
3314 - push (with this repository as the destination)
3315 - unbundle
3315 - unbundle
3316
3316
3317 This command is not intended for use on public repositories. Once
3317 This command is not intended for use on public repositories. Once
3318 changes are visible for pull by other users, rolling a transaction
3318 changes are visible for pull by other users, rolling a transaction
3319 back locally is ineffective (someone else may already have pulled
3319 back locally is ineffective (someone else may already have pulled
3320 the changes). Furthermore, a race is possible with readers of the
3320 the changes). Furthermore, a race is possible with readers of the
3321 repository; for example an in-progress pull from the repository
3321 repository; for example an in-progress pull from the repository
3322 may fail if a rollback is performed.
3322 may fail if a rollback is performed.
3323
3323
3324 Returns 0 on success, 1 if no rollback data is available.
3324 Returns 0 on success, 1 if no rollback data is available.
3325 """
3325 """
3326 return repo.rollback(opts.get('dry_run'))
3326 return repo.rollback(opts.get('dry_run'))
3327
3327
3328 def root(ui, repo):
3328 def root(ui, repo):
3329 """print the root (top) of the current working directory
3329 """print the root (top) of the current working directory
3330
3330
3331 Print the root directory of the current repository.
3331 Print the root directory of the current repository.
3332
3332
3333 Returns 0 on success.
3333 Returns 0 on success.
3334 """
3334 """
3335 ui.write(repo.root + "\n")
3335 ui.write(repo.root + "\n")
3336
3336
3337 def serve(ui, repo, **opts):
3337 def serve(ui, repo, **opts):
3338 """start stand-alone webserver
3338 """start stand-alone webserver
3339
3339
3340 Start a local HTTP repository browser and pull server. You can use
3340 Start a local HTTP repository browser and pull server. You can use
3341 this for ad-hoc sharing and browsing of repositories. It is
3341 this for ad-hoc sharing and browsing of repositories. It is
3342 recommended to use a real web server to serve a repository for
3342 recommended to use a real web server to serve a repository for
3343 longer periods of time.
3343 longer periods of time.
3344
3344
3345 Please note that the server does not implement access control.
3345 Please note that the server does not implement access control.
3346 This means that, by default, anybody can read from the server and
3346 This means that, by default, anybody can read from the server and
3347 nobody can write to it by default. Set the ``web.allow_push``
3347 nobody can write to it by default. Set the ``web.allow_push``
3348 option to ``*`` to allow everybody to push to the server. You
3348 option to ``*`` to allow everybody to push to the server. You
3349 should use a real web server if you need to authenticate users.
3349 should use a real web server if you need to authenticate users.
3350
3350
3351 By default, the server logs accesses to stdout and errors to
3351 By default, the server logs accesses to stdout and errors to
3352 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3352 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3353 files.
3353 files.
3354
3354
3355 To have the server choose a free port number to listen on, specify
3355 To have the server choose a free port number to listen on, specify
3356 a port number of 0; in this case, the server will print the port
3356 a port number of 0; in this case, the server will print the port
3357 number it uses.
3357 number it uses.
3358
3358
3359 Returns 0 on success.
3359 Returns 0 on success.
3360 """
3360 """
3361
3361
3362 if opts["stdio"]:
3362 if opts["stdio"]:
3363 if repo is None:
3363 if repo is None:
3364 raise error.RepoError(_("There is no Mercurial repository here"
3364 raise error.RepoError(_("There is no Mercurial repository here"
3365 " (.hg not found)"))
3365 " (.hg not found)"))
3366 s = sshserver.sshserver(ui, repo)
3366 s = sshserver.sshserver(ui, repo)
3367 s.serve_forever()
3367 s.serve_forever()
3368
3368
3369 # this way we can check if something was given in the command-line
3369 # this way we can check if something was given in the command-line
3370 if opts.get('port'):
3370 if opts.get('port'):
3371 opts['port'] = util.getport(opts.get('port'))
3371 opts['port'] = util.getport(opts.get('port'))
3372
3372
3373 baseui = repo and repo.baseui or ui
3373 baseui = repo and repo.baseui or ui
3374 optlist = ("name templates style address port prefix ipv6"
3374 optlist = ("name templates style address port prefix ipv6"
3375 " accesslog errorlog certificate encoding")
3375 " accesslog errorlog certificate encoding")
3376 for o in optlist.split():
3376 for o in optlist.split():
3377 val = opts.get(o, '')
3377 val = opts.get(o, '')
3378 if val in (None, ''): # should check against default options instead
3378 if val in (None, ''): # should check against default options instead
3379 continue
3379 continue
3380 baseui.setconfig("web", o, val)
3380 baseui.setconfig("web", o, val)
3381 if repo and repo.ui != baseui:
3381 if repo and repo.ui != baseui:
3382 repo.ui.setconfig("web", o, val)
3382 repo.ui.setconfig("web", o, val)
3383
3383
3384 o = opts.get('web_conf') or opts.get('webdir_conf')
3384 o = opts.get('web_conf') or opts.get('webdir_conf')
3385 if not o:
3385 if not o:
3386 if not repo:
3386 if not repo:
3387 raise error.RepoError(_("There is no Mercurial repository"
3387 raise error.RepoError(_("There is no Mercurial repository"
3388 " here (.hg not found)"))
3388 " here (.hg not found)"))
3389 o = repo.root
3389 o = repo.root
3390
3390
3391 app = hgweb.hgweb(o, baseui=ui)
3391 app = hgweb.hgweb(o, baseui=ui)
3392
3392
3393 class service(object):
3393 class service(object):
3394 def init(self):
3394 def init(self):
3395 util.set_signal_handler()
3395 util.set_signal_handler()
3396 self.httpd = hgweb.server.create_server(ui, app)
3396 self.httpd = hgweb.server.create_server(ui, app)
3397
3397
3398 if opts['port'] and not ui.verbose:
3398 if opts['port'] and not ui.verbose:
3399 return
3399 return
3400
3400
3401 if self.httpd.prefix:
3401 if self.httpd.prefix:
3402 prefix = self.httpd.prefix.strip('/') + '/'
3402 prefix = self.httpd.prefix.strip('/') + '/'
3403 else:
3403 else:
3404 prefix = ''
3404 prefix = ''
3405
3405
3406 port = ':%d' % self.httpd.port
3406 port = ':%d' % self.httpd.port
3407 if port == ':80':
3407 if port == ':80':
3408 port = ''
3408 port = ''
3409
3409
3410 bindaddr = self.httpd.addr
3410 bindaddr = self.httpd.addr
3411 if bindaddr == '0.0.0.0':
3411 if bindaddr == '0.0.0.0':
3412 bindaddr = '*'
3412 bindaddr = '*'
3413 elif ':' in bindaddr: # IPv6
3413 elif ':' in bindaddr: # IPv6
3414 bindaddr = '[%s]' % bindaddr
3414 bindaddr = '[%s]' % bindaddr
3415
3415
3416 fqaddr = self.httpd.fqaddr
3416 fqaddr = self.httpd.fqaddr
3417 if ':' in fqaddr:
3417 if ':' in fqaddr:
3418 fqaddr = '[%s]' % fqaddr
3418 fqaddr = '[%s]' % fqaddr
3419 if opts['port']:
3419 if opts['port']:
3420 write = ui.status
3420 write = ui.status
3421 else:
3421 else:
3422 write = ui.write
3422 write = ui.write
3423 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3423 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3424 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3424 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3425
3425
3426 def run(self):
3426 def run(self):
3427 self.httpd.serve_forever()
3427 self.httpd.serve_forever()
3428
3428
3429 service = service()
3429 service = service()
3430
3430
3431 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3431 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3432
3432
3433 def status(ui, repo, *pats, **opts):
3433 def status(ui, repo, *pats, **opts):
3434 """show changed files in the working directory
3434 """show changed files in the working directory
3435
3435
3436 Show status of files in the repository. If names are given, only
3436 Show status of files in the repository. If names are given, only
3437 files that match are shown. Files that are clean or ignored or
3437 files that match are shown. Files that are clean or ignored or
3438 the source of a copy/move operation, are not listed unless
3438 the source of a copy/move operation, are not listed unless
3439 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3439 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3440 Unless options described with "show only ..." are given, the
3440 Unless options described with "show only ..." are given, the
3441 options -mardu are used.
3441 options -mardu are used.
3442
3442
3443 Option -q/--quiet hides untracked (unknown and ignored) files
3443 Option -q/--quiet hides untracked (unknown and ignored) files
3444 unless explicitly requested with -u/--unknown or -i/--ignored.
3444 unless explicitly requested with -u/--unknown or -i/--ignored.
3445
3445
3446 .. note::
3446 .. note::
3447 status may appear to disagree with diff if permissions have
3447 status may appear to disagree with diff if permissions have
3448 changed or a merge has occurred. The standard diff format does
3448 changed or a merge has occurred. The standard diff format does
3449 not report permission changes and diff only reports changes
3449 not report permission changes and diff only reports changes
3450 relative to one merge parent.
3450 relative to one merge parent.
3451
3451
3452 If one revision is given, it is used as the base revision.
3452 If one revision is given, it is used as the base revision.
3453 If two revisions are given, the differences between them are
3453 If two revisions are given, the differences between them are
3454 shown. The --change option can also be used as a shortcut to list
3454 shown. The --change option can also be used as a shortcut to list
3455 the changed files of a revision from its first parent.
3455 the changed files of a revision from its first parent.
3456
3456
3457 The codes used to show the status of files are::
3457 The codes used to show the status of files are::
3458
3458
3459 M = modified
3459 M = modified
3460 A = added
3460 A = added
3461 R = removed
3461 R = removed
3462 C = clean
3462 C = clean
3463 ! = missing (deleted by non-hg command, but still tracked)
3463 ! = missing (deleted by non-hg command, but still tracked)
3464 ? = not tracked
3464 ? = not tracked
3465 I = ignored
3465 I = ignored
3466 = origin of the previous file listed as A (added)
3466 = origin of the previous file listed as A (added)
3467
3467
3468 Returns 0 on success.
3468 Returns 0 on success.
3469 """
3469 """
3470
3470
3471 revs = opts.get('rev')
3471 revs = opts.get('rev')
3472 change = opts.get('change')
3472 change = opts.get('change')
3473
3473
3474 if revs and change:
3474 if revs and change:
3475 msg = _('cannot specify --rev and --change at the same time')
3475 msg = _('cannot specify --rev and --change at the same time')
3476 raise util.Abort(msg)
3476 raise util.Abort(msg)
3477 elif change:
3477 elif change:
3478 node2 = repo.lookup(change)
3478 node2 = repo.lookup(change)
3479 node1 = repo[node2].parents()[0].node()
3479 node1 = repo[node2].parents()[0].node()
3480 else:
3480 else:
3481 node1, node2 = cmdutil.revpair(repo, revs)
3481 node1, node2 = cmdutil.revpair(repo, revs)
3482
3482
3483 cwd = (pats and repo.getcwd()) or ''
3483 cwd = (pats and repo.getcwd()) or ''
3484 end = opts.get('print0') and '\0' or '\n'
3484 end = opts.get('print0') and '\0' or '\n'
3485 copy = {}
3485 copy = {}
3486 states = 'modified added removed deleted unknown ignored clean'.split()
3486 states = 'modified added removed deleted unknown ignored clean'.split()
3487 show = [k for k in states if opts.get(k)]
3487 show = [k for k in states if opts.get(k)]
3488 if opts.get('all'):
3488 if opts.get('all'):
3489 show += ui.quiet and (states[:4] + ['clean']) or states
3489 show += ui.quiet and (states[:4] + ['clean']) or states
3490 if not show:
3490 if not show:
3491 show = ui.quiet and states[:4] or states[:5]
3491 show = ui.quiet and states[:4] or states[:5]
3492
3492
3493 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3493 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3494 'ignored' in show, 'clean' in show, 'unknown' in show,
3494 'ignored' in show, 'clean' in show, 'unknown' in show,
3495 opts.get('subrepos'))
3495 opts.get('subrepos'))
3496 changestates = zip(states, 'MAR!?IC', stat)
3496 changestates = zip(states, 'MAR!?IC', stat)
3497
3497
3498 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3498 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3499 ctxn = repo[nullid]
3499 ctxn = repo[nullid]
3500 ctx1 = repo[node1]
3500 ctx1 = repo[node1]
3501 ctx2 = repo[node2]
3501 ctx2 = repo[node2]
3502 added = stat[1]
3502 added = stat[1]
3503 if node2 is None:
3503 if node2 is None:
3504 added = stat[0] + stat[1] # merged?
3504 added = stat[0] + stat[1] # merged?
3505
3505
3506 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3506 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3507 if k in added:
3507 if k in added:
3508 copy[k] = v
3508 copy[k] = v
3509 elif v in added:
3509 elif v in added:
3510 copy[v] = k
3510 copy[v] = k
3511
3511
3512 for state, char, files in changestates:
3512 for state, char, files in changestates:
3513 if state in show:
3513 if state in show:
3514 format = "%s %%s%s" % (char, end)
3514 format = "%s %%s%s" % (char, end)
3515 if opts.get('no_status'):
3515 if opts.get('no_status'):
3516 format = "%%s%s" % end
3516 format = "%%s%s" % end
3517
3517
3518 for f in files:
3518 for f in files:
3519 ui.write(format % repo.pathto(f, cwd),
3519 ui.write(format % repo.pathto(f, cwd),
3520 label='status.' + state)
3520 label='status.' + state)
3521 if f in copy:
3521 if f in copy:
3522 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3522 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3523 label='status.copied')
3523 label='status.copied')
3524
3524
3525 def summary(ui, repo, **opts):
3525 def summary(ui, repo, **opts):
3526 """summarize working directory state
3526 """summarize working directory state
3527
3527
3528 This generates a brief summary of the working directory state,
3528 This generates a brief summary of the working directory state,
3529 including parents, branch, commit status, and available updates.
3529 including parents, branch, commit status, and available updates.
3530
3530
3531 With the --remote option, this will check the default paths for
3531 With the --remote option, this will check the default paths for
3532 incoming and outgoing changes. This can be time-consuming.
3532 incoming and outgoing changes. This can be time-consuming.
3533
3533
3534 Returns 0 on success.
3534 Returns 0 on success.
3535 """
3535 """
3536
3536
3537 ctx = repo[None]
3537 ctx = repo[None]
3538 parents = ctx.parents()
3538 parents = ctx.parents()
3539 pnode = parents[0].node()
3539 pnode = parents[0].node()
3540
3540
3541 for p in parents:
3541 for p in parents:
3542 # label with log.changeset (instead of log.parent) since this
3542 # label with log.changeset (instead of log.parent) since this
3543 # shows a working directory parent *changeset*:
3543 # shows a working directory parent *changeset*:
3544 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3544 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3545 label='log.changeset')
3545 label='log.changeset')
3546 ui.write(' '.join(p.tags()), label='log.tag')
3546 ui.write(' '.join(p.tags()), label='log.tag')
3547 if p.rev() == -1:
3547 if p.rev() == -1:
3548 if not len(repo):
3548 if not len(repo):
3549 ui.write(_(' (empty repository)'))
3549 ui.write(_(' (empty repository)'))
3550 else:
3550 else:
3551 ui.write(_(' (no revision checked out)'))
3551 ui.write(_(' (no revision checked out)'))
3552 ui.write('\n')
3552 ui.write('\n')
3553 if p.description():
3553 if p.description():
3554 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3554 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3555 label='log.summary')
3555 label='log.summary')
3556
3556
3557 branch = ctx.branch()
3557 branch = ctx.branch()
3558 bheads = repo.branchheads(branch)
3558 bheads = repo.branchheads(branch)
3559 m = _('branch: %s\n') % branch
3559 m = _('branch: %s\n') % branch
3560 if branch != 'default':
3560 if branch != 'default':
3561 ui.write(m, label='log.branch')
3561 ui.write(m, label='log.branch')
3562 else:
3562 else:
3563 ui.status(m, label='log.branch')
3563 ui.status(m, label='log.branch')
3564
3564
3565 st = list(repo.status(unknown=True))[:6]
3565 st = list(repo.status(unknown=True))[:6]
3566
3566
3567 c = repo.dirstate.copies()
3567 c = repo.dirstate.copies()
3568 copied, renamed = [], []
3568 copied, renamed = [], []
3569 for d, s in c.iteritems():
3569 for d, s in c.iteritems():
3570 if s in st[2]:
3570 if s in st[2]:
3571 st[2].remove(s)
3571 st[2].remove(s)
3572 renamed.append(d)
3572 renamed.append(d)
3573 else:
3573 else:
3574 copied.append(d)
3574 copied.append(d)
3575 if d in st[1]:
3575 if d in st[1]:
3576 st[1].remove(d)
3576 st[1].remove(d)
3577 st.insert(3, renamed)
3577 st.insert(3, renamed)
3578 st.insert(4, copied)
3578 st.insert(4, copied)
3579
3579
3580 ms = mergemod.mergestate(repo)
3580 ms = mergemod.mergestate(repo)
3581 st.append([f for f in ms if ms[f] == 'u'])
3581 st.append([f for f in ms if ms[f] == 'u'])
3582
3582
3583 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3583 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3584 st.append(subs)
3584 st.append(subs)
3585
3585
3586 labels = [ui.label(_('%d modified'), 'status.modified'),
3586 labels = [ui.label(_('%d modified'), 'status.modified'),
3587 ui.label(_('%d added'), 'status.added'),
3587 ui.label(_('%d added'), 'status.added'),
3588 ui.label(_('%d removed'), 'status.removed'),
3588 ui.label(_('%d removed'), 'status.removed'),
3589 ui.label(_('%d renamed'), 'status.copied'),
3589 ui.label(_('%d renamed'), 'status.copied'),
3590 ui.label(_('%d copied'), 'status.copied'),
3590 ui.label(_('%d copied'), 'status.copied'),
3591 ui.label(_('%d deleted'), 'status.deleted'),
3591 ui.label(_('%d deleted'), 'status.deleted'),
3592 ui.label(_('%d unknown'), 'status.unknown'),
3592 ui.label(_('%d unknown'), 'status.unknown'),
3593 ui.label(_('%d ignored'), 'status.ignored'),
3593 ui.label(_('%d ignored'), 'status.ignored'),
3594 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3594 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3595 ui.label(_('%d subrepos'), 'status.modified')]
3595 ui.label(_('%d subrepos'), 'status.modified')]
3596 t = []
3596 t = []
3597 for s, l in zip(st, labels):
3597 for s, l in zip(st, labels):
3598 if s:
3598 if s:
3599 t.append(l % len(s))
3599 t.append(l % len(s))
3600
3600
3601 t = ', '.join(t)
3601 t = ', '.join(t)
3602 cleanworkdir = False
3602 cleanworkdir = False
3603
3603
3604 if len(parents) > 1:
3604 if len(parents) > 1:
3605 t += _(' (merge)')
3605 t += _(' (merge)')
3606 elif branch != parents[0].branch():
3606 elif branch != parents[0].branch():
3607 t += _(' (new branch)')
3607 t += _(' (new branch)')
3608 elif (parents[0].extra().get('close') and
3608 elif (parents[0].extra().get('close') and
3609 pnode in repo.branchheads(branch, closed=True)):
3609 pnode in repo.branchheads(branch, closed=True)):
3610 t += _(' (head closed)')
3610 t += _(' (head closed)')
3611 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3611 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3612 t += _(' (clean)')
3612 t += _(' (clean)')
3613 cleanworkdir = True
3613 cleanworkdir = True
3614 elif pnode not in bheads:
3614 elif pnode not in bheads:
3615 t += _(' (new branch head)')
3615 t += _(' (new branch head)')
3616
3616
3617 if cleanworkdir:
3617 if cleanworkdir:
3618 ui.status(_('commit: %s\n') % t.strip())
3618 ui.status(_('commit: %s\n') % t.strip())
3619 else:
3619 else:
3620 ui.write(_('commit: %s\n') % t.strip())
3620 ui.write(_('commit: %s\n') % t.strip())
3621
3621
3622 # all ancestors of branch heads - all ancestors of parent = new csets
3622 # all ancestors of branch heads - all ancestors of parent = new csets
3623 new = [0] * len(repo)
3623 new = [0] * len(repo)
3624 cl = repo.changelog
3624 cl = repo.changelog
3625 for a in [cl.rev(n) for n in bheads]:
3625 for a in [cl.rev(n) for n in bheads]:
3626 new[a] = 1
3626 new[a] = 1
3627 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3627 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3628 new[a] = 1
3628 new[a] = 1
3629 for a in [p.rev() for p in parents]:
3629 for a in [p.rev() for p in parents]:
3630 if a >= 0:
3630 if a >= 0:
3631 new[a] = 0
3631 new[a] = 0
3632 for a in cl.ancestors(*[p.rev() for p in parents]):
3632 for a in cl.ancestors(*[p.rev() for p in parents]):
3633 new[a] = 0
3633 new[a] = 0
3634 new = sum(new)
3634 new = sum(new)
3635
3635
3636 if new == 0:
3636 if new == 0:
3637 ui.status(_('update: (current)\n'))
3637 ui.status(_('update: (current)\n'))
3638 elif pnode not in bheads:
3638 elif pnode not in bheads:
3639 ui.write(_('update: %d new changesets (update)\n') % new)
3639 ui.write(_('update: %d new changesets (update)\n') % new)
3640 else:
3640 else:
3641 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3641 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3642 (new, len(bheads)))
3642 (new, len(bheads)))
3643
3643
3644 if opts.get('remote'):
3644 if opts.get('remote'):
3645 t = []
3645 t = []
3646 source, branches = hg.parseurl(ui.expandpath('default'))
3646 source, branches = hg.parseurl(ui.expandpath('default'))
3647 other = hg.repository(hg.remoteui(repo, {}), source)
3647 other = hg.repository(hg.remoteui(repo, {}), source)
3648 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3648 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3649 ui.debug('comparing with %s\n' % url.hidepassword(source))
3649 ui.debug('comparing with %s\n' % url.hidepassword(source))
3650 repo.ui.pushbuffer()
3650 repo.ui.pushbuffer()
3651 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3651 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3652 repo.ui.popbuffer()
3652 repo.ui.popbuffer()
3653 if incoming:
3653 if incoming:
3654 t.append(_('1 or more incoming'))
3654 t.append(_('1 or more incoming'))
3655
3655
3656 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3656 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3657 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3657 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3658 other = hg.repository(hg.remoteui(repo, {}), dest)
3658 other = hg.repository(hg.remoteui(repo, {}), dest)
3659 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3659 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3660 repo.ui.pushbuffer()
3660 repo.ui.pushbuffer()
3661 o = discovery.findoutgoing(repo, other)
3661 o = discovery.findoutgoing(repo, other)
3662 repo.ui.popbuffer()
3662 repo.ui.popbuffer()
3663 o = repo.changelog.nodesbetween(o, None)[0]
3663 o = repo.changelog.nodesbetween(o, None)[0]
3664 if o:
3664 if o:
3665 t.append(_('%d outgoing') % len(o))
3665 t.append(_('%d outgoing') % len(o))
3666
3666
3667 if t:
3667 if t:
3668 ui.write(_('remote: %s\n') % (', '.join(t)))
3668 ui.write(_('remote: %s\n') % (', '.join(t)))
3669 else:
3669 else:
3670 ui.status(_('remote: (synced)\n'))
3670 ui.status(_('remote: (synced)\n'))
3671
3671
3672 def tag(ui, repo, name1, *names, **opts):
3672 def tag(ui, repo, name1, *names, **opts):
3673 """add one or more tags for the current or given revision
3673 """add one or more tags for the current or given revision
3674
3674
3675 Name a particular revision using <name>.
3675 Name a particular revision using <name>.
3676
3676
3677 Tags are used to name particular revisions of the repository and are
3677 Tags are used to name particular revisions of the repository and are
3678 very useful to compare different revisions, to go back to significant
3678 very useful to compare different revisions, to go back to significant
3679 earlier versions or to mark branch points as releases, etc. Changing
3679 earlier versions or to mark branch points as releases, etc. Changing
3680 an existing tag is normally disallowed; use -f/--force to override.
3680 an existing tag is normally disallowed; use -f/--force to override.
3681
3681
3682 If no revision is given, the parent of the working directory is
3682 If no revision is given, the parent of the working directory is
3683 used, or tip if no revision is checked out.
3683 used, or tip if no revision is checked out.
3684
3684
3685 To facilitate version control, distribution, and merging of tags,
3685 To facilitate version control, distribution, and merging of tags,
3686 they are stored as a file named ".hgtags" which is managed similarly
3686 they are stored as a file named ".hgtags" which is managed similarly
3687 to other project files and can be hand-edited if necessary. This
3687 to other project files and can be hand-edited if necessary. This
3688 also means that tagging creates a new commit. The file
3688 also means that tagging creates a new commit. The file
3689 ".hg/localtags" is used for local tags (not shared among
3689 ".hg/localtags" is used for local tags (not shared among
3690 repositories).
3690 repositories).
3691
3691
3692 Tag commits are usually made at the head of a branch. If the parent
3692 Tag commits are usually made at the head of a branch. If the parent
3693 of the working directory is not a branch head, :hg:`tag` aborts; use
3693 of the working directory is not a branch head, :hg:`tag` aborts; use
3694 -f/--force to force the tag commit to be based on a non-head
3694 -f/--force to force the tag commit to be based on a non-head
3695 changeset.
3695 changeset.
3696
3696
3697 See :hg:`help dates` for a list of formats valid for -d/--date.
3697 See :hg:`help dates` for a list of formats valid for -d/--date.
3698
3698
3699 Since tag names have priority over branch names during revision
3699 Since tag names have priority over branch names during revision
3700 lookup, using an existing branch name as a tag name is discouraged.
3700 lookup, using an existing branch name as a tag name is discouraged.
3701
3701
3702 Returns 0 on success.
3702 Returns 0 on success.
3703 """
3703 """
3704
3704
3705 rev_ = "."
3705 rev_ = "."
3706 names = [t.strip() for t in (name1,) + names]
3706 names = [t.strip() for t in (name1,) + names]
3707 if len(names) != len(set(names)):
3707 if len(names) != len(set(names)):
3708 raise util.Abort(_('tag names must be unique'))
3708 raise util.Abort(_('tag names must be unique'))
3709 for n in names:
3709 for n in names:
3710 if n in ['tip', '.', 'null']:
3710 if n in ['tip', '.', 'null']:
3711 raise util.Abort(_('the name \'%s\' is reserved') % n)
3711 raise util.Abort(_('the name \'%s\' is reserved') % n)
3712 if not n:
3712 if not n:
3713 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3713 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3714 if opts.get('rev') and opts.get('remove'):
3714 if opts.get('rev') and opts.get('remove'):
3715 raise util.Abort(_("--rev and --remove are incompatible"))
3715 raise util.Abort(_("--rev and --remove are incompatible"))
3716 if opts.get('rev'):
3716 if opts.get('rev'):
3717 rev_ = opts['rev']
3717 rev_ = opts['rev']
3718 message = opts.get('message')
3718 message = opts.get('message')
3719 if opts.get('remove'):
3719 if opts.get('remove'):
3720 expectedtype = opts.get('local') and 'local' or 'global'
3720 expectedtype = opts.get('local') and 'local' or 'global'
3721 for n in names:
3721 for n in names:
3722 if not repo.tagtype(n):
3722 if not repo.tagtype(n):
3723 raise util.Abort(_('tag \'%s\' does not exist') % n)
3723 raise util.Abort(_('tag \'%s\' does not exist') % n)
3724 if repo.tagtype(n) != expectedtype:
3724 if repo.tagtype(n) != expectedtype:
3725 if expectedtype == 'global':
3725 if expectedtype == 'global':
3726 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3726 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3727 else:
3727 else:
3728 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3728 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3729 rev_ = nullid
3729 rev_ = nullid
3730 if not message:
3730 if not message:
3731 # we don't translate commit messages
3731 # we don't translate commit messages
3732 message = 'Removed tag %s' % ', '.join(names)
3732 message = 'Removed tag %s' % ', '.join(names)
3733 elif not opts.get('force'):
3733 elif not opts.get('force'):
3734 for n in names:
3734 for n in names:
3735 if n in repo.tags():
3735 if n in repo.tags():
3736 raise util.Abort(_('tag \'%s\' already exists '
3736 raise util.Abort(_('tag \'%s\' already exists '
3737 '(use -f to force)') % n)
3737 '(use -f to force)') % n)
3738 if not opts.get('local'):
3738 if not opts.get('local'):
3739 p1, p2 = repo.dirstate.parents()
3739 p1, p2 = repo.dirstate.parents()
3740 if p2 != nullid:
3740 if p2 != nullid:
3741 raise util.Abort(_('uncommitted merge'))
3741 raise util.Abort(_('uncommitted merge'))
3742 bheads = repo.branchheads()
3742 bheads = repo.branchheads()
3743 if not opts.get('force') and bheads and p1 not in bheads:
3743 if not opts.get('force') and bheads and p1 not in bheads:
3744 raise util.Abort(_('not at a branch head (use -f to force)'))
3744 raise util.Abort(_('not at a branch head (use -f to force)'))
3745 r = cmdutil.revsingle(repo, rev_).node()
3745 r = cmdutil.revsingle(repo, rev_).node()
3746
3746
3747 if not message:
3747 if not message:
3748 # we don't translate commit messages
3748 # we don't translate commit messages
3749 message = ('Added tag %s for changeset %s' %
3749 message = ('Added tag %s for changeset %s' %
3750 (', '.join(names), short(r)))
3750 (', '.join(names), short(r)))
3751
3751
3752 date = opts.get('date')
3752 date = opts.get('date')
3753 if date:
3753 if date:
3754 date = util.parsedate(date)
3754 date = util.parsedate(date)
3755
3755
3756 if opts.get('edit'):
3756 if opts.get('edit'):
3757 message = ui.edit(message, ui.username())
3757 message = ui.edit(message, ui.username())
3758
3758
3759 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3759 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3760
3760
3761 def tags(ui, repo):
3761 def tags(ui, repo):
3762 """list repository tags
3762 """list repository tags
3763
3763
3764 This lists both regular and local tags. When the -v/--verbose
3764 This lists both regular and local tags. When the -v/--verbose
3765 switch is used, a third column "local" is printed for local tags.
3765 switch is used, a third column "local" is printed for local tags.
3766
3766
3767 Returns 0 on success.
3767 Returns 0 on success.
3768 """
3768 """
3769
3769
3770 hexfunc = ui.debugflag and hex or short
3770 hexfunc = ui.debugflag and hex or short
3771 tagtype = ""
3771 tagtype = ""
3772
3772
3773 for t, n in reversed(repo.tagslist()):
3773 for t, n in reversed(repo.tagslist()):
3774 if ui.quiet:
3774 if ui.quiet:
3775 ui.write("%s\n" % t)
3775 ui.write("%s\n" % t)
3776 continue
3776 continue
3777
3777
3778 try:
3778 try:
3779 hn = hexfunc(n)
3779 hn = hexfunc(n)
3780 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3780 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3781 except error.LookupError:
3781 except error.LookupError:
3782 r = " ?:%s" % hn
3782 r = " ?:%s" % hn
3783 else:
3783 else:
3784 spaces = " " * (30 - encoding.colwidth(t))
3784 spaces = " " * (30 - encoding.colwidth(t))
3785 if ui.verbose:
3785 if ui.verbose:
3786 if repo.tagtype(t) == 'local':
3786 if repo.tagtype(t) == 'local':
3787 tagtype = " local"
3787 tagtype = " local"
3788 else:
3788 else:
3789 tagtype = ""
3789 tagtype = ""
3790 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3790 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3791
3791
3792 def tip(ui, repo, **opts):
3792 def tip(ui, repo, **opts):
3793 """show the tip revision
3793 """show the tip revision
3794
3794
3795 The tip revision (usually just called the tip) is the changeset
3795 The tip revision (usually just called the tip) is the changeset
3796 most recently added to the repository (and therefore the most
3796 most recently added to the repository (and therefore the most
3797 recently changed head).
3797 recently changed head).
3798
3798
3799 If you have just made a commit, that commit will be the tip. If
3799 If you have just made a commit, that commit will be the tip. If
3800 you have just pulled changes from another repository, the tip of
3800 you have just pulled changes from another repository, the tip of
3801 that repository becomes the current tip. The "tip" tag is special
3801 that repository becomes the current tip. The "tip" tag is special
3802 and cannot be renamed or assigned to a different changeset.
3802 and cannot be renamed or assigned to a different changeset.
3803
3803
3804 Returns 0 on success.
3804 Returns 0 on success.
3805 """
3805 """
3806 displayer = cmdutil.show_changeset(ui, repo, opts)
3806 displayer = cmdutil.show_changeset(ui, repo, opts)
3807 displayer.show(repo[len(repo) - 1])
3807 displayer.show(repo[len(repo) - 1])
3808 displayer.close()
3808 displayer.close()
3809
3809
3810 def unbundle(ui, repo, fname1, *fnames, **opts):
3810 def unbundle(ui, repo, fname1, *fnames, **opts):
3811 """apply one or more changegroup files
3811 """apply one or more changegroup files
3812
3812
3813 Apply one or more compressed changegroup files generated by the
3813 Apply one or more compressed changegroup files generated by the
3814 bundle command.
3814 bundle command.
3815
3815
3816 Returns 0 on success, 1 if an update has unresolved files.
3816 Returns 0 on success, 1 if an update has unresolved files.
3817 """
3817 """
3818 fnames = (fname1,) + fnames
3818 fnames = (fname1,) + fnames
3819
3819
3820 lock = repo.lock()
3820 lock = repo.lock()
3821 try:
3821 try:
3822 for fname in fnames:
3822 for fname in fnames:
3823 f = url.open(ui, fname)
3823 f = url.open(ui, fname)
3824 gen = changegroup.readbundle(f, fname)
3824 gen = changegroup.readbundle(f, fname)
3825 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3825 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3826 lock=lock)
3826 lock=lock)
3827 finally:
3827 finally:
3828 lock.release()
3828 lock.release()
3829
3829
3830 return postincoming(ui, repo, modheads, opts.get('update'), None)
3830 return postincoming(ui, repo, modheads, opts.get('update'), None)
3831
3831
3832 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3832 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3833 """update working directory (or switch revisions)
3833 """update working directory (or switch revisions)
3834
3834
3835 Update the repository's working directory to the specified
3835 Update the repository's working directory to the specified
3836 changeset. If no changeset is specified, update to the tip of the
3836 changeset. If no changeset is specified, update to the tip of the
3837 current named branch.
3837 current named branch.
3838
3838
3839 If the changeset is not a descendant of the working directory's
3839 If the changeset is not a descendant of the working directory's
3840 parent, the update is aborted. With the -c/--check option, the
3840 parent, the update is aborted. With the -c/--check option, the
3841 working directory is checked for uncommitted changes; if none are
3841 working directory is checked for uncommitted changes; if none are
3842 found, the working directory is updated to the specified
3842 found, the working directory is updated to the specified
3843 changeset.
3843 changeset.
3844
3844
3845 The following rules apply when the working directory contains
3845 The following rules apply when the working directory contains
3846 uncommitted changes:
3846 uncommitted changes:
3847
3847
3848 1. If neither -c/--check nor -C/--clean is specified, and if
3848 1. If neither -c/--check nor -C/--clean is specified, and if
3849 the requested changeset is an ancestor or descendant of
3849 the requested changeset is an ancestor or descendant of
3850 the working directory's parent, the uncommitted changes
3850 the working directory's parent, the uncommitted changes
3851 are merged into the requested changeset and the merged
3851 are merged into the requested changeset and the merged
3852 result is left uncommitted. If the requested changeset is
3852 result is left uncommitted. If the requested changeset is
3853 not an ancestor or descendant (that is, it is on another
3853 not an ancestor or descendant (that is, it is on another
3854 branch), the update is aborted and the uncommitted changes
3854 branch), the update is aborted and the uncommitted changes
3855 are preserved.
3855 are preserved.
3856
3856
3857 2. With the -c/--check option, the update is aborted and the
3857 2. With the -c/--check option, the update is aborted and the
3858 uncommitted changes are preserved.
3858 uncommitted changes are preserved.
3859
3859
3860 3. With the -C/--clean option, uncommitted changes are discarded and
3860 3. With the -C/--clean option, uncommitted changes are discarded and
3861 the working directory is updated to the requested changeset.
3861 the working directory is updated to the requested changeset.
3862
3862
3863 Use null as the changeset to remove the working directory (like
3863 Use null as the changeset to remove the working directory (like
3864 :hg:`clone -U`).
3864 :hg:`clone -U`).
3865
3865
3866 If you want to update just one file to an older changeset, use
3866 If you want to update just one file to an older changeset, use
3867 :hg:`revert`.
3867 :hg:`revert`.
3868
3868
3869 See :hg:`help dates` for a list of formats valid for -d/--date.
3869 See :hg:`help dates` for a list of formats valid for -d/--date.
3870
3870
3871 Returns 0 on success, 1 if there are unresolved files.
3871 Returns 0 on success, 1 if there are unresolved files.
3872 """
3872 """
3873 if rev and node:
3873 if rev and node:
3874 raise util.Abort(_("please specify just one revision"))
3874 raise util.Abort(_("please specify just one revision"))
3875
3875
3876 if not rev:
3876 if not rev:
3877 rev = node
3877 rev = node
3878
3878
3879 rev = cmdutil.revsingle(repo, rev, rev).rev()
3879 rev = cmdutil.revsingle(repo, rev, rev).rev()
3880
3880
3881 if check and clean:
3881 if check and clean:
3882 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3882 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
3883
3883
3884 if check:
3884 if check:
3885 # we could use dirty() but we can ignore merge and branch trivia
3885 # we could use dirty() but we can ignore merge and branch trivia
3886 c = repo[None]
3886 c = repo[None]
3887 if c.modified() or c.added() or c.removed():
3887 if c.modified() or c.added() or c.removed():
3888 raise util.Abort(_("uncommitted local changes"))
3888 raise util.Abort(_("uncommitted local changes"))
3889
3889
3890 if date:
3890 if date:
3891 if rev:
3891 if rev:
3892 raise util.Abort(_("you can't specify a revision and a date"))
3892 raise util.Abort(_("you can't specify a revision and a date"))
3893 rev = cmdutil.finddate(ui, repo, date)
3893 rev = cmdutil.finddate(ui, repo, date)
3894
3894
3895 if clean or check:
3895 if clean or check:
3896 return hg.clean(repo, rev)
3896 ret = hg.clean(repo, rev)
3897 else:
3897 else:
3898 return hg.update(repo, rev)
3898 ret = hg.update(repo, rev)
3899
3900 if repo.ui.configbool('bookmarks', 'track.current'):
3901 bookmarks.setcurrent(repo, rev)
3902
3903 return ret
3899
3904
3900 def verify(ui, repo):
3905 def verify(ui, repo):
3901 """verify the integrity of the repository
3906 """verify the integrity of the repository
3902
3907
3903 Verify the integrity of the current repository.
3908 Verify the integrity of the current repository.
3904
3909
3905 This will perform an extensive check of the repository's
3910 This will perform an extensive check of the repository's
3906 integrity, validating the hashes and checksums of each entry in
3911 integrity, validating the hashes and checksums of each entry in
3907 the changelog, manifest, and tracked files, as well as the
3912 the changelog, manifest, and tracked files, as well as the
3908 integrity of their crosslinks and indices.
3913 integrity of their crosslinks and indices.
3909
3914
3910 Returns 0 on success, 1 if errors are encountered.
3915 Returns 0 on success, 1 if errors are encountered.
3911 """
3916 """
3912 return hg.verify(repo)
3917 return hg.verify(repo)
3913
3918
3914 def version_(ui):
3919 def version_(ui):
3915 """output version and copyright information"""
3920 """output version and copyright information"""
3916 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3921 ui.write(_("Mercurial Distributed SCM (version %s)\n")
3917 % util.version())
3922 % util.version())
3918 ui.status(_(
3923 ui.status(_(
3919 "(see http://mercurial.selenic.com for more information)\n"
3924 "(see http://mercurial.selenic.com for more information)\n"
3920 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3925 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
3921 "This is free software; see the source for copying conditions. "
3926 "This is free software; see the source for copying conditions. "
3922 "There is NO\nwarranty; "
3927 "There is NO\nwarranty; "
3923 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3928 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
3924 ))
3929 ))
3925
3930
3926 # Command options and aliases are listed here, alphabetically
3931 # Command options and aliases are listed here, alphabetically
3927
3932
3928 globalopts = [
3933 globalopts = [
3929 ('R', 'repository', '',
3934 ('R', 'repository', '',
3930 _('repository root directory or name of overlay bundle file'),
3935 _('repository root directory or name of overlay bundle file'),
3931 _('REPO')),
3936 _('REPO')),
3932 ('', 'cwd', '',
3937 ('', 'cwd', '',
3933 _('change working directory'), _('DIR')),
3938 _('change working directory'), _('DIR')),
3934 ('y', 'noninteractive', None,
3939 ('y', 'noninteractive', None,
3935 _('do not prompt, assume \'yes\' for any required answers')),
3940 _('do not prompt, assume \'yes\' for any required answers')),
3936 ('q', 'quiet', None, _('suppress output')),
3941 ('q', 'quiet', None, _('suppress output')),
3937 ('v', 'verbose', None, _('enable additional output')),
3942 ('v', 'verbose', None, _('enable additional output')),
3938 ('', 'config', [],
3943 ('', 'config', [],
3939 _('set/override config option (use \'section.name=value\')'),
3944 _('set/override config option (use \'section.name=value\')'),
3940 _('CONFIG')),
3945 _('CONFIG')),
3941 ('', 'debug', None, _('enable debugging output')),
3946 ('', 'debug', None, _('enable debugging output')),
3942 ('', 'debugger', None, _('start debugger')),
3947 ('', 'debugger', None, _('start debugger')),
3943 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3948 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
3944 _('ENCODE')),
3949 _('ENCODE')),
3945 ('', 'encodingmode', encoding.encodingmode,
3950 ('', 'encodingmode', encoding.encodingmode,
3946 _('set the charset encoding mode'), _('MODE')),
3951 _('set the charset encoding mode'), _('MODE')),
3947 ('', 'traceback', None, _('always print a traceback on exception')),
3952 ('', 'traceback', None, _('always print a traceback on exception')),
3948 ('', 'time', None, _('time how long the command takes')),
3953 ('', 'time', None, _('time how long the command takes')),
3949 ('', 'profile', None, _('print command execution profile')),
3954 ('', 'profile', None, _('print command execution profile')),
3950 ('', 'version', None, _('output version information and exit')),
3955 ('', 'version', None, _('output version information and exit')),
3951 ('h', 'help', None, _('display help and exit')),
3956 ('h', 'help', None, _('display help and exit')),
3952 ]
3957 ]
3953
3958
3954 dryrunopts = [('n', 'dry-run', None,
3959 dryrunopts = [('n', 'dry-run', None,
3955 _('do not perform actions, just print output'))]
3960 _('do not perform actions, just print output'))]
3956
3961
3957 remoteopts = [
3962 remoteopts = [
3958 ('e', 'ssh', '',
3963 ('e', 'ssh', '',
3959 _('specify ssh command to use'), _('CMD')),
3964 _('specify ssh command to use'), _('CMD')),
3960 ('', 'remotecmd', '',
3965 ('', 'remotecmd', '',
3961 _('specify hg command to run on the remote side'), _('CMD')),
3966 _('specify hg command to run on the remote side'), _('CMD')),
3962 ('', 'insecure', None,
3967 ('', 'insecure', None,
3963 _('do not verify server certificate (ignoring web.cacerts config)')),
3968 _('do not verify server certificate (ignoring web.cacerts config)')),
3964 ]
3969 ]
3965
3970
3966 walkopts = [
3971 walkopts = [
3967 ('I', 'include', [],
3972 ('I', 'include', [],
3968 _('include names matching the given patterns'), _('PATTERN')),
3973 _('include names matching the given patterns'), _('PATTERN')),
3969 ('X', 'exclude', [],
3974 ('X', 'exclude', [],
3970 _('exclude names matching the given patterns'), _('PATTERN')),
3975 _('exclude names matching the given patterns'), _('PATTERN')),
3971 ]
3976 ]
3972
3977
3973 commitopts = [
3978 commitopts = [
3974 ('m', 'message', '',
3979 ('m', 'message', '',
3975 _('use text as commit message'), _('TEXT')),
3980 _('use text as commit message'), _('TEXT')),
3976 ('l', 'logfile', '',
3981 ('l', 'logfile', '',
3977 _('read commit message from file'), _('FILE')),
3982 _('read commit message from file'), _('FILE')),
3978 ]
3983 ]
3979
3984
3980 commitopts2 = [
3985 commitopts2 = [
3981 ('d', 'date', '',
3986 ('d', 'date', '',
3982 _('record datecode as commit date'), _('DATE')),
3987 _('record datecode as commit date'), _('DATE')),
3983 ('u', 'user', '',
3988 ('u', 'user', '',
3984 _('record the specified user as committer'), _('USER')),
3989 _('record the specified user as committer'), _('USER')),
3985 ]
3990 ]
3986
3991
3987 templateopts = [
3992 templateopts = [
3988 ('', 'style', '',
3993 ('', 'style', '',
3989 _('display using template map file'), _('STYLE')),
3994 _('display using template map file'), _('STYLE')),
3990 ('', 'template', '',
3995 ('', 'template', '',
3991 _('display with template'), _('TEMPLATE')),
3996 _('display with template'), _('TEMPLATE')),
3992 ]
3997 ]
3993
3998
3994 logopts = [
3999 logopts = [
3995 ('p', 'patch', None, _('show patch')),
4000 ('p', 'patch', None, _('show patch')),
3996 ('g', 'git', None, _('use git extended diff format')),
4001 ('g', 'git', None, _('use git extended diff format')),
3997 ('l', 'limit', '',
4002 ('l', 'limit', '',
3998 _('limit number of changes displayed'), _('NUM')),
4003 _('limit number of changes displayed'), _('NUM')),
3999 ('M', 'no-merges', None, _('do not show merges')),
4004 ('M', 'no-merges', None, _('do not show merges')),
4000 ('', 'stat', None, _('output diffstat-style summary of changes')),
4005 ('', 'stat', None, _('output diffstat-style summary of changes')),
4001 ] + templateopts
4006 ] + templateopts
4002
4007
4003 diffopts = [
4008 diffopts = [
4004 ('a', 'text', None, _('treat all files as text')),
4009 ('a', 'text', None, _('treat all files as text')),
4005 ('g', 'git', None, _('use git extended diff format')),
4010 ('g', 'git', None, _('use git extended diff format')),
4006 ('', 'nodates', None, _('omit dates from diff headers'))
4011 ('', 'nodates', None, _('omit dates from diff headers'))
4007 ]
4012 ]
4008
4013
4009 diffopts2 = [
4014 diffopts2 = [
4010 ('p', 'show-function', None, _('show which function each change is in')),
4015 ('p', 'show-function', None, _('show which function each change is in')),
4011 ('', 'reverse', None, _('produce a diff that undoes the changes')),
4016 ('', 'reverse', None, _('produce a diff that undoes the changes')),
4012 ('w', 'ignore-all-space', None,
4017 ('w', 'ignore-all-space', None,
4013 _('ignore white space when comparing lines')),
4018 _('ignore white space when comparing lines')),
4014 ('b', 'ignore-space-change', None,
4019 ('b', 'ignore-space-change', None,
4015 _('ignore changes in the amount of white space')),
4020 _('ignore changes in the amount of white space')),
4016 ('B', 'ignore-blank-lines', None,
4021 ('B', 'ignore-blank-lines', None,
4017 _('ignore changes whose lines are all blank')),
4022 _('ignore changes whose lines are all blank')),
4018 ('U', 'unified', '',
4023 ('U', 'unified', '',
4019 _('number of lines of context to show'), _('NUM')),
4024 _('number of lines of context to show'), _('NUM')),
4020 ('', 'stat', None, _('output diffstat-style summary of changes')),
4025 ('', 'stat', None, _('output diffstat-style summary of changes')),
4021 ]
4026 ]
4022
4027
4023 similarityopts = [
4028 similarityopts = [
4024 ('s', 'similarity', '',
4029 ('s', 'similarity', '',
4025 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4030 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4026 ]
4031 ]
4027
4032
4028 subrepoopts = [
4033 subrepoopts = [
4029 ('S', 'subrepos', None,
4034 ('S', 'subrepos', None,
4030 _('recurse into subrepositories'))
4035 _('recurse into subrepositories'))
4031 ]
4036 ]
4032
4037
4033 table = {
4038 table = {
4034 "^add": (add, walkopts + subrepoopts + dryrunopts,
4039 "^add": (add, walkopts + subrepoopts + dryrunopts,
4035 _('[OPTION]... [FILE]...')),
4040 _('[OPTION]... [FILE]...')),
4036 "addremove":
4041 "addremove":
4037 (addremove, similarityopts + walkopts + dryrunopts,
4042 (addremove, similarityopts + walkopts + dryrunopts,
4038 _('[OPTION]... [FILE]...')),
4043 _('[OPTION]... [FILE]...')),
4039 "^annotate|blame":
4044 "^annotate|blame":
4040 (annotate,
4045 (annotate,
4041 [('r', 'rev', '',
4046 [('r', 'rev', '',
4042 _('annotate the specified revision'), _('REV')),
4047 _('annotate the specified revision'), _('REV')),
4043 ('', 'follow', None,
4048 ('', 'follow', None,
4044 _('follow copies/renames and list the filename (DEPRECATED)')),
4049 _('follow copies/renames and list the filename (DEPRECATED)')),
4045 ('', 'no-follow', None, _("don't follow copies and renames")),
4050 ('', 'no-follow', None, _("don't follow copies and renames")),
4046 ('a', 'text', None, _('treat all files as text')),
4051 ('a', 'text', None, _('treat all files as text')),
4047 ('u', 'user', None, _('list the author (long with -v)')),
4052 ('u', 'user', None, _('list the author (long with -v)')),
4048 ('f', 'file', None, _('list the filename')),
4053 ('f', 'file', None, _('list the filename')),
4049 ('d', 'date', None, _('list the date (short with -q)')),
4054 ('d', 'date', None, _('list the date (short with -q)')),
4050 ('n', 'number', None, _('list the revision number (default)')),
4055 ('n', 'number', None, _('list the revision number (default)')),
4051 ('c', 'changeset', None, _('list the changeset')),
4056 ('c', 'changeset', None, _('list the changeset')),
4052 ('l', 'line-number', None,
4057 ('l', 'line-number', None,
4053 _('show line number at the first appearance'))
4058 _('show line number at the first appearance'))
4054 ] + walkopts,
4059 ] + walkopts,
4055 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4060 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4056 "archive":
4061 "archive":
4057 (archive,
4062 (archive,
4058 [('', 'no-decode', None, _('do not pass files through decoders')),
4063 [('', 'no-decode', None, _('do not pass files through decoders')),
4059 ('p', 'prefix', '',
4064 ('p', 'prefix', '',
4060 _('directory prefix for files in archive'), _('PREFIX')),
4065 _('directory prefix for files in archive'), _('PREFIX')),
4061 ('r', 'rev', '',
4066 ('r', 'rev', '',
4062 _('revision to distribute'), _('REV')),
4067 _('revision to distribute'), _('REV')),
4063 ('t', 'type', '',
4068 ('t', 'type', '',
4064 _('type of distribution to create'), _('TYPE')),
4069 _('type of distribution to create'), _('TYPE')),
4065 ] + subrepoopts + walkopts,
4070 ] + subrepoopts + walkopts,
4066 _('[OPTION]... DEST')),
4071 _('[OPTION]... DEST')),
4067 "backout":
4072 "backout":
4068 (backout,
4073 (backout,
4069 [('', 'merge', None,
4074 [('', 'merge', None,
4070 _('merge with old dirstate parent after backout')),
4075 _('merge with old dirstate parent after backout')),
4071 ('', 'parent', '',
4076 ('', 'parent', '',
4072 _('parent to choose when backing out merge'), _('REV')),
4077 _('parent to choose when backing out merge'), _('REV')),
4073 ('t', 'tool', '',
4078 ('t', 'tool', '',
4074 _('specify merge tool')),
4079 _('specify merge tool')),
4075 ('r', 'rev', '',
4080 ('r', 'rev', '',
4076 _('revision to backout'), _('REV')),
4081 _('revision to backout'), _('REV')),
4077 ] + walkopts + commitopts + commitopts2,
4082 ] + walkopts + commitopts + commitopts2,
4078 _('[OPTION]... [-r] REV')),
4083 _('[OPTION]... [-r] REV')),
4079 "bisect":
4084 "bisect":
4080 (bisect,
4085 (bisect,
4081 [('r', 'reset', False, _('reset bisect state')),
4086 [('r', 'reset', False, _('reset bisect state')),
4082 ('g', 'good', False, _('mark changeset good')),
4087 ('g', 'good', False, _('mark changeset good')),
4083 ('b', 'bad', False, _('mark changeset bad')),
4088 ('b', 'bad', False, _('mark changeset bad')),
4084 ('s', 'skip', False, _('skip testing changeset')),
4089 ('s', 'skip', False, _('skip testing changeset')),
4085 ('c', 'command', '',
4090 ('c', 'command', '',
4086 _('use command to check changeset state'), _('CMD')),
4091 _('use command to check changeset state'), _('CMD')),
4087 ('U', 'noupdate', False, _('do not update to target'))],
4092 ('U', 'noupdate', False, _('do not update to target'))],
4088 _("[-gbsr] [-U] [-c CMD] [REV]")),
4093 _("[-gbsr] [-U] [-c CMD] [REV]")),
4089 "branch":
4094 "branch":
4090 (branch,
4095 (branch,
4091 [('f', 'force', None,
4096 [('f', 'force', None,
4092 _('set branch name even if it shadows an existing branch')),
4097 _('set branch name even if it shadows an existing branch')),
4093 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4098 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4094 _('[-fC] [NAME]')),
4099 _('[-fC] [NAME]')),
4095 "branches":
4100 "branches":
4096 (branches,
4101 (branches,
4097 [('a', 'active', False,
4102 [('a', 'active', False,
4098 _('show only branches that have unmerged heads')),
4103 _('show only branches that have unmerged heads')),
4099 ('c', 'closed', False,
4104 ('c', 'closed', False,
4100 _('show normal and closed branches'))],
4105 _('show normal and closed branches'))],
4101 _('[-ac]')),
4106 _('[-ac]')),
4102 "bundle":
4107 "bundle":
4103 (bundle,
4108 (bundle,
4104 [('f', 'force', None,
4109 [('f', 'force', None,
4105 _('run even when the destination is unrelated')),
4110 _('run even when the destination is unrelated')),
4106 ('r', 'rev', [],
4111 ('r', 'rev', [],
4107 _('a changeset intended to be added to the destination'),
4112 _('a changeset intended to be added to the destination'),
4108 _('REV')),
4113 _('REV')),
4109 ('b', 'branch', [],
4114 ('b', 'branch', [],
4110 _('a specific branch you would like to bundle'),
4115 _('a specific branch you would like to bundle'),
4111 _('BRANCH')),
4116 _('BRANCH')),
4112 ('', 'base', [],
4117 ('', 'base', [],
4113 _('a base changeset assumed to be available at the destination'),
4118 _('a base changeset assumed to be available at the destination'),
4114 _('REV')),
4119 _('REV')),
4115 ('a', 'all', None, _('bundle all changesets in the repository')),
4120 ('a', 'all', None, _('bundle all changesets in the repository')),
4116 ('t', 'type', 'bzip2',
4121 ('t', 'type', 'bzip2',
4117 _('bundle compression type to use'), _('TYPE')),
4122 _('bundle compression type to use'), _('TYPE')),
4118 ] + remoteopts,
4123 ] + remoteopts,
4119 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4124 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4120 "cat":
4125 "cat":
4121 (cat,
4126 (cat,
4122 [('o', 'output', '',
4127 [('o', 'output', '',
4123 _('print output to file with formatted name'), _('FORMAT')),
4128 _('print output to file with formatted name'), _('FORMAT')),
4124 ('r', 'rev', '',
4129 ('r', 'rev', '',
4125 _('print the given revision'), _('REV')),
4130 _('print the given revision'), _('REV')),
4126 ('', 'decode', None, _('apply any matching decode filter')),
4131 ('', 'decode', None, _('apply any matching decode filter')),
4127 ] + walkopts,
4132 ] + walkopts,
4128 _('[OPTION]... FILE...')),
4133 _('[OPTION]... FILE...')),
4129 "^clone":
4134 "^clone":
4130 (clone,
4135 (clone,
4131 [('U', 'noupdate', None,
4136 [('U', 'noupdate', None,
4132 _('the clone will include an empty working copy (only a repository)')),
4137 _('the clone will include an empty working copy (only a repository)')),
4133 ('u', 'updaterev', '',
4138 ('u', 'updaterev', '',
4134 _('revision, tag or branch to check out'), _('REV')),
4139 _('revision, tag or branch to check out'), _('REV')),
4135 ('r', 'rev', [],
4140 ('r', 'rev', [],
4136 _('include the specified changeset'), _('REV')),
4141 _('include the specified changeset'), _('REV')),
4137 ('b', 'branch', [],
4142 ('b', 'branch', [],
4138 _('clone only the specified branch'), _('BRANCH')),
4143 _('clone only the specified branch'), _('BRANCH')),
4139 ('', 'pull', None, _('use pull protocol to copy metadata')),
4144 ('', 'pull', None, _('use pull protocol to copy metadata')),
4140 ('', 'uncompressed', None,
4145 ('', 'uncompressed', None,
4141 _('use uncompressed transfer (fast over LAN)')),
4146 _('use uncompressed transfer (fast over LAN)')),
4142 ] + remoteopts,
4147 ] + remoteopts,
4143 _('[OPTION]... SOURCE [DEST]')),
4148 _('[OPTION]... SOURCE [DEST]')),
4144 "^commit|ci":
4149 "^commit|ci":
4145 (commit,
4150 (commit,
4146 [('A', 'addremove', None,
4151 [('A', 'addremove', None,
4147 _('mark new/missing files as added/removed before committing')),
4152 _('mark new/missing files as added/removed before committing')),
4148 ('', 'close-branch', None,
4153 ('', 'close-branch', None,
4149 _('mark a branch as closed, hiding it from the branch list')),
4154 _('mark a branch as closed, hiding it from the branch list')),
4150 ] + walkopts + commitopts + commitopts2,
4155 ] + walkopts + commitopts + commitopts2,
4151 _('[OPTION]... [FILE]...')),
4156 _('[OPTION]... [FILE]...')),
4152 "copy|cp":
4157 "copy|cp":
4153 (copy,
4158 (copy,
4154 [('A', 'after', None, _('record a copy that has already occurred')),
4159 [('A', 'after', None, _('record a copy that has already occurred')),
4155 ('f', 'force', None,
4160 ('f', 'force', None,
4156 _('forcibly copy over an existing managed file')),
4161 _('forcibly copy over an existing managed file')),
4157 ] + walkopts + dryrunopts,
4162 ] + walkopts + dryrunopts,
4158 _('[OPTION]... [SOURCE]... DEST')),
4163 _('[OPTION]... [SOURCE]... DEST')),
4159 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4164 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4160 "debugbuilddag":
4165 "debugbuilddag":
4161 (debugbuilddag,
4166 (debugbuilddag,
4162 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4167 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4163 ('a', 'appended-file', None, _('add single file all revs append to')),
4168 ('a', 'appended-file', None, _('add single file all revs append to')),
4164 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4169 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4165 ('n', 'new-file', None, _('add new file at each rev')),
4170 ('n', 'new-file', None, _('add new file at each rev')),
4166 ],
4171 ],
4167 _('[OPTION]... TEXT')),
4172 _('[OPTION]... TEXT')),
4168 "debugcheckstate": (debugcheckstate, [], ''),
4173 "debugcheckstate": (debugcheckstate, [], ''),
4169 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4174 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4170 "debugcomplete":
4175 "debugcomplete":
4171 (debugcomplete,
4176 (debugcomplete,
4172 [('o', 'options', None, _('show the command options'))],
4177 [('o', 'options', None, _('show the command options'))],
4173 _('[-o] CMD')),
4178 _('[-o] CMD')),
4174 "debugdag":
4179 "debugdag":
4175 (debugdag,
4180 (debugdag,
4176 [('t', 'tags', None, _('use tags as labels')),
4181 [('t', 'tags', None, _('use tags as labels')),
4177 ('b', 'branches', None, _('annotate with branch names')),
4182 ('b', 'branches', None, _('annotate with branch names')),
4178 ('', 'dots', None, _('use dots for runs')),
4183 ('', 'dots', None, _('use dots for runs')),
4179 ('s', 'spaces', None, _('separate elements by spaces')),
4184 ('s', 'spaces', None, _('separate elements by spaces')),
4180 ],
4185 ],
4181 _('[OPTION]... [FILE [REV]...]')),
4186 _('[OPTION]... [FILE [REV]...]')),
4182 "debugdate":
4187 "debugdate":
4183 (debugdate,
4188 (debugdate,
4184 [('e', 'extended', None, _('try extended date formats'))],
4189 [('e', 'extended', None, _('try extended date formats'))],
4185 _('[-e] DATE [RANGE]')),
4190 _('[-e] DATE [RANGE]')),
4186 "debugdata": (debugdata, [], _('FILE REV')),
4191 "debugdata": (debugdata, [], _('FILE REV')),
4187 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4192 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4188 "debugindex": (debugindex,
4193 "debugindex": (debugindex,
4189 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4194 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4190 _('FILE')),
4195 _('FILE')),
4191 "debugindexdot": (debugindexdot, [], _('FILE')),
4196 "debugindexdot": (debugindexdot, [], _('FILE')),
4192 "debuginstall": (debuginstall, [], ''),
4197 "debuginstall": (debuginstall, [], ''),
4193 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4198 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4194 "debugrebuildstate":
4199 "debugrebuildstate":
4195 (debugrebuildstate,
4200 (debugrebuildstate,
4196 [('r', 'rev', '',
4201 [('r', 'rev', '',
4197 _('revision to rebuild to'), _('REV'))],
4202 _('revision to rebuild to'), _('REV'))],
4198 _('[-r REV] [REV]')),
4203 _('[-r REV] [REV]')),
4199 "debugrename":
4204 "debugrename":
4200 (debugrename,
4205 (debugrename,
4201 [('r', 'rev', '',
4206 [('r', 'rev', '',
4202 _('revision to debug'), _('REV'))],
4207 _('revision to debug'), _('REV'))],
4203 _('[-r REV] FILE')),
4208 _('[-r REV] FILE')),
4204 "debugrevspec":
4209 "debugrevspec":
4205 (debugrevspec, [], ('REVSPEC')),
4210 (debugrevspec, [], ('REVSPEC')),
4206 "debugsetparents":
4211 "debugsetparents":
4207 (debugsetparents, [], _('REV1 [REV2]')),
4212 (debugsetparents, [], _('REV1 [REV2]')),
4208 "debugstate":
4213 "debugstate":
4209 (debugstate,
4214 (debugstate,
4210 [('', 'nodates', None, _('do not display the saved mtime'))],
4215 [('', 'nodates', None, _('do not display the saved mtime'))],
4211 _('[OPTION]...')),
4216 _('[OPTION]...')),
4212 "debugsub":
4217 "debugsub":
4213 (debugsub,
4218 (debugsub,
4214 [('r', 'rev', '',
4219 [('r', 'rev', '',
4215 _('revision to check'), _('REV'))],
4220 _('revision to check'), _('REV'))],
4216 _('[-r REV] [REV]')),
4221 _('[-r REV] [REV]')),
4217 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4222 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4218 "^diff":
4223 "^diff":
4219 (diff,
4224 (diff,
4220 [('r', 'rev', [],
4225 [('r', 'rev', [],
4221 _('revision'), _('REV')),
4226 _('revision'), _('REV')),
4222 ('c', 'change', '',
4227 ('c', 'change', '',
4223 _('change made by revision'), _('REV'))
4228 _('change made by revision'), _('REV'))
4224 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4229 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4225 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4230 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4226 "^export":
4231 "^export":
4227 (export,
4232 (export,
4228 [('o', 'output', '',
4233 [('o', 'output', '',
4229 _('print output to file with formatted name'), _('FORMAT')),
4234 _('print output to file with formatted name'), _('FORMAT')),
4230 ('', 'switch-parent', None, _('diff against the second parent')),
4235 ('', 'switch-parent', None, _('diff against the second parent')),
4231 ('r', 'rev', [],
4236 ('r', 'rev', [],
4232 _('revisions to export'), _('REV')),
4237 _('revisions to export'), _('REV')),
4233 ] + diffopts,
4238 ] + diffopts,
4234 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4239 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4235 "^forget":
4240 "^forget":
4236 (forget,
4241 (forget,
4237 [] + walkopts,
4242 [] + walkopts,
4238 _('[OPTION]... FILE...')),
4243 _('[OPTION]... FILE...')),
4239 "grep":
4244 "grep":
4240 (grep,
4245 (grep,
4241 [('0', 'print0', None, _('end fields with NUL')),
4246 [('0', 'print0', None, _('end fields with NUL')),
4242 ('', 'all', None, _('print all revisions that match')),
4247 ('', 'all', None, _('print all revisions that match')),
4243 ('f', 'follow', None,
4248 ('f', 'follow', None,
4244 _('follow changeset history,'
4249 _('follow changeset history,'
4245 ' or file history across copies and renames')),
4250 ' or file history across copies and renames')),
4246 ('i', 'ignore-case', None, _('ignore case when matching')),
4251 ('i', 'ignore-case', None, _('ignore case when matching')),
4247 ('l', 'files-with-matches', None,
4252 ('l', 'files-with-matches', None,
4248 _('print only filenames and revisions that match')),
4253 _('print only filenames and revisions that match')),
4249 ('n', 'line-number', None, _('print matching line numbers')),
4254 ('n', 'line-number', None, _('print matching line numbers')),
4250 ('r', 'rev', [],
4255 ('r', 'rev', [],
4251 _('only search files changed within revision range'), _('REV')),
4256 _('only search files changed within revision range'), _('REV')),
4252 ('u', 'user', None, _('list the author (long with -v)')),
4257 ('u', 'user', None, _('list the author (long with -v)')),
4253 ('d', 'date', None, _('list the date (short with -q)')),
4258 ('d', 'date', None, _('list the date (short with -q)')),
4254 ] + walkopts,
4259 ] + walkopts,
4255 _('[OPTION]... PATTERN [FILE]...')),
4260 _('[OPTION]... PATTERN [FILE]...')),
4256 "heads":
4261 "heads":
4257 (heads,
4262 (heads,
4258 [('r', 'rev', '',
4263 [('r', 'rev', '',
4259 _('show only heads which are descendants of STARTREV'),
4264 _('show only heads which are descendants of STARTREV'),
4260 _('STARTREV')),
4265 _('STARTREV')),
4261 ('t', 'topo', False, _('show topological heads only')),
4266 ('t', 'topo', False, _('show topological heads only')),
4262 ('a', 'active', False,
4267 ('a', 'active', False,
4263 _('show active branchheads only (DEPRECATED)')),
4268 _('show active branchheads only (DEPRECATED)')),
4264 ('c', 'closed', False,
4269 ('c', 'closed', False,
4265 _('show normal and closed branch heads')),
4270 _('show normal and closed branch heads')),
4266 ] + templateopts,
4271 ] + templateopts,
4267 _('[-ac] [-r STARTREV] [REV]...')),
4272 _('[-ac] [-r STARTREV] [REV]...')),
4268 "help": (help_, [], _('[TOPIC]')),
4273 "help": (help_, [], _('[TOPIC]')),
4269 "identify|id":
4274 "identify|id":
4270 (identify,
4275 (identify,
4271 [('r', 'rev', '',
4276 [('r', 'rev', '',
4272 _('identify the specified revision'), _('REV')),
4277 _('identify the specified revision'), _('REV')),
4273 ('n', 'num', None, _('show local revision number')),
4278 ('n', 'num', None, _('show local revision number')),
4274 ('i', 'id', None, _('show global revision id')),
4279 ('i', 'id', None, _('show global revision id')),
4275 ('b', 'branch', None, _('show branch')),
4280 ('b', 'branch', None, _('show branch')),
4276 ('t', 'tags', None, _('show tags'))],
4281 ('t', 'tags', None, _('show tags'))],
4277 _('[-nibt] [-r REV] [SOURCE]')),
4282 _('[-nibt] [-r REV] [SOURCE]')),
4278 "import|patch":
4283 "import|patch":
4279 (import_,
4284 (import_,
4280 [('p', 'strip', 1,
4285 [('p', 'strip', 1,
4281 _('directory strip option for patch. This has the same '
4286 _('directory strip option for patch. This has the same '
4282 'meaning as the corresponding patch option'),
4287 'meaning as the corresponding patch option'),
4283 _('NUM')),
4288 _('NUM')),
4284 ('b', 'base', '',
4289 ('b', 'base', '',
4285 _('base path'), _('PATH')),
4290 _('base path'), _('PATH')),
4286 ('f', 'force', None,
4291 ('f', 'force', None,
4287 _('skip check for outstanding uncommitted changes')),
4292 _('skip check for outstanding uncommitted changes')),
4288 ('', 'no-commit', None,
4293 ('', 'no-commit', None,
4289 _("don't commit, just update the working directory")),
4294 _("don't commit, just update the working directory")),
4290 ('', 'exact', None,
4295 ('', 'exact', None,
4291 _('apply patch to the nodes from which it was generated')),
4296 _('apply patch to the nodes from which it was generated')),
4292 ('', 'import-branch', None,
4297 ('', 'import-branch', None,
4293 _('use any branch information in patch (implied by --exact)'))] +
4298 _('use any branch information in patch (implied by --exact)'))] +
4294 commitopts + commitopts2 + similarityopts,
4299 commitopts + commitopts2 + similarityopts,
4295 _('[OPTION]... PATCH...')),
4300 _('[OPTION]... PATCH...')),
4296 "incoming|in":
4301 "incoming|in":
4297 (incoming,
4302 (incoming,
4298 [('f', 'force', None,
4303 [('f', 'force', None,
4299 _('run even if remote repository is unrelated')),
4304 _('run even if remote repository is unrelated')),
4300 ('n', 'newest-first', None, _('show newest record first')),
4305 ('n', 'newest-first', None, _('show newest record first')),
4301 ('', 'bundle', '',
4306 ('', 'bundle', '',
4302 _('file to store the bundles into'), _('FILE')),
4307 _('file to store the bundles into'), _('FILE')),
4303 ('r', 'rev', [],
4308 ('r', 'rev', [],
4304 _('a remote changeset intended to be added'), _('REV')),
4309 _('a remote changeset intended to be added'), _('REV')),
4305 ('B', 'bookmarks', False, _("compare bookmarks")),
4310 ('B', 'bookmarks', False, _("compare bookmarks")),
4306 ('b', 'branch', [],
4311 ('b', 'branch', [],
4307 _('a specific branch you would like to pull'), _('BRANCH')),
4312 _('a specific branch you would like to pull'), _('BRANCH')),
4308 ] + logopts + remoteopts + subrepoopts,
4313 ] + logopts + remoteopts + subrepoopts,
4309 _('[-p] [-n] [-M] [-f] [-r REV]...'
4314 _('[-p] [-n] [-M] [-f] [-r REV]...'
4310 ' [--bundle FILENAME] [SOURCE]')),
4315 ' [--bundle FILENAME] [SOURCE]')),
4311 "^init":
4316 "^init":
4312 (init,
4317 (init,
4313 remoteopts,
4318 remoteopts,
4314 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4319 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4315 "locate":
4320 "locate":
4316 (locate,
4321 (locate,
4317 [('r', 'rev', '',
4322 [('r', 'rev', '',
4318 _('search the repository as it is in REV'), _('REV')),
4323 _('search the repository as it is in REV'), _('REV')),
4319 ('0', 'print0', None,
4324 ('0', 'print0', None,
4320 _('end filenames with NUL, for use with xargs')),
4325 _('end filenames with NUL, for use with xargs')),
4321 ('f', 'fullpath', None,
4326 ('f', 'fullpath', None,
4322 _('print complete paths from the filesystem root')),
4327 _('print complete paths from the filesystem root')),
4323 ] + walkopts,
4328 ] + walkopts,
4324 _('[OPTION]... [PATTERN]...')),
4329 _('[OPTION]... [PATTERN]...')),
4325 "^log|history":
4330 "^log|history":
4326 (log,
4331 (log,
4327 [('f', 'follow', None,
4332 [('f', 'follow', None,
4328 _('follow changeset history,'
4333 _('follow changeset history,'
4329 ' or file history across copies and renames')),
4334 ' or file history across copies and renames')),
4330 ('', 'follow-first', None,
4335 ('', 'follow-first', None,
4331 _('only follow the first parent of merge changesets')),
4336 _('only follow the first parent of merge changesets')),
4332 ('d', 'date', '',
4337 ('d', 'date', '',
4333 _('show revisions matching date spec'), _('DATE')),
4338 _('show revisions matching date spec'), _('DATE')),
4334 ('C', 'copies', None, _('show copied files')),
4339 ('C', 'copies', None, _('show copied files')),
4335 ('k', 'keyword', [],
4340 ('k', 'keyword', [],
4336 _('do case-insensitive search for a given text'), _('TEXT')),
4341 _('do case-insensitive search for a given text'), _('TEXT')),
4337 ('r', 'rev', [],
4342 ('r', 'rev', [],
4338 _('show the specified revision or range'), _('REV')),
4343 _('show the specified revision or range'), _('REV')),
4339 ('', 'removed', None, _('include revisions where files were removed')),
4344 ('', 'removed', None, _('include revisions where files were removed')),
4340 ('m', 'only-merges', None, _('show only merges')),
4345 ('m', 'only-merges', None, _('show only merges')),
4341 ('u', 'user', [],
4346 ('u', 'user', [],
4342 _('revisions committed by user'), _('USER')),
4347 _('revisions committed by user'), _('USER')),
4343 ('', 'only-branch', [],
4348 ('', 'only-branch', [],
4344 _('show only changesets within the given named branch (DEPRECATED)'),
4349 _('show only changesets within the given named branch (DEPRECATED)'),
4345 _('BRANCH')),
4350 _('BRANCH')),
4346 ('b', 'branch', [],
4351 ('b', 'branch', [],
4347 _('show changesets within the given named branch'), _('BRANCH')),
4352 _('show changesets within the given named branch'), _('BRANCH')),
4348 ('P', 'prune', [],
4353 ('P', 'prune', [],
4349 _('do not display revision or any of its ancestors'), _('REV')),
4354 _('do not display revision or any of its ancestors'), _('REV')),
4350 ] + logopts + walkopts,
4355 ] + logopts + walkopts,
4351 _('[OPTION]... [FILE]')),
4356 _('[OPTION]... [FILE]')),
4352 "manifest":
4357 "manifest":
4353 (manifest,
4358 (manifest,
4354 [('r', 'rev', '',
4359 [('r', 'rev', '',
4355 _('revision to display'), _('REV'))],
4360 _('revision to display'), _('REV'))],
4356 _('[-r REV]')),
4361 _('[-r REV]')),
4357 "^merge":
4362 "^merge":
4358 (merge,
4363 (merge,
4359 [('f', 'force', None, _('force a merge with outstanding changes')),
4364 [('f', 'force', None, _('force a merge with outstanding changes')),
4360 ('t', 'tool', '', _('specify merge tool')),
4365 ('t', 'tool', '', _('specify merge tool')),
4361 ('r', 'rev', '',
4366 ('r', 'rev', '',
4362 _('revision to merge'), _('REV')),
4367 _('revision to merge'), _('REV')),
4363 ('P', 'preview', None,
4368 ('P', 'preview', None,
4364 _('review revisions to merge (no merge is performed)'))],
4369 _('review revisions to merge (no merge is performed)'))],
4365 _('[-P] [-f] [[-r] REV]')),
4370 _('[-P] [-f] [[-r] REV]')),
4366 "outgoing|out":
4371 "outgoing|out":
4367 (outgoing,
4372 (outgoing,
4368 [('f', 'force', None,
4373 [('f', 'force', None,
4369 _('run even when the destination is unrelated')),
4374 _('run even when the destination is unrelated')),
4370 ('r', 'rev', [],
4375 ('r', 'rev', [],
4371 _('a changeset intended to be included in the destination'),
4376 _('a changeset intended to be included in the destination'),
4372 _('REV')),
4377 _('REV')),
4373 ('n', 'newest-first', None, _('show newest record first')),
4378 ('n', 'newest-first', None, _('show newest record first')),
4374 ('B', 'bookmarks', False, _("compare bookmarks")),
4379 ('B', 'bookmarks', False, _("compare bookmarks")),
4375 ('b', 'branch', [],
4380 ('b', 'branch', [],
4376 _('a specific branch you would like to push'), _('BRANCH')),
4381 _('a specific branch you would like to push'), _('BRANCH')),
4377 ] + logopts + remoteopts + subrepoopts,
4382 ] + logopts + remoteopts + subrepoopts,
4378 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4383 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4379 "parents":
4384 "parents":
4380 (parents,
4385 (parents,
4381 [('r', 'rev', '',
4386 [('r', 'rev', '',
4382 _('show parents of the specified revision'), _('REV')),
4387 _('show parents of the specified revision'), _('REV')),
4383 ] + templateopts,
4388 ] + templateopts,
4384 _('[-r REV] [FILE]')),
4389 _('[-r REV] [FILE]')),
4385 "paths": (paths, [], _('[NAME]')),
4390 "paths": (paths, [], _('[NAME]')),
4386 "^pull":
4391 "^pull":
4387 (pull,
4392 (pull,
4388 [('u', 'update', None,
4393 [('u', 'update', None,
4389 _('update to new branch head if changesets were pulled')),
4394 _('update to new branch head if changesets were pulled')),
4390 ('f', 'force', None,
4395 ('f', 'force', None,
4391 _('run even when remote repository is unrelated')),
4396 _('run even when remote repository is unrelated')),
4392 ('r', 'rev', [],
4397 ('r', 'rev', [],
4393 _('a remote changeset intended to be added'), _('REV')),
4398 _('a remote changeset intended to be added'), _('REV')),
4394 ('b', 'branch', [],
4399 ('b', 'branch', [],
4395 _('a specific branch you would like to pull'), _('BRANCH')),
4400 _('a specific branch you would like to pull'), _('BRANCH')),
4396 ] + remoteopts,
4401 ] + remoteopts,
4397 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4402 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4398 "^push":
4403 "^push":
4399 (push,
4404 (push,
4400 [('f', 'force', None, _('force push')),
4405 [('f', 'force', None, _('force push')),
4401 ('r', 'rev', [],
4406 ('r', 'rev', [],
4402 _('a changeset intended to be included in the destination'),
4407 _('a changeset intended to be included in the destination'),
4403 _('REV')),
4408 _('REV')),
4404 ('b', 'branch', [],
4409 ('b', 'branch', [],
4405 _('a specific branch you would like to push'), _('BRANCH')),
4410 _('a specific branch you would like to push'), _('BRANCH')),
4406 ('', 'new-branch', False, _('allow pushing a new branch')),
4411 ('', 'new-branch', False, _('allow pushing a new branch')),
4407 ] + remoteopts,
4412 ] + remoteopts,
4408 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4413 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4409 "recover": (recover, []),
4414 "recover": (recover, []),
4410 "^remove|rm":
4415 "^remove|rm":
4411 (remove,
4416 (remove,
4412 [('A', 'after', None, _('record delete for missing files')),
4417 [('A', 'after', None, _('record delete for missing files')),
4413 ('f', 'force', None,
4418 ('f', 'force', None,
4414 _('remove (and delete) file even if added or modified')),
4419 _('remove (and delete) file even if added or modified')),
4415 ] + walkopts,
4420 ] + walkopts,
4416 _('[OPTION]... FILE...')),
4421 _('[OPTION]... FILE...')),
4417 "rename|move|mv":
4422 "rename|move|mv":
4418 (rename,
4423 (rename,
4419 [('A', 'after', None, _('record a rename that has already occurred')),
4424 [('A', 'after', None, _('record a rename that has already occurred')),
4420 ('f', 'force', None,
4425 ('f', 'force', None,
4421 _('forcibly copy over an existing managed file')),
4426 _('forcibly copy over an existing managed file')),
4422 ] + walkopts + dryrunopts,
4427 ] + walkopts + dryrunopts,
4423 _('[OPTION]... SOURCE... DEST')),
4428 _('[OPTION]... SOURCE... DEST')),
4424 "resolve":
4429 "resolve":
4425 (resolve,
4430 (resolve,
4426 [('a', 'all', None, _('select all unresolved files')),
4431 [('a', 'all', None, _('select all unresolved files')),
4427 ('l', 'list', None, _('list state of files needing merge')),
4432 ('l', 'list', None, _('list state of files needing merge')),
4428 ('m', 'mark', None, _('mark files as resolved')),
4433 ('m', 'mark', None, _('mark files as resolved')),
4429 ('u', 'unmark', None, _('mark files as unresolved')),
4434 ('u', 'unmark', None, _('mark files as unresolved')),
4430 ('t', 'tool', '', _('specify merge tool')),
4435 ('t', 'tool', '', _('specify merge tool')),
4431 ('n', 'no-status', None, _('hide status prefix'))]
4436 ('n', 'no-status', None, _('hide status prefix'))]
4432 + walkopts,
4437 + walkopts,
4433 _('[OPTION]... [FILE]...')),
4438 _('[OPTION]... [FILE]...')),
4434 "revert":
4439 "revert":
4435 (revert,
4440 (revert,
4436 [('a', 'all', None, _('revert all changes when no arguments given')),
4441 [('a', 'all', None, _('revert all changes when no arguments given')),
4437 ('d', 'date', '',
4442 ('d', 'date', '',
4438 _('tipmost revision matching date'), _('DATE')),
4443 _('tipmost revision matching date'), _('DATE')),
4439 ('r', 'rev', '',
4444 ('r', 'rev', '',
4440 _('revert to the specified revision'), _('REV')),
4445 _('revert to the specified revision'), _('REV')),
4441 ('', 'no-backup', None, _('do not save backup copies of files')),
4446 ('', 'no-backup', None, _('do not save backup copies of files')),
4442 ] + walkopts + dryrunopts,
4447 ] + walkopts + dryrunopts,
4443 _('[OPTION]... [-r REV] [NAME]...')),
4448 _('[OPTION]... [-r REV] [NAME]...')),
4444 "rollback": (rollback, dryrunopts),
4449 "rollback": (rollback, dryrunopts),
4445 "root": (root, []),
4450 "root": (root, []),
4446 "^serve":
4451 "^serve":
4447 (serve,
4452 (serve,
4448 [('A', 'accesslog', '',
4453 [('A', 'accesslog', '',
4449 _('name of access log file to write to'), _('FILE')),
4454 _('name of access log file to write to'), _('FILE')),
4450 ('d', 'daemon', None, _('run server in background')),
4455 ('d', 'daemon', None, _('run server in background')),
4451 ('', 'daemon-pipefds', '',
4456 ('', 'daemon-pipefds', '',
4452 _('used internally by daemon mode'), _('NUM')),
4457 _('used internally by daemon mode'), _('NUM')),
4453 ('E', 'errorlog', '',
4458 ('E', 'errorlog', '',
4454 _('name of error log file to write to'), _('FILE')),
4459 _('name of error log file to write to'), _('FILE')),
4455 # use string type, then we can check if something was passed
4460 # use string type, then we can check if something was passed
4456 ('p', 'port', '',
4461 ('p', 'port', '',
4457 _('port to listen on (default: 8000)'), _('PORT')),
4462 _('port to listen on (default: 8000)'), _('PORT')),
4458 ('a', 'address', '',
4463 ('a', 'address', '',
4459 _('address to listen on (default: all interfaces)'), _('ADDR')),
4464 _('address to listen on (default: all interfaces)'), _('ADDR')),
4460 ('', 'prefix', '',
4465 ('', 'prefix', '',
4461 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4466 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4462 ('n', 'name', '',
4467 ('n', 'name', '',
4463 _('name to show in web pages (default: working directory)'),
4468 _('name to show in web pages (default: working directory)'),
4464 _('NAME')),
4469 _('NAME')),
4465 ('', 'web-conf', '',
4470 ('', 'web-conf', '',
4466 _('name of the hgweb config file (see "hg help hgweb")'),
4471 _('name of the hgweb config file (see "hg help hgweb")'),
4467 _('FILE')),
4472 _('FILE')),
4468 ('', 'webdir-conf', '',
4473 ('', 'webdir-conf', '',
4469 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4474 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4470 ('', 'pid-file', '',
4475 ('', 'pid-file', '',
4471 _('name of file to write process ID to'), _('FILE')),
4476 _('name of file to write process ID to'), _('FILE')),
4472 ('', 'stdio', None, _('for remote clients')),
4477 ('', 'stdio', None, _('for remote clients')),
4473 ('t', 'templates', '',
4478 ('t', 'templates', '',
4474 _('web templates to use'), _('TEMPLATE')),
4479 _('web templates to use'), _('TEMPLATE')),
4475 ('', 'style', '',
4480 ('', 'style', '',
4476 _('template style to use'), _('STYLE')),
4481 _('template style to use'), _('STYLE')),
4477 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4482 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4478 ('', 'certificate', '',
4483 ('', 'certificate', '',
4479 _('SSL certificate file'), _('FILE'))],
4484 _('SSL certificate file'), _('FILE'))],
4480 _('[OPTION]...')),
4485 _('[OPTION]...')),
4481 "showconfig|debugconfig":
4486 "showconfig|debugconfig":
4482 (showconfig,
4487 (showconfig,
4483 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4488 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4484 _('[-u] [NAME]...')),
4489 _('[-u] [NAME]...')),
4485 "^summary|sum":
4490 "^summary|sum":
4486 (summary,
4491 (summary,
4487 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4492 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4488 "^status|st":
4493 "^status|st":
4489 (status,
4494 (status,
4490 [('A', 'all', None, _('show status of all files')),
4495 [('A', 'all', None, _('show status of all files')),
4491 ('m', 'modified', None, _('show only modified files')),
4496 ('m', 'modified', None, _('show only modified files')),
4492 ('a', 'added', None, _('show only added files')),
4497 ('a', 'added', None, _('show only added files')),
4493 ('r', 'removed', None, _('show only removed files')),
4498 ('r', 'removed', None, _('show only removed files')),
4494 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4499 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4495 ('c', 'clean', None, _('show only files without changes')),
4500 ('c', 'clean', None, _('show only files without changes')),
4496 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4501 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4497 ('i', 'ignored', None, _('show only ignored files')),
4502 ('i', 'ignored', None, _('show only ignored files')),
4498 ('n', 'no-status', None, _('hide status prefix')),
4503 ('n', 'no-status', None, _('hide status prefix')),
4499 ('C', 'copies', None, _('show source of copied files')),
4504 ('C', 'copies', None, _('show source of copied files')),
4500 ('0', 'print0', None,
4505 ('0', 'print0', None,
4501 _('end filenames with NUL, for use with xargs')),
4506 _('end filenames with NUL, for use with xargs')),
4502 ('', 'rev', [],
4507 ('', 'rev', [],
4503 _('show difference from revision'), _('REV')),
4508 _('show difference from revision'), _('REV')),
4504 ('', 'change', '',
4509 ('', 'change', '',
4505 _('list the changed files of a revision'), _('REV')),
4510 _('list the changed files of a revision'), _('REV')),
4506 ] + walkopts + subrepoopts,
4511 ] + walkopts + subrepoopts,
4507 _('[OPTION]... [FILE]...')),
4512 _('[OPTION]... [FILE]...')),
4508 "tag":
4513 "tag":
4509 (tag,
4514 (tag,
4510 [('f', 'force', None, _('force tag')),
4515 [('f', 'force', None, _('force tag')),
4511 ('l', 'local', None, _('make the tag local')),
4516 ('l', 'local', None, _('make the tag local')),
4512 ('r', 'rev', '',
4517 ('r', 'rev', '',
4513 _('revision to tag'), _('REV')),
4518 _('revision to tag'), _('REV')),
4514 ('', 'remove', None, _('remove a tag')),
4519 ('', 'remove', None, _('remove a tag')),
4515 # -l/--local is already there, commitopts cannot be used
4520 # -l/--local is already there, commitopts cannot be used
4516 ('e', 'edit', None, _('edit commit message')),
4521 ('e', 'edit', None, _('edit commit message')),
4517 ('m', 'message', '',
4522 ('m', 'message', '',
4518 _('use <text> as commit message'), _('TEXT')),
4523 _('use <text> as commit message'), _('TEXT')),
4519 ] + commitopts2,
4524 ] + commitopts2,
4520 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4525 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4521 "tags": (tags, [], ''),
4526 "tags": (tags, [], ''),
4522 "tip":
4527 "tip":
4523 (tip,
4528 (tip,
4524 [('p', 'patch', None, _('show patch')),
4529 [('p', 'patch', None, _('show patch')),
4525 ('g', 'git', None, _('use git extended diff format')),
4530 ('g', 'git', None, _('use git extended diff format')),
4526 ] + templateopts,
4531 ] + templateopts,
4527 _('[-p] [-g]')),
4532 _('[-p] [-g]')),
4528 "unbundle":
4533 "unbundle":
4529 (unbundle,
4534 (unbundle,
4530 [('u', 'update', None,
4535 [('u', 'update', None,
4531 _('update to new branch head if changesets were unbundled'))],
4536 _('update to new branch head if changesets were unbundled'))],
4532 _('[-u] FILE...')),
4537 _('[-u] FILE...')),
4533 "^update|up|checkout|co":
4538 "^update|up|checkout|co":
4534 (update,
4539 (update,
4535 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4540 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4536 ('c', 'check', None,
4541 ('c', 'check', None,
4537 _('update across branches if no uncommitted changes')),
4542 _('update across branches if no uncommitted changes')),
4538 ('d', 'date', '',
4543 ('d', 'date', '',
4539 _('tipmost revision matching date'), _('DATE')),
4544 _('tipmost revision matching date'), _('DATE')),
4540 ('r', 'rev', '',
4545 ('r', 'rev', '',
4541 _('revision'), _('REV'))],
4546 _('revision'), _('REV'))],
4542 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4547 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4543 "verify": (verify, []),
4548 "verify": (verify, []),
4544 "version": (version_, []),
4549 "version": (version_, []),
4545 }
4550 }
4546
4551
4547 norepo = ("clone init version help debugcommands debugcomplete"
4552 norepo = ("clone init version help debugcommands debugcomplete"
4548 " debugdate debuginstall debugfsinfo debugpushkey")
4553 " debugdate debuginstall debugfsinfo debugpushkey")
4549 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4554 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4550 " debugdata debugindex debugindexdot")
4555 " debugdata debugindex debugindexdot")
General Comments 0
You need to be logged in to leave comments. Login now