##// END OF EJS Templates
command: creation of obsolete marker...
Pierre-Yves.David@ens-lyon.org -
r17071:11f26e26 default
parent child Browse files
Show More
@@ -0,0 +1,49 b''
1
2 $ mkcommit() {
3 > echo "$1" > "$1"
4 > hg add "$1"
5 > hg ci -m "add $1"
6 > }
7 $ getid() {
8 > hg id --debug -ir "desc('$1')"
9 > }
10
11
12 $ hg init tmpa
13 $ cd tmpa
14
15 Killing a single changeset without replacement
16
17 $ mkcommit kill_me
18 $ hg debugobsolete -d '0 0' `getid kill_me` -u babar
19 $ cd ..
20
21 Killing a single changeset with replacement
22
23 $ hg init tmpb
24 $ cd tmpb
25 $ mkcommit a
26 $ mkcommit b
27 $ mkcommit original_c
28 $ hg up "desc('b')"
29 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
30 $ mkcommit new_c
31 created new head
32 $ hg debugobsolete `getid original_c` `getid new_c` -d '56 12'
33
34 do it again (it read the obsstore before adding new changeset)
35
36 $ hg up '.^'
37 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
38 $ mkcommit new_2_c
39 created new head
40 $ hg debugobsolete -d '1337 0' `getid new_c` `getid new_2_c`
41
42 Register two markers with a missing node
43
44 $ hg up '.^'
45 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
46 $ mkcommit new_3_c
47 created new head
48 $ hg debugobsolete -d '1338 0' `getid new_2_c` 1337133713371337133713371337133713371337
49 $ hg debugobsolete -d '1339 0' 1337133713371337133713371337133713371337 `getid new_3_c`
@@ -1,5783 +1,5798 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, bin, nullid, nullrev, short
8 from node import hex, bin, 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, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
12 import hg, scmutil, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, url, encoding, templatekw, discovery
13 import patch, help, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, hgweb.server, commandserver
15 import sshserver, hgweb, hgweb.server, commandserver
16 import merge as mergemod
16 import merge as mergemod
17 import minirst, revset, fileset
17 import minirst, revset, fileset
18 import dagparser, context, simplemerge
18 import dagparser, context, simplemerge
19 import random, setdiscovery, treediscovery, dagutil, pvec
19 import random, setdiscovery, treediscovery, dagutil, pvec
20 import phases
20 import phases
21
21
22 table = {}
22 table = {}
23
23
24 command = cmdutil.command(table)
24 command = cmdutil.command(table)
25
25
26 # common command options
26 # common command options
27
27
28 globalopts = [
28 globalopts = [
29 ('R', 'repository', '',
29 ('R', 'repository', '',
30 _('repository root directory or name of overlay bundle file'),
30 _('repository root directory or name of overlay bundle file'),
31 _('REPO')),
31 _('REPO')),
32 ('', 'cwd', '',
32 ('', 'cwd', '',
33 _('change working directory'), _('DIR')),
33 _('change working directory'), _('DIR')),
34 ('y', 'noninteractive', None,
34 ('y', 'noninteractive', None,
35 _('do not prompt, automatically pick the first choice for all prompts')),
35 _('do not prompt, automatically pick the first choice for all prompts')),
36 ('q', 'quiet', None, _('suppress output')),
36 ('q', 'quiet', None, _('suppress output')),
37 ('v', 'verbose', None, _('enable additional output')),
37 ('v', 'verbose', None, _('enable additional output')),
38 ('', 'config', [],
38 ('', 'config', [],
39 _('set/override config option (use \'section.name=value\')'),
39 _('set/override config option (use \'section.name=value\')'),
40 _('CONFIG')),
40 _('CONFIG')),
41 ('', 'debug', None, _('enable debugging output')),
41 ('', 'debug', None, _('enable debugging output')),
42 ('', 'debugger', None, _('start debugger')),
42 ('', 'debugger', None, _('start debugger')),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
43 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
44 _('ENCODE')),
44 _('ENCODE')),
45 ('', 'encodingmode', encoding.encodingmode,
45 ('', 'encodingmode', encoding.encodingmode,
46 _('set the charset encoding mode'), _('MODE')),
46 _('set the charset encoding mode'), _('MODE')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
47 ('', 'traceback', None, _('always print a traceback on exception')),
48 ('', 'time', None, _('time how long the command takes')),
48 ('', 'time', None, _('time how long the command takes')),
49 ('', 'profile', None, _('print command execution profile')),
49 ('', 'profile', None, _('print command execution profile')),
50 ('', 'version', None, _('output version information and exit')),
50 ('', 'version', None, _('output version information and exit')),
51 ('h', 'help', None, _('display help and exit')),
51 ('h', 'help', None, _('display help and exit')),
52 ]
52 ]
53
53
54 dryrunopts = [('n', 'dry-run', None,
54 dryrunopts = [('n', 'dry-run', None,
55 _('do not perform actions, just print output'))]
55 _('do not perform actions, just print output'))]
56
56
57 remoteopts = [
57 remoteopts = [
58 ('e', 'ssh', '',
58 ('e', 'ssh', '',
59 _('specify ssh command to use'), _('CMD')),
59 _('specify ssh command to use'), _('CMD')),
60 ('', 'remotecmd', '',
60 ('', 'remotecmd', '',
61 _('specify hg command to run on the remote side'), _('CMD')),
61 _('specify hg command to run on the remote side'), _('CMD')),
62 ('', 'insecure', None,
62 ('', 'insecure', None,
63 _('do not verify server certificate (ignoring web.cacerts config)')),
63 _('do not verify server certificate (ignoring web.cacerts config)')),
64 ]
64 ]
65
65
66 walkopts = [
66 walkopts = [
67 ('I', 'include', [],
67 ('I', 'include', [],
68 _('include names matching the given patterns'), _('PATTERN')),
68 _('include names matching the given patterns'), _('PATTERN')),
69 ('X', 'exclude', [],
69 ('X', 'exclude', [],
70 _('exclude names matching the given patterns'), _('PATTERN')),
70 _('exclude names matching the given patterns'), _('PATTERN')),
71 ]
71 ]
72
72
73 commitopts = [
73 commitopts = [
74 ('m', 'message', '',
74 ('m', 'message', '',
75 _('use text as commit message'), _('TEXT')),
75 _('use text as commit message'), _('TEXT')),
76 ('l', 'logfile', '',
76 ('l', 'logfile', '',
77 _('read commit message from file'), _('FILE')),
77 _('read commit message from file'), _('FILE')),
78 ]
78 ]
79
79
80 commitopts2 = [
80 commitopts2 = [
81 ('d', 'date', '',
81 ('d', 'date', '',
82 _('record the specified date as commit date'), _('DATE')),
82 _('record the specified date as commit date'), _('DATE')),
83 ('u', 'user', '',
83 ('u', 'user', '',
84 _('record the specified user as committer'), _('USER')),
84 _('record the specified user as committer'), _('USER')),
85 ]
85 ]
86
86
87 templateopts = [
87 templateopts = [
88 ('', 'style', '',
88 ('', 'style', '',
89 _('display using template map file'), _('STYLE')),
89 _('display using template map file'), _('STYLE')),
90 ('', 'template', '',
90 ('', 'template', '',
91 _('display with template'), _('TEMPLATE')),
91 _('display with template'), _('TEMPLATE')),
92 ]
92 ]
93
93
94 logopts = [
94 logopts = [
95 ('p', 'patch', None, _('show patch')),
95 ('p', 'patch', None, _('show patch')),
96 ('g', 'git', None, _('use git extended diff format')),
96 ('g', 'git', None, _('use git extended diff format')),
97 ('l', 'limit', '',
97 ('l', 'limit', '',
98 _('limit number of changes displayed'), _('NUM')),
98 _('limit number of changes displayed'), _('NUM')),
99 ('M', 'no-merges', None, _('do not show merges')),
99 ('M', 'no-merges', None, _('do not show merges')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
100 ('', 'stat', None, _('output diffstat-style summary of changes')),
101 ] + templateopts
101 ] + templateopts
102
102
103 diffopts = [
103 diffopts = [
104 ('a', 'text', None, _('treat all files as text')),
104 ('a', 'text', None, _('treat all files as text')),
105 ('g', 'git', None, _('use git extended diff format')),
105 ('g', 'git', None, _('use git extended diff format')),
106 ('', 'nodates', None, _('omit dates from diff headers'))
106 ('', 'nodates', None, _('omit dates from diff headers'))
107 ]
107 ]
108
108
109 diffwsopts = [
109 diffwsopts = [
110 ('w', 'ignore-all-space', None,
110 ('w', 'ignore-all-space', None,
111 _('ignore white space when comparing lines')),
111 _('ignore white space when comparing lines')),
112 ('b', 'ignore-space-change', None,
112 ('b', 'ignore-space-change', None,
113 _('ignore changes in the amount of white space')),
113 _('ignore changes in the amount of white space')),
114 ('B', 'ignore-blank-lines', None,
114 ('B', 'ignore-blank-lines', None,
115 _('ignore changes whose lines are all blank')),
115 _('ignore changes whose lines are all blank')),
116 ]
116 ]
117
117
118 diffopts2 = [
118 diffopts2 = [
119 ('p', 'show-function', None, _('show which function each change is in')),
119 ('p', 'show-function', None, _('show which function each change is in')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
120 ('', 'reverse', None, _('produce a diff that undoes the changes')),
121 ] + diffwsopts + [
121 ] + diffwsopts + [
122 ('U', 'unified', '',
122 ('U', 'unified', '',
123 _('number of lines of context to show'), _('NUM')),
123 _('number of lines of context to show'), _('NUM')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ]
125 ]
126
126
127 mergetoolopts = [
127 mergetoolopts = [
128 ('t', 'tool', '', _('specify merge tool')),
128 ('t', 'tool', '', _('specify merge tool')),
129 ]
129 ]
130
130
131 similarityopts = [
131 similarityopts = [
132 ('s', 'similarity', '',
132 ('s', 'similarity', '',
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
133 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
134 ]
134 ]
135
135
136 subrepoopts = [
136 subrepoopts = [
137 ('S', 'subrepos', None,
137 ('S', 'subrepos', None,
138 _('recurse into subrepositories'))
138 _('recurse into subrepositories'))
139 ]
139 ]
140
140
141 # Commands start here, listed alphabetically
141 # Commands start here, listed alphabetically
142
142
143 @command('^add',
143 @command('^add',
144 walkopts + subrepoopts + dryrunopts,
144 walkopts + subrepoopts + dryrunopts,
145 _('[OPTION]... [FILE]...'))
145 _('[OPTION]... [FILE]...'))
146 def add(ui, repo, *pats, **opts):
146 def add(ui, repo, *pats, **opts):
147 """add the specified files on the next commit
147 """add the specified files on the next commit
148
148
149 Schedule files to be version controlled and added to the
149 Schedule files to be version controlled and added to the
150 repository.
150 repository.
151
151
152 The files will be added to the repository at the next commit. To
152 The files will be added to the repository at the next commit. To
153 undo an add before that, see :hg:`forget`.
153 undo an add before that, see :hg:`forget`.
154
154
155 If no names are given, add all files to the repository.
155 If no names are given, add all files to the repository.
156
156
157 .. container:: verbose
157 .. container:: verbose
158
158
159 An example showing how new (unknown) files are added
159 An example showing how new (unknown) files are added
160 automatically by :hg:`add`::
160 automatically by :hg:`add`::
161
161
162 $ ls
162 $ ls
163 foo.c
163 foo.c
164 $ hg status
164 $ hg status
165 ? foo.c
165 ? foo.c
166 $ hg add
166 $ hg add
167 adding foo.c
167 adding foo.c
168 $ hg status
168 $ hg status
169 A foo.c
169 A foo.c
170
170
171 Returns 0 if all files are successfully added.
171 Returns 0 if all files are successfully added.
172 """
172 """
173
173
174 m = scmutil.match(repo[None], pats, opts)
174 m = scmutil.match(repo[None], pats, opts)
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
175 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
176 opts.get('subrepos'), prefix="", explicitonly=False)
176 opts.get('subrepos'), prefix="", explicitonly=False)
177 return rejected and 1 or 0
177 return rejected and 1 or 0
178
178
179 @command('addremove',
179 @command('addremove',
180 similarityopts + walkopts + dryrunopts,
180 similarityopts + walkopts + dryrunopts,
181 _('[OPTION]... [FILE]...'))
181 _('[OPTION]... [FILE]...'))
182 def addremove(ui, repo, *pats, **opts):
182 def addremove(ui, repo, *pats, **opts):
183 """add all new files, delete all missing files
183 """add all new files, delete all missing files
184
184
185 Add all new files and remove all missing files from the
185 Add all new files and remove all missing files from the
186 repository.
186 repository.
187
187
188 New files are ignored if they match any of the patterns in
188 New files are ignored if they match any of the patterns in
189 ``.hgignore``. As with add, these changes take effect at the next
189 ``.hgignore``. As with add, these changes take effect at the next
190 commit.
190 commit.
191
191
192 Use the -s/--similarity option to detect renamed files. With a
192 Use the -s/--similarity option to detect renamed files. With a
193 parameter greater than 0, this compares every removed file with
193 parameter greater than 0, this compares every removed file with
194 every added file and records those similar enough as renames. This
194 every added file and records those similar enough as renames. This
195 option takes a percentage between 0 (disabled) and 100 (files must
195 option takes a percentage between 0 (disabled) and 100 (files must
196 be identical) as its parameter. Detecting renamed files this way
196 be identical) as its parameter. Detecting renamed files this way
197 can be expensive. After using this option, :hg:`status -C` can be
197 can be expensive. After using this option, :hg:`status -C` can be
198 used to check which files were identified as moved or renamed.
198 used to check which files were identified as moved or renamed.
199 If this option is not specified, only renames of identical files
199 If this option is not specified, only renames of identical files
200 are detected.
200 are detected.
201
201
202 Returns 0 if all files are successfully added.
202 Returns 0 if all files are successfully added.
203 """
203 """
204 try:
204 try:
205 sim = float(opts.get('similarity') or 100)
205 sim = float(opts.get('similarity') or 100)
206 except ValueError:
206 except ValueError:
207 raise util.Abort(_('similarity must be a number'))
207 raise util.Abort(_('similarity must be a number'))
208 if sim < 0 or sim > 100:
208 if sim < 0 or sim > 100:
209 raise util.Abort(_('similarity must be between 0 and 100'))
209 raise util.Abort(_('similarity must be between 0 and 100'))
210 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
210 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
211
211
212 @command('^annotate|blame',
212 @command('^annotate|blame',
213 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
213 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
214 ('', 'follow', None,
214 ('', 'follow', None,
215 _('follow copies/renames and list the filename (DEPRECATED)')),
215 _('follow copies/renames and list the filename (DEPRECATED)')),
216 ('', 'no-follow', None, _("don't follow copies and renames")),
216 ('', 'no-follow', None, _("don't follow copies and renames")),
217 ('a', 'text', None, _('treat all files as text')),
217 ('a', 'text', None, _('treat all files as text')),
218 ('u', 'user', None, _('list the author (long with -v)')),
218 ('u', 'user', None, _('list the author (long with -v)')),
219 ('f', 'file', None, _('list the filename')),
219 ('f', 'file', None, _('list the filename')),
220 ('d', 'date', None, _('list the date (short with -q)')),
220 ('d', 'date', None, _('list the date (short with -q)')),
221 ('n', 'number', None, _('list the revision number (default)')),
221 ('n', 'number', None, _('list the revision number (default)')),
222 ('c', 'changeset', None, _('list the changeset')),
222 ('c', 'changeset', None, _('list the changeset')),
223 ('l', 'line-number', None, _('show line number at the first appearance'))
223 ('l', 'line-number', None, _('show line number at the first appearance'))
224 ] + diffwsopts + walkopts,
224 ] + diffwsopts + walkopts,
225 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
225 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
226 def annotate(ui, repo, *pats, **opts):
226 def annotate(ui, repo, *pats, **opts):
227 """show changeset information by line for each file
227 """show changeset information by line for each file
228
228
229 List changes in files, showing the revision id responsible for
229 List changes in files, showing the revision id responsible for
230 each line
230 each line
231
231
232 This command is useful for discovering when a change was made and
232 This command is useful for discovering when a change was made and
233 by whom.
233 by whom.
234
234
235 Without the -a/--text option, annotate will avoid processing files
235 Without the -a/--text option, annotate will avoid processing files
236 it detects as binary. With -a, annotate will annotate the file
236 it detects as binary. With -a, annotate will annotate the file
237 anyway, although the results will probably be neither useful
237 anyway, although the results will probably be neither useful
238 nor desirable.
238 nor desirable.
239
239
240 Returns 0 on success.
240 Returns 0 on success.
241 """
241 """
242 if opts.get('follow'):
242 if opts.get('follow'):
243 # --follow is deprecated and now just an alias for -f/--file
243 # --follow is deprecated and now just an alias for -f/--file
244 # to mimic the behavior of Mercurial before version 1.5
244 # to mimic the behavior of Mercurial before version 1.5
245 opts['file'] = True
245 opts['file'] = True
246
246
247 datefunc = ui.quiet and util.shortdate or util.datestr
247 datefunc = ui.quiet and util.shortdate or util.datestr
248 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
248 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
249
249
250 if not pats:
250 if not pats:
251 raise util.Abort(_('at least one filename or pattern is required'))
251 raise util.Abort(_('at least one filename or pattern is required'))
252
252
253 hexfn = ui.debugflag and hex or short
253 hexfn = ui.debugflag and hex or short
254
254
255 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
255 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
256 ('number', ' ', lambda x: str(x[0].rev())),
256 ('number', ' ', lambda x: str(x[0].rev())),
257 ('changeset', ' ', lambda x: hexfn(x[0].node())),
257 ('changeset', ' ', lambda x: hexfn(x[0].node())),
258 ('date', ' ', getdate),
258 ('date', ' ', getdate),
259 ('file', ' ', lambda x: x[0].path()),
259 ('file', ' ', lambda x: x[0].path()),
260 ('line_number', ':', lambda x: str(x[1])),
260 ('line_number', ':', lambda x: str(x[1])),
261 ]
261 ]
262
262
263 if (not opts.get('user') and not opts.get('changeset')
263 if (not opts.get('user') and not opts.get('changeset')
264 and not opts.get('date') and not opts.get('file')):
264 and not opts.get('date') and not opts.get('file')):
265 opts['number'] = True
265 opts['number'] = True
266
266
267 linenumber = opts.get('line_number') is not None
267 linenumber = opts.get('line_number') is not None
268 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
268 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
269 raise util.Abort(_('at least one of -n/-c is required for -l'))
269 raise util.Abort(_('at least one of -n/-c is required for -l'))
270
270
271 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
271 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
272 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
272 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
273
273
274 def bad(x, y):
274 def bad(x, y):
275 raise util.Abort("%s: %s" % (x, y))
275 raise util.Abort("%s: %s" % (x, y))
276
276
277 ctx = scmutil.revsingle(repo, opts.get('rev'))
277 ctx = scmutil.revsingle(repo, opts.get('rev'))
278 m = scmutil.match(ctx, pats, opts)
278 m = scmutil.match(ctx, pats, opts)
279 m.bad = bad
279 m.bad = bad
280 follow = not opts.get('no_follow')
280 follow = not opts.get('no_follow')
281 diffopts = patch.diffopts(ui, opts, section='annotate')
281 diffopts = patch.diffopts(ui, opts, section='annotate')
282 for abs in ctx.walk(m):
282 for abs in ctx.walk(m):
283 fctx = ctx[abs]
283 fctx = ctx[abs]
284 if not opts.get('text') and util.binary(fctx.data()):
284 if not opts.get('text') and util.binary(fctx.data()):
285 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
285 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
286 continue
286 continue
287
287
288 lines = fctx.annotate(follow=follow, linenumber=linenumber,
288 lines = fctx.annotate(follow=follow, linenumber=linenumber,
289 diffopts=diffopts)
289 diffopts=diffopts)
290 pieces = []
290 pieces = []
291
291
292 for f, sep in funcmap:
292 for f, sep in funcmap:
293 l = [f(n) for n, dummy in lines]
293 l = [f(n) for n, dummy in lines]
294 if l:
294 if l:
295 sized = [(x, encoding.colwidth(x)) for x in l]
295 sized = [(x, encoding.colwidth(x)) for x in l]
296 ml = max([w for x, w in sized])
296 ml = max([w for x, w in sized])
297 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
297 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
298 for x, w in sized])
298 for x, w in sized])
299
299
300 if pieces:
300 if pieces:
301 for p, l in zip(zip(*pieces), lines):
301 for p, l in zip(zip(*pieces), lines):
302 ui.write("%s: %s" % ("".join(p), l[1]))
302 ui.write("%s: %s" % ("".join(p), l[1]))
303
303
304 if lines and not lines[-1][1].endswith('\n'):
304 if lines and not lines[-1][1].endswith('\n'):
305 ui.write('\n')
305 ui.write('\n')
306
306
307 @command('archive',
307 @command('archive',
308 [('', 'no-decode', None, _('do not pass files through decoders')),
308 [('', 'no-decode', None, _('do not pass files through decoders')),
309 ('p', 'prefix', '', _('directory prefix for files in archive'),
309 ('p', 'prefix', '', _('directory prefix for files in archive'),
310 _('PREFIX')),
310 _('PREFIX')),
311 ('r', 'rev', '', _('revision to distribute'), _('REV')),
311 ('r', 'rev', '', _('revision to distribute'), _('REV')),
312 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
312 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
313 ] + subrepoopts + walkopts,
313 ] + subrepoopts + walkopts,
314 _('[OPTION]... DEST'))
314 _('[OPTION]... DEST'))
315 def archive(ui, repo, dest, **opts):
315 def archive(ui, repo, dest, **opts):
316 '''create an unversioned archive of a repository revision
316 '''create an unversioned archive of a repository revision
317
317
318 By default, the revision used is the parent of the working
318 By default, the revision used is the parent of the working
319 directory; use -r/--rev to specify a different revision.
319 directory; use -r/--rev to specify a different revision.
320
320
321 The archive type is automatically detected based on file
321 The archive type is automatically detected based on file
322 extension (or override using -t/--type).
322 extension (or override using -t/--type).
323
323
324 .. container:: verbose
324 .. container:: verbose
325
325
326 Examples:
326 Examples:
327
327
328 - create a zip file containing the 1.0 release::
328 - create a zip file containing the 1.0 release::
329
329
330 hg archive -r 1.0 project-1.0.zip
330 hg archive -r 1.0 project-1.0.zip
331
331
332 - create a tarball excluding .hg files::
332 - create a tarball excluding .hg files::
333
333
334 hg archive project.tar.gz -X ".hg*"
334 hg archive project.tar.gz -X ".hg*"
335
335
336 Valid types are:
336 Valid types are:
337
337
338 :``files``: a directory full of files (default)
338 :``files``: a directory full of files (default)
339 :``tar``: tar archive, uncompressed
339 :``tar``: tar archive, uncompressed
340 :``tbz2``: tar archive, compressed using bzip2
340 :``tbz2``: tar archive, compressed using bzip2
341 :``tgz``: tar archive, compressed using gzip
341 :``tgz``: tar archive, compressed using gzip
342 :``uzip``: zip archive, uncompressed
342 :``uzip``: zip archive, uncompressed
343 :``zip``: zip archive, compressed using deflate
343 :``zip``: zip archive, compressed using deflate
344
344
345 The exact name of the destination archive or directory is given
345 The exact name of the destination archive or directory is given
346 using a format string; see :hg:`help export` for details.
346 using a format string; see :hg:`help export` for details.
347
347
348 Each member added to an archive file has a directory prefix
348 Each member added to an archive file has a directory prefix
349 prepended. Use -p/--prefix to specify a format string for the
349 prepended. Use -p/--prefix to specify a format string for the
350 prefix. The default is the basename of the archive, with suffixes
350 prefix. The default is the basename of the archive, with suffixes
351 removed.
351 removed.
352
352
353 Returns 0 on success.
353 Returns 0 on success.
354 '''
354 '''
355
355
356 ctx = scmutil.revsingle(repo, opts.get('rev'))
356 ctx = scmutil.revsingle(repo, opts.get('rev'))
357 if not ctx:
357 if not ctx:
358 raise util.Abort(_('no working directory: please specify a revision'))
358 raise util.Abort(_('no working directory: please specify a revision'))
359 node = ctx.node()
359 node = ctx.node()
360 dest = cmdutil.makefilename(repo, dest, node)
360 dest = cmdutil.makefilename(repo, dest, node)
361 if os.path.realpath(dest) == repo.root:
361 if os.path.realpath(dest) == repo.root:
362 raise util.Abort(_('repository root cannot be destination'))
362 raise util.Abort(_('repository root cannot be destination'))
363
363
364 kind = opts.get('type') or archival.guesskind(dest) or 'files'
364 kind = opts.get('type') or archival.guesskind(dest) or 'files'
365 prefix = opts.get('prefix')
365 prefix = opts.get('prefix')
366
366
367 if dest == '-':
367 if dest == '-':
368 if kind == 'files':
368 if kind == 'files':
369 raise util.Abort(_('cannot archive plain files to stdout'))
369 raise util.Abort(_('cannot archive plain files to stdout'))
370 dest = cmdutil.makefileobj(repo, dest)
370 dest = cmdutil.makefileobj(repo, dest)
371 if not prefix:
371 if not prefix:
372 prefix = os.path.basename(repo.root) + '-%h'
372 prefix = os.path.basename(repo.root) + '-%h'
373
373
374 prefix = cmdutil.makefilename(repo, prefix, node)
374 prefix = cmdutil.makefilename(repo, prefix, node)
375 matchfn = scmutil.match(ctx, [], opts)
375 matchfn = scmutil.match(ctx, [], opts)
376 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
376 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
377 matchfn, prefix, subrepos=opts.get('subrepos'))
377 matchfn, prefix, subrepos=opts.get('subrepos'))
378
378
379 @command('backout',
379 @command('backout',
380 [('', 'merge', None, _('merge with old dirstate parent after backout')),
380 [('', 'merge', None, _('merge with old dirstate parent after backout')),
381 ('', 'parent', '',
381 ('', 'parent', '',
382 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
382 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
383 ('r', 'rev', '', _('revision to backout'), _('REV')),
383 ('r', 'rev', '', _('revision to backout'), _('REV')),
384 ] + mergetoolopts + walkopts + commitopts + commitopts2,
384 ] + mergetoolopts + walkopts + commitopts + commitopts2,
385 _('[OPTION]... [-r] REV'))
385 _('[OPTION]... [-r] REV'))
386 def backout(ui, repo, node=None, rev=None, **opts):
386 def backout(ui, repo, node=None, rev=None, **opts):
387 '''reverse effect of earlier changeset
387 '''reverse effect of earlier changeset
388
388
389 Prepare a new changeset with the effect of REV undone in the
389 Prepare a new changeset with the effect of REV undone in the
390 current working directory.
390 current working directory.
391
391
392 If REV is the parent of the working directory, then this new changeset
392 If REV is the parent of the working directory, then this new changeset
393 is committed automatically. Otherwise, hg needs to merge the
393 is committed automatically. Otherwise, hg needs to merge the
394 changes and the merged result is left uncommitted.
394 changes and the merged result is left uncommitted.
395
395
396 .. note::
396 .. note::
397 backout cannot be used to fix either an unwanted or
397 backout cannot be used to fix either an unwanted or
398 incorrect merge.
398 incorrect merge.
399
399
400 .. container:: verbose
400 .. container:: verbose
401
401
402 By default, the pending changeset will have one parent,
402 By default, the pending changeset will have one parent,
403 maintaining a linear history. With --merge, the pending
403 maintaining a linear history. With --merge, the pending
404 changeset will instead have two parents: the old parent of the
404 changeset will instead have two parents: the old parent of the
405 working directory and a new child of REV that simply undoes REV.
405 working directory and a new child of REV that simply undoes REV.
406
406
407 Before version 1.7, the behavior without --merge was equivalent
407 Before version 1.7, the behavior without --merge was equivalent
408 to specifying --merge followed by :hg:`update --clean .` to
408 to specifying --merge followed by :hg:`update --clean .` to
409 cancel the merge and leave the child of REV as a head to be
409 cancel the merge and leave the child of REV as a head to be
410 merged separately.
410 merged separately.
411
411
412 See :hg:`help dates` for a list of formats valid for -d/--date.
412 See :hg:`help dates` for a list of formats valid for -d/--date.
413
413
414 Returns 0 on success.
414 Returns 0 on success.
415 '''
415 '''
416 if rev and node:
416 if rev and node:
417 raise util.Abort(_("please specify just one revision"))
417 raise util.Abort(_("please specify just one revision"))
418
418
419 if not rev:
419 if not rev:
420 rev = node
420 rev = node
421
421
422 if not rev:
422 if not rev:
423 raise util.Abort(_("please specify a revision to backout"))
423 raise util.Abort(_("please specify a revision to backout"))
424
424
425 date = opts.get('date')
425 date = opts.get('date')
426 if date:
426 if date:
427 opts['date'] = util.parsedate(date)
427 opts['date'] = util.parsedate(date)
428
428
429 cmdutil.bailifchanged(repo)
429 cmdutil.bailifchanged(repo)
430 node = scmutil.revsingle(repo, rev).node()
430 node = scmutil.revsingle(repo, rev).node()
431
431
432 op1, op2 = repo.dirstate.parents()
432 op1, op2 = repo.dirstate.parents()
433 a = repo.changelog.ancestor(op1, node)
433 a = repo.changelog.ancestor(op1, node)
434 if a != node:
434 if a != node:
435 raise util.Abort(_('cannot backout change on a different branch'))
435 raise util.Abort(_('cannot backout change on a different branch'))
436
436
437 p1, p2 = repo.changelog.parents(node)
437 p1, p2 = repo.changelog.parents(node)
438 if p1 == nullid:
438 if p1 == nullid:
439 raise util.Abort(_('cannot backout a change with no parents'))
439 raise util.Abort(_('cannot backout a change with no parents'))
440 if p2 != nullid:
440 if p2 != nullid:
441 if not opts.get('parent'):
441 if not opts.get('parent'):
442 raise util.Abort(_('cannot backout a merge changeset'))
442 raise util.Abort(_('cannot backout a merge changeset'))
443 p = repo.lookup(opts['parent'])
443 p = repo.lookup(opts['parent'])
444 if p not in (p1, p2):
444 if p not in (p1, p2):
445 raise util.Abort(_('%s is not a parent of %s') %
445 raise util.Abort(_('%s is not a parent of %s') %
446 (short(p), short(node)))
446 (short(p), short(node)))
447 parent = p
447 parent = p
448 else:
448 else:
449 if opts.get('parent'):
449 if opts.get('parent'):
450 raise util.Abort(_('cannot use --parent on non-merge changeset'))
450 raise util.Abort(_('cannot use --parent on non-merge changeset'))
451 parent = p1
451 parent = p1
452
452
453 # the backout should appear on the same branch
453 # the backout should appear on the same branch
454 wlock = repo.wlock()
454 wlock = repo.wlock()
455 try:
455 try:
456 branch = repo.dirstate.branch()
456 branch = repo.dirstate.branch()
457 hg.clean(repo, node, show_stats=False)
457 hg.clean(repo, node, show_stats=False)
458 repo.dirstate.setbranch(branch)
458 repo.dirstate.setbranch(branch)
459 revert_opts = opts.copy()
459 revert_opts = opts.copy()
460 revert_opts['date'] = None
460 revert_opts['date'] = None
461 revert_opts['all'] = True
461 revert_opts['all'] = True
462 revert_opts['rev'] = hex(parent)
462 revert_opts['rev'] = hex(parent)
463 revert_opts['no_backup'] = None
463 revert_opts['no_backup'] = None
464 revert(ui, repo, **revert_opts)
464 revert(ui, repo, **revert_opts)
465 if not opts.get('merge') and op1 != node:
465 if not opts.get('merge') and op1 != node:
466 try:
466 try:
467 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
468 return hg.update(repo, op1)
468 return hg.update(repo, op1)
469 finally:
469 finally:
470 ui.setconfig('ui', 'forcemerge', '')
470 ui.setconfig('ui', 'forcemerge', '')
471
471
472 commit_opts = opts.copy()
472 commit_opts = opts.copy()
473 commit_opts['addremove'] = False
473 commit_opts['addremove'] = False
474 if not commit_opts['message'] and not commit_opts['logfile']:
474 if not commit_opts['message'] and not commit_opts['logfile']:
475 # we don't translate commit messages
475 # we don't translate commit messages
476 commit_opts['message'] = "Backed out changeset %s" % short(node)
476 commit_opts['message'] = "Backed out changeset %s" % short(node)
477 commit_opts['force_editor'] = True
477 commit_opts['force_editor'] = True
478 commit(ui, repo, **commit_opts)
478 commit(ui, repo, **commit_opts)
479 def nice(node):
479 def nice(node):
480 return '%d:%s' % (repo.changelog.rev(node), short(node))
480 return '%d:%s' % (repo.changelog.rev(node), short(node))
481 ui.status(_('changeset %s backs out changeset %s\n') %
481 ui.status(_('changeset %s backs out changeset %s\n') %
482 (nice(repo.changelog.tip()), nice(node)))
482 (nice(repo.changelog.tip()), nice(node)))
483 if opts.get('merge') and op1 != node:
483 if opts.get('merge') and op1 != node:
484 hg.clean(repo, op1, show_stats=False)
484 hg.clean(repo, op1, show_stats=False)
485 ui.status(_('merging with changeset %s\n')
485 ui.status(_('merging with changeset %s\n')
486 % nice(repo.changelog.tip()))
486 % nice(repo.changelog.tip()))
487 try:
487 try:
488 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
488 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
489 return hg.merge(repo, hex(repo.changelog.tip()))
489 return hg.merge(repo, hex(repo.changelog.tip()))
490 finally:
490 finally:
491 ui.setconfig('ui', 'forcemerge', '')
491 ui.setconfig('ui', 'forcemerge', '')
492 finally:
492 finally:
493 wlock.release()
493 wlock.release()
494 return 0
494 return 0
495
495
496 @command('bisect',
496 @command('bisect',
497 [('r', 'reset', False, _('reset bisect state')),
497 [('r', 'reset', False, _('reset bisect state')),
498 ('g', 'good', False, _('mark changeset good')),
498 ('g', 'good', False, _('mark changeset good')),
499 ('b', 'bad', False, _('mark changeset bad')),
499 ('b', 'bad', False, _('mark changeset bad')),
500 ('s', 'skip', False, _('skip testing changeset')),
500 ('s', 'skip', False, _('skip testing changeset')),
501 ('e', 'extend', False, _('extend the bisect range')),
501 ('e', 'extend', False, _('extend the bisect range')),
502 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
502 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
503 ('U', 'noupdate', False, _('do not update to target'))],
503 ('U', 'noupdate', False, _('do not update to target'))],
504 _("[-gbsr] [-U] [-c CMD] [REV]"))
504 _("[-gbsr] [-U] [-c CMD] [REV]"))
505 def bisect(ui, repo, rev=None, extra=None, command=None,
505 def bisect(ui, repo, rev=None, extra=None, command=None,
506 reset=None, good=None, bad=None, skip=None, extend=None,
506 reset=None, good=None, bad=None, skip=None, extend=None,
507 noupdate=None):
507 noupdate=None):
508 """subdivision search of changesets
508 """subdivision search of changesets
509
509
510 This command helps to find changesets which introduce problems. To
510 This command helps to find changesets which introduce problems. To
511 use, mark the earliest changeset you know exhibits the problem as
511 use, mark the earliest changeset you know exhibits the problem as
512 bad, then mark the latest changeset which is free from the problem
512 bad, then mark the latest changeset which is free from the problem
513 as good. Bisect will update your working directory to a revision
513 as good. Bisect will update your working directory to a revision
514 for testing (unless the -U/--noupdate option is specified). Once
514 for testing (unless the -U/--noupdate option is specified). Once
515 you have performed tests, mark the working directory as good or
515 you have performed tests, mark the working directory as good or
516 bad, and bisect will either update to another candidate changeset
516 bad, and bisect will either update to another candidate changeset
517 or announce that it has found the bad revision.
517 or announce that it has found the bad revision.
518
518
519 As a shortcut, you can also use the revision argument to mark a
519 As a shortcut, you can also use the revision argument to mark a
520 revision as good or bad without checking it out first.
520 revision as good or bad without checking it out first.
521
521
522 If you supply a command, it will be used for automatic bisection.
522 If you supply a command, it will be used for automatic bisection.
523 The environment variable HG_NODE will contain the ID of the
523 The environment variable HG_NODE will contain the ID of the
524 changeset being tested. The exit status of the command will be
524 changeset being tested. The exit status of the command will be
525 used to mark revisions as good or bad: status 0 means good, 125
525 used to mark revisions as good or bad: status 0 means good, 125
526 means to skip the revision, 127 (command not found) will abort the
526 means to skip the revision, 127 (command not found) will abort the
527 bisection, and any other non-zero exit status means the revision
527 bisection, and any other non-zero exit status means the revision
528 is bad.
528 is bad.
529
529
530 .. container:: verbose
530 .. container:: verbose
531
531
532 Some examples:
532 Some examples:
533
533
534 - start a bisection with known bad revision 12, and good revision 34::
534 - start a bisection with known bad revision 12, and good revision 34::
535
535
536 hg bisect --bad 34
536 hg bisect --bad 34
537 hg bisect --good 12
537 hg bisect --good 12
538
538
539 - advance the current bisection by marking current revision as good or
539 - advance the current bisection by marking current revision as good or
540 bad::
540 bad::
541
541
542 hg bisect --good
542 hg bisect --good
543 hg bisect --bad
543 hg bisect --bad
544
544
545 - mark the current revision, or a known revision, to be skipped (eg. if
545 - mark the current revision, or a known revision, to be skipped (eg. if
546 that revision is not usable because of another issue)::
546 that revision is not usable because of another issue)::
547
547
548 hg bisect --skip
548 hg bisect --skip
549 hg bisect --skip 23
549 hg bisect --skip 23
550
550
551 - forget the current bisection::
551 - forget the current bisection::
552
552
553 hg bisect --reset
553 hg bisect --reset
554
554
555 - use 'make && make tests' to automatically find the first broken
555 - use 'make && make tests' to automatically find the first broken
556 revision::
556 revision::
557
557
558 hg bisect --reset
558 hg bisect --reset
559 hg bisect --bad 34
559 hg bisect --bad 34
560 hg bisect --good 12
560 hg bisect --good 12
561 hg bisect --command 'make && make tests'
561 hg bisect --command 'make && make tests'
562
562
563 - see all changesets whose states are already known in the current
563 - see all changesets whose states are already known in the current
564 bisection::
564 bisection::
565
565
566 hg log -r "bisect(pruned)"
566 hg log -r "bisect(pruned)"
567
567
568 - see the changeset currently being bisected (especially useful
568 - see the changeset currently being bisected (especially useful
569 if running with -U/--noupdate)::
569 if running with -U/--noupdate)::
570
570
571 hg log -r "bisect(current)"
571 hg log -r "bisect(current)"
572
572
573 - see all changesets that took part in the current bisection::
573 - see all changesets that took part in the current bisection::
574
574
575 hg log -r "bisect(range)"
575 hg log -r "bisect(range)"
576
576
577 - with the graphlog extension, you can even get a nice graph::
577 - with the graphlog extension, you can even get a nice graph::
578
578
579 hg log --graph -r "bisect(range)"
579 hg log --graph -r "bisect(range)"
580
580
581 See :hg:`help revsets` for more about the `bisect()` keyword.
581 See :hg:`help revsets` for more about the `bisect()` keyword.
582
582
583 Returns 0 on success.
583 Returns 0 on success.
584 """
584 """
585 def extendbisectrange(nodes, good):
585 def extendbisectrange(nodes, good):
586 # bisect is incomplete when it ends on a merge node and
586 # bisect is incomplete when it ends on a merge node and
587 # one of the parent was not checked.
587 # one of the parent was not checked.
588 parents = repo[nodes[0]].parents()
588 parents = repo[nodes[0]].parents()
589 if len(parents) > 1:
589 if len(parents) > 1:
590 side = good and state['bad'] or state['good']
590 side = good and state['bad'] or state['good']
591 num = len(set(i.node() for i in parents) & set(side))
591 num = len(set(i.node() for i in parents) & set(side))
592 if num == 1:
592 if num == 1:
593 return parents[0].ancestor(parents[1])
593 return parents[0].ancestor(parents[1])
594 return None
594 return None
595
595
596 def print_result(nodes, good):
596 def print_result(nodes, good):
597 displayer = cmdutil.show_changeset(ui, repo, {})
597 displayer = cmdutil.show_changeset(ui, repo, {})
598 if len(nodes) == 1:
598 if len(nodes) == 1:
599 # narrowed it down to a single revision
599 # narrowed it down to a single revision
600 if good:
600 if good:
601 ui.write(_("The first good revision is:\n"))
601 ui.write(_("The first good revision is:\n"))
602 else:
602 else:
603 ui.write(_("The first bad revision is:\n"))
603 ui.write(_("The first bad revision is:\n"))
604 displayer.show(repo[nodes[0]])
604 displayer.show(repo[nodes[0]])
605 extendnode = extendbisectrange(nodes, good)
605 extendnode = extendbisectrange(nodes, good)
606 if extendnode is not None:
606 if extendnode is not None:
607 ui.write(_('Not all ancestors of this changeset have been'
607 ui.write(_('Not all ancestors of this changeset have been'
608 ' checked.\nUse bisect --extend to continue the '
608 ' checked.\nUse bisect --extend to continue the '
609 'bisection from\nthe common ancestor, %s.\n')
609 'bisection from\nthe common ancestor, %s.\n')
610 % extendnode)
610 % extendnode)
611 else:
611 else:
612 # multiple possible revisions
612 # multiple possible revisions
613 if good:
613 if good:
614 ui.write(_("Due to skipped revisions, the first "
614 ui.write(_("Due to skipped revisions, the first "
615 "good revision could be any of:\n"))
615 "good revision could be any of:\n"))
616 else:
616 else:
617 ui.write(_("Due to skipped revisions, the first "
617 ui.write(_("Due to skipped revisions, the first "
618 "bad revision could be any of:\n"))
618 "bad revision could be any of:\n"))
619 for n in nodes:
619 for n in nodes:
620 displayer.show(repo[n])
620 displayer.show(repo[n])
621 displayer.close()
621 displayer.close()
622
622
623 def check_state(state, interactive=True):
623 def check_state(state, interactive=True):
624 if not state['good'] or not state['bad']:
624 if not state['good'] or not state['bad']:
625 if (good or bad or skip or reset) and interactive:
625 if (good or bad or skip or reset) and interactive:
626 return
626 return
627 if not state['good']:
627 if not state['good']:
628 raise util.Abort(_('cannot bisect (no known good revisions)'))
628 raise util.Abort(_('cannot bisect (no known good revisions)'))
629 else:
629 else:
630 raise util.Abort(_('cannot bisect (no known bad revisions)'))
630 raise util.Abort(_('cannot bisect (no known bad revisions)'))
631 return True
631 return True
632
632
633 # backward compatibility
633 # backward compatibility
634 if rev in "good bad reset init".split():
634 if rev in "good bad reset init".split():
635 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
635 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
636 cmd, rev, extra = rev, extra, None
636 cmd, rev, extra = rev, extra, None
637 if cmd == "good":
637 if cmd == "good":
638 good = True
638 good = True
639 elif cmd == "bad":
639 elif cmd == "bad":
640 bad = True
640 bad = True
641 else:
641 else:
642 reset = True
642 reset = True
643 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
643 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
644 raise util.Abort(_('incompatible arguments'))
644 raise util.Abort(_('incompatible arguments'))
645
645
646 if reset:
646 if reset:
647 p = repo.join("bisect.state")
647 p = repo.join("bisect.state")
648 if os.path.exists(p):
648 if os.path.exists(p):
649 os.unlink(p)
649 os.unlink(p)
650 return
650 return
651
651
652 state = hbisect.load_state(repo)
652 state = hbisect.load_state(repo)
653
653
654 if command:
654 if command:
655 changesets = 1
655 changesets = 1
656 try:
656 try:
657 node = state['current'][0]
657 node = state['current'][0]
658 except LookupError:
658 except LookupError:
659 if noupdate:
659 if noupdate:
660 raise util.Abort(_('current bisect revision is unknown - '
660 raise util.Abort(_('current bisect revision is unknown - '
661 'start a new bisect to fix'))
661 'start a new bisect to fix'))
662 node, p2 = repo.dirstate.parents()
662 node, p2 = repo.dirstate.parents()
663 if p2 != nullid:
663 if p2 != nullid:
664 raise util.Abort(_('current bisect revision is a merge'))
664 raise util.Abort(_('current bisect revision is a merge'))
665 try:
665 try:
666 while changesets:
666 while changesets:
667 # update state
667 # update state
668 state['current'] = [node]
668 state['current'] = [node]
669 hbisect.save_state(repo, state)
669 hbisect.save_state(repo, state)
670 status = util.system(command,
670 status = util.system(command,
671 environ={'HG_NODE': hex(node)},
671 environ={'HG_NODE': hex(node)},
672 out=ui.fout)
672 out=ui.fout)
673 if status == 125:
673 if status == 125:
674 transition = "skip"
674 transition = "skip"
675 elif status == 0:
675 elif status == 0:
676 transition = "good"
676 transition = "good"
677 # status < 0 means process was killed
677 # status < 0 means process was killed
678 elif status == 127:
678 elif status == 127:
679 raise util.Abort(_("failed to execute %s") % command)
679 raise util.Abort(_("failed to execute %s") % command)
680 elif status < 0:
680 elif status < 0:
681 raise util.Abort(_("%s killed") % command)
681 raise util.Abort(_("%s killed") % command)
682 else:
682 else:
683 transition = "bad"
683 transition = "bad"
684 ctx = scmutil.revsingle(repo, rev, node)
684 ctx = scmutil.revsingle(repo, rev, node)
685 rev = None # clear for future iterations
685 rev = None # clear for future iterations
686 state[transition].append(ctx.node())
686 state[transition].append(ctx.node())
687 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
687 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
688 check_state(state, interactive=False)
688 check_state(state, interactive=False)
689 # bisect
689 # bisect
690 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
690 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
691 # update to next check
691 # update to next check
692 node = nodes[0]
692 node = nodes[0]
693 if not noupdate:
693 if not noupdate:
694 cmdutil.bailifchanged(repo)
694 cmdutil.bailifchanged(repo)
695 hg.clean(repo, node, show_stats=False)
695 hg.clean(repo, node, show_stats=False)
696 finally:
696 finally:
697 state['current'] = [node]
697 state['current'] = [node]
698 hbisect.save_state(repo, state)
698 hbisect.save_state(repo, state)
699 print_result(nodes, good)
699 print_result(nodes, good)
700 return
700 return
701
701
702 # update state
702 # update state
703
703
704 if rev:
704 if rev:
705 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
705 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
706 else:
706 else:
707 nodes = [repo.lookup('.')]
707 nodes = [repo.lookup('.')]
708
708
709 if good or bad or skip:
709 if good or bad or skip:
710 if good:
710 if good:
711 state['good'] += nodes
711 state['good'] += nodes
712 elif bad:
712 elif bad:
713 state['bad'] += nodes
713 state['bad'] += nodes
714 elif skip:
714 elif skip:
715 state['skip'] += nodes
715 state['skip'] += nodes
716 hbisect.save_state(repo, state)
716 hbisect.save_state(repo, state)
717
717
718 if not check_state(state):
718 if not check_state(state):
719 return
719 return
720
720
721 # actually bisect
721 # actually bisect
722 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
722 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
723 if extend:
723 if extend:
724 if not changesets:
724 if not changesets:
725 extendnode = extendbisectrange(nodes, good)
725 extendnode = extendbisectrange(nodes, good)
726 if extendnode is not None:
726 if extendnode is not None:
727 ui.write(_("Extending search to changeset %d:%s\n"
727 ui.write(_("Extending search to changeset %d:%s\n"
728 % (extendnode.rev(), extendnode)))
728 % (extendnode.rev(), extendnode)))
729 state['current'] = [extendnode.node()]
729 state['current'] = [extendnode.node()]
730 hbisect.save_state(repo, state)
730 hbisect.save_state(repo, state)
731 if noupdate:
731 if noupdate:
732 return
732 return
733 cmdutil.bailifchanged(repo)
733 cmdutil.bailifchanged(repo)
734 return hg.clean(repo, extendnode.node())
734 return hg.clean(repo, extendnode.node())
735 raise util.Abort(_("nothing to extend"))
735 raise util.Abort(_("nothing to extend"))
736
736
737 if changesets == 0:
737 if changesets == 0:
738 print_result(nodes, good)
738 print_result(nodes, good)
739 else:
739 else:
740 assert len(nodes) == 1 # only a single node can be tested next
740 assert len(nodes) == 1 # only a single node can be tested next
741 node = nodes[0]
741 node = nodes[0]
742 # compute the approximate number of remaining tests
742 # compute the approximate number of remaining tests
743 tests, size = 0, 2
743 tests, size = 0, 2
744 while size <= changesets:
744 while size <= changesets:
745 tests, size = tests + 1, size * 2
745 tests, size = tests + 1, size * 2
746 rev = repo.changelog.rev(node)
746 rev = repo.changelog.rev(node)
747 ui.write(_("Testing changeset %d:%s "
747 ui.write(_("Testing changeset %d:%s "
748 "(%d changesets remaining, ~%d tests)\n")
748 "(%d changesets remaining, ~%d tests)\n")
749 % (rev, short(node), changesets, tests))
749 % (rev, short(node), changesets, tests))
750 state['current'] = [node]
750 state['current'] = [node]
751 hbisect.save_state(repo, state)
751 hbisect.save_state(repo, state)
752 if not noupdate:
752 if not noupdate:
753 cmdutil.bailifchanged(repo)
753 cmdutil.bailifchanged(repo)
754 return hg.clean(repo, node)
754 return hg.clean(repo, node)
755
755
756 @command('bookmarks',
756 @command('bookmarks',
757 [('f', 'force', False, _('force')),
757 [('f', 'force', False, _('force')),
758 ('r', 'rev', '', _('revision'), _('REV')),
758 ('r', 'rev', '', _('revision'), _('REV')),
759 ('d', 'delete', False, _('delete a given bookmark')),
759 ('d', 'delete', False, _('delete a given bookmark')),
760 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
760 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
761 ('i', 'inactive', False, _('mark a bookmark inactive'))],
761 ('i', 'inactive', False, _('mark a bookmark inactive'))],
762 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
762 _('hg bookmarks [-f] [-d] [-i] [-m NAME] [-r REV] [NAME]'))
763 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
763 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False,
764 rename=None, inactive=False):
764 rename=None, inactive=False):
765 '''track a line of development with movable markers
765 '''track a line of development with movable markers
766
766
767 Bookmarks are pointers to certain commits that move when committing.
767 Bookmarks are pointers to certain commits that move when committing.
768 Bookmarks are local. They can be renamed, copied and deleted. It is
768 Bookmarks are local. They can be renamed, copied and deleted. It is
769 possible to use :hg:`merge NAME` to merge from a given bookmark, and
769 possible to use :hg:`merge NAME` to merge from a given bookmark, and
770 :hg:`update NAME` to update to a given bookmark.
770 :hg:`update NAME` to update to a given bookmark.
771
771
772 You can use :hg:`bookmark NAME` to set a bookmark on the working
772 You can use :hg:`bookmark NAME` to set a bookmark on the working
773 directory's parent revision with the given name. If you specify
773 directory's parent revision with the given name. If you specify
774 a revision using -r REV (where REV may be an existing bookmark),
774 a revision using -r REV (where REV may be an existing bookmark),
775 the bookmark is assigned to that revision.
775 the bookmark is assigned to that revision.
776
776
777 Bookmarks can be pushed and pulled between repositories (see :hg:`help
777 Bookmarks can be pushed and pulled between repositories (see :hg:`help
778 push` and :hg:`help pull`). This requires both the local and remote
778 push` and :hg:`help pull`). This requires both the local and remote
779 repositories to support bookmarks. For versions prior to 1.8, this means
779 repositories to support bookmarks. For versions prior to 1.8, this means
780 the bookmarks extension must be enabled.
780 the bookmarks extension must be enabled.
781
781
782 With -i/--inactive, the new bookmark will not be made the active
782 With -i/--inactive, the new bookmark will not be made the active
783 bookmark. If -r/--rev is given, the new bookmark will not be made
783 bookmark. If -r/--rev is given, the new bookmark will not be made
784 active even if -i/--inactive is not given. If no NAME is given, the
784 active even if -i/--inactive is not given. If no NAME is given, the
785 current active bookmark will be marked inactive.
785 current active bookmark will be marked inactive.
786 '''
786 '''
787 hexfn = ui.debugflag and hex or short
787 hexfn = ui.debugflag and hex or short
788 marks = repo._bookmarks
788 marks = repo._bookmarks
789 cur = repo.changectx('.').node()
789 cur = repo.changectx('.').node()
790
790
791 if delete:
791 if delete:
792 if mark is None:
792 if mark is None:
793 raise util.Abort(_("bookmark name required"))
793 raise util.Abort(_("bookmark name required"))
794 if mark not in marks:
794 if mark not in marks:
795 raise util.Abort(_("bookmark '%s' does not exist") % mark)
795 raise util.Abort(_("bookmark '%s' does not exist") % mark)
796 if mark == repo._bookmarkcurrent:
796 if mark == repo._bookmarkcurrent:
797 bookmarks.setcurrent(repo, None)
797 bookmarks.setcurrent(repo, None)
798 del marks[mark]
798 del marks[mark]
799 bookmarks.write(repo)
799 bookmarks.write(repo)
800 return
800 return
801
801
802 if rename:
802 if rename:
803 if rename not in marks:
803 if rename not in marks:
804 raise util.Abort(_("bookmark '%s' does not exist") % rename)
804 raise util.Abort(_("bookmark '%s' does not exist") % rename)
805 if mark in marks and not force:
805 if mark in marks and not force:
806 raise util.Abort(_("bookmark '%s' already exists "
806 raise util.Abort(_("bookmark '%s' already exists "
807 "(use -f to force)") % mark)
807 "(use -f to force)") % mark)
808 if mark is None:
808 if mark is None:
809 raise util.Abort(_("new bookmark name required"))
809 raise util.Abort(_("new bookmark name required"))
810 marks[mark] = marks[rename]
810 marks[mark] = marks[rename]
811 if repo._bookmarkcurrent == rename and not inactive:
811 if repo._bookmarkcurrent == rename and not inactive:
812 bookmarks.setcurrent(repo, mark)
812 bookmarks.setcurrent(repo, mark)
813 del marks[rename]
813 del marks[rename]
814 bookmarks.write(repo)
814 bookmarks.write(repo)
815 return
815 return
816
816
817 if mark is not None:
817 if mark is not None:
818 if "\n" in mark:
818 if "\n" in mark:
819 raise util.Abort(_("bookmark name cannot contain newlines"))
819 raise util.Abort(_("bookmark name cannot contain newlines"))
820 mark = mark.strip()
820 mark = mark.strip()
821 if not mark:
821 if not mark:
822 raise util.Abort(_("bookmark names cannot consist entirely of "
822 raise util.Abort(_("bookmark names cannot consist entirely of "
823 "whitespace"))
823 "whitespace"))
824 if inactive and mark == repo._bookmarkcurrent:
824 if inactive and mark == repo._bookmarkcurrent:
825 bookmarks.setcurrent(repo, None)
825 bookmarks.setcurrent(repo, None)
826 return
826 return
827 if mark in marks and not force:
827 if mark in marks and not force:
828 raise util.Abort(_("bookmark '%s' already exists "
828 raise util.Abort(_("bookmark '%s' already exists "
829 "(use -f to force)") % mark)
829 "(use -f to force)") % mark)
830 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
830 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
831 and not force):
831 and not force):
832 raise util.Abort(
832 raise util.Abort(
833 _("a bookmark cannot have the name of an existing branch"))
833 _("a bookmark cannot have the name of an existing branch"))
834 if rev:
834 if rev:
835 marks[mark] = repo.lookup(rev)
835 marks[mark] = repo.lookup(rev)
836 else:
836 else:
837 marks[mark] = cur
837 marks[mark] = cur
838 if not inactive and cur == marks[mark]:
838 if not inactive and cur == marks[mark]:
839 bookmarks.setcurrent(repo, mark)
839 bookmarks.setcurrent(repo, mark)
840 bookmarks.write(repo)
840 bookmarks.write(repo)
841 return
841 return
842
842
843 if mark is None:
843 if mark is None:
844 if rev:
844 if rev:
845 raise util.Abort(_("bookmark name required"))
845 raise util.Abort(_("bookmark name required"))
846 if len(marks) == 0:
846 if len(marks) == 0:
847 ui.status(_("no bookmarks set\n"))
847 ui.status(_("no bookmarks set\n"))
848 else:
848 else:
849 for bmark, n in sorted(marks.iteritems()):
849 for bmark, n in sorted(marks.iteritems()):
850 current = repo._bookmarkcurrent
850 current = repo._bookmarkcurrent
851 if bmark == current and n == cur:
851 if bmark == current and n == cur:
852 prefix, label = '*', 'bookmarks.current'
852 prefix, label = '*', 'bookmarks.current'
853 else:
853 else:
854 prefix, label = ' ', ''
854 prefix, label = ' ', ''
855
855
856 if ui.quiet:
856 if ui.quiet:
857 ui.write("%s\n" % bmark, label=label)
857 ui.write("%s\n" % bmark, label=label)
858 else:
858 else:
859 ui.write(" %s %-25s %d:%s\n" % (
859 ui.write(" %s %-25s %d:%s\n" % (
860 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
860 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
861 label=label)
861 label=label)
862 return
862 return
863
863
864 @command('branch',
864 @command('branch',
865 [('f', 'force', None,
865 [('f', 'force', None,
866 _('set branch name even if it shadows an existing branch')),
866 _('set branch name even if it shadows an existing branch')),
867 ('C', 'clean', None, _('reset branch name to parent branch name'))],
867 ('C', 'clean', None, _('reset branch name to parent branch name'))],
868 _('[-fC] [NAME]'))
868 _('[-fC] [NAME]'))
869 def branch(ui, repo, label=None, **opts):
869 def branch(ui, repo, label=None, **opts):
870 """set or show the current branch name
870 """set or show the current branch name
871
871
872 .. note::
872 .. note::
873 Branch names are permanent and global. Use :hg:`bookmark` to create a
873 Branch names are permanent and global. Use :hg:`bookmark` to create a
874 light-weight bookmark instead. See :hg:`help glossary` for more
874 light-weight bookmark instead. See :hg:`help glossary` for more
875 information about named branches and bookmarks.
875 information about named branches and bookmarks.
876
876
877 With no argument, show the current branch name. With one argument,
877 With no argument, show the current branch name. With one argument,
878 set the working directory branch name (the branch will not exist
878 set the working directory branch name (the branch will not exist
879 in the repository until the next commit). Standard practice
879 in the repository until the next commit). Standard practice
880 recommends that primary development take place on the 'default'
880 recommends that primary development take place on the 'default'
881 branch.
881 branch.
882
882
883 Unless -f/--force is specified, branch will not let you set a
883 Unless -f/--force is specified, branch will not let you set a
884 branch name that already exists, even if it's inactive.
884 branch name that already exists, even if it's inactive.
885
885
886 Use -C/--clean to reset the working directory branch to that of
886 Use -C/--clean to reset the working directory branch to that of
887 the parent of the working directory, negating a previous branch
887 the parent of the working directory, negating a previous branch
888 change.
888 change.
889
889
890 Use the command :hg:`update` to switch to an existing branch. Use
890 Use the command :hg:`update` to switch to an existing branch. Use
891 :hg:`commit --close-branch` to mark this branch as closed.
891 :hg:`commit --close-branch` to mark this branch as closed.
892
892
893 Returns 0 on success.
893 Returns 0 on success.
894 """
894 """
895 if not opts.get('clean') and not label:
895 if not opts.get('clean') and not label:
896 ui.write("%s\n" % repo.dirstate.branch())
896 ui.write("%s\n" % repo.dirstate.branch())
897 return
897 return
898
898
899 wlock = repo.wlock()
899 wlock = repo.wlock()
900 try:
900 try:
901 if opts.get('clean'):
901 if opts.get('clean'):
902 label = repo[None].p1().branch()
902 label = repo[None].p1().branch()
903 repo.dirstate.setbranch(label)
903 repo.dirstate.setbranch(label)
904 ui.status(_('reset working directory to branch %s\n') % label)
904 ui.status(_('reset working directory to branch %s\n') % label)
905 elif label:
905 elif label:
906 if not opts.get('force') and label in repo.branchmap():
906 if not opts.get('force') and label in repo.branchmap():
907 if label not in [p.branch() for p in repo.parents()]:
907 if label not in [p.branch() for p in repo.parents()]:
908 raise util.Abort(_('a branch of the same name already'
908 raise util.Abort(_('a branch of the same name already'
909 ' exists'),
909 ' exists'),
910 # i18n: "it" refers to an existing branch
910 # i18n: "it" refers to an existing branch
911 hint=_("use 'hg update' to switch to it"))
911 hint=_("use 'hg update' to switch to it"))
912 repo.dirstate.setbranch(label)
912 repo.dirstate.setbranch(label)
913 ui.status(_('marked working directory as branch %s\n') % label)
913 ui.status(_('marked working directory as branch %s\n') % label)
914 ui.status(_('(branches are permanent and global, '
914 ui.status(_('(branches are permanent and global, '
915 'did you want a bookmark?)\n'))
915 'did you want a bookmark?)\n'))
916 finally:
916 finally:
917 wlock.release()
917 wlock.release()
918
918
919 @command('branches',
919 @command('branches',
920 [('a', 'active', False, _('show only branches that have unmerged heads')),
920 [('a', 'active', False, _('show only branches that have unmerged heads')),
921 ('c', 'closed', False, _('show normal and closed branches'))],
921 ('c', 'closed', False, _('show normal and closed branches'))],
922 _('[-ac]'))
922 _('[-ac]'))
923 def branches(ui, repo, active=False, closed=False):
923 def branches(ui, repo, active=False, closed=False):
924 """list repository named branches
924 """list repository named branches
925
925
926 List the repository's named branches, indicating which ones are
926 List the repository's named branches, indicating which ones are
927 inactive. If -c/--closed is specified, also list branches which have
927 inactive. If -c/--closed is specified, also list branches which have
928 been marked closed (see :hg:`commit --close-branch`).
928 been marked closed (see :hg:`commit --close-branch`).
929
929
930 If -a/--active is specified, only show active branches. A branch
930 If -a/--active is specified, only show active branches. A branch
931 is considered active if it contains repository heads.
931 is considered active if it contains repository heads.
932
932
933 Use the command :hg:`update` to switch to an existing branch.
933 Use the command :hg:`update` to switch to an existing branch.
934
934
935 Returns 0.
935 Returns 0.
936 """
936 """
937
937
938 hexfunc = ui.debugflag and hex or short
938 hexfunc = ui.debugflag and hex or short
939
939
940 activebranches = set([repo[n].branch() for n in repo.heads()])
940 activebranches = set([repo[n].branch() for n in repo.heads()])
941 branches = []
941 branches = []
942 for tag, heads in repo.branchmap().iteritems():
942 for tag, heads in repo.branchmap().iteritems():
943 for h in reversed(heads):
943 for h in reversed(heads):
944 ctx = repo[h]
944 ctx = repo[h]
945 isopen = not ctx.closesbranch()
945 isopen = not ctx.closesbranch()
946 if isopen:
946 if isopen:
947 tip = ctx
947 tip = ctx
948 break
948 break
949 else:
949 else:
950 tip = repo[heads[-1]]
950 tip = repo[heads[-1]]
951 isactive = tag in activebranches and isopen
951 isactive = tag in activebranches and isopen
952 branches.append((tip, isactive, isopen))
952 branches.append((tip, isactive, isopen))
953 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
953 branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
954 reverse=True)
954 reverse=True)
955
955
956 for ctx, isactive, isopen in branches:
956 for ctx, isactive, isopen in branches:
957 if (not active) or isactive:
957 if (not active) or isactive:
958 if isactive:
958 if isactive:
959 label = 'branches.active'
959 label = 'branches.active'
960 notice = ''
960 notice = ''
961 elif not isopen:
961 elif not isopen:
962 if not closed:
962 if not closed:
963 continue
963 continue
964 label = 'branches.closed'
964 label = 'branches.closed'
965 notice = _(' (closed)')
965 notice = _(' (closed)')
966 else:
966 else:
967 label = 'branches.inactive'
967 label = 'branches.inactive'
968 notice = _(' (inactive)')
968 notice = _(' (inactive)')
969 if ctx.branch() == repo.dirstate.branch():
969 if ctx.branch() == repo.dirstate.branch():
970 label = 'branches.current'
970 label = 'branches.current'
971 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
971 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
972 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
972 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
973 'log.changeset')
973 'log.changeset')
974 tag = ui.label(ctx.branch(), label)
974 tag = ui.label(ctx.branch(), label)
975 if ui.quiet:
975 if ui.quiet:
976 ui.write("%s\n" % tag)
976 ui.write("%s\n" % tag)
977 else:
977 else:
978 ui.write("%s %s%s\n" % (tag, rev, notice))
978 ui.write("%s %s%s\n" % (tag, rev, notice))
979
979
980 @command('bundle',
980 @command('bundle',
981 [('f', 'force', None, _('run even when the destination is unrelated')),
981 [('f', 'force', None, _('run even when the destination is unrelated')),
982 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
982 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
983 _('REV')),
983 _('REV')),
984 ('b', 'branch', [], _('a specific branch you would like to bundle'),
984 ('b', 'branch', [], _('a specific branch you would like to bundle'),
985 _('BRANCH')),
985 _('BRANCH')),
986 ('', 'base', [],
986 ('', 'base', [],
987 _('a base changeset assumed to be available at the destination'),
987 _('a base changeset assumed to be available at the destination'),
988 _('REV')),
988 _('REV')),
989 ('a', 'all', None, _('bundle all changesets in the repository')),
989 ('a', 'all', None, _('bundle all changesets in the repository')),
990 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
990 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
991 ] + remoteopts,
991 ] + remoteopts,
992 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
992 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
993 def bundle(ui, repo, fname, dest=None, **opts):
993 def bundle(ui, repo, fname, dest=None, **opts):
994 """create a changegroup file
994 """create a changegroup file
995
995
996 Generate a compressed changegroup file collecting changesets not
996 Generate a compressed changegroup file collecting changesets not
997 known to be in another repository.
997 known to be in another repository.
998
998
999 If you omit the destination repository, then hg assumes the
999 If you omit the destination repository, then hg assumes the
1000 destination will have all the nodes you specify with --base
1000 destination will have all the nodes you specify with --base
1001 parameters. To create a bundle containing all changesets, use
1001 parameters. To create a bundle containing all changesets, use
1002 -a/--all (or --base null).
1002 -a/--all (or --base null).
1003
1003
1004 You can change compression method with the -t/--type option.
1004 You can change compression method with the -t/--type option.
1005 The available compression methods are: none, bzip2, and
1005 The available compression methods are: none, bzip2, and
1006 gzip (by default, bundles are compressed using bzip2).
1006 gzip (by default, bundles are compressed using bzip2).
1007
1007
1008 The bundle file can then be transferred using conventional means
1008 The bundle file can then be transferred using conventional means
1009 and applied to another repository with the unbundle or pull
1009 and applied to another repository with the unbundle or pull
1010 command. This is useful when direct push and pull are not
1010 command. This is useful when direct push and pull are not
1011 available or when exporting an entire repository is undesirable.
1011 available or when exporting an entire repository is undesirable.
1012
1012
1013 Applying bundles preserves all changeset contents including
1013 Applying bundles preserves all changeset contents including
1014 permissions, copy/rename information, and revision history.
1014 permissions, copy/rename information, and revision history.
1015
1015
1016 Returns 0 on success, 1 if no changes found.
1016 Returns 0 on success, 1 if no changes found.
1017 """
1017 """
1018 revs = None
1018 revs = None
1019 if 'rev' in opts:
1019 if 'rev' in opts:
1020 revs = scmutil.revrange(repo, opts['rev'])
1020 revs = scmutil.revrange(repo, opts['rev'])
1021
1021
1022 bundletype = opts.get('type', 'bzip2').lower()
1022 bundletype = opts.get('type', 'bzip2').lower()
1023 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1023 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1024 bundletype = btypes.get(bundletype)
1024 bundletype = btypes.get(bundletype)
1025 if bundletype not in changegroup.bundletypes:
1025 if bundletype not in changegroup.bundletypes:
1026 raise util.Abort(_('unknown bundle type specified with --type'))
1026 raise util.Abort(_('unknown bundle type specified with --type'))
1027
1027
1028 if opts.get('all'):
1028 if opts.get('all'):
1029 base = ['null']
1029 base = ['null']
1030 else:
1030 else:
1031 base = scmutil.revrange(repo, opts.get('base'))
1031 base = scmutil.revrange(repo, opts.get('base'))
1032 if base:
1032 if base:
1033 if dest:
1033 if dest:
1034 raise util.Abort(_("--base is incompatible with specifying "
1034 raise util.Abort(_("--base is incompatible with specifying "
1035 "a destination"))
1035 "a destination"))
1036 common = [repo.lookup(rev) for rev in base]
1036 common = [repo.lookup(rev) for rev in base]
1037 heads = revs and map(repo.lookup, revs) or revs
1037 heads = revs and map(repo.lookup, revs) or revs
1038 cg = repo.getbundle('bundle', heads=heads, common=common)
1038 cg = repo.getbundle('bundle', heads=heads, common=common)
1039 outgoing = None
1039 outgoing = None
1040 else:
1040 else:
1041 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1041 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1042 dest, branches = hg.parseurl(dest, opts.get('branch'))
1042 dest, branches = hg.parseurl(dest, opts.get('branch'))
1043 other = hg.peer(repo, opts, dest)
1043 other = hg.peer(repo, opts, dest)
1044 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1044 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
1045 heads = revs and map(repo.lookup, revs) or revs
1045 heads = revs and map(repo.lookup, revs) or revs
1046 outgoing = discovery.findcommonoutgoing(repo, other,
1046 outgoing = discovery.findcommonoutgoing(repo, other,
1047 onlyheads=heads,
1047 onlyheads=heads,
1048 force=opts.get('force'),
1048 force=opts.get('force'),
1049 portable=True)
1049 portable=True)
1050 cg = repo.getlocalbundle('bundle', outgoing)
1050 cg = repo.getlocalbundle('bundle', outgoing)
1051 if not cg:
1051 if not cg:
1052 scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
1052 scmutil.nochangesfound(ui, outgoing and outgoing.excluded)
1053 return 1
1053 return 1
1054
1054
1055 changegroup.writebundle(cg, fname, bundletype)
1055 changegroup.writebundle(cg, fname, bundletype)
1056
1056
1057 @command('cat',
1057 @command('cat',
1058 [('o', 'output', '',
1058 [('o', 'output', '',
1059 _('print output to file with formatted name'), _('FORMAT')),
1059 _('print output to file with formatted name'), _('FORMAT')),
1060 ('r', 'rev', '', _('print the given revision'), _('REV')),
1060 ('r', 'rev', '', _('print the given revision'), _('REV')),
1061 ('', 'decode', None, _('apply any matching decode filter')),
1061 ('', 'decode', None, _('apply any matching decode filter')),
1062 ] + walkopts,
1062 ] + walkopts,
1063 _('[OPTION]... FILE...'))
1063 _('[OPTION]... FILE...'))
1064 def cat(ui, repo, file1, *pats, **opts):
1064 def cat(ui, repo, file1, *pats, **opts):
1065 """output the current or given revision of files
1065 """output the current or given revision of files
1066
1066
1067 Print the specified files as they were at the given revision. If
1067 Print the specified files as they were at the given revision. If
1068 no revision is given, the parent of the working directory is used,
1068 no revision is given, the parent of the working directory is used,
1069 or tip if no revision is checked out.
1069 or tip if no revision is checked out.
1070
1070
1071 Output may be to a file, in which case the name of the file is
1071 Output may be to a file, in which case the name of the file is
1072 given using a format string. The formatting rules are the same as
1072 given using a format string. The formatting rules are the same as
1073 for the export command, with the following additions:
1073 for the export command, with the following additions:
1074
1074
1075 :``%s``: basename of file being printed
1075 :``%s``: basename of file being printed
1076 :``%d``: dirname of file being printed, or '.' if in repository root
1076 :``%d``: dirname of file being printed, or '.' if in repository root
1077 :``%p``: root-relative path name of file being printed
1077 :``%p``: root-relative path name of file being printed
1078
1078
1079 Returns 0 on success.
1079 Returns 0 on success.
1080 """
1080 """
1081 ctx = scmutil.revsingle(repo, opts.get('rev'))
1081 ctx = scmutil.revsingle(repo, opts.get('rev'))
1082 err = 1
1082 err = 1
1083 m = scmutil.match(ctx, (file1,) + pats, opts)
1083 m = scmutil.match(ctx, (file1,) + pats, opts)
1084 for abs in ctx.walk(m):
1084 for abs in ctx.walk(m):
1085 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1085 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1086 pathname=abs)
1086 pathname=abs)
1087 data = ctx[abs].data()
1087 data = ctx[abs].data()
1088 if opts.get('decode'):
1088 if opts.get('decode'):
1089 data = repo.wwritedata(abs, data)
1089 data = repo.wwritedata(abs, data)
1090 fp.write(data)
1090 fp.write(data)
1091 fp.close()
1091 fp.close()
1092 err = 0
1092 err = 0
1093 return err
1093 return err
1094
1094
1095 @command('^clone',
1095 @command('^clone',
1096 [('U', 'noupdate', None,
1096 [('U', 'noupdate', None,
1097 _('the clone will include an empty working copy (only a repository)')),
1097 _('the clone will include an empty working copy (only a repository)')),
1098 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1098 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1099 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1099 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1100 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1100 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1101 ('', 'pull', None, _('use pull protocol to copy metadata')),
1101 ('', 'pull', None, _('use pull protocol to copy metadata')),
1102 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1102 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1103 ] + remoteopts,
1103 ] + remoteopts,
1104 _('[OPTION]... SOURCE [DEST]'))
1104 _('[OPTION]... SOURCE [DEST]'))
1105 def clone(ui, source, dest=None, **opts):
1105 def clone(ui, source, dest=None, **opts):
1106 """make a copy of an existing repository
1106 """make a copy of an existing repository
1107
1107
1108 Create a copy of an existing repository in a new directory.
1108 Create a copy of an existing repository in a new directory.
1109
1109
1110 If no destination directory name is specified, it defaults to the
1110 If no destination directory name is specified, it defaults to the
1111 basename of the source.
1111 basename of the source.
1112
1112
1113 The location of the source is added to the new repository's
1113 The location of the source is added to the new repository's
1114 ``.hg/hgrc`` file, as the default to be used for future pulls.
1114 ``.hg/hgrc`` file, as the default to be used for future pulls.
1115
1115
1116 Only local paths and ``ssh://`` URLs are supported as
1116 Only local paths and ``ssh://`` URLs are supported as
1117 destinations. For ``ssh://`` destinations, no working directory or
1117 destinations. For ``ssh://`` destinations, no working directory or
1118 ``.hg/hgrc`` will be created on the remote side.
1118 ``.hg/hgrc`` will be created on the remote side.
1119
1119
1120 To pull only a subset of changesets, specify one or more revisions
1120 To pull only a subset of changesets, specify one or more revisions
1121 identifiers with -r/--rev or branches with -b/--branch. The
1121 identifiers with -r/--rev or branches with -b/--branch. The
1122 resulting clone will contain only the specified changesets and
1122 resulting clone will contain only the specified changesets and
1123 their ancestors. These options (or 'clone src#rev dest') imply
1123 their ancestors. These options (or 'clone src#rev dest') imply
1124 --pull, even for local source repositories. Note that specifying a
1124 --pull, even for local source repositories. Note that specifying a
1125 tag will include the tagged changeset but not the changeset
1125 tag will include the tagged changeset but not the changeset
1126 containing the tag.
1126 containing the tag.
1127
1127
1128 To check out a particular version, use -u/--update, or
1128 To check out a particular version, use -u/--update, or
1129 -U/--noupdate to create a clone with no working directory.
1129 -U/--noupdate to create a clone with no working directory.
1130
1130
1131 .. container:: verbose
1131 .. container:: verbose
1132
1132
1133 For efficiency, hardlinks are used for cloning whenever the
1133 For efficiency, hardlinks are used for cloning whenever the
1134 source and destination are on the same filesystem (note this
1134 source and destination are on the same filesystem (note this
1135 applies only to the repository data, not to the working
1135 applies only to the repository data, not to the working
1136 directory). Some filesystems, such as AFS, implement hardlinking
1136 directory). Some filesystems, such as AFS, implement hardlinking
1137 incorrectly, but do not report errors. In these cases, use the
1137 incorrectly, but do not report errors. In these cases, use the
1138 --pull option to avoid hardlinking.
1138 --pull option to avoid hardlinking.
1139
1139
1140 In some cases, you can clone repositories and the working
1140 In some cases, you can clone repositories and the working
1141 directory using full hardlinks with ::
1141 directory using full hardlinks with ::
1142
1142
1143 $ cp -al REPO REPOCLONE
1143 $ cp -al REPO REPOCLONE
1144
1144
1145 This is the fastest way to clone, but it is not always safe. The
1145 This is the fastest way to clone, but it is not always safe. The
1146 operation is not atomic (making sure REPO is not modified during
1146 operation is not atomic (making sure REPO is not modified during
1147 the operation is up to you) and you have to make sure your
1147 the operation is up to you) and you have to make sure your
1148 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1148 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1149 so). Also, this is not compatible with certain extensions that
1149 so). Also, this is not compatible with certain extensions that
1150 place their metadata under the .hg directory, such as mq.
1150 place their metadata under the .hg directory, such as mq.
1151
1151
1152 Mercurial will update the working directory to the first applicable
1152 Mercurial will update the working directory to the first applicable
1153 revision from this list:
1153 revision from this list:
1154
1154
1155 a) null if -U or the source repository has no changesets
1155 a) null if -U or the source repository has no changesets
1156 b) if -u . and the source repository is local, the first parent of
1156 b) if -u . and the source repository is local, the first parent of
1157 the source repository's working directory
1157 the source repository's working directory
1158 c) the changeset specified with -u (if a branch name, this means the
1158 c) the changeset specified with -u (if a branch name, this means the
1159 latest head of that branch)
1159 latest head of that branch)
1160 d) the changeset specified with -r
1160 d) the changeset specified with -r
1161 e) the tipmost head specified with -b
1161 e) the tipmost head specified with -b
1162 f) the tipmost head specified with the url#branch source syntax
1162 f) the tipmost head specified with the url#branch source syntax
1163 g) the tipmost head of the default branch
1163 g) the tipmost head of the default branch
1164 h) tip
1164 h) tip
1165
1165
1166 Examples:
1166 Examples:
1167
1167
1168 - clone a remote repository to a new directory named hg/::
1168 - clone a remote repository to a new directory named hg/::
1169
1169
1170 hg clone http://selenic.com/hg
1170 hg clone http://selenic.com/hg
1171
1171
1172 - create a lightweight local clone::
1172 - create a lightweight local clone::
1173
1173
1174 hg clone project/ project-feature/
1174 hg clone project/ project-feature/
1175
1175
1176 - clone from an absolute path on an ssh server (note double-slash)::
1176 - clone from an absolute path on an ssh server (note double-slash)::
1177
1177
1178 hg clone ssh://user@server//home/projects/alpha/
1178 hg clone ssh://user@server//home/projects/alpha/
1179
1179
1180 - do a high-speed clone over a LAN while checking out a
1180 - do a high-speed clone over a LAN while checking out a
1181 specified version::
1181 specified version::
1182
1182
1183 hg clone --uncompressed http://server/repo -u 1.5
1183 hg clone --uncompressed http://server/repo -u 1.5
1184
1184
1185 - create a repository without changesets after a particular revision::
1185 - create a repository without changesets after a particular revision::
1186
1186
1187 hg clone -r 04e544 experimental/ good/
1187 hg clone -r 04e544 experimental/ good/
1188
1188
1189 - clone (and track) a particular named branch::
1189 - clone (and track) a particular named branch::
1190
1190
1191 hg clone http://selenic.com/hg#stable
1191 hg clone http://selenic.com/hg#stable
1192
1192
1193 See :hg:`help urls` for details on specifying URLs.
1193 See :hg:`help urls` for details on specifying URLs.
1194
1194
1195 Returns 0 on success.
1195 Returns 0 on success.
1196 """
1196 """
1197 if opts.get('noupdate') and opts.get('updaterev'):
1197 if opts.get('noupdate') and opts.get('updaterev'):
1198 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1198 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1199
1199
1200 r = hg.clone(ui, opts, source, dest,
1200 r = hg.clone(ui, opts, source, dest,
1201 pull=opts.get('pull'),
1201 pull=opts.get('pull'),
1202 stream=opts.get('uncompressed'),
1202 stream=opts.get('uncompressed'),
1203 rev=opts.get('rev'),
1203 rev=opts.get('rev'),
1204 update=opts.get('updaterev') or not opts.get('noupdate'),
1204 update=opts.get('updaterev') or not opts.get('noupdate'),
1205 branch=opts.get('branch'))
1205 branch=opts.get('branch'))
1206
1206
1207 return r is None
1207 return r is None
1208
1208
1209 @command('^commit|ci',
1209 @command('^commit|ci',
1210 [('A', 'addremove', None,
1210 [('A', 'addremove', None,
1211 _('mark new/missing files as added/removed before committing')),
1211 _('mark new/missing files as added/removed before committing')),
1212 ('', 'close-branch', None,
1212 ('', 'close-branch', None,
1213 _('mark a branch as closed, hiding it from the branch list')),
1213 _('mark a branch as closed, hiding it from the branch list')),
1214 ('', 'amend', None, _('amend the parent of the working dir')),
1214 ('', 'amend', None, _('amend the parent of the working dir')),
1215 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1215 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1216 _('[OPTION]... [FILE]...'))
1216 _('[OPTION]... [FILE]...'))
1217 def commit(ui, repo, *pats, **opts):
1217 def commit(ui, repo, *pats, **opts):
1218 """commit the specified files or all outstanding changes
1218 """commit the specified files or all outstanding changes
1219
1219
1220 Commit changes to the given files into the repository. Unlike a
1220 Commit changes to the given files into the repository. Unlike a
1221 centralized SCM, this operation is a local operation. See
1221 centralized SCM, this operation is a local operation. See
1222 :hg:`push` for a way to actively distribute your changes.
1222 :hg:`push` for a way to actively distribute your changes.
1223
1223
1224 If a list of files is omitted, all changes reported by :hg:`status`
1224 If a list of files is omitted, all changes reported by :hg:`status`
1225 will be committed.
1225 will be committed.
1226
1226
1227 If you are committing the result of a merge, do not provide any
1227 If you are committing the result of a merge, do not provide any
1228 filenames or -I/-X filters.
1228 filenames or -I/-X filters.
1229
1229
1230 If no commit message is specified, Mercurial starts your
1230 If no commit message is specified, Mercurial starts your
1231 configured editor where you can enter a message. In case your
1231 configured editor where you can enter a message. In case your
1232 commit fails, you will find a backup of your message in
1232 commit fails, you will find a backup of your message in
1233 ``.hg/last-message.txt``.
1233 ``.hg/last-message.txt``.
1234
1234
1235 The --amend flag can be used to amend the parent of the
1235 The --amend flag can be used to amend the parent of the
1236 working directory with a new commit that contains the changes
1236 working directory with a new commit that contains the changes
1237 in the parent in addition to those currently reported by :hg:`status`,
1237 in the parent in addition to those currently reported by :hg:`status`,
1238 if there are any. The old commit is stored in a backup bundle in
1238 if there are any. The old commit is stored in a backup bundle in
1239 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1239 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1240 on how to restore it).
1240 on how to restore it).
1241
1241
1242 Message, user and date are taken from the amended commit unless
1242 Message, user and date are taken from the amended commit unless
1243 specified. When a message isn't specified on the command line,
1243 specified. When a message isn't specified on the command line,
1244 the editor will open with the message of the amended commit.
1244 the editor will open with the message of the amended commit.
1245
1245
1246 It is not possible to amend public changesets (see :hg:`help phases`)
1246 It is not possible to amend public changesets (see :hg:`help phases`)
1247 or changesets that have children.
1247 or changesets that have children.
1248
1248
1249 See :hg:`help dates` for a list of formats valid for -d/--date.
1249 See :hg:`help dates` for a list of formats valid for -d/--date.
1250
1250
1251 Returns 0 on success, 1 if nothing changed.
1251 Returns 0 on success, 1 if nothing changed.
1252 """
1252 """
1253 if opts.get('subrepos'):
1253 if opts.get('subrepos'):
1254 # Let --subrepos on the command line overide config setting.
1254 # Let --subrepos on the command line overide config setting.
1255 ui.setconfig('ui', 'commitsubrepos', True)
1255 ui.setconfig('ui', 'commitsubrepos', True)
1256
1256
1257 extra = {}
1257 extra = {}
1258 if opts.get('close_branch'):
1258 if opts.get('close_branch'):
1259 if repo['.'].node() not in repo.branchheads():
1259 if repo['.'].node() not in repo.branchheads():
1260 # The topo heads set is included in the branch heads set of the
1260 # The topo heads set is included in the branch heads set of the
1261 # current branch, so it's sufficient to test branchheads
1261 # current branch, so it's sufficient to test branchheads
1262 raise util.Abort(_('can only close branch heads'))
1262 raise util.Abort(_('can only close branch heads'))
1263 extra['close'] = 1
1263 extra['close'] = 1
1264
1264
1265 branch = repo[None].branch()
1265 branch = repo[None].branch()
1266 bheads = repo.branchheads(branch)
1266 bheads = repo.branchheads(branch)
1267
1267
1268 if opts.get('amend'):
1268 if opts.get('amend'):
1269 if ui.configbool('ui', 'commitsubrepos'):
1269 if ui.configbool('ui', 'commitsubrepos'):
1270 raise util.Abort(_('cannot amend recursively'))
1270 raise util.Abort(_('cannot amend recursively'))
1271
1271
1272 old = repo['.']
1272 old = repo['.']
1273 if old.phase() == phases.public:
1273 if old.phase() == phases.public:
1274 raise util.Abort(_('cannot amend public changesets'))
1274 raise util.Abort(_('cannot amend public changesets'))
1275 if len(old.parents()) > 1:
1275 if len(old.parents()) > 1:
1276 raise util.Abort(_('cannot amend merge changesets'))
1276 raise util.Abort(_('cannot amend merge changesets'))
1277 if len(repo[None].parents()) > 1:
1277 if len(repo[None].parents()) > 1:
1278 raise util.Abort(_('cannot amend while merging'))
1278 raise util.Abort(_('cannot amend while merging'))
1279 if old.children():
1279 if old.children():
1280 raise util.Abort(_('cannot amend changeset with children'))
1280 raise util.Abort(_('cannot amend changeset with children'))
1281
1281
1282 e = cmdutil.commiteditor
1282 e = cmdutil.commiteditor
1283 if opts.get('force_editor'):
1283 if opts.get('force_editor'):
1284 e = cmdutil.commitforceeditor
1284 e = cmdutil.commitforceeditor
1285
1285
1286 def commitfunc(ui, repo, message, match, opts):
1286 def commitfunc(ui, repo, message, match, opts):
1287 editor = e
1287 editor = e
1288 # message contains text from -m or -l, if it's empty,
1288 # message contains text from -m or -l, if it's empty,
1289 # open the editor with the old message
1289 # open the editor with the old message
1290 if not message:
1290 if not message:
1291 message = old.description()
1291 message = old.description()
1292 editor = cmdutil.commitforceeditor
1292 editor = cmdutil.commitforceeditor
1293 return repo.commit(message,
1293 return repo.commit(message,
1294 opts.get('user') or old.user(),
1294 opts.get('user') or old.user(),
1295 opts.get('date') or old.date(),
1295 opts.get('date') or old.date(),
1296 match,
1296 match,
1297 editor=editor,
1297 editor=editor,
1298 extra=extra)
1298 extra=extra)
1299
1299
1300 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1300 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1301 if node == old.node():
1301 if node == old.node():
1302 ui.status(_("nothing changed\n"))
1302 ui.status(_("nothing changed\n"))
1303 return 1
1303 return 1
1304 else:
1304 else:
1305 e = cmdutil.commiteditor
1305 e = cmdutil.commiteditor
1306 if opts.get('force_editor'):
1306 if opts.get('force_editor'):
1307 e = cmdutil.commitforceeditor
1307 e = cmdutil.commitforceeditor
1308
1308
1309 def commitfunc(ui, repo, message, match, opts):
1309 def commitfunc(ui, repo, message, match, opts):
1310 return repo.commit(message, opts.get('user'), opts.get('date'),
1310 return repo.commit(message, opts.get('user'), opts.get('date'),
1311 match, editor=e, extra=extra)
1311 match, editor=e, extra=extra)
1312
1312
1313 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1313 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1314
1314
1315 if not node:
1315 if not node:
1316 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1316 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1317 if stat[3]:
1317 if stat[3]:
1318 ui.status(_("nothing changed (%d missing files, see "
1318 ui.status(_("nothing changed (%d missing files, see "
1319 "'hg status')\n") % len(stat[3]))
1319 "'hg status')\n") % len(stat[3]))
1320 else:
1320 else:
1321 ui.status(_("nothing changed\n"))
1321 ui.status(_("nothing changed\n"))
1322 return 1
1322 return 1
1323
1323
1324 ctx = repo[node]
1324 ctx = repo[node]
1325 parents = ctx.parents()
1325 parents = ctx.parents()
1326
1326
1327 if (not opts.get('amend') and bheads and node not in bheads and not
1327 if (not opts.get('amend') and bheads and node not in bheads and not
1328 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1328 [x for x in parents if x.node() in bheads and x.branch() == branch]):
1329 ui.status(_('created new head\n'))
1329 ui.status(_('created new head\n'))
1330 # The message is not printed for initial roots. For the other
1330 # The message is not printed for initial roots. For the other
1331 # changesets, it is printed in the following situations:
1331 # changesets, it is printed in the following situations:
1332 #
1332 #
1333 # Par column: for the 2 parents with ...
1333 # Par column: for the 2 parents with ...
1334 # N: null or no parent
1334 # N: null or no parent
1335 # B: parent is on another named branch
1335 # B: parent is on another named branch
1336 # C: parent is a regular non head changeset
1336 # C: parent is a regular non head changeset
1337 # H: parent was a branch head of the current branch
1337 # H: parent was a branch head of the current branch
1338 # Msg column: whether we print "created new head" message
1338 # Msg column: whether we print "created new head" message
1339 # In the following, it is assumed that there already exists some
1339 # In the following, it is assumed that there already exists some
1340 # initial branch heads of the current branch, otherwise nothing is
1340 # initial branch heads of the current branch, otherwise nothing is
1341 # printed anyway.
1341 # printed anyway.
1342 #
1342 #
1343 # Par Msg Comment
1343 # Par Msg Comment
1344 # NN y additional topo root
1344 # NN y additional topo root
1345 #
1345 #
1346 # BN y additional branch root
1346 # BN y additional branch root
1347 # CN y additional topo head
1347 # CN y additional topo head
1348 # HN n usual case
1348 # HN n usual case
1349 #
1349 #
1350 # BB y weird additional branch root
1350 # BB y weird additional branch root
1351 # CB y branch merge
1351 # CB y branch merge
1352 # HB n merge with named branch
1352 # HB n merge with named branch
1353 #
1353 #
1354 # CC y additional head from merge
1354 # CC y additional head from merge
1355 # CH n merge with a head
1355 # CH n merge with a head
1356 #
1356 #
1357 # HH n head merge: head count decreases
1357 # HH n head merge: head count decreases
1358
1358
1359 if not opts.get('close_branch'):
1359 if not opts.get('close_branch'):
1360 for r in parents:
1360 for r in parents:
1361 if r.closesbranch() and r.branch() == branch:
1361 if r.closesbranch() and r.branch() == branch:
1362 ui.status(_('reopening closed branch head %d\n') % r)
1362 ui.status(_('reopening closed branch head %d\n') % r)
1363
1363
1364 if ui.debugflag:
1364 if ui.debugflag:
1365 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1365 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
1366 elif ui.verbose:
1366 elif ui.verbose:
1367 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1367 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
1368
1368
1369 @command('copy|cp',
1369 @command('copy|cp',
1370 [('A', 'after', None, _('record a copy that has already occurred')),
1370 [('A', 'after', None, _('record a copy that has already occurred')),
1371 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1371 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1372 ] + walkopts + dryrunopts,
1372 ] + walkopts + dryrunopts,
1373 _('[OPTION]... [SOURCE]... DEST'))
1373 _('[OPTION]... [SOURCE]... DEST'))
1374 def copy(ui, repo, *pats, **opts):
1374 def copy(ui, repo, *pats, **opts):
1375 """mark files as copied for the next commit
1375 """mark files as copied for the next commit
1376
1376
1377 Mark dest as having copies of source files. If dest is a
1377 Mark dest as having copies of source files. If dest is a
1378 directory, copies are put in that directory. If dest is a file,
1378 directory, copies are put in that directory. If dest is a file,
1379 the source must be a single file.
1379 the source must be a single file.
1380
1380
1381 By default, this command copies the contents of files as they
1381 By default, this command copies the contents of files as they
1382 exist in the working directory. If invoked with -A/--after, the
1382 exist in the working directory. If invoked with -A/--after, the
1383 operation is recorded, but no copying is performed.
1383 operation is recorded, but no copying is performed.
1384
1384
1385 This command takes effect with the next commit. To undo a copy
1385 This command takes effect with the next commit. To undo a copy
1386 before that, see :hg:`revert`.
1386 before that, see :hg:`revert`.
1387
1387
1388 Returns 0 on success, 1 if errors are encountered.
1388 Returns 0 on success, 1 if errors are encountered.
1389 """
1389 """
1390 wlock = repo.wlock(False)
1390 wlock = repo.wlock(False)
1391 try:
1391 try:
1392 return cmdutil.copy(ui, repo, pats, opts)
1392 return cmdutil.copy(ui, repo, pats, opts)
1393 finally:
1393 finally:
1394 wlock.release()
1394 wlock.release()
1395
1395
1396 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1396 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1397 def debugancestor(ui, repo, *args):
1397 def debugancestor(ui, repo, *args):
1398 """find the ancestor revision of two revisions in a given index"""
1398 """find the ancestor revision of two revisions in a given index"""
1399 if len(args) == 3:
1399 if len(args) == 3:
1400 index, rev1, rev2 = args
1400 index, rev1, rev2 = args
1401 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1401 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1402 lookup = r.lookup
1402 lookup = r.lookup
1403 elif len(args) == 2:
1403 elif len(args) == 2:
1404 if not repo:
1404 if not repo:
1405 raise util.Abort(_("there is no Mercurial repository here "
1405 raise util.Abort(_("there is no Mercurial repository here "
1406 "(.hg not found)"))
1406 "(.hg not found)"))
1407 rev1, rev2 = args
1407 rev1, rev2 = args
1408 r = repo.changelog
1408 r = repo.changelog
1409 lookup = repo.lookup
1409 lookup = repo.lookup
1410 else:
1410 else:
1411 raise util.Abort(_('either two or three arguments required'))
1411 raise util.Abort(_('either two or three arguments required'))
1412 a = r.ancestor(lookup(rev1), lookup(rev2))
1412 a = r.ancestor(lookup(rev1), lookup(rev2))
1413 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1413 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1414
1414
1415 @command('debugbuilddag',
1415 @command('debugbuilddag',
1416 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1416 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1417 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1417 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1418 ('n', 'new-file', None, _('add new file at each rev'))],
1418 ('n', 'new-file', None, _('add new file at each rev'))],
1419 _('[OPTION]... [TEXT]'))
1419 _('[OPTION]... [TEXT]'))
1420 def debugbuilddag(ui, repo, text=None,
1420 def debugbuilddag(ui, repo, text=None,
1421 mergeable_file=False,
1421 mergeable_file=False,
1422 overwritten_file=False,
1422 overwritten_file=False,
1423 new_file=False):
1423 new_file=False):
1424 """builds a repo with a given DAG from scratch in the current empty repo
1424 """builds a repo with a given DAG from scratch in the current empty repo
1425
1425
1426 The description of the DAG is read from stdin if not given on the
1426 The description of the DAG is read from stdin if not given on the
1427 command line.
1427 command line.
1428
1428
1429 Elements:
1429 Elements:
1430
1430
1431 - "+n" is a linear run of n nodes based on the current default parent
1431 - "+n" is a linear run of n nodes based on the current default parent
1432 - "." is a single node based on the current default parent
1432 - "." is a single node based on the current default parent
1433 - "$" resets the default parent to null (implied at the start);
1433 - "$" resets the default parent to null (implied at the start);
1434 otherwise the default parent is always the last node created
1434 otherwise the default parent is always the last node created
1435 - "<p" sets the default parent to the backref p
1435 - "<p" sets the default parent to the backref p
1436 - "*p" is a fork at parent p, which is a backref
1436 - "*p" is a fork at parent p, which is a backref
1437 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1437 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1438 - "/p2" is a merge of the preceding node and p2
1438 - "/p2" is a merge of the preceding node and p2
1439 - ":tag" defines a local tag for the preceding node
1439 - ":tag" defines a local tag for the preceding node
1440 - "@branch" sets the named branch for subsequent nodes
1440 - "@branch" sets the named branch for subsequent nodes
1441 - "#...\\n" is a comment up to the end of the line
1441 - "#...\\n" is a comment up to the end of the line
1442
1442
1443 Whitespace between the above elements is ignored.
1443 Whitespace between the above elements is ignored.
1444
1444
1445 A backref is either
1445 A backref is either
1446
1446
1447 - a number n, which references the node curr-n, where curr is the current
1447 - a number n, which references the node curr-n, where curr is the current
1448 node, or
1448 node, or
1449 - the name of a local tag you placed earlier using ":tag", or
1449 - the name of a local tag you placed earlier using ":tag", or
1450 - empty to denote the default parent.
1450 - empty to denote the default parent.
1451
1451
1452 All string valued-elements are either strictly alphanumeric, or must
1452 All string valued-elements are either strictly alphanumeric, or must
1453 be enclosed in double quotes ("..."), with "\\" as escape character.
1453 be enclosed in double quotes ("..."), with "\\" as escape character.
1454 """
1454 """
1455
1455
1456 if text is None:
1456 if text is None:
1457 ui.status(_("reading DAG from stdin\n"))
1457 ui.status(_("reading DAG from stdin\n"))
1458 text = ui.fin.read()
1458 text = ui.fin.read()
1459
1459
1460 cl = repo.changelog
1460 cl = repo.changelog
1461 if len(cl) > 0:
1461 if len(cl) > 0:
1462 raise util.Abort(_('repository is not empty'))
1462 raise util.Abort(_('repository is not empty'))
1463
1463
1464 # determine number of revs in DAG
1464 # determine number of revs in DAG
1465 total = 0
1465 total = 0
1466 for type, data in dagparser.parsedag(text):
1466 for type, data in dagparser.parsedag(text):
1467 if type == 'n':
1467 if type == 'n':
1468 total += 1
1468 total += 1
1469
1469
1470 if mergeable_file:
1470 if mergeable_file:
1471 linesperrev = 2
1471 linesperrev = 2
1472 # make a file with k lines per rev
1472 # make a file with k lines per rev
1473 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1473 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1474 initialmergedlines.append("")
1474 initialmergedlines.append("")
1475
1475
1476 tags = []
1476 tags = []
1477
1477
1478 lock = tr = None
1478 lock = tr = None
1479 try:
1479 try:
1480 lock = repo.lock()
1480 lock = repo.lock()
1481 tr = repo.transaction("builddag")
1481 tr = repo.transaction("builddag")
1482
1482
1483 at = -1
1483 at = -1
1484 atbranch = 'default'
1484 atbranch = 'default'
1485 nodeids = []
1485 nodeids = []
1486 id = 0
1486 id = 0
1487 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1487 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1488 for type, data in dagparser.parsedag(text):
1488 for type, data in dagparser.parsedag(text):
1489 if type == 'n':
1489 if type == 'n':
1490 ui.note('node %s\n' % str(data))
1490 ui.note('node %s\n' % str(data))
1491 id, ps = data
1491 id, ps = data
1492
1492
1493 files = []
1493 files = []
1494 fctxs = {}
1494 fctxs = {}
1495
1495
1496 p2 = None
1496 p2 = None
1497 if mergeable_file:
1497 if mergeable_file:
1498 fn = "mf"
1498 fn = "mf"
1499 p1 = repo[ps[0]]
1499 p1 = repo[ps[0]]
1500 if len(ps) > 1:
1500 if len(ps) > 1:
1501 p2 = repo[ps[1]]
1501 p2 = repo[ps[1]]
1502 pa = p1.ancestor(p2)
1502 pa = p1.ancestor(p2)
1503 base, local, other = [x[fn].data() for x in pa, p1, p2]
1503 base, local, other = [x[fn].data() for x in pa, p1, p2]
1504 m3 = simplemerge.Merge3Text(base, local, other)
1504 m3 = simplemerge.Merge3Text(base, local, other)
1505 ml = [l.strip() for l in m3.merge_lines()]
1505 ml = [l.strip() for l in m3.merge_lines()]
1506 ml.append("")
1506 ml.append("")
1507 elif at > 0:
1507 elif at > 0:
1508 ml = p1[fn].data().split("\n")
1508 ml = p1[fn].data().split("\n")
1509 else:
1509 else:
1510 ml = initialmergedlines
1510 ml = initialmergedlines
1511 ml[id * linesperrev] += " r%i" % id
1511 ml[id * linesperrev] += " r%i" % id
1512 mergedtext = "\n".join(ml)
1512 mergedtext = "\n".join(ml)
1513 files.append(fn)
1513 files.append(fn)
1514 fctxs[fn] = context.memfilectx(fn, mergedtext)
1514 fctxs[fn] = context.memfilectx(fn, mergedtext)
1515
1515
1516 if overwritten_file:
1516 if overwritten_file:
1517 fn = "of"
1517 fn = "of"
1518 files.append(fn)
1518 files.append(fn)
1519 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1519 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1520
1520
1521 if new_file:
1521 if new_file:
1522 fn = "nf%i" % id
1522 fn = "nf%i" % id
1523 files.append(fn)
1523 files.append(fn)
1524 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1524 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1525 if len(ps) > 1:
1525 if len(ps) > 1:
1526 if not p2:
1526 if not p2:
1527 p2 = repo[ps[1]]
1527 p2 = repo[ps[1]]
1528 for fn in p2:
1528 for fn in p2:
1529 if fn.startswith("nf"):
1529 if fn.startswith("nf"):
1530 files.append(fn)
1530 files.append(fn)
1531 fctxs[fn] = p2[fn]
1531 fctxs[fn] = p2[fn]
1532
1532
1533 def fctxfn(repo, cx, path):
1533 def fctxfn(repo, cx, path):
1534 return fctxs.get(path)
1534 return fctxs.get(path)
1535
1535
1536 if len(ps) == 0 or ps[0] < 0:
1536 if len(ps) == 0 or ps[0] < 0:
1537 pars = [None, None]
1537 pars = [None, None]
1538 elif len(ps) == 1:
1538 elif len(ps) == 1:
1539 pars = [nodeids[ps[0]], None]
1539 pars = [nodeids[ps[0]], None]
1540 else:
1540 else:
1541 pars = [nodeids[p] for p in ps]
1541 pars = [nodeids[p] for p in ps]
1542 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1542 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1543 date=(id, 0),
1543 date=(id, 0),
1544 user="debugbuilddag",
1544 user="debugbuilddag",
1545 extra={'branch': atbranch})
1545 extra={'branch': atbranch})
1546 nodeid = repo.commitctx(cx)
1546 nodeid = repo.commitctx(cx)
1547 nodeids.append(nodeid)
1547 nodeids.append(nodeid)
1548 at = id
1548 at = id
1549 elif type == 'l':
1549 elif type == 'l':
1550 id, name = data
1550 id, name = data
1551 ui.note('tag %s\n' % name)
1551 ui.note('tag %s\n' % name)
1552 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1552 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1553 elif type == 'a':
1553 elif type == 'a':
1554 ui.note('branch %s\n' % data)
1554 ui.note('branch %s\n' % data)
1555 atbranch = data
1555 atbranch = data
1556 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1556 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1557 tr.close()
1557 tr.close()
1558
1558
1559 if tags:
1559 if tags:
1560 repo.opener.write("localtags", "".join(tags))
1560 repo.opener.write("localtags", "".join(tags))
1561 finally:
1561 finally:
1562 ui.progress(_('building'), None)
1562 ui.progress(_('building'), None)
1563 release(tr, lock)
1563 release(tr, lock)
1564
1564
1565 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1565 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1566 def debugbundle(ui, bundlepath, all=None, **opts):
1566 def debugbundle(ui, bundlepath, all=None, **opts):
1567 """lists the contents of a bundle"""
1567 """lists the contents of a bundle"""
1568 f = url.open(ui, bundlepath)
1568 f = url.open(ui, bundlepath)
1569 try:
1569 try:
1570 gen = changegroup.readbundle(f, bundlepath)
1570 gen = changegroup.readbundle(f, bundlepath)
1571 if all:
1571 if all:
1572 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1572 ui.write("format: id, p1, p2, cset, delta base, len(delta)\n")
1573
1573
1574 def showchunks(named):
1574 def showchunks(named):
1575 ui.write("\n%s\n" % named)
1575 ui.write("\n%s\n" % named)
1576 chain = None
1576 chain = None
1577 while True:
1577 while True:
1578 chunkdata = gen.deltachunk(chain)
1578 chunkdata = gen.deltachunk(chain)
1579 if not chunkdata:
1579 if not chunkdata:
1580 break
1580 break
1581 node = chunkdata['node']
1581 node = chunkdata['node']
1582 p1 = chunkdata['p1']
1582 p1 = chunkdata['p1']
1583 p2 = chunkdata['p2']
1583 p2 = chunkdata['p2']
1584 cs = chunkdata['cs']
1584 cs = chunkdata['cs']
1585 deltabase = chunkdata['deltabase']
1585 deltabase = chunkdata['deltabase']
1586 delta = chunkdata['delta']
1586 delta = chunkdata['delta']
1587 ui.write("%s %s %s %s %s %s\n" %
1587 ui.write("%s %s %s %s %s %s\n" %
1588 (hex(node), hex(p1), hex(p2),
1588 (hex(node), hex(p1), hex(p2),
1589 hex(cs), hex(deltabase), len(delta)))
1589 hex(cs), hex(deltabase), len(delta)))
1590 chain = node
1590 chain = node
1591
1591
1592 chunkdata = gen.changelogheader()
1592 chunkdata = gen.changelogheader()
1593 showchunks("changelog")
1593 showchunks("changelog")
1594 chunkdata = gen.manifestheader()
1594 chunkdata = gen.manifestheader()
1595 showchunks("manifest")
1595 showchunks("manifest")
1596 while True:
1596 while True:
1597 chunkdata = gen.filelogheader()
1597 chunkdata = gen.filelogheader()
1598 if not chunkdata:
1598 if not chunkdata:
1599 break
1599 break
1600 fname = chunkdata['filename']
1600 fname = chunkdata['filename']
1601 showchunks(fname)
1601 showchunks(fname)
1602 else:
1602 else:
1603 chunkdata = gen.changelogheader()
1603 chunkdata = gen.changelogheader()
1604 chain = None
1604 chain = None
1605 while True:
1605 while True:
1606 chunkdata = gen.deltachunk(chain)
1606 chunkdata = gen.deltachunk(chain)
1607 if not chunkdata:
1607 if not chunkdata:
1608 break
1608 break
1609 node = chunkdata['node']
1609 node = chunkdata['node']
1610 ui.write("%s\n" % hex(node))
1610 ui.write("%s\n" % hex(node))
1611 chain = node
1611 chain = node
1612 finally:
1612 finally:
1613 f.close()
1613 f.close()
1614
1614
1615 @command('debugcheckstate', [], '')
1615 @command('debugcheckstate', [], '')
1616 def debugcheckstate(ui, repo):
1616 def debugcheckstate(ui, repo):
1617 """validate the correctness of the current dirstate"""
1617 """validate the correctness of the current dirstate"""
1618 parent1, parent2 = repo.dirstate.parents()
1618 parent1, parent2 = repo.dirstate.parents()
1619 m1 = repo[parent1].manifest()
1619 m1 = repo[parent1].manifest()
1620 m2 = repo[parent2].manifest()
1620 m2 = repo[parent2].manifest()
1621 errors = 0
1621 errors = 0
1622 for f in repo.dirstate:
1622 for f in repo.dirstate:
1623 state = repo.dirstate[f]
1623 state = repo.dirstate[f]
1624 if state in "nr" and f not in m1:
1624 if state in "nr" and f not in m1:
1625 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1625 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1626 errors += 1
1626 errors += 1
1627 if state in "a" and f in m1:
1627 if state in "a" and f in m1:
1628 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1628 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1629 errors += 1
1629 errors += 1
1630 if state in "m" and f not in m1 and f not in m2:
1630 if state in "m" and f not in m1 and f not in m2:
1631 ui.warn(_("%s in state %s, but not in either manifest\n") %
1631 ui.warn(_("%s in state %s, but not in either manifest\n") %
1632 (f, state))
1632 (f, state))
1633 errors += 1
1633 errors += 1
1634 for f in m1:
1634 for f in m1:
1635 state = repo.dirstate[f]
1635 state = repo.dirstate[f]
1636 if state not in "nrm":
1636 if state not in "nrm":
1637 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1637 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1638 errors += 1
1638 errors += 1
1639 if errors:
1639 if errors:
1640 error = _(".hg/dirstate inconsistent with current parent's manifest")
1640 error = _(".hg/dirstate inconsistent with current parent's manifest")
1641 raise util.Abort(error)
1641 raise util.Abort(error)
1642
1642
1643 @command('debugcommands', [], _('[COMMAND]'))
1643 @command('debugcommands', [], _('[COMMAND]'))
1644 def debugcommands(ui, cmd='', *args):
1644 def debugcommands(ui, cmd='', *args):
1645 """list all available commands and options"""
1645 """list all available commands and options"""
1646 for cmd, vals in sorted(table.iteritems()):
1646 for cmd, vals in sorted(table.iteritems()):
1647 cmd = cmd.split('|')[0].strip('^')
1647 cmd = cmd.split('|')[0].strip('^')
1648 opts = ', '.join([i[1] for i in vals[1]])
1648 opts = ', '.join([i[1] for i in vals[1]])
1649 ui.write('%s: %s\n' % (cmd, opts))
1649 ui.write('%s: %s\n' % (cmd, opts))
1650
1650
1651 @command('debugcomplete',
1651 @command('debugcomplete',
1652 [('o', 'options', None, _('show the command options'))],
1652 [('o', 'options', None, _('show the command options'))],
1653 _('[-o] CMD'))
1653 _('[-o] CMD'))
1654 def debugcomplete(ui, cmd='', **opts):
1654 def debugcomplete(ui, cmd='', **opts):
1655 """returns the completion list associated with the given command"""
1655 """returns the completion list associated with the given command"""
1656
1656
1657 if opts.get('options'):
1657 if opts.get('options'):
1658 options = []
1658 options = []
1659 otables = [globalopts]
1659 otables = [globalopts]
1660 if cmd:
1660 if cmd:
1661 aliases, entry = cmdutil.findcmd(cmd, table, False)
1661 aliases, entry = cmdutil.findcmd(cmd, table, False)
1662 otables.append(entry[1])
1662 otables.append(entry[1])
1663 for t in otables:
1663 for t in otables:
1664 for o in t:
1664 for o in t:
1665 if "(DEPRECATED)" in o[3]:
1665 if "(DEPRECATED)" in o[3]:
1666 continue
1666 continue
1667 if o[0]:
1667 if o[0]:
1668 options.append('-%s' % o[0])
1668 options.append('-%s' % o[0])
1669 options.append('--%s' % o[1])
1669 options.append('--%s' % o[1])
1670 ui.write("%s\n" % "\n".join(options))
1670 ui.write("%s\n" % "\n".join(options))
1671 return
1671 return
1672
1672
1673 cmdlist = cmdutil.findpossible(cmd, table)
1673 cmdlist = cmdutil.findpossible(cmd, table)
1674 if ui.verbose:
1674 if ui.verbose:
1675 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1675 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1676 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1676 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1677
1677
1678 @command('debugdag',
1678 @command('debugdag',
1679 [('t', 'tags', None, _('use tags as labels')),
1679 [('t', 'tags', None, _('use tags as labels')),
1680 ('b', 'branches', None, _('annotate with branch names')),
1680 ('b', 'branches', None, _('annotate with branch names')),
1681 ('', 'dots', None, _('use dots for runs')),
1681 ('', 'dots', None, _('use dots for runs')),
1682 ('s', 'spaces', None, _('separate elements by spaces'))],
1682 ('s', 'spaces', None, _('separate elements by spaces'))],
1683 _('[OPTION]... [FILE [REV]...]'))
1683 _('[OPTION]... [FILE [REV]...]'))
1684 def debugdag(ui, repo, file_=None, *revs, **opts):
1684 def debugdag(ui, repo, file_=None, *revs, **opts):
1685 """format the changelog or an index DAG as a concise textual description
1685 """format the changelog or an index DAG as a concise textual description
1686
1686
1687 If you pass a revlog index, the revlog's DAG is emitted. If you list
1687 If you pass a revlog index, the revlog's DAG is emitted. If you list
1688 revision numbers, they get labelled in the output as rN.
1688 revision numbers, they get labelled in the output as rN.
1689
1689
1690 Otherwise, the changelog DAG of the current repo is emitted.
1690 Otherwise, the changelog DAG of the current repo is emitted.
1691 """
1691 """
1692 spaces = opts.get('spaces')
1692 spaces = opts.get('spaces')
1693 dots = opts.get('dots')
1693 dots = opts.get('dots')
1694 if file_:
1694 if file_:
1695 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1695 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1696 revs = set((int(r) for r in revs))
1696 revs = set((int(r) for r in revs))
1697 def events():
1697 def events():
1698 for r in rlog:
1698 for r in rlog:
1699 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1699 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1700 if p != -1)))
1700 if p != -1)))
1701 if r in revs:
1701 if r in revs:
1702 yield 'l', (r, "r%i" % r)
1702 yield 'l', (r, "r%i" % r)
1703 elif repo:
1703 elif repo:
1704 cl = repo.changelog
1704 cl = repo.changelog
1705 tags = opts.get('tags')
1705 tags = opts.get('tags')
1706 branches = opts.get('branches')
1706 branches = opts.get('branches')
1707 if tags:
1707 if tags:
1708 labels = {}
1708 labels = {}
1709 for l, n in repo.tags().items():
1709 for l, n in repo.tags().items():
1710 labels.setdefault(cl.rev(n), []).append(l)
1710 labels.setdefault(cl.rev(n), []).append(l)
1711 def events():
1711 def events():
1712 b = "default"
1712 b = "default"
1713 for r in cl:
1713 for r in cl:
1714 if branches:
1714 if branches:
1715 newb = cl.read(cl.node(r))[5]['branch']
1715 newb = cl.read(cl.node(r))[5]['branch']
1716 if newb != b:
1716 if newb != b:
1717 yield 'a', newb
1717 yield 'a', newb
1718 b = newb
1718 b = newb
1719 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1719 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1720 if p != -1)))
1720 if p != -1)))
1721 if tags:
1721 if tags:
1722 ls = labels.get(r)
1722 ls = labels.get(r)
1723 if ls:
1723 if ls:
1724 for l in ls:
1724 for l in ls:
1725 yield 'l', (r, l)
1725 yield 'l', (r, l)
1726 else:
1726 else:
1727 raise util.Abort(_('need repo for changelog dag'))
1727 raise util.Abort(_('need repo for changelog dag'))
1728
1728
1729 for line in dagparser.dagtextlines(events(),
1729 for line in dagparser.dagtextlines(events(),
1730 addspaces=spaces,
1730 addspaces=spaces,
1731 wraplabels=True,
1731 wraplabels=True,
1732 wrapannotations=True,
1732 wrapannotations=True,
1733 wrapnonlinear=dots,
1733 wrapnonlinear=dots,
1734 usedots=dots,
1734 usedots=dots,
1735 maxlinewidth=70):
1735 maxlinewidth=70):
1736 ui.write(line)
1736 ui.write(line)
1737 ui.write("\n")
1737 ui.write("\n")
1738
1738
1739 @command('debugdata',
1739 @command('debugdata',
1740 [('c', 'changelog', False, _('open changelog')),
1740 [('c', 'changelog', False, _('open changelog')),
1741 ('m', 'manifest', False, _('open manifest'))],
1741 ('m', 'manifest', False, _('open manifest'))],
1742 _('-c|-m|FILE REV'))
1742 _('-c|-m|FILE REV'))
1743 def debugdata(ui, repo, file_, rev = None, **opts):
1743 def debugdata(ui, repo, file_, rev = None, **opts):
1744 """dump the contents of a data file revision"""
1744 """dump the contents of a data file revision"""
1745 if opts.get('changelog') or opts.get('manifest'):
1745 if opts.get('changelog') or opts.get('manifest'):
1746 file_, rev = None, file_
1746 file_, rev = None, file_
1747 elif rev is None:
1747 elif rev is None:
1748 raise error.CommandError('debugdata', _('invalid arguments'))
1748 raise error.CommandError('debugdata', _('invalid arguments'))
1749 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1749 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1750 try:
1750 try:
1751 ui.write(r.revision(r.lookup(rev)))
1751 ui.write(r.revision(r.lookup(rev)))
1752 except KeyError:
1752 except KeyError:
1753 raise util.Abort(_('invalid revision identifier %s') % rev)
1753 raise util.Abort(_('invalid revision identifier %s') % rev)
1754
1754
1755 @command('debugdate',
1755 @command('debugdate',
1756 [('e', 'extended', None, _('try extended date formats'))],
1756 [('e', 'extended', None, _('try extended date formats'))],
1757 _('[-e] DATE [RANGE]'))
1757 _('[-e] DATE [RANGE]'))
1758 def debugdate(ui, date, range=None, **opts):
1758 def debugdate(ui, date, range=None, **opts):
1759 """parse and display a date"""
1759 """parse and display a date"""
1760 if opts["extended"]:
1760 if opts["extended"]:
1761 d = util.parsedate(date, util.extendeddateformats)
1761 d = util.parsedate(date, util.extendeddateformats)
1762 else:
1762 else:
1763 d = util.parsedate(date)
1763 d = util.parsedate(date)
1764 ui.write("internal: %s %s\n" % d)
1764 ui.write("internal: %s %s\n" % d)
1765 ui.write("standard: %s\n" % util.datestr(d))
1765 ui.write("standard: %s\n" % util.datestr(d))
1766 if range:
1766 if range:
1767 m = util.matchdate(range)
1767 m = util.matchdate(range)
1768 ui.write("match: %s\n" % m(d[0]))
1768 ui.write("match: %s\n" % m(d[0]))
1769
1769
1770 @command('debugdiscovery',
1770 @command('debugdiscovery',
1771 [('', 'old', None, _('use old-style discovery')),
1771 [('', 'old', None, _('use old-style discovery')),
1772 ('', 'nonheads', None,
1772 ('', 'nonheads', None,
1773 _('use old-style discovery with non-heads included')),
1773 _('use old-style discovery with non-heads included')),
1774 ] + remoteopts,
1774 ] + remoteopts,
1775 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1775 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1776 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1776 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1777 """runs the changeset discovery protocol in isolation"""
1777 """runs the changeset discovery protocol in isolation"""
1778 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1778 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1779 opts.get('branch'))
1779 opts.get('branch'))
1780 remote = hg.peer(repo, opts, remoteurl)
1780 remote = hg.peer(repo, opts, remoteurl)
1781 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1781 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1782
1782
1783 # make sure tests are repeatable
1783 # make sure tests are repeatable
1784 random.seed(12323)
1784 random.seed(12323)
1785
1785
1786 def doit(localheads, remoteheads):
1786 def doit(localheads, remoteheads):
1787 if opts.get('old'):
1787 if opts.get('old'):
1788 if localheads:
1788 if localheads:
1789 raise util.Abort('cannot use localheads with old style '
1789 raise util.Abort('cannot use localheads with old style '
1790 'discovery')
1790 'discovery')
1791 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1791 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1792 force=True)
1792 force=True)
1793 common = set(common)
1793 common = set(common)
1794 if not opts.get('nonheads'):
1794 if not opts.get('nonheads'):
1795 ui.write("unpruned common: %s\n" % " ".join([short(n)
1795 ui.write("unpruned common: %s\n" % " ".join([short(n)
1796 for n in common]))
1796 for n in common]))
1797 dag = dagutil.revlogdag(repo.changelog)
1797 dag = dagutil.revlogdag(repo.changelog)
1798 all = dag.ancestorset(dag.internalizeall(common))
1798 all = dag.ancestorset(dag.internalizeall(common))
1799 common = dag.externalizeall(dag.headsetofconnecteds(all))
1799 common = dag.externalizeall(dag.headsetofconnecteds(all))
1800 else:
1800 else:
1801 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1801 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1802 common = set(common)
1802 common = set(common)
1803 rheads = set(hds)
1803 rheads = set(hds)
1804 lheads = set(repo.heads())
1804 lheads = set(repo.heads())
1805 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1805 ui.write("common heads: %s\n" % " ".join([short(n) for n in common]))
1806 if lheads <= common:
1806 if lheads <= common:
1807 ui.write("local is subset\n")
1807 ui.write("local is subset\n")
1808 elif rheads <= common:
1808 elif rheads <= common:
1809 ui.write("remote is subset\n")
1809 ui.write("remote is subset\n")
1810
1810
1811 serverlogs = opts.get('serverlog')
1811 serverlogs = opts.get('serverlog')
1812 if serverlogs:
1812 if serverlogs:
1813 for filename in serverlogs:
1813 for filename in serverlogs:
1814 logfile = open(filename, 'r')
1814 logfile = open(filename, 'r')
1815 try:
1815 try:
1816 line = logfile.readline()
1816 line = logfile.readline()
1817 while line:
1817 while line:
1818 parts = line.strip().split(';')
1818 parts = line.strip().split(';')
1819 op = parts[1]
1819 op = parts[1]
1820 if op == 'cg':
1820 if op == 'cg':
1821 pass
1821 pass
1822 elif op == 'cgss':
1822 elif op == 'cgss':
1823 doit(parts[2].split(' '), parts[3].split(' '))
1823 doit(parts[2].split(' '), parts[3].split(' '))
1824 elif op == 'unb':
1824 elif op == 'unb':
1825 doit(parts[3].split(' '), parts[2].split(' '))
1825 doit(parts[3].split(' '), parts[2].split(' '))
1826 line = logfile.readline()
1826 line = logfile.readline()
1827 finally:
1827 finally:
1828 logfile.close()
1828 logfile.close()
1829
1829
1830 else:
1830 else:
1831 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1831 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1832 opts.get('remote_head'))
1832 opts.get('remote_head'))
1833 localrevs = opts.get('local_head')
1833 localrevs = opts.get('local_head')
1834 doit(localrevs, remoterevs)
1834 doit(localrevs, remoterevs)
1835
1835
1836 @command('debugfileset', [], ('REVSPEC'))
1836 @command('debugfileset', [], ('REVSPEC'))
1837 def debugfileset(ui, repo, expr):
1837 def debugfileset(ui, repo, expr):
1838 '''parse and apply a fileset specification'''
1838 '''parse and apply a fileset specification'''
1839 if ui.verbose:
1839 if ui.verbose:
1840 tree = fileset.parse(expr)[0]
1840 tree = fileset.parse(expr)[0]
1841 ui.note(tree, "\n")
1841 ui.note(tree, "\n")
1842
1842
1843 for f in fileset.getfileset(repo[None], expr):
1843 for f in fileset.getfileset(repo[None], expr):
1844 ui.write("%s\n" % f)
1844 ui.write("%s\n" % f)
1845
1845
1846 @command('debugfsinfo', [], _('[PATH]'))
1846 @command('debugfsinfo', [], _('[PATH]'))
1847 def debugfsinfo(ui, path = "."):
1847 def debugfsinfo(ui, path = "."):
1848 """show information detected about current filesystem"""
1848 """show information detected about current filesystem"""
1849 util.writefile('.debugfsinfo', '')
1849 util.writefile('.debugfsinfo', '')
1850 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1850 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1851 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1851 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1852 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1852 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1853 and 'yes' or 'no'))
1853 and 'yes' or 'no'))
1854 os.unlink('.debugfsinfo')
1854 os.unlink('.debugfsinfo')
1855
1855
1856 @command('debuggetbundle',
1856 @command('debuggetbundle',
1857 [('H', 'head', [], _('id of head node'), _('ID')),
1857 [('H', 'head', [], _('id of head node'), _('ID')),
1858 ('C', 'common', [], _('id of common node'), _('ID')),
1858 ('C', 'common', [], _('id of common node'), _('ID')),
1859 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1859 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1860 _('REPO FILE [-H|-C ID]...'))
1860 _('REPO FILE [-H|-C ID]...'))
1861 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1861 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1862 """retrieves a bundle from a repo
1862 """retrieves a bundle from a repo
1863
1863
1864 Every ID must be a full-length hex node id string. Saves the bundle to the
1864 Every ID must be a full-length hex node id string. Saves the bundle to the
1865 given file.
1865 given file.
1866 """
1866 """
1867 repo = hg.peer(ui, opts, repopath)
1867 repo = hg.peer(ui, opts, repopath)
1868 if not repo.capable('getbundle'):
1868 if not repo.capable('getbundle'):
1869 raise util.Abort("getbundle() not supported by target repository")
1869 raise util.Abort("getbundle() not supported by target repository")
1870 args = {}
1870 args = {}
1871 if common:
1871 if common:
1872 args['common'] = [bin(s) for s in common]
1872 args['common'] = [bin(s) for s in common]
1873 if head:
1873 if head:
1874 args['heads'] = [bin(s) for s in head]
1874 args['heads'] = [bin(s) for s in head]
1875 bundle = repo.getbundle('debug', **args)
1875 bundle = repo.getbundle('debug', **args)
1876
1876
1877 bundletype = opts.get('type', 'bzip2').lower()
1877 bundletype = opts.get('type', 'bzip2').lower()
1878 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1878 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1879 bundletype = btypes.get(bundletype)
1879 bundletype = btypes.get(bundletype)
1880 if bundletype not in changegroup.bundletypes:
1880 if bundletype not in changegroup.bundletypes:
1881 raise util.Abort(_('unknown bundle type specified with --type'))
1881 raise util.Abort(_('unknown bundle type specified with --type'))
1882 changegroup.writebundle(bundle, bundlepath, bundletype)
1882 changegroup.writebundle(bundle, bundlepath, bundletype)
1883
1883
1884 @command('debugignore', [], '')
1884 @command('debugignore', [], '')
1885 def debugignore(ui, repo, *values, **opts):
1885 def debugignore(ui, repo, *values, **opts):
1886 """display the combined ignore pattern"""
1886 """display the combined ignore pattern"""
1887 ignore = repo.dirstate._ignore
1887 ignore = repo.dirstate._ignore
1888 includepat = getattr(ignore, 'includepat', None)
1888 includepat = getattr(ignore, 'includepat', None)
1889 if includepat is not None:
1889 if includepat is not None:
1890 ui.write("%s\n" % includepat)
1890 ui.write("%s\n" % includepat)
1891 else:
1891 else:
1892 raise util.Abort(_("no ignore patterns found"))
1892 raise util.Abort(_("no ignore patterns found"))
1893
1893
1894 @command('debugindex',
1894 @command('debugindex',
1895 [('c', 'changelog', False, _('open changelog')),
1895 [('c', 'changelog', False, _('open changelog')),
1896 ('m', 'manifest', False, _('open manifest')),
1896 ('m', 'manifest', False, _('open manifest')),
1897 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1897 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1898 _('[-f FORMAT] -c|-m|FILE'))
1898 _('[-f FORMAT] -c|-m|FILE'))
1899 def debugindex(ui, repo, file_ = None, **opts):
1899 def debugindex(ui, repo, file_ = None, **opts):
1900 """dump the contents of an index file"""
1900 """dump the contents of an index file"""
1901 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1901 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1902 format = opts.get('format', 0)
1902 format = opts.get('format', 0)
1903 if format not in (0, 1):
1903 if format not in (0, 1):
1904 raise util.Abort(_("unknown format %d") % format)
1904 raise util.Abort(_("unknown format %d") % format)
1905
1905
1906 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1906 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1907 if generaldelta:
1907 if generaldelta:
1908 basehdr = ' delta'
1908 basehdr = ' delta'
1909 else:
1909 else:
1910 basehdr = ' base'
1910 basehdr = ' base'
1911
1911
1912 if format == 0:
1912 if format == 0:
1913 ui.write(" rev offset length " + basehdr + " linkrev"
1913 ui.write(" rev offset length " + basehdr + " linkrev"
1914 " nodeid p1 p2\n")
1914 " nodeid p1 p2\n")
1915 elif format == 1:
1915 elif format == 1:
1916 ui.write(" rev flag offset length"
1916 ui.write(" rev flag offset length"
1917 " size " + basehdr + " link p1 p2"
1917 " size " + basehdr + " link p1 p2"
1918 " nodeid\n")
1918 " nodeid\n")
1919
1919
1920 for i in r:
1920 for i in r:
1921 node = r.node(i)
1921 node = r.node(i)
1922 if generaldelta:
1922 if generaldelta:
1923 base = r.deltaparent(i)
1923 base = r.deltaparent(i)
1924 else:
1924 else:
1925 base = r.chainbase(i)
1925 base = r.chainbase(i)
1926 if format == 0:
1926 if format == 0:
1927 try:
1927 try:
1928 pp = r.parents(node)
1928 pp = r.parents(node)
1929 except Exception:
1929 except Exception:
1930 pp = [nullid, nullid]
1930 pp = [nullid, nullid]
1931 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1931 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1932 i, r.start(i), r.length(i), base, r.linkrev(i),
1932 i, r.start(i), r.length(i), base, r.linkrev(i),
1933 short(node), short(pp[0]), short(pp[1])))
1933 short(node), short(pp[0]), short(pp[1])))
1934 elif format == 1:
1934 elif format == 1:
1935 pr = r.parentrevs(i)
1935 pr = r.parentrevs(i)
1936 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1936 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1937 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1937 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1938 base, r.linkrev(i), pr[0], pr[1], short(node)))
1938 base, r.linkrev(i), pr[0], pr[1], short(node)))
1939
1939
1940 @command('debugindexdot', [], _('FILE'))
1940 @command('debugindexdot', [], _('FILE'))
1941 def debugindexdot(ui, repo, file_):
1941 def debugindexdot(ui, repo, file_):
1942 """dump an index DAG as a graphviz dot file"""
1942 """dump an index DAG as a graphviz dot file"""
1943 r = None
1943 r = None
1944 if repo:
1944 if repo:
1945 filelog = repo.file(file_)
1945 filelog = repo.file(file_)
1946 if len(filelog):
1946 if len(filelog):
1947 r = filelog
1947 r = filelog
1948 if not r:
1948 if not r:
1949 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1949 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1950 ui.write("digraph G {\n")
1950 ui.write("digraph G {\n")
1951 for i in r:
1951 for i in r:
1952 node = r.node(i)
1952 node = r.node(i)
1953 pp = r.parents(node)
1953 pp = r.parents(node)
1954 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1954 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1955 if pp[1] != nullid:
1955 if pp[1] != nullid:
1956 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1956 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1957 ui.write("}\n")
1957 ui.write("}\n")
1958
1958
1959 @command('debuginstall', [], '')
1959 @command('debuginstall', [], '')
1960 def debuginstall(ui):
1960 def debuginstall(ui):
1961 '''test Mercurial installation
1961 '''test Mercurial installation
1962
1962
1963 Returns 0 on success.
1963 Returns 0 on success.
1964 '''
1964 '''
1965
1965
1966 def writetemp(contents):
1966 def writetemp(contents):
1967 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1967 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1968 f = os.fdopen(fd, "wb")
1968 f = os.fdopen(fd, "wb")
1969 f.write(contents)
1969 f.write(contents)
1970 f.close()
1970 f.close()
1971 return name
1971 return name
1972
1972
1973 problems = 0
1973 problems = 0
1974
1974
1975 # encoding
1975 # encoding
1976 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1976 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
1977 try:
1977 try:
1978 encoding.fromlocal("test")
1978 encoding.fromlocal("test")
1979 except util.Abort, inst:
1979 except util.Abort, inst:
1980 ui.write(" %s\n" % inst)
1980 ui.write(" %s\n" % inst)
1981 ui.write(_(" (check that your locale is properly set)\n"))
1981 ui.write(_(" (check that your locale is properly set)\n"))
1982 problems += 1
1982 problems += 1
1983
1983
1984 # compiled modules
1984 # compiled modules
1985 ui.status(_("checking installed modules (%s)...\n")
1985 ui.status(_("checking installed modules (%s)...\n")
1986 % os.path.dirname(__file__))
1986 % os.path.dirname(__file__))
1987 try:
1987 try:
1988 import bdiff, mpatch, base85, osutil
1988 import bdiff, mpatch, base85, osutil
1989 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1989 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
1990 except Exception, inst:
1990 except Exception, inst:
1991 ui.write(" %s\n" % inst)
1991 ui.write(" %s\n" % inst)
1992 ui.write(_(" One or more extensions could not be found"))
1992 ui.write(_(" One or more extensions could not be found"))
1993 ui.write(_(" (check that you compiled the extensions)\n"))
1993 ui.write(_(" (check that you compiled the extensions)\n"))
1994 problems += 1
1994 problems += 1
1995
1995
1996 # templates
1996 # templates
1997 import templater
1997 import templater
1998 p = templater.templatepath()
1998 p = templater.templatepath()
1999 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
1999 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2000 try:
2000 try:
2001 templater.templater(templater.templatepath("map-cmdline.default"))
2001 templater.templater(templater.templatepath("map-cmdline.default"))
2002 except Exception, inst:
2002 except Exception, inst:
2003 ui.write(" %s\n" % inst)
2003 ui.write(" %s\n" % inst)
2004 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2004 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2005 problems += 1
2005 problems += 1
2006
2006
2007 # editor
2007 # editor
2008 ui.status(_("checking commit editor...\n"))
2008 ui.status(_("checking commit editor...\n"))
2009 editor = ui.geteditor()
2009 editor = ui.geteditor()
2010 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2010 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2011 if not cmdpath:
2011 if not cmdpath:
2012 if editor == 'vi':
2012 if editor == 'vi':
2013 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2013 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2014 ui.write(_(" (specify a commit editor in your configuration"
2014 ui.write(_(" (specify a commit editor in your configuration"
2015 " file)\n"))
2015 " file)\n"))
2016 else:
2016 else:
2017 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2017 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2018 ui.write(_(" (specify a commit editor in your configuration"
2018 ui.write(_(" (specify a commit editor in your configuration"
2019 " file)\n"))
2019 " file)\n"))
2020 problems += 1
2020 problems += 1
2021
2021
2022 # check username
2022 # check username
2023 ui.status(_("checking username...\n"))
2023 ui.status(_("checking username...\n"))
2024 try:
2024 try:
2025 ui.username()
2025 ui.username()
2026 except util.Abort, e:
2026 except util.Abort, e:
2027 ui.write(" %s\n" % e)
2027 ui.write(" %s\n" % e)
2028 ui.write(_(" (specify a username in your configuration file)\n"))
2028 ui.write(_(" (specify a username in your configuration file)\n"))
2029 problems += 1
2029 problems += 1
2030
2030
2031 if not problems:
2031 if not problems:
2032 ui.status(_("no problems detected\n"))
2032 ui.status(_("no problems detected\n"))
2033 else:
2033 else:
2034 ui.write(_("%s problems detected,"
2034 ui.write(_("%s problems detected,"
2035 " please check your install!\n") % problems)
2035 " please check your install!\n") % problems)
2036
2036
2037 return problems
2037 return problems
2038
2038
2039 @command('debugknown', [], _('REPO ID...'))
2039 @command('debugknown', [], _('REPO ID...'))
2040 def debugknown(ui, repopath, *ids, **opts):
2040 def debugknown(ui, repopath, *ids, **opts):
2041 """test whether node ids are known to a repo
2041 """test whether node ids are known to a repo
2042
2042
2043 Every ID must be a full-length hex node id string. Returns a list of 0s
2043 Every ID must be a full-length hex node id string. Returns a list of 0s
2044 and 1s indicating unknown/known.
2044 and 1s indicating unknown/known.
2045 """
2045 """
2046 repo = hg.peer(ui, opts, repopath)
2046 repo = hg.peer(ui, opts, repopath)
2047 if not repo.capable('known'):
2047 if not repo.capable('known'):
2048 raise util.Abort("known() not supported by target repository")
2048 raise util.Abort("known() not supported by target repository")
2049 flags = repo.known([bin(s) for s in ids])
2049 flags = repo.known([bin(s) for s in ids])
2050 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2050 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2051
2051
2052 @command('debugobsolete', [] + commitopts2,
2053 _('OBSOLETED [REPLACEMENT] [REPL...'))
2054 def debugobsolete(ui, repo, precursor, *successors, **opts):
2055 """create arbitrary obsolete marker"""
2056 metadata = {}
2057 if 'date' in opts:
2058 metadata['date'] = opts['date']
2059 metadata['user'] = opts['user'] or ui.username()
2060 succs = tuple(bin(succ) for succ in successors)
2061 l = repo.lock()
2062 try:
2063 repo.obsstore.create(bin(precursor), succs, 0, metadata)
2064 finally:
2065 l.release()
2066
2052 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2067 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2053 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2068 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2054 '''access the pushkey key/value protocol
2069 '''access the pushkey key/value protocol
2055
2070
2056 With two args, list the keys in the given namespace.
2071 With two args, list the keys in the given namespace.
2057
2072
2058 With five args, set a key to new if it currently is set to old.
2073 With five args, set a key to new if it currently is set to old.
2059 Reports success or failure.
2074 Reports success or failure.
2060 '''
2075 '''
2061
2076
2062 target = hg.peer(ui, {}, repopath)
2077 target = hg.peer(ui, {}, repopath)
2063 if keyinfo:
2078 if keyinfo:
2064 key, old, new = keyinfo
2079 key, old, new = keyinfo
2065 r = target.pushkey(namespace, key, old, new)
2080 r = target.pushkey(namespace, key, old, new)
2066 ui.status(str(r) + '\n')
2081 ui.status(str(r) + '\n')
2067 return not r
2082 return not r
2068 else:
2083 else:
2069 for k, v in target.listkeys(namespace).iteritems():
2084 for k, v in target.listkeys(namespace).iteritems():
2070 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2085 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2071 v.encode('string-escape')))
2086 v.encode('string-escape')))
2072
2087
2073 @command('debugpvec', [], _('A B'))
2088 @command('debugpvec', [], _('A B'))
2074 def debugpvec(ui, repo, a, b=None):
2089 def debugpvec(ui, repo, a, b=None):
2075 ca = scmutil.revsingle(repo, a)
2090 ca = scmutil.revsingle(repo, a)
2076 cb = scmutil.revsingle(repo, b)
2091 cb = scmutil.revsingle(repo, b)
2077 pa = pvec.ctxpvec(ca)
2092 pa = pvec.ctxpvec(ca)
2078 pb = pvec.ctxpvec(cb)
2093 pb = pvec.ctxpvec(cb)
2079 if pa == pb:
2094 if pa == pb:
2080 rel = "="
2095 rel = "="
2081 elif pa > pb:
2096 elif pa > pb:
2082 rel = ">"
2097 rel = ">"
2083 elif pa < pb:
2098 elif pa < pb:
2084 rel = "<"
2099 rel = "<"
2085 elif pa | pb:
2100 elif pa | pb:
2086 rel = "|"
2101 rel = "|"
2087 ui.write(_("a: %s\n") % pa)
2102 ui.write(_("a: %s\n") % pa)
2088 ui.write(_("b: %s\n") % pb)
2103 ui.write(_("b: %s\n") % pb)
2089 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2104 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2090 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2105 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2091 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2106 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2092 pa.distance(pb), rel))
2107 pa.distance(pb), rel))
2093
2108
2094 @command('debugrebuildstate',
2109 @command('debugrebuildstate',
2095 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2110 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2096 _('[-r REV] [REV]'))
2111 _('[-r REV] [REV]'))
2097 def debugrebuildstate(ui, repo, rev="tip"):
2112 def debugrebuildstate(ui, repo, rev="tip"):
2098 """rebuild the dirstate as it would look like for the given revision"""
2113 """rebuild the dirstate as it would look like for the given revision"""
2099 ctx = scmutil.revsingle(repo, rev)
2114 ctx = scmutil.revsingle(repo, rev)
2100 wlock = repo.wlock()
2115 wlock = repo.wlock()
2101 try:
2116 try:
2102 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2117 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2103 finally:
2118 finally:
2104 wlock.release()
2119 wlock.release()
2105
2120
2106 @command('debugrename',
2121 @command('debugrename',
2107 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2122 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2108 _('[-r REV] FILE'))
2123 _('[-r REV] FILE'))
2109 def debugrename(ui, repo, file1, *pats, **opts):
2124 def debugrename(ui, repo, file1, *pats, **opts):
2110 """dump rename information"""
2125 """dump rename information"""
2111
2126
2112 ctx = scmutil.revsingle(repo, opts.get('rev'))
2127 ctx = scmutil.revsingle(repo, opts.get('rev'))
2113 m = scmutil.match(ctx, (file1,) + pats, opts)
2128 m = scmutil.match(ctx, (file1,) + pats, opts)
2114 for abs in ctx.walk(m):
2129 for abs in ctx.walk(m):
2115 fctx = ctx[abs]
2130 fctx = ctx[abs]
2116 o = fctx.filelog().renamed(fctx.filenode())
2131 o = fctx.filelog().renamed(fctx.filenode())
2117 rel = m.rel(abs)
2132 rel = m.rel(abs)
2118 if o:
2133 if o:
2119 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2134 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2120 else:
2135 else:
2121 ui.write(_("%s not renamed\n") % rel)
2136 ui.write(_("%s not renamed\n") % rel)
2122
2137
2123 @command('debugrevlog',
2138 @command('debugrevlog',
2124 [('c', 'changelog', False, _('open changelog')),
2139 [('c', 'changelog', False, _('open changelog')),
2125 ('m', 'manifest', False, _('open manifest')),
2140 ('m', 'manifest', False, _('open manifest')),
2126 ('d', 'dump', False, _('dump index data'))],
2141 ('d', 'dump', False, _('dump index data'))],
2127 _('-c|-m|FILE'))
2142 _('-c|-m|FILE'))
2128 def debugrevlog(ui, repo, file_ = None, **opts):
2143 def debugrevlog(ui, repo, file_ = None, **opts):
2129 """show data and statistics about a revlog"""
2144 """show data and statistics about a revlog"""
2130 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2145 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2131
2146
2132 if opts.get("dump"):
2147 if opts.get("dump"):
2133 numrevs = len(r)
2148 numrevs = len(r)
2134 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2149 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2135 " rawsize totalsize compression heads\n")
2150 " rawsize totalsize compression heads\n")
2136 ts = 0
2151 ts = 0
2137 heads = set()
2152 heads = set()
2138 for rev in xrange(numrevs):
2153 for rev in xrange(numrevs):
2139 dbase = r.deltaparent(rev)
2154 dbase = r.deltaparent(rev)
2140 if dbase == -1:
2155 if dbase == -1:
2141 dbase = rev
2156 dbase = rev
2142 cbase = r.chainbase(rev)
2157 cbase = r.chainbase(rev)
2143 p1, p2 = r.parentrevs(rev)
2158 p1, p2 = r.parentrevs(rev)
2144 rs = r.rawsize(rev)
2159 rs = r.rawsize(rev)
2145 ts = ts + rs
2160 ts = ts + rs
2146 heads -= set(r.parentrevs(rev))
2161 heads -= set(r.parentrevs(rev))
2147 heads.add(rev)
2162 heads.add(rev)
2148 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2163 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2149 (rev, p1, p2, r.start(rev), r.end(rev),
2164 (rev, p1, p2, r.start(rev), r.end(rev),
2150 r.start(dbase), r.start(cbase),
2165 r.start(dbase), r.start(cbase),
2151 r.start(p1), r.start(p2),
2166 r.start(p1), r.start(p2),
2152 rs, ts, ts / r.end(rev), len(heads)))
2167 rs, ts, ts / r.end(rev), len(heads)))
2153 return 0
2168 return 0
2154
2169
2155 v = r.version
2170 v = r.version
2156 format = v & 0xFFFF
2171 format = v & 0xFFFF
2157 flags = []
2172 flags = []
2158 gdelta = False
2173 gdelta = False
2159 if v & revlog.REVLOGNGINLINEDATA:
2174 if v & revlog.REVLOGNGINLINEDATA:
2160 flags.append('inline')
2175 flags.append('inline')
2161 if v & revlog.REVLOGGENERALDELTA:
2176 if v & revlog.REVLOGGENERALDELTA:
2162 gdelta = True
2177 gdelta = True
2163 flags.append('generaldelta')
2178 flags.append('generaldelta')
2164 if not flags:
2179 if not flags:
2165 flags = ['(none)']
2180 flags = ['(none)']
2166
2181
2167 nummerges = 0
2182 nummerges = 0
2168 numfull = 0
2183 numfull = 0
2169 numprev = 0
2184 numprev = 0
2170 nump1 = 0
2185 nump1 = 0
2171 nump2 = 0
2186 nump2 = 0
2172 numother = 0
2187 numother = 0
2173 nump1prev = 0
2188 nump1prev = 0
2174 nump2prev = 0
2189 nump2prev = 0
2175 chainlengths = []
2190 chainlengths = []
2176
2191
2177 datasize = [None, 0, 0L]
2192 datasize = [None, 0, 0L]
2178 fullsize = [None, 0, 0L]
2193 fullsize = [None, 0, 0L]
2179 deltasize = [None, 0, 0L]
2194 deltasize = [None, 0, 0L]
2180
2195
2181 def addsize(size, l):
2196 def addsize(size, l):
2182 if l[0] is None or size < l[0]:
2197 if l[0] is None or size < l[0]:
2183 l[0] = size
2198 l[0] = size
2184 if size > l[1]:
2199 if size > l[1]:
2185 l[1] = size
2200 l[1] = size
2186 l[2] += size
2201 l[2] += size
2187
2202
2188 numrevs = len(r)
2203 numrevs = len(r)
2189 for rev in xrange(numrevs):
2204 for rev in xrange(numrevs):
2190 p1, p2 = r.parentrevs(rev)
2205 p1, p2 = r.parentrevs(rev)
2191 delta = r.deltaparent(rev)
2206 delta = r.deltaparent(rev)
2192 if format > 0:
2207 if format > 0:
2193 addsize(r.rawsize(rev), datasize)
2208 addsize(r.rawsize(rev), datasize)
2194 if p2 != nullrev:
2209 if p2 != nullrev:
2195 nummerges += 1
2210 nummerges += 1
2196 size = r.length(rev)
2211 size = r.length(rev)
2197 if delta == nullrev:
2212 if delta == nullrev:
2198 chainlengths.append(0)
2213 chainlengths.append(0)
2199 numfull += 1
2214 numfull += 1
2200 addsize(size, fullsize)
2215 addsize(size, fullsize)
2201 else:
2216 else:
2202 chainlengths.append(chainlengths[delta] + 1)
2217 chainlengths.append(chainlengths[delta] + 1)
2203 addsize(size, deltasize)
2218 addsize(size, deltasize)
2204 if delta == rev - 1:
2219 if delta == rev - 1:
2205 numprev += 1
2220 numprev += 1
2206 if delta == p1:
2221 if delta == p1:
2207 nump1prev += 1
2222 nump1prev += 1
2208 elif delta == p2:
2223 elif delta == p2:
2209 nump2prev += 1
2224 nump2prev += 1
2210 elif delta == p1:
2225 elif delta == p1:
2211 nump1 += 1
2226 nump1 += 1
2212 elif delta == p2:
2227 elif delta == p2:
2213 nump2 += 1
2228 nump2 += 1
2214 elif delta != nullrev:
2229 elif delta != nullrev:
2215 numother += 1
2230 numother += 1
2216
2231
2217 numdeltas = numrevs - numfull
2232 numdeltas = numrevs - numfull
2218 numoprev = numprev - nump1prev - nump2prev
2233 numoprev = numprev - nump1prev - nump2prev
2219 totalrawsize = datasize[2]
2234 totalrawsize = datasize[2]
2220 datasize[2] /= numrevs
2235 datasize[2] /= numrevs
2221 fulltotal = fullsize[2]
2236 fulltotal = fullsize[2]
2222 fullsize[2] /= numfull
2237 fullsize[2] /= numfull
2223 deltatotal = deltasize[2]
2238 deltatotal = deltasize[2]
2224 deltasize[2] /= numrevs - numfull
2239 deltasize[2] /= numrevs - numfull
2225 totalsize = fulltotal + deltatotal
2240 totalsize = fulltotal + deltatotal
2226 avgchainlen = sum(chainlengths) / numrevs
2241 avgchainlen = sum(chainlengths) / numrevs
2227 compratio = totalrawsize / totalsize
2242 compratio = totalrawsize / totalsize
2228
2243
2229 basedfmtstr = '%%%dd\n'
2244 basedfmtstr = '%%%dd\n'
2230 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2245 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2231
2246
2232 def dfmtstr(max):
2247 def dfmtstr(max):
2233 return basedfmtstr % len(str(max))
2248 return basedfmtstr % len(str(max))
2234 def pcfmtstr(max, padding=0):
2249 def pcfmtstr(max, padding=0):
2235 return basepcfmtstr % (len(str(max)), ' ' * padding)
2250 return basepcfmtstr % (len(str(max)), ' ' * padding)
2236
2251
2237 def pcfmt(value, total):
2252 def pcfmt(value, total):
2238 return (value, 100 * float(value) / total)
2253 return (value, 100 * float(value) / total)
2239
2254
2240 ui.write('format : %d\n' % format)
2255 ui.write('format : %d\n' % format)
2241 ui.write('flags : %s\n' % ', '.join(flags))
2256 ui.write('flags : %s\n' % ', '.join(flags))
2242
2257
2243 ui.write('\n')
2258 ui.write('\n')
2244 fmt = pcfmtstr(totalsize)
2259 fmt = pcfmtstr(totalsize)
2245 fmt2 = dfmtstr(totalsize)
2260 fmt2 = dfmtstr(totalsize)
2246 ui.write('revisions : ' + fmt2 % numrevs)
2261 ui.write('revisions : ' + fmt2 % numrevs)
2247 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2262 ui.write(' merges : ' + fmt % pcfmt(nummerges, numrevs))
2248 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2263 ui.write(' normal : ' + fmt % pcfmt(numrevs - nummerges, numrevs))
2249 ui.write('revisions : ' + fmt2 % numrevs)
2264 ui.write('revisions : ' + fmt2 % numrevs)
2250 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2265 ui.write(' full : ' + fmt % pcfmt(numfull, numrevs))
2251 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2266 ui.write(' deltas : ' + fmt % pcfmt(numdeltas, numrevs))
2252 ui.write('revision size : ' + fmt2 % totalsize)
2267 ui.write('revision size : ' + fmt2 % totalsize)
2253 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2268 ui.write(' full : ' + fmt % pcfmt(fulltotal, totalsize))
2254 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2269 ui.write(' deltas : ' + fmt % pcfmt(deltatotal, totalsize))
2255
2270
2256 ui.write('\n')
2271 ui.write('\n')
2257 fmt = dfmtstr(max(avgchainlen, compratio))
2272 fmt = dfmtstr(max(avgchainlen, compratio))
2258 ui.write('avg chain length : ' + fmt % avgchainlen)
2273 ui.write('avg chain length : ' + fmt % avgchainlen)
2259 ui.write('compression ratio : ' + fmt % compratio)
2274 ui.write('compression ratio : ' + fmt % compratio)
2260
2275
2261 if format > 0:
2276 if format > 0:
2262 ui.write('\n')
2277 ui.write('\n')
2263 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2278 ui.write('uncompressed data size (min/max/avg) : %d / %d / %d\n'
2264 % tuple(datasize))
2279 % tuple(datasize))
2265 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2280 ui.write('full revision size (min/max/avg) : %d / %d / %d\n'
2266 % tuple(fullsize))
2281 % tuple(fullsize))
2267 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2282 ui.write('delta size (min/max/avg) : %d / %d / %d\n'
2268 % tuple(deltasize))
2283 % tuple(deltasize))
2269
2284
2270 if numdeltas > 0:
2285 if numdeltas > 0:
2271 ui.write('\n')
2286 ui.write('\n')
2272 fmt = pcfmtstr(numdeltas)
2287 fmt = pcfmtstr(numdeltas)
2273 fmt2 = pcfmtstr(numdeltas, 4)
2288 fmt2 = pcfmtstr(numdeltas, 4)
2274 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2289 ui.write('deltas against prev : ' + fmt % pcfmt(numprev, numdeltas))
2275 if numprev > 0:
2290 if numprev > 0:
2276 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2291 ui.write(' where prev = p1 : ' + fmt2 % pcfmt(nump1prev,
2277 numprev))
2292 numprev))
2278 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2293 ui.write(' where prev = p2 : ' + fmt2 % pcfmt(nump2prev,
2279 numprev))
2294 numprev))
2280 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2295 ui.write(' other : ' + fmt2 % pcfmt(numoprev,
2281 numprev))
2296 numprev))
2282 if gdelta:
2297 if gdelta:
2283 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2298 ui.write('deltas against p1 : ' + fmt % pcfmt(nump1, numdeltas))
2284 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2299 ui.write('deltas against p2 : ' + fmt % pcfmt(nump2, numdeltas))
2285 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2300 ui.write('deltas against other : ' + fmt % pcfmt(numother,
2286 numdeltas))
2301 numdeltas))
2287
2302
2288 @command('debugrevspec', [], ('REVSPEC'))
2303 @command('debugrevspec', [], ('REVSPEC'))
2289 def debugrevspec(ui, repo, expr):
2304 def debugrevspec(ui, repo, expr):
2290 """parse and apply a revision specification
2305 """parse and apply a revision specification
2291
2306
2292 Use --verbose to print the parsed tree before and after aliases
2307 Use --verbose to print the parsed tree before and after aliases
2293 expansion.
2308 expansion.
2294 """
2309 """
2295 if ui.verbose:
2310 if ui.verbose:
2296 tree = revset.parse(expr)[0]
2311 tree = revset.parse(expr)[0]
2297 ui.note(revset.prettyformat(tree), "\n")
2312 ui.note(revset.prettyformat(tree), "\n")
2298 newtree = revset.findaliases(ui, tree)
2313 newtree = revset.findaliases(ui, tree)
2299 if newtree != tree:
2314 if newtree != tree:
2300 ui.note(revset.prettyformat(newtree), "\n")
2315 ui.note(revset.prettyformat(newtree), "\n")
2301 func = revset.match(ui, expr)
2316 func = revset.match(ui, expr)
2302 for c in func(repo, range(len(repo))):
2317 for c in func(repo, range(len(repo))):
2303 ui.write("%s\n" % c)
2318 ui.write("%s\n" % c)
2304
2319
2305 @command('debugsetparents', [], _('REV1 [REV2]'))
2320 @command('debugsetparents', [], _('REV1 [REV2]'))
2306 def debugsetparents(ui, repo, rev1, rev2=None):
2321 def debugsetparents(ui, repo, rev1, rev2=None):
2307 """manually set the parents of the current working directory
2322 """manually set the parents of the current working directory
2308
2323
2309 This is useful for writing repository conversion tools, but should
2324 This is useful for writing repository conversion tools, but should
2310 be used with care.
2325 be used with care.
2311
2326
2312 Returns 0 on success.
2327 Returns 0 on success.
2313 """
2328 """
2314
2329
2315 r1 = scmutil.revsingle(repo, rev1).node()
2330 r1 = scmutil.revsingle(repo, rev1).node()
2316 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2331 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2317
2332
2318 wlock = repo.wlock()
2333 wlock = repo.wlock()
2319 try:
2334 try:
2320 repo.setparents(r1, r2)
2335 repo.setparents(r1, r2)
2321 finally:
2336 finally:
2322 wlock.release()
2337 wlock.release()
2323
2338
2324 @command('debugstate',
2339 @command('debugstate',
2325 [('', 'nodates', None, _('do not display the saved mtime')),
2340 [('', 'nodates', None, _('do not display the saved mtime')),
2326 ('', 'datesort', None, _('sort by saved mtime'))],
2341 ('', 'datesort', None, _('sort by saved mtime'))],
2327 _('[OPTION]...'))
2342 _('[OPTION]...'))
2328 def debugstate(ui, repo, nodates=None, datesort=None):
2343 def debugstate(ui, repo, nodates=None, datesort=None):
2329 """show the contents of the current dirstate"""
2344 """show the contents of the current dirstate"""
2330 timestr = ""
2345 timestr = ""
2331 showdate = not nodates
2346 showdate = not nodates
2332 if datesort:
2347 if datesort:
2333 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2348 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2334 else:
2349 else:
2335 keyfunc = None # sort by filename
2350 keyfunc = None # sort by filename
2336 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2351 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2337 if showdate:
2352 if showdate:
2338 if ent[3] == -1:
2353 if ent[3] == -1:
2339 # Pad or slice to locale representation
2354 # Pad or slice to locale representation
2340 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2355 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2341 time.localtime(0)))
2356 time.localtime(0)))
2342 timestr = 'unset'
2357 timestr = 'unset'
2343 timestr = (timestr[:locale_len] +
2358 timestr = (timestr[:locale_len] +
2344 ' ' * (locale_len - len(timestr)))
2359 ' ' * (locale_len - len(timestr)))
2345 else:
2360 else:
2346 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2361 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2347 time.localtime(ent[3]))
2362 time.localtime(ent[3]))
2348 if ent[1] & 020000:
2363 if ent[1] & 020000:
2349 mode = 'lnk'
2364 mode = 'lnk'
2350 else:
2365 else:
2351 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2366 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2352 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2367 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2353 for f in repo.dirstate.copies():
2368 for f in repo.dirstate.copies():
2354 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2369 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2355
2370
2356 @command('debugsub',
2371 @command('debugsub',
2357 [('r', 'rev', '',
2372 [('r', 'rev', '',
2358 _('revision to check'), _('REV'))],
2373 _('revision to check'), _('REV'))],
2359 _('[-r REV] [REV]'))
2374 _('[-r REV] [REV]'))
2360 def debugsub(ui, repo, rev=None):
2375 def debugsub(ui, repo, rev=None):
2361 ctx = scmutil.revsingle(repo, rev, None)
2376 ctx = scmutil.revsingle(repo, rev, None)
2362 for k, v in sorted(ctx.substate.items()):
2377 for k, v in sorted(ctx.substate.items()):
2363 ui.write('path %s\n' % k)
2378 ui.write('path %s\n' % k)
2364 ui.write(' source %s\n' % v[0])
2379 ui.write(' source %s\n' % v[0])
2365 ui.write(' revision %s\n' % v[1])
2380 ui.write(' revision %s\n' % v[1])
2366
2381
2367 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2382 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2368 def debugwalk(ui, repo, *pats, **opts):
2383 def debugwalk(ui, repo, *pats, **opts):
2369 """show how files match on given patterns"""
2384 """show how files match on given patterns"""
2370 m = scmutil.match(repo[None], pats, opts)
2385 m = scmutil.match(repo[None], pats, opts)
2371 items = list(repo.walk(m))
2386 items = list(repo.walk(m))
2372 if not items:
2387 if not items:
2373 return
2388 return
2374 f = lambda fn: fn
2389 f = lambda fn: fn
2375 if ui.configbool('ui', 'slash') and os.sep != '/':
2390 if ui.configbool('ui', 'slash') and os.sep != '/':
2376 f = lambda fn: util.normpath(fn)
2391 f = lambda fn: util.normpath(fn)
2377 fmt = 'f %%-%ds %%-%ds %%s' % (
2392 fmt = 'f %%-%ds %%-%ds %%s' % (
2378 max([len(abs) for abs in items]),
2393 max([len(abs) for abs in items]),
2379 max([len(m.rel(abs)) for abs in items]))
2394 max([len(m.rel(abs)) for abs in items]))
2380 for abs in items:
2395 for abs in items:
2381 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2396 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2382 ui.write("%s\n" % line.rstrip())
2397 ui.write("%s\n" % line.rstrip())
2383
2398
2384 @command('debugwireargs',
2399 @command('debugwireargs',
2385 [('', 'three', '', 'three'),
2400 [('', 'three', '', 'three'),
2386 ('', 'four', '', 'four'),
2401 ('', 'four', '', 'four'),
2387 ('', 'five', '', 'five'),
2402 ('', 'five', '', 'five'),
2388 ] + remoteopts,
2403 ] + remoteopts,
2389 _('REPO [OPTIONS]... [ONE [TWO]]'))
2404 _('REPO [OPTIONS]... [ONE [TWO]]'))
2390 def debugwireargs(ui, repopath, *vals, **opts):
2405 def debugwireargs(ui, repopath, *vals, **opts):
2391 repo = hg.peer(ui, opts, repopath)
2406 repo = hg.peer(ui, opts, repopath)
2392 for opt in remoteopts:
2407 for opt in remoteopts:
2393 del opts[opt[1]]
2408 del opts[opt[1]]
2394 args = {}
2409 args = {}
2395 for k, v in opts.iteritems():
2410 for k, v in opts.iteritems():
2396 if v:
2411 if v:
2397 args[k] = v
2412 args[k] = v
2398 # run twice to check that we don't mess up the stream for the next command
2413 # run twice to check that we don't mess up the stream for the next command
2399 res1 = repo.debugwireargs(*vals, **args)
2414 res1 = repo.debugwireargs(*vals, **args)
2400 res2 = repo.debugwireargs(*vals, **args)
2415 res2 = repo.debugwireargs(*vals, **args)
2401 ui.write("%s\n" % res1)
2416 ui.write("%s\n" % res1)
2402 if res1 != res2:
2417 if res1 != res2:
2403 ui.warn("%s\n" % res2)
2418 ui.warn("%s\n" % res2)
2404
2419
2405 @command('^diff',
2420 @command('^diff',
2406 [('r', 'rev', [], _('revision'), _('REV')),
2421 [('r', 'rev', [], _('revision'), _('REV')),
2407 ('c', 'change', '', _('change made by revision'), _('REV'))
2422 ('c', 'change', '', _('change made by revision'), _('REV'))
2408 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2423 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2409 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2424 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2410 def diff(ui, repo, *pats, **opts):
2425 def diff(ui, repo, *pats, **opts):
2411 """diff repository (or selected files)
2426 """diff repository (or selected files)
2412
2427
2413 Show differences between revisions for the specified files.
2428 Show differences between revisions for the specified files.
2414
2429
2415 Differences between files are shown using the unified diff format.
2430 Differences between files are shown using the unified diff format.
2416
2431
2417 .. note::
2432 .. note::
2418 diff may generate unexpected results for merges, as it will
2433 diff may generate unexpected results for merges, as it will
2419 default to comparing against the working directory's first
2434 default to comparing against the working directory's first
2420 parent changeset if no revisions are specified.
2435 parent changeset if no revisions are specified.
2421
2436
2422 When two revision arguments are given, then changes are shown
2437 When two revision arguments are given, then changes are shown
2423 between those revisions. If only one revision is specified then
2438 between those revisions. If only one revision is specified then
2424 that revision is compared to the working directory, and, when no
2439 that revision is compared to the working directory, and, when no
2425 revisions are specified, the working directory files are compared
2440 revisions are specified, the working directory files are compared
2426 to its parent.
2441 to its parent.
2427
2442
2428 Alternatively you can specify -c/--change with a revision to see
2443 Alternatively you can specify -c/--change with a revision to see
2429 the changes in that changeset relative to its first parent.
2444 the changes in that changeset relative to its first parent.
2430
2445
2431 Without the -a/--text option, diff will avoid generating diffs of
2446 Without the -a/--text option, diff will avoid generating diffs of
2432 files it detects as binary. With -a, diff will generate a diff
2447 files it detects as binary. With -a, diff will generate a diff
2433 anyway, probably with undesirable results.
2448 anyway, probably with undesirable results.
2434
2449
2435 Use the -g/--git option to generate diffs in the git extended diff
2450 Use the -g/--git option to generate diffs in the git extended diff
2436 format. For more information, read :hg:`help diffs`.
2451 format. For more information, read :hg:`help diffs`.
2437
2452
2438 .. container:: verbose
2453 .. container:: verbose
2439
2454
2440 Examples:
2455 Examples:
2441
2456
2442 - compare a file in the current working directory to its parent::
2457 - compare a file in the current working directory to its parent::
2443
2458
2444 hg diff foo.c
2459 hg diff foo.c
2445
2460
2446 - compare two historical versions of a directory, with rename info::
2461 - compare two historical versions of a directory, with rename info::
2447
2462
2448 hg diff --git -r 1.0:1.2 lib/
2463 hg diff --git -r 1.0:1.2 lib/
2449
2464
2450 - get change stats relative to the last change on some date::
2465 - get change stats relative to the last change on some date::
2451
2466
2452 hg diff --stat -r "date('may 2')"
2467 hg diff --stat -r "date('may 2')"
2453
2468
2454 - diff all newly-added files that contain a keyword::
2469 - diff all newly-added files that contain a keyword::
2455
2470
2456 hg diff "set:added() and grep(GNU)"
2471 hg diff "set:added() and grep(GNU)"
2457
2472
2458 - compare a revision and its parents::
2473 - compare a revision and its parents::
2459
2474
2460 hg diff -c 9353 # compare against first parent
2475 hg diff -c 9353 # compare against first parent
2461 hg diff -r 9353^:9353 # same using revset syntax
2476 hg diff -r 9353^:9353 # same using revset syntax
2462 hg diff -r 9353^2:9353 # compare against the second parent
2477 hg diff -r 9353^2:9353 # compare against the second parent
2463
2478
2464 Returns 0 on success.
2479 Returns 0 on success.
2465 """
2480 """
2466
2481
2467 revs = opts.get('rev')
2482 revs = opts.get('rev')
2468 change = opts.get('change')
2483 change = opts.get('change')
2469 stat = opts.get('stat')
2484 stat = opts.get('stat')
2470 reverse = opts.get('reverse')
2485 reverse = opts.get('reverse')
2471
2486
2472 if revs and change:
2487 if revs and change:
2473 msg = _('cannot specify --rev and --change at the same time')
2488 msg = _('cannot specify --rev and --change at the same time')
2474 raise util.Abort(msg)
2489 raise util.Abort(msg)
2475 elif change:
2490 elif change:
2476 node2 = scmutil.revsingle(repo, change, None).node()
2491 node2 = scmutil.revsingle(repo, change, None).node()
2477 node1 = repo[node2].p1().node()
2492 node1 = repo[node2].p1().node()
2478 else:
2493 else:
2479 node1, node2 = scmutil.revpair(repo, revs)
2494 node1, node2 = scmutil.revpair(repo, revs)
2480
2495
2481 if reverse:
2496 if reverse:
2482 node1, node2 = node2, node1
2497 node1, node2 = node2, node1
2483
2498
2484 diffopts = patch.diffopts(ui, opts)
2499 diffopts = patch.diffopts(ui, opts)
2485 m = scmutil.match(repo[node2], pats, opts)
2500 m = scmutil.match(repo[node2], pats, opts)
2486 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2501 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2487 listsubrepos=opts.get('subrepos'))
2502 listsubrepos=opts.get('subrepos'))
2488
2503
2489 @command('^export',
2504 @command('^export',
2490 [('o', 'output', '',
2505 [('o', 'output', '',
2491 _('print output to file with formatted name'), _('FORMAT')),
2506 _('print output to file with formatted name'), _('FORMAT')),
2492 ('', 'switch-parent', None, _('diff against the second parent')),
2507 ('', 'switch-parent', None, _('diff against the second parent')),
2493 ('r', 'rev', [], _('revisions to export'), _('REV')),
2508 ('r', 'rev', [], _('revisions to export'), _('REV')),
2494 ] + diffopts,
2509 ] + diffopts,
2495 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2510 _('[OPTION]... [-o OUTFILESPEC] [-r] REV...'))
2496 def export(ui, repo, *changesets, **opts):
2511 def export(ui, repo, *changesets, **opts):
2497 """dump the header and diffs for one or more changesets
2512 """dump the header and diffs for one or more changesets
2498
2513
2499 Print the changeset header and diffs for one or more revisions.
2514 Print the changeset header and diffs for one or more revisions.
2500
2515
2501 The information shown in the changeset header is: author, date,
2516 The information shown in the changeset header is: author, date,
2502 branch name (if non-default), changeset hash, parent(s) and commit
2517 branch name (if non-default), changeset hash, parent(s) and commit
2503 comment.
2518 comment.
2504
2519
2505 .. note::
2520 .. note::
2506 export may generate unexpected diff output for merge
2521 export may generate unexpected diff output for merge
2507 changesets, as it will compare the merge changeset against its
2522 changesets, as it will compare the merge changeset against its
2508 first parent only.
2523 first parent only.
2509
2524
2510 Output may be to a file, in which case the name of the file is
2525 Output may be to a file, in which case the name of the file is
2511 given using a format string. The formatting rules are as follows:
2526 given using a format string. The formatting rules are as follows:
2512
2527
2513 :``%%``: literal "%" character
2528 :``%%``: literal "%" character
2514 :``%H``: changeset hash (40 hexadecimal digits)
2529 :``%H``: changeset hash (40 hexadecimal digits)
2515 :``%N``: number of patches being generated
2530 :``%N``: number of patches being generated
2516 :``%R``: changeset revision number
2531 :``%R``: changeset revision number
2517 :``%b``: basename of the exporting repository
2532 :``%b``: basename of the exporting repository
2518 :``%h``: short-form changeset hash (12 hexadecimal digits)
2533 :``%h``: short-form changeset hash (12 hexadecimal digits)
2519 :``%m``: first line of the commit message (only alphanumeric characters)
2534 :``%m``: first line of the commit message (only alphanumeric characters)
2520 :``%n``: zero-padded sequence number, starting at 1
2535 :``%n``: zero-padded sequence number, starting at 1
2521 :``%r``: zero-padded changeset revision number
2536 :``%r``: zero-padded changeset revision number
2522
2537
2523 Without the -a/--text option, export will avoid generating diffs
2538 Without the -a/--text option, export will avoid generating diffs
2524 of files it detects as binary. With -a, export will generate a
2539 of files it detects as binary. With -a, export will generate a
2525 diff anyway, probably with undesirable results.
2540 diff anyway, probably with undesirable results.
2526
2541
2527 Use the -g/--git option to generate diffs in the git extended diff
2542 Use the -g/--git option to generate diffs in the git extended diff
2528 format. See :hg:`help diffs` for more information.
2543 format. See :hg:`help diffs` for more information.
2529
2544
2530 With the --switch-parent option, the diff will be against the
2545 With the --switch-parent option, the diff will be against the
2531 second parent. It can be useful to review a merge.
2546 second parent. It can be useful to review a merge.
2532
2547
2533 .. container:: verbose
2548 .. container:: verbose
2534
2549
2535 Examples:
2550 Examples:
2536
2551
2537 - use export and import to transplant a bugfix to the current
2552 - use export and import to transplant a bugfix to the current
2538 branch::
2553 branch::
2539
2554
2540 hg export -r 9353 | hg import -
2555 hg export -r 9353 | hg import -
2541
2556
2542 - export all the changesets between two revisions to a file with
2557 - export all the changesets between two revisions to a file with
2543 rename information::
2558 rename information::
2544
2559
2545 hg export --git -r 123:150 > changes.txt
2560 hg export --git -r 123:150 > changes.txt
2546
2561
2547 - split outgoing changes into a series of patches with
2562 - split outgoing changes into a series of patches with
2548 descriptive names::
2563 descriptive names::
2549
2564
2550 hg export -r "outgoing()" -o "%n-%m.patch"
2565 hg export -r "outgoing()" -o "%n-%m.patch"
2551
2566
2552 Returns 0 on success.
2567 Returns 0 on success.
2553 """
2568 """
2554 changesets += tuple(opts.get('rev', []))
2569 changesets += tuple(opts.get('rev', []))
2555 revs = scmutil.revrange(repo, changesets)
2570 revs = scmutil.revrange(repo, changesets)
2556 if not revs:
2571 if not revs:
2557 raise util.Abort(_("export requires at least one changeset"))
2572 raise util.Abort(_("export requires at least one changeset"))
2558 if len(revs) > 1:
2573 if len(revs) > 1:
2559 ui.note(_('exporting patches:\n'))
2574 ui.note(_('exporting patches:\n'))
2560 else:
2575 else:
2561 ui.note(_('exporting patch:\n'))
2576 ui.note(_('exporting patch:\n'))
2562 cmdutil.export(repo, revs, template=opts.get('output'),
2577 cmdutil.export(repo, revs, template=opts.get('output'),
2563 switch_parent=opts.get('switch_parent'),
2578 switch_parent=opts.get('switch_parent'),
2564 opts=patch.diffopts(ui, opts))
2579 opts=patch.diffopts(ui, opts))
2565
2580
2566 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2581 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2567 def forget(ui, repo, *pats, **opts):
2582 def forget(ui, repo, *pats, **opts):
2568 """forget the specified files on the next commit
2583 """forget the specified files on the next commit
2569
2584
2570 Mark the specified files so they will no longer be tracked
2585 Mark the specified files so they will no longer be tracked
2571 after the next commit.
2586 after the next commit.
2572
2587
2573 This only removes files from the current branch, not from the
2588 This only removes files from the current branch, not from the
2574 entire project history, and it does not delete them from the
2589 entire project history, and it does not delete them from the
2575 working directory.
2590 working directory.
2576
2591
2577 To undo a forget before the next commit, see :hg:`add`.
2592 To undo a forget before the next commit, see :hg:`add`.
2578
2593
2579 .. container:: verbose
2594 .. container:: verbose
2580
2595
2581 Examples:
2596 Examples:
2582
2597
2583 - forget newly-added binary files::
2598 - forget newly-added binary files::
2584
2599
2585 hg forget "set:added() and binary()"
2600 hg forget "set:added() and binary()"
2586
2601
2587 - forget files that would be excluded by .hgignore::
2602 - forget files that would be excluded by .hgignore::
2588
2603
2589 hg forget "set:hgignore()"
2604 hg forget "set:hgignore()"
2590
2605
2591 Returns 0 on success.
2606 Returns 0 on success.
2592 """
2607 """
2593
2608
2594 if not pats:
2609 if not pats:
2595 raise util.Abort(_('no files specified'))
2610 raise util.Abort(_('no files specified'))
2596
2611
2597 m = scmutil.match(repo[None], pats, opts)
2612 m = scmutil.match(repo[None], pats, opts)
2598 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2613 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2599 return rejected and 1 or 0
2614 return rejected and 1 or 0
2600
2615
2601 @command(
2616 @command(
2602 'graft',
2617 'graft',
2603 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2618 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2604 ('c', 'continue', False, _('resume interrupted graft')),
2619 ('c', 'continue', False, _('resume interrupted graft')),
2605 ('e', 'edit', False, _('invoke editor on commit messages')),
2620 ('e', 'edit', False, _('invoke editor on commit messages')),
2606 ('', 'log', None, _('append graft info to log message')),
2621 ('', 'log', None, _('append graft info to log message')),
2607 ('D', 'currentdate', False,
2622 ('D', 'currentdate', False,
2608 _('record the current date as commit date')),
2623 _('record the current date as commit date')),
2609 ('U', 'currentuser', False,
2624 ('U', 'currentuser', False,
2610 _('record the current user as committer'), _('DATE'))]
2625 _('record the current user as committer'), _('DATE'))]
2611 + commitopts2 + mergetoolopts + dryrunopts,
2626 + commitopts2 + mergetoolopts + dryrunopts,
2612 _('[OPTION]... [-r] REV...'))
2627 _('[OPTION]... [-r] REV...'))
2613 def graft(ui, repo, *revs, **opts):
2628 def graft(ui, repo, *revs, **opts):
2614 '''copy changes from other branches onto the current branch
2629 '''copy changes from other branches onto the current branch
2615
2630
2616 This command uses Mercurial's merge logic to copy individual
2631 This command uses Mercurial's merge logic to copy individual
2617 changes from other branches without merging branches in the
2632 changes from other branches without merging branches in the
2618 history graph. This is sometimes known as 'backporting' or
2633 history graph. This is sometimes known as 'backporting' or
2619 'cherry-picking'. By default, graft will copy user, date, and
2634 'cherry-picking'. By default, graft will copy user, date, and
2620 description from the source changesets.
2635 description from the source changesets.
2621
2636
2622 Changesets that are ancestors of the current revision, that have
2637 Changesets that are ancestors of the current revision, that have
2623 already been grafted, or that are merges will be skipped.
2638 already been grafted, or that are merges will be skipped.
2624
2639
2625 If --log is specified, log messages will have a comment appended
2640 If --log is specified, log messages will have a comment appended
2626 of the form::
2641 of the form::
2627
2642
2628 (grafted from CHANGESETHASH)
2643 (grafted from CHANGESETHASH)
2629
2644
2630 If a graft merge results in conflicts, the graft process is
2645 If a graft merge results in conflicts, the graft process is
2631 interrupted so that the current merge can be manually resolved.
2646 interrupted so that the current merge can be manually resolved.
2632 Once all conflicts are addressed, the graft process can be
2647 Once all conflicts are addressed, the graft process can be
2633 continued with the -c/--continue option.
2648 continued with the -c/--continue option.
2634
2649
2635 .. note::
2650 .. note::
2636 The -c/--continue option does not reapply earlier options.
2651 The -c/--continue option does not reapply earlier options.
2637
2652
2638 .. container:: verbose
2653 .. container:: verbose
2639
2654
2640 Examples:
2655 Examples:
2641
2656
2642 - copy a single change to the stable branch and edit its description::
2657 - copy a single change to the stable branch and edit its description::
2643
2658
2644 hg update stable
2659 hg update stable
2645 hg graft --edit 9393
2660 hg graft --edit 9393
2646
2661
2647 - graft a range of changesets with one exception, updating dates::
2662 - graft a range of changesets with one exception, updating dates::
2648
2663
2649 hg graft -D "2085::2093 and not 2091"
2664 hg graft -D "2085::2093 and not 2091"
2650
2665
2651 - continue a graft after resolving conflicts::
2666 - continue a graft after resolving conflicts::
2652
2667
2653 hg graft -c
2668 hg graft -c
2654
2669
2655 - show the source of a grafted changeset::
2670 - show the source of a grafted changeset::
2656
2671
2657 hg log --debug -r tip
2672 hg log --debug -r tip
2658
2673
2659 Returns 0 on successful completion.
2674 Returns 0 on successful completion.
2660 '''
2675 '''
2661
2676
2662 revs = list(revs)
2677 revs = list(revs)
2663 revs.extend(opts['rev'])
2678 revs.extend(opts['rev'])
2664
2679
2665 if not opts.get('user') and opts.get('currentuser'):
2680 if not opts.get('user') and opts.get('currentuser'):
2666 opts['user'] = ui.username()
2681 opts['user'] = ui.username()
2667 if not opts.get('date') and opts.get('currentdate'):
2682 if not opts.get('date') and opts.get('currentdate'):
2668 opts['date'] = "%d %d" % util.makedate()
2683 opts['date'] = "%d %d" % util.makedate()
2669
2684
2670 editor = None
2685 editor = None
2671 if opts.get('edit'):
2686 if opts.get('edit'):
2672 editor = cmdutil.commitforceeditor
2687 editor = cmdutil.commitforceeditor
2673
2688
2674 cont = False
2689 cont = False
2675 if opts['continue']:
2690 if opts['continue']:
2676 cont = True
2691 cont = True
2677 if revs:
2692 if revs:
2678 raise util.Abort(_("can't specify --continue and revisions"))
2693 raise util.Abort(_("can't specify --continue and revisions"))
2679 # read in unfinished revisions
2694 # read in unfinished revisions
2680 try:
2695 try:
2681 nodes = repo.opener.read('graftstate').splitlines()
2696 nodes = repo.opener.read('graftstate').splitlines()
2682 revs = [repo[node].rev() for node in nodes]
2697 revs = [repo[node].rev() for node in nodes]
2683 except IOError, inst:
2698 except IOError, inst:
2684 if inst.errno != errno.ENOENT:
2699 if inst.errno != errno.ENOENT:
2685 raise
2700 raise
2686 raise util.Abort(_("no graft state found, can't continue"))
2701 raise util.Abort(_("no graft state found, can't continue"))
2687 else:
2702 else:
2688 cmdutil.bailifchanged(repo)
2703 cmdutil.bailifchanged(repo)
2689 if not revs:
2704 if not revs:
2690 raise util.Abort(_('no revisions specified'))
2705 raise util.Abort(_('no revisions specified'))
2691 revs = scmutil.revrange(repo, revs)
2706 revs = scmutil.revrange(repo, revs)
2692
2707
2693 # check for merges
2708 # check for merges
2694 for rev in repo.revs('%ld and merge()', revs):
2709 for rev in repo.revs('%ld and merge()', revs):
2695 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2710 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2696 revs.remove(rev)
2711 revs.remove(rev)
2697 if not revs:
2712 if not revs:
2698 return -1
2713 return -1
2699
2714
2700 # check for ancestors of dest branch
2715 # check for ancestors of dest branch
2701 for rev in repo.revs('::. and %ld', revs):
2716 for rev in repo.revs('::. and %ld', revs):
2702 ui.warn(_('skipping ancestor revision %s\n') % rev)
2717 ui.warn(_('skipping ancestor revision %s\n') % rev)
2703 revs.remove(rev)
2718 revs.remove(rev)
2704 if not revs:
2719 if not revs:
2705 return -1
2720 return -1
2706
2721
2707 # analyze revs for earlier grafts
2722 # analyze revs for earlier grafts
2708 ids = {}
2723 ids = {}
2709 for ctx in repo.set("%ld", revs):
2724 for ctx in repo.set("%ld", revs):
2710 ids[ctx.hex()] = ctx.rev()
2725 ids[ctx.hex()] = ctx.rev()
2711 n = ctx.extra().get('source')
2726 n = ctx.extra().get('source')
2712 if n:
2727 if n:
2713 ids[n] = ctx.rev()
2728 ids[n] = ctx.rev()
2714
2729
2715 # check ancestors for earlier grafts
2730 # check ancestors for earlier grafts
2716 ui.debug('scanning for duplicate grafts\n')
2731 ui.debug('scanning for duplicate grafts\n')
2717 for ctx in repo.set("::. - ::%ld", revs):
2732 for ctx in repo.set("::. - ::%ld", revs):
2718 n = ctx.extra().get('source')
2733 n = ctx.extra().get('source')
2719 if n in ids:
2734 if n in ids:
2720 r = repo[n].rev()
2735 r = repo[n].rev()
2721 if r in revs:
2736 if r in revs:
2722 ui.warn(_('skipping already grafted revision %s\n') % r)
2737 ui.warn(_('skipping already grafted revision %s\n') % r)
2723 revs.remove(r)
2738 revs.remove(r)
2724 elif ids[n] in revs:
2739 elif ids[n] in revs:
2725 ui.warn(_('skipping already grafted revision %s '
2740 ui.warn(_('skipping already grafted revision %s '
2726 '(same origin %d)\n') % (ids[n], r))
2741 '(same origin %d)\n') % (ids[n], r))
2727 revs.remove(ids[n])
2742 revs.remove(ids[n])
2728 elif ctx.hex() in ids:
2743 elif ctx.hex() in ids:
2729 r = ids[ctx.hex()]
2744 r = ids[ctx.hex()]
2730 ui.warn(_('skipping already grafted revision %s '
2745 ui.warn(_('skipping already grafted revision %s '
2731 '(was grafted from %d)\n') % (r, ctx.rev()))
2746 '(was grafted from %d)\n') % (r, ctx.rev()))
2732 revs.remove(r)
2747 revs.remove(r)
2733 if not revs:
2748 if not revs:
2734 return -1
2749 return -1
2735
2750
2736 wlock = repo.wlock()
2751 wlock = repo.wlock()
2737 try:
2752 try:
2738 for pos, ctx in enumerate(repo.set("%ld", revs)):
2753 for pos, ctx in enumerate(repo.set("%ld", revs)):
2739 current = repo['.']
2754 current = repo['.']
2740
2755
2741 ui.status(_('grafting revision %s\n') % ctx.rev())
2756 ui.status(_('grafting revision %s\n') % ctx.rev())
2742 if opts.get('dry_run'):
2757 if opts.get('dry_run'):
2743 continue
2758 continue
2744
2759
2745 # we don't merge the first commit when continuing
2760 # we don't merge the first commit when continuing
2746 if not cont:
2761 if not cont:
2747 # perform the graft merge with p1(rev) as 'ancestor'
2762 # perform the graft merge with p1(rev) as 'ancestor'
2748 try:
2763 try:
2749 # ui.forcemerge is an internal variable, do not document
2764 # ui.forcemerge is an internal variable, do not document
2750 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2765 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2751 stats = mergemod.update(repo, ctx.node(), True, True, False,
2766 stats = mergemod.update(repo, ctx.node(), True, True, False,
2752 ctx.p1().node())
2767 ctx.p1().node())
2753 finally:
2768 finally:
2754 repo.ui.setconfig('ui', 'forcemerge', '')
2769 repo.ui.setconfig('ui', 'forcemerge', '')
2755 # report any conflicts
2770 # report any conflicts
2756 if stats and stats[3] > 0:
2771 if stats and stats[3] > 0:
2757 # write out state for --continue
2772 # write out state for --continue
2758 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2773 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
2759 repo.opener.write('graftstate', ''.join(nodelines))
2774 repo.opener.write('graftstate', ''.join(nodelines))
2760 raise util.Abort(
2775 raise util.Abort(
2761 _("unresolved conflicts, can't continue"),
2776 _("unresolved conflicts, can't continue"),
2762 hint=_('use hg resolve and hg graft --continue'))
2777 hint=_('use hg resolve and hg graft --continue'))
2763 else:
2778 else:
2764 cont = False
2779 cont = False
2765
2780
2766 # drop the second merge parent
2781 # drop the second merge parent
2767 repo.setparents(current.node(), nullid)
2782 repo.setparents(current.node(), nullid)
2768 repo.dirstate.write()
2783 repo.dirstate.write()
2769 # fix up dirstate for copies and renames
2784 # fix up dirstate for copies and renames
2770 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2785 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
2771
2786
2772 # commit
2787 # commit
2773 source = ctx.extra().get('source')
2788 source = ctx.extra().get('source')
2774 if not source:
2789 if not source:
2775 source = ctx.hex()
2790 source = ctx.hex()
2776 extra = {'source': source}
2791 extra = {'source': source}
2777 user = ctx.user()
2792 user = ctx.user()
2778 if opts.get('user'):
2793 if opts.get('user'):
2779 user = opts['user']
2794 user = opts['user']
2780 date = ctx.date()
2795 date = ctx.date()
2781 if opts.get('date'):
2796 if opts.get('date'):
2782 date = opts['date']
2797 date = opts['date']
2783 message = ctx.description()
2798 message = ctx.description()
2784 if opts.get('log'):
2799 if opts.get('log'):
2785 message += '\n(grafted from %s)' % ctx.hex()
2800 message += '\n(grafted from %s)' % ctx.hex()
2786 node = repo.commit(text=message, user=user,
2801 node = repo.commit(text=message, user=user,
2787 date=date, extra=extra, editor=editor)
2802 date=date, extra=extra, editor=editor)
2788 if node is None:
2803 if node is None:
2789 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2804 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
2790 finally:
2805 finally:
2791 wlock.release()
2806 wlock.release()
2792
2807
2793 # remove state when we complete successfully
2808 # remove state when we complete successfully
2794 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2809 if not opts.get('dry_run') and os.path.exists(repo.join('graftstate')):
2795 util.unlinkpath(repo.join('graftstate'))
2810 util.unlinkpath(repo.join('graftstate'))
2796
2811
2797 return 0
2812 return 0
2798
2813
2799 @command('grep',
2814 @command('grep',
2800 [('0', 'print0', None, _('end fields with NUL')),
2815 [('0', 'print0', None, _('end fields with NUL')),
2801 ('', 'all', None, _('print all revisions that match')),
2816 ('', 'all', None, _('print all revisions that match')),
2802 ('a', 'text', None, _('treat all files as text')),
2817 ('a', 'text', None, _('treat all files as text')),
2803 ('f', 'follow', None,
2818 ('f', 'follow', None,
2804 _('follow changeset history,'
2819 _('follow changeset history,'
2805 ' or file history across copies and renames')),
2820 ' or file history across copies and renames')),
2806 ('i', 'ignore-case', None, _('ignore case when matching')),
2821 ('i', 'ignore-case', None, _('ignore case when matching')),
2807 ('l', 'files-with-matches', None,
2822 ('l', 'files-with-matches', None,
2808 _('print only filenames and revisions that match')),
2823 _('print only filenames and revisions that match')),
2809 ('n', 'line-number', None, _('print matching line numbers')),
2824 ('n', 'line-number', None, _('print matching line numbers')),
2810 ('r', 'rev', [],
2825 ('r', 'rev', [],
2811 _('only search files changed within revision range'), _('REV')),
2826 _('only search files changed within revision range'), _('REV')),
2812 ('u', 'user', None, _('list the author (long with -v)')),
2827 ('u', 'user', None, _('list the author (long with -v)')),
2813 ('d', 'date', None, _('list the date (short with -q)')),
2828 ('d', 'date', None, _('list the date (short with -q)')),
2814 ] + walkopts,
2829 ] + walkopts,
2815 _('[OPTION]... PATTERN [FILE]...'))
2830 _('[OPTION]... PATTERN [FILE]...'))
2816 def grep(ui, repo, pattern, *pats, **opts):
2831 def grep(ui, repo, pattern, *pats, **opts):
2817 """search for a pattern in specified files and revisions
2832 """search for a pattern in specified files and revisions
2818
2833
2819 Search revisions of files for a regular expression.
2834 Search revisions of files for a regular expression.
2820
2835
2821 This command behaves differently than Unix grep. It only accepts
2836 This command behaves differently than Unix grep. It only accepts
2822 Python/Perl regexps. It searches repository history, not the
2837 Python/Perl regexps. It searches repository history, not the
2823 working directory. It always prints the revision number in which a
2838 working directory. It always prints the revision number in which a
2824 match appears.
2839 match appears.
2825
2840
2826 By default, grep only prints output for the first revision of a
2841 By default, grep only prints output for the first revision of a
2827 file in which it finds a match. To get it to print every revision
2842 file in which it finds a match. To get it to print every revision
2828 that contains a change in match status ("-" for a match that
2843 that contains a change in match status ("-" for a match that
2829 becomes a non-match, or "+" for a non-match that becomes a match),
2844 becomes a non-match, or "+" for a non-match that becomes a match),
2830 use the --all flag.
2845 use the --all flag.
2831
2846
2832 Returns 0 if a match is found, 1 otherwise.
2847 Returns 0 if a match is found, 1 otherwise.
2833 """
2848 """
2834 reflags = re.M
2849 reflags = re.M
2835 if opts.get('ignore_case'):
2850 if opts.get('ignore_case'):
2836 reflags |= re.I
2851 reflags |= re.I
2837 try:
2852 try:
2838 regexp = re.compile(pattern, reflags)
2853 regexp = re.compile(pattern, reflags)
2839 except re.error, inst:
2854 except re.error, inst:
2840 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2855 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
2841 return 1
2856 return 1
2842 sep, eol = ':', '\n'
2857 sep, eol = ':', '\n'
2843 if opts.get('print0'):
2858 if opts.get('print0'):
2844 sep = eol = '\0'
2859 sep = eol = '\0'
2845
2860
2846 getfile = util.lrucachefunc(repo.file)
2861 getfile = util.lrucachefunc(repo.file)
2847
2862
2848 def matchlines(body):
2863 def matchlines(body):
2849 begin = 0
2864 begin = 0
2850 linenum = 0
2865 linenum = 0
2851 while True:
2866 while True:
2852 match = regexp.search(body, begin)
2867 match = regexp.search(body, begin)
2853 if not match:
2868 if not match:
2854 break
2869 break
2855 mstart, mend = match.span()
2870 mstart, mend = match.span()
2856 linenum += body.count('\n', begin, mstart) + 1
2871 linenum += body.count('\n', begin, mstart) + 1
2857 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2872 lstart = body.rfind('\n', begin, mstart) + 1 or begin
2858 begin = body.find('\n', mend) + 1 or len(body) + 1
2873 begin = body.find('\n', mend) + 1 or len(body) + 1
2859 lend = begin - 1
2874 lend = begin - 1
2860 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2875 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
2861
2876
2862 class linestate(object):
2877 class linestate(object):
2863 def __init__(self, line, linenum, colstart, colend):
2878 def __init__(self, line, linenum, colstart, colend):
2864 self.line = line
2879 self.line = line
2865 self.linenum = linenum
2880 self.linenum = linenum
2866 self.colstart = colstart
2881 self.colstart = colstart
2867 self.colend = colend
2882 self.colend = colend
2868
2883
2869 def __hash__(self):
2884 def __hash__(self):
2870 return hash((self.linenum, self.line))
2885 return hash((self.linenum, self.line))
2871
2886
2872 def __eq__(self, other):
2887 def __eq__(self, other):
2873 return self.line == other.line
2888 return self.line == other.line
2874
2889
2875 matches = {}
2890 matches = {}
2876 copies = {}
2891 copies = {}
2877 def grepbody(fn, rev, body):
2892 def grepbody(fn, rev, body):
2878 matches[rev].setdefault(fn, [])
2893 matches[rev].setdefault(fn, [])
2879 m = matches[rev][fn]
2894 m = matches[rev][fn]
2880 for lnum, cstart, cend, line in matchlines(body):
2895 for lnum, cstart, cend, line in matchlines(body):
2881 s = linestate(line, lnum, cstart, cend)
2896 s = linestate(line, lnum, cstart, cend)
2882 m.append(s)
2897 m.append(s)
2883
2898
2884 def difflinestates(a, b):
2899 def difflinestates(a, b):
2885 sm = difflib.SequenceMatcher(None, a, b)
2900 sm = difflib.SequenceMatcher(None, a, b)
2886 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2901 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
2887 if tag == 'insert':
2902 if tag == 'insert':
2888 for i in xrange(blo, bhi):
2903 for i in xrange(blo, bhi):
2889 yield ('+', b[i])
2904 yield ('+', b[i])
2890 elif tag == 'delete':
2905 elif tag == 'delete':
2891 for i in xrange(alo, ahi):
2906 for i in xrange(alo, ahi):
2892 yield ('-', a[i])
2907 yield ('-', a[i])
2893 elif tag == 'replace':
2908 elif tag == 'replace':
2894 for i in xrange(alo, ahi):
2909 for i in xrange(alo, ahi):
2895 yield ('-', a[i])
2910 yield ('-', a[i])
2896 for i in xrange(blo, bhi):
2911 for i in xrange(blo, bhi):
2897 yield ('+', b[i])
2912 yield ('+', b[i])
2898
2913
2899 def display(fn, ctx, pstates, states):
2914 def display(fn, ctx, pstates, states):
2900 rev = ctx.rev()
2915 rev = ctx.rev()
2901 datefunc = ui.quiet and util.shortdate or util.datestr
2916 datefunc = ui.quiet and util.shortdate or util.datestr
2902 found = False
2917 found = False
2903 filerevmatches = {}
2918 filerevmatches = {}
2904 def binary():
2919 def binary():
2905 flog = getfile(fn)
2920 flog = getfile(fn)
2906 return util.binary(flog.read(ctx.filenode(fn)))
2921 return util.binary(flog.read(ctx.filenode(fn)))
2907
2922
2908 if opts.get('all'):
2923 if opts.get('all'):
2909 iter = difflinestates(pstates, states)
2924 iter = difflinestates(pstates, states)
2910 else:
2925 else:
2911 iter = [('', l) for l in states]
2926 iter = [('', l) for l in states]
2912 for change, l in iter:
2927 for change, l in iter:
2913 cols = [fn, str(rev)]
2928 cols = [fn, str(rev)]
2914 before, match, after = None, None, None
2929 before, match, after = None, None, None
2915 if opts.get('line_number'):
2930 if opts.get('line_number'):
2916 cols.append(str(l.linenum))
2931 cols.append(str(l.linenum))
2917 if opts.get('all'):
2932 if opts.get('all'):
2918 cols.append(change)
2933 cols.append(change)
2919 if opts.get('user'):
2934 if opts.get('user'):
2920 cols.append(ui.shortuser(ctx.user()))
2935 cols.append(ui.shortuser(ctx.user()))
2921 if opts.get('date'):
2936 if opts.get('date'):
2922 cols.append(datefunc(ctx.date()))
2937 cols.append(datefunc(ctx.date()))
2923 if opts.get('files_with_matches'):
2938 if opts.get('files_with_matches'):
2924 c = (fn, rev)
2939 c = (fn, rev)
2925 if c in filerevmatches:
2940 if c in filerevmatches:
2926 continue
2941 continue
2927 filerevmatches[c] = 1
2942 filerevmatches[c] = 1
2928 else:
2943 else:
2929 before = l.line[:l.colstart]
2944 before = l.line[:l.colstart]
2930 match = l.line[l.colstart:l.colend]
2945 match = l.line[l.colstart:l.colend]
2931 after = l.line[l.colend:]
2946 after = l.line[l.colend:]
2932 ui.write(sep.join(cols))
2947 ui.write(sep.join(cols))
2933 if before is not None:
2948 if before is not None:
2934 if not opts.get('text') and binary():
2949 if not opts.get('text') and binary():
2935 ui.write(sep + " Binary file matches")
2950 ui.write(sep + " Binary file matches")
2936 else:
2951 else:
2937 ui.write(sep + before)
2952 ui.write(sep + before)
2938 ui.write(match, label='grep.match')
2953 ui.write(match, label='grep.match')
2939 ui.write(after)
2954 ui.write(after)
2940 ui.write(eol)
2955 ui.write(eol)
2941 found = True
2956 found = True
2942 return found
2957 return found
2943
2958
2944 skip = {}
2959 skip = {}
2945 revfiles = {}
2960 revfiles = {}
2946 matchfn = scmutil.match(repo[None], pats, opts)
2961 matchfn = scmutil.match(repo[None], pats, opts)
2947 found = False
2962 found = False
2948 follow = opts.get('follow')
2963 follow = opts.get('follow')
2949
2964
2950 def prep(ctx, fns):
2965 def prep(ctx, fns):
2951 rev = ctx.rev()
2966 rev = ctx.rev()
2952 pctx = ctx.p1()
2967 pctx = ctx.p1()
2953 parent = pctx.rev()
2968 parent = pctx.rev()
2954 matches.setdefault(rev, {})
2969 matches.setdefault(rev, {})
2955 matches.setdefault(parent, {})
2970 matches.setdefault(parent, {})
2956 files = revfiles.setdefault(rev, [])
2971 files = revfiles.setdefault(rev, [])
2957 for fn in fns:
2972 for fn in fns:
2958 flog = getfile(fn)
2973 flog = getfile(fn)
2959 try:
2974 try:
2960 fnode = ctx.filenode(fn)
2975 fnode = ctx.filenode(fn)
2961 except error.LookupError:
2976 except error.LookupError:
2962 continue
2977 continue
2963
2978
2964 copied = flog.renamed(fnode)
2979 copied = flog.renamed(fnode)
2965 copy = follow and copied and copied[0]
2980 copy = follow and copied and copied[0]
2966 if copy:
2981 if copy:
2967 copies.setdefault(rev, {})[fn] = copy
2982 copies.setdefault(rev, {})[fn] = copy
2968 if fn in skip:
2983 if fn in skip:
2969 if copy:
2984 if copy:
2970 skip[copy] = True
2985 skip[copy] = True
2971 continue
2986 continue
2972 files.append(fn)
2987 files.append(fn)
2973
2988
2974 if fn not in matches[rev]:
2989 if fn not in matches[rev]:
2975 grepbody(fn, rev, flog.read(fnode))
2990 grepbody(fn, rev, flog.read(fnode))
2976
2991
2977 pfn = copy or fn
2992 pfn = copy or fn
2978 if pfn not in matches[parent]:
2993 if pfn not in matches[parent]:
2979 try:
2994 try:
2980 fnode = pctx.filenode(pfn)
2995 fnode = pctx.filenode(pfn)
2981 grepbody(pfn, parent, flog.read(fnode))
2996 grepbody(pfn, parent, flog.read(fnode))
2982 except error.LookupError:
2997 except error.LookupError:
2983 pass
2998 pass
2984
2999
2985 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3000 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2986 rev = ctx.rev()
3001 rev = ctx.rev()
2987 parent = ctx.p1().rev()
3002 parent = ctx.p1().rev()
2988 for fn in sorted(revfiles.get(rev, [])):
3003 for fn in sorted(revfiles.get(rev, [])):
2989 states = matches[rev][fn]
3004 states = matches[rev][fn]
2990 copy = copies.get(rev, {}).get(fn)
3005 copy = copies.get(rev, {}).get(fn)
2991 if fn in skip:
3006 if fn in skip:
2992 if copy:
3007 if copy:
2993 skip[copy] = True
3008 skip[copy] = True
2994 continue
3009 continue
2995 pstates = matches.get(parent, {}).get(copy or fn, [])
3010 pstates = matches.get(parent, {}).get(copy or fn, [])
2996 if pstates or states:
3011 if pstates or states:
2997 r = display(fn, ctx, pstates, states)
3012 r = display(fn, ctx, pstates, states)
2998 found = found or r
3013 found = found or r
2999 if r and not opts.get('all'):
3014 if r and not opts.get('all'):
3000 skip[fn] = True
3015 skip[fn] = True
3001 if copy:
3016 if copy:
3002 skip[copy] = True
3017 skip[copy] = True
3003 del matches[rev]
3018 del matches[rev]
3004 del revfiles[rev]
3019 del revfiles[rev]
3005
3020
3006 return not found
3021 return not found
3007
3022
3008 @command('heads',
3023 @command('heads',
3009 [('r', 'rev', '',
3024 [('r', 'rev', '',
3010 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3025 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3011 ('t', 'topo', False, _('show topological heads only')),
3026 ('t', 'topo', False, _('show topological heads only')),
3012 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3027 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3013 ('c', 'closed', False, _('show normal and closed branch heads')),
3028 ('c', 'closed', False, _('show normal and closed branch heads')),
3014 ] + templateopts,
3029 ] + templateopts,
3015 _('[-ct] [-r STARTREV] [REV]...'))
3030 _('[-ct] [-r STARTREV] [REV]...'))
3016 def heads(ui, repo, *branchrevs, **opts):
3031 def heads(ui, repo, *branchrevs, **opts):
3017 """show current repository heads or show branch heads
3032 """show current repository heads or show branch heads
3018
3033
3019 With no arguments, show all repository branch heads.
3034 With no arguments, show all repository branch heads.
3020
3035
3021 Repository "heads" are changesets with no child changesets. They are
3036 Repository "heads" are changesets with no child changesets. They are
3022 where development generally takes place and are the usual targets
3037 where development generally takes place and are the usual targets
3023 for update and merge operations. Branch heads are changesets that have
3038 for update and merge operations. Branch heads are changesets that have
3024 no child changeset on the same branch.
3039 no child changeset on the same branch.
3025
3040
3026 If one or more REVs are given, only branch heads on the branches
3041 If one or more REVs are given, only branch heads on the branches
3027 associated with the specified changesets are shown. This means
3042 associated with the specified changesets are shown. This means
3028 that you can use :hg:`heads foo` to see the heads on a branch
3043 that you can use :hg:`heads foo` to see the heads on a branch
3029 named ``foo``.
3044 named ``foo``.
3030
3045
3031 If -c/--closed is specified, also show branch heads marked closed
3046 If -c/--closed is specified, also show branch heads marked closed
3032 (see :hg:`commit --close-branch`).
3047 (see :hg:`commit --close-branch`).
3033
3048
3034 If STARTREV is specified, only those heads that are descendants of
3049 If STARTREV is specified, only those heads that are descendants of
3035 STARTREV will be displayed.
3050 STARTREV will be displayed.
3036
3051
3037 If -t/--topo is specified, named branch mechanics will be ignored and only
3052 If -t/--topo is specified, named branch mechanics will be ignored and only
3038 changesets without children will be shown.
3053 changesets without children will be shown.
3039
3054
3040 Returns 0 if matching heads are found, 1 if not.
3055 Returns 0 if matching heads are found, 1 if not.
3041 """
3056 """
3042
3057
3043 start = None
3058 start = None
3044 if 'rev' in opts:
3059 if 'rev' in opts:
3045 start = scmutil.revsingle(repo, opts['rev'], None).node()
3060 start = scmutil.revsingle(repo, opts['rev'], None).node()
3046
3061
3047 if opts.get('topo'):
3062 if opts.get('topo'):
3048 heads = [repo[h] for h in repo.heads(start)]
3063 heads = [repo[h] for h in repo.heads(start)]
3049 else:
3064 else:
3050 heads = []
3065 heads = []
3051 for branch in repo.branchmap():
3066 for branch in repo.branchmap():
3052 heads += repo.branchheads(branch, start, opts.get('closed'))
3067 heads += repo.branchheads(branch, start, opts.get('closed'))
3053 heads = [repo[h] for h in heads]
3068 heads = [repo[h] for h in heads]
3054
3069
3055 if branchrevs:
3070 if branchrevs:
3056 branches = set(repo[br].branch() for br in branchrevs)
3071 branches = set(repo[br].branch() for br in branchrevs)
3057 heads = [h for h in heads if h.branch() in branches]
3072 heads = [h for h in heads if h.branch() in branches]
3058
3073
3059 if opts.get('active') and branchrevs:
3074 if opts.get('active') and branchrevs:
3060 dagheads = repo.heads(start)
3075 dagheads = repo.heads(start)
3061 heads = [h for h in heads if h.node() in dagheads]
3076 heads = [h for h in heads if h.node() in dagheads]
3062
3077
3063 if branchrevs:
3078 if branchrevs:
3064 haveheads = set(h.branch() for h in heads)
3079 haveheads = set(h.branch() for h in heads)
3065 if branches - haveheads:
3080 if branches - haveheads:
3066 headless = ', '.join(b for b in branches - haveheads)
3081 headless = ', '.join(b for b in branches - haveheads)
3067 msg = _('no open branch heads found on branches %s')
3082 msg = _('no open branch heads found on branches %s')
3068 if opts.get('rev'):
3083 if opts.get('rev'):
3069 msg += _(' (started at %s)') % opts['rev']
3084 msg += _(' (started at %s)') % opts['rev']
3070 ui.warn((msg + '\n') % headless)
3085 ui.warn((msg + '\n') % headless)
3071
3086
3072 if not heads:
3087 if not heads:
3073 return 1
3088 return 1
3074
3089
3075 heads = sorted(heads, key=lambda x: -x.rev())
3090 heads = sorted(heads, key=lambda x: -x.rev())
3076 displayer = cmdutil.show_changeset(ui, repo, opts)
3091 displayer = cmdutil.show_changeset(ui, repo, opts)
3077 for ctx in heads:
3092 for ctx in heads:
3078 displayer.show(ctx)
3093 displayer.show(ctx)
3079 displayer.close()
3094 displayer.close()
3080
3095
3081 @command('help',
3096 @command('help',
3082 [('e', 'extension', None, _('show only help for extensions')),
3097 [('e', 'extension', None, _('show only help for extensions')),
3083 ('c', 'command', None, _('show only help for commands')),
3098 ('c', 'command', None, _('show only help for commands')),
3084 ('k', 'keyword', '', _('show topics matching keyword')),
3099 ('k', 'keyword', '', _('show topics matching keyword')),
3085 ],
3100 ],
3086 _('[-ec] [TOPIC]'))
3101 _('[-ec] [TOPIC]'))
3087 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3102 def help_(ui, name=None, unknowncmd=False, full=True, **opts):
3088 """show help for a given topic or a help overview
3103 """show help for a given topic or a help overview
3089
3104
3090 With no arguments, print a list of commands with short help messages.
3105 With no arguments, print a list of commands with short help messages.
3091
3106
3092 Given a topic, extension, or command name, print help for that
3107 Given a topic, extension, or command name, print help for that
3093 topic.
3108 topic.
3094
3109
3095 Returns 0 if successful.
3110 Returns 0 if successful.
3096 """
3111 """
3097
3112
3098 textwidth = min(ui.termwidth(), 80) - 2
3113 textwidth = min(ui.termwidth(), 80) - 2
3099
3114
3100 def helpcmd(name):
3115 def helpcmd(name):
3101 try:
3116 try:
3102 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3117 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
3103 except error.AmbiguousCommand, inst:
3118 except error.AmbiguousCommand, inst:
3104 # py3k fix: except vars can't be used outside the scope of the
3119 # py3k fix: except vars can't be used outside the scope of the
3105 # except block, nor can be used inside a lambda. python issue4617
3120 # except block, nor can be used inside a lambda. python issue4617
3106 prefix = inst.args[0]
3121 prefix = inst.args[0]
3107 select = lambda c: c.lstrip('^').startswith(prefix)
3122 select = lambda c: c.lstrip('^').startswith(prefix)
3108 rst = helplist(select)
3123 rst = helplist(select)
3109 return rst
3124 return rst
3110
3125
3111 rst = []
3126 rst = []
3112
3127
3113 # check if it's an invalid alias and display its error if it is
3128 # check if it's an invalid alias and display its error if it is
3114 if getattr(entry[0], 'badalias', False):
3129 if getattr(entry[0], 'badalias', False):
3115 if not unknowncmd:
3130 if not unknowncmd:
3116 ui.pushbuffer()
3131 ui.pushbuffer()
3117 entry[0](ui)
3132 entry[0](ui)
3118 rst.append(ui.popbuffer())
3133 rst.append(ui.popbuffer())
3119 return rst
3134 return rst
3120
3135
3121 # synopsis
3136 # synopsis
3122 if len(entry) > 2:
3137 if len(entry) > 2:
3123 if entry[2].startswith('hg'):
3138 if entry[2].startswith('hg'):
3124 rst.append("%s\n" % entry[2])
3139 rst.append("%s\n" % entry[2])
3125 else:
3140 else:
3126 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3141 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
3127 else:
3142 else:
3128 rst.append('hg %s\n' % aliases[0])
3143 rst.append('hg %s\n' % aliases[0])
3129 # aliases
3144 # aliases
3130 if full and not ui.quiet and len(aliases) > 1:
3145 if full and not ui.quiet and len(aliases) > 1:
3131 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3146 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
3132 rst.append('\n')
3147 rst.append('\n')
3133
3148
3134 # description
3149 # description
3135 doc = gettext(entry[0].__doc__)
3150 doc = gettext(entry[0].__doc__)
3136 if not doc:
3151 if not doc:
3137 doc = _("(no help text available)")
3152 doc = _("(no help text available)")
3138 if util.safehasattr(entry[0], 'definition'): # aliased command
3153 if util.safehasattr(entry[0], 'definition'): # aliased command
3139 if entry[0].definition.startswith('!'): # shell alias
3154 if entry[0].definition.startswith('!'): # shell alias
3140 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3155 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
3141 else:
3156 else:
3142 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3157 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
3143 doc = doc.splitlines(True)
3158 doc = doc.splitlines(True)
3144 if ui.quiet or not full:
3159 if ui.quiet or not full:
3145 rst.append(doc[0])
3160 rst.append(doc[0])
3146 else:
3161 else:
3147 rst.extend(doc)
3162 rst.extend(doc)
3148 rst.append('\n')
3163 rst.append('\n')
3149
3164
3150 # check if this command shadows a non-trivial (multi-line)
3165 # check if this command shadows a non-trivial (multi-line)
3151 # extension help text
3166 # extension help text
3152 try:
3167 try:
3153 mod = extensions.find(name)
3168 mod = extensions.find(name)
3154 doc = gettext(mod.__doc__) or ''
3169 doc = gettext(mod.__doc__) or ''
3155 if '\n' in doc.strip():
3170 if '\n' in doc.strip():
3156 msg = _('use "hg help -e %s" to show help for '
3171 msg = _('use "hg help -e %s" to show help for '
3157 'the %s extension') % (name, name)
3172 'the %s extension') % (name, name)
3158 rst.append('\n%s\n' % msg)
3173 rst.append('\n%s\n' % msg)
3159 except KeyError:
3174 except KeyError:
3160 pass
3175 pass
3161
3176
3162 # options
3177 # options
3163 if not ui.quiet and entry[1]:
3178 if not ui.quiet and entry[1]:
3164 rst.append('\n%s\n\n' % _("options:"))
3179 rst.append('\n%s\n\n' % _("options:"))
3165 rst.append(help.optrst(entry[1], ui.verbose))
3180 rst.append(help.optrst(entry[1], ui.verbose))
3166
3181
3167 if ui.verbose:
3182 if ui.verbose:
3168 rst.append('\n%s\n\n' % _("global options:"))
3183 rst.append('\n%s\n\n' % _("global options:"))
3169 rst.append(help.optrst(globalopts, ui.verbose))
3184 rst.append(help.optrst(globalopts, ui.verbose))
3170
3185
3171 if not ui.verbose:
3186 if not ui.verbose:
3172 if not full:
3187 if not full:
3173 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3188 rst.append(_('\nuse "hg help %s" to show the full help text\n')
3174 % name)
3189 % name)
3175 elif not ui.quiet:
3190 elif not ui.quiet:
3176 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3191 rst.append(_('\nuse "hg -v help %s" to show more info\n')
3177 % name)
3192 % name)
3178 return rst
3193 return rst
3179
3194
3180
3195
3181 def helplist(select=None):
3196 def helplist(select=None):
3182 # list of commands
3197 # list of commands
3183 if name == "shortlist":
3198 if name == "shortlist":
3184 header = _('basic commands:\n\n')
3199 header = _('basic commands:\n\n')
3185 else:
3200 else:
3186 header = _('list of commands:\n\n')
3201 header = _('list of commands:\n\n')
3187
3202
3188 h = {}
3203 h = {}
3189 cmds = {}
3204 cmds = {}
3190 for c, e in table.iteritems():
3205 for c, e in table.iteritems():
3191 f = c.split("|", 1)[0]
3206 f = c.split("|", 1)[0]
3192 if select and not select(f):
3207 if select and not select(f):
3193 continue
3208 continue
3194 if (not select and name != 'shortlist' and
3209 if (not select and name != 'shortlist' and
3195 e[0].__module__ != __name__):
3210 e[0].__module__ != __name__):
3196 continue
3211 continue
3197 if name == "shortlist" and not f.startswith("^"):
3212 if name == "shortlist" and not f.startswith("^"):
3198 continue
3213 continue
3199 f = f.lstrip("^")
3214 f = f.lstrip("^")
3200 if not ui.debugflag and f.startswith("debug"):
3215 if not ui.debugflag and f.startswith("debug"):
3201 continue
3216 continue
3202 doc = e[0].__doc__
3217 doc = e[0].__doc__
3203 if doc and 'DEPRECATED' in doc and not ui.verbose:
3218 if doc and 'DEPRECATED' in doc and not ui.verbose:
3204 continue
3219 continue
3205 doc = gettext(doc)
3220 doc = gettext(doc)
3206 if not doc:
3221 if not doc:
3207 doc = _("(no help text available)")
3222 doc = _("(no help text available)")
3208 h[f] = doc.splitlines()[0].rstrip()
3223 h[f] = doc.splitlines()[0].rstrip()
3209 cmds[f] = c.lstrip("^")
3224 cmds[f] = c.lstrip("^")
3210
3225
3211 rst = []
3226 rst = []
3212 if not h:
3227 if not h:
3213 if not ui.quiet:
3228 if not ui.quiet:
3214 rst.append(_('no commands defined\n'))
3229 rst.append(_('no commands defined\n'))
3215 return rst
3230 return rst
3216
3231
3217 if not ui.quiet:
3232 if not ui.quiet:
3218 rst.append(header)
3233 rst.append(header)
3219 fns = sorted(h)
3234 fns = sorted(h)
3220 for f in fns:
3235 for f in fns:
3221 if ui.verbose:
3236 if ui.verbose:
3222 commands = cmds[f].replace("|",", ")
3237 commands = cmds[f].replace("|",", ")
3223 rst.append(" :%s: %s\n" % (commands, h[f]))
3238 rst.append(" :%s: %s\n" % (commands, h[f]))
3224 else:
3239 else:
3225 rst.append(' :%s: %s\n' % (f, h[f]))
3240 rst.append(' :%s: %s\n' % (f, h[f]))
3226
3241
3227 if not name:
3242 if not name:
3228 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3243 exts = help.listexts(_('enabled extensions:'), extensions.enabled())
3229 if exts:
3244 if exts:
3230 rst.append('\n')
3245 rst.append('\n')
3231 rst.extend(exts)
3246 rst.extend(exts)
3232
3247
3233 rst.append(_("\nadditional help topics:\n\n"))
3248 rst.append(_("\nadditional help topics:\n\n"))
3234 topics = []
3249 topics = []
3235 for names, header, doc in help.helptable:
3250 for names, header, doc in help.helptable:
3236 topics.append((sorted(names, key=len, reverse=True)[0], header))
3251 topics.append((sorted(names, key=len, reverse=True)[0], header))
3237 for t, desc in topics:
3252 for t, desc in topics:
3238 rst.append(" :%s: %s\n" % (t, desc))
3253 rst.append(" :%s: %s\n" % (t, desc))
3239
3254
3240 optlist = []
3255 optlist = []
3241 if not ui.quiet:
3256 if not ui.quiet:
3242 if ui.verbose:
3257 if ui.verbose:
3243 optlist.append((_("global options:"), globalopts))
3258 optlist.append((_("global options:"), globalopts))
3244 if name == 'shortlist':
3259 if name == 'shortlist':
3245 optlist.append((_('use "hg help" for the full list '
3260 optlist.append((_('use "hg help" for the full list '
3246 'of commands'), ()))
3261 'of commands'), ()))
3247 else:
3262 else:
3248 if name == 'shortlist':
3263 if name == 'shortlist':
3249 msg = _('use "hg help" for the full list of commands '
3264 msg = _('use "hg help" for the full list of commands '
3250 'or "hg -v" for details')
3265 'or "hg -v" for details')
3251 elif name and not full:
3266 elif name and not full:
3252 msg = _('use "hg help %s" to show the full help '
3267 msg = _('use "hg help %s" to show the full help '
3253 'text') % name
3268 'text') % name
3254 else:
3269 else:
3255 msg = _('use "hg -v help%s" to show builtin aliases and '
3270 msg = _('use "hg -v help%s" to show builtin aliases and '
3256 'global options') % (name and " " + name or "")
3271 'global options') % (name and " " + name or "")
3257 optlist.append((msg, ()))
3272 optlist.append((msg, ()))
3258
3273
3259 if optlist:
3274 if optlist:
3260 for title, options in optlist:
3275 for title, options in optlist:
3261 rst.append('\n%s\n' % title)
3276 rst.append('\n%s\n' % title)
3262 if options:
3277 if options:
3263 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3278 rst.append('\n%s\n' % help.optrst(options, ui.verbose))
3264 return rst
3279 return rst
3265
3280
3266 def helptopic(name):
3281 def helptopic(name):
3267 for names, header, doc in help.helptable:
3282 for names, header, doc in help.helptable:
3268 if name in names:
3283 if name in names:
3269 break
3284 break
3270 else:
3285 else:
3271 raise error.UnknownCommand(name)
3286 raise error.UnknownCommand(name)
3272
3287
3273 rst = ["%s\n\n" % header]
3288 rst = ["%s\n\n" % header]
3274 # description
3289 # description
3275 if not doc:
3290 if not doc:
3276 rst.append(" %s\n" % _("(no help text available)"))
3291 rst.append(" %s\n" % _("(no help text available)"))
3277 if util.safehasattr(doc, '__call__'):
3292 if util.safehasattr(doc, '__call__'):
3278 rst += [" %s\n" % l for l in doc().splitlines()]
3293 rst += [" %s\n" % l for l in doc().splitlines()]
3279
3294
3280 try:
3295 try:
3281 cmdutil.findcmd(name, table)
3296 cmdutil.findcmd(name, table)
3282 rst.append(_('\nuse "hg help -c %s" to see help for '
3297 rst.append(_('\nuse "hg help -c %s" to see help for '
3283 'the %s command\n') % (name, name))
3298 'the %s command\n') % (name, name))
3284 except error.UnknownCommand:
3299 except error.UnknownCommand:
3285 pass
3300 pass
3286 return rst
3301 return rst
3287
3302
3288 def helpext(name):
3303 def helpext(name):
3289 try:
3304 try:
3290 mod = extensions.find(name)
3305 mod = extensions.find(name)
3291 doc = gettext(mod.__doc__) or _('no help text available')
3306 doc = gettext(mod.__doc__) or _('no help text available')
3292 except KeyError:
3307 except KeyError:
3293 mod = None
3308 mod = None
3294 doc = extensions.disabledext(name)
3309 doc = extensions.disabledext(name)
3295 if not doc:
3310 if not doc:
3296 raise error.UnknownCommand(name)
3311 raise error.UnknownCommand(name)
3297
3312
3298 if '\n' not in doc:
3313 if '\n' not in doc:
3299 head, tail = doc, ""
3314 head, tail = doc, ""
3300 else:
3315 else:
3301 head, tail = doc.split('\n', 1)
3316 head, tail = doc.split('\n', 1)
3302 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3317 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
3303 if tail:
3318 if tail:
3304 rst.extend(tail.splitlines(True))
3319 rst.extend(tail.splitlines(True))
3305 rst.append('\n')
3320 rst.append('\n')
3306
3321
3307 if mod:
3322 if mod:
3308 try:
3323 try:
3309 ct = mod.cmdtable
3324 ct = mod.cmdtable
3310 except AttributeError:
3325 except AttributeError:
3311 ct = {}
3326 ct = {}
3312 modcmds = set([c.split('|', 1)[0] for c in ct])
3327 modcmds = set([c.split('|', 1)[0] for c in ct])
3313 rst.extend(helplist(modcmds.__contains__))
3328 rst.extend(helplist(modcmds.__contains__))
3314 else:
3329 else:
3315 rst.append(_('use "hg help extensions" for information on enabling '
3330 rst.append(_('use "hg help extensions" for information on enabling '
3316 'extensions\n'))
3331 'extensions\n'))
3317 return rst
3332 return rst
3318
3333
3319 def helpextcmd(name):
3334 def helpextcmd(name):
3320 cmd, ext, mod = extensions.disabledcmd(ui, name,
3335 cmd, ext, mod = extensions.disabledcmd(ui, name,
3321 ui.configbool('ui', 'strict'))
3336 ui.configbool('ui', 'strict'))
3322 doc = gettext(mod.__doc__).splitlines()[0]
3337 doc = gettext(mod.__doc__).splitlines()[0]
3323
3338
3324 rst = help.listexts(_("'%s' is provided by the following "
3339 rst = help.listexts(_("'%s' is provided by the following "
3325 "extension:") % cmd, {ext: doc}, indent=4)
3340 "extension:") % cmd, {ext: doc}, indent=4)
3326 rst.append('\n')
3341 rst.append('\n')
3327 rst.append(_('use "hg help extensions" for information on enabling '
3342 rst.append(_('use "hg help extensions" for information on enabling '
3328 'extensions\n'))
3343 'extensions\n'))
3329 return rst
3344 return rst
3330
3345
3331
3346
3332 rst = []
3347 rst = []
3333 kw = opts.get('keyword')
3348 kw = opts.get('keyword')
3334 if kw:
3349 if kw:
3335 matches = help.topicmatch(kw)
3350 matches = help.topicmatch(kw)
3336 for t, title in (('topics', _('Topics')),
3351 for t, title in (('topics', _('Topics')),
3337 ('commands', _('Commands')),
3352 ('commands', _('Commands')),
3338 ('extensions', _('Extensions')),
3353 ('extensions', _('Extensions')),
3339 ('extensioncommands', _('Extension Commands'))):
3354 ('extensioncommands', _('Extension Commands'))):
3340 if matches[t]:
3355 if matches[t]:
3341 rst.append('%s:\n\n' % title)
3356 rst.append('%s:\n\n' % title)
3342 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3357 rst.extend(minirst.maketable(sorted(matches[t]), 1))
3343 rst.append('\n')
3358 rst.append('\n')
3344 elif name and name != 'shortlist':
3359 elif name and name != 'shortlist':
3345 i = None
3360 i = None
3346 if unknowncmd:
3361 if unknowncmd:
3347 queries = (helpextcmd,)
3362 queries = (helpextcmd,)
3348 elif opts.get('extension'):
3363 elif opts.get('extension'):
3349 queries = (helpext,)
3364 queries = (helpext,)
3350 elif opts.get('command'):
3365 elif opts.get('command'):
3351 queries = (helpcmd,)
3366 queries = (helpcmd,)
3352 else:
3367 else:
3353 queries = (helptopic, helpcmd, helpext, helpextcmd)
3368 queries = (helptopic, helpcmd, helpext, helpextcmd)
3354 for f in queries:
3369 for f in queries:
3355 try:
3370 try:
3356 rst = f(name)
3371 rst = f(name)
3357 i = None
3372 i = None
3358 break
3373 break
3359 except error.UnknownCommand, inst:
3374 except error.UnknownCommand, inst:
3360 i = inst
3375 i = inst
3361 if i:
3376 if i:
3362 raise i
3377 raise i
3363 else:
3378 else:
3364 # program name
3379 # program name
3365 if not ui.quiet:
3380 if not ui.quiet:
3366 rst = [_("Mercurial Distributed SCM\n"), '\n']
3381 rst = [_("Mercurial Distributed SCM\n"), '\n']
3367 rst.extend(helplist())
3382 rst.extend(helplist())
3368
3383
3369 keep = ui.verbose and ['verbose'] or []
3384 keep = ui.verbose and ['verbose'] or []
3370 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3385 formatted, pruned = minirst.format(''.join(rst), textwidth, keep=keep)
3371 ui.write(formatted)
3386 ui.write(formatted)
3372
3387
3373
3388
3374 @command('identify|id',
3389 @command('identify|id',
3375 [('r', 'rev', '',
3390 [('r', 'rev', '',
3376 _('identify the specified revision'), _('REV')),
3391 _('identify the specified revision'), _('REV')),
3377 ('n', 'num', None, _('show local revision number')),
3392 ('n', 'num', None, _('show local revision number')),
3378 ('i', 'id', None, _('show global revision id')),
3393 ('i', 'id', None, _('show global revision id')),
3379 ('b', 'branch', None, _('show branch')),
3394 ('b', 'branch', None, _('show branch')),
3380 ('t', 'tags', None, _('show tags')),
3395 ('t', 'tags', None, _('show tags')),
3381 ('B', 'bookmarks', None, _('show bookmarks')),
3396 ('B', 'bookmarks', None, _('show bookmarks')),
3382 ] + remoteopts,
3397 ] + remoteopts,
3383 _('[-nibtB] [-r REV] [SOURCE]'))
3398 _('[-nibtB] [-r REV] [SOURCE]'))
3384 def identify(ui, repo, source=None, rev=None,
3399 def identify(ui, repo, source=None, rev=None,
3385 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3400 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3386 """identify the working copy or specified revision
3401 """identify the working copy or specified revision
3387
3402
3388 Print a summary identifying the repository state at REV using one or
3403 Print a summary identifying the repository state at REV using one or
3389 two parent hash identifiers, followed by a "+" if the working
3404 two parent hash identifiers, followed by a "+" if the working
3390 directory has uncommitted changes, the branch name (if not default),
3405 directory has uncommitted changes, the branch name (if not default),
3391 a list of tags, and a list of bookmarks.
3406 a list of tags, and a list of bookmarks.
3392
3407
3393 When REV is not given, print a summary of the current state of the
3408 When REV is not given, print a summary of the current state of the
3394 repository.
3409 repository.
3395
3410
3396 Specifying a path to a repository root or Mercurial bundle will
3411 Specifying a path to a repository root or Mercurial bundle will
3397 cause lookup to operate on that repository/bundle.
3412 cause lookup to operate on that repository/bundle.
3398
3413
3399 .. container:: verbose
3414 .. container:: verbose
3400
3415
3401 Examples:
3416 Examples:
3402
3417
3403 - generate a build identifier for the working directory::
3418 - generate a build identifier for the working directory::
3404
3419
3405 hg id --id > build-id.dat
3420 hg id --id > build-id.dat
3406
3421
3407 - find the revision corresponding to a tag::
3422 - find the revision corresponding to a tag::
3408
3423
3409 hg id -n -r 1.3
3424 hg id -n -r 1.3
3410
3425
3411 - check the most recent revision of a remote repository::
3426 - check the most recent revision of a remote repository::
3412
3427
3413 hg id -r tip http://selenic.com/hg/
3428 hg id -r tip http://selenic.com/hg/
3414
3429
3415 Returns 0 if successful.
3430 Returns 0 if successful.
3416 """
3431 """
3417
3432
3418 if not repo and not source:
3433 if not repo and not source:
3419 raise util.Abort(_("there is no Mercurial repository here "
3434 raise util.Abort(_("there is no Mercurial repository here "
3420 "(.hg not found)"))
3435 "(.hg not found)"))
3421
3436
3422 hexfunc = ui.debugflag and hex or short
3437 hexfunc = ui.debugflag and hex or short
3423 default = not (num or id or branch or tags or bookmarks)
3438 default = not (num or id or branch or tags or bookmarks)
3424 output = []
3439 output = []
3425 revs = []
3440 revs = []
3426
3441
3427 if source:
3442 if source:
3428 source, branches = hg.parseurl(ui.expandpath(source))
3443 source, branches = hg.parseurl(ui.expandpath(source))
3429 repo = hg.peer(ui, opts, source)
3444 repo = hg.peer(ui, opts, source)
3430 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3445 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3431
3446
3432 if not repo.local():
3447 if not repo.local():
3433 if num or branch or tags:
3448 if num or branch or tags:
3434 raise util.Abort(
3449 raise util.Abort(
3435 _("can't query remote revision number, branch, or tags"))
3450 _("can't query remote revision number, branch, or tags"))
3436 if not rev and revs:
3451 if not rev and revs:
3437 rev = revs[0]
3452 rev = revs[0]
3438 if not rev:
3453 if not rev:
3439 rev = "tip"
3454 rev = "tip"
3440
3455
3441 remoterev = repo.lookup(rev)
3456 remoterev = repo.lookup(rev)
3442 if default or id:
3457 if default or id:
3443 output = [hexfunc(remoterev)]
3458 output = [hexfunc(remoterev)]
3444
3459
3445 def getbms():
3460 def getbms():
3446 bms = []
3461 bms = []
3447
3462
3448 if 'bookmarks' in repo.listkeys('namespaces'):
3463 if 'bookmarks' in repo.listkeys('namespaces'):
3449 hexremoterev = hex(remoterev)
3464 hexremoterev = hex(remoterev)
3450 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3465 bms = [bm for bm, bmr in repo.listkeys('bookmarks').iteritems()
3451 if bmr == hexremoterev]
3466 if bmr == hexremoterev]
3452
3467
3453 return bms
3468 return bms
3454
3469
3455 if bookmarks:
3470 if bookmarks:
3456 output.extend(getbms())
3471 output.extend(getbms())
3457 elif default and not ui.quiet:
3472 elif default and not ui.quiet:
3458 # multiple bookmarks for a single parent separated by '/'
3473 # multiple bookmarks for a single parent separated by '/'
3459 bm = '/'.join(getbms())
3474 bm = '/'.join(getbms())
3460 if bm:
3475 if bm:
3461 output.append(bm)
3476 output.append(bm)
3462 else:
3477 else:
3463 if not rev:
3478 if not rev:
3464 ctx = repo[None]
3479 ctx = repo[None]
3465 parents = ctx.parents()
3480 parents = ctx.parents()
3466 changed = ""
3481 changed = ""
3467 if default or id or num:
3482 if default or id or num:
3468 changed = util.any(repo.status()) and "+" or ""
3483 changed = util.any(repo.status()) and "+" or ""
3469 if default or id:
3484 if default or id:
3470 output = ["%s%s" %
3485 output = ["%s%s" %
3471 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3486 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3472 if num:
3487 if num:
3473 output.append("%s%s" %
3488 output.append("%s%s" %
3474 ('+'.join([str(p.rev()) for p in parents]), changed))
3489 ('+'.join([str(p.rev()) for p in parents]), changed))
3475 else:
3490 else:
3476 ctx = scmutil.revsingle(repo, rev)
3491 ctx = scmutil.revsingle(repo, rev)
3477 if default or id:
3492 if default or id:
3478 output = [hexfunc(ctx.node())]
3493 output = [hexfunc(ctx.node())]
3479 if num:
3494 if num:
3480 output.append(str(ctx.rev()))
3495 output.append(str(ctx.rev()))
3481
3496
3482 if default and not ui.quiet:
3497 if default and not ui.quiet:
3483 b = ctx.branch()
3498 b = ctx.branch()
3484 if b != 'default':
3499 if b != 'default':
3485 output.append("(%s)" % b)
3500 output.append("(%s)" % b)
3486
3501
3487 # multiple tags for a single parent separated by '/'
3502 # multiple tags for a single parent separated by '/'
3488 t = '/'.join(ctx.tags())
3503 t = '/'.join(ctx.tags())
3489 if t:
3504 if t:
3490 output.append(t)
3505 output.append(t)
3491
3506
3492 # multiple bookmarks for a single parent separated by '/'
3507 # multiple bookmarks for a single parent separated by '/'
3493 bm = '/'.join(ctx.bookmarks())
3508 bm = '/'.join(ctx.bookmarks())
3494 if bm:
3509 if bm:
3495 output.append(bm)
3510 output.append(bm)
3496 else:
3511 else:
3497 if branch:
3512 if branch:
3498 output.append(ctx.branch())
3513 output.append(ctx.branch())
3499
3514
3500 if tags:
3515 if tags:
3501 output.extend(ctx.tags())
3516 output.extend(ctx.tags())
3502
3517
3503 if bookmarks:
3518 if bookmarks:
3504 output.extend(ctx.bookmarks())
3519 output.extend(ctx.bookmarks())
3505
3520
3506 ui.write("%s\n" % ' '.join(output))
3521 ui.write("%s\n" % ' '.join(output))
3507
3522
3508 @command('import|patch',
3523 @command('import|patch',
3509 [('p', 'strip', 1,
3524 [('p', 'strip', 1,
3510 _('directory strip option for patch. This has the same '
3525 _('directory strip option for patch. This has the same '
3511 'meaning as the corresponding patch option'), _('NUM')),
3526 'meaning as the corresponding patch option'), _('NUM')),
3512 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3527 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3513 ('e', 'edit', False, _('invoke editor on commit messages')),
3528 ('e', 'edit', False, _('invoke editor on commit messages')),
3514 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3529 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
3515 ('', 'no-commit', None,
3530 ('', 'no-commit', None,
3516 _("don't commit, just update the working directory")),
3531 _("don't commit, just update the working directory")),
3517 ('', 'bypass', None,
3532 ('', 'bypass', None,
3518 _("apply patch without touching the working directory")),
3533 _("apply patch without touching the working directory")),
3519 ('', 'exact', None,
3534 ('', 'exact', None,
3520 _('apply patch to the nodes from which it was generated')),
3535 _('apply patch to the nodes from which it was generated')),
3521 ('', 'import-branch', None,
3536 ('', 'import-branch', None,
3522 _('use any branch information in patch (implied by --exact)'))] +
3537 _('use any branch information in patch (implied by --exact)'))] +
3523 commitopts + commitopts2 + similarityopts,
3538 commitopts + commitopts2 + similarityopts,
3524 _('[OPTION]... PATCH...'))
3539 _('[OPTION]... PATCH...'))
3525 def import_(ui, repo, patch1=None, *patches, **opts):
3540 def import_(ui, repo, patch1=None, *patches, **opts):
3526 """import an ordered set of patches
3541 """import an ordered set of patches
3527
3542
3528 Import a list of patches and commit them individually (unless
3543 Import a list of patches and commit them individually (unless
3529 --no-commit is specified).
3544 --no-commit is specified).
3530
3545
3531 If there are outstanding changes in the working directory, import
3546 If there are outstanding changes in the working directory, import
3532 will abort unless given the -f/--force flag.
3547 will abort unless given the -f/--force flag.
3533
3548
3534 You can import a patch straight from a mail message. Even patches
3549 You can import a patch straight from a mail message. Even patches
3535 as attachments work (to use the body part, it must have type
3550 as attachments work (to use the body part, it must have type
3536 text/plain or text/x-patch). From and Subject headers of email
3551 text/plain or text/x-patch). From and Subject headers of email
3537 message are used as default committer and commit message. All
3552 message are used as default committer and commit message. All
3538 text/plain body parts before first diff are added to commit
3553 text/plain body parts before first diff are added to commit
3539 message.
3554 message.
3540
3555
3541 If the imported patch was generated by :hg:`export`, user and
3556 If the imported patch was generated by :hg:`export`, user and
3542 description from patch override values from message headers and
3557 description from patch override values from message headers and
3543 body. Values given on command line with -m/--message and -u/--user
3558 body. Values given on command line with -m/--message and -u/--user
3544 override these.
3559 override these.
3545
3560
3546 If --exact is specified, import will set the working directory to
3561 If --exact is specified, import will set the working directory to
3547 the parent of each patch before applying it, and will abort if the
3562 the parent of each patch before applying it, and will abort if the
3548 resulting changeset has a different ID than the one recorded in
3563 resulting changeset has a different ID than the one recorded in
3549 the patch. This may happen due to character set problems or other
3564 the patch. This may happen due to character set problems or other
3550 deficiencies in the text patch format.
3565 deficiencies in the text patch format.
3551
3566
3552 Use --bypass to apply and commit patches directly to the
3567 Use --bypass to apply and commit patches directly to the
3553 repository, not touching the working directory. Without --exact,
3568 repository, not touching the working directory. Without --exact,
3554 patches will be applied on top of the working directory parent
3569 patches will be applied on top of the working directory parent
3555 revision.
3570 revision.
3556
3571
3557 With -s/--similarity, hg will attempt to discover renames and
3572 With -s/--similarity, hg will attempt to discover renames and
3558 copies in the patch in the same way as :hg:`addremove`.
3573 copies in the patch in the same way as :hg:`addremove`.
3559
3574
3560 To read a patch from standard input, use "-" as the patch name. If
3575 To read a patch from standard input, use "-" as the patch name. If
3561 a URL is specified, the patch will be downloaded from it.
3576 a URL is specified, the patch will be downloaded from it.
3562 See :hg:`help dates` for a list of formats valid for -d/--date.
3577 See :hg:`help dates` for a list of formats valid for -d/--date.
3563
3578
3564 .. container:: verbose
3579 .. container:: verbose
3565
3580
3566 Examples:
3581 Examples:
3567
3582
3568 - import a traditional patch from a website and detect renames::
3583 - import a traditional patch from a website and detect renames::
3569
3584
3570 hg import -s 80 http://example.com/bugfix.patch
3585 hg import -s 80 http://example.com/bugfix.patch
3571
3586
3572 - import a changeset from an hgweb server::
3587 - import a changeset from an hgweb server::
3573
3588
3574 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3589 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3575
3590
3576 - import all the patches in an Unix-style mbox::
3591 - import all the patches in an Unix-style mbox::
3577
3592
3578 hg import incoming-patches.mbox
3593 hg import incoming-patches.mbox
3579
3594
3580 - attempt to exactly restore an exported changeset (not always
3595 - attempt to exactly restore an exported changeset (not always
3581 possible)::
3596 possible)::
3582
3597
3583 hg import --exact proposed-fix.patch
3598 hg import --exact proposed-fix.patch
3584
3599
3585 Returns 0 on success.
3600 Returns 0 on success.
3586 """
3601 """
3587
3602
3588 if not patch1:
3603 if not patch1:
3589 raise util.Abort(_('need at least one patch to import'))
3604 raise util.Abort(_('need at least one patch to import'))
3590
3605
3591 patches = (patch1,) + patches
3606 patches = (patch1,) + patches
3592
3607
3593 date = opts.get('date')
3608 date = opts.get('date')
3594 if date:
3609 if date:
3595 opts['date'] = util.parsedate(date)
3610 opts['date'] = util.parsedate(date)
3596
3611
3597 editor = cmdutil.commiteditor
3612 editor = cmdutil.commiteditor
3598 if opts.get('edit'):
3613 if opts.get('edit'):
3599 editor = cmdutil.commitforceeditor
3614 editor = cmdutil.commitforceeditor
3600
3615
3601 update = not opts.get('bypass')
3616 update = not opts.get('bypass')
3602 if not update and opts.get('no_commit'):
3617 if not update and opts.get('no_commit'):
3603 raise util.Abort(_('cannot use --no-commit with --bypass'))
3618 raise util.Abort(_('cannot use --no-commit with --bypass'))
3604 try:
3619 try:
3605 sim = float(opts.get('similarity') or 0)
3620 sim = float(opts.get('similarity') or 0)
3606 except ValueError:
3621 except ValueError:
3607 raise util.Abort(_('similarity must be a number'))
3622 raise util.Abort(_('similarity must be a number'))
3608 if sim < 0 or sim > 100:
3623 if sim < 0 or sim > 100:
3609 raise util.Abort(_('similarity must be between 0 and 100'))
3624 raise util.Abort(_('similarity must be between 0 and 100'))
3610 if sim and not update:
3625 if sim and not update:
3611 raise util.Abort(_('cannot use --similarity with --bypass'))
3626 raise util.Abort(_('cannot use --similarity with --bypass'))
3612
3627
3613 if (opts.get('exact') or not opts.get('force')) and update:
3628 if (opts.get('exact') or not opts.get('force')) and update:
3614 cmdutil.bailifchanged(repo)
3629 cmdutil.bailifchanged(repo)
3615
3630
3616 base = opts["base"]
3631 base = opts["base"]
3617 strip = opts["strip"]
3632 strip = opts["strip"]
3618 wlock = lock = tr = None
3633 wlock = lock = tr = None
3619 msgs = []
3634 msgs = []
3620
3635
3621 def checkexact(repo, n, nodeid):
3636 def checkexact(repo, n, nodeid):
3622 if opts.get('exact') and hex(n) != nodeid:
3637 if opts.get('exact') and hex(n) != nodeid:
3623 repo.rollback()
3638 repo.rollback()
3624 raise util.Abort(_('patch is damaged or loses information'))
3639 raise util.Abort(_('patch is damaged or loses information'))
3625
3640
3626 def tryone(ui, hunk, parents):
3641 def tryone(ui, hunk, parents):
3627 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3642 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3628 patch.extract(ui, hunk)
3643 patch.extract(ui, hunk)
3629
3644
3630 if not tmpname:
3645 if not tmpname:
3631 return (None, None)
3646 return (None, None)
3632 msg = _('applied to working directory')
3647 msg = _('applied to working directory')
3633
3648
3634 try:
3649 try:
3635 cmdline_message = cmdutil.logmessage(ui, opts)
3650 cmdline_message = cmdutil.logmessage(ui, opts)
3636 if cmdline_message:
3651 if cmdline_message:
3637 # pickup the cmdline msg
3652 # pickup the cmdline msg
3638 message = cmdline_message
3653 message = cmdline_message
3639 elif message:
3654 elif message:
3640 # pickup the patch msg
3655 # pickup the patch msg
3641 message = message.strip()
3656 message = message.strip()
3642 else:
3657 else:
3643 # launch the editor
3658 # launch the editor
3644 message = None
3659 message = None
3645 ui.debug('message:\n%s\n' % message)
3660 ui.debug('message:\n%s\n' % message)
3646
3661
3647 if len(parents) == 1:
3662 if len(parents) == 1:
3648 parents.append(repo[nullid])
3663 parents.append(repo[nullid])
3649 if opts.get('exact'):
3664 if opts.get('exact'):
3650 if not nodeid or not p1:
3665 if not nodeid or not p1:
3651 raise util.Abort(_('not a Mercurial patch'))
3666 raise util.Abort(_('not a Mercurial patch'))
3652 p1 = repo[p1]
3667 p1 = repo[p1]
3653 p2 = repo[p2 or nullid]
3668 p2 = repo[p2 or nullid]
3654 elif p2:
3669 elif p2:
3655 try:
3670 try:
3656 p1 = repo[p1]
3671 p1 = repo[p1]
3657 p2 = repo[p2]
3672 p2 = repo[p2]
3658 # Without any options, consider p2 only if the
3673 # Without any options, consider p2 only if the
3659 # patch is being applied on top of the recorded
3674 # patch is being applied on top of the recorded
3660 # first parent.
3675 # first parent.
3661 if p1 != parents[0]:
3676 if p1 != parents[0]:
3662 p1 = parents[0]
3677 p1 = parents[0]
3663 p2 = repo[nullid]
3678 p2 = repo[nullid]
3664 except error.RepoError:
3679 except error.RepoError:
3665 p1, p2 = parents
3680 p1, p2 = parents
3666 else:
3681 else:
3667 p1, p2 = parents
3682 p1, p2 = parents
3668
3683
3669 n = None
3684 n = None
3670 if update:
3685 if update:
3671 if p1 != parents[0]:
3686 if p1 != parents[0]:
3672 hg.clean(repo, p1.node())
3687 hg.clean(repo, p1.node())
3673 if p2 != parents[1]:
3688 if p2 != parents[1]:
3674 repo.setparents(p1.node(), p2.node())
3689 repo.setparents(p1.node(), p2.node())
3675
3690
3676 if opts.get('exact') or opts.get('import_branch'):
3691 if opts.get('exact') or opts.get('import_branch'):
3677 repo.dirstate.setbranch(branch or 'default')
3692 repo.dirstate.setbranch(branch or 'default')
3678
3693
3679 files = set()
3694 files = set()
3680 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3695 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3681 eolmode=None, similarity=sim / 100.0)
3696 eolmode=None, similarity=sim / 100.0)
3682 files = list(files)
3697 files = list(files)
3683 if opts.get('no_commit'):
3698 if opts.get('no_commit'):
3684 if message:
3699 if message:
3685 msgs.append(message)
3700 msgs.append(message)
3686 else:
3701 else:
3687 if opts.get('exact') or p2:
3702 if opts.get('exact') or p2:
3688 # If you got here, you either use --force and know what
3703 # If you got here, you either use --force and know what
3689 # you are doing or used --exact or a merge patch while
3704 # you are doing or used --exact or a merge patch while
3690 # being updated to its first parent.
3705 # being updated to its first parent.
3691 m = None
3706 m = None
3692 else:
3707 else:
3693 m = scmutil.matchfiles(repo, files or [])
3708 m = scmutil.matchfiles(repo, files or [])
3694 n = repo.commit(message, opts.get('user') or user,
3709 n = repo.commit(message, opts.get('user') or user,
3695 opts.get('date') or date, match=m,
3710 opts.get('date') or date, match=m,
3696 editor=editor)
3711 editor=editor)
3697 checkexact(repo, n, nodeid)
3712 checkexact(repo, n, nodeid)
3698 else:
3713 else:
3699 if opts.get('exact') or opts.get('import_branch'):
3714 if opts.get('exact') or opts.get('import_branch'):
3700 branch = branch or 'default'
3715 branch = branch or 'default'
3701 else:
3716 else:
3702 branch = p1.branch()
3717 branch = p1.branch()
3703 store = patch.filestore()
3718 store = patch.filestore()
3704 try:
3719 try:
3705 files = set()
3720 files = set()
3706 try:
3721 try:
3707 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3722 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3708 files, eolmode=None)
3723 files, eolmode=None)
3709 except patch.PatchError, e:
3724 except patch.PatchError, e:
3710 raise util.Abort(str(e))
3725 raise util.Abort(str(e))
3711 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3726 memctx = patch.makememctx(repo, (p1.node(), p2.node()),
3712 message,
3727 message,
3713 opts.get('user') or user,
3728 opts.get('user') or user,
3714 opts.get('date') or date,
3729 opts.get('date') or date,
3715 branch, files, store,
3730 branch, files, store,
3716 editor=cmdutil.commiteditor)
3731 editor=cmdutil.commiteditor)
3717 repo.savecommitmessage(memctx.description())
3732 repo.savecommitmessage(memctx.description())
3718 n = memctx.commit()
3733 n = memctx.commit()
3719 checkexact(repo, n, nodeid)
3734 checkexact(repo, n, nodeid)
3720 finally:
3735 finally:
3721 store.close()
3736 store.close()
3722 if n:
3737 if n:
3723 # i18n: refers to a short changeset id
3738 # i18n: refers to a short changeset id
3724 msg = _('created %s') % short(n)
3739 msg = _('created %s') % short(n)
3725 return (msg, n)
3740 return (msg, n)
3726 finally:
3741 finally:
3727 os.unlink(tmpname)
3742 os.unlink(tmpname)
3728
3743
3729 try:
3744 try:
3730 try:
3745 try:
3731 wlock = repo.wlock()
3746 wlock = repo.wlock()
3732 if not opts.get('no_commit'):
3747 if not opts.get('no_commit'):
3733 lock = repo.lock()
3748 lock = repo.lock()
3734 tr = repo.transaction('import')
3749 tr = repo.transaction('import')
3735 parents = repo.parents()
3750 parents = repo.parents()
3736 for patchurl in patches:
3751 for patchurl in patches:
3737 if patchurl == '-':
3752 if patchurl == '-':
3738 ui.status(_('applying patch from stdin\n'))
3753 ui.status(_('applying patch from stdin\n'))
3739 patchfile = ui.fin
3754 patchfile = ui.fin
3740 patchurl = 'stdin' # for error message
3755 patchurl = 'stdin' # for error message
3741 else:
3756 else:
3742 patchurl = os.path.join(base, patchurl)
3757 patchurl = os.path.join(base, patchurl)
3743 ui.status(_('applying %s\n') % patchurl)
3758 ui.status(_('applying %s\n') % patchurl)
3744 patchfile = url.open(ui, patchurl)
3759 patchfile = url.open(ui, patchurl)
3745
3760
3746 haspatch = False
3761 haspatch = False
3747 for hunk in patch.split(patchfile):
3762 for hunk in patch.split(patchfile):
3748 (msg, node) = tryone(ui, hunk, parents)
3763 (msg, node) = tryone(ui, hunk, parents)
3749 if msg:
3764 if msg:
3750 haspatch = True
3765 haspatch = True
3751 ui.note(msg + '\n')
3766 ui.note(msg + '\n')
3752 if update or opts.get('exact'):
3767 if update or opts.get('exact'):
3753 parents = repo.parents()
3768 parents = repo.parents()
3754 else:
3769 else:
3755 parents = [repo[node]]
3770 parents = [repo[node]]
3756
3771
3757 if not haspatch:
3772 if not haspatch:
3758 raise util.Abort(_('%s: no diffs found') % patchurl)
3773 raise util.Abort(_('%s: no diffs found') % patchurl)
3759
3774
3760 if tr:
3775 if tr:
3761 tr.close()
3776 tr.close()
3762 if msgs:
3777 if msgs:
3763 repo.savecommitmessage('\n* * *\n'.join(msgs))
3778 repo.savecommitmessage('\n* * *\n'.join(msgs))
3764 except: # re-raises
3779 except: # re-raises
3765 # wlock.release() indirectly calls dirstate.write(): since
3780 # wlock.release() indirectly calls dirstate.write(): since
3766 # we're crashing, we do not want to change the working dir
3781 # we're crashing, we do not want to change the working dir
3767 # parent after all, so make sure it writes nothing
3782 # parent after all, so make sure it writes nothing
3768 repo.dirstate.invalidate()
3783 repo.dirstate.invalidate()
3769 raise
3784 raise
3770 finally:
3785 finally:
3771 if tr:
3786 if tr:
3772 tr.release()
3787 tr.release()
3773 release(lock, wlock)
3788 release(lock, wlock)
3774
3789
3775 @command('incoming|in',
3790 @command('incoming|in',
3776 [('f', 'force', None,
3791 [('f', 'force', None,
3777 _('run even if remote repository is unrelated')),
3792 _('run even if remote repository is unrelated')),
3778 ('n', 'newest-first', None, _('show newest record first')),
3793 ('n', 'newest-first', None, _('show newest record first')),
3779 ('', 'bundle', '',
3794 ('', 'bundle', '',
3780 _('file to store the bundles into'), _('FILE')),
3795 _('file to store the bundles into'), _('FILE')),
3781 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3796 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3782 ('B', 'bookmarks', False, _("compare bookmarks")),
3797 ('B', 'bookmarks', False, _("compare bookmarks")),
3783 ('b', 'branch', [],
3798 ('b', 'branch', [],
3784 _('a specific branch you would like to pull'), _('BRANCH')),
3799 _('a specific branch you would like to pull'), _('BRANCH')),
3785 ] + logopts + remoteopts + subrepoopts,
3800 ] + logopts + remoteopts + subrepoopts,
3786 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3801 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3787 def incoming(ui, repo, source="default", **opts):
3802 def incoming(ui, repo, source="default", **opts):
3788 """show new changesets found in source
3803 """show new changesets found in source
3789
3804
3790 Show new changesets found in the specified path/URL or the default
3805 Show new changesets found in the specified path/URL or the default
3791 pull location. These are the changesets that would have been pulled
3806 pull location. These are the changesets that would have been pulled
3792 if a pull at the time you issued this command.
3807 if a pull at the time you issued this command.
3793
3808
3794 For remote repository, using --bundle avoids downloading the
3809 For remote repository, using --bundle avoids downloading the
3795 changesets twice if the incoming is followed by a pull.
3810 changesets twice if the incoming is followed by a pull.
3796
3811
3797 See pull for valid source format details.
3812 See pull for valid source format details.
3798
3813
3799 Returns 0 if there are incoming changes, 1 otherwise.
3814 Returns 0 if there are incoming changes, 1 otherwise.
3800 """
3815 """
3801 if opts.get('bundle') and opts.get('subrepos'):
3816 if opts.get('bundle') and opts.get('subrepos'):
3802 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3817 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3803
3818
3804 if opts.get('bookmarks'):
3819 if opts.get('bookmarks'):
3805 source, branches = hg.parseurl(ui.expandpath(source),
3820 source, branches = hg.parseurl(ui.expandpath(source),
3806 opts.get('branch'))
3821 opts.get('branch'))
3807 other = hg.peer(repo, opts, source)
3822 other = hg.peer(repo, opts, source)
3808 if 'bookmarks' not in other.listkeys('namespaces'):
3823 if 'bookmarks' not in other.listkeys('namespaces'):
3809 ui.warn(_("remote doesn't support bookmarks\n"))
3824 ui.warn(_("remote doesn't support bookmarks\n"))
3810 return 0
3825 return 0
3811 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3826 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3812 return bookmarks.diff(ui, repo, other)
3827 return bookmarks.diff(ui, repo, other)
3813
3828
3814 repo._subtoppath = ui.expandpath(source)
3829 repo._subtoppath = ui.expandpath(source)
3815 try:
3830 try:
3816 return hg.incoming(ui, repo, source, opts)
3831 return hg.incoming(ui, repo, source, opts)
3817 finally:
3832 finally:
3818 del repo._subtoppath
3833 del repo._subtoppath
3819
3834
3820
3835
3821 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3836 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3822 def init(ui, dest=".", **opts):
3837 def init(ui, dest=".", **opts):
3823 """create a new repository in the given directory
3838 """create a new repository in the given directory
3824
3839
3825 Initialize a new repository in the given directory. If the given
3840 Initialize a new repository in the given directory. If the given
3826 directory does not exist, it will be created.
3841 directory does not exist, it will be created.
3827
3842
3828 If no directory is given, the current directory is used.
3843 If no directory is given, the current directory is used.
3829
3844
3830 It is possible to specify an ``ssh://`` URL as the destination.
3845 It is possible to specify an ``ssh://`` URL as the destination.
3831 See :hg:`help urls` for more information.
3846 See :hg:`help urls` for more information.
3832
3847
3833 Returns 0 on success.
3848 Returns 0 on success.
3834 """
3849 """
3835 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3850 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3836
3851
3837 @command('locate',
3852 @command('locate',
3838 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3853 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3839 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3854 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3840 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3855 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3841 ] + walkopts,
3856 ] + walkopts,
3842 _('[OPTION]... [PATTERN]...'))
3857 _('[OPTION]... [PATTERN]...'))
3843 def locate(ui, repo, *pats, **opts):
3858 def locate(ui, repo, *pats, **opts):
3844 """locate files matching specific patterns
3859 """locate files matching specific patterns
3845
3860
3846 Print files under Mercurial control in the working directory whose
3861 Print files under Mercurial control in the working directory whose
3847 names match the given patterns.
3862 names match the given patterns.
3848
3863
3849 By default, this command searches all directories in the working
3864 By default, this command searches all directories in the working
3850 directory. To search just the current directory and its
3865 directory. To search just the current directory and its
3851 subdirectories, use "--include .".
3866 subdirectories, use "--include .".
3852
3867
3853 If no patterns are given to match, this command prints the names
3868 If no patterns are given to match, this command prints the names
3854 of all files under Mercurial control in the working directory.
3869 of all files under Mercurial control in the working directory.
3855
3870
3856 If you want to feed the output of this command into the "xargs"
3871 If you want to feed the output of this command into the "xargs"
3857 command, use the -0 option to both this command and "xargs". This
3872 command, use the -0 option to both this command and "xargs". This
3858 will avoid the problem of "xargs" treating single filenames that
3873 will avoid the problem of "xargs" treating single filenames that
3859 contain whitespace as multiple filenames.
3874 contain whitespace as multiple filenames.
3860
3875
3861 Returns 0 if a match is found, 1 otherwise.
3876 Returns 0 if a match is found, 1 otherwise.
3862 """
3877 """
3863 end = opts.get('print0') and '\0' or '\n'
3878 end = opts.get('print0') and '\0' or '\n'
3864 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3879 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3865
3880
3866 ret = 1
3881 ret = 1
3867 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3882 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3868 m.bad = lambda x, y: False
3883 m.bad = lambda x, y: False
3869 for abs in repo[rev].walk(m):
3884 for abs in repo[rev].walk(m):
3870 if not rev and abs not in repo.dirstate:
3885 if not rev and abs not in repo.dirstate:
3871 continue
3886 continue
3872 if opts.get('fullpath'):
3887 if opts.get('fullpath'):
3873 ui.write(repo.wjoin(abs), end)
3888 ui.write(repo.wjoin(abs), end)
3874 else:
3889 else:
3875 ui.write(((pats and m.rel(abs)) or abs), end)
3890 ui.write(((pats and m.rel(abs)) or abs), end)
3876 ret = 0
3891 ret = 0
3877
3892
3878 return ret
3893 return ret
3879
3894
3880 @command('^log|history',
3895 @command('^log|history',
3881 [('f', 'follow', None,
3896 [('f', 'follow', None,
3882 _('follow changeset history, or file history across copies and renames')),
3897 _('follow changeset history, or file history across copies and renames')),
3883 ('', 'follow-first', None,
3898 ('', 'follow-first', None,
3884 _('only follow the first parent of merge changesets (DEPRECATED)')),
3899 _('only follow the first parent of merge changesets (DEPRECATED)')),
3885 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3900 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3886 ('C', 'copies', None, _('show copied files')),
3901 ('C', 'copies', None, _('show copied files')),
3887 ('k', 'keyword', [],
3902 ('k', 'keyword', [],
3888 _('do case-insensitive search for a given text'), _('TEXT')),
3903 _('do case-insensitive search for a given text'), _('TEXT')),
3889 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3904 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3890 ('', 'removed', None, _('include revisions where files were removed')),
3905 ('', 'removed', None, _('include revisions where files were removed')),
3891 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3906 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3892 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3907 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3893 ('', 'only-branch', [],
3908 ('', 'only-branch', [],
3894 _('show only changesets within the given named branch (DEPRECATED)'),
3909 _('show only changesets within the given named branch (DEPRECATED)'),
3895 _('BRANCH')),
3910 _('BRANCH')),
3896 ('b', 'branch', [],
3911 ('b', 'branch', [],
3897 _('show changesets within the given named branch'), _('BRANCH')),
3912 _('show changesets within the given named branch'), _('BRANCH')),
3898 ('P', 'prune', [],
3913 ('P', 'prune', [],
3899 _('do not display revision or any of its ancestors'), _('REV')),
3914 _('do not display revision or any of its ancestors'), _('REV')),
3900 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3915 ('', 'hidden', False, _('show hidden changesets (DEPRECATED)')),
3901 ] + logopts + walkopts,
3916 ] + logopts + walkopts,
3902 _('[OPTION]... [FILE]'))
3917 _('[OPTION]... [FILE]'))
3903 def log(ui, repo, *pats, **opts):
3918 def log(ui, repo, *pats, **opts):
3904 """show revision history of entire repository or files
3919 """show revision history of entire repository or files
3905
3920
3906 Print the revision history of the specified files or the entire
3921 Print the revision history of the specified files or the entire
3907 project.
3922 project.
3908
3923
3909 If no revision range is specified, the default is ``tip:0`` unless
3924 If no revision range is specified, the default is ``tip:0`` unless
3910 --follow is set, in which case the working directory parent is
3925 --follow is set, in which case the working directory parent is
3911 used as the starting revision.
3926 used as the starting revision.
3912
3927
3913 File history is shown without following rename or copy history of
3928 File history is shown without following rename or copy history of
3914 files. Use -f/--follow with a filename to follow history across
3929 files. Use -f/--follow with a filename to follow history across
3915 renames and copies. --follow without a filename will only show
3930 renames and copies. --follow without a filename will only show
3916 ancestors or descendants of the starting revision.
3931 ancestors or descendants of the starting revision.
3917
3932
3918 By default this command prints revision number and changeset id,
3933 By default this command prints revision number and changeset id,
3919 tags, non-trivial parents, user, date and time, and a summary for
3934 tags, non-trivial parents, user, date and time, and a summary for
3920 each commit. When the -v/--verbose switch is used, the list of
3935 each commit. When the -v/--verbose switch is used, the list of
3921 changed files and full commit message are shown.
3936 changed files and full commit message are shown.
3922
3937
3923 .. note::
3938 .. note::
3924 log -p/--patch may generate unexpected diff output for merge
3939 log -p/--patch may generate unexpected diff output for merge
3925 changesets, as it will only compare the merge changeset against
3940 changesets, as it will only compare the merge changeset against
3926 its first parent. Also, only files different from BOTH parents
3941 its first parent. Also, only files different from BOTH parents
3927 will appear in files:.
3942 will appear in files:.
3928
3943
3929 .. note::
3944 .. note::
3930 for performance reasons, log FILE may omit duplicate changes
3945 for performance reasons, log FILE may omit duplicate changes
3931 made on branches and will not show deletions. To see all
3946 made on branches and will not show deletions. To see all
3932 changes including duplicates and deletions, use the --removed
3947 changes including duplicates and deletions, use the --removed
3933 switch.
3948 switch.
3934
3949
3935 .. container:: verbose
3950 .. container:: verbose
3936
3951
3937 Some examples:
3952 Some examples:
3938
3953
3939 - changesets with full descriptions and file lists::
3954 - changesets with full descriptions and file lists::
3940
3955
3941 hg log -v
3956 hg log -v
3942
3957
3943 - changesets ancestral to the working directory::
3958 - changesets ancestral to the working directory::
3944
3959
3945 hg log -f
3960 hg log -f
3946
3961
3947 - last 10 commits on the current branch::
3962 - last 10 commits on the current branch::
3948
3963
3949 hg log -l 10 -b .
3964 hg log -l 10 -b .
3950
3965
3951 - changesets showing all modifications of a file, including removals::
3966 - changesets showing all modifications of a file, including removals::
3952
3967
3953 hg log --removed file.c
3968 hg log --removed file.c
3954
3969
3955 - all changesets that touch a directory, with diffs, excluding merges::
3970 - all changesets that touch a directory, with diffs, excluding merges::
3956
3971
3957 hg log -Mp lib/
3972 hg log -Mp lib/
3958
3973
3959 - all revision numbers that match a keyword::
3974 - all revision numbers that match a keyword::
3960
3975
3961 hg log -k bug --template "{rev}\\n"
3976 hg log -k bug --template "{rev}\\n"
3962
3977
3963 - check if a given changeset is included is a tagged release::
3978 - check if a given changeset is included is a tagged release::
3964
3979
3965 hg log -r "a21ccf and ancestor(1.9)"
3980 hg log -r "a21ccf and ancestor(1.9)"
3966
3981
3967 - find all changesets by some user in a date range::
3982 - find all changesets by some user in a date range::
3968
3983
3969 hg log -k alice -d "may 2008 to jul 2008"
3984 hg log -k alice -d "may 2008 to jul 2008"
3970
3985
3971 - summary of all changesets after the last tag::
3986 - summary of all changesets after the last tag::
3972
3987
3973 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3988 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
3974
3989
3975 See :hg:`help dates` for a list of formats valid for -d/--date.
3990 See :hg:`help dates` for a list of formats valid for -d/--date.
3976
3991
3977 See :hg:`help revisions` and :hg:`help revsets` for more about
3992 See :hg:`help revisions` and :hg:`help revsets` for more about
3978 specifying revisions.
3993 specifying revisions.
3979
3994
3980 See :hg:`help templates` for more about pre-packaged styles and
3995 See :hg:`help templates` for more about pre-packaged styles and
3981 specifying custom templates.
3996 specifying custom templates.
3982
3997
3983 Returns 0 on success.
3998 Returns 0 on success.
3984 """
3999 """
3985
4000
3986 matchfn = scmutil.match(repo[None], pats, opts)
4001 matchfn = scmutil.match(repo[None], pats, opts)
3987 limit = cmdutil.loglimit(opts)
4002 limit = cmdutil.loglimit(opts)
3988 count = 0
4003 count = 0
3989
4004
3990 getrenamed, endrev = None, None
4005 getrenamed, endrev = None, None
3991 if opts.get('copies'):
4006 if opts.get('copies'):
3992 if opts.get('rev'):
4007 if opts.get('rev'):
3993 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4008 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
3994 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4009 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
3995
4010
3996 df = False
4011 df = False
3997 if opts["date"]:
4012 if opts["date"]:
3998 df = util.matchdate(opts["date"])
4013 df = util.matchdate(opts["date"])
3999
4014
4000 branches = opts.get('branch', []) + opts.get('only_branch', [])
4015 branches = opts.get('branch', []) + opts.get('only_branch', [])
4001 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4016 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4002
4017
4003 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4018 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4004 def prep(ctx, fns):
4019 def prep(ctx, fns):
4005 rev = ctx.rev()
4020 rev = ctx.rev()
4006 parents = [p for p in repo.changelog.parentrevs(rev)
4021 parents = [p for p in repo.changelog.parentrevs(rev)
4007 if p != nullrev]
4022 if p != nullrev]
4008 if opts.get('no_merges') and len(parents) == 2:
4023 if opts.get('no_merges') and len(parents) == 2:
4009 return
4024 return
4010 if opts.get('only_merges') and len(parents) != 2:
4025 if opts.get('only_merges') and len(parents) != 2:
4011 return
4026 return
4012 if opts.get('branch') and ctx.branch() not in opts['branch']:
4027 if opts.get('branch') and ctx.branch() not in opts['branch']:
4013 return
4028 return
4014 if not opts.get('hidden') and ctx.hidden():
4029 if not opts.get('hidden') and ctx.hidden():
4015 return
4030 return
4016 if df and not df(ctx.date()[0]):
4031 if df and not df(ctx.date()[0]):
4017 return
4032 return
4018
4033
4019 lower = encoding.lower
4034 lower = encoding.lower
4020 if opts.get('user'):
4035 if opts.get('user'):
4021 luser = lower(ctx.user())
4036 luser = lower(ctx.user())
4022 for k in [lower(x) for x in opts['user']]:
4037 for k in [lower(x) for x in opts['user']]:
4023 if (k in luser):
4038 if (k in luser):
4024 break
4039 break
4025 else:
4040 else:
4026 return
4041 return
4027 if opts.get('keyword'):
4042 if opts.get('keyword'):
4028 luser = lower(ctx.user())
4043 luser = lower(ctx.user())
4029 ldesc = lower(ctx.description())
4044 ldesc = lower(ctx.description())
4030 lfiles = lower(" ".join(ctx.files()))
4045 lfiles = lower(" ".join(ctx.files()))
4031 for k in [lower(x) for x in opts['keyword']]:
4046 for k in [lower(x) for x in opts['keyword']]:
4032 if (k in luser or k in ldesc or k in lfiles):
4047 if (k in luser or k in ldesc or k in lfiles):
4033 break
4048 break
4034 else:
4049 else:
4035 return
4050 return
4036
4051
4037 copies = None
4052 copies = None
4038 if getrenamed is not None and rev:
4053 if getrenamed is not None and rev:
4039 copies = []
4054 copies = []
4040 for fn in ctx.files():
4055 for fn in ctx.files():
4041 rename = getrenamed(fn, rev)
4056 rename = getrenamed(fn, rev)
4042 if rename:
4057 if rename:
4043 copies.append((fn, rename[0]))
4058 copies.append((fn, rename[0]))
4044
4059
4045 revmatchfn = None
4060 revmatchfn = None
4046 if opts.get('patch') or opts.get('stat'):
4061 if opts.get('patch') or opts.get('stat'):
4047 if opts.get('follow') or opts.get('follow_first'):
4062 if opts.get('follow') or opts.get('follow_first'):
4048 # note: this might be wrong when following through merges
4063 # note: this might be wrong when following through merges
4049 revmatchfn = scmutil.match(repo[None], fns, default='path')
4064 revmatchfn = scmutil.match(repo[None], fns, default='path')
4050 else:
4065 else:
4051 revmatchfn = matchfn
4066 revmatchfn = matchfn
4052
4067
4053 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4068 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4054
4069
4055 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4070 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4056 if count == limit:
4071 if count == limit:
4057 break
4072 break
4058 if displayer.flush(ctx.rev()):
4073 if displayer.flush(ctx.rev()):
4059 count += 1
4074 count += 1
4060 displayer.close()
4075 displayer.close()
4061
4076
4062 @command('manifest',
4077 @command('manifest',
4063 [('r', 'rev', '', _('revision to display'), _('REV')),
4078 [('r', 'rev', '', _('revision to display'), _('REV')),
4064 ('', 'all', False, _("list files from all revisions"))],
4079 ('', 'all', False, _("list files from all revisions"))],
4065 _('[-r REV]'))
4080 _('[-r REV]'))
4066 def manifest(ui, repo, node=None, rev=None, **opts):
4081 def manifest(ui, repo, node=None, rev=None, **opts):
4067 """output the current or given revision of the project manifest
4082 """output the current or given revision of the project manifest
4068
4083
4069 Print a list of version controlled files for the given revision.
4084 Print a list of version controlled files for the given revision.
4070 If no revision is given, the first parent of the working directory
4085 If no revision is given, the first parent of the working directory
4071 is used, or the null revision if no revision is checked out.
4086 is used, or the null revision if no revision is checked out.
4072
4087
4073 With -v, print file permissions, symlink and executable bits.
4088 With -v, print file permissions, symlink and executable bits.
4074 With --debug, print file revision hashes.
4089 With --debug, print file revision hashes.
4075
4090
4076 If option --all is specified, the list of all files from all revisions
4091 If option --all is specified, the list of all files from all revisions
4077 is printed. This includes deleted and renamed files.
4092 is printed. This includes deleted and renamed files.
4078
4093
4079 Returns 0 on success.
4094 Returns 0 on success.
4080 """
4095 """
4081 if opts.get('all'):
4096 if opts.get('all'):
4082 if rev or node:
4097 if rev or node:
4083 raise util.Abort(_("can't specify a revision with --all"))
4098 raise util.Abort(_("can't specify a revision with --all"))
4084
4099
4085 res = []
4100 res = []
4086 prefix = "data/"
4101 prefix = "data/"
4087 suffix = ".i"
4102 suffix = ".i"
4088 plen = len(prefix)
4103 plen = len(prefix)
4089 slen = len(suffix)
4104 slen = len(suffix)
4090 lock = repo.lock()
4105 lock = repo.lock()
4091 try:
4106 try:
4092 for fn, b, size in repo.store.datafiles():
4107 for fn, b, size in repo.store.datafiles():
4093 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4108 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4094 res.append(fn[plen:-slen])
4109 res.append(fn[plen:-slen])
4095 finally:
4110 finally:
4096 lock.release()
4111 lock.release()
4097 for f in sorted(res):
4112 for f in sorted(res):
4098 ui.write("%s\n" % f)
4113 ui.write("%s\n" % f)
4099 return
4114 return
4100
4115
4101 if rev and node:
4116 if rev and node:
4102 raise util.Abort(_("please specify just one revision"))
4117 raise util.Abort(_("please specify just one revision"))
4103
4118
4104 if not node:
4119 if not node:
4105 node = rev
4120 node = rev
4106
4121
4107 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4122 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
4108 ctx = scmutil.revsingle(repo, node)
4123 ctx = scmutil.revsingle(repo, node)
4109 for f in ctx:
4124 for f in ctx:
4110 if ui.debugflag:
4125 if ui.debugflag:
4111 ui.write("%40s " % hex(ctx.manifest()[f]))
4126 ui.write("%40s " % hex(ctx.manifest()[f]))
4112 if ui.verbose:
4127 if ui.verbose:
4113 ui.write(decor[ctx.flags(f)])
4128 ui.write(decor[ctx.flags(f)])
4114 ui.write("%s\n" % f)
4129 ui.write("%s\n" % f)
4115
4130
4116 @command('^merge',
4131 @command('^merge',
4117 [('f', 'force', None, _('force a merge with outstanding changes')),
4132 [('f', 'force', None, _('force a merge with outstanding changes')),
4118 ('r', 'rev', '', _('revision to merge'), _('REV')),
4133 ('r', 'rev', '', _('revision to merge'), _('REV')),
4119 ('P', 'preview', None,
4134 ('P', 'preview', None,
4120 _('review revisions to merge (no merge is performed)'))
4135 _('review revisions to merge (no merge is performed)'))
4121 ] + mergetoolopts,
4136 ] + mergetoolopts,
4122 _('[-P] [-f] [[-r] REV]'))
4137 _('[-P] [-f] [[-r] REV]'))
4123 def merge(ui, repo, node=None, **opts):
4138 def merge(ui, repo, node=None, **opts):
4124 """merge working directory with another revision
4139 """merge working directory with another revision
4125
4140
4126 The current working directory is updated with all changes made in
4141 The current working directory is updated with all changes made in
4127 the requested revision since the last common predecessor revision.
4142 the requested revision since the last common predecessor revision.
4128
4143
4129 Files that changed between either parent are marked as changed for
4144 Files that changed between either parent are marked as changed for
4130 the next commit and a commit must be performed before any further
4145 the next commit and a commit must be performed before any further
4131 updates to the repository are allowed. The next commit will have
4146 updates to the repository are allowed. The next commit will have
4132 two parents.
4147 two parents.
4133
4148
4134 ``--tool`` can be used to specify the merge tool used for file
4149 ``--tool`` can be used to specify the merge tool used for file
4135 merges. It overrides the HGMERGE environment variable and your
4150 merges. It overrides the HGMERGE environment variable and your
4136 configuration files. See :hg:`help merge-tools` for options.
4151 configuration files. See :hg:`help merge-tools` for options.
4137
4152
4138 If no revision is specified, the working directory's parent is a
4153 If no revision is specified, the working directory's parent is a
4139 head revision, and the current branch contains exactly one other
4154 head revision, and the current branch contains exactly one other
4140 head, the other head is merged with by default. Otherwise, an
4155 head, the other head is merged with by default. Otherwise, an
4141 explicit revision with which to merge with must be provided.
4156 explicit revision with which to merge with must be provided.
4142
4157
4143 :hg:`resolve` must be used to resolve unresolved files.
4158 :hg:`resolve` must be used to resolve unresolved files.
4144
4159
4145 To undo an uncommitted merge, use :hg:`update --clean .` which
4160 To undo an uncommitted merge, use :hg:`update --clean .` which
4146 will check out a clean copy of the original merge parent, losing
4161 will check out a clean copy of the original merge parent, losing
4147 all changes.
4162 all changes.
4148
4163
4149 Returns 0 on success, 1 if there are unresolved files.
4164 Returns 0 on success, 1 if there are unresolved files.
4150 """
4165 """
4151
4166
4152 if opts.get('rev') and node:
4167 if opts.get('rev') and node:
4153 raise util.Abort(_("please specify just one revision"))
4168 raise util.Abort(_("please specify just one revision"))
4154 if not node:
4169 if not node:
4155 node = opts.get('rev')
4170 node = opts.get('rev')
4156
4171
4157 if node:
4172 if node:
4158 node = scmutil.revsingle(repo, node).node()
4173 node = scmutil.revsingle(repo, node).node()
4159
4174
4160 if not node and repo._bookmarkcurrent:
4175 if not node and repo._bookmarkcurrent:
4161 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4176 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4162 curhead = repo[repo._bookmarkcurrent]
4177 curhead = repo[repo._bookmarkcurrent]
4163 if len(bmheads) == 2:
4178 if len(bmheads) == 2:
4164 if curhead == bmheads[0]:
4179 if curhead == bmheads[0]:
4165 node = bmheads[1]
4180 node = bmheads[1]
4166 else:
4181 else:
4167 node = bmheads[0]
4182 node = bmheads[0]
4168 elif len(bmheads) > 2:
4183 elif len(bmheads) > 2:
4169 raise util.Abort(_("multiple matching bookmarks to merge - "
4184 raise util.Abort(_("multiple matching bookmarks to merge - "
4170 "please merge with an explicit rev or bookmark"),
4185 "please merge with an explicit rev or bookmark"),
4171 hint=_("run 'hg heads' to see all heads"))
4186 hint=_("run 'hg heads' to see all heads"))
4172 elif len(bmheads) <= 1:
4187 elif len(bmheads) <= 1:
4173 raise util.Abort(_("no matching bookmark to merge - "
4188 raise util.Abort(_("no matching bookmark to merge - "
4174 "please merge with an explicit rev or bookmark"),
4189 "please merge with an explicit rev or bookmark"),
4175 hint=_("run 'hg heads' to see all heads"))
4190 hint=_("run 'hg heads' to see all heads"))
4176
4191
4177 if not node and not repo._bookmarkcurrent:
4192 if not node and not repo._bookmarkcurrent:
4178 branch = repo[None].branch()
4193 branch = repo[None].branch()
4179 bheads = repo.branchheads(branch)
4194 bheads = repo.branchheads(branch)
4180 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4195 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4181
4196
4182 if len(nbhs) > 2:
4197 if len(nbhs) > 2:
4183 raise util.Abort(_("branch '%s' has %d heads - "
4198 raise util.Abort(_("branch '%s' has %d heads - "
4184 "please merge with an explicit rev")
4199 "please merge with an explicit rev")
4185 % (branch, len(bheads)),
4200 % (branch, len(bheads)),
4186 hint=_("run 'hg heads .' to see heads"))
4201 hint=_("run 'hg heads .' to see heads"))
4187
4202
4188 parent = repo.dirstate.p1()
4203 parent = repo.dirstate.p1()
4189 if len(nbhs) == 1:
4204 if len(nbhs) == 1:
4190 if len(bheads) > 1:
4205 if len(bheads) > 1:
4191 raise util.Abort(_("heads are bookmarked - "
4206 raise util.Abort(_("heads are bookmarked - "
4192 "please merge with an explicit rev"),
4207 "please merge with an explicit rev"),
4193 hint=_("run 'hg heads' to see all heads"))
4208 hint=_("run 'hg heads' to see all heads"))
4194 if len(repo.heads()) > 1:
4209 if len(repo.heads()) > 1:
4195 raise util.Abort(_("branch '%s' has one head - "
4210 raise util.Abort(_("branch '%s' has one head - "
4196 "please merge with an explicit rev")
4211 "please merge with an explicit rev")
4197 % branch,
4212 % branch,
4198 hint=_("run 'hg heads' to see all heads"))
4213 hint=_("run 'hg heads' to see all heads"))
4199 msg, hint = _('nothing to merge'), None
4214 msg, hint = _('nothing to merge'), None
4200 if parent != repo.lookup(branch):
4215 if parent != repo.lookup(branch):
4201 hint = _("use 'hg update' instead")
4216 hint = _("use 'hg update' instead")
4202 raise util.Abort(msg, hint=hint)
4217 raise util.Abort(msg, hint=hint)
4203
4218
4204 if parent not in bheads:
4219 if parent not in bheads:
4205 raise util.Abort(_('working directory not at a head revision'),
4220 raise util.Abort(_('working directory not at a head revision'),
4206 hint=_("use 'hg update' or merge with an "
4221 hint=_("use 'hg update' or merge with an "
4207 "explicit revision"))
4222 "explicit revision"))
4208 if parent == nbhs[0]:
4223 if parent == nbhs[0]:
4209 node = nbhs[-1]
4224 node = nbhs[-1]
4210 else:
4225 else:
4211 node = nbhs[0]
4226 node = nbhs[0]
4212
4227
4213 if opts.get('preview'):
4228 if opts.get('preview'):
4214 # find nodes that are ancestors of p2 but not of p1
4229 # find nodes that are ancestors of p2 but not of p1
4215 p1 = repo.lookup('.')
4230 p1 = repo.lookup('.')
4216 p2 = repo.lookup(node)
4231 p2 = repo.lookup(node)
4217 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4232 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4218
4233
4219 displayer = cmdutil.show_changeset(ui, repo, opts)
4234 displayer = cmdutil.show_changeset(ui, repo, opts)
4220 for node in nodes:
4235 for node in nodes:
4221 displayer.show(repo[node])
4236 displayer.show(repo[node])
4222 displayer.close()
4237 displayer.close()
4223 return 0
4238 return 0
4224
4239
4225 try:
4240 try:
4226 # ui.forcemerge is an internal variable, do not document
4241 # ui.forcemerge is an internal variable, do not document
4227 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4242 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4228 return hg.merge(repo, node, force=opts.get('force'))
4243 return hg.merge(repo, node, force=opts.get('force'))
4229 finally:
4244 finally:
4230 ui.setconfig('ui', 'forcemerge', '')
4245 ui.setconfig('ui', 'forcemerge', '')
4231
4246
4232 @command('outgoing|out',
4247 @command('outgoing|out',
4233 [('f', 'force', None, _('run even when the destination is unrelated')),
4248 [('f', 'force', None, _('run even when the destination is unrelated')),
4234 ('r', 'rev', [],
4249 ('r', 'rev', [],
4235 _('a changeset intended to be included in the destination'), _('REV')),
4250 _('a changeset intended to be included in the destination'), _('REV')),
4236 ('n', 'newest-first', None, _('show newest record first')),
4251 ('n', 'newest-first', None, _('show newest record first')),
4237 ('B', 'bookmarks', False, _('compare bookmarks')),
4252 ('B', 'bookmarks', False, _('compare bookmarks')),
4238 ('b', 'branch', [], _('a specific branch you would like to push'),
4253 ('b', 'branch', [], _('a specific branch you would like to push'),
4239 _('BRANCH')),
4254 _('BRANCH')),
4240 ] + logopts + remoteopts + subrepoopts,
4255 ] + logopts + remoteopts + subrepoopts,
4241 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4256 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4242 def outgoing(ui, repo, dest=None, **opts):
4257 def outgoing(ui, repo, dest=None, **opts):
4243 """show changesets not found in the destination
4258 """show changesets not found in the destination
4244
4259
4245 Show changesets not found in the specified destination repository
4260 Show changesets not found in the specified destination repository
4246 or the default push location. These are the changesets that would
4261 or the default push location. These are the changesets that would
4247 be pushed if a push was requested.
4262 be pushed if a push was requested.
4248
4263
4249 See pull for details of valid destination formats.
4264 See pull for details of valid destination formats.
4250
4265
4251 Returns 0 if there are outgoing changes, 1 otherwise.
4266 Returns 0 if there are outgoing changes, 1 otherwise.
4252 """
4267 """
4253
4268
4254 if opts.get('bookmarks'):
4269 if opts.get('bookmarks'):
4255 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4270 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4256 dest, branches = hg.parseurl(dest, opts.get('branch'))
4271 dest, branches = hg.parseurl(dest, opts.get('branch'))
4257 other = hg.peer(repo, opts, dest)
4272 other = hg.peer(repo, opts, dest)
4258 if 'bookmarks' not in other.listkeys('namespaces'):
4273 if 'bookmarks' not in other.listkeys('namespaces'):
4259 ui.warn(_("remote doesn't support bookmarks\n"))
4274 ui.warn(_("remote doesn't support bookmarks\n"))
4260 return 0
4275 return 0
4261 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4276 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4262 return bookmarks.diff(ui, other, repo)
4277 return bookmarks.diff(ui, other, repo)
4263
4278
4264 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4279 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4265 try:
4280 try:
4266 return hg.outgoing(ui, repo, dest, opts)
4281 return hg.outgoing(ui, repo, dest, opts)
4267 finally:
4282 finally:
4268 del repo._subtoppath
4283 del repo._subtoppath
4269
4284
4270 @command('parents',
4285 @command('parents',
4271 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4286 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4272 ] + templateopts,
4287 ] + templateopts,
4273 _('[-r REV] [FILE]'))
4288 _('[-r REV] [FILE]'))
4274 def parents(ui, repo, file_=None, **opts):
4289 def parents(ui, repo, file_=None, **opts):
4275 """show the parents of the working directory or revision
4290 """show the parents of the working directory or revision
4276
4291
4277 Print the working directory's parent revisions. If a revision is
4292 Print the working directory's parent revisions. If a revision is
4278 given via -r/--rev, the parent of that revision will be printed.
4293 given via -r/--rev, the parent of that revision will be printed.
4279 If a file argument is given, the revision in which the file was
4294 If a file argument is given, the revision in which the file was
4280 last changed (before the working directory revision or the
4295 last changed (before the working directory revision or the
4281 argument to --rev if given) is printed.
4296 argument to --rev if given) is printed.
4282
4297
4283 Returns 0 on success.
4298 Returns 0 on success.
4284 """
4299 """
4285
4300
4286 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4301 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4287
4302
4288 if file_:
4303 if file_:
4289 m = scmutil.match(ctx, (file_,), opts)
4304 m = scmutil.match(ctx, (file_,), opts)
4290 if m.anypats() or len(m.files()) != 1:
4305 if m.anypats() or len(m.files()) != 1:
4291 raise util.Abort(_('can only specify an explicit filename'))
4306 raise util.Abort(_('can only specify an explicit filename'))
4292 file_ = m.files()[0]
4307 file_ = m.files()[0]
4293 filenodes = []
4308 filenodes = []
4294 for cp in ctx.parents():
4309 for cp in ctx.parents():
4295 if not cp:
4310 if not cp:
4296 continue
4311 continue
4297 try:
4312 try:
4298 filenodes.append(cp.filenode(file_))
4313 filenodes.append(cp.filenode(file_))
4299 except error.LookupError:
4314 except error.LookupError:
4300 pass
4315 pass
4301 if not filenodes:
4316 if not filenodes:
4302 raise util.Abort(_("'%s' not found in manifest!") % file_)
4317 raise util.Abort(_("'%s' not found in manifest!") % file_)
4303 fl = repo.file(file_)
4318 fl = repo.file(file_)
4304 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4319 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
4305 else:
4320 else:
4306 p = [cp.node() for cp in ctx.parents()]
4321 p = [cp.node() for cp in ctx.parents()]
4307
4322
4308 displayer = cmdutil.show_changeset(ui, repo, opts)
4323 displayer = cmdutil.show_changeset(ui, repo, opts)
4309 for n in p:
4324 for n in p:
4310 if n != nullid:
4325 if n != nullid:
4311 displayer.show(repo[n])
4326 displayer.show(repo[n])
4312 displayer.close()
4327 displayer.close()
4313
4328
4314 @command('paths', [], _('[NAME]'))
4329 @command('paths', [], _('[NAME]'))
4315 def paths(ui, repo, search=None):
4330 def paths(ui, repo, search=None):
4316 """show aliases for remote repositories
4331 """show aliases for remote repositories
4317
4332
4318 Show definition of symbolic path name NAME. If no name is given,
4333 Show definition of symbolic path name NAME. If no name is given,
4319 show definition of all available names.
4334 show definition of all available names.
4320
4335
4321 Option -q/--quiet suppresses all output when searching for NAME
4336 Option -q/--quiet suppresses all output when searching for NAME
4322 and shows only the path names when listing all definitions.
4337 and shows only the path names when listing all definitions.
4323
4338
4324 Path names are defined in the [paths] section of your
4339 Path names are defined in the [paths] section of your
4325 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4340 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4326 repository, ``.hg/hgrc`` is used, too.
4341 repository, ``.hg/hgrc`` is used, too.
4327
4342
4328 The path names ``default`` and ``default-push`` have a special
4343 The path names ``default`` and ``default-push`` have a special
4329 meaning. When performing a push or pull operation, they are used
4344 meaning. When performing a push or pull operation, they are used
4330 as fallbacks if no location is specified on the command-line.
4345 as fallbacks if no location is specified on the command-line.
4331 When ``default-push`` is set, it will be used for push and
4346 When ``default-push`` is set, it will be used for push and
4332 ``default`` will be used for pull; otherwise ``default`` is used
4347 ``default`` will be used for pull; otherwise ``default`` is used
4333 as the fallback for both. When cloning a repository, the clone
4348 as the fallback for both. When cloning a repository, the clone
4334 source is written as ``default`` in ``.hg/hgrc``. Note that
4349 source is written as ``default`` in ``.hg/hgrc``. Note that
4335 ``default`` and ``default-push`` apply to all inbound (e.g.
4350 ``default`` and ``default-push`` apply to all inbound (e.g.
4336 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4351 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4337 :hg:`bundle`) operations.
4352 :hg:`bundle`) operations.
4338
4353
4339 See :hg:`help urls` for more information.
4354 See :hg:`help urls` for more information.
4340
4355
4341 Returns 0 on success.
4356 Returns 0 on success.
4342 """
4357 """
4343 if search:
4358 if search:
4344 for name, path in ui.configitems("paths"):
4359 for name, path in ui.configitems("paths"):
4345 if name == search:
4360 if name == search:
4346 ui.status("%s\n" % util.hidepassword(path))
4361 ui.status("%s\n" % util.hidepassword(path))
4347 return
4362 return
4348 if not ui.quiet:
4363 if not ui.quiet:
4349 ui.warn(_("not found!\n"))
4364 ui.warn(_("not found!\n"))
4350 return 1
4365 return 1
4351 else:
4366 else:
4352 for name, path in ui.configitems("paths"):
4367 for name, path in ui.configitems("paths"):
4353 if ui.quiet:
4368 if ui.quiet:
4354 ui.write("%s\n" % name)
4369 ui.write("%s\n" % name)
4355 else:
4370 else:
4356 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4371 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4357
4372
4358 @command('^phase',
4373 @command('^phase',
4359 [('p', 'public', False, _('set changeset phase to public')),
4374 [('p', 'public', False, _('set changeset phase to public')),
4360 ('d', 'draft', False, _('set changeset phase to draft')),
4375 ('d', 'draft', False, _('set changeset phase to draft')),
4361 ('s', 'secret', False, _('set changeset phase to secret')),
4376 ('s', 'secret', False, _('set changeset phase to secret')),
4362 ('f', 'force', False, _('allow to move boundary backward')),
4377 ('f', 'force', False, _('allow to move boundary backward')),
4363 ('r', 'rev', [], _('target revision'), _('REV')),
4378 ('r', 'rev', [], _('target revision'), _('REV')),
4364 ],
4379 ],
4365 _('[-p|-d|-s] [-f] [-r] REV...'))
4380 _('[-p|-d|-s] [-f] [-r] REV...'))
4366 def phase(ui, repo, *revs, **opts):
4381 def phase(ui, repo, *revs, **opts):
4367 """set or show the current phase name
4382 """set or show the current phase name
4368
4383
4369 With no argument, show the phase name of specified revisions.
4384 With no argument, show the phase name of specified revisions.
4370
4385
4371 With one of -p/--public, -d/--draft or -s/--secret, change the
4386 With one of -p/--public, -d/--draft or -s/--secret, change the
4372 phase value of the specified revisions.
4387 phase value of the specified revisions.
4373
4388
4374 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4389 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4375 lower phase to an higher phase. Phases are ordered as follows::
4390 lower phase to an higher phase. Phases are ordered as follows::
4376
4391
4377 public < draft < secret
4392 public < draft < secret
4378
4393
4379 Return 0 on success, 1 if no phases were changed or some could not
4394 Return 0 on success, 1 if no phases were changed or some could not
4380 be changed.
4395 be changed.
4381 """
4396 """
4382 # search for a unique phase argument
4397 # search for a unique phase argument
4383 targetphase = None
4398 targetphase = None
4384 for idx, name in enumerate(phases.phasenames):
4399 for idx, name in enumerate(phases.phasenames):
4385 if opts[name]:
4400 if opts[name]:
4386 if targetphase is not None:
4401 if targetphase is not None:
4387 raise util.Abort(_('only one phase can be specified'))
4402 raise util.Abort(_('only one phase can be specified'))
4388 targetphase = idx
4403 targetphase = idx
4389
4404
4390 # look for specified revision
4405 # look for specified revision
4391 revs = list(revs)
4406 revs = list(revs)
4392 revs.extend(opts['rev'])
4407 revs.extend(opts['rev'])
4393 if not revs:
4408 if not revs:
4394 raise util.Abort(_('no revisions specified'))
4409 raise util.Abort(_('no revisions specified'))
4395
4410
4396 revs = scmutil.revrange(repo, revs)
4411 revs = scmutil.revrange(repo, revs)
4397
4412
4398 lock = None
4413 lock = None
4399 ret = 0
4414 ret = 0
4400 if targetphase is None:
4415 if targetphase is None:
4401 # display
4416 # display
4402 for r in revs:
4417 for r in revs:
4403 ctx = repo[r]
4418 ctx = repo[r]
4404 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4419 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4405 else:
4420 else:
4406 lock = repo.lock()
4421 lock = repo.lock()
4407 try:
4422 try:
4408 # set phase
4423 # set phase
4409 if not revs:
4424 if not revs:
4410 raise util.Abort(_('empty revision set'))
4425 raise util.Abort(_('empty revision set'))
4411 nodes = [repo[r].node() for r in revs]
4426 nodes = [repo[r].node() for r in revs]
4412 olddata = repo._phasecache.getphaserevs(repo)[:]
4427 olddata = repo._phasecache.getphaserevs(repo)[:]
4413 phases.advanceboundary(repo, targetphase, nodes)
4428 phases.advanceboundary(repo, targetphase, nodes)
4414 if opts['force']:
4429 if opts['force']:
4415 phases.retractboundary(repo, targetphase, nodes)
4430 phases.retractboundary(repo, targetphase, nodes)
4416 finally:
4431 finally:
4417 lock.release()
4432 lock.release()
4418 newdata = repo._phasecache.getphaserevs(repo)
4433 newdata = repo._phasecache.getphaserevs(repo)
4419 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4434 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4420 rejected = [n for n in nodes
4435 rejected = [n for n in nodes
4421 if newdata[repo[n].rev()] < targetphase]
4436 if newdata[repo[n].rev()] < targetphase]
4422 if rejected:
4437 if rejected:
4423 ui.warn(_('cannot move %i changesets to a more permissive '
4438 ui.warn(_('cannot move %i changesets to a more permissive '
4424 'phase, use --force\n') % len(rejected))
4439 'phase, use --force\n') % len(rejected))
4425 ret = 1
4440 ret = 1
4426 if changes:
4441 if changes:
4427 msg = _('phase changed for %i changesets\n') % changes
4442 msg = _('phase changed for %i changesets\n') % changes
4428 if ret:
4443 if ret:
4429 ui.status(msg)
4444 ui.status(msg)
4430 else:
4445 else:
4431 ui.note(msg)
4446 ui.note(msg)
4432 else:
4447 else:
4433 ui.warn(_('no phases changed\n'))
4448 ui.warn(_('no phases changed\n'))
4434 ret = 1
4449 ret = 1
4435 return ret
4450 return ret
4436
4451
4437 def postincoming(ui, repo, modheads, optupdate, checkout):
4452 def postincoming(ui, repo, modheads, optupdate, checkout):
4438 if modheads == 0:
4453 if modheads == 0:
4439 return
4454 return
4440 if optupdate:
4455 if optupdate:
4441 movemarkfrom = repo['.'].node()
4456 movemarkfrom = repo['.'].node()
4442 try:
4457 try:
4443 ret = hg.update(repo, checkout)
4458 ret = hg.update(repo, checkout)
4444 except util.Abort, inst:
4459 except util.Abort, inst:
4445 ui.warn(_("not updating: %s\n") % str(inst))
4460 ui.warn(_("not updating: %s\n") % str(inst))
4446 return 0
4461 return 0
4447 if not ret and not checkout:
4462 if not ret and not checkout:
4448 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4463 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4449 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4464 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4450 return ret
4465 return ret
4451 if modheads > 1:
4466 if modheads > 1:
4452 currentbranchheads = len(repo.branchheads())
4467 currentbranchheads = len(repo.branchheads())
4453 if currentbranchheads == modheads:
4468 if currentbranchheads == modheads:
4454 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4469 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4455 elif currentbranchheads > 1:
4470 elif currentbranchheads > 1:
4456 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4471 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4457 "merge)\n"))
4472 "merge)\n"))
4458 else:
4473 else:
4459 ui.status(_("(run 'hg heads' to see heads)\n"))
4474 ui.status(_("(run 'hg heads' to see heads)\n"))
4460 else:
4475 else:
4461 ui.status(_("(run 'hg update' to get a working copy)\n"))
4476 ui.status(_("(run 'hg update' to get a working copy)\n"))
4462
4477
4463 @command('^pull',
4478 @command('^pull',
4464 [('u', 'update', None,
4479 [('u', 'update', None,
4465 _('update to new branch head if changesets were pulled')),
4480 _('update to new branch head if changesets were pulled')),
4466 ('f', 'force', None, _('run even when remote repository is unrelated')),
4481 ('f', 'force', None, _('run even when remote repository is unrelated')),
4467 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4482 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4468 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4483 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4469 ('b', 'branch', [], _('a specific branch you would like to pull'),
4484 ('b', 'branch', [], _('a specific branch you would like to pull'),
4470 _('BRANCH')),
4485 _('BRANCH')),
4471 ] + remoteopts,
4486 ] + remoteopts,
4472 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4487 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4473 def pull(ui, repo, source="default", **opts):
4488 def pull(ui, repo, source="default", **opts):
4474 """pull changes from the specified source
4489 """pull changes from the specified source
4475
4490
4476 Pull changes from a remote repository to a local one.
4491 Pull changes from a remote repository to a local one.
4477
4492
4478 This finds all changes from the repository at the specified path
4493 This finds all changes from the repository at the specified path
4479 or URL and adds them to a local repository (the current one unless
4494 or URL and adds them to a local repository (the current one unless
4480 -R is specified). By default, this does not update the copy of the
4495 -R is specified). By default, this does not update the copy of the
4481 project in the working directory.
4496 project in the working directory.
4482
4497
4483 Use :hg:`incoming` if you want to see what would have been added
4498 Use :hg:`incoming` if you want to see what would have been added
4484 by a pull at the time you issued this command. If you then decide
4499 by a pull at the time you issued this command. If you then decide
4485 to add those changes to the repository, you should use :hg:`pull
4500 to add those changes to the repository, you should use :hg:`pull
4486 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4501 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4487
4502
4488 If SOURCE is omitted, the 'default' path will be used.
4503 If SOURCE is omitted, the 'default' path will be used.
4489 See :hg:`help urls` for more information.
4504 See :hg:`help urls` for more information.
4490
4505
4491 Returns 0 on success, 1 if an update had unresolved files.
4506 Returns 0 on success, 1 if an update had unresolved files.
4492 """
4507 """
4493 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4508 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4494 other = hg.peer(repo, opts, source)
4509 other = hg.peer(repo, opts, source)
4495 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4510 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4496 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4511 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4497
4512
4498 if opts.get('bookmark'):
4513 if opts.get('bookmark'):
4499 if not revs:
4514 if not revs:
4500 revs = []
4515 revs = []
4501 rb = other.listkeys('bookmarks')
4516 rb = other.listkeys('bookmarks')
4502 for b in opts['bookmark']:
4517 for b in opts['bookmark']:
4503 if b not in rb:
4518 if b not in rb:
4504 raise util.Abort(_('remote bookmark %s not found!') % b)
4519 raise util.Abort(_('remote bookmark %s not found!') % b)
4505 revs.append(rb[b])
4520 revs.append(rb[b])
4506
4521
4507 if revs:
4522 if revs:
4508 try:
4523 try:
4509 revs = [other.lookup(rev) for rev in revs]
4524 revs = [other.lookup(rev) for rev in revs]
4510 except error.CapabilityError:
4525 except error.CapabilityError:
4511 err = _("other repository doesn't support revision lookup, "
4526 err = _("other repository doesn't support revision lookup, "
4512 "so a rev cannot be specified.")
4527 "so a rev cannot be specified.")
4513 raise util.Abort(err)
4528 raise util.Abort(err)
4514
4529
4515 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4530 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4516 bookmarks.updatefromremote(ui, repo, other, source)
4531 bookmarks.updatefromremote(ui, repo, other, source)
4517 if checkout:
4532 if checkout:
4518 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4533 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4519 repo._subtoppath = source
4534 repo._subtoppath = source
4520 try:
4535 try:
4521 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4536 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4522
4537
4523 finally:
4538 finally:
4524 del repo._subtoppath
4539 del repo._subtoppath
4525
4540
4526 # update specified bookmarks
4541 # update specified bookmarks
4527 if opts.get('bookmark'):
4542 if opts.get('bookmark'):
4528 for b in opts['bookmark']:
4543 for b in opts['bookmark']:
4529 # explicit pull overrides local bookmark if any
4544 # explicit pull overrides local bookmark if any
4530 ui.status(_("importing bookmark %s\n") % b)
4545 ui.status(_("importing bookmark %s\n") % b)
4531 repo._bookmarks[b] = repo[rb[b]].node()
4546 repo._bookmarks[b] = repo[rb[b]].node()
4532 bookmarks.write(repo)
4547 bookmarks.write(repo)
4533
4548
4534 return ret
4549 return ret
4535
4550
4536 @command('^push',
4551 @command('^push',
4537 [('f', 'force', None, _('force push')),
4552 [('f', 'force', None, _('force push')),
4538 ('r', 'rev', [],
4553 ('r', 'rev', [],
4539 _('a changeset intended to be included in the destination'),
4554 _('a changeset intended to be included in the destination'),
4540 _('REV')),
4555 _('REV')),
4541 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4556 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4542 ('b', 'branch', [],
4557 ('b', 'branch', [],
4543 _('a specific branch you would like to push'), _('BRANCH')),
4558 _('a specific branch you would like to push'), _('BRANCH')),
4544 ('', 'new-branch', False, _('allow pushing a new branch')),
4559 ('', 'new-branch', False, _('allow pushing a new branch')),
4545 ] + remoteopts,
4560 ] + remoteopts,
4546 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4561 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4547 def push(ui, repo, dest=None, **opts):
4562 def push(ui, repo, dest=None, **opts):
4548 """push changes to the specified destination
4563 """push changes to the specified destination
4549
4564
4550 Push changesets from the local repository to the specified
4565 Push changesets from the local repository to the specified
4551 destination.
4566 destination.
4552
4567
4553 This operation is symmetrical to pull: it is identical to a pull
4568 This operation is symmetrical to pull: it is identical to a pull
4554 in the destination repository from the current one.
4569 in the destination repository from the current one.
4555
4570
4556 By default, push will not allow creation of new heads at the
4571 By default, push will not allow creation of new heads at the
4557 destination, since multiple heads would make it unclear which head
4572 destination, since multiple heads would make it unclear which head
4558 to use. In this situation, it is recommended to pull and merge
4573 to use. In this situation, it is recommended to pull and merge
4559 before pushing.
4574 before pushing.
4560
4575
4561 Use --new-branch if you want to allow push to create a new named
4576 Use --new-branch if you want to allow push to create a new named
4562 branch that is not present at the destination. This allows you to
4577 branch that is not present at the destination. This allows you to
4563 only create a new branch without forcing other changes.
4578 only create a new branch without forcing other changes.
4564
4579
4565 Use -f/--force to override the default behavior and push all
4580 Use -f/--force to override the default behavior and push all
4566 changesets on all branches.
4581 changesets on all branches.
4567
4582
4568 If -r/--rev is used, the specified revision and all its ancestors
4583 If -r/--rev is used, the specified revision and all its ancestors
4569 will be pushed to the remote repository.
4584 will be pushed to the remote repository.
4570
4585
4571 Please see :hg:`help urls` for important details about ``ssh://``
4586 Please see :hg:`help urls` for important details about ``ssh://``
4572 URLs. If DESTINATION is omitted, a default path will be used.
4587 URLs. If DESTINATION is omitted, a default path will be used.
4573
4588
4574 Returns 0 if push was successful, 1 if nothing to push.
4589 Returns 0 if push was successful, 1 if nothing to push.
4575 """
4590 """
4576
4591
4577 if opts.get('bookmark'):
4592 if opts.get('bookmark'):
4578 for b in opts['bookmark']:
4593 for b in opts['bookmark']:
4579 # translate -B options to -r so changesets get pushed
4594 # translate -B options to -r so changesets get pushed
4580 if b in repo._bookmarks:
4595 if b in repo._bookmarks:
4581 opts.setdefault('rev', []).append(b)
4596 opts.setdefault('rev', []).append(b)
4582 else:
4597 else:
4583 # if we try to push a deleted bookmark, translate it to null
4598 # if we try to push a deleted bookmark, translate it to null
4584 # this lets simultaneous -r, -b options continue working
4599 # this lets simultaneous -r, -b options continue working
4585 opts.setdefault('rev', []).append("null")
4600 opts.setdefault('rev', []).append("null")
4586
4601
4587 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4602 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4588 dest, branches = hg.parseurl(dest, opts.get('branch'))
4603 dest, branches = hg.parseurl(dest, opts.get('branch'))
4589 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4604 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4590 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4605 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4591 other = hg.peer(repo, opts, dest)
4606 other = hg.peer(repo, opts, dest)
4592 if revs:
4607 if revs:
4593 revs = [repo.lookup(rev) for rev in revs]
4608 revs = [repo.lookup(rev) for rev in revs]
4594
4609
4595 repo._subtoppath = dest
4610 repo._subtoppath = dest
4596 try:
4611 try:
4597 # push subrepos depth-first for coherent ordering
4612 # push subrepos depth-first for coherent ordering
4598 c = repo['']
4613 c = repo['']
4599 subs = c.substate # only repos that are committed
4614 subs = c.substate # only repos that are committed
4600 for s in sorted(subs):
4615 for s in sorted(subs):
4601 if c.sub(s).push(opts) == 0:
4616 if c.sub(s).push(opts) == 0:
4602 return False
4617 return False
4603 finally:
4618 finally:
4604 del repo._subtoppath
4619 del repo._subtoppath
4605 result = repo.push(other, opts.get('force'), revs=revs,
4620 result = repo.push(other, opts.get('force'), revs=revs,
4606 newbranch=opts.get('new_branch'))
4621 newbranch=opts.get('new_branch'))
4607
4622
4608 result = not result
4623 result = not result
4609
4624
4610 if opts.get('bookmark'):
4625 if opts.get('bookmark'):
4611 rb = other.listkeys('bookmarks')
4626 rb = other.listkeys('bookmarks')
4612 for b in opts['bookmark']:
4627 for b in opts['bookmark']:
4613 # explicit push overrides remote bookmark if any
4628 # explicit push overrides remote bookmark if any
4614 if b in repo._bookmarks:
4629 if b in repo._bookmarks:
4615 ui.status(_("exporting bookmark %s\n") % b)
4630 ui.status(_("exporting bookmark %s\n") % b)
4616 new = repo[b].hex()
4631 new = repo[b].hex()
4617 elif b in rb:
4632 elif b in rb:
4618 ui.status(_("deleting remote bookmark %s\n") % b)
4633 ui.status(_("deleting remote bookmark %s\n") % b)
4619 new = '' # delete
4634 new = '' # delete
4620 else:
4635 else:
4621 ui.warn(_('bookmark %s does not exist on the local '
4636 ui.warn(_('bookmark %s does not exist on the local '
4622 'or remote repository!\n') % b)
4637 'or remote repository!\n') % b)
4623 return 2
4638 return 2
4624 old = rb.get(b, '')
4639 old = rb.get(b, '')
4625 r = other.pushkey('bookmarks', b, old, new)
4640 r = other.pushkey('bookmarks', b, old, new)
4626 if not r:
4641 if not r:
4627 ui.warn(_('updating bookmark %s failed!\n') % b)
4642 ui.warn(_('updating bookmark %s failed!\n') % b)
4628 if not result:
4643 if not result:
4629 result = 2
4644 result = 2
4630
4645
4631 return result
4646 return result
4632
4647
4633 @command('recover', [])
4648 @command('recover', [])
4634 def recover(ui, repo):
4649 def recover(ui, repo):
4635 """roll back an interrupted transaction
4650 """roll back an interrupted transaction
4636
4651
4637 Recover from an interrupted commit or pull.
4652 Recover from an interrupted commit or pull.
4638
4653
4639 This command tries to fix the repository status after an
4654 This command tries to fix the repository status after an
4640 interrupted operation. It should only be necessary when Mercurial
4655 interrupted operation. It should only be necessary when Mercurial
4641 suggests it.
4656 suggests it.
4642
4657
4643 Returns 0 if successful, 1 if nothing to recover or verify fails.
4658 Returns 0 if successful, 1 if nothing to recover or verify fails.
4644 """
4659 """
4645 if repo.recover():
4660 if repo.recover():
4646 return hg.verify(repo)
4661 return hg.verify(repo)
4647 return 1
4662 return 1
4648
4663
4649 @command('^remove|rm',
4664 @command('^remove|rm',
4650 [('A', 'after', None, _('record delete for missing files')),
4665 [('A', 'after', None, _('record delete for missing files')),
4651 ('f', 'force', None,
4666 ('f', 'force', None,
4652 _('remove (and delete) file even if added or modified')),
4667 _('remove (and delete) file even if added or modified')),
4653 ] + walkopts,
4668 ] + walkopts,
4654 _('[OPTION]... FILE...'))
4669 _('[OPTION]... FILE...'))
4655 def remove(ui, repo, *pats, **opts):
4670 def remove(ui, repo, *pats, **opts):
4656 """remove the specified files on the next commit
4671 """remove the specified files on the next commit
4657
4672
4658 Schedule the indicated files for removal from the current branch.
4673 Schedule the indicated files for removal from the current branch.
4659
4674
4660 This command schedules the files to be removed at the next commit.
4675 This command schedules the files to be removed at the next commit.
4661 To undo a remove before that, see :hg:`revert`. To undo added
4676 To undo a remove before that, see :hg:`revert`. To undo added
4662 files, see :hg:`forget`.
4677 files, see :hg:`forget`.
4663
4678
4664 .. container:: verbose
4679 .. container:: verbose
4665
4680
4666 -A/--after can be used to remove only files that have already
4681 -A/--after can be used to remove only files that have already
4667 been deleted, -f/--force can be used to force deletion, and -Af
4682 been deleted, -f/--force can be used to force deletion, and -Af
4668 can be used to remove files from the next revision without
4683 can be used to remove files from the next revision without
4669 deleting them from the working directory.
4684 deleting them from the working directory.
4670
4685
4671 The following table details the behavior of remove for different
4686 The following table details the behavior of remove for different
4672 file states (columns) and option combinations (rows). The file
4687 file states (columns) and option combinations (rows). The file
4673 states are Added [A], Clean [C], Modified [M] and Missing [!]
4688 states are Added [A], Clean [C], Modified [M] and Missing [!]
4674 (as reported by :hg:`status`). The actions are Warn, Remove
4689 (as reported by :hg:`status`). The actions are Warn, Remove
4675 (from branch) and Delete (from disk):
4690 (from branch) and Delete (from disk):
4676
4691
4677 ======= == == == ==
4692 ======= == == == ==
4678 A C M !
4693 A C M !
4679 ======= == == == ==
4694 ======= == == == ==
4680 none W RD W R
4695 none W RD W R
4681 -f R RD RD R
4696 -f R RD RD R
4682 -A W W W R
4697 -A W W W R
4683 -Af R R R R
4698 -Af R R R R
4684 ======= == == == ==
4699 ======= == == == ==
4685
4700
4686 Note that remove never deletes files in Added [A] state from the
4701 Note that remove never deletes files in Added [A] state from the
4687 working directory, not even if option --force is specified.
4702 working directory, not even if option --force is specified.
4688
4703
4689 Returns 0 on success, 1 if any warnings encountered.
4704 Returns 0 on success, 1 if any warnings encountered.
4690 """
4705 """
4691
4706
4692 ret = 0
4707 ret = 0
4693 after, force = opts.get('after'), opts.get('force')
4708 after, force = opts.get('after'), opts.get('force')
4694 if not pats and not after:
4709 if not pats and not after:
4695 raise util.Abort(_('no files specified'))
4710 raise util.Abort(_('no files specified'))
4696
4711
4697 m = scmutil.match(repo[None], pats, opts)
4712 m = scmutil.match(repo[None], pats, opts)
4698 s = repo.status(match=m, clean=True)
4713 s = repo.status(match=m, clean=True)
4699 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4714 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4700
4715
4701 for f in m.files():
4716 for f in m.files():
4702 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4717 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
4703 if os.path.exists(m.rel(f)):
4718 if os.path.exists(m.rel(f)):
4704 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4719 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4705 ret = 1
4720 ret = 1
4706
4721
4707 if force:
4722 if force:
4708 list = modified + deleted + clean + added
4723 list = modified + deleted + clean + added
4709 elif after:
4724 elif after:
4710 list = deleted
4725 list = deleted
4711 for f in modified + added + clean:
4726 for f in modified + added + clean:
4712 ui.warn(_('not removing %s: file still exists (use -f'
4727 ui.warn(_('not removing %s: file still exists (use -f'
4713 ' to force removal)\n') % m.rel(f))
4728 ' to force removal)\n') % m.rel(f))
4714 ret = 1
4729 ret = 1
4715 else:
4730 else:
4716 list = deleted + clean
4731 list = deleted + clean
4717 for f in modified:
4732 for f in modified:
4718 ui.warn(_('not removing %s: file is modified (use -f'
4733 ui.warn(_('not removing %s: file is modified (use -f'
4719 ' to force removal)\n') % m.rel(f))
4734 ' to force removal)\n') % m.rel(f))
4720 ret = 1
4735 ret = 1
4721 for f in added:
4736 for f in added:
4722 ui.warn(_('not removing %s: file has been marked for add'
4737 ui.warn(_('not removing %s: file has been marked for add'
4723 ' (use forget to undo)\n') % m.rel(f))
4738 ' (use forget to undo)\n') % m.rel(f))
4724 ret = 1
4739 ret = 1
4725
4740
4726 for f in sorted(list):
4741 for f in sorted(list):
4727 if ui.verbose or not m.exact(f):
4742 if ui.verbose or not m.exact(f):
4728 ui.status(_('removing %s\n') % m.rel(f))
4743 ui.status(_('removing %s\n') % m.rel(f))
4729
4744
4730 wlock = repo.wlock()
4745 wlock = repo.wlock()
4731 try:
4746 try:
4732 if not after:
4747 if not after:
4733 for f in list:
4748 for f in list:
4734 if f in added:
4749 if f in added:
4735 continue # we never unlink added files on remove
4750 continue # we never unlink added files on remove
4736 try:
4751 try:
4737 util.unlinkpath(repo.wjoin(f))
4752 util.unlinkpath(repo.wjoin(f))
4738 except OSError, inst:
4753 except OSError, inst:
4739 if inst.errno != errno.ENOENT:
4754 if inst.errno != errno.ENOENT:
4740 raise
4755 raise
4741 repo[None].forget(list)
4756 repo[None].forget(list)
4742 finally:
4757 finally:
4743 wlock.release()
4758 wlock.release()
4744
4759
4745 return ret
4760 return ret
4746
4761
4747 @command('rename|move|mv',
4762 @command('rename|move|mv',
4748 [('A', 'after', None, _('record a rename that has already occurred')),
4763 [('A', 'after', None, _('record a rename that has already occurred')),
4749 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4764 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4750 ] + walkopts + dryrunopts,
4765 ] + walkopts + dryrunopts,
4751 _('[OPTION]... SOURCE... DEST'))
4766 _('[OPTION]... SOURCE... DEST'))
4752 def rename(ui, repo, *pats, **opts):
4767 def rename(ui, repo, *pats, **opts):
4753 """rename files; equivalent of copy + remove
4768 """rename files; equivalent of copy + remove
4754
4769
4755 Mark dest as copies of sources; mark sources for deletion. If dest
4770 Mark dest as copies of sources; mark sources for deletion. If dest
4756 is a directory, copies are put in that directory. If dest is a
4771 is a directory, copies are put in that directory. If dest is a
4757 file, there can only be one source.
4772 file, there can only be one source.
4758
4773
4759 By default, this command copies the contents of files as they
4774 By default, this command copies the contents of files as they
4760 exist in the working directory. If invoked with -A/--after, the
4775 exist in the working directory. If invoked with -A/--after, the
4761 operation is recorded, but no copying is performed.
4776 operation is recorded, but no copying is performed.
4762
4777
4763 This command takes effect at the next commit. To undo a rename
4778 This command takes effect at the next commit. To undo a rename
4764 before that, see :hg:`revert`.
4779 before that, see :hg:`revert`.
4765
4780
4766 Returns 0 on success, 1 if errors are encountered.
4781 Returns 0 on success, 1 if errors are encountered.
4767 """
4782 """
4768 wlock = repo.wlock(False)
4783 wlock = repo.wlock(False)
4769 try:
4784 try:
4770 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4785 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4771 finally:
4786 finally:
4772 wlock.release()
4787 wlock.release()
4773
4788
4774 @command('resolve',
4789 @command('resolve',
4775 [('a', 'all', None, _('select all unresolved files')),
4790 [('a', 'all', None, _('select all unresolved files')),
4776 ('l', 'list', None, _('list state of files needing merge')),
4791 ('l', 'list', None, _('list state of files needing merge')),
4777 ('m', 'mark', None, _('mark files as resolved')),
4792 ('m', 'mark', None, _('mark files as resolved')),
4778 ('u', 'unmark', None, _('mark files as unresolved')),
4793 ('u', 'unmark', None, _('mark files as unresolved')),
4779 ('n', 'no-status', None, _('hide status prefix'))]
4794 ('n', 'no-status', None, _('hide status prefix'))]
4780 + mergetoolopts + walkopts,
4795 + mergetoolopts + walkopts,
4781 _('[OPTION]... [FILE]...'))
4796 _('[OPTION]... [FILE]...'))
4782 def resolve(ui, repo, *pats, **opts):
4797 def resolve(ui, repo, *pats, **opts):
4783 """redo merges or set/view the merge status of files
4798 """redo merges or set/view the merge status of files
4784
4799
4785 Merges with unresolved conflicts are often the result of
4800 Merges with unresolved conflicts are often the result of
4786 non-interactive merging using the ``internal:merge`` configuration
4801 non-interactive merging using the ``internal:merge`` configuration
4787 setting, or a command-line merge tool like ``diff3``. The resolve
4802 setting, or a command-line merge tool like ``diff3``. The resolve
4788 command is used to manage the files involved in a merge, after
4803 command is used to manage the files involved in a merge, after
4789 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4804 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4790 working directory must have two parents). See :hg:`help
4805 working directory must have two parents). See :hg:`help
4791 merge-tools` for information on configuring merge tools.
4806 merge-tools` for information on configuring merge tools.
4792
4807
4793 The resolve command can be used in the following ways:
4808 The resolve command can be used in the following ways:
4794
4809
4795 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4810 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4796 files, discarding any previous merge attempts. Re-merging is not
4811 files, discarding any previous merge attempts. Re-merging is not
4797 performed for files already marked as resolved. Use ``--all/-a``
4812 performed for files already marked as resolved. Use ``--all/-a``
4798 to select all unresolved files. ``--tool`` can be used to specify
4813 to select all unresolved files. ``--tool`` can be used to specify
4799 the merge tool used for the given files. It overrides the HGMERGE
4814 the merge tool used for the given files. It overrides the HGMERGE
4800 environment variable and your configuration files. Previous file
4815 environment variable and your configuration files. Previous file
4801 contents are saved with a ``.orig`` suffix.
4816 contents are saved with a ``.orig`` suffix.
4802
4817
4803 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4818 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4804 (e.g. after having manually fixed-up the files). The default is
4819 (e.g. after having manually fixed-up the files). The default is
4805 to mark all unresolved files.
4820 to mark all unresolved files.
4806
4821
4807 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4822 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4808 default is to mark all resolved files.
4823 default is to mark all resolved files.
4809
4824
4810 - :hg:`resolve -l`: list files which had or still have conflicts.
4825 - :hg:`resolve -l`: list files which had or still have conflicts.
4811 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4826 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4812
4827
4813 Note that Mercurial will not let you commit files with unresolved
4828 Note that Mercurial will not let you commit files with unresolved
4814 merge conflicts. You must use :hg:`resolve -m ...` before you can
4829 merge conflicts. You must use :hg:`resolve -m ...` before you can
4815 commit after a conflicting merge.
4830 commit after a conflicting merge.
4816
4831
4817 Returns 0 on success, 1 if any files fail a resolve attempt.
4832 Returns 0 on success, 1 if any files fail a resolve attempt.
4818 """
4833 """
4819
4834
4820 all, mark, unmark, show, nostatus = \
4835 all, mark, unmark, show, nostatus = \
4821 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4836 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4822
4837
4823 if (show and (mark or unmark)) or (mark and unmark):
4838 if (show and (mark or unmark)) or (mark and unmark):
4824 raise util.Abort(_("too many options specified"))
4839 raise util.Abort(_("too many options specified"))
4825 if pats and all:
4840 if pats and all:
4826 raise util.Abort(_("can't specify --all and patterns"))
4841 raise util.Abort(_("can't specify --all and patterns"))
4827 if not (all or pats or show or mark or unmark):
4842 if not (all or pats or show or mark or unmark):
4828 raise util.Abort(_('no files or directories specified; '
4843 raise util.Abort(_('no files or directories specified; '
4829 'use --all to remerge all files'))
4844 'use --all to remerge all files'))
4830
4845
4831 ms = mergemod.mergestate(repo)
4846 ms = mergemod.mergestate(repo)
4832 m = scmutil.match(repo[None], pats, opts)
4847 m = scmutil.match(repo[None], pats, opts)
4833 ret = 0
4848 ret = 0
4834
4849
4835 for f in ms:
4850 for f in ms:
4836 if m(f):
4851 if m(f):
4837 if show:
4852 if show:
4838 if nostatus:
4853 if nostatus:
4839 ui.write("%s\n" % f)
4854 ui.write("%s\n" % f)
4840 else:
4855 else:
4841 ui.write("%s %s\n" % (ms[f].upper(), f),
4856 ui.write("%s %s\n" % (ms[f].upper(), f),
4842 label='resolve.' +
4857 label='resolve.' +
4843 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4858 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4844 elif mark:
4859 elif mark:
4845 ms.mark(f, "r")
4860 ms.mark(f, "r")
4846 elif unmark:
4861 elif unmark:
4847 ms.mark(f, "u")
4862 ms.mark(f, "u")
4848 else:
4863 else:
4849 wctx = repo[None]
4864 wctx = repo[None]
4850 mctx = wctx.parents()[-1]
4865 mctx = wctx.parents()[-1]
4851
4866
4852 # backup pre-resolve (merge uses .orig for its own purposes)
4867 # backup pre-resolve (merge uses .orig for its own purposes)
4853 a = repo.wjoin(f)
4868 a = repo.wjoin(f)
4854 util.copyfile(a, a + ".resolve")
4869 util.copyfile(a, a + ".resolve")
4855
4870
4856 try:
4871 try:
4857 # resolve file
4872 # resolve file
4858 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4873 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4859 if ms.resolve(f, wctx, mctx):
4874 if ms.resolve(f, wctx, mctx):
4860 ret = 1
4875 ret = 1
4861 finally:
4876 finally:
4862 ui.setconfig('ui', 'forcemerge', '')
4877 ui.setconfig('ui', 'forcemerge', '')
4863
4878
4864 # replace filemerge's .orig file with our resolve file
4879 # replace filemerge's .orig file with our resolve file
4865 util.rename(a + ".resolve", a + ".orig")
4880 util.rename(a + ".resolve", a + ".orig")
4866
4881
4867 ms.commit()
4882 ms.commit()
4868 return ret
4883 return ret
4869
4884
4870 @command('revert',
4885 @command('revert',
4871 [('a', 'all', None, _('revert all changes when no arguments given')),
4886 [('a', 'all', None, _('revert all changes when no arguments given')),
4872 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4887 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4873 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4888 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4874 ('C', 'no-backup', None, _('do not save backup copies of files')),
4889 ('C', 'no-backup', None, _('do not save backup copies of files')),
4875 ] + walkopts + dryrunopts,
4890 ] + walkopts + dryrunopts,
4876 _('[OPTION]... [-r REV] [NAME]...'))
4891 _('[OPTION]... [-r REV] [NAME]...'))
4877 def revert(ui, repo, *pats, **opts):
4892 def revert(ui, repo, *pats, **opts):
4878 """restore files to their checkout state
4893 """restore files to their checkout state
4879
4894
4880 .. note::
4895 .. note::
4881 To check out earlier revisions, you should use :hg:`update REV`.
4896 To check out earlier revisions, you should use :hg:`update REV`.
4882 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4897 To cancel a merge (and lose your changes), use :hg:`update --clean .`.
4883
4898
4884 With no revision specified, revert the specified files or directories
4899 With no revision specified, revert the specified files or directories
4885 to the contents they had in the parent of the working directory.
4900 to the contents they had in the parent of the working directory.
4886 This restores the contents of files to an unmodified
4901 This restores the contents of files to an unmodified
4887 state and unschedules adds, removes, copies, and renames. If the
4902 state and unschedules adds, removes, copies, and renames. If the
4888 working directory has two parents, you must explicitly specify a
4903 working directory has two parents, you must explicitly specify a
4889 revision.
4904 revision.
4890
4905
4891 Using the -r/--rev or -d/--date options, revert the given files or
4906 Using the -r/--rev or -d/--date options, revert the given files or
4892 directories to their states as of a specific revision. Because
4907 directories to their states as of a specific revision. Because
4893 revert does not change the working directory parents, this will
4908 revert does not change the working directory parents, this will
4894 cause these files to appear modified. This can be helpful to "back
4909 cause these files to appear modified. This can be helpful to "back
4895 out" some or all of an earlier change. See :hg:`backout` for a
4910 out" some or all of an earlier change. See :hg:`backout` for a
4896 related method.
4911 related method.
4897
4912
4898 Modified files are saved with a .orig suffix before reverting.
4913 Modified files are saved with a .orig suffix before reverting.
4899 To disable these backups, use --no-backup.
4914 To disable these backups, use --no-backup.
4900
4915
4901 See :hg:`help dates` for a list of formats valid for -d/--date.
4916 See :hg:`help dates` for a list of formats valid for -d/--date.
4902
4917
4903 Returns 0 on success.
4918 Returns 0 on success.
4904 """
4919 """
4905
4920
4906 if opts.get("date"):
4921 if opts.get("date"):
4907 if opts.get("rev"):
4922 if opts.get("rev"):
4908 raise util.Abort(_("you can't specify a revision and a date"))
4923 raise util.Abort(_("you can't specify a revision and a date"))
4909 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4924 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4910
4925
4911 parent, p2 = repo.dirstate.parents()
4926 parent, p2 = repo.dirstate.parents()
4912 if not opts.get('rev') and p2 != nullid:
4927 if not opts.get('rev') and p2 != nullid:
4913 # revert after merge is a trap for new users (issue2915)
4928 # revert after merge is a trap for new users (issue2915)
4914 raise util.Abort(_('uncommitted merge with no revision specified'),
4929 raise util.Abort(_('uncommitted merge with no revision specified'),
4915 hint=_('use "hg update" or see "hg help revert"'))
4930 hint=_('use "hg update" or see "hg help revert"'))
4916
4931
4917 ctx = scmutil.revsingle(repo, opts.get('rev'))
4932 ctx = scmutil.revsingle(repo, opts.get('rev'))
4918
4933
4919 if not pats and not opts.get('all'):
4934 if not pats and not opts.get('all'):
4920 msg = _("no files or directories specified")
4935 msg = _("no files or directories specified")
4921 if p2 != nullid:
4936 if p2 != nullid:
4922 hint = _("uncommitted merge, use --all to discard all changes,"
4937 hint = _("uncommitted merge, use --all to discard all changes,"
4923 " or 'hg update -C .' to abort the merge")
4938 " or 'hg update -C .' to abort the merge")
4924 raise util.Abort(msg, hint=hint)
4939 raise util.Abort(msg, hint=hint)
4925 dirty = util.any(repo.status())
4940 dirty = util.any(repo.status())
4926 node = ctx.node()
4941 node = ctx.node()
4927 if node != parent:
4942 if node != parent:
4928 if dirty:
4943 if dirty:
4929 hint = _("uncommitted changes, use --all to discard all"
4944 hint = _("uncommitted changes, use --all to discard all"
4930 " changes, or 'hg update %s' to update") % ctx.rev()
4945 " changes, or 'hg update %s' to update") % ctx.rev()
4931 else:
4946 else:
4932 hint = _("use --all to revert all files,"
4947 hint = _("use --all to revert all files,"
4933 " or 'hg update %s' to update") % ctx.rev()
4948 " or 'hg update %s' to update") % ctx.rev()
4934 elif dirty:
4949 elif dirty:
4935 hint = _("uncommitted changes, use --all to discard all changes")
4950 hint = _("uncommitted changes, use --all to discard all changes")
4936 else:
4951 else:
4937 hint = _("use --all to revert all files")
4952 hint = _("use --all to revert all files")
4938 raise util.Abort(msg, hint=hint)
4953 raise util.Abort(msg, hint=hint)
4939
4954
4940 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4955 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
4941
4956
4942 @command('rollback', dryrunopts +
4957 @command('rollback', dryrunopts +
4943 [('f', 'force', False, _('ignore safety measures'))])
4958 [('f', 'force', False, _('ignore safety measures'))])
4944 def rollback(ui, repo, **opts):
4959 def rollback(ui, repo, **opts):
4945 """roll back the last transaction (dangerous)
4960 """roll back the last transaction (dangerous)
4946
4961
4947 This command should be used with care. There is only one level of
4962 This command should be used with care. There is only one level of
4948 rollback, and there is no way to undo a rollback. It will also
4963 rollback, and there is no way to undo a rollback. It will also
4949 restore the dirstate at the time of the last transaction, losing
4964 restore the dirstate at the time of the last transaction, losing
4950 any dirstate changes since that time. This command does not alter
4965 any dirstate changes since that time. This command does not alter
4951 the working directory.
4966 the working directory.
4952
4967
4953 Transactions are used to encapsulate the effects of all commands
4968 Transactions are used to encapsulate the effects of all commands
4954 that create new changesets or propagate existing changesets into a
4969 that create new changesets or propagate existing changesets into a
4955 repository. For example, the following commands are transactional,
4970 repository. For example, the following commands are transactional,
4956 and their effects can be rolled back:
4971 and their effects can be rolled back:
4957
4972
4958 - commit
4973 - commit
4959 - import
4974 - import
4960 - pull
4975 - pull
4961 - push (with this repository as the destination)
4976 - push (with this repository as the destination)
4962 - unbundle
4977 - unbundle
4963
4978
4964 To avoid permanent data loss, rollback will refuse to rollback a
4979 To avoid permanent data loss, rollback will refuse to rollback a
4965 commit transaction if it isn't checked out. Use --force to
4980 commit transaction if it isn't checked out. Use --force to
4966 override this protection.
4981 override this protection.
4967
4982
4968 This command is not intended for use on public repositories. Once
4983 This command is not intended for use on public repositories. Once
4969 changes are visible for pull by other users, rolling a transaction
4984 changes are visible for pull by other users, rolling a transaction
4970 back locally is ineffective (someone else may already have pulled
4985 back locally is ineffective (someone else may already have pulled
4971 the changes). Furthermore, a race is possible with readers of the
4986 the changes). Furthermore, a race is possible with readers of the
4972 repository; for example an in-progress pull from the repository
4987 repository; for example an in-progress pull from the repository
4973 may fail if a rollback is performed.
4988 may fail if a rollback is performed.
4974
4989
4975 Returns 0 on success, 1 if no rollback data is available.
4990 Returns 0 on success, 1 if no rollback data is available.
4976 """
4991 """
4977 return repo.rollback(dryrun=opts.get('dry_run'),
4992 return repo.rollback(dryrun=opts.get('dry_run'),
4978 force=opts.get('force'))
4993 force=opts.get('force'))
4979
4994
4980 @command('root', [])
4995 @command('root', [])
4981 def root(ui, repo):
4996 def root(ui, repo):
4982 """print the root (top) of the current working directory
4997 """print the root (top) of the current working directory
4983
4998
4984 Print the root directory of the current repository.
4999 Print the root directory of the current repository.
4985
5000
4986 Returns 0 on success.
5001 Returns 0 on success.
4987 """
5002 """
4988 ui.write(repo.root + "\n")
5003 ui.write(repo.root + "\n")
4989
5004
4990 @command('^serve',
5005 @command('^serve',
4991 [('A', 'accesslog', '', _('name of access log file to write to'),
5006 [('A', 'accesslog', '', _('name of access log file to write to'),
4992 _('FILE')),
5007 _('FILE')),
4993 ('d', 'daemon', None, _('run server in background')),
5008 ('d', 'daemon', None, _('run server in background')),
4994 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5009 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
4995 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5010 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
4996 # use string type, then we can check if something was passed
5011 # use string type, then we can check if something was passed
4997 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5012 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
4998 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5013 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
4999 _('ADDR')),
5014 _('ADDR')),
5000 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5015 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5001 _('PREFIX')),
5016 _('PREFIX')),
5002 ('n', 'name', '',
5017 ('n', 'name', '',
5003 _('name to show in web pages (default: working directory)'), _('NAME')),
5018 _('name to show in web pages (default: working directory)'), _('NAME')),
5004 ('', 'web-conf', '',
5019 ('', 'web-conf', '',
5005 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5020 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5006 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5021 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5007 _('FILE')),
5022 _('FILE')),
5008 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5023 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5009 ('', 'stdio', None, _('for remote clients')),
5024 ('', 'stdio', None, _('for remote clients')),
5010 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5025 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5011 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5026 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5012 ('', 'style', '', _('template style to use'), _('STYLE')),
5027 ('', 'style', '', _('template style to use'), _('STYLE')),
5013 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5028 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5014 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5029 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5015 _('[OPTION]...'))
5030 _('[OPTION]...'))
5016 def serve(ui, repo, **opts):
5031 def serve(ui, repo, **opts):
5017 """start stand-alone webserver
5032 """start stand-alone webserver
5018
5033
5019 Start a local HTTP repository browser and pull server. You can use
5034 Start a local HTTP repository browser and pull server. You can use
5020 this for ad-hoc sharing and browsing of repositories. It is
5035 this for ad-hoc sharing and browsing of repositories. It is
5021 recommended to use a real web server to serve a repository for
5036 recommended to use a real web server to serve a repository for
5022 longer periods of time.
5037 longer periods of time.
5023
5038
5024 Please note that the server does not implement access control.
5039 Please note that the server does not implement access control.
5025 This means that, by default, anybody can read from the server and
5040 This means that, by default, anybody can read from the server and
5026 nobody can write to it by default. Set the ``web.allow_push``
5041 nobody can write to it by default. Set the ``web.allow_push``
5027 option to ``*`` to allow everybody to push to the server. You
5042 option to ``*`` to allow everybody to push to the server. You
5028 should use a real web server if you need to authenticate users.
5043 should use a real web server if you need to authenticate users.
5029
5044
5030 By default, the server logs accesses to stdout and errors to
5045 By default, the server logs accesses to stdout and errors to
5031 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5046 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5032 files.
5047 files.
5033
5048
5034 To have the server choose a free port number to listen on, specify
5049 To have the server choose a free port number to listen on, specify
5035 a port number of 0; in this case, the server will print the port
5050 a port number of 0; in this case, the server will print the port
5036 number it uses.
5051 number it uses.
5037
5052
5038 Returns 0 on success.
5053 Returns 0 on success.
5039 """
5054 """
5040
5055
5041 if opts["stdio"] and opts["cmdserver"]:
5056 if opts["stdio"] and opts["cmdserver"]:
5042 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5057 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5043
5058
5044 def checkrepo():
5059 def checkrepo():
5045 if repo is None:
5060 if repo is None:
5046 raise error.RepoError(_("there is no Mercurial repository here"
5061 raise error.RepoError(_("there is no Mercurial repository here"
5047 " (.hg not found)"))
5062 " (.hg not found)"))
5048
5063
5049 if opts["stdio"]:
5064 if opts["stdio"]:
5050 checkrepo()
5065 checkrepo()
5051 s = sshserver.sshserver(ui, repo)
5066 s = sshserver.sshserver(ui, repo)
5052 s.serve_forever()
5067 s.serve_forever()
5053
5068
5054 if opts["cmdserver"]:
5069 if opts["cmdserver"]:
5055 checkrepo()
5070 checkrepo()
5056 s = commandserver.server(ui, repo, opts["cmdserver"])
5071 s = commandserver.server(ui, repo, opts["cmdserver"])
5057 return s.serve()
5072 return s.serve()
5058
5073
5059 # this way we can check if something was given in the command-line
5074 # this way we can check if something was given in the command-line
5060 if opts.get('port'):
5075 if opts.get('port'):
5061 opts['port'] = util.getport(opts.get('port'))
5076 opts['port'] = util.getport(opts.get('port'))
5062
5077
5063 baseui = repo and repo.baseui or ui
5078 baseui = repo and repo.baseui or ui
5064 optlist = ("name templates style address port prefix ipv6"
5079 optlist = ("name templates style address port prefix ipv6"
5065 " accesslog errorlog certificate encoding")
5080 " accesslog errorlog certificate encoding")
5066 for o in optlist.split():
5081 for o in optlist.split():
5067 val = opts.get(o, '')
5082 val = opts.get(o, '')
5068 if val in (None, ''): # should check against default options instead
5083 if val in (None, ''): # should check against default options instead
5069 continue
5084 continue
5070 baseui.setconfig("web", o, val)
5085 baseui.setconfig("web", o, val)
5071 if repo and repo.ui != baseui:
5086 if repo and repo.ui != baseui:
5072 repo.ui.setconfig("web", o, val)
5087 repo.ui.setconfig("web", o, val)
5073
5088
5074 o = opts.get('web_conf') or opts.get('webdir_conf')
5089 o = opts.get('web_conf') or opts.get('webdir_conf')
5075 if not o:
5090 if not o:
5076 if not repo:
5091 if not repo:
5077 raise error.RepoError(_("there is no Mercurial repository"
5092 raise error.RepoError(_("there is no Mercurial repository"
5078 " here (.hg not found)"))
5093 " here (.hg not found)"))
5079 o = repo.root
5094 o = repo.root
5080
5095
5081 app = hgweb.hgweb(o, baseui=ui)
5096 app = hgweb.hgweb(o, baseui=ui)
5082
5097
5083 class service(object):
5098 class service(object):
5084 def init(self):
5099 def init(self):
5085 util.setsignalhandler()
5100 util.setsignalhandler()
5086 self.httpd = hgweb.server.create_server(ui, app)
5101 self.httpd = hgweb.server.create_server(ui, app)
5087
5102
5088 if opts['port'] and not ui.verbose:
5103 if opts['port'] and not ui.verbose:
5089 return
5104 return
5090
5105
5091 if self.httpd.prefix:
5106 if self.httpd.prefix:
5092 prefix = self.httpd.prefix.strip('/') + '/'
5107 prefix = self.httpd.prefix.strip('/') + '/'
5093 else:
5108 else:
5094 prefix = ''
5109 prefix = ''
5095
5110
5096 port = ':%d' % self.httpd.port
5111 port = ':%d' % self.httpd.port
5097 if port == ':80':
5112 if port == ':80':
5098 port = ''
5113 port = ''
5099
5114
5100 bindaddr = self.httpd.addr
5115 bindaddr = self.httpd.addr
5101 if bindaddr == '0.0.0.0':
5116 if bindaddr == '0.0.0.0':
5102 bindaddr = '*'
5117 bindaddr = '*'
5103 elif ':' in bindaddr: # IPv6
5118 elif ':' in bindaddr: # IPv6
5104 bindaddr = '[%s]' % bindaddr
5119 bindaddr = '[%s]' % bindaddr
5105
5120
5106 fqaddr = self.httpd.fqaddr
5121 fqaddr = self.httpd.fqaddr
5107 if ':' in fqaddr:
5122 if ':' in fqaddr:
5108 fqaddr = '[%s]' % fqaddr
5123 fqaddr = '[%s]' % fqaddr
5109 if opts['port']:
5124 if opts['port']:
5110 write = ui.status
5125 write = ui.status
5111 else:
5126 else:
5112 write = ui.write
5127 write = ui.write
5113 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5128 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5114 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5129 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5115
5130
5116 def run(self):
5131 def run(self):
5117 self.httpd.serve_forever()
5132 self.httpd.serve_forever()
5118
5133
5119 service = service()
5134 service = service()
5120
5135
5121 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5136 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5122
5137
5123 @command('showconfig|debugconfig',
5138 @command('showconfig|debugconfig',
5124 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5139 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5125 _('[-u] [NAME]...'))
5140 _('[-u] [NAME]...'))
5126 def showconfig(ui, repo, *values, **opts):
5141 def showconfig(ui, repo, *values, **opts):
5127 """show combined config settings from all hgrc files
5142 """show combined config settings from all hgrc files
5128
5143
5129 With no arguments, print names and values of all config items.
5144 With no arguments, print names and values of all config items.
5130
5145
5131 With one argument of the form section.name, print just the value
5146 With one argument of the form section.name, print just the value
5132 of that config item.
5147 of that config item.
5133
5148
5134 With multiple arguments, print names and values of all config
5149 With multiple arguments, print names and values of all config
5135 items with matching section names.
5150 items with matching section names.
5136
5151
5137 With --debug, the source (filename and line number) is printed
5152 With --debug, the source (filename and line number) is printed
5138 for each config item.
5153 for each config item.
5139
5154
5140 Returns 0 on success.
5155 Returns 0 on success.
5141 """
5156 """
5142
5157
5143 for f in scmutil.rcpath():
5158 for f in scmutil.rcpath():
5144 ui.debug('read config from: %s\n' % f)
5159 ui.debug('read config from: %s\n' % f)
5145 untrusted = bool(opts.get('untrusted'))
5160 untrusted = bool(opts.get('untrusted'))
5146 if values:
5161 if values:
5147 sections = [v for v in values if '.' not in v]
5162 sections = [v for v in values if '.' not in v]
5148 items = [v for v in values if '.' in v]
5163 items = [v for v in values if '.' in v]
5149 if len(items) > 1 or items and sections:
5164 if len(items) > 1 or items and sections:
5150 raise util.Abort(_('only one config item permitted'))
5165 raise util.Abort(_('only one config item permitted'))
5151 for section, name, value in ui.walkconfig(untrusted=untrusted):
5166 for section, name, value in ui.walkconfig(untrusted=untrusted):
5152 value = str(value).replace('\n', '\\n')
5167 value = str(value).replace('\n', '\\n')
5153 sectname = section + '.' + name
5168 sectname = section + '.' + name
5154 if values:
5169 if values:
5155 for v in values:
5170 for v in values:
5156 if v == section:
5171 if v == section:
5157 ui.debug('%s: ' %
5172 ui.debug('%s: ' %
5158 ui.configsource(section, name, untrusted))
5173 ui.configsource(section, name, untrusted))
5159 ui.write('%s=%s\n' % (sectname, value))
5174 ui.write('%s=%s\n' % (sectname, value))
5160 elif v == sectname:
5175 elif v == sectname:
5161 ui.debug('%s: ' %
5176 ui.debug('%s: ' %
5162 ui.configsource(section, name, untrusted))
5177 ui.configsource(section, name, untrusted))
5163 ui.write(value, '\n')
5178 ui.write(value, '\n')
5164 else:
5179 else:
5165 ui.debug('%s: ' %
5180 ui.debug('%s: ' %
5166 ui.configsource(section, name, untrusted))
5181 ui.configsource(section, name, untrusted))
5167 ui.write('%s=%s\n' % (sectname, value))
5182 ui.write('%s=%s\n' % (sectname, value))
5168
5183
5169 @command('^status|st',
5184 @command('^status|st',
5170 [('A', 'all', None, _('show status of all files')),
5185 [('A', 'all', None, _('show status of all files')),
5171 ('m', 'modified', None, _('show only modified files')),
5186 ('m', 'modified', None, _('show only modified files')),
5172 ('a', 'added', None, _('show only added files')),
5187 ('a', 'added', None, _('show only added files')),
5173 ('r', 'removed', None, _('show only removed files')),
5188 ('r', 'removed', None, _('show only removed files')),
5174 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5189 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5175 ('c', 'clean', None, _('show only files without changes')),
5190 ('c', 'clean', None, _('show only files without changes')),
5176 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5191 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5177 ('i', 'ignored', None, _('show only ignored files')),
5192 ('i', 'ignored', None, _('show only ignored files')),
5178 ('n', 'no-status', None, _('hide status prefix')),
5193 ('n', 'no-status', None, _('hide status prefix')),
5179 ('C', 'copies', None, _('show source of copied files')),
5194 ('C', 'copies', None, _('show source of copied files')),
5180 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5195 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5181 ('', 'rev', [], _('show difference from revision'), _('REV')),
5196 ('', 'rev', [], _('show difference from revision'), _('REV')),
5182 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5197 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5183 ] + walkopts + subrepoopts,
5198 ] + walkopts + subrepoopts,
5184 _('[OPTION]... [FILE]...'))
5199 _('[OPTION]... [FILE]...'))
5185 def status(ui, repo, *pats, **opts):
5200 def status(ui, repo, *pats, **opts):
5186 """show changed files in the working directory
5201 """show changed files in the working directory
5187
5202
5188 Show status of files in the repository. If names are given, only
5203 Show status of files in the repository. If names are given, only
5189 files that match are shown. Files that are clean or ignored or
5204 files that match are shown. Files that are clean or ignored or
5190 the source of a copy/move operation, are not listed unless
5205 the source of a copy/move operation, are not listed unless
5191 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5206 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5192 Unless options described with "show only ..." are given, the
5207 Unless options described with "show only ..." are given, the
5193 options -mardu are used.
5208 options -mardu are used.
5194
5209
5195 Option -q/--quiet hides untracked (unknown and ignored) files
5210 Option -q/--quiet hides untracked (unknown and ignored) files
5196 unless explicitly requested with -u/--unknown or -i/--ignored.
5211 unless explicitly requested with -u/--unknown or -i/--ignored.
5197
5212
5198 .. note::
5213 .. note::
5199 status may appear to disagree with diff if permissions have
5214 status may appear to disagree with diff if permissions have
5200 changed or a merge has occurred. The standard diff format does
5215 changed or a merge has occurred. The standard diff format does
5201 not report permission changes and diff only reports changes
5216 not report permission changes and diff only reports changes
5202 relative to one merge parent.
5217 relative to one merge parent.
5203
5218
5204 If one revision is given, it is used as the base revision.
5219 If one revision is given, it is used as the base revision.
5205 If two revisions are given, the differences between them are
5220 If two revisions are given, the differences between them are
5206 shown. The --change option can also be used as a shortcut to list
5221 shown. The --change option can also be used as a shortcut to list
5207 the changed files of a revision from its first parent.
5222 the changed files of a revision from its first parent.
5208
5223
5209 The codes used to show the status of files are::
5224 The codes used to show the status of files are::
5210
5225
5211 M = modified
5226 M = modified
5212 A = added
5227 A = added
5213 R = removed
5228 R = removed
5214 C = clean
5229 C = clean
5215 ! = missing (deleted by non-hg command, but still tracked)
5230 ! = missing (deleted by non-hg command, but still tracked)
5216 ? = not tracked
5231 ? = not tracked
5217 I = ignored
5232 I = ignored
5218 = origin of the previous file listed as A (added)
5233 = origin of the previous file listed as A (added)
5219
5234
5220 .. container:: verbose
5235 .. container:: verbose
5221
5236
5222 Examples:
5237 Examples:
5223
5238
5224 - show changes in the working directory relative to a
5239 - show changes in the working directory relative to a
5225 changeset::
5240 changeset::
5226
5241
5227 hg status --rev 9353
5242 hg status --rev 9353
5228
5243
5229 - show all changes including copies in an existing changeset::
5244 - show all changes including copies in an existing changeset::
5230
5245
5231 hg status --copies --change 9353
5246 hg status --copies --change 9353
5232
5247
5233 - get a NUL separated list of added files, suitable for xargs::
5248 - get a NUL separated list of added files, suitable for xargs::
5234
5249
5235 hg status -an0
5250 hg status -an0
5236
5251
5237 Returns 0 on success.
5252 Returns 0 on success.
5238 """
5253 """
5239
5254
5240 revs = opts.get('rev')
5255 revs = opts.get('rev')
5241 change = opts.get('change')
5256 change = opts.get('change')
5242
5257
5243 if revs and change:
5258 if revs and change:
5244 msg = _('cannot specify --rev and --change at the same time')
5259 msg = _('cannot specify --rev and --change at the same time')
5245 raise util.Abort(msg)
5260 raise util.Abort(msg)
5246 elif change:
5261 elif change:
5247 node2 = scmutil.revsingle(repo, change, None).node()
5262 node2 = scmutil.revsingle(repo, change, None).node()
5248 node1 = repo[node2].p1().node()
5263 node1 = repo[node2].p1().node()
5249 else:
5264 else:
5250 node1, node2 = scmutil.revpair(repo, revs)
5265 node1, node2 = scmutil.revpair(repo, revs)
5251
5266
5252 cwd = (pats and repo.getcwd()) or ''
5267 cwd = (pats and repo.getcwd()) or ''
5253 end = opts.get('print0') and '\0' or '\n'
5268 end = opts.get('print0') and '\0' or '\n'
5254 copy = {}
5269 copy = {}
5255 states = 'modified added removed deleted unknown ignored clean'.split()
5270 states = 'modified added removed deleted unknown ignored clean'.split()
5256 show = [k for k in states if opts.get(k)]
5271 show = [k for k in states if opts.get(k)]
5257 if opts.get('all'):
5272 if opts.get('all'):
5258 show += ui.quiet and (states[:4] + ['clean']) or states
5273 show += ui.quiet and (states[:4] + ['clean']) or states
5259 if not show:
5274 if not show:
5260 show = ui.quiet and states[:4] or states[:5]
5275 show = ui.quiet and states[:4] or states[:5]
5261
5276
5262 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5277 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5263 'ignored' in show, 'clean' in show, 'unknown' in show,
5278 'ignored' in show, 'clean' in show, 'unknown' in show,
5264 opts.get('subrepos'))
5279 opts.get('subrepos'))
5265 changestates = zip(states, 'MAR!?IC', stat)
5280 changestates = zip(states, 'MAR!?IC', stat)
5266
5281
5267 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5282 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5268 copy = copies.pathcopies(repo[node1], repo[node2])
5283 copy = copies.pathcopies(repo[node1], repo[node2])
5269
5284
5270 fm = ui.formatter('status', opts)
5285 fm = ui.formatter('status', opts)
5271 format = '%s %s' + end
5286 format = '%s %s' + end
5272 if opts.get('no_status'):
5287 if opts.get('no_status'):
5273 format = '%.0s%s' + end
5288 format = '%.0s%s' + end
5274
5289
5275 for state, char, files in changestates:
5290 for state, char, files in changestates:
5276 if state in show:
5291 if state in show:
5277 label = 'status.' + state
5292 label = 'status.' + state
5278 for f in files:
5293 for f in files:
5279 fm.startitem()
5294 fm.startitem()
5280 fm.write("status path", format, char,
5295 fm.write("status path", format, char,
5281 repo.pathto(f, cwd), label=label)
5296 repo.pathto(f, cwd), label=label)
5282 if f in copy:
5297 if f in copy:
5283 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5298 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5284 label='status.copied')
5299 label='status.copied')
5285 fm.end()
5300 fm.end()
5286
5301
5287 @command('^summary|sum',
5302 @command('^summary|sum',
5288 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5303 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5289 def summary(ui, repo, **opts):
5304 def summary(ui, repo, **opts):
5290 """summarize working directory state
5305 """summarize working directory state
5291
5306
5292 This generates a brief summary of the working directory state,
5307 This generates a brief summary of the working directory state,
5293 including parents, branch, commit status, and available updates.
5308 including parents, branch, commit status, and available updates.
5294
5309
5295 With the --remote option, this will check the default paths for
5310 With the --remote option, this will check the default paths for
5296 incoming and outgoing changes. This can be time-consuming.
5311 incoming and outgoing changes. This can be time-consuming.
5297
5312
5298 Returns 0 on success.
5313 Returns 0 on success.
5299 """
5314 """
5300
5315
5301 ctx = repo[None]
5316 ctx = repo[None]
5302 parents = ctx.parents()
5317 parents = ctx.parents()
5303 pnode = parents[0].node()
5318 pnode = parents[0].node()
5304 marks = []
5319 marks = []
5305
5320
5306 for p in parents:
5321 for p in parents:
5307 # label with log.changeset (instead of log.parent) since this
5322 # label with log.changeset (instead of log.parent) since this
5308 # shows a working directory parent *changeset*:
5323 # shows a working directory parent *changeset*:
5309 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5324 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5310 label='log.changeset')
5325 label='log.changeset')
5311 ui.write(' '.join(p.tags()), label='log.tag')
5326 ui.write(' '.join(p.tags()), label='log.tag')
5312 if p.bookmarks():
5327 if p.bookmarks():
5313 marks.extend(p.bookmarks())
5328 marks.extend(p.bookmarks())
5314 if p.rev() == -1:
5329 if p.rev() == -1:
5315 if not len(repo):
5330 if not len(repo):
5316 ui.write(_(' (empty repository)'))
5331 ui.write(_(' (empty repository)'))
5317 else:
5332 else:
5318 ui.write(_(' (no revision checked out)'))
5333 ui.write(_(' (no revision checked out)'))
5319 ui.write('\n')
5334 ui.write('\n')
5320 if p.description():
5335 if p.description():
5321 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5336 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5322 label='log.summary')
5337 label='log.summary')
5323
5338
5324 branch = ctx.branch()
5339 branch = ctx.branch()
5325 bheads = repo.branchheads(branch)
5340 bheads = repo.branchheads(branch)
5326 m = _('branch: %s\n') % branch
5341 m = _('branch: %s\n') % branch
5327 if branch != 'default':
5342 if branch != 'default':
5328 ui.write(m, label='log.branch')
5343 ui.write(m, label='log.branch')
5329 else:
5344 else:
5330 ui.status(m, label='log.branch')
5345 ui.status(m, label='log.branch')
5331
5346
5332 if marks:
5347 if marks:
5333 current = repo._bookmarkcurrent
5348 current = repo._bookmarkcurrent
5334 ui.write(_('bookmarks:'), label='log.bookmark')
5349 ui.write(_('bookmarks:'), label='log.bookmark')
5335 if current is not None:
5350 if current is not None:
5336 try:
5351 try:
5337 marks.remove(current)
5352 marks.remove(current)
5338 ui.write(' *' + current, label='bookmarks.current')
5353 ui.write(' *' + current, label='bookmarks.current')
5339 except ValueError:
5354 except ValueError:
5340 # current bookmark not in parent ctx marks
5355 # current bookmark not in parent ctx marks
5341 pass
5356 pass
5342 for m in marks:
5357 for m in marks:
5343 ui.write(' ' + m, label='log.bookmark')
5358 ui.write(' ' + m, label='log.bookmark')
5344 ui.write('\n', label='log.bookmark')
5359 ui.write('\n', label='log.bookmark')
5345
5360
5346 st = list(repo.status(unknown=True))[:6]
5361 st = list(repo.status(unknown=True))[:6]
5347
5362
5348 c = repo.dirstate.copies()
5363 c = repo.dirstate.copies()
5349 copied, renamed = [], []
5364 copied, renamed = [], []
5350 for d, s in c.iteritems():
5365 for d, s in c.iteritems():
5351 if s in st[2]:
5366 if s in st[2]:
5352 st[2].remove(s)
5367 st[2].remove(s)
5353 renamed.append(d)
5368 renamed.append(d)
5354 else:
5369 else:
5355 copied.append(d)
5370 copied.append(d)
5356 if d in st[1]:
5371 if d in st[1]:
5357 st[1].remove(d)
5372 st[1].remove(d)
5358 st.insert(3, renamed)
5373 st.insert(3, renamed)
5359 st.insert(4, copied)
5374 st.insert(4, copied)
5360
5375
5361 ms = mergemod.mergestate(repo)
5376 ms = mergemod.mergestate(repo)
5362 st.append([f for f in ms if ms[f] == 'u'])
5377 st.append([f for f in ms if ms[f] == 'u'])
5363
5378
5364 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5379 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5365 st.append(subs)
5380 st.append(subs)
5366
5381
5367 labels = [ui.label(_('%d modified'), 'status.modified'),
5382 labels = [ui.label(_('%d modified'), 'status.modified'),
5368 ui.label(_('%d added'), 'status.added'),
5383 ui.label(_('%d added'), 'status.added'),
5369 ui.label(_('%d removed'), 'status.removed'),
5384 ui.label(_('%d removed'), 'status.removed'),
5370 ui.label(_('%d renamed'), 'status.copied'),
5385 ui.label(_('%d renamed'), 'status.copied'),
5371 ui.label(_('%d copied'), 'status.copied'),
5386 ui.label(_('%d copied'), 'status.copied'),
5372 ui.label(_('%d deleted'), 'status.deleted'),
5387 ui.label(_('%d deleted'), 'status.deleted'),
5373 ui.label(_('%d unknown'), 'status.unknown'),
5388 ui.label(_('%d unknown'), 'status.unknown'),
5374 ui.label(_('%d ignored'), 'status.ignored'),
5389 ui.label(_('%d ignored'), 'status.ignored'),
5375 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5390 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5376 ui.label(_('%d subrepos'), 'status.modified')]
5391 ui.label(_('%d subrepos'), 'status.modified')]
5377 t = []
5392 t = []
5378 for s, l in zip(st, labels):
5393 for s, l in zip(st, labels):
5379 if s:
5394 if s:
5380 t.append(l % len(s))
5395 t.append(l % len(s))
5381
5396
5382 t = ', '.join(t)
5397 t = ', '.join(t)
5383 cleanworkdir = False
5398 cleanworkdir = False
5384
5399
5385 if len(parents) > 1:
5400 if len(parents) > 1:
5386 t += _(' (merge)')
5401 t += _(' (merge)')
5387 elif branch != parents[0].branch():
5402 elif branch != parents[0].branch():
5388 t += _(' (new branch)')
5403 t += _(' (new branch)')
5389 elif (parents[0].closesbranch() and
5404 elif (parents[0].closesbranch() and
5390 pnode in repo.branchheads(branch, closed=True)):
5405 pnode in repo.branchheads(branch, closed=True)):
5391 t += _(' (head closed)')
5406 t += _(' (head closed)')
5392 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5407 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5393 t += _(' (clean)')
5408 t += _(' (clean)')
5394 cleanworkdir = True
5409 cleanworkdir = True
5395 elif pnode not in bheads:
5410 elif pnode not in bheads:
5396 t += _(' (new branch head)')
5411 t += _(' (new branch head)')
5397
5412
5398 if cleanworkdir:
5413 if cleanworkdir:
5399 ui.status(_('commit: %s\n') % t.strip())
5414 ui.status(_('commit: %s\n') % t.strip())
5400 else:
5415 else:
5401 ui.write(_('commit: %s\n') % t.strip())
5416 ui.write(_('commit: %s\n') % t.strip())
5402
5417
5403 # all ancestors of branch heads - all ancestors of parent = new csets
5418 # all ancestors of branch heads - all ancestors of parent = new csets
5404 new = [0] * len(repo)
5419 new = [0] * len(repo)
5405 cl = repo.changelog
5420 cl = repo.changelog
5406 for a in [cl.rev(n) for n in bheads]:
5421 for a in [cl.rev(n) for n in bheads]:
5407 new[a] = 1
5422 new[a] = 1
5408 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5423 for a in cl.ancestors([cl.rev(n) for n in bheads]):
5409 new[a] = 1
5424 new[a] = 1
5410 for a in [p.rev() for p in parents]:
5425 for a in [p.rev() for p in parents]:
5411 if a >= 0:
5426 if a >= 0:
5412 new[a] = 0
5427 new[a] = 0
5413 for a in cl.ancestors([p.rev() for p in parents]):
5428 for a in cl.ancestors([p.rev() for p in parents]):
5414 new[a] = 0
5429 new[a] = 0
5415 new = sum(new)
5430 new = sum(new)
5416
5431
5417 if new == 0:
5432 if new == 0:
5418 ui.status(_('update: (current)\n'))
5433 ui.status(_('update: (current)\n'))
5419 elif pnode not in bheads:
5434 elif pnode not in bheads:
5420 ui.write(_('update: %d new changesets (update)\n') % new)
5435 ui.write(_('update: %d new changesets (update)\n') % new)
5421 else:
5436 else:
5422 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5437 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5423 (new, len(bheads)))
5438 (new, len(bheads)))
5424
5439
5425 if opts.get('remote'):
5440 if opts.get('remote'):
5426 t = []
5441 t = []
5427 source, branches = hg.parseurl(ui.expandpath('default'))
5442 source, branches = hg.parseurl(ui.expandpath('default'))
5428 other = hg.peer(repo, {}, source)
5443 other = hg.peer(repo, {}, source)
5429 revs, checkout = hg.addbranchrevs(repo, other, branches,
5444 revs, checkout = hg.addbranchrevs(repo, other, branches,
5430 opts.get('rev'))
5445 opts.get('rev'))
5431 ui.debug('comparing with %s\n' % util.hidepassword(source))
5446 ui.debug('comparing with %s\n' % util.hidepassword(source))
5432 repo.ui.pushbuffer()
5447 repo.ui.pushbuffer()
5433 commoninc = discovery.findcommonincoming(repo, other)
5448 commoninc = discovery.findcommonincoming(repo, other)
5434 _common, incoming, _rheads = commoninc
5449 _common, incoming, _rheads = commoninc
5435 repo.ui.popbuffer()
5450 repo.ui.popbuffer()
5436 if incoming:
5451 if incoming:
5437 t.append(_('1 or more incoming'))
5452 t.append(_('1 or more incoming'))
5438
5453
5439 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5454 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5440 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5455 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5441 if source != dest:
5456 if source != dest:
5442 other = hg.peer(repo, {}, dest)
5457 other = hg.peer(repo, {}, dest)
5443 commoninc = None
5458 commoninc = None
5444 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5459 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5445 repo.ui.pushbuffer()
5460 repo.ui.pushbuffer()
5446 outgoing = discovery.findcommonoutgoing(repo, other,
5461 outgoing = discovery.findcommonoutgoing(repo, other,
5447 commoninc=commoninc)
5462 commoninc=commoninc)
5448 repo.ui.popbuffer()
5463 repo.ui.popbuffer()
5449 o = outgoing.missing
5464 o = outgoing.missing
5450 if o:
5465 if o:
5451 t.append(_('%d outgoing') % len(o))
5466 t.append(_('%d outgoing') % len(o))
5452 if 'bookmarks' in other.listkeys('namespaces'):
5467 if 'bookmarks' in other.listkeys('namespaces'):
5453 lmarks = repo.listkeys('bookmarks')
5468 lmarks = repo.listkeys('bookmarks')
5454 rmarks = other.listkeys('bookmarks')
5469 rmarks = other.listkeys('bookmarks')
5455 diff = set(rmarks) - set(lmarks)
5470 diff = set(rmarks) - set(lmarks)
5456 if len(diff) > 0:
5471 if len(diff) > 0:
5457 t.append(_('%d incoming bookmarks') % len(diff))
5472 t.append(_('%d incoming bookmarks') % len(diff))
5458 diff = set(lmarks) - set(rmarks)
5473 diff = set(lmarks) - set(rmarks)
5459 if len(diff) > 0:
5474 if len(diff) > 0:
5460 t.append(_('%d outgoing bookmarks') % len(diff))
5475 t.append(_('%d outgoing bookmarks') % len(diff))
5461
5476
5462 if t:
5477 if t:
5463 ui.write(_('remote: %s\n') % (', '.join(t)))
5478 ui.write(_('remote: %s\n') % (', '.join(t)))
5464 else:
5479 else:
5465 ui.status(_('remote: (synced)\n'))
5480 ui.status(_('remote: (synced)\n'))
5466
5481
5467 @command('tag',
5482 @command('tag',
5468 [('f', 'force', None, _('force tag')),
5483 [('f', 'force', None, _('force tag')),
5469 ('l', 'local', None, _('make the tag local')),
5484 ('l', 'local', None, _('make the tag local')),
5470 ('r', 'rev', '', _('revision to tag'), _('REV')),
5485 ('r', 'rev', '', _('revision to tag'), _('REV')),
5471 ('', 'remove', None, _('remove a tag')),
5486 ('', 'remove', None, _('remove a tag')),
5472 # -l/--local is already there, commitopts cannot be used
5487 # -l/--local is already there, commitopts cannot be used
5473 ('e', 'edit', None, _('edit commit message')),
5488 ('e', 'edit', None, _('edit commit message')),
5474 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5489 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5475 ] + commitopts2,
5490 ] + commitopts2,
5476 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5491 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5477 def tag(ui, repo, name1, *names, **opts):
5492 def tag(ui, repo, name1, *names, **opts):
5478 """add one or more tags for the current or given revision
5493 """add one or more tags for the current or given revision
5479
5494
5480 Name a particular revision using <name>.
5495 Name a particular revision using <name>.
5481
5496
5482 Tags are used to name particular revisions of the repository and are
5497 Tags are used to name particular revisions of the repository and are
5483 very useful to compare different revisions, to go back to significant
5498 very useful to compare different revisions, to go back to significant
5484 earlier versions or to mark branch points as releases, etc. Changing
5499 earlier versions or to mark branch points as releases, etc. Changing
5485 an existing tag is normally disallowed; use -f/--force to override.
5500 an existing tag is normally disallowed; use -f/--force to override.
5486
5501
5487 If no revision is given, the parent of the working directory is
5502 If no revision is given, the parent of the working directory is
5488 used, or tip if no revision is checked out.
5503 used, or tip if no revision is checked out.
5489
5504
5490 To facilitate version control, distribution, and merging of tags,
5505 To facilitate version control, distribution, and merging of tags,
5491 they are stored as a file named ".hgtags" which is managed similarly
5506 they are stored as a file named ".hgtags" which is managed similarly
5492 to other project files and can be hand-edited if necessary. This
5507 to other project files and can be hand-edited if necessary. This
5493 also means that tagging creates a new commit. The file
5508 also means that tagging creates a new commit. The file
5494 ".hg/localtags" is used for local tags (not shared among
5509 ".hg/localtags" is used for local tags (not shared among
5495 repositories).
5510 repositories).
5496
5511
5497 Tag commits are usually made at the head of a branch. If the parent
5512 Tag commits are usually made at the head of a branch. If the parent
5498 of the working directory is not a branch head, :hg:`tag` aborts; use
5513 of the working directory is not a branch head, :hg:`tag` aborts; use
5499 -f/--force to force the tag commit to be based on a non-head
5514 -f/--force to force the tag commit to be based on a non-head
5500 changeset.
5515 changeset.
5501
5516
5502 See :hg:`help dates` for a list of formats valid for -d/--date.
5517 See :hg:`help dates` for a list of formats valid for -d/--date.
5503
5518
5504 Since tag names have priority over branch names during revision
5519 Since tag names have priority over branch names during revision
5505 lookup, using an existing branch name as a tag name is discouraged.
5520 lookup, using an existing branch name as a tag name is discouraged.
5506
5521
5507 Returns 0 on success.
5522 Returns 0 on success.
5508 """
5523 """
5509 wlock = lock = None
5524 wlock = lock = None
5510 try:
5525 try:
5511 wlock = repo.wlock()
5526 wlock = repo.wlock()
5512 lock = repo.lock()
5527 lock = repo.lock()
5513 rev_ = "."
5528 rev_ = "."
5514 names = [t.strip() for t in (name1,) + names]
5529 names = [t.strip() for t in (name1,) + names]
5515 if len(names) != len(set(names)):
5530 if len(names) != len(set(names)):
5516 raise util.Abort(_('tag names must be unique'))
5531 raise util.Abort(_('tag names must be unique'))
5517 for n in names:
5532 for n in names:
5518 if n in ['tip', '.', 'null']:
5533 if n in ['tip', '.', 'null']:
5519 raise util.Abort(_("the name '%s' is reserved") % n)
5534 raise util.Abort(_("the name '%s' is reserved") % n)
5520 if not n:
5535 if not n:
5521 raise util.Abort(_('tag names cannot consist entirely of '
5536 raise util.Abort(_('tag names cannot consist entirely of '
5522 'whitespace'))
5537 'whitespace'))
5523 if opts.get('rev') and opts.get('remove'):
5538 if opts.get('rev') and opts.get('remove'):
5524 raise util.Abort(_("--rev and --remove are incompatible"))
5539 raise util.Abort(_("--rev and --remove are incompatible"))
5525 if opts.get('rev'):
5540 if opts.get('rev'):
5526 rev_ = opts['rev']
5541 rev_ = opts['rev']
5527 message = opts.get('message')
5542 message = opts.get('message')
5528 if opts.get('remove'):
5543 if opts.get('remove'):
5529 expectedtype = opts.get('local') and 'local' or 'global'
5544 expectedtype = opts.get('local') and 'local' or 'global'
5530 for n in names:
5545 for n in names:
5531 if not repo.tagtype(n):
5546 if not repo.tagtype(n):
5532 raise util.Abort(_("tag '%s' does not exist") % n)
5547 raise util.Abort(_("tag '%s' does not exist") % n)
5533 if repo.tagtype(n) != expectedtype:
5548 if repo.tagtype(n) != expectedtype:
5534 if expectedtype == 'global':
5549 if expectedtype == 'global':
5535 raise util.Abort(_("tag '%s' is not a global tag") % n)
5550 raise util.Abort(_("tag '%s' is not a global tag") % n)
5536 else:
5551 else:
5537 raise util.Abort(_("tag '%s' is not a local tag") % n)
5552 raise util.Abort(_("tag '%s' is not a local tag") % n)
5538 rev_ = nullid
5553 rev_ = nullid
5539 if not message:
5554 if not message:
5540 # we don't translate commit messages
5555 # we don't translate commit messages
5541 message = 'Removed tag %s' % ', '.join(names)
5556 message = 'Removed tag %s' % ', '.join(names)
5542 elif not opts.get('force'):
5557 elif not opts.get('force'):
5543 for n in names:
5558 for n in names:
5544 if n in repo.tags():
5559 if n in repo.tags():
5545 raise util.Abort(_("tag '%s' already exists "
5560 raise util.Abort(_("tag '%s' already exists "
5546 "(use -f to force)") % n)
5561 "(use -f to force)") % n)
5547 if not opts.get('local'):
5562 if not opts.get('local'):
5548 p1, p2 = repo.dirstate.parents()
5563 p1, p2 = repo.dirstate.parents()
5549 if p2 != nullid:
5564 if p2 != nullid:
5550 raise util.Abort(_('uncommitted merge'))
5565 raise util.Abort(_('uncommitted merge'))
5551 bheads = repo.branchheads()
5566 bheads = repo.branchheads()
5552 if not opts.get('force') and bheads and p1 not in bheads:
5567 if not opts.get('force') and bheads and p1 not in bheads:
5553 raise util.Abort(_('not at a branch head (use -f to force)'))
5568 raise util.Abort(_('not at a branch head (use -f to force)'))
5554 r = scmutil.revsingle(repo, rev_).node()
5569 r = scmutil.revsingle(repo, rev_).node()
5555
5570
5556 if not message:
5571 if not message:
5557 # we don't translate commit messages
5572 # we don't translate commit messages
5558 message = ('Added tag %s for changeset %s' %
5573 message = ('Added tag %s for changeset %s' %
5559 (', '.join(names), short(r)))
5574 (', '.join(names), short(r)))
5560
5575
5561 date = opts.get('date')
5576 date = opts.get('date')
5562 if date:
5577 if date:
5563 date = util.parsedate(date)
5578 date = util.parsedate(date)
5564
5579
5565 if opts.get('edit'):
5580 if opts.get('edit'):
5566 message = ui.edit(message, ui.username())
5581 message = ui.edit(message, ui.username())
5567
5582
5568 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5583 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5569 finally:
5584 finally:
5570 release(lock, wlock)
5585 release(lock, wlock)
5571
5586
5572 @command('tags', [], '')
5587 @command('tags', [], '')
5573 def tags(ui, repo):
5588 def tags(ui, repo):
5574 """list repository tags
5589 """list repository tags
5575
5590
5576 This lists both regular and local tags. When the -v/--verbose
5591 This lists both regular and local tags. When the -v/--verbose
5577 switch is used, a third column "local" is printed for local tags.
5592 switch is used, a third column "local" is printed for local tags.
5578
5593
5579 Returns 0 on success.
5594 Returns 0 on success.
5580 """
5595 """
5581
5596
5582 hexfunc = ui.debugflag and hex or short
5597 hexfunc = ui.debugflag and hex or short
5583 tagtype = ""
5598 tagtype = ""
5584
5599
5585 for t, n in reversed(repo.tagslist()):
5600 for t, n in reversed(repo.tagslist()):
5586 if ui.quiet:
5601 if ui.quiet:
5587 ui.write("%s\n" % t, label='tags.normal')
5602 ui.write("%s\n" % t, label='tags.normal')
5588 continue
5603 continue
5589
5604
5590 hn = hexfunc(n)
5605 hn = hexfunc(n)
5591 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5606 r = "%5d:%s" % (repo.changelog.rev(n), hn)
5592 rev = ui.label(r, 'log.changeset')
5607 rev = ui.label(r, 'log.changeset')
5593 spaces = " " * (30 - encoding.colwidth(t))
5608 spaces = " " * (30 - encoding.colwidth(t))
5594
5609
5595 tag = ui.label(t, 'tags.normal')
5610 tag = ui.label(t, 'tags.normal')
5596 if ui.verbose:
5611 if ui.verbose:
5597 if repo.tagtype(t) == 'local':
5612 if repo.tagtype(t) == 'local':
5598 tagtype = " local"
5613 tagtype = " local"
5599 tag = ui.label(t, 'tags.local')
5614 tag = ui.label(t, 'tags.local')
5600 else:
5615 else:
5601 tagtype = ""
5616 tagtype = ""
5602 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5617 ui.write("%s%s %s%s\n" % (tag, spaces, rev, tagtype))
5603
5618
5604 @command('tip',
5619 @command('tip',
5605 [('p', 'patch', None, _('show patch')),
5620 [('p', 'patch', None, _('show patch')),
5606 ('g', 'git', None, _('use git extended diff format')),
5621 ('g', 'git', None, _('use git extended diff format')),
5607 ] + templateopts,
5622 ] + templateopts,
5608 _('[-p] [-g]'))
5623 _('[-p] [-g]'))
5609 def tip(ui, repo, **opts):
5624 def tip(ui, repo, **opts):
5610 """show the tip revision
5625 """show the tip revision
5611
5626
5612 The tip revision (usually just called the tip) is the changeset
5627 The tip revision (usually just called the tip) is the changeset
5613 most recently added to the repository (and therefore the most
5628 most recently added to the repository (and therefore the most
5614 recently changed head).
5629 recently changed head).
5615
5630
5616 If you have just made a commit, that commit will be the tip. If
5631 If you have just made a commit, that commit will be the tip. If
5617 you have just pulled changes from another repository, the tip of
5632 you have just pulled changes from another repository, the tip of
5618 that repository becomes the current tip. The "tip" tag is special
5633 that repository becomes the current tip. The "tip" tag is special
5619 and cannot be renamed or assigned to a different changeset.
5634 and cannot be renamed or assigned to a different changeset.
5620
5635
5621 Returns 0 on success.
5636 Returns 0 on success.
5622 """
5637 """
5623 displayer = cmdutil.show_changeset(ui, repo, opts)
5638 displayer = cmdutil.show_changeset(ui, repo, opts)
5624 displayer.show(repo[len(repo) - 1])
5639 displayer.show(repo[len(repo) - 1])
5625 displayer.close()
5640 displayer.close()
5626
5641
5627 @command('unbundle',
5642 @command('unbundle',
5628 [('u', 'update', None,
5643 [('u', 'update', None,
5629 _('update to new branch head if changesets were unbundled'))],
5644 _('update to new branch head if changesets were unbundled'))],
5630 _('[-u] FILE...'))
5645 _('[-u] FILE...'))
5631 def unbundle(ui, repo, fname1, *fnames, **opts):
5646 def unbundle(ui, repo, fname1, *fnames, **opts):
5632 """apply one or more changegroup files
5647 """apply one or more changegroup files
5633
5648
5634 Apply one or more compressed changegroup files generated by the
5649 Apply one or more compressed changegroup files generated by the
5635 bundle command.
5650 bundle command.
5636
5651
5637 Returns 0 on success, 1 if an update has unresolved files.
5652 Returns 0 on success, 1 if an update has unresolved files.
5638 """
5653 """
5639 fnames = (fname1,) + fnames
5654 fnames = (fname1,) + fnames
5640
5655
5641 lock = repo.lock()
5656 lock = repo.lock()
5642 wc = repo['.']
5657 wc = repo['.']
5643 try:
5658 try:
5644 for fname in fnames:
5659 for fname in fnames:
5645 f = url.open(ui, fname)
5660 f = url.open(ui, fname)
5646 gen = changegroup.readbundle(f, fname)
5661 gen = changegroup.readbundle(f, fname)
5647 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5662 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5648 finally:
5663 finally:
5649 lock.release()
5664 lock.release()
5650 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5665 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5651 return postincoming(ui, repo, modheads, opts.get('update'), None)
5666 return postincoming(ui, repo, modheads, opts.get('update'), None)
5652
5667
5653 @command('^update|up|checkout|co',
5668 @command('^update|up|checkout|co',
5654 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5669 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5655 ('c', 'check', None,
5670 ('c', 'check', None,
5656 _('update across branches if no uncommitted changes')),
5671 _('update across branches if no uncommitted changes')),
5657 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5672 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5658 ('r', 'rev', '', _('revision'), _('REV'))],
5673 ('r', 'rev', '', _('revision'), _('REV'))],
5659 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5674 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5660 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5675 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5661 """update working directory (or switch revisions)
5676 """update working directory (or switch revisions)
5662
5677
5663 Update the repository's working directory to the specified
5678 Update the repository's working directory to the specified
5664 changeset. If no changeset is specified, update to the tip of the
5679 changeset. If no changeset is specified, update to the tip of the
5665 current named branch and move the current bookmark (see :hg:`help
5680 current named branch and move the current bookmark (see :hg:`help
5666 bookmarks`).
5681 bookmarks`).
5667
5682
5668 If the changeset is not a descendant or ancestor of the working
5683 If the changeset is not a descendant or ancestor of the working
5669 directory's parent, the update is aborted. With the -c/--check
5684 directory's parent, the update is aborted. With the -c/--check
5670 option, the working directory is checked for uncommitted changes; if
5685 option, the working directory is checked for uncommitted changes; if
5671 none are found, the working directory is updated to the specified
5686 none are found, the working directory is updated to the specified
5672 changeset.
5687 changeset.
5673
5688
5674 Update sets the working directory's parent revison to the specified
5689 Update sets the working directory's parent revison to the specified
5675 changeset (see :hg:`help parents`).
5690 changeset (see :hg:`help parents`).
5676
5691
5677 The following rules apply when the working directory contains
5692 The following rules apply when the working directory contains
5678 uncommitted changes:
5693 uncommitted changes:
5679
5694
5680 1. If neither -c/--check nor -C/--clean is specified, and if
5695 1. If neither -c/--check nor -C/--clean is specified, and if
5681 the requested changeset is an ancestor or descendant of
5696 the requested changeset is an ancestor or descendant of
5682 the working directory's parent, the uncommitted changes
5697 the working directory's parent, the uncommitted changes
5683 are merged into the requested changeset and the merged
5698 are merged into the requested changeset and the merged
5684 result is left uncommitted. If the requested changeset is
5699 result is left uncommitted. If the requested changeset is
5685 not an ancestor or descendant (that is, it is on another
5700 not an ancestor or descendant (that is, it is on another
5686 branch), the update is aborted and the uncommitted changes
5701 branch), the update is aborted and the uncommitted changes
5687 are preserved.
5702 are preserved.
5688
5703
5689 2. With the -c/--check option, the update is aborted and the
5704 2. With the -c/--check option, the update is aborted and the
5690 uncommitted changes are preserved.
5705 uncommitted changes are preserved.
5691
5706
5692 3. With the -C/--clean option, uncommitted changes are discarded and
5707 3. With the -C/--clean option, uncommitted changes are discarded and
5693 the working directory is updated to the requested changeset.
5708 the working directory is updated to the requested changeset.
5694
5709
5695 Use null as the changeset to remove the working directory (like
5710 Use null as the changeset to remove the working directory (like
5696 :hg:`clone -U`).
5711 :hg:`clone -U`).
5697
5712
5698 If you want to revert just one file to an older revision, use
5713 If you want to revert just one file to an older revision, use
5699 :hg:`revert [-r REV] NAME`.
5714 :hg:`revert [-r REV] NAME`.
5700
5715
5701 See :hg:`help dates` for a list of formats valid for -d/--date.
5716 See :hg:`help dates` for a list of formats valid for -d/--date.
5702
5717
5703 Returns 0 on success, 1 if there are unresolved files.
5718 Returns 0 on success, 1 if there are unresolved files.
5704 """
5719 """
5705 if rev and node:
5720 if rev and node:
5706 raise util.Abort(_("please specify just one revision"))
5721 raise util.Abort(_("please specify just one revision"))
5707
5722
5708 if rev is None or rev == '':
5723 if rev is None or rev == '':
5709 rev = node
5724 rev = node
5710
5725
5711 # with no argument, we also move the current bookmark, if any
5726 # with no argument, we also move the current bookmark, if any
5712 movemarkfrom = None
5727 movemarkfrom = None
5713 if rev is None or node == '':
5728 if rev is None or node == '':
5714 movemarkfrom = repo['.'].node()
5729 movemarkfrom = repo['.'].node()
5715
5730
5716 # if we defined a bookmark, we have to remember the original bookmark name
5731 # if we defined a bookmark, we have to remember the original bookmark name
5717 brev = rev
5732 brev = rev
5718 rev = scmutil.revsingle(repo, rev, rev).rev()
5733 rev = scmutil.revsingle(repo, rev, rev).rev()
5719
5734
5720 if check and clean:
5735 if check and clean:
5721 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5736 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5722
5737
5723 if date:
5738 if date:
5724 if rev is not None:
5739 if rev is not None:
5725 raise util.Abort(_("you can't specify a revision and a date"))
5740 raise util.Abort(_("you can't specify a revision and a date"))
5726 rev = cmdutil.finddate(ui, repo, date)
5741 rev = cmdutil.finddate(ui, repo, date)
5727
5742
5728 if check:
5743 if check:
5729 c = repo[None]
5744 c = repo[None]
5730 if c.dirty(merge=False, branch=False):
5745 if c.dirty(merge=False, branch=False):
5731 raise util.Abort(_("uncommitted local changes"))
5746 raise util.Abort(_("uncommitted local changes"))
5732 if rev is None:
5747 if rev is None:
5733 rev = repo[repo[None].branch()].rev()
5748 rev = repo[repo[None].branch()].rev()
5734 mergemod._checkunknown(repo, repo[None], repo[rev])
5749 mergemod._checkunknown(repo, repo[None], repo[rev])
5735
5750
5736 if clean:
5751 if clean:
5737 ret = hg.clean(repo, rev)
5752 ret = hg.clean(repo, rev)
5738 else:
5753 else:
5739 ret = hg.update(repo, rev)
5754 ret = hg.update(repo, rev)
5740
5755
5741 if not ret and movemarkfrom:
5756 if not ret and movemarkfrom:
5742 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5757 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5743 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5758 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5744 elif brev in repo._bookmarks:
5759 elif brev in repo._bookmarks:
5745 bookmarks.setcurrent(repo, brev)
5760 bookmarks.setcurrent(repo, brev)
5746 elif brev:
5761 elif brev:
5747 bookmarks.unsetcurrent(repo)
5762 bookmarks.unsetcurrent(repo)
5748
5763
5749 return ret
5764 return ret
5750
5765
5751 @command('verify', [])
5766 @command('verify', [])
5752 def verify(ui, repo):
5767 def verify(ui, repo):
5753 """verify the integrity of the repository
5768 """verify the integrity of the repository
5754
5769
5755 Verify the integrity of the current repository.
5770 Verify the integrity of the current repository.
5756
5771
5757 This will perform an extensive check of the repository's
5772 This will perform an extensive check of the repository's
5758 integrity, validating the hashes and checksums of each entry in
5773 integrity, validating the hashes and checksums of each entry in
5759 the changelog, manifest, and tracked files, as well as the
5774 the changelog, manifest, and tracked files, as well as the
5760 integrity of their crosslinks and indices.
5775 integrity of their crosslinks and indices.
5761
5776
5762 Returns 0 on success, 1 if errors are encountered.
5777 Returns 0 on success, 1 if errors are encountered.
5763 """
5778 """
5764 return hg.verify(repo)
5779 return hg.verify(repo)
5765
5780
5766 @command('version', [])
5781 @command('version', [])
5767 def version_(ui):
5782 def version_(ui):
5768 """output version and copyright information"""
5783 """output version and copyright information"""
5769 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5784 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5770 % util.version())
5785 % util.version())
5771 ui.status(_(
5786 ui.status(_(
5772 "(see http://mercurial.selenic.com for more information)\n"
5787 "(see http://mercurial.selenic.com for more information)\n"
5773 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5788 "\nCopyright (C) 2005-2012 Matt Mackall and others\n"
5774 "This is free software; see the source for copying conditions. "
5789 "This is free software; see the source for copying conditions. "
5775 "There is NO\nwarranty; "
5790 "There is NO\nwarranty; "
5776 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5791 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5777 ))
5792 ))
5778
5793
5779 norepo = ("clone init version help debugcommands debugcomplete"
5794 norepo = ("clone init version help debugcommands debugcomplete"
5780 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5795 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5781 " debugknown debuggetbundle debugbundle")
5796 " debugknown debuggetbundle debugbundle")
5782 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5797 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5783 " debugdata debugindex debugindexdot debugrevlog")
5798 " debugdata debugindex debugindexdot debugrevlog")
@@ -1,175 +1,192 b''
1 # obsolete.py - obsolete markers handling
1 # obsolete.py - obsolete markers handling
2 #
2 #
3 # Copyright 2012 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
3 # Copyright 2012 Pierre-Yves David <pierre-yves.david@ens-lyon.org>
4 # Logilab SA <contact@logilab.fr>
4 # Logilab SA <contact@logilab.fr>
5 #
5 #
6 # This software may be used and distributed according to the terms of the
6 # This software may be used and distributed according to the terms of the
7 # GNU General Public License version 2 or any later version.
7 # GNU General Public License version 2 or any later version.
8
8
9 """Obsolete markers handling
9 """Obsolete markers handling
10
10
11 An obsolete marker maps an old changeset to a list of new
11 An obsolete marker maps an old changeset to a list of new
12 changesets. If the list of new changesets is empty, the old changeset
12 changesets. If the list of new changesets is empty, the old changeset
13 is said to be "killed". Otherwise, the old changeset is being
13 is said to be "killed". Otherwise, the old changeset is being
14 "replaced" by the new changesets.
14 "replaced" by the new changesets.
15
15
16 Obsolete markers can be used to record and distribute changeset graph
16 Obsolete markers can be used to record and distribute changeset graph
17 transformations performed by history rewriting operations, and help
17 transformations performed by history rewriting operations, and help
18 building new tools to reconciliate conflicting rewriting actions. To
18 building new tools to reconciliate conflicting rewriting actions. To
19 facilitate conflicts resolution, markers include various annotations
19 facilitate conflicts resolution, markers include various annotations
20 besides old and news changeset identifiers, such as creation date or
20 besides old and news changeset identifiers, such as creation date or
21 author name.
21 author name.
22
22
23
23
24 Format
24 Format
25 ------
25 ------
26
26
27 Markers are stored in an append-only file stored in
27 Markers are stored in an append-only file stored in
28 '.hg/store/obsstore'.
28 '.hg/store/obsstore'.
29
29
30 The file starts with a version header:
30 The file starts with a version header:
31
31
32 - 1 unsigned byte: version number, starting at zero.
32 - 1 unsigned byte: version number, starting at zero.
33
33
34
34
35 The header is followed by the markers. Each marker is made of:
35 The header is followed by the markers. Each marker is made of:
36
36
37 - 1 unsigned byte: number of new changesets "R", could be zero.
37 - 1 unsigned byte: number of new changesets "R", could be zero.
38
38
39 - 1 unsigned 32-bits integer: metadata size "M" in bytes.
39 - 1 unsigned 32-bits integer: metadata size "M" in bytes.
40
40
41 - 1 byte: a bit field. It is reserved for flags used in obsolete
41 - 1 byte: a bit field. It is reserved for flags used in obsolete
42 markers common operations, to avoid repeated decoding of metadata
42 markers common operations, to avoid repeated decoding of metadata
43 entries.
43 entries.
44
44
45 - 20 bytes: obsoleted changeset identifier.
45 - 20 bytes: obsoleted changeset identifier.
46
46
47 - N*20 bytes: new changesets identifiers.
47 - N*20 bytes: new changesets identifiers.
48
48
49 - M bytes: metadata as a sequence of nul-terminated strings. Each
49 - M bytes: metadata as a sequence of nul-terminated strings. Each
50 string contains a key and a value, separated by a color ':', without
50 string contains a key and a value, separated by a color ':', without
51 additional encoding. Keys cannot contain '\0' or ':' and values
51 additional encoding. Keys cannot contain '\0' or ':' and values
52 cannot contain '\0'.
52 cannot contain '\0'.
53 """
53 """
54 import struct
54 import struct
55 from mercurial import util
55 from mercurial import util
56 from i18n import _
56 from i18n import _
57
57
58 _pack = struct.pack
58 _pack = struct.pack
59 _unpack = struct.unpack
59 _unpack = struct.unpack
60
60
61
61
62
62
63 # data used for parsing and writing
63 # data used for parsing and writing
64 _fmversion = 0
64 _fmversion = 0
65 _fmfixed = '>BIB20s'
65 _fmfixed = '>BIB20s'
66 _fmnode = '20s'
66 _fmnode = '20s'
67 _fmfsize = struct.calcsize(_fmfixed)
67 _fmfsize = struct.calcsize(_fmfixed)
68 _fnodesize = struct.calcsize(_fmnode)
68 _fnodesize = struct.calcsize(_fmnode)
69
69
70 def _readmarkers(data):
70 def _readmarkers(data):
71 """Read and enumerate markers from raw data"""
71 """Read and enumerate markers from raw data"""
72 off = 0
72 off = 0
73 diskversion = _unpack('>B', data[off:off + 1])[0]
73 diskversion = _unpack('>B', data[off:off + 1])[0]
74 off += 1
74 off += 1
75 if diskversion != _fmversion:
75 if diskversion != _fmversion:
76 raise util.Abort(_('parsing obsolete marker: unknown version %r')
76 raise util.Abort(_('parsing obsolete marker: unknown version %r')
77 % diskversion)
77 % diskversion)
78
78
79 # Loop on markers
79 # Loop on markers
80 l = len(data)
80 l = len(data)
81 while off + _fmfsize <= l:
81 while off + _fmfsize <= l:
82 # read fixed part
82 # read fixed part
83 cur = data[off:off + _fmfsize]
83 cur = data[off:off + _fmfsize]
84 off += _fmfsize
84 off += _fmfsize
85 nbsuc, mdsize, flags, pre = _unpack(_fmfixed, cur)
85 nbsuc, mdsize, flags, pre = _unpack(_fmfixed, cur)
86 # read replacement
86 # read replacement
87 sucs = ()
87 sucs = ()
88 if nbsuc:
88 if nbsuc:
89 s = (_fnodesize * nbsuc)
89 s = (_fnodesize * nbsuc)
90 cur = data[off:off + s]
90 cur = data[off:off + s]
91 sucs = _unpack(_fmnode * nbsuc, cur)
91 sucs = _unpack(_fmnode * nbsuc, cur)
92 off += s
92 off += s
93 # read metadata
93 # read metadata
94 # (metadata will be decoded on demand)
94 # (metadata will be decoded on demand)
95 metadata = data[off:off + mdsize]
95 metadata = data[off:off + mdsize]
96 if len(metadata) != mdsize:
96 if len(metadata) != mdsize:
97 raise util.Abort(_('parsing obsolete marker: metadata is too '
97 raise util.Abort(_('parsing obsolete marker: metadata is too '
98 'short, %d bytes expected, got %d')
98 'short, %d bytes expected, got %d')
99 % (len(metadata), mdsize))
99 % (len(metadata), mdsize))
100 off += mdsize
100 off += mdsize
101 yield (pre, sucs, flags, metadata)
101 yield (pre, sucs, flags, metadata)
102
102
103 def encodemeta(meta):
103 def encodemeta(meta):
104 """Return encoded metadata string to string mapping.
104 """Return encoded metadata string to string mapping.
105
105
106 Assume no ':' in key and no '\0' in both key and value."""
106 Assume no ':' in key and no '\0' in both key and value."""
107 for key, value in meta.iteritems():
107 for key, value in meta.iteritems():
108 if ':' in key or '\0' in key:
108 if ':' in key or '\0' in key:
109 raise ValueError("':' and '\0' are forbidden in metadata key'")
109 raise ValueError("':' and '\0' are forbidden in metadata key'")
110 if '\0' in value:
110 if '\0' in value:
111 raise ValueError("':' are forbidden in metadata value'")
111 raise ValueError("':' are forbidden in metadata value'")
112 return '\0'.join(['%s:%s' % (k, meta[k]) for k in sorted(meta)])
112 return '\0'.join(['%s:%s' % (k, meta[k]) for k in sorted(meta)])
113
113
114 def decodemeta(data):
114 def decodemeta(data):
115 """Return string to string dictionary from encoded version."""
115 """Return string to string dictionary from encoded version."""
116 d = {}
116 d = {}
117 for l in data.split('\0'):
117 for l in data.split('\0'):
118 if l:
118 if l:
119 key, value = l.split(':')
119 key, value = l.split(':')
120 d[key] = value
120 d[key] = value
121 return d
121 return d
122
122
123 class obsstore(object):
123 class obsstore(object):
124 """Store obsolete markers
124 """Store obsolete markers
125
125
126 Markers can be accessed with two mappings:
126 Markers can be accessed with two mappings:
127 - precursors: old -> set(new)
127 - precursors: old -> set(new)
128 - successors: new -> set(old)
128 - successors: new -> set(old)
129 """
129 """
130
130
131 def __init__(self):
131 def __init__(self):
132 self._all = []
132 self._all = []
133 # new markers to serialize
133 # new markers to serialize
134 self._new = []
134 self._new = []
135 self.precursors = {}
135 self.precursors = {}
136 self.successors = {}
136 self.successors = {}
137
137
138 def create(self, prec, succs=(), flag=0, metadata=None):
139 """obsolete: add a new obsolete marker
140
141 * ensuring it is hashable
142 * check mandatory metadata
143 * encode metadata
144 """
145 if metadata is None:
146 metadata = {}
147 if len(prec) != 20:
148 raise ValueError(prec)
149 for succ in succs:
150 if len(succ) != 20:
151 raise ValueError(prec)
152 marker = (str(prec), tuple(succs), int(flag), encodemeta(metadata))
153 self.add(marker)
154
138 def add(self, marker):
155 def add(self, marker):
139 """Add a new marker to the store
156 """Add a new marker to the store
140
157
141 This marker still needs to be written to disk"""
158 This marker still needs to be written to disk"""
142 self._new.append(marker)
159 self._new.append(marker)
143 self._load(marker)
160 self._load(marker)
144
161
145 def loadmarkers(self, data):
162 def loadmarkers(self, data):
146 """Load all markers in data, mark them as known."""
163 """Load all markers in data, mark them as known."""
147 for marker in _readmarkers(data):
164 for marker in _readmarkers(data):
148 self._load(marker)
165 self._load(marker)
149
166
150 def flushmarkers(self, stream):
167 def flushmarkers(self, stream):
151 """Write all markers to a stream
168 """Write all markers to a stream
152
169
153 After this operation, "new" markers are considered "known"."""
170 After this operation, "new" markers are considered "known"."""
154 self._writemarkers(stream)
171 self._writemarkers(stream)
155 self._new[:] = []
172 self._new[:] = []
156
173
157 def _load(self, marker):
174 def _load(self, marker):
158 self._all.append(marker)
175 self._all.append(marker)
159 pre, sucs = marker[:2]
176 pre, sucs = marker[:2]
160 self.precursors.setdefault(pre, set()).add(marker)
177 self.precursors.setdefault(pre, set()).add(marker)
161 for suc in sucs:
178 for suc in sucs:
162 self.successors.setdefault(suc, set()).add(marker)
179 self.successors.setdefault(suc, set()).add(marker)
163
180
164 def _writemarkers(self, stream):
181 def _writemarkers(self, stream):
165 # Kept separate from flushmarkers(), it will be reused for
182 # Kept separate from flushmarkers(), it will be reused for
166 # markers exchange.
183 # markers exchange.
167 stream.write(_pack('>B', _fmversion))
184 stream.write(_pack('>B', _fmversion))
168 for marker in self._all:
185 for marker in self._all:
169 pre, sucs, flags, metadata = marker
186 pre, sucs, flags, metadata = marker
170 nbsuc = len(sucs)
187 nbsuc = len(sucs)
171 format = _fmfixed + (_fmnode * nbsuc)
188 format = _fmfixed + (_fmnode * nbsuc)
172 data = [nbsuc, len(metadata), flags, pre]
189 data = [nbsuc, len(metadata), flags, pre]
173 data.extend(sucs)
190 data.extend(sucs)
174 stream.write(_pack(format, *data))
191 stream.write(_pack(format, *data))
175 stream.write(metadata)
192 stream.write(metadata)
@@ -1,274 +1,276 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 copy
16 copy
17 diff
17 diff
18 export
18 export
19 forget
19 forget
20 graft
20 graft
21 grep
21 grep
22 heads
22 heads
23 help
23 help
24 identify
24 identify
25 import
25 import
26 incoming
26 incoming
27 init
27 init
28 locate
28 locate
29 log
29 log
30 manifest
30 manifest
31 merge
31 merge
32 outgoing
32 outgoing
33 parents
33 parents
34 paths
34 paths
35 phase
35 phase
36 pull
36 pull
37 push
37 push
38 recover
38 recover
39 remove
39 remove
40 rename
40 rename
41 resolve
41 resolve
42 revert
42 revert
43 rollback
43 rollback
44 root
44 root
45 serve
45 serve
46 showconfig
46 showconfig
47 status
47 status
48 summary
48 summary
49 tag
49 tag
50 tags
50 tags
51 tip
51 tip
52 unbundle
52 unbundle
53 update
53 update
54 verify
54 verify
55 version
55 version
56
56
57 Show all commands that start with "a"
57 Show all commands that start with "a"
58 $ hg debugcomplete a
58 $ hg debugcomplete a
59 add
59 add
60 addremove
60 addremove
61 annotate
61 annotate
62 archive
62 archive
63
63
64 Do not show debug commands if there are other candidates
64 Do not show debug commands if there are other candidates
65 $ hg debugcomplete d
65 $ hg debugcomplete d
66 diff
66 diff
67
67
68 Show debug commands if there are no other candidates
68 Show debug commands if there are no other candidates
69 $ hg debugcomplete debug
69 $ hg debugcomplete debug
70 debugancestor
70 debugancestor
71 debugbuilddag
71 debugbuilddag
72 debugbundle
72 debugbundle
73 debugcheckstate
73 debugcheckstate
74 debugcommands
74 debugcommands
75 debugcomplete
75 debugcomplete
76 debugconfig
76 debugconfig
77 debugdag
77 debugdag
78 debugdata
78 debugdata
79 debugdate
79 debugdate
80 debugdiscovery
80 debugdiscovery
81 debugfileset
81 debugfileset
82 debugfsinfo
82 debugfsinfo
83 debuggetbundle
83 debuggetbundle
84 debugignore
84 debugignore
85 debugindex
85 debugindex
86 debugindexdot
86 debugindexdot
87 debuginstall
87 debuginstall
88 debugknown
88 debugknown
89 debugobsolete
89 debugpushkey
90 debugpushkey
90 debugpvec
91 debugpvec
91 debugrebuildstate
92 debugrebuildstate
92 debugrename
93 debugrename
93 debugrevlog
94 debugrevlog
94 debugrevspec
95 debugrevspec
95 debugsetparents
96 debugsetparents
96 debugstate
97 debugstate
97 debugsub
98 debugsub
98 debugwalk
99 debugwalk
99 debugwireargs
100 debugwireargs
100
101
101 Do not show the alias of a debug command if there are other candidates
102 Do not show the alias of a debug command if there are other candidates
102 (this should hide rawcommit)
103 (this should hide rawcommit)
103 $ hg debugcomplete r
104 $ hg debugcomplete r
104 recover
105 recover
105 remove
106 remove
106 rename
107 rename
107 resolve
108 resolve
108 revert
109 revert
109 rollback
110 rollback
110 root
111 root
111 Show the alias of a debug command if there are no other candidates
112 Show the alias of a debug command if there are no other candidates
112 $ hg debugcomplete rawc
113 $ hg debugcomplete rawc
113
114
114
115
115 Show the global options
116 Show the global options
116 $ hg debugcomplete --options | sort
117 $ hg debugcomplete --options | sort
117 --config
118 --config
118 --cwd
119 --cwd
119 --debug
120 --debug
120 --debugger
121 --debugger
121 --encoding
122 --encoding
122 --encodingmode
123 --encodingmode
123 --help
124 --help
124 --noninteractive
125 --noninteractive
125 --profile
126 --profile
126 --quiet
127 --quiet
127 --repository
128 --repository
128 --time
129 --time
129 --traceback
130 --traceback
130 --verbose
131 --verbose
131 --version
132 --version
132 -R
133 -R
133 -h
134 -h
134 -q
135 -q
135 -v
136 -v
136 -y
137 -y
137
138
138 Show the options for the "serve" command
139 Show the options for the "serve" command
139 $ hg debugcomplete --options serve | sort
140 $ hg debugcomplete --options serve | sort
140 --accesslog
141 --accesslog
141 --address
142 --address
142 --certificate
143 --certificate
143 --cmdserver
144 --cmdserver
144 --config
145 --config
145 --cwd
146 --cwd
146 --daemon
147 --daemon
147 --daemon-pipefds
148 --daemon-pipefds
148 --debug
149 --debug
149 --debugger
150 --debugger
150 --encoding
151 --encoding
151 --encodingmode
152 --encodingmode
152 --errorlog
153 --errorlog
153 --help
154 --help
154 --ipv6
155 --ipv6
155 --name
156 --name
156 --noninteractive
157 --noninteractive
157 --pid-file
158 --pid-file
158 --port
159 --port
159 --prefix
160 --prefix
160 --profile
161 --profile
161 --quiet
162 --quiet
162 --repository
163 --repository
163 --stdio
164 --stdio
164 --style
165 --style
165 --templates
166 --templates
166 --time
167 --time
167 --traceback
168 --traceback
168 --verbose
169 --verbose
169 --version
170 --version
170 --web-conf
171 --web-conf
171 -6
172 -6
172 -A
173 -A
173 -E
174 -E
174 -R
175 -R
175 -a
176 -a
176 -d
177 -d
177 -h
178 -h
178 -n
179 -n
179 -p
180 -p
180 -q
181 -q
181 -t
182 -t
182 -v
183 -v
183 -y
184 -y
184
185
185 Show an error if we use --options with an ambiguous abbreviation
186 Show an error if we use --options with an ambiguous abbreviation
186 $ hg debugcomplete --options s
187 $ hg debugcomplete --options s
187 hg: command 's' is ambiguous:
188 hg: command 's' is ambiguous:
188 serve showconfig status summary
189 serve showconfig status summary
189 [255]
190 [255]
190
191
191 Show all commands + options
192 Show all commands + options
192 $ hg debugcommands
193 $ hg debugcommands
193 add: include, exclude, subrepos, dry-run
194 add: include, exclude, subrepos, dry-run
194 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude
195 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude
195 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
196 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
196 commit: addremove, close-branch, amend, include, exclude, message, logfile, date, user, subrepos
197 commit: addremove, close-branch, amend, include, exclude, message, logfile, date, user, subrepos
197 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
198 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
198 export: output, switch-parent, rev, text, git, nodates
199 export: output, switch-parent, rev, text, git, nodates
199 forget: include, exclude
200 forget: include, exclude
200 init: ssh, remotecmd, insecure
201 init: ssh, remotecmd, insecure
201 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, hidden, patch, git, limit, no-merges, stat, style, template, include, exclude
202 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, hidden, patch, git, limit, no-merges, stat, style, template, include, exclude
202 merge: force, rev, preview, tool
203 merge: force, rev, preview, tool
203 phase: public, draft, secret, force, rev
204 phase: public, draft, secret, force, rev
204 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
205 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
205 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
206 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
206 remove: after, force, include, exclude
207 remove: after, force, include, exclude
207 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
208 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
208 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
209 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
209 summary: remote
210 summary: remote
210 update: clean, check, date, rev
211 update: clean, check, date, rev
211 addremove: similarity, include, exclude, dry-run
212 addremove: similarity, include, exclude, dry-run
212 archive: no-decode, prefix, rev, type, subrepos, include, exclude
213 archive: no-decode, prefix, rev, type, subrepos, include, exclude
213 backout: merge, parent, rev, tool, include, exclude, message, logfile, date, user
214 backout: merge, parent, rev, tool, include, exclude, message, logfile, date, user
214 bisect: reset, good, bad, skip, extend, command, noupdate
215 bisect: reset, good, bad, skip, extend, command, noupdate
215 bookmarks: force, rev, delete, rename, inactive
216 bookmarks: force, rev, delete, rename, inactive
216 branch: force, clean
217 branch: force, clean
217 branches: active, closed
218 branches: active, closed
218 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
219 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
219 cat: output, rev, decode, include, exclude
220 cat: output, rev, decode, include, exclude
220 copy: after, force, include, exclude, dry-run
221 copy: after, force, include, exclude, dry-run
221 debugancestor:
222 debugancestor:
222 debugbuilddag: mergeable-file, overwritten-file, new-file
223 debugbuilddag: mergeable-file, overwritten-file, new-file
223 debugbundle: all
224 debugbundle: all
224 debugcheckstate:
225 debugcheckstate:
225 debugcommands:
226 debugcommands:
226 debugcomplete: options
227 debugcomplete: options
227 debugdag: tags, branches, dots, spaces
228 debugdag: tags, branches, dots, spaces
228 debugdata: changelog, manifest
229 debugdata: changelog, manifest
229 debugdate: extended
230 debugdate: extended
230 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
231 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
231 debugfileset:
232 debugfileset:
232 debugfsinfo:
233 debugfsinfo:
233 debuggetbundle: head, common, type
234 debuggetbundle: head, common, type
234 debugignore:
235 debugignore:
235 debugindex: changelog, manifest, format
236 debugindex: changelog, manifest, format
236 debugindexdot:
237 debugindexdot:
237 debuginstall:
238 debuginstall:
238 debugknown:
239 debugknown:
240 debugobsolete: date, user
239 debugpushkey:
241 debugpushkey:
240 debugpvec:
242 debugpvec:
241 debugrebuildstate: rev
243 debugrebuildstate: rev
242 debugrename: rev
244 debugrename: rev
243 debugrevlog: changelog, manifest, dump
245 debugrevlog: changelog, manifest, dump
244 debugrevspec:
246 debugrevspec:
245 debugsetparents:
247 debugsetparents:
246 debugstate: nodates, datesort
248 debugstate: nodates, datesort
247 debugsub: rev
249 debugsub: rev
248 debugwalk: include, exclude
250 debugwalk: include, exclude
249 debugwireargs: three, four, five, ssh, remotecmd, insecure
251 debugwireargs: three, four, five, ssh, remotecmd, insecure
250 graft: rev, continue, edit, log, currentdate, currentuser, date, user, tool, dry-run
252 graft: rev, continue, edit, log, currentdate, currentuser, date, user, tool, dry-run
251 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
253 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
252 heads: rev, topo, active, closed, style, template
254 heads: rev, topo, active, closed, style, template
253 help: extension, command, keyword
255 help: extension, command, keyword
254 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
256 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
255 import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
257 import: strip, base, edit, force, no-commit, bypass, exact, import-branch, message, logfile, date, user, similarity
256 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
258 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
257 locate: rev, print0, fullpath, include, exclude
259 locate: rev, print0, fullpath, include, exclude
258 manifest: rev, all
260 manifest: rev, all
259 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
261 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, style, template, ssh, remotecmd, insecure, subrepos
260 parents: rev, style, template
262 parents: rev, style, template
261 paths:
263 paths:
262 recover:
264 recover:
263 rename: after, force, include, exclude, dry-run
265 rename: after, force, include, exclude, dry-run
264 resolve: all, list, mark, unmark, no-status, tool, include, exclude
266 resolve: all, list, mark, unmark, no-status, tool, include, exclude
265 revert: all, date, rev, no-backup, include, exclude, dry-run
267 revert: all, date, rev, no-backup, include, exclude, dry-run
266 rollback: dry-run, force
268 rollback: dry-run, force
267 root:
269 root:
268 showconfig: untrusted
270 showconfig: untrusted
269 tag: force, local, rev, remove, edit, message, date, user
271 tag: force, local, rev, remove, edit, message, date, user
270 tags:
272 tags:
271 tip: patch, git, style, template
273 tip: patch, git, style, template
272 unbundle: update
274 unbundle: update
273 verify:
275 verify:
274 version:
276 version:
General Comments 0
You need to be logged in to leave comments. Login now