##// END OF EJS Templates
commands: add hidden -T option for files/manifest/status/tags...
Matt Mackall -
r22429:7a7eed51 default
parent child Browse files
Show More
@@ -1,6197 +1,6204
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 _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno, shlex
11 import os, re, difflib, time, tempfile, errno, shlex
12 import sys
12 import sys
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb, commandserver
16 import sshserver, hgweb, commandserver
17 import extensions
17 import extensions
18 from hgweb import server as hgweb_server
18 from hgweb import server as hgweb_server
19 import merge as mergemod
19 import merge as mergemod
20 import minirst, revset, fileset
20 import minirst, revset, fileset
21 import dagparser, context, simplemerge, graphmod
21 import dagparser, context, simplemerge, graphmod
22 import random
22 import random
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
24 import phases, obsolete, exchange
24 import phases, obsolete, exchange
25
25
26 table = {}
26 table = {}
27
27
28 command = cmdutil.command(table)
28 command = cmdutil.command(table)
29
29
30 # Space delimited list of commands that don't require local repositories.
30 # Space delimited list of commands that don't require local repositories.
31 # This should be populated by passing norepo=True into the @command decorator.
31 # This should be populated by passing norepo=True into the @command decorator.
32 norepo = ''
32 norepo = ''
33 # Space delimited list of commands that optionally require local repositories.
33 # Space delimited list of commands that optionally require local repositories.
34 # This should be populated by passing optionalrepo=True into the @command
34 # This should be populated by passing optionalrepo=True into the @command
35 # decorator.
35 # decorator.
36 optionalrepo = ''
36 optionalrepo = ''
37 # Space delimited list of commands that will examine arguments looking for
37 # Space delimited list of commands that will examine arguments looking for
38 # a repository. This should be populated by passing inferrepo=True into the
38 # a repository. This should be populated by passing inferrepo=True into the
39 # @command decorator.
39 # @command decorator.
40 inferrepo = ''
40 inferrepo = ''
41
41
42 # common command options
42 # common command options
43
43
44 globalopts = [
44 globalopts = [
45 ('R', 'repository', '',
45 ('R', 'repository', '',
46 _('repository root directory or name of overlay bundle file'),
46 _('repository root directory or name of overlay bundle file'),
47 _('REPO')),
47 _('REPO')),
48 ('', 'cwd', '',
48 ('', 'cwd', '',
49 _('change working directory'), _('DIR')),
49 _('change working directory'), _('DIR')),
50 ('y', 'noninteractive', None,
50 ('y', 'noninteractive', None,
51 _('do not prompt, automatically pick the first choice for all prompts')),
51 _('do not prompt, automatically pick the first choice for all prompts')),
52 ('q', 'quiet', None, _('suppress output')),
52 ('q', 'quiet', None, _('suppress output')),
53 ('v', 'verbose', None, _('enable additional output')),
53 ('v', 'verbose', None, _('enable additional output')),
54 ('', 'config', [],
54 ('', 'config', [],
55 _('set/override config option (use \'section.name=value\')'),
55 _('set/override config option (use \'section.name=value\')'),
56 _('CONFIG')),
56 _('CONFIG')),
57 ('', 'debug', None, _('enable debugging output')),
57 ('', 'debug', None, _('enable debugging output')),
58 ('', 'debugger', None, _('start debugger')),
58 ('', 'debugger', None, _('start debugger')),
59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
60 _('ENCODE')),
60 _('ENCODE')),
61 ('', 'encodingmode', encoding.encodingmode,
61 ('', 'encodingmode', encoding.encodingmode,
62 _('set the charset encoding mode'), _('MODE')),
62 _('set the charset encoding mode'), _('MODE')),
63 ('', 'traceback', None, _('always print a traceback on exception')),
63 ('', 'traceback', None, _('always print a traceback on exception')),
64 ('', 'time', None, _('time how long the command takes')),
64 ('', 'time', None, _('time how long the command takes')),
65 ('', 'profile', None, _('print command execution profile')),
65 ('', 'profile', None, _('print command execution profile')),
66 ('', 'version', None, _('output version information and exit')),
66 ('', 'version', None, _('output version information and exit')),
67 ('h', 'help', None, _('display help and exit')),
67 ('h', 'help', None, _('display help and exit')),
68 ('', 'hidden', False, _('consider hidden changesets')),
68 ('', 'hidden', False, _('consider hidden changesets')),
69 ]
69 ]
70
70
71 dryrunopts = [('n', 'dry-run', None,
71 dryrunopts = [('n', 'dry-run', None,
72 _('do not perform actions, just print output'))]
72 _('do not perform actions, just print output'))]
73
73
74 remoteopts = [
74 remoteopts = [
75 ('e', 'ssh', '',
75 ('e', 'ssh', '',
76 _('specify ssh command to use'), _('CMD')),
76 _('specify ssh command to use'), _('CMD')),
77 ('', 'remotecmd', '',
77 ('', 'remotecmd', '',
78 _('specify hg command to run on the remote side'), _('CMD')),
78 _('specify hg command to run on the remote side'), _('CMD')),
79 ('', 'insecure', None,
79 ('', 'insecure', None,
80 _('do not verify server certificate (ignoring web.cacerts config)')),
80 _('do not verify server certificate (ignoring web.cacerts config)')),
81 ]
81 ]
82
82
83 walkopts = [
83 walkopts = [
84 ('I', 'include', [],
84 ('I', 'include', [],
85 _('include names matching the given patterns'), _('PATTERN')),
85 _('include names matching the given patterns'), _('PATTERN')),
86 ('X', 'exclude', [],
86 ('X', 'exclude', [],
87 _('exclude names matching the given patterns'), _('PATTERN')),
87 _('exclude names matching the given patterns'), _('PATTERN')),
88 ]
88 ]
89
89
90 commitopts = [
90 commitopts = [
91 ('m', 'message', '',
91 ('m', 'message', '',
92 _('use text as commit message'), _('TEXT')),
92 _('use text as commit message'), _('TEXT')),
93 ('l', 'logfile', '',
93 ('l', 'logfile', '',
94 _('read commit message from file'), _('FILE')),
94 _('read commit message from file'), _('FILE')),
95 ]
95 ]
96
96
97 commitopts2 = [
97 commitopts2 = [
98 ('d', 'date', '',
98 ('d', 'date', '',
99 _('record the specified date as commit date'), _('DATE')),
99 _('record the specified date as commit date'), _('DATE')),
100 ('u', 'user', '',
100 ('u', 'user', '',
101 _('record the specified user as committer'), _('USER')),
101 _('record the specified user as committer'), _('USER')),
102 ]
102 ]
103
103
104 # hidden for now
105 formatteropts = [
106 ('T', 'template', '',
107 _('display with template (DEPRECATED)'), _('TEMPLATE')),
108 ]
109
104 templateopts = [
110 templateopts = [
105 ('', 'style', '',
111 ('', 'style', '',
106 _('display using template map file (DEPRECATED)'), _('STYLE')),
112 _('display using template map file (DEPRECATED)'), _('STYLE')),
107 ('T', 'template', '',
113 ('T', 'template', '',
108 _('display with template'), _('TEMPLATE')),
114 _('display with template'), _('TEMPLATE')),
109 ]
115 ]
110
116
111 logopts = [
117 logopts = [
112 ('p', 'patch', None, _('show patch')),
118 ('p', 'patch', None, _('show patch')),
113 ('g', 'git', None, _('use git extended diff format')),
119 ('g', 'git', None, _('use git extended diff format')),
114 ('l', 'limit', '',
120 ('l', 'limit', '',
115 _('limit number of changes displayed'), _('NUM')),
121 _('limit number of changes displayed'), _('NUM')),
116 ('M', 'no-merges', None, _('do not show merges')),
122 ('M', 'no-merges', None, _('do not show merges')),
117 ('', 'stat', None, _('output diffstat-style summary of changes')),
123 ('', 'stat', None, _('output diffstat-style summary of changes')),
118 ('G', 'graph', None, _("show the revision DAG")),
124 ('G', 'graph', None, _("show the revision DAG")),
119 ] + templateopts
125 ] + templateopts
120
126
121 diffopts = [
127 diffopts = [
122 ('a', 'text', None, _('treat all files as text')),
128 ('a', 'text', None, _('treat all files as text')),
123 ('g', 'git', None, _('use git extended diff format')),
129 ('g', 'git', None, _('use git extended diff format')),
124 ('', 'nodates', None, _('omit dates from diff headers'))
130 ('', 'nodates', None, _('omit dates from diff headers'))
125 ]
131 ]
126
132
127 diffwsopts = [
133 diffwsopts = [
128 ('w', 'ignore-all-space', None,
134 ('w', 'ignore-all-space', None,
129 _('ignore white space when comparing lines')),
135 _('ignore white space when comparing lines')),
130 ('b', 'ignore-space-change', None,
136 ('b', 'ignore-space-change', None,
131 _('ignore changes in the amount of white space')),
137 _('ignore changes in the amount of white space')),
132 ('B', 'ignore-blank-lines', None,
138 ('B', 'ignore-blank-lines', None,
133 _('ignore changes whose lines are all blank')),
139 _('ignore changes whose lines are all blank')),
134 ]
140 ]
135
141
136 diffopts2 = [
142 diffopts2 = [
137 ('p', 'show-function', None, _('show which function each change is in')),
143 ('p', 'show-function', None, _('show which function each change is in')),
138 ('', 'reverse', None, _('produce a diff that undoes the changes')),
144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
139 ] + diffwsopts + [
145 ] + diffwsopts + [
140 ('U', 'unified', '',
146 ('U', 'unified', '',
141 _('number of lines of context to show'), _('NUM')),
147 _('number of lines of context to show'), _('NUM')),
142 ('', 'stat', None, _('output diffstat-style summary of changes')),
148 ('', 'stat', None, _('output diffstat-style summary of changes')),
143 ]
149 ]
144
150
145 mergetoolopts = [
151 mergetoolopts = [
146 ('t', 'tool', '', _('specify merge tool')),
152 ('t', 'tool', '', _('specify merge tool')),
147 ]
153 ]
148
154
149 similarityopts = [
155 similarityopts = [
150 ('s', 'similarity', '',
156 ('s', 'similarity', '',
151 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
152 ]
158 ]
153
159
154 subrepoopts = [
160 subrepoopts = [
155 ('S', 'subrepos', None,
161 ('S', 'subrepos', None,
156 _('recurse into subrepositories'))
162 _('recurse into subrepositories'))
157 ]
163 ]
158
164
159 # Commands start here, listed alphabetically
165 # Commands start here, listed alphabetically
160
166
161 @command('^add',
167 @command('^add',
162 walkopts + subrepoopts + dryrunopts,
168 walkopts + subrepoopts + dryrunopts,
163 _('[OPTION]... [FILE]...'),
169 _('[OPTION]... [FILE]...'),
164 inferrepo=True)
170 inferrepo=True)
165 def add(ui, repo, *pats, **opts):
171 def add(ui, repo, *pats, **opts):
166 """add the specified files on the next commit
172 """add the specified files on the next commit
167
173
168 Schedule files to be version controlled and added to the
174 Schedule files to be version controlled and added to the
169 repository.
175 repository.
170
176
171 The files will be added to the repository at the next commit. To
177 The files will be added to the repository at the next commit. To
172 undo an add before that, see :hg:`forget`.
178 undo an add before that, see :hg:`forget`.
173
179
174 If no names are given, add all files to the repository.
180 If no names are given, add all files to the repository.
175
181
176 .. container:: verbose
182 .. container:: verbose
177
183
178 An example showing how new (unknown) files are added
184 An example showing how new (unknown) files are added
179 automatically by :hg:`add`::
185 automatically by :hg:`add`::
180
186
181 $ ls
187 $ ls
182 foo.c
188 foo.c
183 $ hg status
189 $ hg status
184 ? foo.c
190 ? foo.c
185 $ hg add
191 $ hg add
186 adding foo.c
192 adding foo.c
187 $ hg status
193 $ hg status
188 A foo.c
194 A foo.c
189
195
190 Returns 0 if all files are successfully added.
196 Returns 0 if all files are successfully added.
191 """
197 """
192
198
193 m = scmutil.match(repo[None], pats, opts)
199 m = scmutil.match(repo[None], pats, opts)
194 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
200 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
195 opts.get('subrepos'), prefix="", explicitonly=False)
201 opts.get('subrepos'), prefix="", explicitonly=False)
196 return rejected and 1 or 0
202 return rejected and 1 or 0
197
203
198 @command('addremove',
204 @command('addremove',
199 similarityopts + walkopts + dryrunopts,
205 similarityopts + walkopts + dryrunopts,
200 _('[OPTION]... [FILE]...'),
206 _('[OPTION]... [FILE]...'),
201 inferrepo=True)
207 inferrepo=True)
202 def addremove(ui, repo, *pats, **opts):
208 def addremove(ui, repo, *pats, **opts):
203 """add all new files, delete all missing files
209 """add all new files, delete all missing files
204
210
205 Add all new files and remove all missing files from the
211 Add all new files and remove all missing files from the
206 repository.
212 repository.
207
213
208 New files are ignored if they match any of the patterns in
214 New files are ignored if they match any of the patterns in
209 ``.hgignore``. As with add, these changes take effect at the next
215 ``.hgignore``. As with add, these changes take effect at the next
210 commit.
216 commit.
211
217
212 Use the -s/--similarity option to detect renamed files. This
218 Use the -s/--similarity option to detect renamed files. This
213 option takes a percentage between 0 (disabled) and 100 (files must
219 option takes a percentage between 0 (disabled) and 100 (files must
214 be identical) as its parameter. With a parameter greater than 0,
220 be identical) as its parameter. With a parameter greater than 0,
215 this compares every removed file with every added file and records
221 this compares every removed file with every added file and records
216 those similar enough as renames. Detecting renamed files this way
222 those similar enough as renames. Detecting renamed files this way
217 can be expensive. After using this option, :hg:`status -C` can be
223 can be expensive. After using this option, :hg:`status -C` can be
218 used to check which files were identified as moved or renamed. If
224 used to check which files were identified as moved or renamed. If
219 not specified, -s/--similarity defaults to 100 and only renames of
225 not specified, -s/--similarity defaults to 100 and only renames of
220 identical files are detected.
226 identical files are detected.
221
227
222 Returns 0 if all files are successfully added.
228 Returns 0 if all files are successfully added.
223 """
229 """
224 try:
230 try:
225 sim = float(opts.get('similarity') or 100)
231 sim = float(opts.get('similarity') or 100)
226 except ValueError:
232 except ValueError:
227 raise util.Abort(_('similarity must be a number'))
233 raise util.Abort(_('similarity must be a number'))
228 if sim < 0 or sim > 100:
234 if sim < 0 or sim > 100:
229 raise util.Abort(_('similarity must be between 0 and 100'))
235 raise util.Abort(_('similarity must be between 0 and 100'))
230 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
236 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
231
237
232 @command('^annotate|blame',
238 @command('^annotate|blame',
233 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
239 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
234 ('', 'follow', None,
240 ('', 'follow', None,
235 _('follow copies/renames and list the filename (DEPRECATED)')),
241 _('follow copies/renames and list the filename (DEPRECATED)')),
236 ('', 'no-follow', None, _("don't follow copies and renames")),
242 ('', 'no-follow', None, _("don't follow copies and renames")),
237 ('a', 'text', None, _('treat all files as text')),
243 ('a', 'text', None, _('treat all files as text')),
238 ('u', 'user', None, _('list the author (long with -v)')),
244 ('u', 'user', None, _('list the author (long with -v)')),
239 ('f', 'file', None, _('list the filename')),
245 ('f', 'file', None, _('list the filename')),
240 ('d', 'date', None, _('list the date (short with -q)')),
246 ('d', 'date', None, _('list the date (short with -q)')),
241 ('n', 'number', None, _('list the revision number (default)')),
247 ('n', 'number', None, _('list the revision number (default)')),
242 ('c', 'changeset', None, _('list the changeset')),
248 ('c', 'changeset', None, _('list the changeset')),
243 ('l', 'line-number', None, _('show line number at the first appearance'))
249 ('l', 'line-number', None, _('show line number at the first appearance'))
244 ] + diffwsopts + walkopts,
250 ] + diffwsopts + walkopts,
245 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
251 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
246 inferrepo=True)
252 inferrepo=True)
247 def annotate(ui, repo, *pats, **opts):
253 def annotate(ui, repo, *pats, **opts):
248 """show changeset information by line for each file
254 """show changeset information by line for each file
249
255
250 List changes in files, showing the revision id responsible for
256 List changes in files, showing the revision id responsible for
251 each line
257 each line
252
258
253 This command is useful for discovering when a change was made and
259 This command is useful for discovering when a change was made and
254 by whom.
260 by whom.
255
261
256 Without the -a/--text option, annotate will avoid processing files
262 Without the -a/--text option, annotate will avoid processing files
257 it detects as binary. With -a, annotate will annotate the file
263 it detects as binary. With -a, annotate will annotate the file
258 anyway, although the results will probably be neither useful
264 anyway, although the results will probably be neither useful
259 nor desirable.
265 nor desirable.
260
266
261 Returns 0 on success.
267 Returns 0 on success.
262 """
268 """
263 if not pats:
269 if not pats:
264 raise util.Abort(_('at least one filename or pattern is required'))
270 raise util.Abort(_('at least one filename or pattern is required'))
265
271
266 if opts.get('follow'):
272 if opts.get('follow'):
267 # --follow is deprecated and now just an alias for -f/--file
273 # --follow is deprecated and now just an alias for -f/--file
268 # to mimic the behavior of Mercurial before version 1.5
274 # to mimic the behavior of Mercurial before version 1.5
269 opts['file'] = True
275 opts['file'] = True
270
276
271 datefunc = ui.quiet and util.shortdate or util.datestr
277 datefunc = ui.quiet and util.shortdate or util.datestr
272 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
278 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
273 hexfn = ui.debugflag and hex or short
279 hexfn = ui.debugflag and hex or short
274
280
275 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
281 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
276 ('number', ' ', lambda x: str(x[0].rev())),
282 ('number', ' ', lambda x: str(x[0].rev())),
277 ('changeset', ' ', lambda x: hexfn(x[0].node())),
283 ('changeset', ' ', lambda x: hexfn(x[0].node())),
278 ('date', ' ', getdate),
284 ('date', ' ', getdate),
279 ('file', ' ', lambda x: x[0].path()),
285 ('file', ' ', lambda x: x[0].path()),
280 ('line_number', ':', lambda x: str(x[1])),
286 ('line_number', ':', lambda x: str(x[1])),
281 ]
287 ]
282
288
283 if (not opts.get('user') and not opts.get('changeset')
289 if (not opts.get('user') and not opts.get('changeset')
284 and not opts.get('date') and not opts.get('file')):
290 and not opts.get('date') and not opts.get('file')):
285 opts['number'] = True
291 opts['number'] = True
286
292
287 linenumber = opts.get('line_number') is not None
293 linenumber = opts.get('line_number') is not None
288 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
294 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
289 raise util.Abort(_('at least one of -n/-c is required for -l'))
295 raise util.Abort(_('at least one of -n/-c is required for -l'))
290
296
291 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
297 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
292 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
298 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
293
299
294 def bad(x, y):
300 def bad(x, y):
295 raise util.Abort("%s: %s" % (x, y))
301 raise util.Abort("%s: %s" % (x, y))
296
302
297 ctx = scmutil.revsingle(repo, opts.get('rev'))
303 ctx = scmutil.revsingle(repo, opts.get('rev'))
298 m = scmutil.match(ctx, pats, opts)
304 m = scmutil.match(ctx, pats, opts)
299 m.bad = bad
305 m.bad = bad
300 follow = not opts.get('no_follow')
306 follow = not opts.get('no_follow')
301 diffopts = patch.diffopts(ui, opts, section='annotate')
307 diffopts = patch.diffopts(ui, opts, section='annotate')
302 for abs in ctx.walk(m):
308 for abs in ctx.walk(m):
303 fctx = ctx[abs]
309 fctx = ctx[abs]
304 if not opts.get('text') and util.binary(fctx.data()):
310 if not opts.get('text') and util.binary(fctx.data()):
305 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
311 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
306 continue
312 continue
307
313
308 lines = fctx.annotate(follow=follow, linenumber=linenumber,
314 lines = fctx.annotate(follow=follow, linenumber=linenumber,
309 diffopts=diffopts)
315 diffopts=diffopts)
310 pieces = []
316 pieces = []
311
317
312 for f, sep in funcmap:
318 for f, sep in funcmap:
313 l = [f(n) for n, dummy in lines]
319 l = [f(n) for n, dummy in lines]
314 if l:
320 if l:
315 sized = [(x, encoding.colwidth(x)) for x in l]
321 sized = [(x, encoding.colwidth(x)) for x in l]
316 ml = max([w for x, w in sized])
322 ml = max([w for x, w in sized])
317 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
323 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
318 for x, w in sized])
324 for x, w in sized])
319
325
320 if pieces:
326 if pieces:
321 for p, l in zip(zip(*pieces), lines):
327 for p, l in zip(zip(*pieces), lines):
322 ui.write("%s: %s" % ("".join(p), l[1]))
328 ui.write("%s: %s" % ("".join(p), l[1]))
323
329
324 if lines and not lines[-1][1].endswith('\n'):
330 if lines and not lines[-1][1].endswith('\n'):
325 ui.write('\n')
331 ui.write('\n')
326
332
327 @command('archive',
333 @command('archive',
328 [('', 'no-decode', None, _('do not pass files through decoders')),
334 [('', 'no-decode', None, _('do not pass files through decoders')),
329 ('p', 'prefix', '', _('directory prefix for files in archive'),
335 ('p', 'prefix', '', _('directory prefix for files in archive'),
330 _('PREFIX')),
336 _('PREFIX')),
331 ('r', 'rev', '', _('revision to distribute'), _('REV')),
337 ('r', 'rev', '', _('revision to distribute'), _('REV')),
332 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
338 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
333 ] + subrepoopts + walkopts,
339 ] + subrepoopts + walkopts,
334 _('[OPTION]... DEST'))
340 _('[OPTION]... DEST'))
335 def archive(ui, repo, dest, **opts):
341 def archive(ui, repo, dest, **opts):
336 '''create an unversioned archive of a repository revision
342 '''create an unversioned archive of a repository revision
337
343
338 By default, the revision used is the parent of the working
344 By default, the revision used is the parent of the working
339 directory; use -r/--rev to specify a different revision.
345 directory; use -r/--rev to specify a different revision.
340
346
341 The archive type is automatically detected based on file
347 The archive type is automatically detected based on file
342 extension (or override using -t/--type).
348 extension (or override using -t/--type).
343
349
344 .. container:: verbose
350 .. container:: verbose
345
351
346 Examples:
352 Examples:
347
353
348 - create a zip file containing the 1.0 release::
354 - create a zip file containing the 1.0 release::
349
355
350 hg archive -r 1.0 project-1.0.zip
356 hg archive -r 1.0 project-1.0.zip
351
357
352 - create a tarball excluding .hg files::
358 - create a tarball excluding .hg files::
353
359
354 hg archive project.tar.gz -X ".hg*"
360 hg archive project.tar.gz -X ".hg*"
355
361
356 Valid types are:
362 Valid types are:
357
363
358 :``files``: a directory full of files (default)
364 :``files``: a directory full of files (default)
359 :``tar``: tar archive, uncompressed
365 :``tar``: tar archive, uncompressed
360 :``tbz2``: tar archive, compressed using bzip2
366 :``tbz2``: tar archive, compressed using bzip2
361 :``tgz``: tar archive, compressed using gzip
367 :``tgz``: tar archive, compressed using gzip
362 :``uzip``: zip archive, uncompressed
368 :``uzip``: zip archive, uncompressed
363 :``zip``: zip archive, compressed using deflate
369 :``zip``: zip archive, compressed using deflate
364
370
365 The exact name of the destination archive or directory is given
371 The exact name of the destination archive or directory is given
366 using a format string; see :hg:`help export` for details.
372 using a format string; see :hg:`help export` for details.
367
373
368 Each member added to an archive file has a directory prefix
374 Each member added to an archive file has a directory prefix
369 prepended. Use -p/--prefix to specify a format string for the
375 prepended. Use -p/--prefix to specify a format string for the
370 prefix. The default is the basename of the archive, with suffixes
376 prefix. The default is the basename of the archive, with suffixes
371 removed.
377 removed.
372
378
373 Returns 0 on success.
379 Returns 0 on success.
374 '''
380 '''
375
381
376 ctx = scmutil.revsingle(repo, opts.get('rev'))
382 ctx = scmutil.revsingle(repo, opts.get('rev'))
377 if not ctx:
383 if not ctx:
378 raise util.Abort(_('no working directory: please specify a revision'))
384 raise util.Abort(_('no working directory: please specify a revision'))
379 node = ctx.node()
385 node = ctx.node()
380 dest = cmdutil.makefilename(repo, dest, node)
386 dest = cmdutil.makefilename(repo, dest, node)
381 if os.path.realpath(dest) == repo.root:
387 if os.path.realpath(dest) == repo.root:
382 raise util.Abort(_('repository root cannot be destination'))
388 raise util.Abort(_('repository root cannot be destination'))
383
389
384 kind = opts.get('type') or archival.guesskind(dest) or 'files'
390 kind = opts.get('type') or archival.guesskind(dest) or 'files'
385 prefix = opts.get('prefix')
391 prefix = opts.get('prefix')
386
392
387 if dest == '-':
393 if dest == '-':
388 if kind == 'files':
394 if kind == 'files':
389 raise util.Abort(_('cannot archive plain files to stdout'))
395 raise util.Abort(_('cannot archive plain files to stdout'))
390 dest = cmdutil.makefileobj(repo, dest)
396 dest = cmdutil.makefileobj(repo, dest)
391 if not prefix:
397 if not prefix:
392 prefix = os.path.basename(repo.root) + '-%h'
398 prefix = os.path.basename(repo.root) + '-%h'
393
399
394 prefix = cmdutil.makefilename(repo, prefix, node)
400 prefix = cmdutil.makefilename(repo, prefix, node)
395 matchfn = scmutil.match(ctx, [], opts)
401 matchfn = scmutil.match(ctx, [], opts)
396 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
402 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
397 matchfn, prefix, subrepos=opts.get('subrepos'))
403 matchfn, prefix, subrepos=opts.get('subrepos'))
398
404
399 @command('backout',
405 @command('backout',
400 [('', 'merge', None, _('merge with old dirstate parent after backout')),
406 [('', 'merge', None, _('merge with old dirstate parent after backout')),
401 ('', 'parent', '',
407 ('', 'parent', '',
402 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
408 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
403 ('r', 'rev', '', _('revision to backout'), _('REV')),
409 ('r', 'rev', '', _('revision to backout'), _('REV')),
404 ('e', 'edit', False, _('invoke editor on commit messages')),
410 ('e', 'edit', False, _('invoke editor on commit messages')),
405 ] + mergetoolopts + walkopts + commitopts + commitopts2,
411 ] + mergetoolopts + walkopts + commitopts + commitopts2,
406 _('[OPTION]... [-r] REV'))
412 _('[OPTION]... [-r] REV'))
407 def backout(ui, repo, node=None, rev=None, **opts):
413 def backout(ui, repo, node=None, rev=None, **opts):
408 '''reverse effect of earlier changeset
414 '''reverse effect of earlier changeset
409
415
410 Prepare a new changeset with the effect of REV undone in the
416 Prepare a new changeset with the effect of REV undone in the
411 current working directory.
417 current working directory.
412
418
413 If REV is the parent of the working directory, then this new changeset
419 If REV is the parent of the working directory, then this new changeset
414 is committed automatically. Otherwise, hg needs to merge the
420 is committed automatically. Otherwise, hg needs to merge the
415 changes and the merged result is left uncommitted.
421 changes and the merged result is left uncommitted.
416
422
417 .. note::
423 .. note::
418
424
419 backout cannot be used to fix either an unwanted or
425 backout cannot be used to fix either an unwanted or
420 incorrect merge.
426 incorrect merge.
421
427
422 .. container:: verbose
428 .. container:: verbose
423
429
424 By default, the pending changeset will have one parent,
430 By default, the pending changeset will have one parent,
425 maintaining a linear history. With --merge, the pending
431 maintaining a linear history. With --merge, the pending
426 changeset will instead have two parents: the old parent of the
432 changeset will instead have two parents: the old parent of the
427 working directory and a new child of REV that simply undoes REV.
433 working directory and a new child of REV that simply undoes REV.
428
434
429 Before version 1.7, the behavior without --merge was equivalent
435 Before version 1.7, the behavior without --merge was equivalent
430 to specifying --merge followed by :hg:`update --clean .` to
436 to specifying --merge followed by :hg:`update --clean .` to
431 cancel the merge and leave the child of REV as a head to be
437 cancel the merge and leave the child of REV as a head to be
432 merged separately.
438 merged separately.
433
439
434 See :hg:`help dates` for a list of formats valid for -d/--date.
440 See :hg:`help dates` for a list of formats valid for -d/--date.
435
441
436 Returns 0 on success, 1 if nothing to backout or there are unresolved
442 Returns 0 on success, 1 if nothing to backout or there are unresolved
437 files.
443 files.
438 '''
444 '''
439 if rev and node:
445 if rev and node:
440 raise util.Abort(_("please specify just one revision"))
446 raise util.Abort(_("please specify just one revision"))
441
447
442 if not rev:
448 if not rev:
443 rev = node
449 rev = node
444
450
445 if not rev:
451 if not rev:
446 raise util.Abort(_("please specify a revision to backout"))
452 raise util.Abort(_("please specify a revision to backout"))
447
453
448 date = opts.get('date')
454 date = opts.get('date')
449 if date:
455 if date:
450 opts['date'] = util.parsedate(date)
456 opts['date'] = util.parsedate(date)
451
457
452 cmdutil.checkunfinished(repo)
458 cmdutil.checkunfinished(repo)
453 cmdutil.bailifchanged(repo)
459 cmdutil.bailifchanged(repo)
454 node = scmutil.revsingle(repo, rev).node()
460 node = scmutil.revsingle(repo, rev).node()
455
461
456 op1, op2 = repo.dirstate.parents()
462 op1, op2 = repo.dirstate.parents()
457 if not repo.changelog.isancestor(node, op1):
463 if not repo.changelog.isancestor(node, op1):
458 raise util.Abort(_('cannot backout change that is not an ancestor'))
464 raise util.Abort(_('cannot backout change that is not an ancestor'))
459
465
460 p1, p2 = repo.changelog.parents(node)
466 p1, p2 = repo.changelog.parents(node)
461 if p1 == nullid:
467 if p1 == nullid:
462 raise util.Abort(_('cannot backout a change with no parents'))
468 raise util.Abort(_('cannot backout a change with no parents'))
463 if p2 != nullid:
469 if p2 != nullid:
464 if not opts.get('parent'):
470 if not opts.get('parent'):
465 raise util.Abort(_('cannot backout a merge changeset'))
471 raise util.Abort(_('cannot backout a merge changeset'))
466 p = repo.lookup(opts['parent'])
472 p = repo.lookup(opts['parent'])
467 if p not in (p1, p2):
473 if p not in (p1, p2):
468 raise util.Abort(_('%s is not a parent of %s') %
474 raise util.Abort(_('%s is not a parent of %s') %
469 (short(p), short(node)))
475 (short(p), short(node)))
470 parent = p
476 parent = p
471 else:
477 else:
472 if opts.get('parent'):
478 if opts.get('parent'):
473 raise util.Abort(_('cannot use --parent on non-merge changeset'))
479 raise util.Abort(_('cannot use --parent on non-merge changeset'))
474 parent = p1
480 parent = p1
475
481
476 # the backout should appear on the same branch
482 # the backout should appear on the same branch
477 wlock = repo.wlock()
483 wlock = repo.wlock()
478 try:
484 try:
479 branch = repo.dirstate.branch()
485 branch = repo.dirstate.branch()
480 bheads = repo.branchheads(branch)
486 bheads = repo.branchheads(branch)
481 rctx = scmutil.revsingle(repo, hex(parent))
487 rctx = scmutil.revsingle(repo, hex(parent))
482 if not opts.get('merge') and op1 != node:
488 if not opts.get('merge') and op1 != node:
483 try:
489 try:
484 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
490 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
485 'backout')
491 'backout')
486 repo.dirstate.beginparentchange()
492 repo.dirstate.beginparentchange()
487 stats = mergemod.update(repo, parent, True, True, False,
493 stats = mergemod.update(repo, parent, True, True, False,
488 node, False)
494 node, False)
489 repo.setparents(op1, op2)
495 repo.setparents(op1, op2)
490 repo.dirstate.endparentchange()
496 repo.dirstate.endparentchange()
491 hg._showstats(repo, stats)
497 hg._showstats(repo, stats)
492 if stats[3]:
498 if stats[3]:
493 repo.ui.status(_("use 'hg resolve' to retry unresolved "
499 repo.ui.status(_("use 'hg resolve' to retry unresolved "
494 "file merges\n"))
500 "file merges\n"))
495 else:
501 else:
496 msg = _("changeset %s backed out, "
502 msg = _("changeset %s backed out, "
497 "don't forget to commit.\n")
503 "don't forget to commit.\n")
498 ui.status(msg % short(node))
504 ui.status(msg % short(node))
499 return stats[3] > 0
505 return stats[3] > 0
500 finally:
506 finally:
501 ui.setconfig('ui', 'forcemerge', '', '')
507 ui.setconfig('ui', 'forcemerge', '', '')
502 else:
508 else:
503 hg.clean(repo, node, show_stats=False)
509 hg.clean(repo, node, show_stats=False)
504 repo.dirstate.setbranch(branch)
510 repo.dirstate.setbranch(branch)
505 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
511 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
506
512
507
513
508 def commitfunc(ui, repo, message, match, opts):
514 def commitfunc(ui, repo, message, match, opts):
509 editform = 'backout'
515 editform = 'backout'
510 e = cmdutil.getcommiteditor(editform=editform, **opts)
516 e = cmdutil.getcommiteditor(editform=editform, **opts)
511 if not message:
517 if not message:
512 # we don't translate commit messages
518 # we don't translate commit messages
513 message = "Backed out changeset %s" % short(node)
519 message = "Backed out changeset %s" % short(node)
514 e = cmdutil.getcommiteditor(edit=True, editform=editform)
520 e = cmdutil.getcommiteditor(edit=True, editform=editform)
515 return repo.commit(message, opts.get('user'), opts.get('date'),
521 return repo.commit(message, opts.get('user'), opts.get('date'),
516 match, editor=e)
522 match, editor=e)
517 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
523 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
518 if not newnode:
524 if not newnode:
519 ui.status(_("nothing changed\n"))
525 ui.status(_("nothing changed\n"))
520 return 1
526 return 1
521 cmdutil.commitstatus(repo, newnode, branch, bheads)
527 cmdutil.commitstatus(repo, newnode, branch, bheads)
522
528
523 def nice(node):
529 def nice(node):
524 return '%d:%s' % (repo.changelog.rev(node), short(node))
530 return '%d:%s' % (repo.changelog.rev(node), short(node))
525 ui.status(_('changeset %s backs out changeset %s\n') %
531 ui.status(_('changeset %s backs out changeset %s\n') %
526 (nice(repo.changelog.tip()), nice(node)))
532 (nice(repo.changelog.tip()), nice(node)))
527 if opts.get('merge') and op1 != node:
533 if opts.get('merge') and op1 != node:
528 hg.clean(repo, op1, show_stats=False)
534 hg.clean(repo, op1, show_stats=False)
529 ui.status(_('merging with changeset %s\n')
535 ui.status(_('merging with changeset %s\n')
530 % nice(repo.changelog.tip()))
536 % nice(repo.changelog.tip()))
531 try:
537 try:
532 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
538 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
533 'backout')
539 'backout')
534 return hg.merge(repo, hex(repo.changelog.tip()))
540 return hg.merge(repo, hex(repo.changelog.tip()))
535 finally:
541 finally:
536 ui.setconfig('ui', 'forcemerge', '', '')
542 ui.setconfig('ui', 'forcemerge', '', '')
537 finally:
543 finally:
538 wlock.release()
544 wlock.release()
539 return 0
545 return 0
540
546
541 @command('bisect',
547 @command('bisect',
542 [('r', 'reset', False, _('reset bisect state')),
548 [('r', 'reset', False, _('reset bisect state')),
543 ('g', 'good', False, _('mark changeset good')),
549 ('g', 'good', False, _('mark changeset good')),
544 ('b', 'bad', False, _('mark changeset bad')),
550 ('b', 'bad', False, _('mark changeset bad')),
545 ('s', 'skip', False, _('skip testing changeset')),
551 ('s', 'skip', False, _('skip testing changeset')),
546 ('e', 'extend', False, _('extend the bisect range')),
552 ('e', 'extend', False, _('extend the bisect range')),
547 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
553 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
548 ('U', 'noupdate', False, _('do not update to target'))],
554 ('U', 'noupdate', False, _('do not update to target'))],
549 _("[-gbsr] [-U] [-c CMD] [REV]"))
555 _("[-gbsr] [-U] [-c CMD] [REV]"))
550 def bisect(ui, repo, rev=None, extra=None, command=None,
556 def bisect(ui, repo, rev=None, extra=None, command=None,
551 reset=None, good=None, bad=None, skip=None, extend=None,
557 reset=None, good=None, bad=None, skip=None, extend=None,
552 noupdate=None):
558 noupdate=None):
553 """subdivision search of changesets
559 """subdivision search of changesets
554
560
555 This command helps to find changesets which introduce problems. To
561 This command helps to find changesets which introduce problems. To
556 use, mark the earliest changeset you know exhibits the problem as
562 use, mark the earliest changeset you know exhibits the problem as
557 bad, then mark the latest changeset which is free from the problem
563 bad, then mark the latest changeset which is free from the problem
558 as good. Bisect will update your working directory to a revision
564 as good. Bisect will update your working directory to a revision
559 for testing (unless the -U/--noupdate option is specified). Once
565 for testing (unless the -U/--noupdate option is specified). Once
560 you have performed tests, mark the working directory as good or
566 you have performed tests, mark the working directory as good or
561 bad, and bisect will either update to another candidate changeset
567 bad, and bisect will either update to another candidate changeset
562 or announce that it has found the bad revision.
568 or announce that it has found the bad revision.
563
569
564 As a shortcut, you can also use the revision argument to mark a
570 As a shortcut, you can also use the revision argument to mark a
565 revision as good or bad without checking it out first.
571 revision as good or bad without checking it out first.
566
572
567 If you supply a command, it will be used for automatic bisection.
573 If you supply a command, it will be used for automatic bisection.
568 The environment variable HG_NODE will contain the ID of the
574 The environment variable HG_NODE will contain the ID of the
569 changeset being tested. The exit status of the command will be
575 changeset being tested. The exit status of the command will be
570 used to mark revisions as good or bad: status 0 means good, 125
576 used to mark revisions as good or bad: status 0 means good, 125
571 means to skip the revision, 127 (command not found) will abort the
577 means to skip the revision, 127 (command not found) will abort the
572 bisection, and any other non-zero exit status means the revision
578 bisection, and any other non-zero exit status means the revision
573 is bad.
579 is bad.
574
580
575 .. container:: verbose
581 .. container:: verbose
576
582
577 Some examples:
583 Some examples:
578
584
579 - start a bisection with known bad revision 34, and good revision 12::
585 - start a bisection with known bad revision 34, and good revision 12::
580
586
581 hg bisect --bad 34
587 hg bisect --bad 34
582 hg bisect --good 12
588 hg bisect --good 12
583
589
584 - advance the current bisection by marking current revision as good or
590 - advance the current bisection by marking current revision as good or
585 bad::
591 bad::
586
592
587 hg bisect --good
593 hg bisect --good
588 hg bisect --bad
594 hg bisect --bad
589
595
590 - mark the current revision, or a known revision, to be skipped (e.g. if
596 - mark the current revision, or a known revision, to be skipped (e.g. if
591 that revision is not usable because of another issue)::
597 that revision is not usable because of another issue)::
592
598
593 hg bisect --skip
599 hg bisect --skip
594 hg bisect --skip 23
600 hg bisect --skip 23
595
601
596 - skip all revisions that do not touch directories ``foo`` or ``bar``::
602 - skip all revisions that do not touch directories ``foo`` or ``bar``::
597
603
598 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
604 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
599
605
600 - forget the current bisection::
606 - forget the current bisection::
601
607
602 hg bisect --reset
608 hg bisect --reset
603
609
604 - use 'make && make tests' to automatically find the first broken
610 - use 'make && make tests' to automatically find the first broken
605 revision::
611 revision::
606
612
607 hg bisect --reset
613 hg bisect --reset
608 hg bisect --bad 34
614 hg bisect --bad 34
609 hg bisect --good 12
615 hg bisect --good 12
610 hg bisect --command "make && make tests"
616 hg bisect --command "make && make tests"
611
617
612 - see all changesets whose states are already known in the current
618 - see all changesets whose states are already known in the current
613 bisection::
619 bisection::
614
620
615 hg log -r "bisect(pruned)"
621 hg log -r "bisect(pruned)"
616
622
617 - see the changeset currently being bisected (especially useful
623 - see the changeset currently being bisected (especially useful
618 if running with -U/--noupdate)::
624 if running with -U/--noupdate)::
619
625
620 hg log -r "bisect(current)"
626 hg log -r "bisect(current)"
621
627
622 - see all changesets that took part in the current bisection::
628 - see all changesets that took part in the current bisection::
623
629
624 hg log -r "bisect(range)"
630 hg log -r "bisect(range)"
625
631
626 - you can even get a nice graph::
632 - you can even get a nice graph::
627
633
628 hg log --graph -r "bisect(range)"
634 hg log --graph -r "bisect(range)"
629
635
630 See :hg:`help revsets` for more about the `bisect()` keyword.
636 See :hg:`help revsets` for more about the `bisect()` keyword.
631
637
632 Returns 0 on success.
638 Returns 0 on success.
633 """
639 """
634 def extendbisectrange(nodes, good):
640 def extendbisectrange(nodes, good):
635 # bisect is incomplete when it ends on a merge node and
641 # bisect is incomplete when it ends on a merge node and
636 # one of the parent was not checked.
642 # one of the parent was not checked.
637 parents = repo[nodes[0]].parents()
643 parents = repo[nodes[0]].parents()
638 if len(parents) > 1:
644 if len(parents) > 1:
639 side = good and state['bad'] or state['good']
645 side = good and state['bad'] or state['good']
640 num = len(set(i.node() for i in parents) & set(side))
646 num = len(set(i.node() for i in parents) & set(side))
641 if num == 1:
647 if num == 1:
642 return parents[0].ancestor(parents[1])
648 return parents[0].ancestor(parents[1])
643 return None
649 return None
644
650
645 def print_result(nodes, good):
651 def print_result(nodes, good):
646 displayer = cmdutil.show_changeset(ui, repo, {})
652 displayer = cmdutil.show_changeset(ui, repo, {})
647 if len(nodes) == 1:
653 if len(nodes) == 1:
648 # narrowed it down to a single revision
654 # narrowed it down to a single revision
649 if good:
655 if good:
650 ui.write(_("The first good revision is:\n"))
656 ui.write(_("The first good revision is:\n"))
651 else:
657 else:
652 ui.write(_("The first bad revision is:\n"))
658 ui.write(_("The first bad revision is:\n"))
653 displayer.show(repo[nodes[0]])
659 displayer.show(repo[nodes[0]])
654 extendnode = extendbisectrange(nodes, good)
660 extendnode = extendbisectrange(nodes, good)
655 if extendnode is not None:
661 if extendnode is not None:
656 ui.write(_('Not all ancestors of this changeset have been'
662 ui.write(_('Not all ancestors of this changeset have been'
657 ' checked.\nUse bisect --extend to continue the '
663 ' checked.\nUse bisect --extend to continue the '
658 'bisection from\nthe common ancestor, %s.\n')
664 'bisection from\nthe common ancestor, %s.\n')
659 % extendnode)
665 % extendnode)
660 else:
666 else:
661 # multiple possible revisions
667 # multiple possible revisions
662 if good:
668 if good:
663 ui.write(_("Due to skipped revisions, the first "
669 ui.write(_("Due to skipped revisions, the first "
664 "good revision could be any of:\n"))
670 "good revision could be any of:\n"))
665 else:
671 else:
666 ui.write(_("Due to skipped revisions, the first "
672 ui.write(_("Due to skipped revisions, the first "
667 "bad revision could be any of:\n"))
673 "bad revision could be any of:\n"))
668 for n in nodes:
674 for n in nodes:
669 displayer.show(repo[n])
675 displayer.show(repo[n])
670 displayer.close()
676 displayer.close()
671
677
672 def check_state(state, interactive=True):
678 def check_state(state, interactive=True):
673 if not state['good'] or not state['bad']:
679 if not state['good'] or not state['bad']:
674 if (good or bad or skip or reset) and interactive:
680 if (good or bad or skip or reset) and interactive:
675 return
681 return
676 if not state['good']:
682 if not state['good']:
677 raise util.Abort(_('cannot bisect (no known good revisions)'))
683 raise util.Abort(_('cannot bisect (no known good revisions)'))
678 else:
684 else:
679 raise util.Abort(_('cannot bisect (no known bad revisions)'))
685 raise util.Abort(_('cannot bisect (no known bad revisions)'))
680 return True
686 return True
681
687
682 # backward compatibility
688 # backward compatibility
683 if rev in "good bad reset init".split():
689 if rev in "good bad reset init".split():
684 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
690 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
685 cmd, rev, extra = rev, extra, None
691 cmd, rev, extra = rev, extra, None
686 if cmd == "good":
692 if cmd == "good":
687 good = True
693 good = True
688 elif cmd == "bad":
694 elif cmd == "bad":
689 bad = True
695 bad = True
690 else:
696 else:
691 reset = True
697 reset = True
692 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
698 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
693 raise util.Abort(_('incompatible arguments'))
699 raise util.Abort(_('incompatible arguments'))
694
700
695 cmdutil.checkunfinished(repo)
701 cmdutil.checkunfinished(repo)
696
702
697 if reset:
703 if reset:
698 p = repo.join("bisect.state")
704 p = repo.join("bisect.state")
699 if os.path.exists(p):
705 if os.path.exists(p):
700 os.unlink(p)
706 os.unlink(p)
701 return
707 return
702
708
703 state = hbisect.load_state(repo)
709 state = hbisect.load_state(repo)
704
710
705 if command:
711 if command:
706 changesets = 1
712 changesets = 1
707 if noupdate:
713 if noupdate:
708 try:
714 try:
709 node = state['current'][0]
715 node = state['current'][0]
710 except LookupError:
716 except LookupError:
711 raise util.Abort(_('current bisect revision is unknown - '
717 raise util.Abort(_('current bisect revision is unknown - '
712 'start a new bisect to fix'))
718 'start a new bisect to fix'))
713 else:
719 else:
714 node, p2 = repo.dirstate.parents()
720 node, p2 = repo.dirstate.parents()
715 if p2 != nullid:
721 if p2 != nullid:
716 raise util.Abort(_('current bisect revision is a merge'))
722 raise util.Abort(_('current bisect revision is a merge'))
717 try:
723 try:
718 while changesets:
724 while changesets:
719 # update state
725 # update state
720 state['current'] = [node]
726 state['current'] = [node]
721 hbisect.save_state(repo, state)
727 hbisect.save_state(repo, state)
722 status = util.system(command,
728 status = util.system(command,
723 environ={'HG_NODE': hex(node)},
729 environ={'HG_NODE': hex(node)},
724 out=ui.fout)
730 out=ui.fout)
725 if status == 125:
731 if status == 125:
726 transition = "skip"
732 transition = "skip"
727 elif status == 0:
733 elif status == 0:
728 transition = "good"
734 transition = "good"
729 # status < 0 means process was killed
735 # status < 0 means process was killed
730 elif status == 127:
736 elif status == 127:
731 raise util.Abort(_("failed to execute %s") % command)
737 raise util.Abort(_("failed to execute %s") % command)
732 elif status < 0:
738 elif status < 0:
733 raise util.Abort(_("%s killed") % command)
739 raise util.Abort(_("%s killed") % command)
734 else:
740 else:
735 transition = "bad"
741 transition = "bad"
736 ctx = scmutil.revsingle(repo, rev, node)
742 ctx = scmutil.revsingle(repo, rev, node)
737 rev = None # clear for future iterations
743 rev = None # clear for future iterations
738 state[transition].append(ctx.node())
744 state[transition].append(ctx.node())
739 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
745 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
740 check_state(state, interactive=False)
746 check_state(state, interactive=False)
741 # bisect
747 # bisect
742 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
748 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
743 # update to next check
749 # update to next check
744 node = nodes[0]
750 node = nodes[0]
745 if not noupdate:
751 if not noupdate:
746 cmdutil.bailifchanged(repo)
752 cmdutil.bailifchanged(repo)
747 hg.clean(repo, node, show_stats=False)
753 hg.clean(repo, node, show_stats=False)
748 finally:
754 finally:
749 state['current'] = [node]
755 state['current'] = [node]
750 hbisect.save_state(repo, state)
756 hbisect.save_state(repo, state)
751 print_result(nodes, bgood)
757 print_result(nodes, bgood)
752 return
758 return
753
759
754 # update state
760 # update state
755
761
756 if rev:
762 if rev:
757 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
763 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
758 else:
764 else:
759 nodes = [repo.lookup('.')]
765 nodes = [repo.lookup('.')]
760
766
761 if good or bad or skip:
767 if good or bad or skip:
762 if good:
768 if good:
763 state['good'] += nodes
769 state['good'] += nodes
764 elif bad:
770 elif bad:
765 state['bad'] += nodes
771 state['bad'] += nodes
766 elif skip:
772 elif skip:
767 state['skip'] += nodes
773 state['skip'] += nodes
768 hbisect.save_state(repo, state)
774 hbisect.save_state(repo, state)
769
775
770 if not check_state(state):
776 if not check_state(state):
771 return
777 return
772
778
773 # actually bisect
779 # actually bisect
774 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
780 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
775 if extend:
781 if extend:
776 if not changesets:
782 if not changesets:
777 extendnode = extendbisectrange(nodes, good)
783 extendnode = extendbisectrange(nodes, good)
778 if extendnode is not None:
784 if extendnode is not None:
779 ui.write(_("Extending search to changeset %d:%s\n")
785 ui.write(_("Extending search to changeset %d:%s\n")
780 % (extendnode.rev(), extendnode))
786 % (extendnode.rev(), extendnode))
781 state['current'] = [extendnode.node()]
787 state['current'] = [extendnode.node()]
782 hbisect.save_state(repo, state)
788 hbisect.save_state(repo, state)
783 if noupdate:
789 if noupdate:
784 return
790 return
785 cmdutil.bailifchanged(repo)
791 cmdutil.bailifchanged(repo)
786 return hg.clean(repo, extendnode.node())
792 return hg.clean(repo, extendnode.node())
787 raise util.Abort(_("nothing to extend"))
793 raise util.Abort(_("nothing to extend"))
788
794
789 if changesets == 0:
795 if changesets == 0:
790 print_result(nodes, good)
796 print_result(nodes, good)
791 else:
797 else:
792 assert len(nodes) == 1 # only a single node can be tested next
798 assert len(nodes) == 1 # only a single node can be tested next
793 node = nodes[0]
799 node = nodes[0]
794 # compute the approximate number of remaining tests
800 # compute the approximate number of remaining tests
795 tests, size = 0, 2
801 tests, size = 0, 2
796 while size <= changesets:
802 while size <= changesets:
797 tests, size = tests + 1, size * 2
803 tests, size = tests + 1, size * 2
798 rev = repo.changelog.rev(node)
804 rev = repo.changelog.rev(node)
799 ui.write(_("Testing changeset %d:%s "
805 ui.write(_("Testing changeset %d:%s "
800 "(%d changesets remaining, ~%d tests)\n")
806 "(%d changesets remaining, ~%d tests)\n")
801 % (rev, short(node), changesets, tests))
807 % (rev, short(node), changesets, tests))
802 state['current'] = [node]
808 state['current'] = [node]
803 hbisect.save_state(repo, state)
809 hbisect.save_state(repo, state)
804 if not noupdate:
810 if not noupdate:
805 cmdutil.bailifchanged(repo)
811 cmdutil.bailifchanged(repo)
806 return hg.clean(repo, node)
812 return hg.clean(repo, node)
807
813
808 @command('bookmarks|bookmark',
814 @command('bookmarks|bookmark',
809 [('f', 'force', False, _('force')),
815 [('f', 'force', False, _('force')),
810 ('r', 'rev', '', _('revision'), _('REV')),
816 ('r', 'rev', '', _('revision'), _('REV')),
811 ('d', 'delete', False, _('delete a given bookmark')),
817 ('d', 'delete', False, _('delete a given bookmark')),
812 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
818 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
813 ('i', 'inactive', False, _('mark a bookmark inactive'))],
819 ('i', 'inactive', False, _('mark a bookmark inactive'))],
814 _('hg bookmarks [OPTIONS]... [NAME]...'))
820 _('hg bookmarks [OPTIONS]... [NAME]...'))
815 def bookmark(ui, repo, *names, **opts):
821 def bookmark(ui, repo, *names, **opts):
816 '''create a new bookmark or list existing bookmarks
822 '''create a new bookmark or list existing bookmarks
817
823
818 Bookmarks are labels on changesets to help track lines of development.
824 Bookmarks are labels on changesets to help track lines of development.
819 Bookmarks are unversioned and can be moved, renamed and deleted.
825 Bookmarks are unversioned and can be moved, renamed and deleted.
820 Deleting or moving a bookmark has no effect on the associated changesets.
826 Deleting or moving a bookmark has no effect on the associated changesets.
821
827
822 Creating or updating to a bookmark causes it to be marked as 'active'.
828 Creating or updating to a bookmark causes it to be marked as 'active'.
823 The active bookmark is indicated with a '*'.
829 The active bookmark is indicated with a '*'.
824 When a commit is made, the active bookmark will advance to the new commit.
830 When a commit is made, the active bookmark will advance to the new commit.
825 A plain :hg:`update` will also advance an active bookmark, if possible.
831 A plain :hg:`update` will also advance an active bookmark, if possible.
826 Updating away from a bookmark will cause it to be deactivated.
832 Updating away from a bookmark will cause it to be deactivated.
827
833
828 Bookmarks can be pushed and pulled between repositories (see
834 Bookmarks can be pushed and pulled between repositories (see
829 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
835 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
830 diverged, a new 'divergent bookmark' of the form 'name@path' will
836 diverged, a new 'divergent bookmark' of the form 'name@path' will
831 be created. Using :hg:'merge' will resolve the divergence.
837 be created. Using :hg:'merge' will resolve the divergence.
832
838
833 A bookmark named '@' has the special property that :hg:`clone` will
839 A bookmark named '@' has the special property that :hg:`clone` will
834 check it out by default if it exists.
840 check it out by default if it exists.
835
841
836 .. container:: verbose
842 .. container:: verbose
837
843
838 Examples:
844 Examples:
839
845
840 - create an active bookmark for a new line of development::
846 - create an active bookmark for a new line of development::
841
847
842 hg book new-feature
848 hg book new-feature
843
849
844 - create an inactive bookmark as a place marker::
850 - create an inactive bookmark as a place marker::
845
851
846 hg book -i reviewed
852 hg book -i reviewed
847
853
848 - create an inactive bookmark on another changeset::
854 - create an inactive bookmark on another changeset::
849
855
850 hg book -r .^ tested
856 hg book -r .^ tested
851
857
852 - move the '@' bookmark from another branch::
858 - move the '@' bookmark from another branch::
853
859
854 hg book -f @
860 hg book -f @
855 '''
861 '''
856 force = opts.get('force')
862 force = opts.get('force')
857 rev = opts.get('rev')
863 rev = opts.get('rev')
858 delete = opts.get('delete')
864 delete = opts.get('delete')
859 rename = opts.get('rename')
865 rename = opts.get('rename')
860 inactive = opts.get('inactive')
866 inactive = opts.get('inactive')
861
867
862 def checkformat(mark):
868 def checkformat(mark):
863 mark = mark.strip()
869 mark = mark.strip()
864 if not mark:
870 if not mark:
865 raise util.Abort(_("bookmark names cannot consist entirely of "
871 raise util.Abort(_("bookmark names cannot consist entirely of "
866 "whitespace"))
872 "whitespace"))
867 scmutil.checknewlabel(repo, mark, 'bookmark')
873 scmutil.checknewlabel(repo, mark, 'bookmark')
868 return mark
874 return mark
869
875
870 def checkconflict(repo, mark, cur, force=False, target=None):
876 def checkconflict(repo, mark, cur, force=False, target=None):
871 if mark in marks and not force:
877 if mark in marks and not force:
872 if target:
878 if target:
873 if marks[mark] == target and target == cur:
879 if marks[mark] == target and target == cur:
874 # re-activating a bookmark
880 # re-activating a bookmark
875 return
881 return
876 anc = repo.changelog.ancestors([repo[target].rev()])
882 anc = repo.changelog.ancestors([repo[target].rev()])
877 bmctx = repo[marks[mark]]
883 bmctx = repo[marks[mark]]
878 divs = [repo[b].node() for b in marks
884 divs = [repo[b].node() for b in marks
879 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
885 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
880
886
881 # allow resolving a single divergent bookmark even if moving
887 # allow resolving a single divergent bookmark even if moving
882 # the bookmark across branches when a revision is specified
888 # the bookmark across branches when a revision is specified
883 # that contains a divergent bookmark
889 # that contains a divergent bookmark
884 if bmctx.rev() not in anc and target in divs:
890 if bmctx.rev() not in anc and target in divs:
885 bookmarks.deletedivergent(repo, [target], mark)
891 bookmarks.deletedivergent(repo, [target], mark)
886 return
892 return
887
893
888 deletefrom = [b for b in divs
894 deletefrom = [b for b in divs
889 if repo[b].rev() in anc or b == target]
895 if repo[b].rev() in anc or b == target]
890 bookmarks.deletedivergent(repo, deletefrom, mark)
896 bookmarks.deletedivergent(repo, deletefrom, mark)
891 if bookmarks.validdest(repo, bmctx, repo[target]):
897 if bookmarks.validdest(repo, bmctx, repo[target]):
892 ui.status(_("moving bookmark '%s' forward from %s\n") %
898 ui.status(_("moving bookmark '%s' forward from %s\n") %
893 (mark, short(bmctx.node())))
899 (mark, short(bmctx.node())))
894 return
900 return
895 raise util.Abort(_("bookmark '%s' already exists "
901 raise util.Abort(_("bookmark '%s' already exists "
896 "(use -f to force)") % mark)
902 "(use -f to force)") % mark)
897 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
903 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
898 and not force):
904 and not force):
899 raise util.Abort(
905 raise util.Abort(
900 _("a bookmark cannot have the name of an existing branch"))
906 _("a bookmark cannot have the name of an existing branch"))
901
907
902 if delete and rename:
908 if delete and rename:
903 raise util.Abort(_("--delete and --rename are incompatible"))
909 raise util.Abort(_("--delete and --rename are incompatible"))
904 if delete and rev:
910 if delete and rev:
905 raise util.Abort(_("--rev is incompatible with --delete"))
911 raise util.Abort(_("--rev is incompatible with --delete"))
906 if rename and rev:
912 if rename and rev:
907 raise util.Abort(_("--rev is incompatible with --rename"))
913 raise util.Abort(_("--rev is incompatible with --rename"))
908 if not names and (delete or rev):
914 if not names and (delete or rev):
909 raise util.Abort(_("bookmark name required"))
915 raise util.Abort(_("bookmark name required"))
910
916
911 if delete or rename or names or inactive:
917 if delete or rename or names or inactive:
912 wlock = repo.wlock()
918 wlock = repo.wlock()
913 try:
919 try:
914 cur = repo.changectx('.').node()
920 cur = repo.changectx('.').node()
915 marks = repo._bookmarks
921 marks = repo._bookmarks
916 if delete:
922 if delete:
917 for mark in names:
923 for mark in names:
918 if mark not in marks:
924 if mark not in marks:
919 raise util.Abort(_("bookmark '%s' does not exist") %
925 raise util.Abort(_("bookmark '%s' does not exist") %
920 mark)
926 mark)
921 if mark == repo._bookmarkcurrent:
927 if mark == repo._bookmarkcurrent:
922 bookmarks.unsetcurrent(repo)
928 bookmarks.unsetcurrent(repo)
923 del marks[mark]
929 del marks[mark]
924 marks.write()
930 marks.write()
925
931
926 elif rename:
932 elif rename:
927 if not names:
933 if not names:
928 raise util.Abort(_("new bookmark name required"))
934 raise util.Abort(_("new bookmark name required"))
929 elif len(names) > 1:
935 elif len(names) > 1:
930 raise util.Abort(_("only one new bookmark name allowed"))
936 raise util.Abort(_("only one new bookmark name allowed"))
931 mark = checkformat(names[0])
937 mark = checkformat(names[0])
932 if rename not in marks:
938 if rename not in marks:
933 raise util.Abort(_("bookmark '%s' does not exist") % rename)
939 raise util.Abort(_("bookmark '%s' does not exist") % rename)
934 checkconflict(repo, mark, cur, force)
940 checkconflict(repo, mark, cur, force)
935 marks[mark] = marks[rename]
941 marks[mark] = marks[rename]
936 if repo._bookmarkcurrent == rename and not inactive:
942 if repo._bookmarkcurrent == rename and not inactive:
937 bookmarks.setcurrent(repo, mark)
943 bookmarks.setcurrent(repo, mark)
938 del marks[rename]
944 del marks[rename]
939 marks.write()
945 marks.write()
940
946
941 elif names:
947 elif names:
942 newact = None
948 newact = None
943 for mark in names:
949 for mark in names:
944 mark = checkformat(mark)
950 mark = checkformat(mark)
945 if newact is None:
951 if newact is None:
946 newact = mark
952 newact = mark
947 if inactive and mark == repo._bookmarkcurrent:
953 if inactive and mark == repo._bookmarkcurrent:
948 bookmarks.unsetcurrent(repo)
954 bookmarks.unsetcurrent(repo)
949 return
955 return
950 tgt = cur
956 tgt = cur
951 if rev:
957 if rev:
952 tgt = scmutil.revsingle(repo, rev).node()
958 tgt = scmutil.revsingle(repo, rev).node()
953 checkconflict(repo, mark, cur, force, tgt)
959 checkconflict(repo, mark, cur, force, tgt)
954 marks[mark] = tgt
960 marks[mark] = tgt
955 if not inactive and cur == marks[newact] and not rev:
961 if not inactive and cur == marks[newact] and not rev:
956 bookmarks.setcurrent(repo, newact)
962 bookmarks.setcurrent(repo, newact)
957 elif cur != tgt and newact == repo._bookmarkcurrent:
963 elif cur != tgt and newact == repo._bookmarkcurrent:
958 bookmarks.unsetcurrent(repo)
964 bookmarks.unsetcurrent(repo)
959 marks.write()
965 marks.write()
960
966
961 elif inactive:
967 elif inactive:
962 if len(marks) == 0:
968 if len(marks) == 0:
963 ui.status(_("no bookmarks set\n"))
969 ui.status(_("no bookmarks set\n"))
964 elif not repo._bookmarkcurrent:
970 elif not repo._bookmarkcurrent:
965 ui.status(_("no active bookmark\n"))
971 ui.status(_("no active bookmark\n"))
966 else:
972 else:
967 bookmarks.unsetcurrent(repo)
973 bookmarks.unsetcurrent(repo)
968 finally:
974 finally:
969 wlock.release()
975 wlock.release()
970 else: # show bookmarks
976 else: # show bookmarks
971 hexfn = ui.debugflag and hex or short
977 hexfn = ui.debugflag and hex or short
972 marks = repo._bookmarks
978 marks = repo._bookmarks
973 if len(marks) == 0:
979 if len(marks) == 0:
974 ui.status(_("no bookmarks set\n"))
980 ui.status(_("no bookmarks set\n"))
975 else:
981 else:
976 for bmark, n in sorted(marks.iteritems()):
982 for bmark, n in sorted(marks.iteritems()):
977 current = repo._bookmarkcurrent
983 current = repo._bookmarkcurrent
978 if bmark == current:
984 if bmark == current:
979 prefix, label = '*', 'bookmarks.current'
985 prefix, label = '*', 'bookmarks.current'
980 else:
986 else:
981 prefix, label = ' ', ''
987 prefix, label = ' ', ''
982
988
983 if ui.quiet:
989 if ui.quiet:
984 ui.write("%s\n" % bmark, label=label)
990 ui.write("%s\n" % bmark, label=label)
985 else:
991 else:
986 pad = " " * (25 - encoding.colwidth(bmark))
992 pad = " " * (25 - encoding.colwidth(bmark))
987 ui.write(" %s %s%s %d:%s\n" % (
993 ui.write(" %s %s%s %d:%s\n" % (
988 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
994 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
989 label=label)
995 label=label)
990
996
991 @command('branch',
997 @command('branch',
992 [('f', 'force', None,
998 [('f', 'force', None,
993 _('set branch name even if it shadows an existing branch')),
999 _('set branch name even if it shadows an existing branch')),
994 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1000 ('C', 'clean', None, _('reset branch name to parent branch name'))],
995 _('[-fC] [NAME]'))
1001 _('[-fC] [NAME]'))
996 def branch(ui, repo, label=None, **opts):
1002 def branch(ui, repo, label=None, **opts):
997 """set or show the current branch name
1003 """set or show the current branch name
998
1004
999 .. note::
1005 .. note::
1000
1006
1001 Branch names are permanent and global. Use :hg:`bookmark` to create a
1007 Branch names are permanent and global. Use :hg:`bookmark` to create a
1002 light-weight bookmark instead. See :hg:`help glossary` for more
1008 light-weight bookmark instead. See :hg:`help glossary` for more
1003 information about named branches and bookmarks.
1009 information about named branches and bookmarks.
1004
1010
1005 With no argument, show the current branch name. With one argument,
1011 With no argument, show the current branch name. With one argument,
1006 set the working directory branch name (the branch will not exist
1012 set the working directory branch name (the branch will not exist
1007 in the repository until the next commit). Standard practice
1013 in the repository until the next commit). Standard practice
1008 recommends that primary development take place on the 'default'
1014 recommends that primary development take place on the 'default'
1009 branch.
1015 branch.
1010
1016
1011 Unless -f/--force is specified, branch will not let you set a
1017 Unless -f/--force is specified, branch will not let you set a
1012 branch name that already exists, even if it's inactive.
1018 branch name that already exists, even if it's inactive.
1013
1019
1014 Use -C/--clean to reset the working directory branch to that of
1020 Use -C/--clean to reset the working directory branch to that of
1015 the parent of the working directory, negating a previous branch
1021 the parent of the working directory, negating a previous branch
1016 change.
1022 change.
1017
1023
1018 Use the command :hg:`update` to switch to an existing branch. Use
1024 Use the command :hg:`update` to switch to an existing branch. Use
1019 :hg:`commit --close-branch` to mark this branch as closed.
1025 :hg:`commit --close-branch` to mark this branch as closed.
1020
1026
1021 Returns 0 on success.
1027 Returns 0 on success.
1022 """
1028 """
1023 if label:
1029 if label:
1024 label = label.strip()
1030 label = label.strip()
1025
1031
1026 if not opts.get('clean') and not label:
1032 if not opts.get('clean') and not label:
1027 ui.write("%s\n" % repo.dirstate.branch())
1033 ui.write("%s\n" % repo.dirstate.branch())
1028 return
1034 return
1029
1035
1030 wlock = repo.wlock()
1036 wlock = repo.wlock()
1031 try:
1037 try:
1032 if opts.get('clean'):
1038 if opts.get('clean'):
1033 label = repo[None].p1().branch()
1039 label = repo[None].p1().branch()
1034 repo.dirstate.setbranch(label)
1040 repo.dirstate.setbranch(label)
1035 ui.status(_('reset working directory to branch %s\n') % label)
1041 ui.status(_('reset working directory to branch %s\n') % label)
1036 elif label:
1042 elif label:
1037 if not opts.get('force') and label in repo.branchmap():
1043 if not opts.get('force') and label in repo.branchmap():
1038 if label not in [p.branch() for p in repo.parents()]:
1044 if label not in [p.branch() for p in repo.parents()]:
1039 raise util.Abort(_('a branch of the same name already'
1045 raise util.Abort(_('a branch of the same name already'
1040 ' exists'),
1046 ' exists'),
1041 # i18n: "it" refers to an existing branch
1047 # i18n: "it" refers to an existing branch
1042 hint=_("use 'hg update' to switch to it"))
1048 hint=_("use 'hg update' to switch to it"))
1043 scmutil.checknewlabel(repo, label, 'branch')
1049 scmutil.checknewlabel(repo, label, 'branch')
1044 repo.dirstate.setbranch(label)
1050 repo.dirstate.setbranch(label)
1045 ui.status(_('marked working directory as branch %s\n') % label)
1051 ui.status(_('marked working directory as branch %s\n') % label)
1046 ui.status(_('(branches are permanent and global, '
1052 ui.status(_('(branches are permanent and global, '
1047 'did you want a bookmark?)\n'))
1053 'did you want a bookmark?)\n'))
1048 finally:
1054 finally:
1049 wlock.release()
1055 wlock.release()
1050
1056
1051 @command('branches',
1057 @command('branches',
1052 [('a', 'active', False, _('show only branches that have unmerged heads')),
1058 [('a', 'active', False, _('show only branches that have unmerged heads')),
1053 ('c', 'closed', False, _('show normal and closed branches'))],
1059 ('c', 'closed', False, _('show normal and closed branches'))],
1054 _('[-ac]'))
1060 _('[-ac]'))
1055 def branches(ui, repo, active=False, closed=False):
1061 def branches(ui, repo, active=False, closed=False):
1056 """list repository named branches
1062 """list repository named branches
1057
1063
1058 List the repository's named branches, indicating which ones are
1064 List the repository's named branches, indicating which ones are
1059 inactive. If -c/--closed is specified, also list branches which have
1065 inactive. If -c/--closed is specified, also list branches which have
1060 been marked closed (see :hg:`commit --close-branch`).
1066 been marked closed (see :hg:`commit --close-branch`).
1061
1067
1062 If -a/--active is specified, only show active branches. A branch
1068 If -a/--active is specified, only show active branches. A branch
1063 is considered active if it contains repository heads.
1069 is considered active if it contains repository heads.
1064
1070
1065 Use the command :hg:`update` to switch to an existing branch.
1071 Use the command :hg:`update` to switch to an existing branch.
1066
1072
1067 Returns 0.
1073 Returns 0.
1068 """
1074 """
1069
1075
1070 hexfunc = ui.debugflag and hex or short
1076 hexfunc = ui.debugflag and hex or short
1071
1077
1072 allheads = set(repo.heads())
1078 allheads = set(repo.heads())
1073 branches = []
1079 branches = []
1074 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1080 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1075 isactive = not isclosed and bool(set(heads) & allheads)
1081 isactive = not isclosed and bool(set(heads) & allheads)
1076 branches.append((tag, repo[tip], isactive, not isclosed))
1082 branches.append((tag, repo[tip], isactive, not isclosed))
1077 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1083 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1078 reverse=True)
1084 reverse=True)
1079
1085
1080 for tag, ctx, isactive, isopen in branches:
1086 for tag, ctx, isactive, isopen in branches:
1081 if (not active) or isactive:
1087 if (not active) or isactive:
1082 if isactive:
1088 if isactive:
1083 label = 'branches.active'
1089 label = 'branches.active'
1084 notice = ''
1090 notice = ''
1085 elif not isopen:
1091 elif not isopen:
1086 if not closed:
1092 if not closed:
1087 continue
1093 continue
1088 label = 'branches.closed'
1094 label = 'branches.closed'
1089 notice = _(' (closed)')
1095 notice = _(' (closed)')
1090 else:
1096 else:
1091 label = 'branches.inactive'
1097 label = 'branches.inactive'
1092 notice = _(' (inactive)')
1098 notice = _(' (inactive)')
1093 if tag == repo.dirstate.branch():
1099 if tag == repo.dirstate.branch():
1094 label = 'branches.current'
1100 label = 'branches.current'
1095 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1101 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1096 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1102 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1097 'log.changeset changeset.%s' % ctx.phasestr())
1103 'log.changeset changeset.%s' % ctx.phasestr())
1098 labeledtag = ui.label(tag, label)
1104 labeledtag = ui.label(tag, label)
1099 if ui.quiet:
1105 if ui.quiet:
1100 ui.write("%s\n" % labeledtag)
1106 ui.write("%s\n" % labeledtag)
1101 else:
1107 else:
1102 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1108 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1103
1109
1104 @command('bundle',
1110 @command('bundle',
1105 [('f', 'force', None, _('run even when the destination is unrelated')),
1111 [('f', 'force', None, _('run even when the destination is unrelated')),
1106 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1112 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1107 _('REV')),
1113 _('REV')),
1108 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1114 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1109 _('BRANCH')),
1115 _('BRANCH')),
1110 ('', 'base', [],
1116 ('', 'base', [],
1111 _('a base changeset assumed to be available at the destination'),
1117 _('a base changeset assumed to be available at the destination'),
1112 _('REV')),
1118 _('REV')),
1113 ('a', 'all', None, _('bundle all changesets in the repository')),
1119 ('a', 'all', None, _('bundle all changesets in the repository')),
1114 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1120 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1115 ] + remoteopts,
1121 ] + remoteopts,
1116 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1122 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1117 def bundle(ui, repo, fname, dest=None, **opts):
1123 def bundle(ui, repo, fname, dest=None, **opts):
1118 """create a changegroup file
1124 """create a changegroup file
1119
1125
1120 Generate a compressed changegroup file collecting changesets not
1126 Generate a compressed changegroup file collecting changesets not
1121 known to be in another repository.
1127 known to be in another repository.
1122
1128
1123 If you omit the destination repository, then hg assumes the
1129 If you omit the destination repository, then hg assumes the
1124 destination will have all the nodes you specify with --base
1130 destination will have all the nodes you specify with --base
1125 parameters. To create a bundle containing all changesets, use
1131 parameters. To create a bundle containing all changesets, use
1126 -a/--all (or --base null).
1132 -a/--all (or --base null).
1127
1133
1128 You can change compression method with the -t/--type option.
1134 You can change compression method with the -t/--type option.
1129 The available compression methods are: none, bzip2, and
1135 The available compression methods are: none, bzip2, and
1130 gzip (by default, bundles are compressed using bzip2).
1136 gzip (by default, bundles are compressed using bzip2).
1131
1137
1132 The bundle file can then be transferred using conventional means
1138 The bundle file can then be transferred using conventional means
1133 and applied to another repository with the unbundle or pull
1139 and applied to another repository with the unbundle or pull
1134 command. This is useful when direct push and pull are not
1140 command. This is useful when direct push and pull are not
1135 available or when exporting an entire repository is undesirable.
1141 available or when exporting an entire repository is undesirable.
1136
1142
1137 Applying bundles preserves all changeset contents including
1143 Applying bundles preserves all changeset contents including
1138 permissions, copy/rename information, and revision history.
1144 permissions, copy/rename information, and revision history.
1139
1145
1140 Returns 0 on success, 1 if no changes found.
1146 Returns 0 on success, 1 if no changes found.
1141 """
1147 """
1142 revs = None
1148 revs = None
1143 if 'rev' in opts:
1149 if 'rev' in opts:
1144 revs = scmutil.revrange(repo, opts['rev'])
1150 revs = scmutil.revrange(repo, opts['rev'])
1145
1151
1146 bundletype = opts.get('type', 'bzip2').lower()
1152 bundletype = opts.get('type', 'bzip2').lower()
1147 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1153 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1148 bundletype = btypes.get(bundletype)
1154 bundletype = btypes.get(bundletype)
1149 if bundletype not in changegroup.bundletypes:
1155 if bundletype not in changegroup.bundletypes:
1150 raise util.Abort(_('unknown bundle type specified with --type'))
1156 raise util.Abort(_('unknown bundle type specified with --type'))
1151
1157
1152 if opts.get('all'):
1158 if opts.get('all'):
1153 base = ['null']
1159 base = ['null']
1154 else:
1160 else:
1155 base = scmutil.revrange(repo, opts.get('base'))
1161 base = scmutil.revrange(repo, opts.get('base'))
1156 # TODO: get desired bundlecaps from command line.
1162 # TODO: get desired bundlecaps from command line.
1157 bundlecaps = None
1163 bundlecaps = None
1158 if base:
1164 if base:
1159 if dest:
1165 if dest:
1160 raise util.Abort(_("--base is incompatible with specifying "
1166 raise util.Abort(_("--base is incompatible with specifying "
1161 "a destination"))
1167 "a destination"))
1162 common = [repo.lookup(rev) for rev in base]
1168 common = [repo.lookup(rev) for rev in base]
1163 heads = revs and map(repo.lookup, revs) or revs
1169 heads = revs and map(repo.lookup, revs) or revs
1164 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1170 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1165 common=common, bundlecaps=bundlecaps)
1171 common=common, bundlecaps=bundlecaps)
1166 outgoing = None
1172 outgoing = None
1167 else:
1173 else:
1168 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1174 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1169 dest, branches = hg.parseurl(dest, opts.get('branch'))
1175 dest, branches = hg.parseurl(dest, opts.get('branch'))
1170 other = hg.peer(repo, opts, dest)
1176 other = hg.peer(repo, opts, dest)
1171 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1177 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1172 heads = revs and map(repo.lookup, revs) or revs
1178 heads = revs and map(repo.lookup, revs) or revs
1173 outgoing = discovery.findcommonoutgoing(repo, other,
1179 outgoing = discovery.findcommonoutgoing(repo, other,
1174 onlyheads=heads,
1180 onlyheads=heads,
1175 force=opts.get('force'),
1181 force=opts.get('force'),
1176 portable=True)
1182 portable=True)
1177 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1183 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1178 bundlecaps)
1184 bundlecaps)
1179 if not cg:
1185 if not cg:
1180 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1186 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1181 return 1
1187 return 1
1182
1188
1183 changegroup.writebundle(cg, fname, bundletype)
1189 changegroup.writebundle(cg, fname, bundletype)
1184
1190
1185 @command('cat',
1191 @command('cat',
1186 [('o', 'output', '',
1192 [('o', 'output', '',
1187 _('print output to file with formatted name'), _('FORMAT')),
1193 _('print output to file with formatted name'), _('FORMAT')),
1188 ('r', 'rev', '', _('print the given revision'), _('REV')),
1194 ('r', 'rev', '', _('print the given revision'), _('REV')),
1189 ('', 'decode', None, _('apply any matching decode filter')),
1195 ('', 'decode', None, _('apply any matching decode filter')),
1190 ] + walkopts,
1196 ] + walkopts,
1191 _('[OPTION]... FILE...'),
1197 _('[OPTION]... FILE...'),
1192 inferrepo=True)
1198 inferrepo=True)
1193 def cat(ui, repo, file1, *pats, **opts):
1199 def cat(ui, repo, file1, *pats, **opts):
1194 """output the current or given revision of files
1200 """output the current or given revision of files
1195
1201
1196 Print the specified files as they were at the given revision. If
1202 Print the specified files as they were at the given revision. If
1197 no revision is given, the parent of the working directory is used.
1203 no revision is given, the parent of the working directory is used.
1198
1204
1199 Output may be to a file, in which case the name of the file is
1205 Output may be to a file, in which case the name of the file is
1200 given using a format string. The formatting rules as follows:
1206 given using a format string. The formatting rules as follows:
1201
1207
1202 :``%%``: literal "%" character
1208 :``%%``: literal "%" character
1203 :``%s``: basename of file being printed
1209 :``%s``: basename of file being printed
1204 :``%d``: dirname of file being printed, or '.' if in repository root
1210 :``%d``: dirname of file being printed, or '.' if in repository root
1205 :``%p``: root-relative path name of file being printed
1211 :``%p``: root-relative path name of file being printed
1206 :``%H``: changeset hash (40 hexadecimal digits)
1212 :``%H``: changeset hash (40 hexadecimal digits)
1207 :``%R``: changeset revision number
1213 :``%R``: changeset revision number
1208 :``%h``: short-form changeset hash (12 hexadecimal digits)
1214 :``%h``: short-form changeset hash (12 hexadecimal digits)
1209 :``%r``: zero-padded changeset revision number
1215 :``%r``: zero-padded changeset revision number
1210 :``%b``: basename of the exporting repository
1216 :``%b``: basename of the exporting repository
1211
1217
1212 Returns 0 on success.
1218 Returns 0 on success.
1213 """
1219 """
1214 ctx = scmutil.revsingle(repo, opts.get('rev'))
1220 ctx = scmutil.revsingle(repo, opts.get('rev'))
1215 m = scmutil.match(ctx, (file1,) + pats, opts)
1221 m = scmutil.match(ctx, (file1,) + pats, opts)
1216
1222
1217 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1223 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1218
1224
1219 @command('^clone',
1225 @command('^clone',
1220 [('U', 'noupdate', None,
1226 [('U', 'noupdate', None,
1221 _('the clone will include an empty working copy (only a repository)')),
1227 _('the clone will include an empty working copy (only a repository)')),
1222 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1228 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1223 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1229 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1224 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1230 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1225 ('', 'pull', None, _('use pull protocol to copy metadata')),
1231 ('', 'pull', None, _('use pull protocol to copy metadata')),
1226 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1232 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1227 ] + remoteopts,
1233 ] + remoteopts,
1228 _('[OPTION]... SOURCE [DEST]'),
1234 _('[OPTION]... SOURCE [DEST]'),
1229 norepo=True)
1235 norepo=True)
1230 def clone(ui, source, dest=None, **opts):
1236 def clone(ui, source, dest=None, **opts):
1231 """make a copy of an existing repository
1237 """make a copy of an existing repository
1232
1238
1233 Create a copy of an existing repository in a new directory.
1239 Create a copy of an existing repository in a new directory.
1234
1240
1235 If no destination directory name is specified, it defaults to the
1241 If no destination directory name is specified, it defaults to the
1236 basename of the source.
1242 basename of the source.
1237
1243
1238 The location of the source is added to the new repository's
1244 The location of the source is added to the new repository's
1239 ``.hg/hgrc`` file, as the default to be used for future pulls.
1245 ``.hg/hgrc`` file, as the default to be used for future pulls.
1240
1246
1241 Only local paths and ``ssh://`` URLs are supported as
1247 Only local paths and ``ssh://`` URLs are supported as
1242 destinations. For ``ssh://`` destinations, no working directory or
1248 destinations. For ``ssh://`` destinations, no working directory or
1243 ``.hg/hgrc`` will be created on the remote side.
1249 ``.hg/hgrc`` will be created on the remote side.
1244
1250
1245 To pull only a subset of changesets, specify one or more revisions
1251 To pull only a subset of changesets, specify one or more revisions
1246 identifiers with -r/--rev or branches with -b/--branch. The
1252 identifiers with -r/--rev or branches with -b/--branch. The
1247 resulting clone will contain only the specified changesets and
1253 resulting clone will contain only the specified changesets and
1248 their ancestors. These options (or 'clone src#rev dest') imply
1254 their ancestors. These options (or 'clone src#rev dest') imply
1249 --pull, even for local source repositories. Note that specifying a
1255 --pull, even for local source repositories. Note that specifying a
1250 tag will include the tagged changeset but not the changeset
1256 tag will include the tagged changeset but not the changeset
1251 containing the tag.
1257 containing the tag.
1252
1258
1253 If the source repository has a bookmark called '@' set, that
1259 If the source repository has a bookmark called '@' set, that
1254 revision will be checked out in the new repository by default.
1260 revision will be checked out in the new repository by default.
1255
1261
1256 To check out a particular version, use -u/--update, or
1262 To check out a particular version, use -u/--update, or
1257 -U/--noupdate to create a clone with no working directory.
1263 -U/--noupdate to create a clone with no working directory.
1258
1264
1259 .. container:: verbose
1265 .. container:: verbose
1260
1266
1261 For efficiency, hardlinks are used for cloning whenever the
1267 For efficiency, hardlinks are used for cloning whenever the
1262 source and destination are on the same filesystem (note this
1268 source and destination are on the same filesystem (note this
1263 applies only to the repository data, not to the working
1269 applies only to the repository data, not to the working
1264 directory). Some filesystems, such as AFS, implement hardlinking
1270 directory). Some filesystems, such as AFS, implement hardlinking
1265 incorrectly, but do not report errors. In these cases, use the
1271 incorrectly, but do not report errors. In these cases, use the
1266 --pull option to avoid hardlinking.
1272 --pull option to avoid hardlinking.
1267
1273
1268 In some cases, you can clone repositories and the working
1274 In some cases, you can clone repositories and the working
1269 directory using full hardlinks with ::
1275 directory using full hardlinks with ::
1270
1276
1271 $ cp -al REPO REPOCLONE
1277 $ cp -al REPO REPOCLONE
1272
1278
1273 This is the fastest way to clone, but it is not always safe. The
1279 This is the fastest way to clone, but it is not always safe. The
1274 operation is not atomic (making sure REPO is not modified during
1280 operation is not atomic (making sure REPO is not modified during
1275 the operation is up to you) and you have to make sure your
1281 the operation is up to you) and you have to make sure your
1276 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1282 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1277 so). Also, this is not compatible with certain extensions that
1283 so). Also, this is not compatible with certain extensions that
1278 place their metadata under the .hg directory, such as mq.
1284 place their metadata under the .hg directory, such as mq.
1279
1285
1280 Mercurial will update the working directory to the first applicable
1286 Mercurial will update the working directory to the first applicable
1281 revision from this list:
1287 revision from this list:
1282
1288
1283 a) null if -U or the source repository has no changesets
1289 a) null if -U or the source repository has no changesets
1284 b) if -u . and the source repository is local, the first parent of
1290 b) if -u . and the source repository is local, the first parent of
1285 the source repository's working directory
1291 the source repository's working directory
1286 c) the changeset specified with -u (if a branch name, this means the
1292 c) the changeset specified with -u (if a branch name, this means the
1287 latest head of that branch)
1293 latest head of that branch)
1288 d) the changeset specified with -r
1294 d) the changeset specified with -r
1289 e) the tipmost head specified with -b
1295 e) the tipmost head specified with -b
1290 f) the tipmost head specified with the url#branch source syntax
1296 f) the tipmost head specified with the url#branch source syntax
1291 g) the revision marked with the '@' bookmark, if present
1297 g) the revision marked with the '@' bookmark, if present
1292 h) the tipmost head of the default branch
1298 h) the tipmost head of the default branch
1293 i) tip
1299 i) tip
1294
1300
1295 Examples:
1301 Examples:
1296
1302
1297 - clone a remote repository to a new directory named hg/::
1303 - clone a remote repository to a new directory named hg/::
1298
1304
1299 hg clone http://selenic.com/hg
1305 hg clone http://selenic.com/hg
1300
1306
1301 - create a lightweight local clone::
1307 - create a lightweight local clone::
1302
1308
1303 hg clone project/ project-feature/
1309 hg clone project/ project-feature/
1304
1310
1305 - clone from an absolute path on an ssh server (note double-slash)::
1311 - clone from an absolute path on an ssh server (note double-slash)::
1306
1312
1307 hg clone ssh://user@server//home/projects/alpha/
1313 hg clone ssh://user@server//home/projects/alpha/
1308
1314
1309 - do a high-speed clone over a LAN while checking out a
1315 - do a high-speed clone over a LAN while checking out a
1310 specified version::
1316 specified version::
1311
1317
1312 hg clone --uncompressed http://server/repo -u 1.5
1318 hg clone --uncompressed http://server/repo -u 1.5
1313
1319
1314 - create a repository without changesets after a particular revision::
1320 - create a repository without changesets after a particular revision::
1315
1321
1316 hg clone -r 04e544 experimental/ good/
1322 hg clone -r 04e544 experimental/ good/
1317
1323
1318 - clone (and track) a particular named branch::
1324 - clone (and track) a particular named branch::
1319
1325
1320 hg clone http://selenic.com/hg#stable
1326 hg clone http://selenic.com/hg#stable
1321
1327
1322 See :hg:`help urls` for details on specifying URLs.
1328 See :hg:`help urls` for details on specifying URLs.
1323
1329
1324 Returns 0 on success.
1330 Returns 0 on success.
1325 """
1331 """
1326 if opts.get('noupdate') and opts.get('updaterev'):
1332 if opts.get('noupdate') and opts.get('updaterev'):
1327 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1333 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1328
1334
1329 r = hg.clone(ui, opts, source, dest,
1335 r = hg.clone(ui, opts, source, dest,
1330 pull=opts.get('pull'),
1336 pull=opts.get('pull'),
1331 stream=opts.get('uncompressed'),
1337 stream=opts.get('uncompressed'),
1332 rev=opts.get('rev'),
1338 rev=opts.get('rev'),
1333 update=opts.get('updaterev') or not opts.get('noupdate'),
1339 update=opts.get('updaterev') or not opts.get('noupdate'),
1334 branch=opts.get('branch'))
1340 branch=opts.get('branch'))
1335
1341
1336 return r is None
1342 return r is None
1337
1343
1338 @command('^commit|ci',
1344 @command('^commit|ci',
1339 [('A', 'addremove', None,
1345 [('A', 'addremove', None,
1340 _('mark new/missing files as added/removed before committing')),
1346 _('mark new/missing files as added/removed before committing')),
1341 ('', 'close-branch', None,
1347 ('', 'close-branch', None,
1342 _('mark a branch as closed, hiding it from the branch list')),
1348 _('mark a branch as closed, hiding it from the branch list')),
1343 ('', 'amend', None, _('amend the parent of the working dir')),
1349 ('', 'amend', None, _('amend the parent of the working dir')),
1344 ('s', 'secret', None, _('use the secret phase for committing')),
1350 ('s', 'secret', None, _('use the secret phase for committing')),
1345 ('e', 'edit', None, _('invoke editor on commit messages')),
1351 ('e', 'edit', None, _('invoke editor on commit messages')),
1346 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1352 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1347 _('[OPTION]... [FILE]...'),
1353 _('[OPTION]... [FILE]...'),
1348 inferrepo=True)
1354 inferrepo=True)
1349 def commit(ui, repo, *pats, **opts):
1355 def commit(ui, repo, *pats, **opts):
1350 """commit the specified files or all outstanding changes
1356 """commit the specified files or all outstanding changes
1351
1357
1352 Commit changes to the given files into the repository. Unlike a
1358 Commit changes to the given files into the repository. Unlike a
1353 centralized SCM, this operation is a local operation. See
1359 centralized SCM, this operation is a local operation. See
1354 :hg:`push` for a way to actively distribute your changes.
1360 :hg:`push` for a way to actively distribute your changes.
1355
1361
1356 If a list of files is omitted, all changes reported by :hg:`status`
1362 If a list of files is omitted, all changes reported by :hg:`status`
1357 will be committed.
1363 will be committed.
1358
1364
1359 If you are committing the result of a merge, do not provide any
1365 If you are committing the result of a merge, do not provide any
1360 filenames or -I/-X filters.
1366 filenames or -I/-X filters.
1361
1367
1362 If no commit message is specified, Mercurial starts your
1368 If no commit message is specified, Mercurial starts your
1363 configured editor where you can enter a message. In case your
1369 configured editor where you can enter a message. In case your
1364 commit fails, you will find a backup of your message in
1370 commit fails, you will find a backup of your message in
1365 ``.hg/last-message.txt``.
1371 ``.hg/last-message.txt``.
1366
1372
1367 The --amend flag can be used to amend the parent of the
1373 The --amend flag can be used to amend the parent of the
1368 working directory with a new commit that contains the changes
1374 working directory with a new commit that contains the changes
1369 in the parent in addition to those currently reported by :hg:`status`,
1375 in the parent in addition to those currently reported by :hg:`status`,
1370 if there are any. The old commit is stored in a backup bundle in
1376 if there are any. The old commit is stored in a backup bundle in
1371 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1377 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1372 on how to restore it).
1378 on how to restore it).
1373
1379
1374 Message, user and date are taken from the amended commit unless
1380 Message, user and date are taken from the amended commit unless
1375 specified. When a message isn't specified on the command line,
1381 specified. When a message isn't specified on the command line,
1376 the editor will open with the message of the amended commit.
1382 the editor will open with the message of the amended commit.
1377
1383
1378 It is not possible to amend public changesets (see :hg:`help phases`)
1384 It is not possible to amend public changesets (see :hg:`help phases`)
1379 or changesets that have children.
1385 or changesets that have children.
1380
1386
1381 See :hg:`help dates` for a list of formats valid for -d/--date.
1387 See :hg:`help dates` for a list of formats valid for -d/--date.
1382
1388
1383 Returns 0 on success, 1 if nothing changed.
1389 Returns 0 on success, 1 if nothing changed.
1384 """
1390 """
1385 if opts.get('subrepos'):
1391 if opts.get('subrepos'):
1386 if opts.get('amend'):
1392 if opts.get('amend'):
1387 raise util.Abort(_('cannot amend with --subrepos'))
1393 raise util.Abort(_('cannot amend with --subrepos'))
1388 # Let --subrepos on the command line override config setting.
1394 # Let --subrepos on the command line override config setting.
1389 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1395 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1390
1396
1391 cmdutil.checkunfinished(repo, commit=True)
1397 cmdutil.checkunfinished(repo, commit=True)
1392
1398
1393 branch = repo[None].branch()
1399 branch = repo[None].branch()
1394 bheads = repo.branchheads(branch)
1400 bheads = repo.branchheads(branch)
1395
1401
1396 extra = {}
1402 extra = {}
1397 if opts.get('close_branch'):
1403 if opts.get('close_branch'):
1398 extra['close'] = 1
1404 extra['close'] = 1
1399
1405
1400 if not bheads:
1406 if not bheads:
1401 raise util.Abort(_('can only close branch heads'))
1407 raise util.Abort(_('can only close branch heads'))
1402 elif opts.get('amend'):
1408 elif opts.get('amend'):
1403 if repo.parents()[0].p1().branch() != branch and \
1409 if repo.parents()[0].p1().branch() != branch and \
1404 repo.parents()[0].p2().branch() != branch:
1410 repo.parents()[0].p2().branch() != branch:
1405 raise util.Abort(_('can only close branch heads'))
1411 raise util.Abort(_('can only close branch heads'))
1406
1412
1407 if opts.get('amend'):
1413 if opts.get('amend'):
1408 if ui.configbool('ui', 'commitsubrepos'):
1414 if ui.configbool('ui', 'commitsubrepos'):
1409 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1415 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1410
1416
1411 old = repo['.']
1417 old = repo['.']
1412 if not old.mutable():
1418 if not old.mutable():
1413 raise util.Abort(_('cannot amend public changesets'))
1419 raise util.Abort(_('cannot amend public changesets'))
1414 if len(repo[None].parents()) > 1:
1420 if len(repo[None].parents()) > 1:
1415 raise util.Abort(_('cannot amend while merging'))
1421 raise util.Abort(_('cannot amend while merging'))
1416 if (not obsolete._enabled) and old.children():
1422 if (not obsolete._enabled) and old.children():
1417 raise util.Abort(_('cannot amend changeset with children'))
1423 raise util.Abort(_('cannot amend changeset with children'))
1418
1424
1419 # commitfunc is used only for temporary amend commit by cmdutil.amend
1425 # commitfunc is used only for temporary amend commit by cmdutil.amend
1420 def commitfunc(ui, repo, message, match, opts):
1426 def commitfunc(ui, repo, message, match, opts):
1421 return repo.commit(message,
1427 return repo.commit(message,
1422 opts.get('user') or old.user(),
1428 opts.get('user') or old.user(),
1423 opts.get('date') or old.date(),
1429 opts.get('date') or old.date(),
1424 match,
1430 match,
1425 extra=extra)
1431 extra=extra)
1426
1432
1427 current = repo._bookmarkcurrent
1433 current = repo._bookmarkcurrent
1428 marks = old.bookmarks()
1434 marks = old.bookmarks()
1429 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1435 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1430 if node == old.node():
1436 if node == old.node():
1431 ui.status(_("nothing changed\n"))
1437 ui.status(_("nothing changed\n"))
1432 return 1
1438 return 1
1433 elif marks:
1439 elif marks:
1434 ui.debug('moving bookmarks %r from %s to %s\n' %
1440 ui.debug('moving bookmarks %r from %s to %s\n' %
1435 (marks, old.hex(), hex(node)))
1441 (marks, old.hex(), hex(node)))
1436 newmarks = repo._bookmarks
1442 newmarks = repo._bookmarks
1437 for bm in marks:
1443 for bm in marks:
1438 newmarks[bm] = node
1444 newmarks[bm] = node
1439 if bm == current:
1445 if bm == current:
1440 bookmarks.setcurrent(repo, bm)
1446 bookmarks.setcurrent(repo, bm)
1441 newmarks.write()
1447 newmarks.write()
1442 else:
1448 else:
1443 def commitfunc(ui, repo, message, match, opts):
1449 def commitfunc(ui, repo, message, match, opts):
1444 backup = ui.backupconfig('phases', 'new-commit')
1450 backup = ui.backupconfig('phases', 'new-commit')
1445 baseui = repo.baseui
1451 baseui = repo.baseui
1446 basebackup = baseui.backupconfig('phases', 'new-commit')
1452 basebackup = baseui.backupconfig('phases', 'new-commit')
1447 try:
1453 try:
1448 if opts.get('secret'):
1454 if opts.get('secret'):
1449 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1455 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1450 # Propagate to subrepos
1456 # Propagate to subrepos
1451 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1457 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1452
1458
1453 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1459 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1454 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1460 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1455 return repo.commit(message, opts.get('user'), opts.get('date'),
1461 return repo.commit(message, opts.get('user'), opts.get('date'),
1456 match,
1462 match,
1457 editor=editor,
1463 editor=editor,
1458 extra=extra)
1464 extra=extra)
1459 finally:
1465 finally:
1460 ui.restoreconfig(backup)
1466 ui.restoreconfig(backup)
1461 repo.baseui.restoreconfig(basebackup)
1467 repo.baseui.restoreconfig(basebackup)
1462
1468
1463
1469
1464 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1470 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1465
1471
1466 if not node:
1472 if not node:
1467 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1473 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1468 if stat[3]:
1474 if stat[3]:
1469 ui.status(_("nothing changed (%d missing files, see "
1475 ui.status(_("nothing changed (%d missing files, see "
1470 "'hg status')\n") % len(stat[3]))
1476 "'hg status')\n") % len(stat[3]))
1471 else:
1477 else:
1472 ui.status(_("nothing changed\n"))
1478 ui.status(_("nothing changed\n"))
1473 return 1
1479 return 1
1474
1480
1475 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1481 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1476
1482
1477 @command('config|showconfig|debugconfig',
1483 @command('config|showconfig|debugconfig',
1478 [('u', 'untrusted', None, _('show untrusted configuration options')),
1484 [('u', 'untrusted', None, _('show untrusted configuration options')),
1479 ('e', 'edit', None, _('edit user config')),
1485 ('e', 'edit', None, _('edit user config')),
1480 ('l', 'local', None, _('edit repository config')),
1486 ('l', 'local', None, _('edit repository config')),
1481 ('g', 'global', None, _('edit global config'))],
1487 ('g', 'global', None, _('edit global config'))],
1482 _('[-u] [NAME]...'),
1488 _('[-u] [NAME]...'),
1483 optionalrepo=True)
1489 optionalrepo=True)
1484 def config(ui, repo, *values, **opts):
1490 def config(ui, repo, *values, **opts):
1485 """show combined config settings from all hgrc files
1491 """show combined config settings from all hgrc files
1486
1492
1487 With no arguments, print names and values of all config items.
1493 With no arguments, print names and values of all config items.
1488
1494
1489 With one argument of the form section.name, print just the value
1495 With one argument of the form section.name, print just the value
1490 of that config item.
1496 of that config item.
1491
1497
1492 With multiple arguments, print names and values of all config
1498 With multiple arguments, print names and values of all config
1493 items with matching section names.
1499 items with matching section names.
1494
1500
1495 With --edit, start an editor on the user-level config file. With
1501 With --edit, start an editor on the user-level config file. With
1496 --global, edit the system-wide config file. With --local, edit the
1502 --global, edit the system-wide config file. With --local, edit the
1497 repository-level config file.
1503 repository-level config file.
1498
1504
1499 With --debug, the source (filename and line number) is printed
1505 With --debug, the source (filename and line number) is printed
1500 for each config item.
1506 for each config item.
1501
1507
1502 See :hg:`help config` for more information about config files.
1508 See :hg:`help config` for more information about config files.
1503
1509
1504 Returns 0 on success, 1 if NAME does not exist.
1510 Returns 0 on success, 1 if NAME does not exist.
1505
1511
1506 """
1512 """
1507
1513
1508 if opts.get('edit') or opts.get('local') or opts.get('global'):
1514 if opts.get('edit') or opts.get('local') or opts.get('global'):
1509 if opts.get('local') and opts.get('global'):
1515 if opts.get('local') and opts.get('global'):
1510 raise util.Abort(_("can't use --local and --global together"))
1516 raise util.Abort(_("can't use --local and --global together"))
1511
1517
1512 if opts.get('local'):
1518 if opts.get('local'):
1513 if not repo:
1519 if not repo:
1514 raise util.Abort(_("can't use --local outside a repository"))
1520 raise util.Abort(_("can't use --local outside a repository"))
1515 paths = [repo.join('hgrc')]
1521 paths = [repo.join('hgrc')]
1516 elif opts.get('global'):
1522 elif opts.get('global'):
1517 paths = scmutil.systemrcpath()
1523 paths = scmutil.systemrcpath()
1518 else:
1524 else:
1519 paths = scmutil.userrcpath()
1525 paths = scmutil.userrcpath()
1520
1526
1521 for f in paths:
1527 for f in paths:
1522 if os.path.exists(f):
1528 if os.path.exists(f):
1523 break
1529 break
1524 else:
1530 else:
1525 from ui import samplehgrcs
1531 from ui import samplehgrcs
1526
1532
1527 if opts.get('global'):
1533 if opts.get('global'):
1528 samplehgrc = samplehgrcs['global']
1534 samplehgrc = samplehgrcs['global']
1529 elif opts.get('local'):
1535 elif opts.get('local'):
1530 samplehgrc = samplehgrcs['local']
1536 samplehgrc = samplehgrcs['local']
1531 else:
1537 else:
1532 samplehgrc = samplehgrcs['user']
1538 samplehgrc = samplehgrcs['user']
1533
1539
1534 f = paths[0]
1540 f = paths[0]
1535 fp = open(f, "w")
1541 fp = open(f, "w")
1536 fp.write(samplehgrc)
1542 fp.write(samplehgrc)
1537 fp.close()
1543 fp.close()
1538
1544
1539 editor = ui.geteditor()
1545 editor = ui.geteditor()
1540 util.system("%s \"%s\"" % (editor, f),
1546 util.system("%s \"%s\"" % (editor, f),
1541 onerr=util.Abort, errprefix=_("edit failed"),
1547 onerr=util.Abort, errprefix=_("edit failed"),
1542 out=ui.fout)
1548 out=ui.fout)
1543 return
1549 return
1544
1550
1545 for f in scmutil.rcpath():
1551 for f in scmutil.rcpath():
1546 ui.debug('read config from: %s\n' % f)
1552 ui.debug('read config from: %s\n' % f)
1547 untrusted = bool(opts.get('untrusted'))
1553 untrusted = bool(opts.get('untrusted'))
1548 if values:
1554 if values:
1549 sections = [v for v in values if '.' not in v]
1555 sections = [v for v in values if '.' not in v]
1550 items = [v for v in values if '.' in v]
1556 items = [v for v in values if '.' in v]
1551 if len(items) > 1 or items and sections:
1557 if len(items) > 1 or items and sections:
1552 raise util.Abort(_('only one config item permitted'))
1558 raise util.Abort(_('only one config item permitted'))
1553 matched = False
1559 matched = False
1554 for section, name, value in ui.walkconfig(untrusted=untrusted):
1560 for section, name, value in ui.walkconfig(untrusted=untrusted):
1555 value = str(value).replace('\n', '\\n')
1561 value = str(value).replace('\n', '\\n')
1556 sectname = section + '.' + name
1562 sectname = section + '.' + name
1557 if values:
1563 if values:
1558 for v in values:
1564 for v in values:
1559 if v == section:
1565 if v == section:
1560 ui.debug('%s: ' %
1566 ui.debug('%s: ' %
1561 ui.configsource(section, name, untrusted))
1567 ui.configsource(section, name, untrusted))
1562 ui.write('%s=%s\n' % (sectname, value))
1568 ui.write('%s=%s\n' % (sectname, value))
1563 matched = True
1569 matched = True
1564 elif v == sectname:
1570 elif v == sectname:
1565 ui.debug('%s: ' %
1571 ui.debug('%s: ' %
1566 ui.configsource(section, name, untrusted))
1572 ui.configsource(section, name, untrusted))
1567 ui.write(value, '\n')
1573 ui.write(value, '\n')
1568 matched = True
1574 matched = True
1569 else:
1575 else:
1570 ui.debug('%s: ' %
1576 ui.debug('%s: ' %
1571 ui.configsource(section, name, untrusted))
1577 ui.configsource(section, name, untrusted))
1572 ui.write('%s=%s\n' % (sectname, value))
1578 ui.write('%s=%s\n' % (sectname, value))
1573 matched = True
1579 matched = True
1574 if matched:
1580 if matched:
1575 return 0
1581 return 0
1576 return 1
1582 return 1
1577
1583
1578 @command('copy|cp',
1584 @command('copy|cp',
1579 [('A', 'after', None, _('record a copy that has already occurred')),
1585 [('A', 'after', None, _('record a copy that has already occurred')),
1580 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1586 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1581 ] + walkopts + dryrunopts,
1587 ] + walkopts + dryrunopts,
1582 _('[OPTION]... [SOURCE]... DEST'))
1588 _('[OPTION]... [SOURCE]... DEST'))
1583 def copy(ui, repo, *pats, **opts):
1589 def copy(ui, repo, *pats, **opts):
1584 """mark files as copied for the next commit
1590 """mark files as copied for the next commit
1585
1591
1586 Mark dest as having copies of source files. If dest is a
1592 Mark dest as having copies of source files. If dest is a
1587 directory, copies are put in that directory. If dest is a file,
1593 directory, copies are put in that directory. If dest is a file,
1588 the source must be a single file.
1594 the source must be a single file.
1589
1595
1590 By default, this command copies the contents of files as they
1596 By default, this command copies the contents of files as they
1591 exist in the working directory. If invoked with -A/--after, the
1597 exist in the working directory. If invoked with -A/--after, the
1592 operation is recorded, but no copying is performed.
1598 operation is recorded, but no copying is performed.
1593
1599
1594 This command takes effect with the next commit. To undo a copy
1600 This command takes effect with the next commit. To undo a copy
1595 before that, see :hg:`revert`.
1601 before that, see :hg:`revert`.
1596
1602
1597 Returns 0 on success, 1 if errors are encountered.
1603 Returns 0 on success, 1 if errors are encountered.
1598 """
1604 """
1599 wlock = repo.wlock(False)
1605 wlock = repo.wlock(False)
1600 try:
1606 try:
1601 return cmdutil.copy(ui, repo, pats, opts)
1607 return cmdutil.copy(ui, repo, pats, opts)
1602 finally:
1608 finally:
1603 wlock.release()
1609 wlock.release()
1604
1610
1605 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1611 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1606 def debugancestor(ui, repo, *args):
1612 def debugancestor(ui, repo, *args):
1607 """find the ancestor revision of two revisions in a given index"""
1613 """find the ancestor revision of two revisions in a given index"""
1608 if len(args) == 3:
1614 if len(args) == 3:
1609 index, rev1, rev2 = args
1615 index, rev1, rev2 = args
1610 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1616 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1611 lookup = r.lookup
1617 lookup = r.lookup
1612 elif len(args) == 2:
1618 elif len(args) == 2:
1613 if not repo:
1619 if not repo:
1614 raise util.Abort(_("there is no Mercurial repository here "
1620 raise util.Abort(_("there is no Mercurial repository here "
1615 "(.hg not found)"))
1621 "(.hg not found)"))
1616 rev1, rev2 = args
1622 rev1, rev2 = args
1617 r = repo.changelog
1623 r = repo.changelog
1618 lookup = repo.lookup
1624 lookup = repo.lookup
1619 else:
1625 else:
1620 raise util.Abort(_('either two or three arguments required'))
1626 raise util.Abort(_('either two or three arguments required'))
1621 a = r.ancestor(lookup(rev1), lookup(rev2))
1627 a = r.ancestor(lookup(rev1), lookup(rev2))
1622 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1628 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1623
1629
1624 @command('debugbuilddag',
1630 @command('debugbuilddag',
1625 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1631 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1626 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1632 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1627 ('n', 'new-file', None, _('add new file at each rev'))],
1633 ('n', 'new-file', None, _('add new file at each rev'))],
1628 _('[OPTION]... [TEXT]'))
1634 _('[OPTION]... [TEXT]'))
1629 def debugbuilddag(ui, repo, text=None,
1635 def debugbuilddag(ui, repo, text=None,
1630 mergeable_file=False,
1636 mergeable_file=False,
1631 overwritten_file=False,
1637 overwritten_file=False,
1632 new_file=False):
1638 new_file=False):
1633 """builds a repo with a given DAG from scratch in the current empty repo
1639 """builds a repo with a given DAG from scratch in the current empty repo
1634
1640
1635 The description of the DAG is read from stdin if not given on the
1641 The description of the DAG is read from stdin if not given on the
1636 command line.
1642 command line.
1637
1643
1638 Elements:
1644 Elements:
1639
1645
1640 - "+n" is a linear run of n nodes based on the current default parent
1646 - "+n" is a linear run of n nodes based on the current default parent
1641 - "." is a single node based on the current default parent
1647 - "." is a single node based on the current default parent
1642 - "$" resets the default parent to null (implied at the start);
1648 - "$" resets the default parent to null (implied at the start);
1643 otherwise the default parent is always the last node created
1649 otherwise the default parent is always the last node created
1644 - "<p" sets the default parent to the backref p
1650 - "<p" sets the default parent to the backref p
1645 - "*p" is a fork at parent p, which is a backref
1651 - "*p" is a fork at parent p, which is a backref
1646 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1652 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1647 - "/p2" is a merge of the preceding node and p2
1653 - "/p2" is a merge of the preceding node and p2
1648 - ":tag" defines a local tag for the preceding node
1654 - ":tag" defines a local tag for the preceding node
1649 - "@branch" sets the named branch for subsequent nodes
1655 - "@branch" sets the named branch for subsequent nodes
1650 - "#...\\n" is a comment up to the end of the line
1656 - "#...\\n" is a comment up to the end of the line
1651
1657
1652 Whitespace between the above elements is ignored.
1658 Whitespace between the above elements is ignored.
1653
1659
1654 A backref is either
1660 A backref is either
1655
1661
1656 - a number n, which references the node curr-n, where curr is the current
1662 - a number n, which references the node curr-n, where curr is the current
1657 node, or
1663 node, or
1658 - the name of a local tag you placed earlier using ":tag", or
1664 - the name of a local tag you placed earlier using ":tag", or
1659 - empty to denote the default parent.
1665 - empty to denote the default parent.
1660
1666
1661 All string valued-elements are either strictly alphanumeric, or must
1667 All string valued-elements are either strictly alphanumeric, or must
1662 be enclosed in double quotes ("..."), with "\\" as escape character.
1668 be enclosed in double quotes ("..."), with "\\" as escape character.
1663 """
1669 """
1664
1670
1665 if text is None:
1671 if text is None:
1666 ui.status(_("reading DAG from stdin\n"))
1672 ui.status(_("reading DAG from stdin\n"))
1667 text = ui.fin.read()
1673 text = ui.fin.read()
1668
1674
1669 cl = repo.changelog
1675 cl = repo.changelog
1670 if len(cl) > 0:
1676 if len(cl) > 0:
1671 raise util.Abort(_('repository is not empty'))
1677 raise util.Abort(_('repository is not empty'))
1672
1678
1673 # determine number of revs in DAG
1679 # determine number of revs in DAG
1674 total = 0
1680 total = 0
1675 for type, data in dagparser.parsedag(text):
1681 for type, data in dagparser.parsedag(text):
1676 if type == 'n':
1682 if type == 'n':
1677 total += 1
1683 total += 1
1678
1684
1679 if mergeable_file:
1685 if mergeable_file:
1680 linesperrev = 2
1686 linesperrev = 2
1681 # make a file with k lines per rev
1687 # make a file with k lines per rev
1682 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1688 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1683 initialmergedlines.append("")
1689 initialmergedlines.append("")
1684
1690
1685 tags = []
1691 tags = []
1686
1692
1687 lock = tr = None
1693 lock = tr = None
1688 try:
1694 try:
1689 lock = repo.lock()
1695 lock = repo.lock()
1690 tr = repo.transaction("builddag")
1696 tr = repo.transaction("builddag")
1691
1697
1692 at = -1
1698 at = -1
1693 atbranch = 'default'
1699 atbranch = 'default'
1694 nodeids = []
1700 nodeids = []
1695 id = 0
1701 id = 0
1696 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1702 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1697 for type, data in dagparser.parsedag(text):
1703 for type, data in dagparser.parsedag(text):
1698 if type == 'n':
1704 if type == 'n':
1699 ui.note(('node %s\n' % str(data)))
1705 ui.note(('node %s\n' % str(data)))
1700 id, ps = data
1706 id, ps = data
1701
1707
1702 files = []
1708 files = []
1703 fctxs = {}
1709 fctxs = {}
1704
1710
1705 p2 = None
1711 p2 = None
1706 if mergeable_file:
1712 if mergeable_file:
1707 fn = "mf"
1713 fn = "mf"
1708 p1 = repo[ps[0]]
1714 p1 = repo[ps[0]]
1709 if len(ps) > 1:
1715 if len(ps) > 1:
1710 p2 = repo[ps[1]]
1716 p2 = repo[ps[1]]
1711 pa = p1.ancestor(p2)
1717 pa = p1.ancestor(p2)
1712 base, local, other = [x[fn].data() for x in (pa, p1,
1718 base, local, other = [x[fn].data() for x in (pa, p1,
1713 p2)]
1719 p2)]
1714 m3 = simplemerge.Merge3Text(base, local, other)
1720 m3 = simplemerge.Merge3Text(base, local, other)
1715 ml = [l.strip() for l in m3.merge_lines()]
1721 ml = [l.strip() for l in m3.merge_lines()]
1716 ml.append("")
1722 ml.append("")
1717 elif at > 0:
1723 elif at > 0:
1718 ml = p1[fn].data().split("\n")
1724 ml = p1[fn].data().split("\n")
1719 else:
1725 else:
1720 ml = initialmergedlines
1726 ml = initialmergedlines
1721 ml[id * linesperrev] += " r%i" % id
1727 ml[id * linesperrev] += " r%i" % id
1722 mergedtext = "\n".join(ml)
1728 mergedtext = "\n".join(ml)
1723 files.append(fn)
1729 files.append(fn)
1724 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1730 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1725
1731
1726 if overwritten_file:
1732 if overwritten_file:
1727 fn = "of"
1733 fn = "of"
1728 files.append(fn)
1734 files.append(fn)
1729 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1735 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1730
1736
1731 if new_file:
1737 if new_file:
1732 fn = "nf%i" % id
1738 fn = "nf%i" % id
1733 files.append(fn)
1739 files.append(fn)
1734 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1740 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1735 if len(ps) > 1:
1741 if len(ps) > 1:
1736 if not p2:
1742 if not p2:
1737 p2 = repo[ps[1]]
1743 p2 = repo[ps[1]]
1738 for fn in p2:
1744 for fn in p2:
1739 if fn.startswith("nf"):
1745 if fn.startswith("nf"):
1740 files.append(fn)
1746 files.append(fn)
1741 fctxs[fn] = p2[fn]
1747 fctxs[fn] = p2[fn]
1742
1748
1743 def fctxfn(repo, cx, path):
1749 def fctxfn(repo, cx, path):
1744 return fctxs.get(path)
1750 return fctxs.get(path)
1745
1751
1746 if len(ps) == 0 or ps[0] < 0:
1752 if len(ps) == 0 or ps[0] < 0:
1747 pars = [None, None]
1753 pars = [None, None]
1748 elif len(ps) == 1:
1754 elif len(ps) == 1:
1749 pars = [nodeids[ps[0]], None]
1755 pars = [nodeids[ps[0]], None]
1750 else:
1756 else:
1751 pars = [nodeids[p] for p in ps]
1757 pars = [nodeids[p] for p in ps]
1752 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1758 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1753 date=(id, 0),
1759 date=(id, 0),
1754 user="debugbuilddag",
1760 user="debugbuilddag",
1755 extra={'branch': atbranch})
1761 extra={'branch': atbranch})
1756 nodeid = repo.commitctx(cx)
1762 nodeid = repo.commitctx(cx)
1757 nodeids.append(nodeid)
1763 nodeids.append(nodeid)
1758 at = id
1764 at = id
1759 elif type == 'l':
1765 elif type == 'l':
1760 id, name = data
1766 id, name = data
1761 ui.note(('tag %s\n' % name))
1767 ui.note(('tag %s\n' % name))
1762 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1768 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1763 elif type == 'a':
1769 elif type == 'a':
1764 ui.note(('branch %s\n' % data))
1770 ui.note(('branch %s\n' % data))
1765 atbranch = data
1771 atbranch = data
1766 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1772 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1767 tr.close()
1773 tr.close()
1768
1774
1769 if tags:
1775 if tags:
1770 repo.opener.write("localtags", "".join(tags))
1776 repo.opener.write("localtags", "".join(tags))
1771 finally:
1777 finally:
1772 ui.progress(_('building'), None)
1778 ui.progress(_('building'), None)
1773 release(tr, lock)
1779 release(tr, lock)
1774
1780
1775 @command('debugbundle',
1781 @command('debugbundle',
1776 [('a', 'all', None, _('show all details'))],
1782 [('a', 'all', None, _('show all details'))],
1777 _('FILE'),
1783 _('FILE'),
1778 norepo=True)
1784 norepo=True)
1779 def debugbundle(ui, bundlepath, all=None, **opts):
1785 def debugbundle(ui, bundlepath, all=None, **opts):
1780 """lists the contents of a bundle"""
1786 """lists the contents of a bundle"""
1781 f = hg.openpath(ui, bundlepath)
1787 f = hg.openpath(ui, bundlepath)
1782 try:
1788 try:
1783 gen = exchange.readbundle(ui, f, bundlepath)
1789 gen = exchange.readbundle(ui, f, bundlepath)
1784 if all:
1790 if all:
1785 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1791 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1786
1792
1787 def showchunks(named):
1793 def showchunks(named):
1788 ui.write("\n%s\n" % named)
1794 ui.write("\n%s\n" % named)
1789 chain = None
1795 chain = None
1790 while True:
1796 while True:
1791 chunkdata = gen.deltachunk(chain)
1797 chunkdata = gen.deltachunk(chain)
1792 if not chunkdata:
1798 if not chunkdata:
1793 break
1799 break
1794 node = chunkdata['node']
1800 node = chunkdata['node']
1795 p1 = chunkdata['p1']
1801 p1 = chunkdata['p1']
1796 p2 = chunkdata['p2']
1802 p2 = chunkdata['p2']
1797 cs = chunkdata['cs']
1803 cs = chunkdata['cs']
1798 deltabase = chunkdata['deltabase']
1804 deltabase = chunkdata['deltabase']
1799 delta = chunkdata['delta']
1805 delta = chunkdata['delta']
1800 ui.write("%s %s %s %s %s %s\n" %
1806 ui.write("%s %s %s %s %s %s\n" %
1801 (hex(node), hex(p1), hex(p2),
1807 (hex(node), hex(p1), hex(p2),
1802 hex(cs), hex(deltabase), len(delta)))
1808 hex(cs), hex(deltabase), len(delta)))
1803 chain = node
1809 chain = node
1804
1810
1805 chunkdata = gen.changelogheader()
1811 chunkdata = gen.changelogheader()
1806 showchunks("changelog")
1812 showchunks("changelog")
1807 chunkdata = gen.manifestheader()
1813 chunkdata = gen.manifestheader()
1808 showchunks("manifest")
1814 showchunks("manifest")
1809 while True:
1815 while True:
1810 chunkdata = gen.filelogheader()
1816 chunkdata = gen.filelogheader()
1811 if not chunkdata:
1817 if not chunkdata:
1812 break
1818 break
1813 fname = chunkdata['filename']
1819 fname = chunkdata['filename']
1814 showchunks(fname)
1820 showchunks(fname)
1815 else:
1821 else:
1816 chunkdata = gen.changelogheader()
1822 chunkdata = gen.changelogheader()
1817 chain = None
1823 chain = None
1818 while True:
1824 while True:
1819 chunkdata = gen.deltachunk(chain)
1825 chunkdata = gen.deltachunk(chain)
1820 if not chunkdata:
1826 if not chunkdata:
1821 break
1827 break
1822 node = chunkdata['node']
1828 node = chunkdata['node']
1823 ui.write("%s\n" % hex(node))
1829 ui.write("%s\n" % hex(node))
1824 chain = node
1830 chain = node
1825 finally:
1831 finally:
1826 f.close()
1832 f.close()
1827
1833
1828 @command('debugcheckstate', [], '')
1834 @command('debugcheckstate', [], '')
1829 def debugcheckstate(ui, repo):
1835 def debugcheckstate(ui, repo):
1830 """validate the correctness of the current dirstate"""
1836 """validate the correctness of the current dirstate"""
1831 parent1, parent2 = repo.dirstate.parents()
1837 parent1, parent2 = repo.dirstate.parents()
1832 m1 = repo[parent1].manifest()
1838 m1 = repo[parent1].manifest()
1833 m2 = repo[parent2].manifest()
1839 m2 = repo[parent2].manifest()
1834 errors = 0
1840 errors = 0
1835 for f in repo.dirstate:
1841 for f in repo.dirstate:
1836 state = repo.dirstate[f]
1842 state = repo.dirstate[f]
1837 if state in "nr" and f not in m1:
1843 if state in "nr" and f not in m1:
1838 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1844 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1839 errors += 1
1845 errors += 1
1840 if state in "a" and f in m1:
1846 if state in "a" and f in m1:
1841 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1847 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1842 errors += 1
1848 errors += 1
1843 if state in "m" and f not in m1 and f not in m2:
1849 if state in "m" and f not in m1 and f not in m2:
1844 ui.warn(_("%s in state %s, but not in either manifest\n") %
1850 ui.warn(_("%s in state %s, but not in either manifest\n") %
1845 (f, state))
1851 (f, state))
1846 errors += 1
1852 errors += 1
1847 for f in m1:
1853 for f in m1:
1848 state = repo.dirstate[f]
1854 state = repo.dirstate[f]
1849 if state not in "nrm":
1855 if state not in "nrm":
1850 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1856 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1851 errors += 1
1857 errors += 1
1852 if errors:
1858 if errors:
1853 error = _(".hg/dirstate inconsistent with current parent's manifest")
1859 error = _(".hg/dirstate inconsistent with current parent's manifest")
1854 raise util.Abort(error)
1860 raise util.Abort(error)
1855
1861
1856 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1862 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1857 def debugcommands(ui, cmd='', *args):
1863 def debugcommands(ui, cmd='', *args):
1858 """list all available commands and options"""
1864 """list all available commands and options"""
1859 for cmd, vals in sorted(table.iteritems()):
1865 for cmd, vals in sorted(table.iteritems()):
1860 cmd = cmd.split('|')[0].strip('^')
1866 cmd = cmd.split('|')[0].strip('^')
1861 opts = ', '.join([i[1] for i in vals[1]])
1867 opts = ', '.join([i[1] for i in vals[1]])
1862 ui.write('%s: %s\n' % (cmd, opts))
1868 ui.write('%s: %s\n' % (cmd, opts))
1863
1869
1864 @command('debugcomplete',
1870 @command('debugcomplete',
1865 [('o', 'options', None, _('show the command options'))],
1871 [('o', 'options', None, _('show the command options'))],
1866 _('[-o] CMD'),
1872 _('[-o] CMD'),
1867 norepo=True)
1873 norepo=True)
1868 def debugcomplete(ui, cmd='', **opts):
1874 def debugcomplete(ui, cmd='', **opts):
1869 """returns the completion list associated with the given command"""
1875 """returns the completion list associated with the given command"""
1870
1876
1871 if opts.get('options'):
1877 if opts.get('options'):
1872 options = []
1878 options = []
1873 otables = [globalopts]
1879 otables = [globalopts]
1874 if cmd:
1880 if cmd:
1875 aliases, entry = cmdutil.findcmd(cmd, table, False)
1881 aliases, entry = cmdutil.findcmd(cmd, table, False)
1876 otables.append(entry[1])
1882 otables.append(entry[1])
1877 for t in otables:
1883 for t in otables:
1878 for o in t:
1884 for o in t:
1879 if "(DEPRECATED)" in o[3]:
1885 if "(DEPRECATED)" in o[3]:
1880 continue
1886 continue
1881 if o[0]:
1887 if o[0]:
1882 options.append('-%s' % o[0])
1888 options.append('-%s' % o[0])
1883 options.append('--%s' % o[1])
1889 options.append('--%s' % o[1])
1884 ui.write("%s\n" % "\n".join(options))
1890 ui.write("%s\n" % "\n".join(options))
1885 return
1891 return
1886
1892
1887 cmdlist = cmdutil.findpossible(cmd, table)
1893 cmdlist = cmdutil.findpossible(cmd, table)
1888 if ui.verbose:
1894 if ui.verbose:
1889 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1895 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1890 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1896 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1891
1897
1892 @command('debugdag',
1898 @command('debugdag',
1893 [('t', 'tags', None, _('use tags as labels')),
1899 [('t', 'tags', None, _('use tags as labels')),
1894 ('b', 'branches', None, _('annotate with branch names')),
1900 ('b', 'branches', None, _('annotate with branch names')),
1895 ('', 'dots', None, _('use dots for runs')),
1901 ('', 'dots', None, _('use dots for runs')),
1896 ('s', 'spaces', None, _('separate elements by spaces'))],
1902 ('s', 'spaces', None, _('separate elements by spaces'))],
1897 _('[OPTION]... [FILE [REV]...]'),
1903 _('[OPTION]... [FILE [REV]...]'),
1898 optionalrepo=True)
1904 optionalrepo=True)
1899 def debugdag(ui, repo, file_=None, *revs, **opts):
1905 def debugdag(ui, repo, file_=None, *revs, **opts):
1900 """format the changelog or an index DAG as a concise textual description
1906 """format the changelog or an index DAG as a concise textual description
1901
1907
1902 If you pass a revlog index, the revlog's DAG is emitted. If you list
1908 If you pass a revlog index, the revlog's DAG is emitted. If you list
1903 revision numbers, they get labeled in the output as rN.
1909 revision numbers, they get labeled in the output as rN.
1904
1910
1905 Otherwise, the changelog DAG of the current repo is emitted.
1911 Otherwise, the changelog DAG of the current repo is emitted.
1906 """
1912 """
1907 spaces = opts.get('spaces')
1913 spaces = opts.get('spaces')
1908 dots = opts.get('dots')
1914 dots = opts.get('dots')
1909 if file_:
1915 if file_:
1910 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1916 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1911 revs = set((int(r) for r in revs))
1917 revs = set((int(r) for r in revs))
1912 def events():
1918 def events():
1913 for r in rlog:
1919 for r in rlog:
1914 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1920 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1915 if p != -1))
1921 if p != -1))
1916 if r in revs:
1922 if r in revs:
1917 yield 'l', (r, "r%i" % r)
1923 yield 'l', (r, "r%i" % r)
1918 elif repo:
1924 elif repo:
1919 cl = repo.changelog
1925 cl = repo.changelog
1920 tags = opts.get('tags')
1926 tags = opts.get('tags')
1921 branches = opts.get('branches')
1927 branches = opts.get('branches')
1922 if tags:
1928 if tags:
1923 labels = {}
1929 labels = {}
1924 for l, n in repo.tags().items():
1930 for l, n in repo.tags().items():
1925 labels.setdefault(cl.rev(n), []).append(l)
1931 labels.setdefault(cl.rev(n), []).append(l)
1926 def events():
1932 def events():
1927 b = "default"
1933 b = "default"
1928 for r in cl:
1934 for r in cl:
1929 if branches:
1935 if branches:
1930 newb = cl.read(cl.node(r))[5]['branch']
1936 newb = cl.read(cl.node(r))[5]['branch']
1931 if newb != b:
1937 if newb != b:
1932 yield 'a', newb
1938 yield 'a', newb
1933 b = newb
1939 b = newb
1934 yield 'n', (r, list(p for p in cl.parentrevs(r)
1940 yield 'n', (r, list(p for p in cl.parentrevs(r)
1935 if p != -1))
1941 if p != -1))
1936 if tags:
1942 if tags:
1937 ls = labels.get(r)
1943 ls = labels.get(r)
1938 if ls:
1944 if ls:
1939 for l in ls:
1945 for l in ls:
1940 yield 'l', (r, l)
1946 yield 'l', (r, l)
1941 else:
1947 else:
1942 raise util.Abort(_('need repo for changelog dag'))
1948 raise util.Abort(_('need repo for changelog dag'))
1943
1949
1944 for line in dagparser.dagtextlines(events(),
1950 for line in dagparser.dagtextlines(events(),
1945 addspaces=spaces,
1951 addspaces=spaces,
1946 wraplabels=True,
1952 wraplabels=True,
1947 wrapannotations=True,
1953 wrapannotations=True,
1948 wrapnonlinear=dots,
1954 wrapnonlinear=dots,
1949 usedots=dots,
1955 usedots=dots,
1950 maxlinewidth=70):
1956 maxlinewidth=70):
1951 ui.write(line)
1957 ui.write(line)
1952 ui.write("\n")
1958 ui.write("\n")
1953
1959
1954 @command('debugdata',
1960 @command('debugdata',
1955 [('c', 'changelog', False, _('open changelog')),
1961 [('c', 'changelog', False, _('open changelog')),
1956 ('m', 'manifest', False, _('open manifest'))],
1962 ('m', 'manifest', False, _('open manifest'))],
1957 _('-c|-m|FILE REV'))
1963 _('-c|-m|FILE REV'))
1958 def debugdata(ui, repo, file_, rev=None, **opts):
1964 def debugdata(ui, repo, file_, rev=None, **opts):
1959 """dump the contents of a data file revision"""
1965 """dump the contents of a data file revision"""
1960 if opts.get('changelog') or opts.get('manifest'):
1966 if opts.get('changelog') or opts.get('manifest'):
1961 file_, rev = None, file_
1967 file_, rev = None, file_
1962 elif rev is None:
1968 elif rev is None:
1963 raise error.CommandError('debugdata', _('invalid arguments'))
1969 raise error.CommandError('debugdata', _('invalid arguments'))
1964 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1970 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1965 try:
1971 try:
1966 ui.write(r.revision(r.lookup(rev)))
1972 ui.write(r.revision(r.lookup(rev)))
1967 except KeyError:
1973 except KeyError:
1968 raise util.Abort(_('invalid revision identifier %s') % rev)
1974 raise util.Abort(_('invalid revision identifier %s') % rev)
1969
1975
1970 @command('debugdate',
1976 @command('debugdate',
1971 [('e', 'extended', None, _('try extended date formats'))],
1977 [('e', 'extended', None, _('try extended date formats'))],
1972 _('[-e] DATE [RANGE]'),
1978 _('[-e] DATE [RANGE]'),
1973 norepo=True, optionalrepo=True)
1979 norepo=True, optionalrepo=True)
1974 def debugdate(ui, date, range=None, **opts):
1980 def debugdate(ui, date, range=None, **opts):
1975 """parse and display a date"""
1981 """parse and display a date"""
1976 if opts["extended"]:
1982 if opts["extended"]:
1977 d = util.parsedate(date, util.extendeddateformats)
1983 d = util.parsedate(date, util.extendeddateformats)
1978 else:
1984 else:
1979 d = util.parsedate(date)
1985 d = util.parsedate(date)
1980 ui.write(("internal: %s %s\n") % d)
1986 ui.write(("internal: %s %s\n") % d)
1981 ui.write(("standard: %s\n") % util.datestr(d))
1987 ui.write(("standard: %s\n") % util.datestr(d))
1982 if range:
1988 if range:
1983 m = util.matchdate(range)
1989 m = util.matchdate(range)
1984 ui.write(("match: %s\n") % m(d[0]))
1990 ui.write(("match: %s\n") % m(d[0]))
1985
1991
1986 @command('debugdiscovery',
1992 @command('debugdiscovery',
1987 [('', 'old', None, _('use old-style discovery')),
1993 [('', 'old', None, _('use old-style discovery')),
1988 ('', 'nonheads', None,
1994 ('', 'nonheads', None,
1989 _('use old-style discovery with non-heads included')),
1995 _('use old-style discovery with non-heads included')),
1990 ] + remoteopts,
1996 ] + remoteopts,
1991 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1997 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1992 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1998 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1993 """runs the changeset discovery protocol in isolation"""
1999 """runs the changeset discovery protocol in isolation"""
1994 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2000 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1995 opts.get('branch'))
2001 opts.get('branch'))
1996 remote = hg.peer(repo, opts, remoteurl)
2002 remote = hg.peer(repo, opts, remoteurl)
1997 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2003 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1998
2004
1999 # make sure tests are repeatable
2005 # make sure tests are repeatable
2000 random.seed(12323)
2006 random.seed(12323)
2001
2007
2002 def doit(localheads, remoteheads, remote=remote):
2008 def doit(localheads, remoteheads, remote=remote):
2003 if opts.get('old'):
2009 if opts.get('old'):
2004 if localheads:
2010 if localheads:
2005 raise util.Abort('cannot use localheads with old style '
2011 raise util.Abort('cannot use localheads with old style '
2006 'discovery')
2012 'discovery')
2007 if not util.safehasattr(remote, 'branches'):
2013 if not util.safehasattr(remote, 'branches'):
2008 # enable in-client legacy support
2014 # enable in-client legacy support
2009 remote = localrepo.locallegacypeer(remote.local())
2015 remote = localrepo.locallegacypeer(remote.local())
2010 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2016 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2011 force=True)
2017 force=True)
2012 common = set(common)
2018 common = set(common)
2013 if not opts.get('nonheads'):
2019 if not opts.get('nonheads'):
2014 ui.write(("unpruned common: %s\n") %
2020 ui.write(("unpruned common: %s\n") %
2015 " ".join(sorted(short(n) for n in common)))
2021 " ".join(sorted(short(n) for n in common)))
2016 dag = dagutil.revlogdag(repo.changelog)
2022 dag = dagutil.revlogdag(repo.changelog)
2017 all = dag.ancestorset(dag.internalizeall(common))
2023 all = dag.ancestorset(dag.internalizeall(common))
2018 common = dag.externalizeall(dag.headsetofconnecteds(all))
2024 common = dag.externalizeall(dag.headsetofconnecteds(all))
2019 else:
2025 else:
2020 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2026 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2021 common = set(common)
2027 common = set(common)
2022 rheads = set(hds)
2028 rheads = set(hds)
2023 lheads = set(repo.heads())
2029 lheads = set(repo.heads())
2024 ui.write(("common heads: %s\n") %
2030 ui.write(("common heads: %s\n") %
2025 " ".join(sorted(short(n) for n in common)))
2031 " ".join(sorted(short(n) for n in common)))
2026 if lheads <= common:
2032 if lheads <= common:
2027 ui.write(("local is subset\n"))
2033 ui.write(("local is subset\n"))
2028 elif rheads <= common:
2034 elif rheads <= common:
2029 ui.write(("remote is subset\n"))
2035 ui.write(("remote is subset\n"))
2030
2036
2031 serverlogs = opts.get('serverlog')
2037 serverlogs = opts.get('serverlog')
2032 if serverlogs:
2038 if serverlogs:
2033 for filename in serverlogs:
2039 for filename in serverlogs:
2034 logfile = open(filename, 'r')
2040 logfile = open(filename, 'r')
2035 try:
2041 try:
2036 line = logfile.readline()
2042 line = logfile.readline()
2037 while line:
2043 while line:
2038 parts = line.strip().split(';')
2044 parts = line.strip().split(';')
2039 op = parts[1]
2045 op = parts[1]
2040 if op == 'cg':
2046 if op == 'cg':
2041 pass
2047 pass
2042 elif op == 'cgss':
2048 elif op == 'cgss':
2043 doit(parts[2].split(' '), parts[3].split(' '))
2049 doit(parts[2].split(' '), parts[3].split(' '))
2044 elif op == 'unb':
2050 elif op == 'unb':
2045 doit(parts[3].split(' '), parts[2].split(' '))
2051 doit(parts[3].split(' '), parts[2].split(' '))
2046 line = logfile.readline()
2052 line = logfile.readline()
2047 finally:
2053 finally:
2048 logfile.close()
2054 logfile.close()
2049
2055
2050 else:
2056 else:
2051 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2057 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2052 opts.get('remote_head'))
2058 opts.get('remote_head'))
2053 localrevs = opts.get('local_head')
2059 localrevs = opts.get('local_head')
2054 doit(localrevs, remoterevs)
2060 doit(localrevs, remoterevs)
2055
2061
2056 @command('debugfileset',
2062 @command('debugfileset',
2057 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2063 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2058 _('[-r REV] FILESPEC'))
2064 _('[-r REV] FILESPEC'))
2059 def debugfileset(ui, repo, expr, **opts):
2065 def debugfileset(ui, repo, expr, **opts):
2060 '''parse and apply a fileset specification'''
2066 '''parse and apply a fileset specification'''
2061 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2067 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2062 if ui.verbose:
2068 if ui.verbose:
2063 tree = fileset.parse(expr)[0]
2069 tree = fileset.parse(expr)[0]
2064 ui.note(tree, "\n")
2070 ui.note(tree, "\n")
2065
2071
2066 for f in ctx.getfileset(expr):
2072 for f in ctx.getfileset(expr):
2067 ui.write("%s\n" % f)
2073 ui.write("%s\n" % f)
2068
2074
2069 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2075 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2070 def debugfsinfo(ui, path="."):
2076 def debugfsinfo(ui, path="."):
2071 """show information detected about current filesystem"""
2077 """show information detected about current filesystem"""
2072 util.writefile('.debugfsinfo', '')
2078 util.writefile('.debugfsinfo', '')
2073 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2079 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2074 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2080 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2075 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2081 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2076 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2082 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2077 and 'yes' or 'no'))
2083 and 'yes' or 'no'))
2078 os.unlink('.debugfsinfo')
2084 os.unlink('.debugfsinfo')
2079
2085
2080 @command('debuggetbundle',
2086 @command('debuggetbundle',
2081 [('H', 'head', [], _('id of head node'), _('ID')),
2087 [('H', 'head', [], _('id of head node'), _('ID')),
2082 ('C', 'common', [], _('id of common node'), _('ID')),
2088 ('C', 'common', [], _('id of common node'), _('ID')),
2083 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2089 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2084 _('REPO FILE [-H|-C ID]...'),
2090 _('REPO FILE [-H|-C ID]...'),
2085 norepo=True)
2091 norepo=True)
2086 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2092 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2087 """retrieves a bundle from a repo
2093 """retrieves a bundle from a repo
2088
2094
2089 Every ID must be a full-length hex node id string. Saves the bundle to the
2095 Every ID must be a full-length hex node id string. Saves the bundle to the
2090 given file.
2096 given file.
2091 """
2097 """
2092 repo = hg.peer(ui, opts, repopath)
2098 repo = hg.peer(ui, opts, repopath)
2093 if not repo.capable('getbundle'):
2099 if not repo.capable('getbundle'):
2094 raise util.Abort("getbundle() not supported by target repository")
2100 raise util.Abort("getbundle() not supported by target repository")
2095 args = {}
2101 args = {}
2096 if common:
2102 if common:
2097 args['common'] = [bin(s) for s in common]
2103 args['common'] = [bin(s) for s in common]
2098 if head:
2104 if head:
2099 args['heads'] = [bin(s) for s in head]
2105 args['heads'] = [bin(s) for s in head]
2100 # TODO: get desired bundlecaps from command line.
2106 # TODO: get desired bundlecaps from command line.
2101 args['bundlecaps'] = None
2107 args['bundlecaps'] = None
2102 bundle = repo.getbundle('debug', **args)
2108 bundle = repo.getbundle('debug', **args)
2103
2109
2104 bundletype = opts.get('type', 'bzip2').lower()
2110 bundletype = opts.get('type', 'bzip2').lower()
2105 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2111 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2106 bundletype = btypes.get(bundletype)
2112 bundletype = btypes.get(bundletype)
2107 if bundletype not in changegroup.bundletypes:
2113 if bundletype not in changegroup.bundletypes:
2108 raise util.Abort(_('unknown bundle type specified with --type'))
2114 raise util.Abort(_('unknown bundle type specified with --type'))
2109 changegroup.writebundle(bundle, bundlepath, bundletype)
2115 changegroup.writebundle(bundle, bundlepath, bundletype)
2110
2116
2111 @command('debugignore', [], '')
2117 @command('debugignore', [], '')
2112 def debugignore(ui, repo, *values, **opts):
2118 def debugignore(ui, repo, *values, **opts):
2113 """display the combined ignore pattern"""
2119 """display the combined ignore pattern"""
2114 ignore = repo.dirstate._ignore
2120 ignore = repo.dirstate._ignore
2115 includepat = getattr(ignore, 'includepat', None)
2121 includepat = getattr(ignore, 'includepat', None)
2116 if includepat is not None:
2122 if includepat is not None:
2117 ui.write("%s\n" % includepat)
2123 ui.write("%s\n" % includepat)
2118 else:
2124 else:
2119 raise util.Abort(_("no ignore patterns found"))
2125 raise util.Abort(_("no ignore patterns found"))
2120
2126
2121 @command('debugindex',
2127 @command('debugindex',
2122 [('c', 'changelog', False, _('open changelog')),
2128 [('c', 'changelog', False, _('open changelog')),
2123 ('m', 'manifest', False, _('open manifest')),
2129 ('m', 'manifest', False, _('open manifest')),
2124 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2130 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2125 _('[-f FORMAT] -c|-m|FILE'),
2131 _('[-f FORMAT] -c|-m|FILE'),
2126 optionalrepo=True)
2132 optionalrepo=True)
2127 def debugindex(ui, repo, file_=None, **opts):
2133 def debugindex(ui, repo, file_=None, **opts):
2128 """dump the contents of an index file"""
2134 """dump the contents of an index file"""
2129 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2135 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2130 format = opts.get('format', 0)
2136 format = opts.get('format', 0)
2131 if format not in (0, 1):
2137 if format not in (0, 1):
2132 raise util.Abort(_("unknown format %d") % format)
2138 raise util.Abort(_("unknown format %d") % format)
2133
2139
2134 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2140 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2135 if generaldelta:
2141 if generaldelta:
2136 basehdr = ' delta'
2142 basehdr = ' delta'
2137 else:
2143 else:
2138 basehdr = ' base'
2144 basehdr = ' base'
2139
2145
2140 if format == 0:
2146 if format == 0:
2141 ui.write(" rev offset length " + basehdr + " linkrev"
2147 ui.write(" rev offset length " + basehdr + " linkrev"
2142 " nodeid p1 p2\n")
2148 " nodeid p1 p2\n")
2143 elif format == 1:
2149 elif format == 1:
2144 ui.write(" rev flag offset length"
2150 ui.write(" rev flag offset length"
2145 " size " + basehdr + " link p1 p2"
2151 " size " + basehdr + " link p1 p2"
2146 " nodeid\n")
2152 " nodeid\n")
2147
2153
2148 for i in r:
2154 for i in r:
2149 node = r.node(i)
2155 node = r.node(i)
2150 if generaldelta:
2156 if generaldelta:
2151 base = r.deltaparent(i)
2157 base = r.deltaparent(i)
2152 else:
2158 else:
2153 base = r.chainbase(i)
2159 base = r.chainbase(i)
2154 if format == 0:
2160 if format == 0:
2155 try:
2161 try:
2156 pp = r.parents(node)
2162 pp = r.parents(node)
2157 except Exception:
2163 except Exception:
2158 pp = [nullid, nullid]
2164 pp = [nullid, nullid]
2159 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2165 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2160 i, r.start(i), r.length(i), base, r.linkrev(i),
2166 i, r.start(i), r.length(i), base, r.linkrev(i),
2161 short(node), short(pp[0]), short(pp[1])))
2167 short(node), short(pp[0]), short(pp[1])))
2162 elif format == 1:
2168 elif format == 1:
2163 pr = r.parentrevs(i)
2169 pr = r.parentrevs(i)
2164 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2170 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2165 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2171 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2166 base, r.linkrev(i), pr[0], pr[1], short(node)))
2172 base, r.linkrev(i), pr[0], pr[1], short(node)))
2167
2173
2168 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2174 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2169 def debugindexdot(ui, repo, file_):
2175 def debugindexdot(ui, repo, file_):
2170 """dump an index DAG as a graphviz dot file"""
2176 """dump an index DAG as a graphviz dot file"""
2171 r = None
2177 r = None
2172 if repo:
2178 if repo:
2173 filelog = repo.file(file_)
2179 filelog = repo.file(file_)
2174 if len(filelog):
2180 if len(filelog):
2175 r = filelog
2181 r = filelog
2176 if not r:
2182 if not r:
2177 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2183 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2178 ui.write(("digraph G {\n"))
2184 ui.write(("digraph G {\n"))
2179 for i in r:
2185 for i in r:
2180 node = r.node(i)
2186 node = r.node(i)
2181 pp = r.parents(node)
2187 pp = r.parents(node)
2182 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2188 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2183 if pp[1] != nullid:
2189 if pp[1] != nullid:
2184 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2190 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2185 ui.write("}\n")
2191 ui.write("}\n")
2186
2192
2187 @command('debuginstall', [], '', norepo=True)
2193 @command('debuginstall', [], '', norepo=True)
2188 def debuginstall(ui):
2194 def debuginstall(ui):
2189 '''test Mercurial installation
2195 '''test Mercurial installation
2190
2196
2191 Returns 0 on success.
2197 Returns 0 on success.
2192 '''
2198 '''
2193
2199
2194 def writetemp(contents):
2200 def writetemp(contents):
2195 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2201 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2196 f = os.fdopen(fd, "wb")
2202 f = os.fdopen(fd, "wb")
2197 f.write(contents)
2203 f.write(contents)
2198 f.close()
2204 f.close()
2199 return name
2205 return name
2200
2206
2201 problems = 0
2207 problems = 0
2202
2208
2203 # encoding
2209 # encoding
2204 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2210 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2205 try:
2211 try:
2206 encoding.fromlocal("test")
2212 encoding.fromlocal("test")
2207 except util.Abort, inst:
2213 except util.Abort, inst:
2208 ui.write(" %s\n" % inst)
2214 ui.write(" %s\n" % inst)
2209 ui.write(_(" (check that your locale is properly set)\n"))
2215 ui.write(_(" (check that your locale is properly set)\n"))
2210 problems += 1
2216 problems += 1
2211
2217
2212 # Python
2218 # Python
2213 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2219 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2214 ui.status(_("checking Python version (%s)\n")
2220 ui.status(_("checking Python version (%s)\n")
2215 % ("%s.%s.%s" % sys.version_info[:3]))
2221 % ("%s.%s.%s" % sys.version_info[:3]))
2216 ui.status(_("checking Python lib (%s)...\n")
2222 ui.status(_("checking Python lib (%s)...\n")
2217 % os.path.dirname(os.__file__))
2223 % os.path.dirname(os.__file__))
2218
2224
2219 # compiled modules
2225 # compiled modules
2220 ui.status(_("checking installed modules (%s)...\n")
2226 ui.status(_("checking installed modules (%s)...\n")
2221 % os.path.dirname(__file__))
2227 % os.path.dirname(__file__))
2222 try:
2228 try:
2223 import bdiff, mpatch, base85, osutil
2229 import bdiff, mpatch, base85, osutil
2224 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2230 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2225 except Exception, inst:
2231 except Exception, inst:
2226 ui.write(" %s\n" % inst)
2232 ui.write(" %s\n" % inst)
2227 ui.write(_(" One or more extensions could not be found"))
2233 ui.write(_(" One or more extensions could not be found"))
2228 ui.write(_(" (check that you compiled the extensions)\n"))
2234 ui.write(_(" (check that you compiled the extensions)\n"))
2229 problems += 1
2235 problems += 1
2230
2236
2231 # templates
2237 # templates
2232 import templater
2238 import templater
2233 p = templater.templatepath()
2239 p = templater.templatepath()
2234 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2240 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2235 if p:
2241 if p:
2236 m = templater.templatepath("map-cmdline.default")
2242 m = templater.templatepath("map-cmdline.default")
2237 if m:
2243 if m:
2238 # template found, check if it is working
2244 # template found, check if it is working
2239 try:
2245 try:
2240 templater.templater(m)
2246 templater.templater(m)
2241 except Exception, inst:
2247 except Exception, inst:
2242 ui.write(" %s\n" % inst)
2248 ui.write(" %s\n" % inst)
2243 p = None
2249 p = None
2244 else:
2250 else:
2245 ui.write(_(" template 'default' not found\n"))
2251 ui.write(_(" template 'default' not found\n"))
2246 p = None
2252 p = None
2247 else:
2253 else:
2248 ui.write(_(" no template directories found\n"))
2254 ui.write(_(" no template directories found\n"))
2249 if not p:
2255 if not p:
2250 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2256 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2251 problems += 1
2257 problems += 1
2252
2258
2253 # editor
2259 # editor
2254 ui.status(_("checking commit editor...\n"))
2260 ui.status(_("checking commit editor...\n"))
2255 editor = ui.geteditor()
2261 editor = ui.geteditor()
2256 cmdpath = util.findexe(shlex.split(editor)[0])
2262 cmdpath = util.findexe(shlex.split(editor)[0])
2257 if not cmdpath:
2263 if not cmdpath:
2258 if editor == 'vi':
2264 if editor == 'vi':
2259 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2265 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2260 ui.write(_(" (specify a commit editor in your configuration"
2266 ui.write(_(" (specify a commit editor in your configuration"
2261 " file)\n"))
2267 " file)\n"))
2262 else:
2268 else:
2263 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2269 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2264 ui.write(_(" (specify a commit editor in your configuration"
2270 ui.write(_(" (specify a commit editor in your configuration"
2265 " file)\n"))
2271 " file)\n"))
2266 problems += 1
2272 problems += 1
2267
2273
2268 # check username
2274 # check username
2269 ui.status(_("checking username...\n"))
2275 ui.status(_("checking username...\n"))
2270 try:
2276 try:
2271 ui.username()
2277 ui.username()
2272 except util.Abort, e:
2278 except util.Abort, e:
2273 ui.write(" %s\n" % e)
2279 ui.write(" %s\n" % e)
2274 ui.write(_(" (specify a username in your configuration file)\n"))
2280 ui.write(_(" (specify a username in your configuration file)\n"))
2275 problems += 1
2281 problems += 1
2276
2282
2277 if not problems:
2283 if not problems:
2278 ui.status(_("no problems detected\n"))
2284 ui.status(_("no problems detected\n"))
2279 else:
2285 else:
2280 ui.write(_("%s problems detected,"
2286 ui.write(_("%s problems detected,"
2281 " please check your install!\n") % problems)
2287 " please check your install!\n") % problems)
2282
2288
2283 return problems
2289 return problems
2284
2290
2285 @command('debugknown', [], _('REPO ID...'), norepo=True)
2291 @command('debugknown', [], _('REPO ID...'), norepo=True)
2286 def debugknown(ui, repopath, *ids, **opts):
2292 def debugknown(ui, repopath, *ids, **opts):
2287 """test whether node ids are known to a repo
2293 """test whether node ids are known to a repo
2288
2294
2289 Every ID must be a full-length hex node id string. Returns a list of 0s
2295 Every ID must be a full-length hex node id string. Returns a list of 0s
2290 and 1s indicating unknown/known.
2296 and 1s indicating unknown/known.
2291 """
2297 """
2292 repo = hg.peer(ui, opts, repopath)
2298 repo = hg.peer(ui, opts, repopath)
2293 if not repo.capable('known'):
2299 if not repo.capable('known'):
2294 raise util.Abort("known() not supported by target repository")
2300 raise util.Abort("known() not supported by target repository")
2295 flags = repo.known([bin(s) for s in ids])
2301 flags = repo.known([bin(s) for s in ids])
2296 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2302 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2297
2303
2298 @command('debuglabelcomplete', [], _('LABEL...'))
2304 @command('debuglabelcomplete', [], _('LABEL...'))
2299 def debuglabelcomplete(ui, repo, *args):
2305 def debuglabelcomplete(ui, repo, *args):
2300 '''complete "labels" - tags, open branch names, bookmark names'''
2306 '''complete "labels" - tags, open branch names, bookmark names'''
2301
2307
2302 labels = set()
2308 labels = set()
2303 labels.update(t[0] for t in repo.tagslist())
2309 labels.update(t[0] for t in repo.tagslist())
2304 labels.update(repo._bookmarks.keys())
2310 labels.update(repo._bookmarks.keys())
2305 labels.update(tag for (tag, heads, tip, closed)
2311 labels.update(tag for (tag, heads, tip, closed)
2306 in repo.branchmap().iterbranches() if not closed)
2312 in repo.branchmap().iterbranches() if not closed)
2307 completions = set()
2313 completions = set()
2308 if not args:
2314 if not args:
2309 args = ['']
2315 args = ['']
2310 for a in args:
2316 for a in args:
2311 completions.update(l for l in labels if l.startswith(a))
2317 completions.update(l for l in labels if l.startswith(a))
2312 ui.write('\n'.join(sorted(completions)))
2318 ui.write('\n'.join(sorted(completions)))
2313 ui.write('\n')
2319 ui.write('\n')
2314
2320
2315 @command('debugobsolete',
2321 @command('debugobsolete',
2316 [('', 'flags', 0, _('markers flag')),
2322 [('', 'flags', 0, _('markers flag')),
2317 ('', 'record-parents', False,
2323 ('', 'record-parents', False,
2318 _('record parent information for the precursor')),
2324 _('record parent information for the precursor')),
2319 ('r', 'rev', [], _('display markers relevant to REV')),
2325 ('r', 'rev', [], _('display markers relevant to REV')),
2320 ] + commitopts2,
2326 ] + commitopts2,
2321 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2327 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2322 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2328 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2323 """create arbitrary obsolete marker
2329 """create arbitrary obsolete marker
2324
2330
2325 With no arguments, displays the list of obsolescence markers."""
2331 With no arguments, displays the list of obsolescence markers."""
2326
2332
2327 def parsenodeid(s):
2333 def parsenodeid(s):
2328 try:
2334 try:
2329 # We do not use revsingle/revrange functions here to accept
2335 # We do not use revsingle/revrange functions here to accept
2330 # arbitrary node identifiers, possibly not present in the
2336 # arbitrary node identifiers, possibly not present in the
2331 # local repository.
2337 # local repository.
2332 n = bin(s)
2338 n = bin(s)
2333 if len(n) != len(nullid):
2339 if len(n) != len(nullid):
2334 raise TypeError()
2340 raise TypeError()
2335 return n
2341 return n
2336 except TypeError:
2342 except TypeError:
2337 raise util.Abort('changeset references must be full hexadecimal '
2343 raise util.Abort('changeset references must be full hexadecimal '
2338 'node identifiers')
2344 'node identifiers')
2339
2345
2340 if precursor is not None:
2346 if precursor is not None:
2341 if opts['rev']:
2347 if opts['rev']:
2342 raise util.Abort('cannot select revision when creating marker')
2348 raise util.Abort('cannot select revision when creating marker')
2343 metadata = {}
2349 metadata = {}
2344 metadata['user'] = opts['user'] or ui.username()
2350 metadata['user'] = opts['user'] or ui.username()
2345 succs = tuple(parsenodeid(succ) for succ in successors)
2351 succs = tuple(parsenodeid(succ) for succ in successors)
2346 l = repo.lock()
2352 l = repo.lock()
2347 try:
2353 try:
2348 tr = repo.transaction('debugobsolete')
2354 tr = repo.transaction('debugobsolete')
2349 try:
2355 try:
2350 try:
2356 try:
2351 date = opts.get('date')
2357 date = opts.get('date')
2352 if date:
2358 if date:
2353 date = util.parsedate(date)
2359 date = util.parsedate(date)
2354 else:
2360 else:
2355 date = None
2361 date = None
2356 prec = parsenodeid(precursor)
2362 prec = parsenodeid(precursor)
2357 parents = None
2363 parents = None
2358 if opts['record_parents']:
2364 if opts['record_parents']:
2359 if prec not in repo.unfiltered():
2365 if prec not in repo.unfiltered():
2360 raise util.Abort('cannot used --record-parents on '
2366 raise util.Abort('cannot used --record-parents on '
2361 'unknown changesets')
2367 'unknown changesets')
2362 parents = repo.unfiltered()[prec].parents()
2368 parents = repo.unfiltered()[prec].parents()
2363 parents = tuple(p.node() for p in parents)
2369 parents = tuple(p.node() for p in parents)
2364 repo.obsstore.create(tr, prec, succs, opts['flags'],
2370 repo.obsstore.create(tr, prec, succs, opts['flags'],
2365 parents=parents, date=date,
2371 parents=parents, date=date,
2366 metadata=metadata)
2372 metadata=metadata)
2367 tr.close()
2373 tr.close()
2368 except ValueError, exc:
2374 except ValueError, exc:
2369 raise util.Abort(_('bad obsmarker input: %s') % exc)
2375 raise util.Abort(_('bad obsmarker input: %s') % exc)
2370 finally:
2376 finally:
2371 tr.release()
2377 tr.release()
2372 finally:
2378 finally:
2373 l.release()
2379 l.release()
2374 else:
2380 else:
2375 if opts['rev']:
2381 if opts['rev']:
2376 revs = scmutil.revrange(repo, opts['rev'])
2382 revs = scmutil.revrange(repo, opts['rev'])
2377 nodes = [repo[r].node() for r in revs]
2383 nodes = [repo[r].node() for r in revs]
2378 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2384 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2379 markers.sort(key=lambda x: x._data)
2385 markers.sort(key=lambda x: x._data)
2380 else:
2386 else:
2381 markers = obsolete.getmarkers(repo)
2387 markers = obsolete.getmarkers(repo)
2382
2388
2383 for m in markers:
2389 for m in markers:
2384 cmdutil.showmarker(ui, m)
2390 cmdutil.showmarker(ui, m)
2385
2391
2386 @command('debugpathcomplete',
2392 @command('debugpathcomplete',
2387 [('f', 'full', None, _('complete an entire path')),
2393 [('f', 'full', None, _('complete an entire path')),
2388 ('n', 'normal', None, _('show only normal files')),
2394 ('n', 'normal', None, _('show only normal files')),
2389 ('a', 'added', None, _('show only added files')),
2395 ('a', 'added', None, _('show only added files')),
2390 ('r', 'removed', None, _('show only removed files'))],
2396 ('r', 'removed', None, _('show only removed files'))],
2391 _('FILESPEC...'))
2397 _('FILESPEC...'))
2392 def debugpathcomplete(ui, repo, *specs, **opts):
2398 def debugpathcomplete(ui, repo, *specs, **opts):
2393 '''complete part or all of a tracked path
2399 '''complete part or all of a tracked path
2394
2400
2395 This command supports shells that offer path name completion. It
2401 This command supports shells that offer path name completion. It
2396 currently completes only files already known to the dirstate.
2402 currently completes only files already known to the dirstate.
2397
2403
2398 Completion extends only to the next path segment unless
2404 Completion extends only to the next path segment unless
2399 --full is specified, in which case entire paths are used.'''
2405 --full is specified, in which case entire paths are used.'''
2400
2406
2401 def complete(path, acceptable):
2407 def complete(path, acceptable):
2402 dirstate = repo.dirstate
2408 dirstate = repo.dirstate
2403 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2409 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2404 rootdir = repo.root + os.sep
2410 rootdir = repo.root + os.sep
2405 if spec != repo.root and not spec.startswith(rootdir):
2411 if spec != repo.root and not spec.startswith(rootdir):
2406 return [], []
2412 return [], []
2407 if os.path.isdir(spec):
2413 if os.path.isdir(spec):
2408 spec += '/'
2414 spec += '/'
2409 spec = spec[len(rootdir):]
2415 spec = spec[len(rootdir):]
2410 fixpaths = os.sep != '/'
2416 fixpaths = os.sep != '/'
2411 if fixpaths:
2417 if fixpaths:
2412 spec = spec.replace(os.sep, '/')
2418 spec = spec.replace(os.sep, '/')
2413 speclen = len(spec)
2419 speclen = len(spec)
2414 fullpaths = opts['full']
2420 fullpaths = opts['full']
2415 files, dirs = set(), set()
2421 files, dirs = set(), set()
2416 adddir, addfile = dirs.add, files.add
2422 adddir, addfile = dirs.add, files.add
2417 for f, st in dirstate.iteritems():
2423 for f, st in dirstate.iteritems():
2418 if f.startswith(spec) and st[0] in acceptable:
2424 if f.startswith(spec) and st[0] in acceptable:
2419 if fixpaths:
2425 if fixpaths:
2420 f = f.replace('/', os.sep)
2426 f = f.replace('/', os.sep)
2421 if fullpaths:
2427 if fullpaths:
2422 addfile(f)
2428 addfile(f)
2423 continue
2429 continue
2424 s = f.find(os.sep, speclen)
2430 s = f.find(os.sep, speclen)
2425 if s >= 0:
2431 if s >= 0:
2426 adddir(f[:s])
2432 adddir(f[:s])
2427 else:
2433 else:
2428 addfile(f)
2434 addfile(f)
2429 return files, dirs
2435 return files, dirs
2430
2436
2431 acceptable = ''
2437 acceptable = ''
2432 if opts['normal']:
2438 if opts['normal']:
2433 acceptable += 'nm'
2439 acceptable += 'nm'
2434 if opts['added']:
2440 if opts['added']:
2435 acceptable += 'a'
2441 acceptable += 'a'
2436 if opts['removed']:
2442 if opts['removed']:
2437 acceptable += 'r'
2443 acceptable += 'r'
2438 cwd = repo.getcwd()
2444 cwd = repo.getcwd()
2439 if not specs:
2445 if not specs:
2440 specs = ['.']
2446 specs = ['.']
2441
2447
2442 files, dirs = set(), set()
2448 files, dirs = set(), set()
2443 for spec in specs:
2449 for spec in specs:
2444 f, d = complete(spec, acceptable or 'nmar')
2450 f, d = complete(spec, acceptable or 'nmar')
2445 files.update(f)
2451 files.update(f)
2446 dirs.update(d)
2452 dirs.update(d)
2447 files.update(dirs)
2453 files.update(dirs)
2448 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2454 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2449 ui.write('\n')
2455 ui.write('\n')
2450
2456
2451 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2457 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2452 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2458 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2453 '''access the pushkey key/value protocol
2459 '''access the pushkey key/value protocol
2454
2460
2455 With two args, list the keys in the given namespace.
2461 With two args, list the keys in the given namespace.
2456
2462
2457 With five args, set a key to new if it currently is set to old.
2463 With five args, set a key to new if it currently is set to old.
2458 Reports success or failure.
2464 Reports success or failure.
2459 '''
2465 '''
2460
2466
2461 target = hg.peer(ui, {}, repopath)
2467 target = hg.peer(ui, {}, repopath)
2462 if keyinfo:
2468 if keyinfo:
2463 key, old, new = keyinfo
2469 key, old, new = keyinfo
2464 r = target.pushkey(namespace, key, old, new)
2470 r = target.pushkey(namespace, key, old, new)
2465 ui.status(str(r) + '\n')
2471 ui.status(str(r) + '\n')
2466 return not r
2472 return not r
2467 else:
2473 else:
2468 for k, v in sorted(target.listkeys(namespace).iteritems()):
2474 for k, v in sorted(target.listkeys(namespace).iteritems()):
2469 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2475 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2470 v.encode('string-escape')))
2476 v.encode('string-escape')))
2471
2477
2472 @command('debugpvec', [], _('A B'))
2478 @command('debugpvec', [], _('A B'))
2473 def debugpvec(ui, repo, a, b=None):
2479 def debugpvec(ui, repo, a, b=None):
2474 ca = scmutil.revsingle(repo, a)
2480 ca = scmutil.revsingle(repo, a)
2475 cb = scmutil.revsingle(repo, b)
2481 cb = scmutil.revsingle(repo, b)
2476 pa = pvec.ctxpvec(ca)
2482 pa = pvec.ctxpvec(ca)
2477 pb = pvec.ctxpvec(cb)
2483 pb = pvec.ctxpvec(cb)
2478 if pa == pb:
2484 if pa == pb:
2479 rel = "="
2485 rel = "="
2480 elif pa > pb:
2486 elif pa > pb:
2481 rel = ">"
2487 rel = ">"
2482 elif pa < pb:
2488 elif pa < pb:
2483 rel = "<"
2489 rel = "<"
2484 elif pa | pb:
2490 elif pa | pb:
2485 rel = "|"
2491 rel = "|"
2486 ui.write(_("a: %s\n") % pa)
2492 ui.write(_("a: %s\n") % pa)
2487 ui.write(_("b: %s\n") % pb)
2493 ui.write(_("b: %s\n") % pb)
2488 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2494 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2489 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2495 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2490 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2496 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2491 pa.distance(pb), rel))
2497 pa.distance(pb), rel))
2492
2498
2493 @command('debugrebuilddirstate|debugrebuildstate',
2499 @command('debugrebuilddirstate|debugrebuildstate',
2494 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2500 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2495 _('[-r REV]'))
2501 _('[-r REV]'))
2496 def debugrebuilddirstate(ui, repo, rev):
2502 def debugrebuilddirstate(ui, repo, rev):
2497 """rebuild the dirstate as it would look like for the given revision
2503 """rebuild the dirstate as it would look like for the given revision
2498
2504
2499 If no revision is specified the first current parent will be used.
2505 If no revision is specified the first current parent will be used.
2500
2506
2501 The dirstate will be set to the files of the given revision.
2507 The dirstate will be set to the files of the given revision.
2502 The actual working directory content or existing dirstate
2508 The actual working directory content or existing dirstate
2503 information such as adds or removes is not considered.
2509 information such as adds or removes is not considered.
2504
2510
2505 One use of this command is to make the next :hg:`status` invocation
2511 One use of this command is to make the next :hg:`status` invocation
2506 check the actual file content.
2512 check the actual file content.
2507 """
2513 """
2508 ctx = scmutil.revsingle(repo, rev)
2514 ctx = scmutil.revsingle(repo, rev)
2509 wlock = repo.wlock()
2515 wlock = repo.wlock()
2510 try:
2516 try:
2511 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2517 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2512 finally:
2518 finally:
2513 wlock.release()
2519 wlock.release()
2514
2520
2515 @command('debugrename',
2521 @command('debugrename',
2516 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2522 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2517 _('[-r REV] FILE'))
2523 _('[-r REV] FILE'))
2518 def debugrename(ui, repo, file1, *pats, **opts):
2524 def debugrename(ui, repo, file1, *pats, **opts):
2519 """dump rename information"""
2525 """dump rename information"""
2520
2526
2521 ctx = scmutil.revsingle(repo, opts.get('rev'))
2527 ctx = scmutil.revsingle(repo, opts.get('rev'))
2522 m = scmutil.match(ctx, (file1,) + pats, opts)
2528 m = scmutil.match(ctx, (file1,) + pats, opts)
2523 for abs in ctx.walk(m):
2529 for abs in ctx.walk(m):
2524 fctx = ctx[abs]
2530 fctx = ctx[abs]
2525 o = fctx.filelog().renamed(fctx.filenode())
2531 o = fctx.filelog().renamed(fctx.filenode())
2526 rel = m.rel(abs)
2532 rel = m.rel(abs)
2527 if o:
2533 if o:
2528 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2534 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2529 else:
2535 else:
2530 ui.write(_("%s not renamed\n") % rel)
2536 ui.write(_("%s not renamed\n") % rel)
2531
2537
2532 @command('debugrevlog',
2538 @command('debugrevlog',
2533 [('c', 'changelog', False, _('open changelog')),
2539 [('c', 'changelog', False, _('open changelog')),
2534 ('m', 'manifest', False, _('open manifest')),
2540 ('m', 'manifest', False, _('open manifest')),
2535 ('d', 'dump', False, _('dump index data'))],
2541 ('d', 'dump', False, _('dump index data'))],
2536 _('-c|-m|FILE'),
2542 _('-c|-m|FILE'),
2537 optionalrepo=True)
2543 optionalrepo=True)
2538 def debugrevlog(ui, repo, file_=None, **opts):
2544 def debugrevlog(ui, repo, file_=None, **opts):
2539 """show data and statistics about a revlog"""
2545 """show data and statistics about a revlog"""
2540 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2546 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2541
2547
2542 if opts.get("dump"):
2548 if opts.get("dump"):
2543 numrevs = len(r)
2549 numrevs = len(r)
2544 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2550 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2545 " rawsize totalsize compression heads chainlen\n")
2551 " rawsize totalsize compression heads chainlen\n")
2546 ts = 0
2552 ts = 0
2547 heads = set()
2553 heads = set()
2548 rindex = r.index
2554 rindex = r.index
2549
2555
2550 def chainbaseandlen(rev):
2556 def chainbaseandlen(rev):
2551 clen = 0
2557 clen = 0
2552 base = rindex[rev][3]
2558 base = rindex[rev][3]
2553 while base != rev:
2559 while base != rev:
2554 clen += 1
2560 clen += 1
2555 rev = base
2561 rev = base
2556 base = rindex[rev][3]
2562 base = rindex[rev][3]
2557 return base, clen
2563 return base, clen
2558
2564
2559 for rev in xrange(numrevs):
2565 for rev in xrange(numrevs):
2560 dbase = r.deltaparent(rev)
2566 dbase = r.deltaparent(rev)
2561 if dbase == -1:
2567 if dbase == -1:
2562 dbase = rev
2568 dbase = rev
2563 cbase, clen = chainbaseandlen(rev)
2569 cbase, clen = chainbaseandlen(rev)
2564 p1, p2 = r.parentrevs(rev)
2570 p1, p2 = r.parentrevs(rev)
2565 rs = r.rawsize(rev)
2571 rs = r.rawsize(rev)
2566 ts = ts + rs
2572 ts = ts + rs
2567 heads -= set(r.parentrevs(rev))
2573 heads -= set(r.parentrevs(rev))
2568 heads.add(rev)
2574 heads.add(rev)
2569 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2575 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2570 "%11d %5d %8d\n" %
2576 "%11d %5d %8d\n" %
2571 (rev, p1, p2, r.start(rev), r.end(rev),
2577 (rev, p1, p2, r.start(rev), r.end(rev),
2572 r.start(dbase), r.start(cbase),
2578 r.start(dbase), r.start(cbase),
2573 r.start(p1), r.start(p2),
2579 r.start(p1), r.start(p2),
2574 rs, ts, ts / r.end(rev), len(heads), clen))
2580 rs, ts, ts / r.end(rev), len(heads), clen))
2575 return 0
2581 return 0
2576
2582
2577 v = r.version
2583 v = r.version
2578 format = v & 0xFFFF
2584 format = v & 0xFFFF
2579 flags = []
2585 flags = []
2580 gdelta = False
2586 gdelta = False
2581 if v & revlog.REVLOGNGINLINEDATA:
2587 if v & revlog.REVLOGNGINLINEDATA:
2582 flags.append('inline')
2588 flags.append('inline')
2583 if v & revlog.REVLOGGENERALDELTA:
2589 if v & revlog.REVLOGGENERALDELTA:
2584 gdelta = True
2590 gdelta = True
2585 flags.append('generaldelta')
2591 flags.append('generaldelta')
2586 if not flags:
2592 if not flags:
2587 flags = ['(none)']
2593 flags = ['(none)']
2588
2594
2589 nummerges = 0
2595 nummerges = 0
2590 numfull = 0
2596 numfull = 0
2591 numprev = 0
2597 numprev = 0
2592 nump1 = 0
2598 nump1 = 0
2593 nump2 = 0
2599 nump2 = 0
2594 numother = 0
2600 numother = 0
2595 nump1prev = 0
2601 nump1prev = 0
2596 nump2prev = 0
2602 nump2prev = 0
2597 chainlengths = []
2603 chainlengths = []
2598
2604
2599 datasize = [None, 0, 0L]
2605 datasize = [None, 0, 0L]
2600 fullsize = [None, 0, 0L]
2606 fullsize = [None, 0, 0L]
2601 deltasize = [None, 0, 0L]
2607 deltasize = [None, 0, 0L]
2602
2608
2603 def addsize(size, l):
2609 def addsize(size, l):
2604 if l[0] is None or size < l[0]:
2610 if l[0] is None or size < l[0]:
2605 l[0] = size
2611 l[0] = size
2606 if size > l[1]:
2612 if size > l[1]:
2607 l[1] = size
2613 l[1] = size
2608 l[2] += size
2614 l[2] += size
2609
2615
2610 numrevs = len(r)
2616 numrevs = len(r)
2611 for rev in xrange(numrevs):
2617 for rev in xrange(numrevs):
2612 p1, p2 = r.parentrevs(rev)
2618 p1, p2 = r.parentrevs(rev)
2613 delta = r.deltaparent(rev)
2619 delta = r.deltaparent(rev)
2614 if format > 0:
2620 if format > 0:
2615 addsize(r.rawsize(rev), datasize)
2621 addsize(r.rawsize(rev), datasize)
2616 if p2 != nullrev:
2622 if p2 != nullrev:
2617 nummerges += 1
2623 nummerges += 1
2618 size = r.length(rev)
2624 size = r.length(rev)
2619 if delta == nullrev:
2625 if delta == nullrev:
2620 chainlengths.append(0)
2626 chainlengths.append(0)
2621 numfull += 1
2627 numfull += 1
2622 addsize(size, fullsize)
2628 addsize(size, fullsize)
2623 else:
2629 else:
2624 chainlengths.append(chainlengths[delta] + 1)
2630 chainlengths.append(chainlengths[delta] + 1)
2625 addsize(size, deltasize)
2631 addsize(size, deltasize)
2626 if delta == rev - 1:
2632 if delta == rev - 1:
2627 numprev += 1
2633 numprev += 1
2628 if delta == p1:
2634 if delta == p1:
2629 nump1prev += 1
2635 nump1prev += 1
2630 elif delta == p2:
2636 elif delta == p2:
2631 nump2prev += 1
2637 nump2prev += 1
2632 elif delta == p1:
2638 elif delta == p1:
2633 nump1 += 1
2639 nump1 += 1
2634 elif delta == p2:
2640 elif delta == p2:
2635 nump2 += 1
2641 nump2 += 1
2636 elif delta != nullrev:
2642 elif delta != nullrev:
2637 numother += 1
2643 numother += 1
2638
2644
2639 # Adjust size min value for empty cases
2645 # Adjust size min value for empty cases
2640 for size in (datasize, fullsize, deltasize):
2646 for size in (datasize, fullsize, deltasize):
2641 if size[0] is None:
2647 if size[0] is None:
2642 size[0] = 0
2648 size[0] = 0
2643
2649
2644 numdeltas = numrevs - numfull
2650 numdeltas = numrevs - numfull
2645 numoprev = numprev - nump1prev - nump2prev
2651 numoprev = numprev - nump1prev - nump2prev
2646 totalrawsize = datasize[2]
2652 totalrawsize = datasize[2]
2647 datasize[2] /= numrevs
2653 datasize[2] /= numrevs
2648 fulltotal = fullsize[2]
2654 fulltotal = fullsize[2]
2649 fullsize[2] /= numfull
2655 fullsize[2] /= numfull
2650 deltatotal = deltasize[2]
2656 deltatotal = deltasize[2]
2651 if numrevs - numfull > 0:
2657 if numrevs - numfull > 0:
2652 deltasize[2] /= numrevs - numfull
2658 deltasize[2] /= numrevs - numfull
2653 totalsize = fulltotal + deltatotal
2659 totalsize = fulltotal + deltatotal
2654 avgchainlen = sum(chainlengths) / numrevs
2660 avgchainlen = sum(chainlengths) / numrevs
2655 compratio = totalrawsize / totalsize
2661 compratio = totalrawsize / totalsize
2656
2662
2657 basedfmtstr = '%%%dd\n'
2663 basedfmtstr = '%%%dd\n'
2658 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2664 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2659
2665
2660 def dfmtstr(max):
2666 def dfmtstr(max):
2661 return basedfmtstr % len(str(max))
2667 return basedfmtstr % len(str(max))
2662 def pcfmtstr(max, padding=0):
2668 def pcfmtstr(max, padding=0):
2663 return basepcfmtstr % (len(str(max)), ' ' * padding)
2669 return basepcfmtstr % (len(str(max)), ' ' * padding)
2664
2670
2665 def pcfmt(value, total):
2671 def pcfmt(value, total):
2666 return (value, 100 * float(value) / total)
2672 return (value, 100 * float(value) / total)
2667
2673
2668 ui.write(('format : %d\n') % format)
2674 ui.write(('format : %d\n') % format)
2669 ui.write(('flags : %s\n') % ', '.join(flags))
2675 ui.write(('flags : %s\n') % ', '.join(flags))
2670
2676
2671 ui.write('\n')
2677 ui.write('\n')
2672 fmt = pcfmtstr(totalsize)
2678 fmt = pcfmtstr(totalsize)
2673 fmt2 = dfmtstr(totalsize)
2679 fmt2 = dfmtstr(totalsize)
2674 ui.write(('revisions : ') + fmt2 % numrevs)
2680 ui.write(('revisions : ') + fmt2 % numrevs)
2675 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2681 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2676 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2682 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2677 ui.write(('revisions : ') + fmt2 % numrevs)
2683 ui.write(('revisions : ') + fmt2 % numrevs)
2678 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2684 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2679 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2685 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2680 ui.write(('revision size : ') + fmt2 % totalsize)
2686 ui.write(('revision size : ') + fmt2 % totalsize)
2681 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2687 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2682 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2688 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2683
2689
2684 ui.write('\n')
2690 ui.write('\n')
2685 fmt = dfmtstr(max(avgchainlen, compratio))
2691 fmt = dfmtstr(max(avgchainlen, compratio))
2686 ui.write(('avg chain length : ') + fmt % avgchainlen)
2692 ui.write(('avg chain length : ') + fmt % avgchainlen)
2687 ui.write(('compression ratio : ') + fmt % compratio)
2693 ui.write(('compression ratio : ') + fmt % compratio)
2688
2694
2689 if format > 0:
2695 if format > 0:
2690 ui.write('\n')
2696 ui.write('\n')
2691 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2697 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2692 % tuple(datasize))
2698 % tuple(datasize))
2693 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2699 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2694 % tuple(fullsize))
2700 % tuple(fullsize))
2695 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2701 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2696 % tuple(deltasize))
2702 % tuple(deltasize))
2697
2703
2698 if numdeltas > 0:
2704 if numdeltas > 0:
2699 ui.write('\n')
2705 ui.write('\n')
2700 fmt = pcfmtstr(numdeltas)
2706 fmt = pcfmtstr(numdeltas)
2701 fmt2 = pcfmtstr(numdeltas, 4)
2707 fmt2 = pcfmtstr(numdeltas, 4)
2702 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2708 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2703 if numprev > 0:
2709 if numprev > 0:
2704 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2710 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2705 numprev))
2711 numprev))
2706 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2712 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2707 numprev))
2713 numprev))
2708 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2714 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2709 numprev))
2715 numprev))
2710 if gdelta:
2716 if gdelta:
2711 ui.write(('deltas against p1 : ')
2717 ui.write(('deltas against p1 : ')
2712 + fmt % pcfmt(nump1, numdeltas))
2718 + fmt % pcfmt(nump1, numdeltas))
2713 ui.write(('deltas against p2 : ')
2719 ui.write(('deltas against p2 : ')
2714 + fmt % pcfmt(nump2, numdeltas))
2720 + fmt % pcfmt(nump2, numdeltas))
2715 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2721 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2716 numdeltas))
2722 numdeltas))
2717
2723
2718 @command('debugrevspec',
2724 @command('debugrevspec',
2719 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2725 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2720 ('REVSPEC'))
2726 ('REVSPEC'))
2721 def debugrevspec(ui, repo, expr, **opts):
2727 def debugrevspec(ui, repo, expr, **opts):
2722 """parse and apply a revision specification
2728 """parse and apply a revision specification
2723
2729
2724 Use --verbose to print the parsed tree before and after aliases
2730 Use --verbose to print the parsed tree before and after aliases
2725 expansion.
2731 expansion.
2726 """
2732 """
2727 if ui.verbose:
2733 if ui.verbose:
2728 tree = revset.parse(expr)[0]
2734 tree = revset.parse(expr)[0]
2729 ui.note(revset.prettyformat(tree), "\n")
2735 ui.note(revset.prettyformat(tree), "\n")
2730 newtree = revset.findaliases(ui, tree)
2736 newtree = revset.findaliases(ui, tree)
2731 if newtree != tree:
2737 if newtree != tree:
2732 ui.note(revset.prettyformat(newtree), "\n")
2738 ui.note(revset.prettyformat(newtree), "\n")
2733 if opts["optimize"]:
2739 if opts["optimize"]:
2734 weight, optimizedtree = revset.optimize(newtree, True)
2740 weight, optimizedtree = revset.optimize(newtree, True)
2735 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2741 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2736 func = revset.match(ui, expr)
2742 func = revset.match(ui, expr)
2737 for c in func(repo, revset.spanset(repo)):
2743 for c in func(repo, revset.spanset(repo)):
2738 ui.write("%s\n" % c)
2744 ui.write("%s\n" % c)
2739
2745
2740 @command('debugsetparents', [], _('REV1 [REV2]'))
2746 @command('debugsetparents', [], _('REV1 [REV2]'))
2741 def debugsetparents(ui, repo, rev1, rev2=None):
2747 def debugsetparents(ui, repo, rev1, rev2=None):
2742 """manually set the parents of the current working directory
2748 """manually set the parents of the current working directory
2743
2749
2744 This is useful for writing repository conversion tools, but should
2750 This is useful for writing repository conversion tools, but should
2745 be used with care.
2751 be used with care.
2746
2752
2747 Returns 0 on success.
2753 Returns 0 on success.
2748 """
2754 """
2749
2755
2750 r1 = scmutil.revsingle(repo, rev1).node()
2756 r1 = scmutil.revsingle(repo, rev1).node()
2751 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2757 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2752
2758
2753 wlock = repo.wlock()
2759 wlock = repo.wlock()
2754 try:
2760 try:
2755 repo.dirstate.beginparentchange()
2761 repo.dirstate.beginparentchange()
2756 repo.setparents(r1, r2)
2762 repo.setparents(r1, r2)
2757 repo.dirstate.endparentchange()
2763 repo.dirstate.endparentchange()
2758 finally:
2764 finally:
2759 wlock.release()
2765 wlock.release()
2760
2766
2761 @command('debugdirstate|debugstate',
2767 @command('debugdirstate|debugstate',
2762 [('', 'nodates', None, _('do not display the saved mtime')),
2768 [('', 'nodates', None, _('do not display the saved mtime')),
2763 ('', 'datesort', None, _('sort by saved mtime'))],
2769 ('', 'datesort', None, _('sort by saved mtime'))],
2764 _('[OPTION]...'))
2770 _('[OPTION]...'))
2765 def debugstate(ui, repo, nodates=None, datesort=None):
2771 def debugstate(ui, repo, nodates=None, datesort=None):
2766 """show the contents of the current dirstate"""
2772 """show the contents of the current dirstate"""
2767 timestr = ""
2773 timestr = ""
2768 showdate = not nodates
2774 showdate = not nodates
2769 if datesort:
2775 if datesort:
2770 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2776 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2771 else:
2777 else:
2772 keyfunc = None # sort by filename
2778 keyfunc = None # sort by filename
2773 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2779 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2774 if showdate:
2780 if showdate:
2775 if ent[3] == -1:
2781 if ent[3] == -1:
2776 # Pad or slice to locale representation
2782 # Pad or slice to locale representation
2777 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2783 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2778 time.localtime(0)))
2784 time.localtime(0)))
2779 timestr = 'unset'
2785 timestr = 'unset'
2780 timestr = (timestr[:locale_len] +
2786 timestr = (timestr[:locale_len] +
2781 ' ' * (locale_len - len(timestr)))
2787 ' ' * (locale_len - len(timestr)))
2782 else:
2788 else:
2783 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2789 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2784 time.localtime(ent[3]))
2790 time.localtime(ent[3]))
2785 if ent[1] & 020000:
2791 if ent[1] & 020000:
2786 mode = 'lnk'
2792 mode = 'lnk'
2787 else:
2793 else:
2788 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2794 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2789 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2795 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2790 for f in repo.dirstate.copies():
2796 for f in repo.dirstate.copies():
2791 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2797 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2792
2798
2793 @command('debugsub',
2799 @command('debugsub',
2794 [('r', 'rev', '',
2800 [('r', 'rev', '',
2795 _('revision to check'), _('REV'))],
2801 _('revision to check'), _('REV'))],
2796 _('[-r REV] [REV]'))
2802 _('[-r REV] [REV]'))
2797 def debugsub(ui, repo, rev=None):
2803 def debugsub(ui, repo, rev=None):
2798 ctx = scmutil.revsingle(repo, rev, None)
2804 ctx = scmutil.revsingle(repo, rev, None)
2799 for k, v in sorted(ctx.substate.items()):
2805 for k, v in sorted(ctx.substate.items()):
2800 ui.write(('path %s\n') % k)
2806 ui.write(('path %s\n') % k)
2801 ui.write((' source %s\n') % v[0])
2807 ui.write((' source %s\n') % v[0])
2802 ui.write((' revision %s\n') % v[1])
2808 ui.write((' revision %s\n') % v[1])
2803
2809
2804 @command('debugsuccessorssets',
2810 @command('debugsuccessorssets',
2805 [],
2811 [],
2806 _('[REV]'))
2812 _('[REV]'))
2807 def debugsuccessorssets(ui, repo, *revs):
2813 def debugsuccessorssets(ui, repo, *revs):
2808 """show set of successors for revision
2814 """show set of successors for revision
2809
2815
2810 A successors set of changeset A is a consistent group of revisions that
2816 A successors set of changeset A is a consistent group of revisions that
2811 succeed A. It contains non-obsolete changesets only.
2817 succeed A. It contains non-obsolete changesets only.
2812
2818
2813 In most cases a changeset A has a single successors set containing a single
2819 In most cases a changeset A has a single successors set containing a single
2814 successor (changeset A replaced by A').
2820 successor (changeset A replaced by A').
2815
2821
2816 A changeset that is made obsolete with no successors are called "pruned".
2822 A changeset that is made obsolete with no successors are called "pruned".
2817 Such changesets have no successors sets at all.
2823 Such changesets have no successors sets at all.
2818
2824
2819 A changeset that has been "split" will have a successors set containing
2825 A changeset that has been "split" will have a successors set containing
2820 more than one successor.
2826 more than one successor.
2821
2827
2822 A changeset that has been rewritten in multiple different ways is called
2828 A changeset that has been rewritten in multiple different ways is called
2823 "divergent". Such changesets have multiple successor sets (each of which
2829 "divergent". Such changesets have multiple successor sets (each of which
2824 may also be split, i.e. have multiple successors).
2830 may also be split, i.e. have multiple successors).
2825
2831
2826 Results are displayed as follows::
2832 Results are displayed as follows::
2827
2833
2828 <rev1>
2834 <rev1>
2829 <successors-1A>
2835 <successors-1A>
2830 <rev2>
2836 <rev2>
2831 <successors-2A>
2837 <successors-2A>
2832 <successors-2B1> <successors-2B2> <successors-2B3>
2838 <successors-2B1> <successors-2B2> <successors-2B3>
2833
2839
2834 Here rev2 has two possible (i.e. divergent) successors sets. The first
2840 Here rev2 has two possible (i.e. divergent) successors sets. The first
2835 holds one element, whereas the second holds three (i.e. the changeset has
2841 holds one element, whereas the second holds three (i.e. the changeset has
2836 been split).
2842 been split).
2837 """
2843 """
2838 # passed to successorssets caching computation from one call to another
2844 # passed to successorssets caching computation from one call to another
2839 cache = {}
2845 cache = {}
2840 ctx2str = str
2846 ctx2str = str
2841 node2str = short
2847 node2str = short
2842 if ui.debug():
2848 if ui.debug():
2843 def ctx2str(ctx):
2849 def ctx2str(ctx):
2844 return ctx.hex()
2850 return ctx.hex()
2845 node2str = hex
2851 node2str = hex
2846 for rev in scmutil.revrange(repo, revs):
2852 for rev in scmutil.revrange(repo, revs):
2847 ctx = repo[rev]
2853 ctx = repo[rev]
2848 ui.write('%s\n'% ctx2str(ctx))
2854 ui.write('%s\n'% ctx2str(ctx))
2849 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2855 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2850 if succsset:
2856 if succsset:
2851 ui.write(' ')
2857 ui.write(' ')
2852 ui.write(node2str(succsset[0]))
2858 ui.write(node2str(succsset[0]))
2853 for node in succsset[1:]:
2859 for node in succsset[1:]:
2854 ui.write(' ')
2860 ui.write(' ')
2855 ui.write(node2str(node))
2861 ui.write(node2str(node))
2856 ui.write('\n')
2862 ui.write('\n')
2857
2863
2858 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2864 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2859 def debugwalk(ui, repo, *pats, **opts):
2865 def debugwalk(ui, repo, *pats, **opts):
2860 """show how files match on given patterns"""
2866 """show how files match on given patterns"""
2861 m = scmutil.match(repo[None], pats, opts)
2867 m = scmutil.match(repo[None], pats, opts)
2862 items = list(repo.walk(m))
2868 items = list(repo.walk(m))
2863 if not items:
2869 if not items:
2864 return
2870 return
2865 f = lambda fn: fn
2871 f = lambda fn: fn
2866 if ui.configbool('ui', 'slash') and os.sep != '/':
2872 if ui.configbool('ui', 'slash') and os.sep != '/':
2867 f = lambda fn: util.normpath(fn)
2873 f = lambda fn: util.normpath(fn)
2868 fmt = 'f %%-%ds %%-%ds %%s' % (
2874 fmt = 'f %%-%ds %%-%ds %%s' % (
2869 max([len(abs) for abs in items]),
2875 max([len(abs) for abs in items]),
2870 max([len(m.rel(abs)) for abs in items]))
2876 max([len(m.rel(abs)) for abs in items]))
2871 for abs in items:
2877 for abs in items:
2872 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2878 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2873 ui.write("%s\n" % line.rstrip())
2879 ui.write("%s\n" % line.rstrip())
2874
2880
2875 @command('debugwireargs',
2881 @command('debugwireargs',
2876 [('', 'three', '', 'three'),
2882 [('', 'three', '', 'three'),
2877 ('', 'four', '', 'four'),
2883 ('', 'four', '', 'four'),
2878 ('', 'five', '', 'five'),
2884 ('', 'five', '', 'five'),
2879 ] + remoteopts,
2885 ] + remoteopts,
2880 _('REPO [OPTIONS]... [ONE [TWO]]'),
2886 _('REPO [OPTIONS]... [ONE [TWO]]'),
2881 norepo=True)
2887 norepo=True)
2882 def debugwireargs(ui, repopath, *vals, **opts):
2888 def debugwireargs(ui, repopath, *vals, **opts):
2883 repo = hg.peer(ui, opts, repopath)
2889 repo = hg.peer(ui, opts, repopath)
2884 for opt in remoteopts:
2890 for opt in remoteopts:
2885 del opts[opt[1]]
2891 del opts[opt[1]]
2886 args = {}
2892 args = {}
2887 for k, v in opts.iteritems():
2893 for k, v in opts.iteritems():
2888 if v:
2894 if v:
2889 args[k] = v
2895 args[k] = v
2890 # run twice to check that we don't mess up the stream for the next command
2896 # run twice to check that we don't mess up the stream for the next command
2891 res1 = repo.debugwireargs(*vals, **args)
2897 res1 = repo.debugwireargs(*vals, **args)
2892 res2 = repo.debugwireargs(*vals, **args)
2898 res2 = repo.debugwireargs(*vals, **args)
2893 ui.write("%s\n" % res1)
2899 ui.write("%s\n" % res1)
2894 if res1 != res2:
2900 if res1 != res2:
2895 ui.warn("%s\n" % res2)
2901 ui.warn("%s\n" % res2)
2896
2902
2897 @command('^diff',
2903 @command('^diff',
2898 [('r', 'rev', [], _('revision'), _('REV')),
2904 [('r', 'rev', [], _('revision'), _('REV')),
2899 ('c', 'change', '', _('change made by revision'), _('REV'))
2905 ('c', 'change', '', _('change made by revision'), _('REV'))
2900 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2906 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2901 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2907 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2902 inferrepo=True)
2908 inferrepo=True)
2903 def diff(ui, repo, *pats, **opts):
2909 def diff(ui, repo, *pats, **opts):
2904 """diff repository (or selected files)
2910 """diff repository (or selected files)
2905
2911
2906 Show differences between revisions for the specified files.
2912 Show differences between revisions for the specified files.
2907
2913
2908 Differences between files are shown using the unified diff format.
2914 Differences between files are shown using the unified diff format.
2909
2915
2910 .. note::
2916 .. note::
2911
2917
2912 diff may generate unexpected results for merges, as it will
2918 diff may generate unexpected results for merges, as it will
2913 default to comparing against the working directory's first
2919 default to comparing against the working directory's first
2914 parent changeset if no revisions are specified.
2920 parent changeset if no revisions are specified.
2915
2921
2916 When two revision arguments are given, then changes are shown
2922 When two revision arguments are given, then changes are shown
2917 between those revisions. If only one revision is specified then
2923 between those revisions. If only one revision is specified then
2918 that revision is compared to the working directory, and, when no
2924 that revision is compared to the working directory, and, when no
2919 revisions are specified, the working directory files are compared
2925 revisions are specified, the working directory files are compared
2920 to its parent.
2926 to its parent.
2921
2927
2922 Alternatively you can specify -c/--change with a revision to see
2928 Alternatively you can specify -c/--change with a revision to see
2923 the changes in that changeset relative to its first parent.
2929 the changes in that changeset relative to its first parent.
2924
2930
2925 Without the -a/--text option, diff will avoid generating diffs of
2931 Without the -a/--text option, diff will avoid generating diffs of
2926 files it detects as binary. With -a, diff will generate a diff
2932 files it detects as binary. With -a, diff will generate a diff
2927 anyway, probably with undesirable results.
2933 anyway, probably with undesirable results.
2928
2934
2929 Use the -g/--git option to generate diffs in the git extended diff
2935 Use the -g/--git option to generate diffs in the git extended diff
2930 format. For more information, read :hg:`help diffs`.
2936 format. For more information, read :hg:`help diffs`.
2931
2937
2932 .. container:: verbose
2938 .. container:: verbose
2933
2939
2934 Examples:
2940 Examples:
2935
2941
2936 - compare a file in the current working directory to its parent::
2942 - compare a file in the current working directory to its parent::
2937
2943
2938 hg diff foo.c
2944 hg diff foo.c
2939
2945
2940 - compare two historical versions of a directory, with rename info::
2946 - compare two historical versions of a directory, with rename info::
2941
2947
2942 hg diff --git -r 1.0:1.2 lib/
2948 hg diff --git -r 1.0:1.2 lib/
2943
2949
2944 - get change stats relative to the last change on some date::
2950 - get change stats relative to the last change on some date::
2945
2951
2946 hg diff --stat -r "date('may 2')"
2952 hg diff --stat -r "date('may 2')"
2947
2953
2948 - diff all newly-added files that contain a keyword::
2954 - diff all newly-added files that contain a keyword::
2949
2955
2950 hg diff "set:added() and grep(GNU)"
2956 hg diff "set:added() and grep(GNU)"
2951
2957
2952 - compare a revision and its parents::
2958 - compare a revision and its parents::
2953
2959
2954 hg diff -c 9353 # compare against first parent
2960 hg diff -c 9353 # compare against first parent
2955 hg diff -r 9353^:9353 # same using revset syntax
2961 hg diff -r 9353^:9353 # same using revset syntax
2956 hg diff -r 9353^2:9353 # compare against the second parent
2962 hg diff -r 9353^2:9353 # compare against the second parent
2957
2963
2958 Returns 0 on success.
2964 Returns 0 on success.
2959 """
2965 """
2960
2966
2961 revs = opts.get('rev')
2967 revs = opts.get('rev')
2962 change = opts.get('change')
2968 change = opts.get('change')
2963 stat = opts.get('stat')
2969 stat = opts.get('stat')
2964 reverse = opts.get('reverse')
2970 reverse = opts.get('reverse')
2965
2971
2966 if revs and change:
2972 if revs and change:
2967 msg = _('cannot specify --rev and --change at the same time')
2973 msg = _('cannot specify --rev and --change at the same time')
2968 raise util.Abort(msg)
2974 raise util.Abort(msg)
2969 elif change:
2975 elif change:
2970 node2 = scmutil.revsingle(repo, change, None).node()
2976 node2 = scmutil.revsingle(repo, change, None).node()
2971 node1 = repo[node2].p1().node()
2977 node1 = repo[node2].p1().node()
2972 else:
2978 else:
2973 node1, node2 = scmutil.revpair(repo, revs)
2979 node1, node2 = scmutil.revpair(repo, revs)
2974
2980
2975 if reverse:
2981 if reverse:
2976 node1, node2 = node2, node1
2982 node1, node2 = node2, node1
2977
2983
2978 diffopts = patch.diffopts(ui, opts)
2984 diffopts = patch.diffopts(ui, opts)
2979 m = scmutil.match(repo[node2], pats, opts)
2985 m = scmutil.match(repo[node2], pats, opts)
2980 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2986 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2981 listsubrepos=opts.get('subrepos'))
2987 listsubrepos=opts.get('subrepos'))
2982
2988
2983 @command('^export',
2989 @command('^export',
2984 [('o', 'output', '',
2990 [('o', 'output', '',
2985 _('print output to file with formatted name'), _('FORMAT')),
2991 _('print output to file with formatted name'), _('FORMAT')),
2986 ('', 'switch-parent', None, _('diff against the second parent')),
2992 ('', 'switch-parent', None, _('diff against the second parent')),
2987 ('r', 'rev', [], _('revisions to export'), _('REV')),
2993 ('r', 'rev', [], _('revisions to export'), _('REV')),
2988 ] + diffopts,
2994 ] + diffopts,
2989 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2995 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2990 def export(ui, repo, *changesets, **opts):
2996 def export(ui, repo, *changesets, **opts):
2991 """dump the header and diffs for one or more changesets
2997 """dump the header and diffs for one or more changesets
2992
2998
2993 Print the changeset header and diffs for one or more revisions.
2999 Print the changeset header and diffs for one or more revisions.
2994 If no revision is given, the parent of the working directory is used.
3000 If no revision is given, the parent of the working directory is used.
2995
3001
2996 The information shown in the changeset header is: author, date,
3002 The information shown in the changeset header is: author, date,
2997 branch name (if non-default), changeset hash, parent(s) and commit
3003 branch name (if non-default), changeset hash, parent(s) and commit
2998 comment.
3004 comment.
2999
3005
3000 .. note::
3006 .. note::
3001
3007
3002 export may generate unexpected diff output for merge
3008 export may generate unexpected diff output for merge
3003 changesets, as it will compare the merge changeset against its
3009 changesets, as it will compare the merge changeset against its
3004 first parent only.
3010 first parent only.
3005
3011
3006 Output may be to a file, in which case the name of the file is
3012 Output may be to a file, in which case the name of the file is
3007 given using a format string. The formatting rules are as follows:
3013 given using a format string. The formatting rules are as follows:
3008
3014
3009 :``%%``: literal "%" character
3015 :``%%``: literal "%" character
3010 :``%H``: changeset hash (40 hexadecimal digits)
3016 :``%H``: changeset hash (40 hexadecimal digits)
3011 :``%N``: number of patches being generated
3017 :``%N``: number of patches being generated
3012 :``%R``: changeset revision number
3018 :``%R``: changeset revision number
3013 :``%b``: basename of the exporting repository
3019 :``%b``: basename of the exporting repository
3014 :``%h``: short-form changeset hash (12 hexadecimal digits)
3020 :``%h``: short-form changeset hash (12 hexadecimal digits)
3015 :``%m``: first line of the commit message (only alphanumeric characters)
3021 :``%m``: first line of the commit message (only alphanumeric characters)
3016 :``%n``: zero-padded sequence number, starting at 1
3022 :``%n``: zero-padded sequence number, starting at 1
3017 :``%r``: zero-padded changeset revision number
3023 :``%r``: zero-padded changeset revision number
3018
3024
3019 Without the -a/--text option, export will avoid generating diffs
3025 Without the -a/--text option, export will avoid generating diffs
3020 of files it detects as binary. With -a, export will generate a
3026 of files it detects as binary. With -a, export will generate a
3021 diff anyway, probably with undesirable results.
3027 diff anyway, probably with undesirable results.
3022
3028
3023 Use the -g/--git option to generate diffs in the git extended diff
3029 Use the -g/--git option to generate diffs in the git extended diff
3024 format. See :hg:`help diffs` for more information.
3030 format. See :hg:`help diffs` for more information.
3025
3031
3026 With the --switch-parent option, the diff will be against the
3032 With the --switch-parent option, the diff will be against the
3027 second parent. It can be useful to review a merge.
3033 second parent. It can be useful to review a merge.
3028
3034
3029 .. container:: verbose
3035 .. container:: verbose
3030
3036
3031 Examples:
3037 Examples:
3032
3038
3033 - use export and import to transplant a bugfix to the current
3039 - use export and import to transplant a bugfix to the current
3034 branch::
3040 branch::
3035
3041
3036 hg export -r 9353 | hg import -
3042 hg export -r 9353 | hg import -
3037
3043
3038 - export all the changesets between two revisions to a file with
3044 - export all the changesets between two revisions to a file with
3039 rename information::
3045 rename information::
3040
3046
3041 hg export --git -r 123:150 > changes.txt
3047 hg export --git -r 123:150 > changes.txt
3042
3048
3043 - split outgoing changes into a series of patches with
3049 - split outgoing changes into a series of patches with
3044 descriptive names::
3050 descriptive names::
3045
3051
3046 hg export -r "outgoing()" -o "%n-%m.patch"
3052 hg export -r "outgoing()" -o "%n-%m.patch"
3047
3053
3048 Returns 0 on success.
3054 Returns 0 on success.
3049 """
3055 """
3050 changesets += tuple(opts.get('rev', []))
3056 changesets += tuple(opts.get('rev', []))
3051 if not changesets:
3057 if not changesets:
3052 changesets = ['.']
3058 changesets = ['.']
3053 revs = scmutil.revrange(repo, changesets)
3059 revs = scmutil.revrange(repo, changesets)
3054 if not revs:
3060 if not revs:
3055 raise util.Abort(_("export requires at least one changeset"))
3061 raise util.Abort(_("export requires at least one changeset"))
3056 if len(revs) > 1:
3062 if len(revs) > 1:
3057 ui.note(_('exporting patches:\n'))
3063 ui.note(_('exporting patches:\n'))
3058 else:
3064 else:
3059 ui.note(_('exporting patch:\n'))
3065 ui.note(_('exporting patch:\n'))
3060 cmdutil.export(repo, revs, template=opts.get('output'),
3066 cmdutil.export(repo, revs, template=opts.get('output'),
3061 switch_parent=opts.get('switch_parent'),
3067 switch_parent=opts.get('switch_parent'),
3062 opts=patch.diffopts(ui, opts))
3068 opts=patch.diffopts(ui, opts))
3063
3069
3064 @command('files',
3070 @command('files',
3065 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3071 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3066 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3072 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3067 ] + walkopts,
3073 ] + walkopts + formatteropts,
3068 _('[OPTION]... [PATTERN]...'))
3074 _('[OPTION]... [PATTERN]...'))
3069 def files(ui, repo, *pats, **opts):
3075 def files(ui, repo, *pats, **opts):
3070 """list tracked files
3076 """list tracked files
3071
3077
3072 Print files under Mercurial control in the working directory or
3078 Print files under Mercurial control in the working directory or
3073 specified revision whose names match the given patterns (excluding
3079 specified revision whose names match the given patterns (excluding
3074 removed files).
3080 removed files).
3075
3081
3076 If no patterns are given to match, this command prints the names
3082 If no patterns are given to match, this command prints the names
3077 of all files under Mercurial control in the working copy.
3083 of all files under Mercurial control in the working copy.
3078
3084
3079 .. container:: verbose
3085 .. container:: verbose
3080
3086
3081 Examples:
3087 Examples:
3082
3088
3083 - list all files under the current directory::
3089 - list all files under the current directory::
3084
3090
3085 hg files .
3091 hg files .
3086
3092
3087 - shows sizes and flags for current revision::
3093 - shows sizes and flags for current revision::
3088
3094
3089 hg files -vr .
3095 hg files -vr .
3090
3096
3091 - list all files named README::
3097 - list all files named README::
3092
3098
3093 hg files -I "**/README"
3099 hg files -I "**/README"
3094
3100
3095 - list all binary files::
3101 - list all binary files::
3096
3102
3097 hg files "set:binary()"
3103 hg files "set:binary()"
3098
3104
3099 - find files containing a regular expression:
3105 - find files containing a regular expression:
3100
3106
3101 hg files "set:grep('bob')"
3107 hg files "set:grep('bob')"
3102
3108
3103 - search tracked file contents with xargs and grep::
3109 - search tracked file contents with xargs and grep::
3104
3110
3105 hg files -0 | xargs -0 grep foo
3111 hg files -0 | xargs -0 grep foo
3106
3112
3107 See :hg:'help pattern' and :hg:'help revsets' for more information
3113 See :hg:'help pattern' and :hg:'help revsets' for more information
3108 on specifying file patterns.
3114 on specifying file patterns.
3109
3115
3110 Returns 0 if a match is found, 1 otherwise.
3116 Returns 0 if a match is found, 1 otherwise.
3111
3117
3112 """
3118 """
3113 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3119 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3114 rev = ctx.rev()
3120 rev = ctx.rev()
3115 ret = 1
3121 ret = 1
3116
3122
3117 end = '\n'
3123 end = '\n'
3118 if opts.get('print0'):
3124 if opts.get('print0'):
3119 end = '\0'
3125 end = '\0'
3120 fm = ui.formatter('status', opts)
3126 fm = ui.formatter('status', opts)
3121 fmt = '%s' + end
3127 fmt = '%s' + end
3122
3128
3123 m = scmutil.match(ctx, pats, opts)
3129 m = scmutil.match(ctx, pats, opts)
3124 for f in ctx.walk(m):
3130 for f in ctx.walk(m):
3125 if rev is None and repo.dirstate[f] in 'R?!':
3131 if rev is None and repo.dirstate[f] in 'R?!':
3126 continue
3132 continue
3127 fm.startitem()
3133 fm.startitem()
3128 if ui.verbose:
3134 if ui.verbose:
3129 fc = ctx[f]
3135 fc = ctx[f]
3130 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3136 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3131 fm.data(abspath=f)
3137 fm.data(abspath=f)
3132 fm.write('path', fmt, m.rel(f))
3138 fm.write('path', fmt, m.rel(f))
3133 ret = 0
3139 ret = 0
3134
3140
3135 fm.end()
3141 fm.end()
3136
3142
3137 return ret
3143 return ret
3138
3144
3139 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3145 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3140 def forget(ui, repo, *pats, **opts):
3146 def forget(ui, repo, *pats, **opts):
3141 """forget the specified files on the next commit
3147 """forget the specified files on the next commit
3142
3148
3143 Mark the specified files so they will no longer be tracked
3149 Mark the specified files so they will no longer be tracked
3144 after the next commit.
3150 after the next commit.
3145
3151
3146 This only removes files from the current branch, not from the
3152 This only removes files from the current branch, not from the
3147 entire project history, and it does not delete them from the
3153 entire project history, and it does not delete them from the
3148 working directory.
3154 working directory.
3149
3155
3150 To undo a forget before the next commit, see :hg:`add`.
3156 To undo a forget before the next commit, see :hg:`add`.
3151
3157
3152 .. container:: verbose
3158 .. container:: verbose
3153
3159
3154 Examples:
3160 Examples:
3155
3161
3156 - forget newly-added binary files::
3162 - forget newly-added binary files::
3157
3163
3158 hg forget "set:added() and binary()"
3164 hg forget "set:added() and binary()"
3159
3165
3160 - forget files that would be excluded by .hgignore::
3166 - forget files that would be excluded by .hgignore::
3161
3167
3162 hg forget "set:hgignore()"
3168 hg forget "set:hgignore()"
3163
3169
3164 Returns 0 on success.
3170 Returns 0 on success.
3165 """
3171 """
3166
3172
3167 if not pats:
3173 if not pats:
3168 raise util.Abort(_('no files specified'))
3174 raise util.Abort(_('no files specified'))
3169
3175
3170 m = scmutil.match(repo[None], pats, opts)
3176 m = scmutil.match(repo[None], pats, opts)
3171 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3177 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3172 return rejected and 1 or 0
3178 return rejected and 1 or 0
3173
3179
3174 @command(
3180 @command(
3175 'graft',
3181 'graft',
3176 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3182 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3177 ('c', 'continue', False, _('resume interrupted graft')),
3183 ('c', 'continue', False, _('resume interrupted graft')),
3178 ('e', 'edit', False, _('invoke editor on commit messages')),
3184 ('e', 'edit', False, _('invoke editor on commit messages')),
3179 ('', 'log', None, _('append graft info to log message')),
3185 ('', 'log', None, _('append graft info to log message')),
3180 ('f', 'force', False, _('force graft')),
3186 ('f', 'force', False, _('force graft')),
3181 ('D', 'currentdate', False,
3187 ('D', 'currentdate', False,
3182 _('record the current date as commit date')),
3188 _('record the current date as commit date')),
3183 ('U', 'currentuser', False,
3189 ('U', 'currentuser', False,
3184 _('record the current user as committer'), _('DATE'))]
3190 _('record the current user as committer'), _('DATE'))]
3185 + commitopts2 + mergetoolopts + dryrunopts,
3191 + commitopts2 + mergetoolopts + dryrunopts,
3186 _('[OPTION]... [-r] REV...'))
3192 _('[OPTION]... [-r] REV...'))
3187 def graft(ui, repo, *revs, **opts):
3193 def graft(ui, repo, *revs, **opts):
3188 '''copy changes from other branches onto the current branch
3194 '''copy changes from other branches onto the current branch
3189
3195
3190 This command uses Mercurial's merge logic to copy individual
3196 This command uses Mercurial's merge logic to copy individual
3191 changes from other branches without merging branches in the
3197 changes from other branches without merging branches in the
3192 history graph. This is sometimes known as 'backporting' or
3198 history graph. This is sometimes known as 'backporting' or
3193 'cherry-picking'. By default, graft will copy user, date, and
3199 'cherry-picking'. By default, graft will copy user, date, and
3194 description from the source changesets.
3200 description from the source changesets.
3195
3201
3196 Changesets that are ancestors of the current revision, that have
3202 Changesets that are ancestors of the current revision, that have
3197 already been grafted, or that are merges will be skipped.
3203 already been grafted, or that are merges will be skipped.
3198
3204
3199 If --log is specified, log messages will have a comment appended
3205 If --log is specified, log messages will have a comment appended
3200 of the form::
3206 of the form::
3201
3207
3202 (grafted from CHANGESETHASH)
3208 (grafted from CHANGESETHASH)
3203
3209
3204 If --force is specified, revisions will be grafted even if they
3210 If --force is specified, revisions will be grafted even if they
3205 are already ancestors of or have been grafted to the destination.
3211 are already ancestors of or have been grafted to the destination.
3206 This is useful when the revisions have since been backed out.
3212 This is useful when the revisions have since been backed out.
3207
3213
3208 If a graft merge results in conflicts, the graft process is
3214 If a graft merge results in conflicts, the graft process is
3209 interrupted so that the current merge can be manually resolved.
3215 interrupted so that the current merge can be manually resolved.
3210 Once all conflicts are addressed, the graft process can be
3216 Once all conflicts are addressed, the graft process can be
3211 continued with the -c/--continue option.
3217 continued with the -c/--continue option.
3212
3218
3213 .. note::
3219 .. note::
3214
3220
3215 The -c/--continue option does not reapply earlier options, except
3221 The -c/--continue option does not reapply earlier options, except
3216 for --force.
3222 for --force.
3217
3223
3218 .. container:: verbose
3224 .. container:: verbose
3219
3225
3220 Examples:
3226 Examples:
3221
3227
3222 - copy a single change to the stable branch and edit its description::
3228 - copy a single change to the stable branch and edit its description::
3223
3229
3224 hg update stable
3230 hg update stable
3225 hg graft --edit 9393
3231 hg graft --edit 9393
3226
3232
3227 - graft a range of changesets with one exception, updating dates::
3233 - graft a range of changesets with one exception, updating dates::
3228
3234
3229 hg graft -D "2085::2093 and not 2091"
3235 hg graft -D "2085::2093 and not 2091"
3230
3236
3231 - continue a graft after resolving conflicts::
3237 - continue a graft after resolving conflicts::
3232
3238
3233 hg graft -c
3239 hg graft -c
3234
3240
3235 - show the source of a grafted changeset::
3241 - show the source of a grafted changeset::
3236
3242
3237 hg log --debug -r .
3243 hg log --debug -r .
3238
3244
3239 See :hg:`help revisions` and :hg:`help revsets` for more about
3245 See :hg:`help revisions` and :hg:`help revsets` for more about
3240 specifying revisions.
3246 specifying revisions.
3241
3247
3242 Returns 0 on successful completion.
3248 Returns 0 on successful completion.
3243 '''
3249 '''
3244
3250
3245 revs = list(revs)
3251 revs = list(revs)
3246 revs.extend(opts['rev'])
3252 revs.extend(opts['rev'])
3247
3253
3248 if not opts.get('user') and opts.get('currentuser'):
3254 if not opts.get('user') and opts.get('currentuser'):
3249 opts['user'] = ui.username()
3255 opts['user'] = ui.username()
3250 if not opts.get('date') and opts.get('currentdate'):
3256 if not opts.get('date') and opts.get('currentdate'):
3251 opts['date'] = "%d %d" % util.makedate()
3257 opts['date'] = "%d %d" % util.makedate()
3252
3258
3253 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3259 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3254
3260
3255 cont = False
3261 cont = False
3256 if opts['continue']:
3262 if opts['continue']:
3257 cont = True
3263 cont = True
3258 if revs:
3264 if revs:
3259 raise util.Abort(_("can't specify --continue and revisions"))
3265 raise util.Abort(_("can't specify --continue and revisions"))
3260 # read in unfinished revisions
3266 # read in unfinished revisions
3261 try:
3267 try:
3262 nodes = repo.opener.read('graftstate').splitlines()
3268 nodes = repo.opener.read('graftstate').splitlines()
3263 revs = [repo[node].rev() for node in nodes]
3269 revs = [repo[node].rev() for node in nodes]
3264 except IOError, inst:
3270 except IOError, inst:
3265 if inst.errno != errno.ENOENT:
3271 if inst.errno != errno.ENOENT:
3266 raise
3272 raise
3267 raise util.Abort(_("no graft state found, can't continue"))
3273 raise util.Abort(_("no graft state found, can't continue"))
3268 else:
3274 else:
3269 cmdutil.checkunfinished(repo)
3275 cmdutil.checkunfinished(repo)
3270 cmdutil.bailifchanged(repo)
3276 cmdutil.bailifchanged(repo)
3271 if not revs:
3277 if not revs:
3272 raise util.Abort(_('no revisions specified'))
3278 raise util.Abort(_('no revisions specified'))
3273 revs = scmutil.revrange(repo, revs)
3279 revs = scmutil.revrange(repo, revs)
3274
3280
3275 # check for merges
3281 # check for merges
3276 for rev in repo.revs('%ld and merge()', revs):
3282 for rev in repo.revs('%ld and merge()', revs):
3277 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3283 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3278 revs.remove(rev)
3284 revs.remove(rev)
3279 if not revs:
3285 if not revs:
3280 return -1
3286 return -1
3281
3287
3282 # Don't check in the --continue case, in effect retaining --force across
3288 # Don't check in the --continue case, in effect retaining --force across
3283 # --continues. That's because without --force, any revisions we decided to
3289 # --continues. That's because without --force, any revisions we decided to
3284 # skip would have been filtered out here, so they wouldn't have made their
3290 # skip would have been filtered out here, so they wouldn't have made their
3285 # way to the graftstate. With --force, any revisions we would have otherwise
3291 # way to the graftstate. With --force, any revisions we would have otherwise
3286 # skipped would not have been filtered out, and if they hadn't been applied
3292 # skipped would not have been filtered out, and if they hadn't been applied
3287 # already, they'd have been in the graftstate.
3293 # already, they'd have been in the graftstate.
3288 if not (cont or opts.get('force')):
3294 if not (cont or opts.get('force')):
3289 # check for ancestors of dest branch
3295 # check for ancestors of dest branch
3290 crev = repo['.'].rev()
3296 crev = repo['.'].rev()
3291 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3297 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3292 # Cannot use x.remove(y) on smart set, this has to be a list.
3298 # Cannot use x.remove(y) on smart set, this has to be a list.
3293 # XXX make this lazy in the future
3299 # XXX make this lazy in the future
3294 revs = list(revs)
3300 revs = list(revs)
3295 # don't mutate while iterating, create a copy
3301 # don't mutate while iterating, create a copy
3296 for rev in list(revs):
3302 for rev in list(revs):
3297 if rev in ancestors:
3303 if rev in ancestors:
3298 ui.warn(_('skipping ancestor revision %s\n') % rev)
3304 ui.warn(_('skipping ancestor revision %s\n') % rev)
3299 # XXX remove on list is slow
3305 # XXX remove on list is slow
3300 revs.remove(rev)
3306 revs.remove(rev)
3301 if not revs:
3307 if not revs:
3302 return -1
3308 return -1
3303
3309
3304 # analyze revs for earlier grafts
3310 # analyze revs for earlier grafts
3305 ids = {}
3311 ids = {}
3306 for ctx in repo.set("%ld", revs):
3312 for ctx in repo.set("%ld", revs):
3307 ids[ctx.hex()] = ctx.rev()
3313 ids[ctx.hex()] = ctx.rev()
3308 n = ctx.extra().get('source')
3314 n = ctx.extra().get('source')
3309 if n:
3315 if n:
3310 ids[n] = ctx.rev()
3316 ids[n] = ctx.rev()
3311
3317
3312 # check ancestors for earlier grafts
3318 # check ancestors for earlier grafts
3313 ui.debug('scanning for duplicate grafts\n')
3319 ui.debug('scanning for duplicate grafts\n')
3314
3320
3315 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3321 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3316 ctx = repo[rev]
3322 ctx = repo[rev]
3317 n = ctx.extra().get('source')
3323 n = ctx.extra().get('source')
3318 if n in ids:
3324 if n in ids:
3319 try:
3325 try:
3320 r = repo[n].rev()
3326 r = repo[n].rev()
3321 except error.RepoLookupError:
3327 except error.RepoLookupError:
3322 r = None
3328 r = None
3323 if r in revs:
3329 if r in revs:
3324 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3330 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3325 % (r, rev))
3331 % (r, rev))
3326 revs.remove(r)
3332 revs.remove(r)
3327 elif ids[n] in revs:
3333 elif ids[n] in revs:
3328 if r is None:
3334 if r is None:
3329 ui.warn(_('skipping already grafted revision %s '
3335 ui.warn(_('skipping already grafted revision %s '
3330 '(%s also has unknown origin %s)\n')
3336 '(%s also has unknown origin %s)\n')
3331 % (ids[n], rev, n))
3337 % (ids[n], rev, n))
3332 else:
3338 else:
3333 ui.warn(_('skipping already grafted revision %s '
3339 ui.warn(_('skipping already grafted revision %s '
3334 '(%s also has origin %d)\n')
3340 '(%s also has origin %d)\n')
3335 % (ids[n], rev, r))
3341 % (ids[n], rev, r))
3336 revs.remove(ids[n])
3342 revs.remove(ids[n])
3337 elif ctx.hex() in ids:
3343 elif ctx.hex() in ids:
3338 r = ids[ctx.hex()]
3344 r = ids[ctx.hex()]
3339 ui.warn(_('skipping already grafted revision %s '
3345 ui.warn(_('skipping already grafted revision %s '
3340 '(was grafted from %d)\n') % (r, rev))
3346 '(was grafted from %d)\n') % (r, rev))
3341 revs.remove(r)
3347 revs.remove(r)
3342 if not revs:
3348 if not revs:
3343 return -1
3349 return -1
3344
3350
3345 wlock = repo.wlock()
3351 wlock = repo.wlock()
3346 try:
3352 try:
3347 current = repo['.']
3353 current = repo['.']
3348 for pos, ctx in enumerate(repo.set("%ld", revs)):
3354 for pos, ctx in enumerate(repo.set("%ld", revs)):
3349
3355
3350 ui.status(_('grafting revision %s\n') % ctx.rev())
3356 ui.status(_('grafting revision %s\n') % ctx.rev())
3351 if opts.get('dry_run'):
3357 if opts.get('dry_run'):
3352 continue
3358 continue
3353
3359
3354 source = ctx.extra().get('source')
3360 source = ctx.extra().get('source')
3355 if not source:
3361 if not source:
3356 source = ctx.hex()
3362 source = ctx.hex()
3357 extra = {'source': source}
3363 extra = {'source': source}
3358 user = ctx.user()
3364 user = ctx.user()
3359 if opts.get('user'):
3365 if opts.get('user'):
3360 user = opts['user']
3366 user = opts['user']
3361 date = ctx.date()
3367 date = ctx.date()
3362 if opts.get('date'):
3368 if opts.get('date'):
3363 date = opts['date']
3369 date = opts['date']
3364 message = ctx.description()
3370 message = ctx.description()
3365 if opts.get('log'):
3371 if opts.get('log'):
3366 message += '\n(grafted from %s)' % ctx.hex()
3372 message += '\n(grafted from %s)' % ctx.hex()
3367
3373
3368 # we don't merge the first commit when continuing
3374 # we don't merge the first commit when continuing
3369 if not cont:
3375 if not cont:
3370 # perform the graft merge with p1(rev) as 'ancestor'
3376 # perform the graft merge with p1(rev) as 'ancestor'
3371 try:
3377 try:
3372 # ui.forcemerge is an internal variable, do not document
3378 # ui.forcemerge is an internal variable, do not document
3373 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3379 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3374 'graft')
3380 'graft')
3375 stats = mergemod.update(repo, ctx.node(), True, True, False,
3381 stats = mergemod.update(repo, ctx.node(), True, True, False,
3376 ctx.p1().node(),
3382 ctx.p1().node(),
3377 labels=['local', 'graft'])
3383 labels=['local', 'graft'])
3378 finally:
3384 finally:
3379 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3385 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3380 # report any conflicts
3386 # report any conflicts
3381 if stats and stats[3] > 0:
3387 if stats and stats[3] > 0:
3382 # write out state for --continue
3388 # write out state for --continue
3383 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3389 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3384 repo.opener.write('graftstate', ''.join(nodelines))
3390 repo.opener.write('graftstate', ''.join(nodelines))
3385 raise util.Abort(
3391 raise util.Abort(
3386 _("unresolved conflicts, can't continue"),
3392 _("unresolved conflicts, can't continue"),
3387 hint=_('use hg resolve and hg graft --continue'))
3393 hint=_('use hg resolve and hg graft --continue'))
3388 else:
3394 else:
3389 cont = False
3395 cont = False
3390
3396
3391 # drop the second merge parent
3397 # drop the second merge parent
3392 repo.dirstate.beginparentchange()
3398 repo.dirstate.beginparentchange()
3393 repo.setparents(current.node(), nullid)
3399 repo.setparents(current.node(), nullid)
3394 repo.dirstate.write()
3400 repo.dirstate.write()
3395 # fix up dirstate for copies and renames
3401 # fix up dirstate for copies and renames
3396 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3402 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3397 repo.dirstate.endparentchange()
3403 repo.dirstate.endparentchange()
3398
3404
3399 # commit
3405 # commit
3400 node = repo.commit(text=message, user=user,
3406 node = repo.commit(text=message, user=user,
3401 date=date, extra=extra, editor=editor)
3407 date=date, extra=extra, editor=editor)
3402 if node is None:
3408 if node is None:
3403 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3409 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3404 else:
3410 else:
3405 current = repo[node]
3411 current = repo[node]
3406 finally:
3412 finally:
3407 wlock.release()
3413 wlock.release()
3408
3414
3409 # remove state when we complete successfully
3415 # remove state when we complete successfully
3410 if not opts.get('dry_run'):
3416 if not opts.get('dry_run'):
3411 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3417 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3412
3418
3413 return 0
3419 return 0
3414
3420
3415 @command('grep',
3421 @command('grep',
3416 [('0', 'print0', None, _('end fields with NUL')),
3422 [('0', 'print0', None, _('end fields with NUL')),
3417 ('', 'all', None, _('print all revisions that match')),
3423 ('', 'all', None, _('print all revisions that match')),
3418 ('a', 'text', None, _('treat all files as text')),
3424 ('a', 'text', None, _('treat all files as text')),
3419 ('f', 'follow', None,
3425 ('f', 'follow', None,
3420 _('follow changeset history,'
3426 _('follow changeset history,'
3421 ' or file history across copies and renames')),
3427 ' or file history across copies and renames')),
3422 ('i', 'ignore-case', None, _('ignore case when matching')),
3428 ('i', 'ignore-case', None, _('ignore case when matching')),
3423 ('l', 'files-with-matches', None,
3429 ('l', 'files-with-matches', None,
3424 _('print only filenames and revisions that match')),
3430 _('print only filenames and revisions that match')),
3425 ('n', 'line-number', None, _('print matching line numbers')),
3431 ('n', 'line-number', None, _('print matching line numbers')),
3426 ('r', 'rev', [],
3432 ('r', 'rev', [],
3427 _('only search files changed within revision range'), _('REV')),
3433 _('only search files changed within revision range'), _('REV')),
3428 ('u', 'user', None, _('list the author (long with -v)')),
3434 ('u', 'user', None, _('list the author (long with -v)')),
3429 ('d', 'date', None, _('list the date (short with -q)')),
3435 ('d', 'date', None, _('list the date (short with -q)')),
3430 ] + walkopts,
3436 ] + walkopts,
3431 _('[OPTION]... PATTERN [FILE]...'),
3437 _('[OPTION]... PATTERN [FILE]...'),
3432 inferrepo=True)
3438 inferrepo=True)
3433 def grep(ui, repo, pattern, *pats, **opts):
3439 def grep(ui, repo, pattern, *pats, **opts):
3434 """search for a pattern in specified files and revisions
3440 """search for a pattern in specified files and revisions
3435
3441
3436 Search revisions of files for a regular expression.
3442 Search revisions of files for a regular expression.
3437
3443
3438 This command behaves differently than Unix grep. It only accepts
3444 This command behaves differently than Unix grep. It only accepts
3439 Python/Perl regexps. It searches repository history, not the
3445 Python/Perl regexps. It searches repository history, not the
3440 working directory. It always prints the revision number in which a
3446 working directory. It always prints the revision number in which a
3441 match appears.
3447 match appears.
3442
3448
3443 By default, grep only prints output for the first revision of a
3449 By default, grep only prints output for the first revision of a
3444 file in which it finds a match. To get it to print every revision
3450 file in which it finds a match. To get it to print every revision
3445 that contains a change in match status ("-" for a match that
3451 that contains a change in match status ("-" for a match that
3446 becomes a non-match, or "+" for a non-match that becomes a match),
3452 becomes a non-match, or "+" for a non-match that becomes a match),
3447 use the --all flag.
3453 use the --all flag.
3448
3454
3449 Returns 0 if a match is found, 1 otherwise.
3455 Returns 0 if a match is found, 1 otherwise.
3450 """
3456 """
3451 reflags = re.M
3457 reflags = re.M
3452 if opts.get('ignore_case'):
3458 if opts.get('ignore_case'):
3453 reflags |= re.I
3459 reflags |= re.I
3454 try:
3460 try:
3455 regexp = util.re.compile(pattern, reflags)
3461 regexp = util.re.compile(pattern, reflags)
3456 except re.error, inst:
3462 except re.error, inst:
3457 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3463 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3458 return 1
3464 return 1
3459 sep, eol = ':', '\n'
3465 sep, eol = ':', '\n'
3460 if opts.get('print0'):
3466 if opts.get('print0'):
3461 sep = eol = '\0'
3467 sep = eol = '\0'
3462
3468
3463 getfile = util.lrucachefunc(repo.file)
3469 getfile = util.lrucachefunc(repo.file)
3464
3470
3465 def matchlines(body):
3471 def matchlines(body):
3466 begin = 0
3472 begin = 0
3467 linenum = 0
3473 linenum = 0
3468 while begin < len(body):
3474 while begin < len(body):
3469 match = regexp.search(body, begin)
3475 match = regexp.search(body, begin)
3470 if not match:
3476 if not match:
3471 break
3477 break
3472 mstart, mend = match.span()
3478 mstart, mend = match.span()
3473 linenum += body.count('\n', begin, mstart) + 1
3479 linenum += body.count('\n', begin, mstart) + 1
3474 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3480 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3475 begin = body.find('\n', mend) + 1 or len(body) + 1
3481 begin = body.find('\n', mend) + 1 or len(body) + 1
3476 lend = begin - 1
3482 lend = begin - 1
3477 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3483 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3478
3484
3479 class linestate(object):
3485 class linestate(object):
3480 def __init__(self, line, linenum, colstart, colend):
3486 def __init__(self, line, linenum, colstart, colend):
3481 self.line = line
3487 self.line = line
3482 self.linenum = linenum
3488 self.linenum = linenum
3483 self.colstart = colstart
3489 self.colstart = colstart
3484 self.colend = colend
3490 self.colend = colend
3485
3491
3486 def __hash__(self):
3492 def __hash__(self):
3487 return hash((self.linenum, self.line))
3493 return hash((self.linenum, self.line))
3488
3494
3489 def __eq__(self, other):
3495 def __eq__(self, other):
3490 return self.line == other.line
3496 return self.line == other.line
3491
3497
3492 def __iter__(self):
3498 def __iter__(self):
3493 yield (self.line[:self.colstart], '')
3499 yield (self.line[:self.colstart], '')
3494 yield (self.line[self.colstart:self.colend], 'grep.match')
3500 yield (self.line[self.colstart:self.colend], 'grep.match')
3495 rest = self.line[self.colend:]
3501 rest = self.line[self.colend:]
3496 while rest != '':
3502 while rest != '':
3497 match = regexp.search(rest)
3503 match = regexp.search(rest)
3498 if not match:
3504 if not match:
3499 yield (rest, '')
3505 yield (rest, '')
3500 break
3506 break
3501 mstart, mend = match.span()
3507 mstart, mend = match.span()
3502 yield (rest[:mstart], '')
3508 yield (rest[:mstart], '')
3503 yield (rest[mstart:mend], 'grep.match')
3509 yield (rest[mstart:mend], 'grep.match')
3504 rest = rest[mend:]
3510 rest = rest[mend:]
3505
3511
3506 matches = {}
3512 matches = {}
3507 copies = {}
3513 copies = {}
3508 def grepbody(fn, rev, body):
3514 def grepbody(fn, rev, body):
3509 matches[rev].setdefault(fn, [])
3515 matches[rev].setdefault(fn, [])
3510 m = matches[rev][fn]
3516 m = matches[rev][fn]
3511 for lnum, cstart, cend, line in matchlines(body):
3517 for lnum, cstart, cend, line in matchlines(body):
3512 s = linestate(line, lnum, cstart, cend)
3518 s = linestate(line, lnum, cstart, cend)
3513 m.append(s)
3519 m.append(s)
3514
3520
3515 def difflinestates(a, b):
3521 def difflinestates(a, b):
3516 sm = difflib.SequenceMatcher(None, a, b)
3522 sm = difflib.SequenceMatcher(None, a, b)
3517 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3523 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3518 if tag == 'insert':
3524 if tag == 'insert':
3519 for i in xrange(blo, bhi):
3525 for i in xrange(blo, bhi):
3520 yield ('+', b[i])
3526 yield ('+', b[i])
3521 elif tag == 'delete':
3527 elif tag == 'delete':
3522 for i in xrange(alo, ahi):
3528 for i in xrange(alo, ahi):
3523 yield ('-', a[i])
3529 yield ('-', a[i])
3524 elif tag == 'replace':
3530 elif tag == 'replace':
3525 for i in xrange(alo, ahi):
3531 for i in xrange(alo, ahi):
3526 yield ('-', a[i])
3532 yield ('-', a[i])
3527 for i in xrange(blo, bhi):
3533 for i in xrange(blo, bhi):
3528 yield ('+', b[i])
3534 yield ('+', b[i])
3529
3535
3530 def display(fn, ctx, pstates, states):
3536 def display(fn, ctx, pstates, states):
3531 rev = ctx.rev()
3537 rev = ctx.rev()
3532 datefunc = ui.quiet and util.shortdate or util.datestr
3538 datefunc = ui.quiet and util.shortdate or util.datestr
3533 found = False
3539 found = False
3534 @util.cachefunc
3540 @util.cachefunc
3535 def binary():
3541 def binary():
3536 flog = getfile(fn)
3542 flog = getfile(fn)
3537 return util.binary(flog.read(ctx.filenode(fn)))
3543 return util.binary(flog.read(ctx.filenode(fn)))
3538
3544
3539 if opts.get('all'):
3545 if opts.get('all'):
3540 iter = difflinestates(pstates, states)
3546 iter = difflinestates(pstates, states)
3541 else:
3547 else:
3542 iter = [('', l) for l in states]
3548 iter = [('', l) for l in states]
3543 for change, l in iter:
3549 for change, l in iter:
3544 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3550 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3545
3551
3546 if opts.get('line_number'):
3552 if opts.get('line_number'):
3547 cols.append((str(l.linenum), 'grep.linenumber'))
3553 cols.append((str(l.linenum), 'grep.linenumber'))
3548 if opts.get('all'):
3554 if opts.get('all'):
3549 cols.append((change, 'grep.change'))
3555 cols.append((change, 'grep.change'))
3550 if opts.get('user'):
3556 if opts.get('user'):
3551 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3557 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3552 if opts.get('date'):
3558 if opts.get('date'):
3553 cols.append((datefunc(ctx.date()), 'grep.date'))
3559 cols.append((datefunc(ctx.date()), 'grep.date'))
3554 for col, label in cols[:-1]:
3560 for col, label in cols[:-1]:
3555 ui.write(col, label=label)
3561 ui.write(col, label=label)
3556 ui.write(sep, label='grep.sep')
3562 ui.write(sep, label='grep.sep')
3557 ui.write(cols[-1][0], label=cols[-1][1])
3563 ui.write(cols[-1][0], label=cols[-1][1])
3558 if not opts.get('files_with_matches'):
3564 if not opts.get('files_with_matches'):
3559 ui.write(sep, label='grep.sep')
3565 ui.write(sep, label='grep.sep')
3560 if not opts.get('text') and binary():
3566 if not opts.get('text') and binary():
3561 ui.write(" Binary file matches")
3567 ui.write(" Binary file matches")
3562 else:
3568 else:
3563 for s, label in l:
3569 for s, label in l:
3564 ui.write(s, label=label)
3570 ui.write(s, label=label)
3565 ui.write(eol)
3571 ui.write(eol)
3566 found = True
3572 found = True
3567 if opts.get('files_with_matches'):
3573 if opts.get('files_with_matches'):
3568 break
3574 break
3569 return found
3575 return found
3570
3576
3571 skip = {}
3577 skip = {}
3572 revfiles = {}
3578 revfiles = {}
3573 matchfn = scmutil.match(repo[None], pats, opts)
3579 matchfn = scmutil.match(repo[None], pats, opts)
3574 found = False
3580 found = False
3575 follow = opts.get('follow')
3581 follow = opts.get('follow')
3576
3582
3577 def prep(ctx, fns):
3583 def prep(ctx, fns):
3578 rev = ctx.rev()
3584 rev = ctx.rev()
3579 pctx = ctx.p1()
3585 pctx = ctx.p1()
3580 parent = pctx.rev()
3586 parent = pctx.rev()
3581 matches.setdefault(rev, {})
3587 matches.setdefault(rev, {})
3582 matches.setdefault(parent, {})
3588 matches.setdefault(parent, {})
3583 files = revfiles.setdefault(rev, [])
3589 files = revfiles.setdefault(rev, [])
3584 for fn in fns:
3590 for fn in fns:
3585 flog = getfile(fn)
3591 flog = getfile(fn)
3586 try:
3592 try:
3587 fnode = ctx.filenode(fn)
3593 fnode = ctx.filenode(fn)
3588 except error.LookupError:
3594 except error.LookupError:
3589 continue
3595 continue
3590
3596
3591 copied = flog.renamed(fnode)
3597 copied = flog.renamed(fnode)
3592 copy = follow and copied and copied[0]
3598 copy = follow and copied and copied[0]
3593 if copy:
3599 if copy:
3594 copies.setdefault(rev, {})[fn] = copy
3600 copies.setdefault(rev, {})[fn] = copy
3595 if fn in skip:
3601 if fn in skip:
3596 if copy:
3602 if copy:
3597 skip[copy] = True
3603 skip[copy] = True
3598 continue
3604 continue
3599 files.append(fn)
3605 files.append(fn)
3600
3606
3601 if fn not in matches[rev]:
3607 if fn not in matches[rev]:
3602 grepbody(fn, rev, flog.read(fnode))
3608 grepbody(fn, rev, flog.read(fnode))
3603
3609
3604 pfn = copy or fn
3610 pfn = copy or fn
3605 if pfn not in matches[parent]:
3611 if pfn not in matches[parent]:
3606 try:
3612 try:
3607 fnode = pctx.filenode(pfn)
3613 fnode = pctx.filenode(pfn)
3608 grepbody(pfn, parent, flog.read(fnode))
3614 grepbody(pfn, parent, flog.read(fnode))
3609 except error.LookupError:
3615 except error.LookupError:
3610 pass
3616 pass
3611
3617
3612 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3618 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3613 rev = ctx.rev()
3619 rev = ctx.rev()
3614 parent = ctx.p1().rev()
3620 parent = ctx.p1().rev()
3615 for fn in sorted(revfiles.get(rev, [])):
3621 for fn in sorted(revfiles.get(rev, [])):
3616 states = matches[rev][fn]
3622 states = matches[rev][fn]
3617 copy = copies.get(rev, {}).get(fn)
3623 copy = copies.get(rev, {}).get(fn)
3618 if fn in skip:
3624 if fn in skip:
3619 if copy:
3625 if copy:
3620 skip[copy] = True
3626 skip[copy] = True
3621 continue
3627 continue
3622 pstates = matches.get(parent, {}).get(copy or fn, [])
3628 pstates = matches.get(parent, {}).get(copy or fn, [])
3623 if pstates or states:
3629 if pstates or states:
3624 r = display(fn, ctx, pstates, states)
3630 r = display(fn, ctx, pstates, states)
3625 found = found or r
3631 found = found or r
3626 if r and not opts.get('all'):
3632 if r and not opts.get('all'):
3627 skip[fn] = True
3633 skip[fn] = True
3628 if copy:
3634 if copy:
3629 skip[copy] = True
3635 skip[copy] = True
3630 del matches[rev]
3636 del matches[rev]
3631 del revfiles[rev]
3637 del revfiles[rev]
3632
3638
3633 return not found
3639 return not found
3634
3640
3635 @command('heads',
3641 @command('heads',
3636 [('r', 'rev', '',
3642 [('r', 'rev', '',
3637 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3643 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3638 ('t', 'topo', False, _('show topological heads only')),
3644 ('t', 'topo', False, _('show topological heads only')),
3639 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3645 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3640 ('c', 'closed', False, _('show normal and closed branch heads')),
3646 ('c', 'closed', False, _('show normal and closed branch heads')),
3641 ] + templateopts,
3647 ] + templateopts,
3642 _('[-ct] [-r STARTREV] [REV]...'))
3648 _('[-ct] [-r STARTREV] [REV]...'))
3643 def heads(ui, repo, *branchrevs, **opts):
3649 def heads(ui, repo, *branchrevs, **opts):
3644 """show branch heads
3650 """show branch heads
3645
3651
3646 With no arguments, show all open branch heads in the repository.
3652 With no arguments, show all open branch heads in the repository.
3647 Branch heads are changesets that have no descendants on the
3653 Branch heads are changesets that have no descendants on the
3648 same branch. They are where development generally takes place and
3654 same branch. They are where development generally takes place and
3649 are the usual targets for update and merge operations.
3655 are the usual targets for update and merge operations.
3650
3656
3651 If one or more REVs are given, only open branch heads on the
3657 If one or more REVs are given, only open branch heads on the
3652 branches associated with the specified changesets are shown. This
3658 branches associated with the specified changesets are shown. This
3653 means that you can use :hg:`heads .` to see the heads on the
3659 means that you can use :hg:`heads .` to see the heads on the
3654 currently checked-out branch.
3660 currently checked-out branch.
3655
3661
3656 If -c/--closed is specified, also show branch heads marked closed
3662 If -c/--closed is specified, also show branch heads marked closed
3657 (see :hg:`commit --close-branch`).
3663 (see :hg:`commit --close-branch`).
3658
3664
3659 If STARTREV is specified, only those heads that are descendants of
3665 If STARTREV is specified, only those heads that are descendants of
3660 STARTREV will be displayed.
3666 STARTREV will be displayed.
3661
3667
3662 If -t/--topo is specified, named branch mechanics will be ignored and only
3668 If -t/--topo is specified, named branch mechanics will be ignored and only
3663 topological heads (changesets with no children) will be shown.
3669 topological heads (changesets with no children) will be shown.
3664
3670
3665 Returns 0 if matching heads are found, 1 if not.
3671 Returns 0 if matching heads are found, 1 if not.
3666 """
3672 """
3667
3673
3668 start = None
3674 start = None
3669 if 'rev' in opts:
3675 if 'rev' in opts:
3670 start = scmutil.revsingle(repo, opts['rev'], None).node()
3676 start = scmutil.revsingle(repo, opts['rev'], None).node()
3671
3677
3672 if opts.get('topo'):
3678 if opts.get('topo'):
3673 heads = [repo[h] for h in repo.heads(start)]
3679 heads = [repo[h] for h in repo.heads(start)]
3674 else:
3680 else:
3675 heads = []
3681 heads = []
3676 for branch in repo.branchmap():
3682 for branch in repo.branchmap():
3677 heads += repo.branchheads(branch, start, opts.get('closed'))
3683 heads += repo.branchheads(branch, start, opts.get('closed'))
3678 heads = [repo[h] for h in heads]
3684 heads = [repo[h] for h in heads]
3679
3685
3680 if branchrevs:
3686 if branchrevs:
3681 branches = set(repo[br].branch() for br in branchrevs)
3687 branches = set(repo[br].branch() for br in branchrevs)
3682 heads = [h for h in heads if h.branch() in branches]
3688 heads = [h for h in heads if h.branch() in branches]
3683
3689
3684 if opts.get('active') and branchrevs:
3690 if opts.get('active') and branchrevs:
3685 dagheads = repo.heads(start)
3691 dagheads = repo.heads(start)
3686 heads = [h for h in heads if h.node() in dagheads]
3692 heads = [h for h in heads if h.node() in dagheads]
3687
3693
3688 if branchrevs:
3694 if branchrevs:
3689 haveheads = set(h.branch() for h in heads)
3695 haveheads = set(h.branch() for h in heads)
3690 if branches - haveheads:
3696 if branches - haveheads:
3691 headless = ', '.join(b for b in branches - haveheads)
3697 headless = ', '.join(b for b in branches - haveheads)
3692 msg = _('no open branch heads found on branches %s')
3698 msg = _('no open branch heads found on branches %s')
3693 if opts.get('rev'):
3699 if opts.get('rev'):
3694 msg += _(' (started at %s)') % opts['rev']
3700 msg += _(' (started at %s)') % opts['rev']
3695 ui.warn((msg + '\n') % headless)
3701 ui.warn((msg + '\n') % headless)
3696
3702
3697 if not heads:
3703 if not heads:
3698 return 1
3704 return 1
3699
3705
3700 heads = sorted(heads, key=lambda x: -x.rev())
3706 heads = sorted(heads, key=lambda x: -x.rev())
3701 displayer = cmdutil.show_changeset(ui, repo, opts)
3707 displayer = cmdutil.show_changeset(ui, repo, opts)
3702 for ctx in heads:
3708 for ctx in heads:
3703 displayer.show(ctx)
3709 displayer.show(ctx)
3704 displayer.close()
3710 displayer.close()
3705
3711
3706 @command('help',
3712 @command('help',
3707 [('e', 'extension', None, _('show only help for extensions')),
3713 [('e', 'extension', None, _('show only help for extensions')),
3708 ('c', 'command', None, _('show only help for commands')),
3714 ('c', 'command', None, _('show only help for commands')),
3709 ('k', 'keyword', '', _('show topics matching keyword')),
3715 ('k', 'keyword', '', _('show topics matching keyword')),
3710 ],
3716 ],
3711 _('[-ec] [TOPIC]'),
3717 _('[-ec] [TOPIC]'),
3712 norepo=True)
3718 norepo=True)
3713 def help_(ui, name=None, **opts):
3719 def help_(ui, name=None, **opts):
3714 """show help for a given topic or a help overview
3720 """show help for a given topic or a help overview
3715
3721
3716 With no arguments, print a list of commands with short help messages.
3722 With no arguments, print a list of commands with short help messages.
3717
3723
3718 Given a topic, extension, or command name, print help for that
3724 Given a topic, extension, or command name, print help for that
3719 topic.
3725 topic.
3720
3726
3721 Returns 0 if successful.
3727 Returns 0 if successful.
3722 """
3728 """
3723
3729
3724 textwidth = min(ui.termwidth(), 80) - 2
3730 textwidth = min(ui.termwidth(), 80) - 2
3725
3731
3726 keep = ui.verbose and ['verbose'] or []
3732 keep = ui.verbose and ['verbose'] or []
3727 text = help.help_(ui, name, **opts)
3733 text = help.help_(ui, name, **opts)
3728
3734
3729 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3735 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3730 if 'verbose' in pruned:
3736 if 'verbose' in pruned:
3731 keep.append('omitted')
3737 keep.append('omitted')
3732 else:
3738 else:
3733 keep.append('notomitted')
3739 keep.append('notomitted')
3734 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3740 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3735 ui.write(formatted)
3741 ui.write(formatted)
3736
3742
3737
3743
3738 @command('identify|id',
3744 @command('identify|id',
3739 [('r', 'rev', '',
3745 [('r', 'rev', '',
3740 _('identify the specified revision'), _('REV')),
3746 _('identify the specified revision'), _('REV')),
3741 ('n', 'num', None, _('show local revision number')),
3747 ('n', 'num', None, _('show local revision number')),
3742 ('i', 'id', None, _('show global revision id')),
3748 ('i', 'id', None, _('show global revision id')),
3743 ('b', 'branch', None, _('show branch')),
3749 ('b', 'branch', None, _('show branch')),
3744 ('t', 'tags', None, _('show tags')),
3750 ('t', 'tags', None, _('show tags')),
3745 ('B', 'bookmarks', None, _('show bookmarks')),
3751 ('B', 'bookmarks', None, _('show bookmarks')),
3746 ] + remoteopts,
3752 ] + remoteopts,
3747 _('[-nibtB] [-r REV] [SOURCE]'),
3753 _('[-nibtB] [-r REV] [SOURCE]'),
3748 optionalrepo=True)
3754 optionalrepo=True)
3749 def identify(ui, repo, source=None, rev=None,
3755 def identify(ui, repo, source=None, rev=None,
3750 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3756 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3751 """identify the working copy or specified revision
3757 """identify the working copy or specified revision
3752
3758
3753 Print a summary identifying the repository state at REV using one or
3759 Print a summary identifying the repository state at REV using one or
3754 two parent hash identifiers, followed by a "+" if the working
3760 two parent hash identifiers, followed by a "+" if the working
3755 directory has uncommitted changes, the branch name (if not default),
3761 directory has uncommitted changes, the branch name (if not default),
3756 a list of tags, and a list of bookmarks.
3762 a list of tags, and a list of bookmarks.
3757
3763
3758 When REV is not given, print a summary of the current state of the
3764 When REV is not given, print a summary of the current state of the
3759 repository.
3765 repository.
3760
3766
3761 Specifying a path to a repository root or Mercurial bundle will
3767 Specifying a path to a repository root or Mercurial bundle will
3762 cause lookup to operate on that repository/bundle.
3768 cause lookup to operate on that repository/bundle.
3763
3769
3764 .. container:: verbose
3770 .. container:: verbose
3765
3771
3766 Examples:
3772 Examples:
3767
3773
3768 - generate a build identifier for the working directory::
3774 - generate a build identifier for the working directory::
3769
3775
3770 hg id --id > build-id.dat
3776 hg id --id > build-id.dat
3771
3777
3772 - find the revision corresponding to a tag::
3778 - find the revision corresponding to a tag::
3773
3779
3774 hg id -n -r 1.3
3780 hg id -n -r 1.3
3775
3781
3776 - check the most recent revision of a remote repository::
3782 - check the most recent revision of a remote repository::
3777
3783
3778 hg id -r tip http://selenic.com/hg/
3784 hg id -r tip http://selenic.com/hg/
3779
3785
3780 Returns 0 if successful.
3786 Returns 0 if successful.
3781 """
3787 """
3782
3788
3783 if not repo and not source:
3789 if not repo and not source:
3784 raise util.Abort(_("there is no Mercurial repository here "
3790 raise util.Abort(_("there is no Mercurial repository here "
3785 "(.hg not found)"))
3791 "(.hg not found)"))
3786
3792
3787 hexfunc = ui.debugflag and hex or short
3793 hexfunc = ui.debugflag and hex or short
3788 default = not (num or id or branch or tags or bookmarks)
3794 default = not (num or id or branch or tags or bookmarks)
3789 output = []
3795 output = []
3790 revs = []
3796 revs = []
3791
3797
3792 if source:
3798 if source:
3793 source, branches = hg.parseurl(ui.expandpath(source))
3799 source, branches = hg.parseurl(ui.expandpath(source))
3794 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3800 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3795 repo = peer.local()
3801 repo = peer.local()
3796 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3802 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3797
3803
3798 if not repo:
3804 if not repo:
3799 if num or branch or tags:
3805 if num or branch or tags:
3800 raise util.Abort(
3806 raise util.Abort(
3801 _("can't query remote revision number, branch, or tags"))
3807 _("can't query remote revision number, branch, or tags"))
3802 if not rev and revs:
3808 if not rev and revs:
3803 rev = revs[0]
3809 rev = revs[0]
3804 if not rev:
3810 if not rev:
3805 rev = "tip"
3811 rev = "tip"
3806
3812
3807 remoterev = peer.lookup(rev)
3813 remoterev = peer.lookup(rev)
3808 if default or id:
3814 if default or id:
3809 output = [hexfunc(remoterev)]
3815 output = [hexfunc(remoterev)]
3810
3816
3811 def getbms():
3817 def getbms():
3812 bms = []
3818 bms = []
3813
3819
3814 if 'bookmarks' in peer.listkeys('namespaces'):
3820 if 'bookmarks' in peer.listkeys('namespaces'):
3815 hexremoterev = hex(remoterev)
3821 hexremoterev = hex(remoterev)
3816 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3822 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3817 if bmr == hexremoterev]
3823 if bmr == hexremoterev]
3818
3824
3819 return sorted(bms)
3825 return sorted(bms)
3820
3826
3821 if bookmarks:
3827 if bookmarks:
3822 output.extend(getbms())
3828 output.extend(getbms())
3823 elif default and not ui.quiet:
3829 elif default and not ui.quiet:
3824 # multiple bookmarks for a single parent separated by '/'
3830 # multiple bookmarks for a single parent separated by '/'
3825 bm = '/'.join(getbms())
3831 bm = '/'.join(getbms())
3826 if bm:
3832 if bm:
3827 output.append(bm)
3833 output.append(bm)
3828 else:
3834 else:
3829 if not rev:
3835 if not rev:
3830 ctx = repo[None]
3836 ctx = repo[None]
3831 parents = ctx.parents()
3837 parents = ctx.parents()
3832 changed = ""
3838 changed = ""
3833 if default or id or num:
3839 if default or id or num:
3834 if (util.any(repo.status())
3840 if (util.any(repo.status())
3835 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3841 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3836 changed = '+'
3842 changed = '+'
3837 if default or id:
3843 if default or id:
3838 output = ["%s%s" %
3844 output = ["%s%s" %
3839 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3845 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3840 if num:
3846 if num:
3841 output.append("%s%s" %
3847 output.append("%s%s" %
3842 ('+'.join([str(p.rev()) for p in parents]), changed))
3848 ('+'.join([str(p.rev()) for p in parents]), changed))
3843 else:
3849 else:
3844 ctx = scmutil.revsingle(repo, rev)
3850 ctx = scmutil.revsingle(repo, rev)
3845 if default or id:
3851 if default or id:
3846 output = [hexfunc(ctx.node())]
3852 output = [hexfunc(ctx.node())]
3847 if num:
3853 if num:
3848 output.append(str(ctx.rev()))
3854 output.append(str(ctx.rev()))
3849
3855
3850 if default and not ui.quiet:
3856 if default and not ui.quiet:
3851 b = ctx.branch()
3857 b = ctx.branch()
3852 if b != 'default':
3858 if b != 'default':
3853 output.append("(%s)" % b)
3859 output.append("(%s)" % b)
3854
3860
3855 # multiple tags for a single parent separated by '/'
3861 # multiple tags for a single parent separated by '/'
3856 t = '/'.join(ctx.tags())
3862 t = '/'.join(ctx.tags())
3857 if t:
3863 if t:
3858 output.append(t)
3864 output.append(t)
3859
3865
3860 # multiple bookmarks for a single parent separated by '/'
3866 # multiple bookmarks for a single parent separated by '/'
3861 bm = '/'.join(ctx.bookmarks())
3867 bm = '/'.join(ctx.bookmarks())
3862 if bm:
3868 if bm:
3863 output.append(bm)
3869 output.append(bm)
3864 else:
3870 else:
3865 if branch:
3871 if branch:
3866 output.append(ctx.branch())
3872 output.append(ctx.branch())
3867
3873
3868 if tags:
3874 if tags:
3869 output.extend(ctx.tags())
3875 output.extend(ctx.tags())
3870
3876
3871 if bookmarks:
3877 if bookmarks:
3872 output.extend(ctx.bookmarks())
3878 output.extend(ctx.bookmarks())
3873
3879
3874 ui.write("%s\n" % ' '.join(output))
3880 ui.write("%s\n" % ' '.join(output))
3875
3881
3876 @command('import|patch',
3882 @command('import|patch',
3877 [('p', 'strip', 1,
3883 [('p', 'strip', 1,
3878 _('directory strip option for patch. This has the same '
3884 _('directory strip option for patch. This has the same '
3879 'meaning as the corresponding patch option'), _('NUM')),
3885 'meaning as the corresponding patch option'), _('NUM')),
3880 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3886 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3881 ('e', 'edit', False, _('invoke editor on commit messages')),
3887 ('e', 'edit', False, _('invoke editor on commit messages')),
3882 ('f', 'force', None,
3888 ('f', 'force', None,
3883 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3889 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3884 ('', 'no-commit', None,
3890 ('', 'no-commit', None,
3885 _("don't commit, just update the working directory")),
3891 _("don't commit, just update the working directory")),
3886 ('', 'bypass', None,
3892 ('', 'bypass', None,
3887 _("apply patch without touching the working directory")),
3893 _("apply patch without touching the working directory")),
3888 ('', 'partial', None,
3894 ('', 'partial', None,
3889 _('commit even if some hunks fail')),
3895 _('commit even if some hunks fail')),
3890 ('', 'exact', None,
3896 ('', 'exact', None,
3891 _('apply patch to the nodes from which it was generated')),
3897 _('apply patch to the nodes from which it was generated')),
3892 ('', 'import-branch', None,
3898 ('', 'import-branch', None,
3893 _('use any branch information in patch (implied by --exact)'))] +
3899 _('use any branch information in patch (implied by --exact)'))] +
3894 commitopts + commitopts2 + similarityopts,
3900 commitopts + commitopts2 + similarityopts,
3895 _('[OPTION]... PATCH...'))
3901 _('[OPTION]... PATCH...'))
3896 def import_(ui, repo, patch1=None, *patches, **opts):
3902 def import_(ui, repo, patch1=None, *patches, **opts):
3897 """import an ordered set of patches
3903 """import an ordered set of patches
3898
3904
3899 Import a list of patches and commit them individually (unless
3905 Import a list of patches and commit them individually (unless
3900 --no-commit is specified).
3906 --no-commit is specified).
3901
3907
3902 Because import first applies changes to the working directory,
3908 Because import first applies changes to the working directory,
3903 import will abort if there are outstanding changes.
3909 import will abort if there are outstanding changes.
3904
3910
3905 You can import a patch straight from a mail message. Even patches
3911 You can import a patch straight from a mail message. Even patches
3906 as attachments work (to use the body part, it must have type
3912 as attachments work (to use the body part, it must have type
3907 text/plain or text/x-patch). From and Subject headers of email
3913 text/plain or text/x-patch). From and Subject headers of email
3908 message are used as default committer and commit message. All
3914 message are used as default committer and commit message. All
3909 text/plain body parts before first diff are added to commit
3915 text/plain body parts before first diff are added to commit
3910 message.
3916 message.
3911
3917
3912 If the imported patch was generated by :hg:`export`, user and
3918 If the imported patch was generated by :hg:`export`, user and
3913 description from patch override values from message headers and
3919 description from patch override values from message headers and
3914 body. Values given on command line with -m/--message and -u/--user
3920 body. Values given on command line with -m/--message and -u/--user
3915 override these.
3921 override these.
3916
3922
3917 If --exact is specified, import will set the working directory to
3923 If --exact is specified, import will set the working directory to
3918 the parent of each patch before applying it, and will abort if the
3924 the parent of each patch before applying it, and will abort if the
3919 resulting changeset has a different ID than the one recorded in
3925 resulting changeset has a different ID than the one recorded in
3920 the patch. This may happen due to character set problems or other
3926 the patch. This may happen due to character set problems or other
3921 deficiencies in the text patch format.
3927 deficiencies in the text patch format.
3922
3928
3923 Use --bypass to apply and commit patches directly to the
3929 Use --bypass to apply and commit patches directly to the
3924 repository, not touching the working directory. Without --exact,
3930 repository, not touching the working directory. Without --exact,
3925 patches will be applied on top of the working directory parent
3931 patches will be applied on top of the working directory parent
3926 revision.
3932 revision.
3927
3933
3928 With -s/--similarity, hg will attempt to discover renames and
3934 With -s/--similarity, hg will attempt to discover renames and
3929 copies in the patch in the same way as :hg:`addremove`.
3935 copies in the patch in the same way as :hg:`addremove`.
3930
3936
3931 Use --partial to ensure a changeset will be created from the patch
3937 Use --partial to ensure a changeset will be created from the patch
3932 even if some hunks fail to apply. Hunks that fail to apply will be
3938 even if some hunks fail to apply. Hunks that fail to apply will be
3933 written to a <target-file>.rej file. Conflicts can then be resolved
3939 written to a <target-file>.rej file. Conflicts can then be resolved
3934 by hand before :hg:`commit --amend` is run to update the created
3940 by hand before :hg:`commit --amend` is run to update the created
3935 changeset. This flag exists to let people import patches that
3941 changeset. This flag exists to let people import patches that
3936 partially apply without losing the associated metadata (author,
3942 partially apply without losing the associated metadata (author,
3937 date, description, ...). Note that when none of the hunk applies
3943 date, description, ...). Note that when none of the hunk applies
3938 cleanly, :hg:`import --partial` will create an empty changeset,
3944 cleanly, :hg:`import --partial` will create an empty changeset,
3939 importing only the patch metadata.
3945 importing only the patch metadata.
3940
3946
3941 To read a patch from standard input, use "-" as the patch name. If
3947 To read a patch from standard input, use "-" as the patch name. If
3942 a URL is specified, the patch will be downloaded from it.
3948 a URL is specified, the patch will be downloaded from it.
3943 See :hg:`help dates` for a list of formats valid for -d/--date.
3949 See :hg:`help dates` for a list of formats valid for -d/--date.
3944
3950
3945 .. container:: verbose
3951 .. container:: verbose
3946
3952
3947 Examples:
3953 Examples:
3948
3954
3949 - import a traditional patch from a website and detect renames::
3955 - import a traditional patch from a website and detect renames::
3950
3956
3951 hg import -s 80 http://example.com/bugfix.patch
3957 hg import -s 80 http://example.com/bugfix.patch
3952
3958
3953 - import a changeset from an hgweb server::
3959 - import a changeset from an hgweb server::
3954
3960
3955 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3961 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3956
3962
3957 - import all the patches in an Unix-style mbox::
3963 - import all the patches in an Unix-style mbox::
3958
3964
3959 hg import incoming-patches.mbox
3965 hg import incoming-patches.mbox
3960
3966
3961 - attempt to exactly restore an exported changeset (not always
3967 - attempt to exactly restore an exported changeset (not always
3962 possible)::
3968 possible)::
3963
3969
3964 hg import --exact proposed-fix.patch
3970 hg import --exact proposed-fix.patch
3965
3971
3966 Returns 0 on success, 1 on partial success (see --partial).
3972 Returns 0 on success, 1 on partial success (see --partial).
3967 """
3973 """
3968
3974
3969 if not patch1:
3975 if not patch1:
3970 raise util.Abort(_('need at least one patch to import'))
3976 raise util.Abort(_('need at least one patch to import'))
3971
3977
3972 patches = (patch1,) + patches
3978 patches = (patch1,) + patches
3973
3979
3974 date = opts.get('date')
3980 date = opts.get('date')
3975 if date:
3981 if date:
3976 opts['date'] = util.parsedate(date)
3982 opts['date'] = util.parsedate(date)
3977
3983
3978 update = not opts.get('bypass')
3984 update = not opts.get('bypass')
3979 if not update and opts.get('no_commit'):
3985 if not update and opts.get('no_commit'):
3980 raise util.Abort(_('cannot use --no-commit with --bypass'))
3986 raise util.Abort(_('cannot use --no-commit with --bypass'))
3981 try:
3987 try:
3982 sim = float(opts.get('similarity') or 0)
3988 sim = float(opts.get('similarity') or 0)
3983 except ValueError:
3989 except ValueError:
3984 raise util.Abort(_('similarity must be a number'))
3990 raise util.Abort(_('similarity must be a number'))
3985 if sim < 0 or sim > 100:
3991 if sim < 0 or sim > 100:
3986 raise util.Abort(_('similarity must be between 0 and 100'))
3992 raise util.Abort(_('similarity must be between 0 and 100'))
3987 if sim and not update:
3993 if sim and not update:
3988 raise util.Abort(_('cannot use --similarity with --bypass'))
3994 raise util.Abort(_('cannot use --similarity with --bypass'))
3989 if opts.get('exact') and opts.get('edit'):
3995 if opts.get('exact') and opts.get('edit'):
3990 raise util.Abort(_('cannot use --exact with --edit'))
3996 raise util.Abort(_('cannot use --exact with --edit'))
3991
3997
3992 if update:
3998 if update:
3993 cmdutil.checkunfinished(repo)
3999 cmdutil.checkunfinished(repo)
3994 if (opts.get('exact') or not opts.get('force')) and update:
4000 if (opts.get('exact') or not opts.get('force')) and update:
3995 cmdutil.bailifchanged(repo)
4001 cmdutil.bailifchanged(repo)
3996
4002
3997 base = opts["base"]
4003 base = opts["base"]
3998 wlock = lock = tr = None
4004 wlock = lock = tr = None
3999 msgs = []
4005 msgs = []
4000 ret = 0
4006 ret = 0
4001
4007
4002
4008
4003 try:
4009 try:
4004 try:
4010 try:
4005 wlock = repo.wlock()
4011 wlock = repo.wlock()
4006 repo.dirstate.beginparentchange()
4012 repo.dirstate.beginparentchange()
4007 if not opts.get('no_commit'):
4013 if not opts.get('no_commit'):
4008 lock = repo.lock()
4014 lock = repo.lock()
4009 tr = repo.transaction('import')
4015 tr = repo.transaction('import')
4010 parents = repo.parents()
4016 parents = repo.parents()
4011 for patchurl in patches:
4017 for patchurl in patches:
4012 if patchurl == '-':
4018 if patchurl == '-':
4013 ui.status(_('applying patch from stdin\n'))
4019 ui.status(_('applying patch from stdin\n'))
4014 patchfile = ui.fin
4020 patchfile = ui.fin
4015 patchurl = 'stdin' # for error message
4021 patchurl = 'stdin' # for error message
4016 else:
4022 else:
4017 patchurl = os.path.join(base, patchurl)
4023 patchurl = os.path.join(base, patchurl)
4018 ui.status(_('applying %s\n') % patchurl)
4024 ui.status(_('applying %s\n') % patchurl)
4019 patchfile = hg.openpath(ui, patchurl)
4025 patchfile = hg.openpath(ui, patchurl)
4020
4026
4021 haspatch = False
4027 haspatch = False
4022 for hunk in patch.split(patchfile):
4028 for hunk in patch.split(patchfile):
4023 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4029 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4024 parents, opts,
4030 parents, opts,
4025 msgs, hg.clean)
4031 msgs, hg.clean)
4026 if msg:
4032 if msg:
4027 haspatch = True
4033 haspatch = True
4028 ui.note(msg + '\n')
4034 ui.note(msg + '\n')
4029 if update or opts.get('exact'):
4035 if update or opts.get('exact'):
4030 parents = repo.parents()
4036 parents = repo.parents()
4031 else:
4037 else:
4032 parents = [repo[node]]
4038 parents = [repo[node]]
4033 if rej:
4039 if rej:
4034 ui.write_err(_("patch applied partially\n"))
4040 ui.write_err(_("patch applied partially\n"))
4035 ui.write_err(_("(fix the .rej files and run "
4041 ui.write_err(_("(fix the .rej files and run "
4036 "`hg commit --amend`)\n"))
4042 "`hg commit --amend`)\n"))
4037 ret = 1
4043 ret = 1
4038 break
4044 break
4039
4045
4040 if not haspatch:
4046 if not haspatch:
4041 raise util.Abort(_('%s: no diffs found') % patchurl)
4047 raise util.Abort(_('%s: no diffs found') % patchurl)
4042
4048
4043 if tr:
4049 if tr:
4044 tr.close()
4050 tr.close()
4045 if msgs:
4051 if msgs:
4046 repo.savecommitmessage('\n* * *\n'.join(msgs))
4052 repo.savecommitmessage('\n* * *\n'.join(msgs))
4047 repo.dirstate.endparentchange()
4053 repo.dirstate.endparentchange()
4048 return ret
4054 return ret
4049 except: # re-raises
4055 except: # re-raises
4050 # wlock.release() indirectly calls dirstate.write(): since
4056 # wlock.release() indirectly calls dirstate.write(): since
4051 # we're crashing, we do not want to change the working dir
4057 # we're crashing, we do not want to change the working dir
4052 # parent after all, so make sure it writes nothing
4058 # parent after all, so make sure it writes nothing
4053 repo.dirstate.invalidate()
4059 repo.dirstate.invalidate()
4054 raise
4060 raise
4055 finally:
4061 finally:
4056 if tr:
4062 if tr:
4057 tr.release()
4063 tr.release()
4058 release(lock, wlock)
4064 release(lock, wlock)
4059
4065
4060 @command('incoming|in',
4066 @command('incoming|in',
4061 [('f', 'force', None,
4067 [('f', 'force', None,
4062 _('run even if remote repository is unrelated')),
4068 _('run even if remote repository is unrelated')),
4063 ('n', 'newest-first', None, _('show newest record first')),
4069 ('n', 'newest-first', None, _('show newest record first')),
4064 ('', 'bundle', '',
4070 ('', 'bundle', '',
4065 _('file to store the bundles into'), _('FILE')),
4071 _('file to store the bundles into'), _('FILE')),
4066 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4072 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4067 ('B', 'bookmarks', False, _("compare bookmarks")),
4073 ('B', 'bookmarks', False, _("compare bookmarks")),
4068 ('b', 'branch', [],
4074 ('b', 'branch', [],
4069 _('a specific branch you would like to pull'), _('BRANCH')),
4075 _('a specific branch you would like to pull'), _('BRANCH')),
4070 ] + logopts + remoteopts + subrepoopts,
4076 ] + logopts + remoteopts + subrepoopts,
4071 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4077 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4072 def incoming(ui, repo, source="default", **opts):
4078 def incoming(ui, repo, source="default", **opts):
4073 """show new changesets found in source
4079 """show new changesets found in source
4074
4080
4075 Show new changesets found in the specified path/URL or the default
4081 Show new changesets found in the specified path/URL or the default
4076 pull location. These are the changesets that would have been pulled
4082 pull location. These are the changesets that would have been pulled
4077 if a pull at the time you issued this command.
4083 if a pull at the time you issued this command.
4078
4084
4079 For remote repository, using --bundle avoids downloading the
4085 For remote repository, using --bundle avoids downloading the
4080 changesets twice if the incoming is followed by a pull.
4086 changesets twice if the incoming is followed by a pull.
4081
4087
4082 See pull for valid source format details.
4088 See pull for valid source format details.
4083
4089
4084 .. container:: verbose
4090 .. container:: verbose
4085
4091
4086 Examples:
4092 Examples:
4087
4093
4088 - show incoming changes with patches and full description::
4094 - show incoming changes with patches and full description::
4089
4095
4090 hg incoming -vp
4096 hg incoming -vp
4091
4097
4092 - show incoming changes excluding merges, store a bundle::
4098 - show incoming changes excluding merges, store a bundle::
4093
4099
4094 hg in -vpM --bundle incoming.hg
4100 hg in -vpM --bundle incoming.hg
4095 hg pull incoming.hg
4101 hg pull incoming.hg
4096
4102
4097 - briefly list changes inside a bundle::
4103 - briefly list changes inside a bundle::
4098
4104
4099 hg in changes.hg -T "{desc|firstline}\\n"
4105 hg in changes.hg -T "{desc|firstline}\\n"
4100
4106
4101 Returns 0 if there are incoming changes, 1 otherwise.
4107 Returns 0 if there are incoming changes, 1 otherwise.
4102 """
4108 """
4103 if opts.get('graph'):
4109 if opts.get('graph'):
4104 cmdutil.checkunsupportedgraphflags([], opts)
4110 cmdutil.checkunsupportedgraphflags([], opts)
4105 def display(other, chlist, displayer):
4111 def display(other, chlist, displayer):
4106 revdag = cmdutil.graphrevs(other, chlist, opts)
4112 revdag = cmdutil.graphrevs(other, chlist, opts)
4107 showparents = [ctx.node() for ctx in repo[None].parents()]
4113 showparents = [ctx.node() for ctx in repo[None].parents()]
4108 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4114 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4109 graphmod.asciiedges)
4115 graphmod.asciiedges)
4110
4116
4111 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4117 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4112 return 0
4118 return 0
4113
4119
4114 if opts.get('bundle') and opts.get('subrepos'):
4120 if opts.get('bundle') and opts.get('subrepos'):
4115 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4121 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4116
4122
4117 if opts.get('bookmarks'):
4123 if opts.get('bookmarks'):
4118 source, branches = hg.parseurl(ui.expandpath(source),
4124 source, branches = hg.parseurl(ui.expandpath(source),
4119 opts.get('branch'))
4125 opts.get('branch'))
4120 other = hg.peer(repo, opts, source)
4126 other = hg.peer(repo, opts, source)
4121 if 'bookmarks' not in other.listkeys('namespaces'):
4127 if 'bookmarks' not in other.listkeys('namespaces'):
4122 ui.warn(_("remote doesn't support bookmarks\n"))
4128 ui.warn(_("remote doesn't support bookmarks\n"))
4123 return 0
4129 return 0
4124 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4130 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4125 return bookmarks.diff(ui, repo, other)
4131 return bookmarks.diff(ui, repo, other)
4126
4132
4127 repo._subtoppath = ui.expandpath(source)
4133 repo._subtoppath = ui.expandpath(source)
4128 try:
4134 try:
4129 return hg.incoming(ui, repo, source, opts)
4135 return hg.incoming(ui, repo, source, opts)
4130 finally:
4136 finally:
4131 del repo._subtoppath
4137 del repo._subtoppath
4132
4138
4133
4139
4134 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4140 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4135 norepo=True)
4141 norepo=True)
4136 def init(ui, dest=".", **opts):
4142 def init(ui, dest=".", **opts):
4137 """create a new repository in the given directory
4143 """create a new repository in the given directory
4138
4144
4139 Initialize a new repository in the given directory. If the given
4145 Initialize a new repository in the given directory. If the given
4140 directory does not exist, it will be created.
4146 directory does not exist, it will be created.
4141
4147
4142 If no directory is given, the current directory is used.
4148 If no directory is given, the current directory is used.
4143
4149
4144 It is possible to specify an ``ssh://`` URL as the destination.
4150 It is possible to specify an ``ssh://`` URL as the destination.
4145 See :hg:`help urls` for more information.
4151 See :hg:`help urls` for more information.
4146
4152
4147 Returns 0 on success.
4153 Returns 0 on success.
4148 """
4154 """
4149 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4155 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4150
4156
4151 @command('locate',
4157 @command('locate',
4152 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4158 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4153 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4159 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4154 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4160 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4155 ] + walkopts,
4161 ] + walkopts,
4156 _('[OPTION]... [PATTERN]...'))
4162 _('[OPTION]... [PATTERN]...'))
4157 def locate(ui, repo, *pats, **opts):
4163 def locate(ui, repo, *pats, **opts):
4158 """locate files matching specific patterns
4164 """locate files matching specific patterns
4159
4165
4160 Print files under Mercurial control in the working directory whose
4166 Print files under Mercurial control in the working directory whose
4161 names match the given patterns.
4167 names match the given patterns.
4162
4168
4163 By default, this command searches all directories in the working
4169 By default, this command searches all directories in the working
4164 directory. To search just the current directory and its
4170 directory. To search just the current directory and its
4165 subdirectories, use "--include .".
4171 subdirectories, use "--include .".
4166
4172
4167 If no patterns are given to match, this command prints the names
4173 If no patterns are given to match, this command prints the names
4168 of all files under Mercurial control in the working directory.
4174 of all files under Mercurial control in the working directory.
4169
4175
4170 If you want to feed the output of this command into the "xargs"
4176 If you want to feed the output of this command into the "xargs"
4171 command, use the -0 option to both this command and "xargs". This
4177 command, use the -0 option to both this command and "xargs". This
4172 will avoid the problem of "xargs" treating single filenames that
4178 will avoid the problem of "xargs" treating single filenames that
4173 contain whitespace as multiple filenames.
4179 contain whitespace as multiple filenames.
4174
4180
4175 Returns 0 if a match is found, 1 otherwise.
4181 Returns 0 if a match is found, 1 otherwise.
4176 """
4182 """
4177 end = opts.get('print0') and '\0' or '\n'
4183 end = opts.get('print0') and '\0' or '\n'
4178 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4184 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4179
4185
4180 ret = 1
4186 ret = 1
4181 ctx = repo[rev]
4187 ctx = repo[rev]
4182 m = scmutil.match(ctx, pats, opts, default='relglob')
4188 m = scmutil.match(ctx, pats, opts, default='relglob')
4183 m.bad = lambda x, y: False
4189 m.bad = lambda x, y: False
4184
4190
4185 for abs in ctx.matches(m):
4191 for abs in ctx.matches(m):
4186 if opts.get('fullpath'):
4192 if opts.get('fullpath'):
4187 ui.write(repo.wjoin(abs), end)
4193 ui.write(repo.wjoin(abs), end)
4188 else:
4194 else:
4189 ui.write(((pats and m.rel(abs)) or abs), end)
4195 ui.write(((pats and m.rel(abs)) or abs), end)
4190 ret = 0
4196 ret = 0
4191
4197
4192 return ret
4198 return ret
4193
4199
4194 @command('^log|history',
4200 @command('^log|history',
4195 [('f', 'follow', None,
4201 [('f', 'follow', None,
4196 _('follow changeset history, or file history across copies and renames')),
4202 _('follow changeset history, or file history across copies and renames')),
4197 ('', 'follow-first', None,
4203 ('', 'follow-first', None,
4198 _('only follow the first parent of merge changesets (DEPRECATED)')),
4204 _('only follow the first parent of merge changesets (DEPRECATED)')),
4199 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4205 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4200 ('C', 'copies', None, _('show copied files')),
4206 ('C', 'copies', None, _('show copied files')),
4201 ('k', 'keyword', [],
4207 ('k', 'keyword', [],
4202 _('do case-insensitive search for a given text'), _('TEXT')),
4208 _('do case-insensitive search for a given text'), _('TEXT')),
4203 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4209 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4204 ('', 'removed', None, _('include revisions where files were removed')),
4210 ('', 'removed', None, _('include revisions where files were removed')),
4205 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4211 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4206 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4212 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4207 ('', 'only-branch', [],
4213 ('', 'only-branch', [],
4208 _('show only changesets within the given named branch (DEPRECATED)'),
4214 _('show only changesets within the given named branch (DEPRECATED)'),
4209 _('BRANCH')),
4215 _('BRANCH')),
4210 ('b', 'branch', [],
4216 ('b', 'branch', [],
4211 _('show changesets within the given named branch'), _('BRANCH')),
4217 _('show changesets within the given named branch'), _('BRANCH')),
4212 ('P', 'prune', [],
4218 ('P', 'prune', [],
4213 _('do not display revision or any of its ancestors'), _('REV')),
4219 _('do not display revision or any of its ancestors'), _('REV')),
4214 ] + logopts + walkopts,
4220 ] + logopts + walkopts,
4215 _('[OPTION]... [FILE]'),
4221 _('[OPTION]... [FILE]'),
4216 inferrepo=True)
4222 inferrepo=True)
4217 def log(ui, repo, *pats, **opts):
4223 def log(ui, repo, *pats, **opts):
4218 """show revision history of entire repository or files
4224 """show revision history of entire repository or files
4219
4225
4220 Print the revision history of the specified files or the entire
4226 Print the revision history of the specified files or the entire
4221 project.
4227 project.
4222
4228
4223 If no revision range is specified, the default is ``tip:0`` unless
4229 If no revision range is specified, the default is ``tip:0`` unless
4224 --follow is set, in which case the working directory parent is
4230 --follow is set, in which case the working directory parent is
4225 used as the starting revision.
4231 used as the starting revision.
4226
4232
4227 File history is shown without following rename or copy history of
4233 File history is shown without following rename or copy history of
4228 files. Use -f/--follow with a filename to follow history across
4234 files. Use -f/--follow with a filename to follow history across
4229 renames and copies. --follow without a filename will only show
4235 renames and copies. --follow without a filename will only show
4230 ancestors or descendants of the starting revision.
4236 ancestors or descendants of the starting revision.
4231
4237
4232 By default this command prints revision number and changeset id,
4238 By default this command prints revision number and changeset id,
4233 tags, non-trivial parents, user, date and time, and a summary for
4239 tags, non-trivial parents, user, date and time, and a summary for
4234 each commit. When the -v/--verbose switch is used, the list of
4240 each commit. When the -v/--verbose switch is used, the list of
4235 changed files and full commit message are shown.
4241 changed files and full commit message are shown.
4236
4242
4237 With --graph the revisions are shown as an ASCII art DAG with the most
4243 With --graph the revisions are shown as an ASCII art DAG with the most
4238 recent changeset at the top.
4244 recent changeset at the top.
4239 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4245 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4240 and '+' represents a fork where the changeset from the lines below is a
4246 and '+' represents a fork where the changeset from the lines below is a
4241 parent of the 'o' merge on the same line.
4247 parent of the 'o' merge on the same line.
4242
4248
4243 .. note::
4249 .. note::
4244
4250
4245 log -p/--patch may generate unexpected diff output for merge
4251 log -p/--patch may generate unexpected diff output for merge
4246 changesets, as it will only compare the merge changeset against
4252 changesets, as it will only compare the merge changeset against
4247 its first parent. Also, only files different from BOTH parents
4253 its first parent. Also, only files different from BOTH parents
4248 will appear in files:.
4254 will appear in files:.
4249
4255
4250 .. note::
4256 .. note::
4251
4257
4252 for performance reasons, log FILE may omit duplicate changes
4258 for performance reasons, log FILE may omit duplicate changes
4253 made on branches and will not show deletions. To see all
4259 made on branches and will not show deletions. To see all
4254 changes including duplicates and deletions, use the --removed
4260 changes including duplicates and deletions, use the --removed
4255 switch.
4261 switch.
4256
4262
4257 .. container:: verbose
4263 .. container:: verbose
4258
4264
4259 Some examples:
4265 Some examples:
4260
4266
4261 - changesets with full descriptions and file lists::
4267 - changesets with full descriptions and file lists::
4262
4268
4263 hg log -v
4269 hg log -v
4264
4270
4265 - changesets ancestral to the working directory::
4271 - changesets ancestral to the working directory::
4266
4272
4267 hg log -f
4273 hg log -f
4268
4274
4269 - last 10 commits on the current branch::
4275 - last 10 commits on the current branch::
4270
4276
4271 hg log -l 10 -b .
4277 hg log -l 10 -b .
4272
4278
4273 - changesets showing all modifications of a file, including removals::
4279 - changesets showing all modifications of a file, including removals::
4274
4280
4275 hg log --removed file.c
4281 hg log --removed file.c
4276
4282
4277 - all changesets that touch a directory, with diffs, excluding merges::
4283 - all changesets that touch a directory, with diffs, excluding merges::
4278
4284
4279 hg log -Mp lib/
4285 hg log -Mp lib/
4280
4286
4281 - all revision numbers that match a keyword::
4287 - all revision numbers that match a keyword::
4282
4288
4283 hg log -k bug --template "{rev}\\n"
4289 hg log -k bug --template "{rev}\\n"
4284
4290
4285 - list available log templates::
4291 - list available log templates::
4286
4292
4287 hg log -T list
4293 hg log -T list
4288
4294
4289 - check if a given changeset is included is a tagged release::
4295 - check if a given changeset is included is a tagged release::
4290
4296
4291 hg log -r "a21ccf and ancestor(1.9)"
4297 hg log -r "a21ccf and ancestor(1.9)"
4292
4298
4293 - find all changesets by some user in a date range::
4299 - find all changesets by some user in a date range::
4294
4300
4295 hg log -k alice -d "may 2008 to jul 2008"
4301 hg log -k alice -d "may 2008 to jul 2008"
4296
4302
4297 - summary of all changesets after the last tag::
4303 - summary of all changesets after the last tag::
4298
4304
4299 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4305 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4300
4306
4301 See :hg:`help dates` for a list of formats valid for -d/--date.
4307 See :hg:`help dates` for a list of formats valid for -d/--date.
4302
4308
4303 See :hg:`help revisions` and :hg:`help revsets` for more about
4309 See :hg:`help revisions` and :hg:`help revsets` for more about
4304 specifying revisions.
4310 specifying revisions.
4305
4311
4306 See :hg:`help templates` for more about pre-packaged styles and
4312 See :hg:`help templates` for more about pre-packaged styles and
4307 specifying custom templates.
4313 specifying custom templates.
4308
4314
4309 Returns 0 on success.
4315 Returns 0 on success.
4310 """
4316 """
4311 if opts.get('graph'):
4317 if opts.get('graph'):
4312 return cmdutil.graphlog(ui, repo, *pats, **opts)
4318 return cmdutil.graphlog(ui, repo, *pats, **opts)
4313
4319
4314 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4320 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4315 limit = cmdutil.loglimit(opts)
4321 limit = cmdutil.loglimit(opts)
4316 count = 0
4322 count = 0
4317
4323
4318 getrenamed = None
4324 getrenamed = None
4319 if opts.get('copies'):
4325 if opts.get('copies'):
4320 endrev = None
4326 endrev = None
4321 if opts.get('rev'):
4327 if opts.get('rev'):
4322 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4328 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4323 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4329 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4324
4330
4325 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4331 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4326 for rev in revs:
4332 for rev in revs:
4327 if count == limit:
4333 if count == limit:
4328 break
4334 break
4329 ctx = repo[rev]
4335 ctx = repo[rev]
4330 copies = None
4336 copies = None
4331 if getrenamed is not None and rev:
4337 if getrenamed is not None and rev:
4332 copies = []
4338 copies = []
4333 for fn in ctx.files():
4339 for fn in ctx.files():
4334 rename = getrenamed(fn, rev)
4340 rename = getrenamed(fn, rev)
4335 if rename:
4341 if rename:
4336 copies.append((fn, rename[0]))
4342 copies.append((fn, rename[0]))
4337 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4343 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4338 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4344 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4339 if displayer.flush(rev):
4345 if displayer.flush(rev):
4340 count += 1
4346 count += 1
4341
4347
4342 displayer.close()
4348 displayer.close()
4343
4349
4344 @command('manifest',
4350 @command('manifest',
4345 [('r', 'rev', '', _('revision to display'), _('REV')),
4351 [('r', 'rev', '', _('revision to display'), _('REV')),
4346 ('', 'all', False, _("list files from all revisions"))],
4352 ('', 'all', False, _("list files from all revisions"))]
4353 + formatteropts,
4347 _('[-r REV]'))
4354 _('[-r REV]'))
4348 def manifest(ui, repo, node=None, rev=None, **opts):
4355 def manifest(ui, repo, node=None, rev=None, **opts):
4349 """output the current or given revision of the project manifest
4356 """output the current or given revision of the project manifest
4350
4357
4351 Print a list of version controlled files for the given revision.
4358 Print a list of version controlled files for the given revision.
4352 If no revision is given, the first parent of the working directory
4359 If no revision is given, the first parent of the working directory
4353 is used, or the null revision if no revision is checked out.
4360 is used, or the null revision if no revision is checked out.
4354
4361
4355 With -v, print file permissions, symlink and executable bits.
4362 With -v, print file permissions, symlink and executable bits.
4356 With --debug, print file revision hashes.
4363 With --debug, print file revision hashes.
4357
4364
4358 If option --all is specified, the list of all files from all revisions
4365 If option --all is specified, the list of all files from all revisions
4359 is printed. This includes deleted and renamed files.
4366 is printed. This includes deleted and renamed files.
4360
4367
4361 Returns 0 on success.
4368 Returns 0 on success.
4362 """
4369 """
4363
4370
4364 fm = ui.formatter('manifest', opts)
4371 fm = ui.formatter('manifest', opts)
4365
4372
4366 if opts.get('all'):
4373 if opts.get('all'):
4367 if rev or node:
4374 if rev or node:
4368 raise util.Abort(_("can't specify a revision with --all"))
4375 raise util.Abort(_("can't specify a revision with --all"))
4369
4376
4370 res = []
4377 res = []
4371 prefix = "data/"
4378 prefix = "data/"
4372 suffix = ".i"
4379 suffix = ".i"
4373 plen = len(prefix)
4380 plen = len(prefix)
4374 slen = len(suffix)
4381 slen = len(suffix)
4375 lock = repo.lock()
4382 lock = repo.lock()
4376 try:
4383 try:
4377 for fn, b, size in repo.store.datafiles():
4384 for fn, b, size in repo.store.datafiles():
4378 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4385 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4379 res.append(fn[plen:-slen])
4386 res.append(fn[plen:-slen])
4380 finally:
4387 finally:
4381 lock.release()
4388 lock.release()
4382 for f in res:
4389 for f in res:
4383 fm.startitem()
4390 fm.startitem()
4384 fm.write("path", '%s\n', f)
4391 fm.write("path", '%s\n', f)
4385 fm.end()
4392 fm.end()
4386 return
4393 return
4387
4394
4388 if rev and node:
4395 if rev and node:
4389 raise util.Abort(_("please specify just one revision"))
4396 raise util.Abort(_("please specify just one revision"))
4390
4397
4391 if not node:
4398 if not node:
4392 node = rev
4399 node = rev
4393
4400
4394 char = {'l': '@', 'x': '*', '': ''}
4401 char = {'l': '@', 'x': '*', '': ''}
4395 mode = {'l': '644', 'x': '755', '': '644'}
4402 mode = {'l': '644', 'x': '755', '': '644'}
4396 ctx = scmutil.revsingle(repo, node)
4403 ctx = scmutil.revsingle(repo, node)
4397 mf = ctx.manifest()
4404 mf = ctx.manifest()
4398 for f in ctx:
4405 for f in ctx:
4399 fm.startitem()
4406 fm.startitem()
4400 fl = ctx[f].flags()
4407 fl = ctx[f].flags()
4401 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4408 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4402 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4409 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4403 fm.write('path', '%s\n', f)
4410 fm.write('path', '%s\n', f)
4404 fm.end()
4411 fm.end()
4405
4412
4406 @command('^merge',
4413 @command('^merge',
4407 [('f', 'force', None,
4414 [('f', 'force', None,
4408 _('force a merge including outstanding changes (DEPRECATED)')),
4415 _('force a merge including outstanding changes (DEPRECATED)')),
4409 ('r', 'rev', '', _('revision to merge'), _('REV')),
4416 ('r', 'rev', '', _('revision to merge'), _('REV')),
4410 ('P', 'preview', None,
4417 ('P', 'preview', None,
4411 _('review revisions to merge (no merge is performed)'))
4418 _('review revisions to merge (no merge is performed)'))
4412 ] + mergetoolopts,
4419 ] + mergetoolopts,
4413 _('[-P] [-f] [[-r] REV]'))
4420 _('[-P] [-f] [[-r] REV]'))
4414 def merge(ui, repo, node=None, **opts):
4421 def merge(ui, repo, node=None, **opts):
4415 """merge working directory with another revision
4422 """merge working directory with another revision
4416
4423
4417 The current working directory is updated with all changes made in
4424 The current working directory is updated with all changes made in
4418 the requested revision since the last common predecessor revision.
4425 the requested revision since the last common predecessor revision.
4419
4426
4420 Files that changed between either parent are marked as changed for
4427 Files that changed between either parent are marked as changed for
4421 the next commit and a commit must be performed before any further
4428 the next commit and a commit must be performed before any further
4422 updates to the repository are allowed. The next commit will have
4429 updates to the repository are allowed. The next commit will have
4423 two parents.
4430 two parents.
4424
4431
4425 ``--tool`` can be used to specify the merge tool used for file
4432 ``--tool`` can be used to specify the merge tool used for file
4426 merges. It overrides the HGMERGE environment variable and your
4433 merges. It overrides the HGMERGE environment variable and your
4427 configuration files. See :hg:`help merge-tools` for options.
4434 configuration files. See :hg:`help merge-tools` for options.
4428
4435
4429 If no revision is specified, the working directory's parent is a
4436 If no revision is specified, the working directory's parent is a
4430 head revision, and the current branch contains exactly one other
4437 head revision, and the current branch contains exactly one other
4431 head, the other head is merged with by default. Otherwise, an
4438 head, the other head is merged with by default. Otherwise, an
4432 explicit revision with which to merge with must be provided.
4439 explicit revision with which to merge with must be provided.
4433
4440
4434 :hg:`resolve` must be used to resolve unresolved files.
4441 :hg:`resolve` must be used to resolve unresolved files.
4435
4442
4436 To undo an uncommitted merge, use :hg:`update --clean .` which
4443 To undo an uncommitted merge, use :hg:`update --clean .` which
4437 will check out a clean copy of the original merge parent, losing
4444 will check out a clean copy of the original merge parent, losing
4438 all changes.
4445 all changes.
4439
4446
4440 Returns 0 on success, 1 if there are unresolved files.
4447 Returns 0 on success, 1 if there are unresolved files.
4441 """
4448 """
4442
4449
4443 if opts.get('rev') and node:
4450 if opts.get('rev') and node:
4444 raise util.Abort(_("please specify just one revision"))
4451 raise util.Abort(_("please specify just one revision"))
4445 if not node:
4452 if not node:
4446 node = opts.get('rev')
4453 node = opts.get('rev')
4447
4454
4448 if node:
4455 if node:
4449 node = scmutil.revsingle(repo, node).node()
4456 node = scmutil.revsingle(repo, node).node()
4450
4457
4451 if not node and repo._bookmarkcurrent:
4458 if not node and repo._bookmarkcurrent:
4452 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4459 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4453 curhead = repo[repo._bookmarkcurrent].node()
4460 curhead = repo[repo._bookmarkcurrent].node()
4454 if len(bmheads) == 2:
4461 if len(bmheads) == 2:
4455 if curhead == bmheads[0]:
4462 if curhead == bmheads[0]:
4456 node = bmheads[1]
4463 node = bmheads[1]
4457 else:
4464 else:
4458 node = bmheads[0]
4465 node = bmheads[0]
4459 elif len(bmheads) > 2:
4466 elif len(bmheads) > 2:
4460 raise util.Abort(_("multiple matching bookmarks to merge - "
4467 raise util.Abort(_("multiple matching bookmarks to merge - "
4461 "please merge with an explicit rev or bookmark"),
4468 "please merge with an explicit rev or bookmark"),
4462 hint=_("run 'hg heads' to see all heads"))
4469 hint=_("run 'hg heads' to see all heads"))
4463 elif len(bmheads) <= 1:
4470 elif len(bmheads) <= 1:
4464 raise util.Abort(_("no matching bookmark to merge - "
4471 raise util.Abort(_("no matching bookmark to merge - "
4465 "please merge with an explicit rev or bookmark"),
4472 "please merge with an explicit rev or bookmark"),
4466 hint=_("run 'hg heads' to see all heads"))
4473 hint=_("run 'hg heads' to see all heads"))
4467
4474
4468 if not node and not repo._bookmarkcurrent:
4475 if not node and not repo._bookmarkcurrent:
4469 branch = repo[None].branch()
4476 branch = repo[None].branch()
4470 bheads = repo.branchheads(branch)
4477 bheads = repo.branchheads(branch)
4471 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4478 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4472
4479
4473 if len(nbhs) > 2:
4480 if len(nbhs) > 2:
4474 raise util.Abort(_("branch '%s' has %d heads - "
4481 raise util.Abort(_("branch '%s' has %d heads - "
4475 "please merge with an explicit rev")
4482 "please merge with an explicit rev")
4476 % (branch, len(bheads)),
4483 % (branch, len(bheads)),
4477 hint=_("run 'hg heads .' to see heads"))
4484 hint=_("run 'hg heads .' to see heads"))
4478
4485
4479 parent = repo.dirstate.p1()
4486 parent = repo.dirstate.p1()
4480 if len(nbhs) <= 1:
4487 if len(nbhs) <= 1:
4481 if len(bheads) > 1:
4488 if len(bheads) > 1:
4482 raise util.Abort(_("heads are bookmarked - "
4489 raise util.Abort(_("heads are bookmarked - "
4483 "please merge with an explicit rev"),
4490 "please merge with an explicit rev"),
4484 hint=_("run 'hg heads' to see all heads"))
4491 hint=_("run 'hg heads' to see all heads"))
4485 if len(repo.heads()) > 1:
4492 if len(repo.heads()) > 1:
4486 raise util.Abort(_("branch '%s' has one head - "
4493 raise util.Abort(_("branch '%s' has one head - "
4487 "please merge with an explicit rev")
4494 "please merge with an explicit rev")
4488 % branch,
4495 % branch,
4489 hint=_("run 'hg heads' to see all heads"))
4496 hint=_("run 'hg heads' to see all heads"))
4490 msg, hint = _('nothing to merge'), None
4497 msg, hint = _('nothing to merge'), None
4491 if parent != repo.lookup(branch):
4498 if parent != repo.lookup(branch):
4492 hint = _("use 'hg update' instead")
4499 hint = _("use 'hg update' instead")
4493 raise util.Abort(msg, hint=hint)
4500 raise util.Abort(msg, hint=hint)
4494
4501
4495 if parent not in bheads:
4502 if parent not in bheads:
4496 raise util.Abort(_('working directory not at a head revision'),
4503 raise util.Abort(_('working directory not at a head revision'),
4497 hint=_("use 'hg update' or merge with an "
4504 hint=_("use 'hg update' or merge with an "
4498 "explicit revision"))
4505 "explicit revision"))
4499 if parent == nbhs[0]:
4506 if parent == nbhs[0]:
4500 node = nbhs[-1]
4507 node = nbhs[-1]
4501 else:
4508 else:
4502 node = nbhs[0]
4509 node = nbhs[0]
4503
4510
4504 if opts.get('preview'):
4511 if opts.get('preview'):
4505 # find nodes that are ancestors of p2 but not of p1
4512 # find nodes that are ancestors of p2 but not of p1
4506 p1 = repo.lookup('.')
4513 p1 = repo.lookup('.')
4507 p2 = repo.lookup(node)
4514 p2 = repo.lookup(node)
4508 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4515 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4509
4516
4510 displayer = cmdutil.show_changeset(ui, repo, opts)
4517 displayer = cmdutil.show_changeset(ui, repo, opts)
4511 for node in nodes:
4518 for node in nodes:
4512 displayer.show(repo[node])
4519 displayer.show(repo[node])
4513 displayer.close()
4520 displayer.close()
4514 return 0
4521 return 0
4515
4522
4516 try:
4523 try:
4517 # ui.forcemerge is an internal variable, do not document
4524 # ui.forcemerge is an internal variable, do not document
4518 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4525 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4519 return hg.merge(repo, node, force=opts.get('force'))
4526 return hg.merge(repo, node, force=opts.get('force'))
4520 finally:
4527 finally:
4521 ui.setconfig('ui', 'forcemerge', '', 'merge')
4528 ui.setconfig('ui', 'forcemerge', '', 'merge')
4522
4529
4523 @command('outgoing|out',
4530 @command('outgoing|out',
4524 [('f', 'force', None, _('run even when the destination is unrelated')),
4531 [('f', 'force', None, _('run even when the destination is unrelated')),
4525 ('r', 'rev', [],
4532 ('r', 'rev', [],
4526 _('a changeset intended to be included in the destination'), _('REV')),
4533 _('a changeset intended to be included in the destination'), _('REV')),
4527 ('n', 'newest-first', None, _('show newest record first')),
4534 ('n', 'newest-first', None, _('show newest record first')),
4528 ('B', 'bookmarks', False, _('compare bookmarks')),
4535 ('B', 'bookmarks', False, _('compare bookmarks')),
4529 ('b', 'branch', [], _('a specific branch you would like to push'),
4536 ('b', 'branch', [], _('a specific branch you would like to push'),
4530 _('BRANCH')),
4537 _('BRANCH')),
4531 ] + logopts + remoteopts + subrepoopts,
4538 ] + logopts + remoteopts + subrepoopts,
4532 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4539 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4533 def outgoing(ui, repo, dest=None, **opts):
4540 def outgoing(ui, repo, dest=None, **opts):
4534 """show changesets not found in the destination
4541 """show changesets not found in the destination
4535
4542
4536 Show changesets not found in the specified destination repository
4543 Show changesets not found in the specified destination repository
4537 or the default push location. These are the changesets that would
4544 or the default push location. These are the changesets that would
4538 be pushed if a push was requested.
4545 be pushed if a push was requested.
4539
4546
4540 See pull for details of valid destination formats.
4547 See pull for details of valid destination formats.
4541
4548
4542 Returns 0 if there are outgoing changes, 1 otherwise.
4549 Returns 0 if there are outgoing changes, 1 otherwise.
4543 """
4550 """
4544 if opts.get('graph'):
4551 if opts.get('graph'):
4545 cmdutil.checkunsupportedgraphflags([], opts)
4552 cmdutil.checkunsupportedgraphflags([], opts)
4546 o, other = hg._outgoing(ui, repo, dest, opts)
4553 o, other = hg._outgoing(ui, repo, dest, opts)
4547 if not o:
4554 if not o:
4548 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4555 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4549 return
4556 return
4550
4557
4551 revdag = cmdutil.graphrevs(repo, o, opts)
4558 revdag = cmdutil.graphrevs(repo, o, opts)
4552 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4559 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4553 showparents = [ctx.node() for ctx in repo[None].parents()]
4560 showparents = [ctx.node() for ctx in repo[None].parents()]
4554 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4561 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4555 graphmod.asciiedges)
4562 graphmod.asciiedges)
4556 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4563 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4557 return 0
4564 return 0
4558
4565
4559 if opts.get('bookmarks'):
4566 if opts.get('bookmarks'):
4560 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4567 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4561 dest, branches = hg.parseurl(dest, opts.get('branch'))
4568 dest, branches = hg.parseurl(dest, opts.get('branch'))
4562 other = hg.peer(repo, opts, dest)
4569 other = hg.peer(repo, opts, dest)
4563 if 'bookmarks' not in other.listkeys('namespaces'):
4570 if 'bookmarks' not in other.listkeys('namespaces'):
4564 ui.warn(_("remote doesn't support bookmarks\n"))
4571 ui.warn(_("remote doesn't support bookmarks\n"))
4565 return 0
4572 return 0
4566 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4573 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4567 return bookmarks.diff(ui, other, repo)
4574 return bookmarks.diff(ui, other, repo)
4568
4575
4569 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4576 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4570 try:
4577 try:
4571 return hg.outgoing(ui, repo, dest, opts)
4578 return hg.outgoing(ui, repo, dest, opts)
4572 finally:
4579 finally:
4573 del repo._subtoppath
4580 del repo._subtoppath
4574
4581
4575 @command('parents',
4582 @command('parents',
4576 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4583 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4577 ] + templateopts,
4584 ] + templateopts,
4578 _('[-r REV] [FILE]'),
4585 _('[-r REV] [FILE]'),
4579 inferrepo=True)
4586 inferrepo=True)
4580 def parents(ui, repo, file_=None, **opts):
4587 def parents(ui, repo, file_=None, **opts):
4581 """show the parents of the working directory or revision
4588 """show the parents of the working directory or revision
4582
4589
4583 Print the working directory's parent revisions. If a revision is
4590 Print the working directory's parent revisions. If a revision is
4584 given via -r/--rev, the parent of that revision will be printed.
4591 given via -r/--rev, the parent of that revision will be printed.
4585 If a file argument is given, the revision in which the file was
4592 If a file argument is given, the revision in which the file was
4586 last changed (before the working directory revision or the
4593 last changed (before the working directory revision or the
4587 argument to --rev if given) is printed.
4594 argument to --rev if given) is printed.
4588
4595
4589 Returns 0 on success.
4596 Returns 0 on success.
4590 """
4597 """
4591
4598
4592 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4599 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4593
4600
4594 if file_:
4601 if file_:
4595 m = scmutil.match(ctx, (file_,), opts)
4602 m = scmutil.match(ctx, (file_,), opts)
4596 if m.anypats() or len(m.files()) != 1:
4603 if m.anypats() or len(m.files()) != 1:
4597 raise util.Abort(_('can only specify an explicit filename'))
4604 raise util.Abort(_('can only specify an explicit filename'))
4598 file_ = m.files()[0]
4605 file_ = m.files()[0]
4599 filenodes = []
4606 filenodes = []
4600 for cp in ctx.parents():
4607 for cp in ctx.parents():
4601 if not cp:
4608 if not cp:
4602 continue
4609 continue
4603 try:
4610 try:
4604 filenodes.append(cp.filenode(file_))
4611 filenodes.append(cp.filenode(file_))
4605 except error.LookupError:
4612 except error.LookupError:
4606 pass
4613 pass
4607 if not filenodes:
4614 if not filenodes:
4608 raise util.Abort(_("'%s' not found in manifest!") % file_)
4615 raise util.Abort(_("'%s' not found in manifest!") % file_)
4609 p = []
4616 p = []
4610 for fn in filenodes:
4617 for fn in filenodes:
4611 fctx = repo.filectx(file_, fileid=fn)
4618 fctx = repo.filectx(file_, fileid=fn)
4612 p.append(fctx.node())
4619 p.append(fctx.node())
4613 else:
4620 else:
4614 p = [cp.node() for cp in ctx.parents()]
4621 p = [cp.node() for cp in ctx.parents()]
4615
4622
4616 displayer = cmdutil.show_changeset(ui, repo, opts)
4623 displayer = cmdutil.show_changeset(ui, repo, opts)
4617 for n in p:
4624 for n in p:
4618 if n != nullid:
4625 if n != nullid:
4619 displayer.show(repo[n])
4626 displayer.show(repo[n])
4620 displayer.close()
4627 displayer.close()
4621
4628
4622 @command('paths', [], _('[NAME]'), optionalrepo=True)
4629 @command('paths', [], _('[NAME]'), optionalrepo=True)
4623 def paths(ui, repo, search=None):
4630 def paths(ui, repo, search=None):
4624 """show aliases for remote repositories
4631 """show aliases for remote repositories
4625
4632
4626 Show definition of symbolic path name NAME. If no name is given,
4633 Show definition of symbolic path name NAME. If no name is given,
4627 show definition of all available names.
4634 show definition of all available names.
4628
4635
4629 Option -q/--quiet suppresses all output when searching for NAME
4636 Option -q/--quiet suppresses all output when searching for NAME
4630 and shows only the path names when listing all definitions.
4637 and shows only the path names when listing all definitions.
4631
4638
4632 Path names are defined in the [paths] section of your
4639 Path names are defined in the [paths] section of your
4633 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4640 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4634 repository, ``.hg/hgrc`` is used, too.
4641 repository, ``.hg/hgrc`` is used, too.
4635
4642
4636 The path names ``default`` and ``default-push`` have a special
4643 The path names ``default`` and ``default-push`` have a special
4637 meaning. When performing a push or pull operation, they are used
4644 meaning. When performing a push or pull operation, they are used
4638 as fallbacks if no location is specified on the command-line.
4645 as fallbacks if no location is specified on the command-line.
4639 When ``default-push`` is set, it will be used for push and
4646 When ``default-push`` is set, it will be used for push and
4640 ``default`` will be used for pull; otherwise ``default`` is used
4647 ``default`` will be used for pull; otherwise ``default`` is used
4641 as the fallback for both. When cloning a repository, the clone
4648 as the fallback for both. When cloning a repository, the clone
4642 source is written as ``default`` in ``.hg/hgrc``. Note that
4649 source is written as ``default`` in ``.hg/hgrc``. Note that
4643 ``default`` and ``default-push`` apply to all inbound (e.g.
4650 ``default`` and ``default-push`` apply to all inbound (e.g.
4644 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4651 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4645 :hg:`bundle`) operations.
4652 :hg:`bundle`) operations.
4646
4653
4647 See :hg:`help urls` for more information.
4654 See :hg:`help urls` for more information.
4648
4655
4649 Returns 0 on success.
4656 Returns 0 on success.
4650 """
4657 """
4651 if search:
4658 if search:
4652 for name, path in ui.configitems("paths"):
4659 for name, path in ui.configitems("paths"):
4653 if name == search:
4660 if name == search:
4654 ui.status("%s\n" % util.hidepassword(path))
4661 ui.status("%s\n" % util.hidepassword(path))
4655 return
4662 return
4656 if not ui.quiet:
4663 if not ui.quiet:
4657 ui.warn(_("not found!\n"))
4664 ui.warn(_("not found!\n"))
4658 return 1
4665 return 1
4659 else:
4666 else:
4660 for name, path in ui.configitems("paths"):
4667 for name, path in ui.configitems("paths"):
4661 if ui.quiet:
4668 if ui.quiet:
4662 ui.write("%s\n" % name)
4669 ui.write("%s\n" % name)
4663 else:
4670 else:
4664 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4671 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4665
4672
4666 @command('phase',
4673 @command('phase',
4667 [('p', 'public', False, _('set changeset phase to public')),
4674 [('p', 'public', False, _('set changeset phase to public')),
4668 ('d', 'draft', False, _('set changeset phase to draft')),
4675 ('d', 'draft', False, _('set changeset phase to draft')),
4669 ('s', 'secret', False, _('set changeset phase to secret')),
4676 ('s', 'secret', False, _('set changeset phase to secret')),
4670 ('f', 'force', False, _('allow to move boundary backward')),
4677 ('f', 'force', False, _('allow to move boundary backward')),
4671 ('r', 'rev', [], _('target revision'), _('REV')),
4678 ('r', 'rev', [], _('target revision'), _('REV')),
4672 ],
4679 ],
4673 _('[-p|-d|-s] [-f] [-r] REV...'))
4680 _('[-p|-d|-s] [-f] [-r] REV...'))
4674 def phase(ui, repo, *revs, **opts):
4681 def phase(ui, repo, *revs, **opts):
4675 """set or show the current phase name
4682 """set or show the current phase name
4676
4683
4677 With no argument, show the phase name of specified revisions.
4684 With no argument, show the phase name of specified revisions.
4678
4685
4679 With one of -p/--public, -d/--draft or -s/--secret, change the
4686 With one of -p/--public, -d/--draft or -s/--secret, change the
4680 phase value of the specified revisions.
4687 phase value of the specified revisions.
4681
4688
4682 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4689 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4683 lower phase to an higher phase. Phases are ordered as follows::
4690 lower phase to an higher phase. Phases are ordered as follows::
4684
4691
4685 public < draft < secret
4692 public < draft < secret
4686
4693
4687 Returns 0 on success, 1 if no phases were changed or some could not
4694 Returns 0 on success, 1 if no phases were changed or some could not
4688 be changed.
4695 be changed.
4689 """
4696 """
4690 # search for a unique phase argument
4697 # search for a unique phase argument
4691 targetphase = None
4698 targetphase = None
4692 for idx, name in enumerate(phases.phasenames):
4699 for idx, name in enumerate(phases.phasenames):
4693 if opts[name]:
4700 if opts[name]:
4694 if targetphase is not None:
4701 if targetphase is not None:
4695 raise util.Abort(_('only one phase can be specified'))
4702 raise util.Abort(_('only one phase can be specified'))
4696 targetphase = idx
4703 targetphase = idx
4697
4704
4698 # look for specified revision
4705 # look for specified revision
4699 revs = list(revs)
4706 revs = list(revs)
4700 revs.extend(opts['rev'])
4707 revs.extend(opts['rev'])
4701 if not revs:
4708 if not revs:
4702 raise util.Abort(_('no revisions specified'))
4709 raise util.Abort(_('no revisions specified'))
4703
4710
4704 revs = scmutil.revrange(repo, revs)
4711 revs = scmutil.revrange(repo, revs)
4705
4712
4706 lock = None
4713 lock = None
4707 ret = 0
4714 ret = 0
4708 if targetphase is None:
4715 if targetphase is None:
4709 # display
4716 # display
4710 for r in revs:
4717 for r in revs:
4711 ctx = repo[r]
4718 ctx = repo[r]
4712 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4719 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4713 else:
4720 else:
4714 tr = None
4721 tr = None
4715 lock = repo.lock()
4722 lock = repo.lock()
4716 try:
4723 try:
4717 tr = repo.transaction("phase")
4724 tr = repo.transaction("phase")
4718 # set phase
4725 # set phase
4719 if not revs:
4726 if not revs:
4720 raise util.Abort(_('empty revision set'))
4727 raise util.Abort(_('empty revision set'))
4721 nodes = [repo[r].node() for r in revs]
4728 nodes = [repo[r].node() for r in revs]
4722 olddata = repo._phasecache.getphaserevs(repo)[:]
4729 olddata = repo._phasecache.getphaserevs(repo)[:]
4723 phases.advanceboundary(repo, tr, targetphase, nodes)
4730 phases.advanceboundary(repo, tr, targetphase, nodes)
4724 if opts['force']:
4731 if opts['force']:
4725 phases.retractboundary(repo, tr, targetphase, nodes)
4732 phases.retractboundary(repo, tr, targetphase, nodes)
4726 tr.close()
4733 tr.close()
4727 finally:
4734 finally:
4728 if tr is not None:
4735 if tr is not None:
4729 tr.release()
4736 tr.release()
4730 lock.release()
4737 lock.release()
4731 # moving revision from public to draft may hide them
4738 # moving revision from public to draft may hide them
4732 # We have to check result on an unfiltered repository
4739 # We have to check result on an unfiltered repository
4733 unfi = repo.unfiltered()
4740 unfi = repo.unfiltered()
4734 newdata = repo._phasecache.getphaserevs(unfi)
4741 newdata = repo._phasecache.getphaserevs(unfi)
4735 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4742 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4736 cl = unfi.changelog
4743 cl = unfi.changelog
4737 rejected = [n for n in nodes
4744 rejected = [n for n in nodes
4738 if newdata[cl.rev(n)] < targetphase]
4745 if newdata[cl.rev(n)] < targetphase]
4739 if rejected:
4746 if rejected:
4740 ui.warn(_('cannot move %i changesets to a higher '
4747 ui.warn(_('cannot move %i changesets to a higher '
4741 'phase, use --force\n') % len(rejected))
4748 'phase, use --force\n') % len(rejected))
4742 ret = 1
4749 ret = 1
4743 if changes:
4750 if changes:
4744 msg = _('phase changed for %i changesets\n') % changes
4751 msg = _('phase changed for %i changesets\n') % changes
4745 if ret:
4752 if ret:
4746 ui.status(msg)
4753 ui.status(msg)
4747 else:
4754 else:
4748 ui.note(msg)
4755 ui.note(msg)
4749 else:
4756 else:
4750 ui.warn(_('no phases changed\n'))
4757 ui.warn(_('no phases changed\n'))
4751 ret = 1
4758 ret = 1
4752 return ret
4759 return ret
4753
4760
4754 def postincoming(ui, repo, modheads, optupdate, checkout):
4761 def postincoming(ui, repo, modheads, optupdate, checkout):
4755 if modheads == 0:
4762 if modheads == 0:
4756 return
4763 return
4757 if optupdate:
4764 if optupdate:
4758 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4765 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4759 try:
4766 try:
4760 ret = hg.update(repo, checkout)
4767 ret = hg.update(repo, checkout)
4761 except util.Abort, inst:
4768 except util.Abort, inst:
4762 ui.warn(_("not updating: %s\n") % str(inst))
4769 ui.warn(_("not updating: %s\n") % str(inst))
4763 if inst.hint:
4770 if inst.hint:
4764 ui.warn(_("(%s)\n") % inst.hint)
4771 ui.warn(_("(%s)\n") % inst.hint)
4765 return 0
4772 return 0
4766 if not ret and not checkout:
4773 if not ret and not checkout:
4767 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4774 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4768 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4775 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4769 return ret
4776 return ret
4770 if modheads > 1:
4777 if modheads > 1:
4771 currentbranchheads = len(repo.branchheads())
4778 currentbranchheads = len(repo.branchheads())
4772 if currentbranchheads == modheads:
4779 if currentbranchheads == modheads:
4773 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4780 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4774 elif currentbranchheads > 1:
4781 elif currentbranchheads > 1:
4775 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4782 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4776 "merge)\n"))
4783 "merge)\n"))
4777 else:
4784 else:
4778 ui.status(_("(run 'hg heads' to see heads)\n"))
4785 ui.status(_("(run 'hg heads' to see heads)\n"))
4779 else:
4786 else:
4780 ui.status(_("(run 'hg update' to get a working copy)\n"))
4787 ui.status(_("(run 'hg update' to get a working copy)\n"))
4781
4788
4782 @command('^pull',
4789 @command('^pull',
4783 [('u', 'update', None,
4790 [('u', 'update', None,
4784 _('update to new branch head if changesets were pulled')),
4791 _('update to new branch head if changesets were pulled')),
4785 ('f', 'force', None, _('run even when remote repository is unrelated')),
4792 ('f', 'force', None, _('run even when remote repository is unrelated')),
4786 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4793 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4787 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4794 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4788 ('b', 'branch', [], _('a specific branch you would like to pull'),
4795 ('b', 'branch', [], _('a specific branch you would like to pull'),
4789 _('BRANCH')),
4796 _('BRANCH')),
4790 ] + remoteopts,
4797 ] + remoteopts,
4791 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4798 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4792 def pull(ui, repo, source="default", **opts):
4799 def pull(ui, repo, source="default", **opts):
4793 """pull changes from the specified source
4800 """pull changes from the specified source
4794
4801
4795 Pull changes from a remote repository to a local one.
4802 Pull changes from a remote repository to a local one.
4796
4803
4797 This finds all changes from the repository at the specified path
4804 This finds all changes from the repository at the specified path
4798 or URL and adds them to a local repository (the current one unless
4805 or URL and adds them to a local repository (the current one unless
4799 -R is specified). By default, this does not update the copy of the
4806 -R is specified). By default, this does not update the copy of the
4800 project in the working directory.
4807 project in the working directory.
4801
4808
4802 Use :hg:`incoming` if you want to see what would have been added
4809 Use :hg:`incoming` if you want to see what would have been added
4803 by a pull at the time you issued this command. If you then decide
4810 by a pull at the time you issued this command. If you then decide
4804 to add those changes to the repository, you should use :hg:`pull
4811 to add those changes to the repository, you should use :hg:`pull
4805 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4812 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4806
4813
4807 If SOURCE is omitted, the 'default' path will be used.
4814 If SOURCE is omitted, the 'default' path will be used.
4808 See :hg:`help urls` for more information.
4815 See :hg:`help urls` for more information.
4809
4816
4810 Returns 0 on success, 1 if an update had unresolved files.
4817 Returns 0 on success, 1 if an update had unresolved files.
4811 """
4818 """
4812 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4819 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4813 other = hg.peer(repo, opts, source)
4820 other = hg.peer(repo, opts, source)
4814 try:
4821 try:
4815 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4822 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4816 revs, checkout = hg.addbranchrevs(repo, other, branches,
4823 revs, checkout = hg.addbranchrevs(repo, other, branches,
4817 opts.get('rev'))
4824 opts.get('rev'))
4818
4825
4819 remotebookmarks = other.listkeys('bookmarks')
4826 remotebookmarks = other.listkeys('bookmarks')
4820
4827
4821 if opts.get('bookmark'):
4828 if opts.get('bookmark'):
4822 if not revs:
4829 if not revs:
4823 revs = []
4830 revs = []
4824 for b in opts['bookmark']:
4831 for b in opts['bookmark']:
4825 if b not in remotebookmarks:
4832 if b not in remotebookmarks:
4826 raise util.Abort(_('remote bookmark %s not found!') % b)
4833 raise util.Abort(_('remote bookmark %s not found!') % b)
4827 revs.append(remotebookmarks[b])
4834 revs.append(remotebookmarks[b])
4828
4835
4829 if revs:
4836 if revs:
4830 try:
4837 try:
4831 revs = [other.lookup(rev) for rev in revs]
4838 revs = [other.lookup(rev) for rev in revs]
4832 except error.CapabilityError:
4839 except error.CapabilityError:
4833 err = _("other repository doesn't support revision lookup, "
4840 err = _("other repository doesn't support revision lookup, "
4834 "so a rev cannot be specified.")
4841 "so a rev cannot be specified.")
4835 raise util.Abort(err)
4842 raise util.Abort(err)
4836
4843
4837 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4844 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4838 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4845 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4839 if checkout:
4846 if checkout:
4840 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4847 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4841 repo._subtoppath = source
4848 repo._subtoppath = source
4842 try:
4849 try:
4843 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4850 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4844
4851
4845 finally:
4852 finally:
4846 del repo._subtoppath
4853 del repo._subtoppath
4847
4854
4848 # update specified bookmarks
4855 # update specified bookmarks
4849 if opts.get('bookmark'):
4856 if opts.get('bookmark'):
4850 marks = repo._bookmarks
4857 marks = repo._bookmarks
4851 for b in opts['bookmark']:
4858 for b in opts['bookmark']:
4852 # explicit pull overrides local bookmark if any
4859 # explicit pull overrides local bookmark if any
4853 ui.status(_("importing bookmark %s\n") % b)
4860 ui.status(_("importing bookmark %s\n") % b)
4854 marks[b] = repo[remotebookmarks[b]].node()
4861 marks[b] = repo[remotebookmarks[b]].node()
4855 marks.write()
4862 marks.write()
4856 finally:
4863 finally:
4857 other.close()
4864 other.close()
4858 return ret
4865 return ret
4859
4866
4860 @command('^push',
4867 @command('^push',
4861 [('f', 'force', None, _('force push')),
4868 [('f', 'force', None, _('force push')),
4862 ('r', 'rev', [],
4869 ('r', 'rev', [],
4863 _('a changeset intended to be included in the destination'),
4870 _('a changeset intended to be included in the destination'),
4864 _('REV')),
4871 _('REV')),
4865 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4872 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4866 ('b', 'branch', [],
4873 ('b', 'branch', [],
4867 _('a specific branch you would like to push'), _('BRANCH')),
4874 _('a specific branch you would like to push'), _('BRANCH')),
4868 ('', 'new-branch', False, _('allow pushing a new branch')),
4875 ('', 'new-branch', False, _('allow pushing a new branch')),
4869 ] + remoteopts,
4876 ] + remoteopts,
4870 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4877 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4871 def push(ui, repo, dest=None, **opts):
4878 def push(ui, repo, dest=None, **opts):
4872 """push changes to the specified destination
4879 """push changes to the specified destination
4873
4880
4874 Push changesets from the local repository to the specified
4881 Push changesets from the local repository to the specified
4875 destination.
4882 destination.
4876
4883
4877 This operation is symmetrical to pull: it is identical to a pull
4884 This operation is symmetrical to pull: it is identical to a pull
4878 in the destination repository from the current one.
4885 in the destination repository from the current one.
4879
4886
4880 By default, push will not allow creation of new heads at the
4887 By default, push will not allow creation of new heads at the
4881 destination, since multiple heads would make it unclear which head
4888 destination, since multiple heads would make it unclear which head
4882 to use. In this situation, it is recommended to pull and merge
4889 to use. In this situation, it is recommended to pull and merge
4883 before pushing.
4890 before pushing.
4884
4891
4885 Use --new-branch if you want to allow push to create a new named
4892 Use --new-branch if you want to allow push to create a new named
4886 branch that is not present at the destination. This allows you to
4893 branch that is not present at the destination. This allows you to
4887 only create a new branch without forcing other changes.
4894 only create a new branch without forcing other changes.
4888
4895
4889 .. note::
4896 .. note::
4890
4897
4891 Extra care should be taken with the -f/--force option,
4898 Extra care should be taken with the -f/--force option,
4892 which will push all new heads on all branches, an action which will
4899 which will push all new heads on all branches, an action which will
4893 almost always cause confusion for collaborators.
4900 almost always cause confusion for collaborators.
4894
4901
4895 If -r/--rev is used, the specified revision and all its ancestors
4902 If -r/--rev is used, the specified revision and all its ancestors
4896 will be pushed to the remote repository.
4903 will be pushed to the remote repository.
4897
4904
4898 If -B/--bookmark is used, the specified bookmarked revision, its
4905 If -B/--bookmark is used, the specified bookmarked revision, its
4899 ancestors, and the bookmark will be pushed to the remote
4906 ancestors, and the bookmark will be pushed to the remote
4900 repository.
4907 repository.
4901
4908
4902 Please see :hg:`help urls` for important details about ``ssh://``
4909 Please see :hg:`help urls` for important details about ``ssh://``
4903 URLs. If DESTINATION is omitted, a default path will be used.
4910 URLs. If DESTINATION is omitted, a default path will be used.
4904
4911
4905 Returns 0 if push was successful, 1 if nothing to push.
4912 Returns 0 if push was successful, 1 if nothing to push.
4906 """
4913 """
4907
4914
4908 if opts.get('bookmark'):
4915 if opts.get('bookmark'):
4909 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4916 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4910 for b in opts['bookmark']:
4917 for b in opts['bookmark']:
4911 # translate -B options to -r so changesets get pushed
4918 # translate -B options to -r so changesets get pushed
4912 if b in repo._bookmarks:
4919 if b in repo._bookmarks:
4913 opts.setdefault('rev', []).append(b)
4920 opts.setdefault('rev', []).append(b)
4914 else:
4921 else:
4915 # if we try to push a deleted bookmark, translate it to null
4922 # if we try to push a deleted bookmark, translate it to null
4916 # this lets simultaneous -r, -b options continue working
4923 # this lets simultaneous -r, -b options continue working
4917 opts.setdefault('rev', []).append("null")
4924 opts.setdefault('rev', []).append("null")
4918
4925
4919 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4926 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4920 dest, branches = hg.parseurl(dest, opts.get('branch'))
4927 dest, branches = hg.parseurl(dest, opts.get('branch'))
4921 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4928 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4922 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4929 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4923 try:
4930 try:
4924 other = hg.peer(repo, opts, dest)
4931 other = hg.peer(repo, opts, dest)
4925 except error.RepoError:
4932 except error.RepoError:
4926 if dest == "default-push":
4933 if dest == "default-push":
4927 raise util.Abort(_("default repository not configured!"),
4934 raise util.Abort(_("default repository not configured!"),
4928 hint=_('see the "path" section in "hg help config"'))
4935 hint=_('see the "path" section in "hg help config"'))
4929 else:
4936 else:
4930 raise
4937 raise
4931
4938
4932 if revs:
4939 if revs:
4933 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4940 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4934
4941
4935 repo._subtoppath = dest
4942 repo._subtoppath = dest
4936 try:
4943 try:
4937 # push subrepos depth-first for coherent ordering
4944 # push subrepos depth-first for coherent ordering
4938 c = repo['']
4945 c = repo['']
4939 subs = c.substate # only repos that are committed
4946 subs = c.substate # only repos that are committed
4940 for s in sorted(subs):
4947 for s in sorted(subs):
4941 result = c.sub(s).push(opts)
4948 result = c.sub(s).push(opts)
4942 if result == 0:
4949 if result == 0:
4943 return not result
4950 return not result
4944 finally:
4951 finally:
4945 del repo._subtoppath
4952 del repo._subtoppath
4946 result = repo.push(other, opts.get('force'), revs=revs,
4953 result = repo.push(other, opts.get('force'), revs=revs,
4947 newbranch=opts.get('new_branch'))
4954 newbranch=opts.get('new_branch'))
4948
4955
4949 result = not result
4956 result = not result
4950
4957
4951 if opts.get('bookmark'):
4958 if opts.get('bookmark'):
4952 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4959 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4953 if bresult == 2:
4960 if bresult == 2:
4954 return 2
4961 return 2
4955 if not result and bresult:
4962 if not result and bresult:
4956 result = 2
4963 result = 2
4957
4964
4958 return result
4965 return result
4959
4966
4960 @command('recover', [])
4967 @command('recover', [])
4961 def recover(ui, repo):
4968 def recover(ui, repo):
4962 """roll back an interrupted transaction
4969 """roll back an interrupted transaction
4963
4970
4964 Recover from an interrupted commit or pull.
4971 Recover from an interrupted commit or pull.
4965
4972
4966 This command tries to fix the repository status after an
4973 This command tries to fix the repository status after an
4967 interrupted operation. It should only be necessary when Mercurial
4974 interrupted operation. It should only be necessary when Mercurial
4968 suggests it.
4975 suggests it.
4969
4976
4970 Returns 0 if successful, 1 if nothing to recover or verify fails.
4977 Returns 0 if successful, 1 if nothing to recover or verify fails.
4971 """
4978 """
4972 if repo.recover():
4979 if repo.recover():
4973 return hg.verify(repo)
4980 return hg.verify(repo)
4974 return 1
4981 return 1
4975
4982
4976 @command('^remove|rm',
4983 @command('^remove|rm',
4977 [('A', 'after', None, _('record delete for missing files')),
4984 [('A', 'after', None, _('record delete for missing files')),
4978 ('f', 'force', None,
4985 ('f', 'force', None,
4979 _('remove (and delete) file even if added or modified')),
4986 _('remove (and delete) file even if added or modified')),
4980 ] + walkopts,
4987 ] + walkopts,
4981 _('[OPTION]... FILE...'),
4988 _('[OPTION]... FILE...'),
4982 inferrepo=True)
4989 inferrepo=True)
4983 def remove(ui, repo, *pats, **opts):
4990 def remove(ui, repo, *pats, **opts):
4984 """remove the specified files on the next commit
4991 """remove the specified files on the next commit
4985
4992
4986 Schedule the indicated files for removal from the current branch.
4993 Schedule the indicated files for removal from the current branch.
4987
4994
4988 This command schedules the files to be removed at the next commit.
4995 This command schedules the files to be removed at the next commit.
4989 To undo a remove before that, see :hg:`revert`. To undo added
4996 To undo a remove before that, see :hg:`revert`. To undo added
4990 files, see :hg:`forget`.
4997 files, see :hg:`forget`.
4991
4998
4992 .. container:: verbose
4999 .. container:: verbose
4993
5000
4994 -A/--after can be used to remove only files that have already
5001 -A/--after can be used to remove only files that have already
4995 been deleted, -f/--force can be used to force deletion, and -Af
5002 been deleted, -f/--force can be used to force deletion, and -Af
4996 can be used to remove files from the next revision without
5003 can be used to remove files from the next revision without
4997 deleting them from the working directory.
5004 deleting them from the working directory.
4998
5005
4999 The following table details the behavior of remove for different
5006 The following table details the behavior of remove for different
5000 file states (columns) and option combinations (rows). The file
5007 file states (columns) and option combinations (rows). The file
5001 states are Added [A], Clean [C], Modified [M] and Missing [!]
5008 states are Added [A], Clean [C], Modified [M] and Missing [!]
5002 (as reported by :hg:`status`). The actions are Warn, Remove
5009 (as reported by :hg:`status`). The actions are Warn, Remove
5003 (from branch) and Delete (from disk):
5010 (from branch) and Delete (from disk):
5004
5011
5005 ========= == == == ==
5012 ========= == == == ==
5006 opt/state A C M !
5013 opt/state A C M !
5007 ========= == == == ==
5014 ========= == == == ==
5008 none W RD W R
5015 none W RD W R
5009 -f R RD RD R
5016 -f R RD RD R
5010 -A W W W R
5017 -A W W W R
5011 -Af R R R R
5018 -Af R R R R
5012 ========= == == == ==
5019 ========= == == == ==
5013
5020
5014 Note that remove never deletes files in Added [A] state from the
5021 Note that remove never deletes files in Added [A] state from the
5015 working directory, not even if option --force is specified.
5022 working directory, not even if option --force is specified.
5016
5023
5017 Returns 0 on success, 1 if any warnings encountered.
5024 Returns 0 on success, 1 if any warnings encountered.
5018 """
5025 """
5019
5026
5020 ret = 0
5027 ret = 0
5021 after, force = opts.get('after'), opts.get('force')
5028 after, force = opts.get('after'), opts.get('force')
5022 if not pats and not after:
5029 if not pats and not after:
5023 raise util.Abort(_('no files specified'))
5030 raise util.Abort(_('no files specified'))
5024
5031
5025 m = scmutil.match(repo[None], pats, opts)
5032 m = scmutil.match(repo[None], pats, opts)
5026 s = repo.status(match=m, clean=True)
5033 s = repo.status(match=m, clean=True)
5027 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5034 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5028
5035
5029 # warn about failure to delete explicit files/dirs
5036 # warn about failure to delete explicit files/dirs
5030 wctx = repo[None]
5037 wctx = repo[None]
5031 for f in m.files():
5038 for f in m.files():
5032 if f in repo.dirstate or f in wctx.dirs():
5039 if f in repo.dirstate or f in wctx.dirs():
5033 continue
5040 continue
5034 if os.path.exists(m.rel(f)):
5041 if os.path.exists(m.rel(f)):
5035 if os.path.isdir(m.rel(f)):
5042 if os.path.isdir(m.rel(f)):
5036 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5043 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5037 else:
5044 else:
5038 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5045 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5039 # missing files will generate a warning elsewhere
5046 # missing files will generate a warning elsewhere
5040 ret = 1
5047 ret = 1
5041
5048
5042 if force:
5049 if force:
5043 list = modified + deleted + clean + added
5050 list = modified + deleted + clean + added
5044 elif after:
5051 elif after:
5045 list = deleted
5052 list = deleted
5046 for f in modified + added + clean:
5053 for f in modified + added + clean:
5047 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5054 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5048 ret = 1
5055 ret = 1
5049 else:
5056 else:
5050 list = deleted + clean
5057 list = deleted + clean
5051 for f in modified:
5058 for f in modified:
5052 ui.warn(_('not removing %s: file is modified (use -f'
5059 ui.warn(_('not removing %s: file is modified (use -f'
5053 ' to force removal)\n') % m.rel(f))
5060 ' to force removal)\n') % m.rel(f))
5054 ret = 1
5061 ret = 1
5055 for f in added:
5062 for f in added:
5056 ui.warn(_('not removing %s: file has been marked for add'
5063 ui.warn(_('not removing %s: file has been marked for add'
5057 ' (use forget to undo)\n') % m.rel(f))
5064 ' (use forget to undo)\n') % m.rel(f))
5058 ret = 1
5065 ret = 1
5059
5066
5060 for f in sorted(list):
5067 for f in sorted(list):
5061 if ui.verbose or not m.exact(f):
5068 if ui.verbose or not m.exact(f):
5062 ui.status(_('removing %s\n') % m.rel(f))
5069 ui.status(_('removing %s\n') % m.rel(f))
5063
5070
5064 wlock = repo.wlock()
5071 wlock = repo.wlock()
5065 try:
5072 try:
5066 if not after:
5073 if not after:
5067 for f in list:
5074 for f in list:
5068 if f in added:
5075 if f in added:
5069 continue # we never unlink added files on remove
5076 continue # we never unlink added files on remove
5070 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5077 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5071 repo[None].forget(list)
5078 repo[None].forget(list)
5072 finally:
5079 finally:
5073 wlock.release()
5080 wlock.release()
5074
5081
5075 return ret
5082 return ret
5076
5083
5077 @command('rename|move|mv',
5084 @command('rename|move|mv',
5078 [('A', 'after', None, _('record a rename that has already occurred')),
5085 [('A', 'after', None, _('record a rename that has already occurred')),
5079 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5086 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5080 ] + walkopts + dryrunopts,
5087 ] + walkopts + dryrunopts,
5081 _('[OPTION]... SOURCE... DEST'))
5088 _('[OPTION]... SOURCE... DEST'))
5082 def rename(ui, repo, *pats, **opts):
5089 def rename(ui, repo, *pats, **opts):
5083 """rename files; equivalent of copy + remove
5090 """rename files; equivalent of copy + remove
5084
5091
5085 Mark dest as copies of sources; mark sources for deletion. If dest
5092 Mark dest as copies of sources; mark sources for deletion. If dest
5086 is a directory, copies are put in that directory. If dest is a
5093 is a directory, copies are put in that directory. If dest is a
5087 file, there can only be one source.
5094 file, there can only be one source.
5088
5095
5089 By default, this command copies the contents of files as they
5096 By default, this command copies the contents of files as they
5090 exist in the working directory. If invoked with -A/--after, the
5097 exist in the working directory. If invoked with -A/--after, the
5091 operation is recorded, but no copying is performed.
5098 operation is recorded, but no copying is performed.
5092
5099
5093 This command takes effect at the next commit. To undo a rename
5100 This command takes effect at the next commit. To undo a rename
5094 before that, see :hg:`revert`.
5101 before that, see :hg:`revert`.
5095
5102
5096 Returns 0 on success, 1 if errors are encountered.
5103 Returns 0 on success, 1 if errors are encountered.
5097 """
5104 """
5098 wlock = repo.wlock(False)
5105 wlock = repo.wlock(False)
5099 try:
5106 try:
5100 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5107 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5101 finally:
5108 finally:
5102 wlock.release()
5109 wlock.release()
5103
5110
5104 @command('resolve',
5111 @command('resolve',
5105 [('a', 'all', None, _('select all unresolved files')),
5112 [('a', 'all', None, _('select all unresolved files')),
5106 ('l', 'list', None, _('list state of files needing merge')),
5113 ('l', 'list', None, _('list state of files needing merge')),
5107 ('m', 'mark', None, _('mark files as resolved')),
5114 ('m', 'mark', None, _('mark files as resolved')),
5108 ('u', 'unmark', None, _('mark files as unresolved')),
5115 ('u', 'unmark', None, _('mark files as unresolved')),
5109 ('n', 'no-status', None, _('hide status prefix'))]
5116 ('n', 'no-status', None, _('hide status prefix'))]
5110 + mergetoolopts + walkopts,
5117 + mergetoolopts + walkopts,
5111 _('[OPTION]... [FILE]...'),
5118 _('[OPTION]... [FILE]...'),
5112 inferrepo=True)
5119 inferrepo=True)
5113 def resolve(ui, repo, *pats, **opts):
5120 def resolve(ui, repo, *pats, **opts):
5114 """redo merges or set/view the merge status of files
5121 """redo merges or set/view the merge status of files
5115
5122
5116 Merges with unresolved conflicts are often the result of
5123 Merges with unresolved conflicts are often the result of
5117 non-interactive merging using the ``internal:merge`` configuration
5124 non-interactive merging using the ``internal:merge`` configuration
5118 setting, or a command-line merge tool like ``diff3``. The resolve
5125 setting, or a command-line merge tool like ``diff3``. The resolve
5119 command is used to manage the files involved in a merge, after
5126 command is used to manage the files involved in a merge, after
5120 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5127 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5121 working directory must have two parents). See :hg:`help
5128 working directory must have two parents). See :hg:`help
5122 merge-tools` for information on configuring merge tools.
5129 merge-tools` for information on configuring merge tools.
5123
5130
5124 The resolve command can be used in the following ways:
5131 The resolve command can be used in the following ways:
5125
5132
5126 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5133 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5127 files, discarding any previous merge attempts. Re-merging is not
5134 files, discarding any previous merge attempts. Re-merging is not
5128 performed for files already marked as resolved. Use ``--all/-a``
5135 performed for files already marked as resolved. Use ``--all/-a``
5129 to select all unresolved files. ``--tool`` can be used to specify
5136 to select all unresolved files. ``--tool`` can be used to specify
5130 the merge tool used for the given files. It overrides the HGMERGE
5137 the merge tool used for the given files. It overrides the HGMERGE
5131 environment variable and your configuration files. Previous file
5138 environment variable and your configuration files. Previous file
5132 contents are saved with a ``.orig`` suffix.
5139 contents are saved with a ``.orig`` suffix.
5133
5140
5134 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5141 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5135 (e.g. after having manually fixed-up the files). The default is
5142 (e.g. after having manually fixed-up the files). The default is
5136 to mark all unresolved files.
5143 to mark all unresolved files.
5137
5144
5138 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5145 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5139 default is to mark all resolved files.
5146 default is to mark all resolved files.
5140
5147
5141 - :hg:`resolve -l`: list files which had or still have conflicts.
5148 - :hg:`resolve -l`: list files which had or still have conflicts.
5142 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5149 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5143
5150
5144 Note that Mercurial will not let you commit files with unresolved
5151 Note that Mercurial will not let you commit files with unresolved
5145 merge conflicts. You must use :hg:`resolve -m ...` before you can
5152 merge conflicts. You must use :hg:`resolve -m ...` before you can
5146 commit after a conflicting merge.
5153 commit after a conflicting merge.
5147
5154
5148 Returns 0 on success, 1 if any files fail a resolve attempt.
5155 Returns 0 on success, 1 if any files fail a resolve attempt.
5149 """
5156 """
5150
5157
5151 all, mark, unmark, show, nostatus = \
5158 all, mark, unmark, show, nostatus = \
5152 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5159 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5153
5160
5154 if (show and (mark or unmark)) or (mark and unmark):
5161 if (show and (mark or unmark)) or (mark and unmark):
5155 raise util.Abort(_("too many options specified"))
5162 raise util.Abort(_("too many options specified"))
5156 if pats and all:
5163 if pats and all:
5157 raise util.Abort(_("can't specify --all and patterns"))
5164 raise util.Abort(_("can't specify --all and patterns"))
5158 if not (all or pats or show or mark or unmark):
5165 if not (all or pats or show or mark or unmark):
5159 raise util.Abort(_('no files or directories specified'),
5166 raise util.Abort(_('no files or directories specified'),
5160 hint=('use --all to remerge all files'))
5167 hint=('use --all to remerge all files'))
5161
5168
5162 wlock = repo.wlock()
5169 wlock = repo.wlock()
5163 try:
5170 try:
5164 ms = mergemod.mergestate(repo)
5171 ms = mergemod.mergestate(repo)
5165
5172
5166 if not ms.active() and not show:
5173 if not ms.active() and not show:
5167 raise util.Abort(
5174 raise util.Abort(
5168 _('resolve command not applicable when not merging'))
5175 _('resolve command not applicable when not merging'))
5169
5176
5170 m = scmutil.match(repo[None], pats, opts)
5177 m = scmutil.match(repo[None], pats, opts)
5171 ret = 0
5178 ret = 0
5172 didwork = False
5179 didwork = False
5173
5180
5174 for f in ms:
5181 for f in ms:
5175 if not m(f):
5182 if not m(f):
5176 continue
5183 continue
5177
5184
5178 didwork = True
5185 didwork = True
5179
5186
5180 if show:
5187 if show:
5181 if nostatus:
5188 if nostatus:
5182 ui.write("%s\n" % f)
5189 ui.write("%s\n" % f)
5183 else:
5190 else:
5184 ui.write("%s %s\n" % (ms[f].upper(), f),
5191 ui.write("%s %s\n" % (ms[f].upper(), f),
5185 label='resolve.' +
5192 label='resolve.' +
5186 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5193 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5187 elif mark:
5194 elif mark:
5188 ms.mark(f, "r")
5195 ms.mark(f, "r")
5189 elif unmark:
5196 elif unmark:
5190 ms.mark(f, "u")
5197 ms.mark(f, "u")
5191 else:
5198 else:
5192 wctx = repo[None]
5199 wctx = repo[None]
5193
5200
5194 # backup pre-resolve (merge uses .orig for its own purposes)
5201 # backup pre-resolve (merge uses .orig for its own purposes)
5195 a = repo.wjoin(f)
5202 a = repo.wjoin(f)
5196 util.copyfile(a, a + ".resolve")
5203 util.copyfile(a, a + ".resolve")
5197
5204
5198 try:
5205 try:
5199 # resolve file
5206 # resolve file
5200 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5207 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5201 'resolve')
5208 'resolve')
5202 if ms.resolve(f, wctx):
5209 if ms.resolve(f, wctx):
5203 ret = 1
5210 ret = 1
5204 finally:
5211 finally:
5205 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5212 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5206 ms.commit()
5213 ms.commit()
5207
5214
5208 # replace filemerge's .orig file with our resolve file
5215 # replace filemerge's .orig file with our resolve file
5209 util.rename(a + ".resolve", a + ".orig")
5216 util.rename(a + ".resolve", a + ".orig")
5210
5217
5211 ms.commit()
5218 ms.commit()
5212
5219
5213 if not didwork and pats:
5220 if not didwork and pats:
5214 ui.warn(_("arguments do not match paths that need resolving\n"))
5221 ui.warn(_("arguments do not match paths that need resolving\n"))
5215
5222
5216 finally:
5223 finally:
5217 wlock.release()
5224 wlock.release()
5218
5225
5219 # Nudge users into finishing an unfinished operation. We don't print
5226 # Nudge users into finishing an unfinished operation. We don't print
5220 # this with the list/show operation because we want list/show to remain
5227 # this with the list/show operation because we want list/show to remain
5221 # machine readable.
5228 # machine readable.
5222 if not list(ms.unresolved()) and not show:
5229 if not list(ms.unresolved()) and not show:
5223 ui.status(_('(no more unresolved files)\n'))
5230 ui.status(_('(no more unresolved files)\n'))
5224
5231
5225 return ret
5232 return ret
5226
5233
5227 @command('revert',
5234 @command('revert',
5228 [('a', 'all', None, _('revert all changes when no arguments given')),
5235 [('a', 'all', None, _('revert all changes when no arguments given')),
5229 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5236 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5230 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5237 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5231 ('C', 'no-backup', None, _('do not save backup copies of files')),
5238 ('C', 'no-backup', None, _('do not save backup copies of files')),
5232 ] + walkopts + dryrunopts,
5239 ] + walkopts + dryrunopts,
5233 _('[OPTION]... [-r REV] [NAME]...'))
5240 _('[OPTION]... [-r REV] [NAME]...'))
5234 def revert(ui, repo, *pats, **opts):
5241 def revert(ui, repo, *pats, **opts):
5235 """restore files to their checkout state
5242 """restore files to their checkout state
5236
5243
5237 .. note::
5244 .. note::
5238
5245
5239 To check out earlier revisions, you should use :hg:`update REV`.
5246 To check out earlier revisions, you should use :hg:`update REV`.
5240 To cancel an uncommitted merge (and lose your changes),
5247 To cancel an uncommitted merge (and lose your changes),
5241 use :hg:`update --clean .`.
5248 use :hg:`update --clean .`.
5242
5249
5243 With no revision specified, revert the specified files or directories
5250 With no revision specified, revert the specified files or directories
5244 to the contents they had in the parent of the working directory.
5251 to the contents they had in the parent of the working directory.
5245 This restores the contents of files to an unmodified
5252 This restores the contents of files to an unmodified
5246 state and unschedules adds, removes, copies, and renames. If the
5253 state and unschedules adds, removes, copies, and renames. If the
5247 working directory has two parents, you must explicitly specify a
5254 working directory has two parents, you must explicitly specify a
5248 revision.
5255 revision.
5249
5256
5250 Using the -r/--rev or -d/--date options, revert the given files or
5257 Using the -r/--rev or -d/--date options, revert the given files or
5251 directories to their states as of a specific revision. Because
5258 directories to their states as of a specific revision. Because
5252 revert does not change the working directory parents, this will
5259 revert does not change the working directory parents, this will
5253 cause these files to appear modified. This can be helpful to "back
5260 cause these files to appear modified. This can be helpful to "back
5254 out" some or all of an earlier change. See :hg:`backout` for a
5261 out" some or all of an earlier change. See :hg:`backout` for a
5255 related method.
5262 related method.
5256
5263
5257 Modified files are saved with a .orig suffix before reverting.
5264 Modified files are saved with a .orig suffix before reverting.
5258 To disable these backups, use --no-backup.
5265 To disable these backups, use --no-backup.
5259
5266
5260 See :hg:`help dates` for a list of formats valid for -d/--date.
5267 See :hg:`help dates` for a list of formats valid for -d/--date.
5261
5268
5262 Returns 0 on success.
5269 Returns 0 on success.
5263 """
5270 """
5264
5271
5265 if opts.get("date"):
5272 if opts.get("date"):
5266 if opts.get("rev"):
5273 if opts.get("rev"):
5267 raise util.Abort(_("you can't specify a revision and a date"))
5274 raise util.Abort(_("you can't specify a revision and a date"))
5268 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5275 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5269
5276
5270 parent, p2 = repo.dirstate.parents()
5277 parent, p2 = repo.dirstate.parents()
5271 if not opts.get('rev') and p2 != nullid:
5278 if not opts.get('rev') and p2 != nullid:
5272 # revert after merge is a trap for new users (issue2915)
5279 # revert after merge is a trap for new users (issue2915)
5273 raise util.Abort(_('uncommitted merge with no revision specified'),
5280 raise util.Abort(_('uncommitted merge with no revision specified'),
5274 hint=_('use "hg update" or see "hg help revert"'))
5281 hint=_('use "hg update" or see "hg help revert"'))
5275
5282
5276 ctx = scmutil.revsingle(repo, opts.get('rev'))
5283 ctx = scmutil.revsingle(repo, opts.get('rev'))
5277
5284
5278 if not pats and not opts.get('all'):
5285 if not pats and not opts.get('all'):
5279 msg = _("no files or directories specified")
5286 msg = _("no files or directories specified")
5280 if p2 != nullid:
5287 if p2 != nullid:
5281 hint = _("uncommitted merge, use --all to discard all changes,"
5288 hint = _("uncommitted merge, use --all to discard all changes,"
5282 " or 'hg update -C .' to abort the merge")
5289 " or 'hg update -C .' to abort the merge")
5283 raise util.Abort(msg, hint=hint)
5290 raise util.Abort(msg, hint=hint)
5284 dirty = util.any(repo.status())
5291 dirty = util.any(repo.status())
5285 node = ctx.node()
5292 node = ctx.node()
5286 if node != parent:
5293 if node != parent:
5287 if dirty:
5294 if dirty:
5288 hint = _("uncommitted changes, use --all to discard all"
5295 hint = _("uncommitted changes, use --all to discard all"
5289 " changes, or 'hg update %s' to update") % ctx.rev()
5296 " changes, or 'hg update %s' to update") % ctx.rev()
5290 else:
5297 else:
5291 hint = _("use --all to revert all files,"
5298 hint = _("use --all to revert all files,"
5292 " or 'hg update %s' to update") % ctx.rev()
5299 " or 'hg update %s' to update") % ctx.rev()
5293 elif dirty:
5300 elif dirty:
5294 hint = _("uncommitted changes, use --all to discard all changes")
5301 hint = _("uncommitted changes, use --all to discard all changes")
5295 else:
5302 else:
5296 hint = _("use --all to revert all files")
5303 hint = _("use --all to revert all files")
5297 raise util.Abort(msg, hint=hint)
5304 raise util.Abort(msg, hint=hint)
5298
5305
5299 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5306 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5300
5307
5301 @command('rollback', dryrunopts +
5308 @command('rollback', dryrunopts +
5302 [('f', 'force', False, _('ignore safety measures'))])
5309 [('f', 'force', False, _('ignore safety measures'))])
5303 def rollback(ui, repo, **opts):
5310 def rollback(ui, repo, **opts):
5304 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5311 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5305
5312
5306 Please use :hg:`commit --amend` instead of rollback to correct
5313 Please use :hg:`commit --amend` instead of rollback to correct
5307 mistakes in the last commit.
5314 mistakes in the last commit.
5308
5315
5309 This command should be used with care. There is only one level of
5316 This command should be used with care. There is only one level of
5310 rollback, and there is no way to undo a rollback. It will also
5317 rollback, and there is no way to undo a rollback. It will also
5311 restore the dirstate at the time of the last transaction, losing
5318 restore the dirstate at the time of the last transaction, losing
5312 any dirstate changes since that time. This command does not alter
5319 any dirstate changes since that time. This command does not alter
5313 the working directory.
5320 the working directory.
5314
5321
5315 Transactions are used to encapsulate the effects of all commands
5322 Transactions are used to encapsulate the effects of all commands
5316 that create new changesets or propagate existing changesets into a
5323 that create new changesets or propagate existing changesets into a
5317 repository.
5324 repository.
5318
5325
5319 .. container:: verbose
5326 .. container:: verbose
5320
5327
5321 For example, the following commands are transactional, and their
5328 For example, the following commands are transactional, and their
5322 effects can be rolled back:
5329 effects can be rolled back:
5323
5330
5324 - commit
5331 - commit
5325 - import
5332 - import
5326 - pull
5333 - pull
5327 - push (with this repository as the destination)
5334 - push (with this repository as the destination)
5328 - unbundle
5335 - unbundle
5329
5336
5330 To avoid permanent data loss, rollback will refuse to rollback a
5337 To avoid permanent data loss, rollback will refuse to rollback a
5331 commit transaction if it isn't checked out. Use --force to
5338 commit transaction if it isn't checked out. Use --force to
5332 override this protection.
5339 override this protection.
5333
5340
5334 This command is not intended for use on public repositories. Once
5341 This command is not intended for use on public repositories. Once
5335 changes are visible for pull by other users, rolling a transaction
5342 changes are visible for pull by other users, rolling a transaction
5336 back locally is ineffective (someone else may already have pulled
5343 back locally is ineffective (someone else may already have pulled
5337 the changes). Furthermore, a race is possible with readers of the
5344 the changes). Furthermore, a race is possible with readers of the
5338 repository; for example an in-progress pull from the repository
5345 repository; for example an in-progress pull from the repository
5339 may fail if a rollback is performed.
5346 may fail if a rollback is performed.
5340
5347
5341 Returns 0 on success, 1 if no rollback data is available.
5348 Returns 0 on success, 1 if no rollback data is available.
5342 """
5349 """
5343 return repo.rollback(dryrun=opts.get('dry_run'),
5350 return repo.rollback(dryrun=opts.get('dry_run'),
5344 force=opts.get('force'))
5351 force=opts.get('force'))
5345
5352
5346 @command('root', [])
5353 @command('root', [])
5347 def root(ui, repo):
5354 def root(ui, repo):
5348 """print the root (top) of the current working directory
5355 """print the root (top) of the current working directory
5349
5356
5350 Print the root directory of the current repository.
5357 Print the root directory of the current repository.
5351
5358
5352 Returns 0 on success.
5359 Returns 0 on success.
5353 """
5360 """
5354 ui.write(repo.root + "\n")
5361 ui.write(repo.root + "\n")
5355
5362
5356 @command('^serve',
5363 @command('^serve',
5357 [('A', 'accesslog', '', _('name of access log file to write to'),
5364 [('A', 'accesslog', '', _('name of access log file to write to'),
5358 _('FILE')),
5365 _('FILE')),
5359 ('d', 'daemon', None, _('run server in background')),
5366 ('d', 'daemon', None, _('run server in background')),
5360 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5367 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5361 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5368 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5362 # use string type, then we can check if something was passed
5369 # use string type, then we can check if something was passed
5363 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5370 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5364 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5371 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5365 _('ADDR')),
5372 _('ADDR')),
5366 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5373 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5367 _('PREFIX')),
5374 _('PREFIX')),
5368 ('n', 'name', '',
5375 ('n', 'name', '',
5369 _('name to show in web pages (default: working directory)'), _('NAME')),
5376 _('name to show in web pages (default: working directory)'), _('NAME')),
5370 ('', 'web-conf', '',
5377 ('', 'web-conf', '',
5371 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5378 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5372 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5379 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5373 _('FILE')),
5380 _('FILE')),
5374 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5381 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5375 ('', 'stdio', None, _('for remote clients')),
5382 ('', 'stdio', None, _('for remote clients')),
5376 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5383 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5377 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5384 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5378 ('', 'style', '', _('template style to use'), _('STYLE')),
5385 ('', 'style', '', _('template style to use'), _('STYLE')),
5379 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5386 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5380 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5387 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5381 _('[OPTION]...'),
5388 _('[OPTION]...'),
5382 optionalrepo=True)
5389 optionalrepo=True)
5383 def serve(ui, repo, **opts):
5390 def serve(ui, repo, **opts):
5384 """start stand-alone webserver
5391 """start stand-alone webserver
5385
5392
5386 Start a local HTTP repository browser and pull server. You can use
5393 Start a local HTTP repository browser and pull server. You can use
5387 this for ad-hoc sharing and browsing of repositories. It is
5394 this for ad-hoc sharing and browsing of repositories. It is
5388 recommended to use a real web server to serve a repository for
5395 recommended to use a real web server to serve a repository for
5389 longer periods of time.
5396 longer periods of time.
5390
5397
5391 Please note that the server does not implement access control.
5398 Please note that the server does not implement access control.
5392 This means that, by default, anybody can read from the server and
5399 This means that, by default, anybody can read from the server and
5393 nobody can write to it by default. Set the ``web.allow_push``
5400 nobody can write to it by default. Set the ``web.allow_push``
5394 option to ``*`` to allow everybody to push to the server. You
5401 option to ``*`` to allow everybody to push to the server. You
5395 should use a real web server if you need to authenticate users.
5402 should use a real web server if you need to authenticate users.
5396
5403
5397 By default, the server logs accesses to stdout and errors to
5404 By default, the server logs accesses to stdout and errors to
5398 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5405 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5399 files.
5406 files.
5400
5407
5401 To have the server choose a free port number to listen on, specify
5408 To have the server choose a free port number to listen on, specify
5402 a port number of 0; in this case, the server will print the port
5409 a port number of 0; in this case, the server will print the port
5403 number it uses.
5410 number it uses.
5404
5411
5405 Returns 0 on success.
5412 Returns 0 on success.
5406 """
5413 """
5407
5414
5408 if opts["stdio"] and opts["cmdserver"]:
5415 if opts["stdio"] and opts["cmdserver"]:
5409 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5416 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5410
5417
5411 if opts["stdio"]:
5418 if opts["stdio"]:
5412 if repo is None:
5419 if repo is None:
5413 raise error.RepoError(_("there is no Mercurial repository here"
5420 raise error.RepoError(_("there is no Mercurial repository here"
5414 " (.hg not found)"))
5421 " (.hg not found)"))
5415 s = sshserver.sshserver(ui, repo)
5422 s = sshserver.sshserver(ui, repo)
5416 s.serve_forever()
5423 s.serve_forever()
5417
5424
5418 if opts["cmdserver"]:
5425 if opts["cmdserver"]:
5419 s = commandserver.server(ui, repo, opts["cmdserver"])
5426 s = commandserver.server(ui, repo, opts["cmdserver"])
5420 return s.serve()
5427 return s.serve()
5421
5428
5422 # this way we can check if something was given in the command-line
5429 # this way we can check if something was given in the command-line
5423 if opts.get('port'):
5430 if opts.get('port'):
5424 opts['port'] = util.getport(opts.get('port'))
5431 opts['port'] = util.getport(opts.get('port'))
5425
5432
5426 baseui = repo and repo.baseui or ui
5433 baseui = repo and repo.baseui or ui
5427 optlist = ("name templates style address port prefix ipv6"
5434 optlist = ("name templates style address port prefix ipv6"
5428 " accesslog errorlog certificate encoding")
5435 " accesslog errorlog certificate encoding")
5429 for o in optlist.split():
5436 for o in optlist.split():
5430 val = opts.get(o, '')
5437 val = opts.get(o, '')
5431 if val in (None, ''): # should check against default options instead
5438 if val in (None, ''): # should check against default options instead
5432 continue
5439 continue
5433 baseui.setconfig("web", o, val, 'serve')
5440 baseui.setconfig("web", o, val, 'serve')
5434 if repo and repo.ui != baseui:
5441 if repo and repo.ui != baseui:
5435 repo.ui.setconfig("web", o, val, 'serve')
5442 repo.ui.setconfig("web", o, val, 'serve')
5436
5443
5437 o = opts.get('web_conf') or opts.get('webdir_conf')
5444 o = opts.get('web_conf') or opts.get('webdir_conf')
5438 if not o:
5445 if not o:
5439 if not repo:
5446 if not repo:
5440 raise error.RepoError(_("there is no Mercurial repository"
5447 raise error.RepoError(_("there is no Mercurial repository"
5441 " here (.hg not found)"))
5448 " here (.hg not found)"))
5442 o = repo
5449 o = repo
5443
5450
5444 app = hgweb.hgweb(o, baseui=baseui)
5451 app = hgweb.hgweb(o, baseui=baseui)
5445 service = httpservice(ui, app, opts)
5452 service = httpservice(ui, app, opts)
5446 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5453 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5447
5454
5448 class httpservice(object):
5455 class httpservice(object):
5449 def __init__(self, ui, app, opts):
5456 def __init__(self, ui, app, opts):
5450 self.ui = ui
5457 self.ui = ui
5451 self.app = app
5458 self.app = app
5452 self.opts = opts
5459 self.opts = opts
5453
5460
5454 def init(self):
5461 def init(self):
5455 util.setsignalhandler()
5462 util.setsignalhandler()
5456 self.httpd = hgweb_server.create_server(self.ui, self.app)
5463 self.httpd = hgweb_server.create_server(self.ui, self.app)
5457
5464
5458 if self.opts['port'] and not self.ui.verbose:
5465 if self.opts['port'] and not self.ui.verbose:
5459 return
5466 return
5460
5467
5461 if self.httpd.prefix:
5468 if self.httpd.prefix:
5462 prefix = self.httpd.prefix.strip('/') + '/'
5469 prefix = self.httpd.prefix.strip('/') + '/'
5463 else:
5470 else:
5464 prefix = ''
5471 prefix = ''
5465
5472
5466 port = ':%d' % self.httpd.port
5473 port = ':%d' % self.httpd.port
5467 if port == ':80':
5474 if port == ':80':
5468 port = ''
5475 port = ''
5469
5476
5470 bindaddr = self.httpd.addr
5477 bindaddr = self.httpd.addr
5471 if bindaddr == '0.0.0.0':
5478 if bindaddr == '0.0.0.0':
5472 bindaddr = '*'
5479 bindaddr = '*'
5473 elif ':' in bindaddr: # IPv6
5480 elif ':' in bindaddr: # IPv6
5474 bindaddr = '[%s]' % bindaddr
5481 bindaddr = '[%s]' % bindaddr
5475
5482
5476 fqaddr = self.httpd.fqaddr
5483 fqaddr = self.httpd.fqaddr
5477 if ':' in fqaddr:
5484 if ':' in fqaddr:
5478 fqaddr = '[%s]' % fqaddr
5485 fqaddr = '[%s]' % fqaddr
5479 if self.opts['port']:
5486 if self.opts['port']:
5480 write = self.ui.status
5487 write = self.ui.status
5481 else:
5488 else:
5482 write = self.ui.write
5489 write = self.ui.write
5483 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5490 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5484 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5491 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5485 self.ui.flush() # avoid buffering of status message
5492 self.ui.flush() # avoid buffering of status message
5486
5493
5487 def run(self):
5494 def run(self):
5488 self.httpd.serve_forever()
5495 self.httpd.serve_forever()
5489
5496
5490
5497
5491 @command('^status|st',
5498 @command('^status|st',
5492 [('A', 'all', None, _('show status of all files')),
5499 [('A', 'all', None, _('show status of all files')),
5493 ('m', 'modified', None, _('show only modified files')),
5500 ('m', 'modified', None, _('show only modified files')),
5494 ('a', 'added', None, _('show only added files')),
5501 ('a', 'added', None, _('show only added files')),
5495 ('r', 'removed', None, _('show only removed files')),
5502 ('r', 'removed', None, _('show only removed files')),
5496 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5503 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5497 ('c', 'clean', None, _('show only files without changes')),
5504 ('c', 'clean', None, _('show only files without changes')),
5498 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5505 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5499 ('i', 'ignored', None, _('show only ignored files')),
5506 ('i', 'ignored', None, _('show only ignored files')),
5500 ('n', 'no-status', None, _('hide status prefix')),
5507 ('n', 'no-status', None, _('hide status prefix')),
5501 ('C', 'copies', None, _('show source of copied files')),
5508 ('C', 'copies', None, _('show source of copied files')),
5502 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5509 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5503 ('', 'rev', [], _('show difference from revision'), _('REV')),
5510 ('', 'rev', [], _('show difference from revision'), _('REV')),
5504 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5511 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5505 ] + walkopts + subrepoopts,
5512 ] + walkopts + subrepoopts + formatteropts,
5506 _('[OPTION]... [FILE]...'),
5513 _('[OPTION]... [FILE]...'),
5507 inferrepo=True)
5514 inferrepo=True)
5508 def status(ui, repo, *pats, **opts):
5515 def status(ui, repo, *pats, **opts):
5509 """show changed files in the working directory
5516 """show changed files in the working directory
5510
5517
5511 Show status of files in the repository. If names are given, only
5518 Show status of files in the repository. If names are given, only
5512 files that match are shown. Files that are clean or ignored or
5519 files that match are shown. Files that are clean or ignored or
5513 the source of a copy/move operation, are not listed unless
5520 the source of a copy/move operation, are not listed unless
5514 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5521 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5515 Unless options described with "show only ..." are given, the
5522 Unless options described with "show only ..." are given, the
5516 options -mardu are used.
5523 options -mardu are used.
5517
5524
5518 Option -q/--quiet hides untracked (unknown and ignored) files
5525 Option -q/--quiet hides untracked (unknown and ignored) files
5519 unless explicitly requested with -u/--unknown or -i/--ignored.
5526 unless explicitly requested with -u/--unknown or -i/--ignored.
5520
5527
5521 .. note::
5528 .. note::
5522
5529
5523 status may appear to disagree with diff if permissions have
5530 status may appear to disagree with diff if permissions have
5524 changed or a merge has occurred. The standard diff format does
5531 changed or a merge has occurred. The standard diff format does
5525 not report permission changes and diff only reports changes
5532 not report permission changes and diff only reports changes
5526 relative to one merge parent.
5533 relative to one merge parent.
5527
5534
5528 If one revision is given, it is used as the base revision.
5535 If one revision is given, it is used as the base revision.
5529 If two revisions are given, the differences between them are
5536 If two revisions are given, the differences between them are
5530 shown. The --change option can also be used as a shortcut to list
5537 shown. The --change option can also be used as a shortcut to list
5531 the changed files of a revision from its first parent.
5538 the changed files of a revision from its first parent.
5532
5539
5533 The codes used to show the status of files are::
5540 The codes used to show the status of files are::
5534
5541
5535 M = modified
5542 M = modified
5536 A = added
5543 A = added
5537 R = removed
5544 R = removed
5538 C = clean
5545 C = clean
5539 ! = missing (deleted by non-hg command, but still tracked)
5546 ! = missing (deleted by non-hg command, but still tracked)
5540 ? = not tracked
5547 ? = not tracked
5541 I = ignored
5548 I = ignored
5542 = origin of the previous file (with --copies)
5549 = origin of the previous file (with --copies)
5543
5550
5544 .. container:: verbose
5551 .. container:: verbose
5545
5552
5546 Examples:
5553 Examples:
5547
5554
5548 - show changes in the working directory relative to a
5555 - show changes in the working directory relative to a
5549 changeset::
5556 changeset::
5550
5557
5551 hg status --rev 9353
5558 hg status --rev 9353
5552
5559
5553 - show all changes including copies in an existing changeset::
5560 - show all changes including copies in an existing changeset::
5554
5561
5555 hg status --copies --change 9353
5562 hg status --copies --change 9353
5556
5563
5557 - get a NUL separated list of added files, suitable for xargs::
5564 - get a NUL separated list of added files, suitable for xargs::
5558
5565
5559 hg status -an0
5566 hg status -an0
5560
5567
5561 Returns 0 on success.
5568 Returns 0 on success.
5562 """
5569 """
5563
5570
5564 revs = opts.get('rev')
5571 revs = opts.get('rev')
5565 change = opts.get('change')
5572 change = opts.get('change')
5566
5573
5567 if revs and change:
5574 if revs and change:
5568 msg = _('cannot specify --rev and --change at the same time')
5575 msg = _('cannot specify --rev and --change at the same time')
5569 raise util.Abort(msg)
5576 raise util.Abort(msg)
5570 elif change:
5577 elif change:
5571 node2 = scmutil.revsingle(repo, change, None).node()
5578 node2 = scmutil.revsingle(repo, change, None).node()
5572 node1 = repo[node2].p1().node()
5579 node1 = repo[node2].p1().node()
5573 else:
5580 else:
5574 node1, node2 = scmutil.revpair(repo, revs)
5581 node1, node2 = scmutil.revpair(repo, revs)
5575
5582
5576 cwd = (pats and repo.getcwd()) or ''
5583 cwd = (pats and repo.getcwd()) or ''
5577 end = opts.get('print0') and '\0' or '\n'
5584 end = opts.get('print0') and '\0' or '\n'
5578 copy = {}
5585 copy = {}
5579 states = 'modified added removed deleted unknown ignored clean'.split()
5586 states = 'modified added removed deleted unknown ignored clean'.split()
5580 show = [k for k in states if opts.get(k)]
5587 show = [k for k in states if opts.get(k)]
5581 if opts.get('all'):
5588 if opts.get('all'):
5582 show += ui.quiet and (states[:4] + ['clean']) or states
5589 show += ui.quiet and (states[:4] + ['clean']) or states
5583 if not show:
5590 if not show:
5584 show = ui.quiet and states[:4] or states[:5]
5591 show = ui.quiet and states[:4] or states[:5]
5585
5592
5586 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5593 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5587 'ignored' in show, 'clean' in show, 'unknown' in show,
5594 'ignored' in show, 'clean' in show, 'unknown' in show,
5588 opts.get('subrepos'))
5595 opts.get('subrepos'))
5589 changestates = zip(states, 'MAR!?IC', stat)
5596 changestates = zip(states, 'MAR!?IC', stat)
5590
5597
5591 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5598 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5592 copy = copies.pathcopies(repo[node1], repo[node2])
5599 copy = copies.pathcopies(repo[node1], repo[node2])
5593
5600
5594 fm = ui.formatter('status', opts)
5601 fm = ui.formatter('status', opts)
5595 fmt = '%s' + end
5602 fmt = '%s' + end
5596 showchar = not opts.get('no_status')
5603 showchar = not opts.get('no_status')
5597
5604
5598 for state, char, files in changestates:
5605 for state, char, files in changestates:
5599 if state in show:
5606 if state in show:
5600 label = 'status.' + state
5607 label = 'status.' + state
5601 for f in files:
5608 for f in files:
5602 fm.startitem()
5609 fm.startitem()
5603 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5610 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5604 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5611 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5605 if f in copy:
5612 if f in copy:
5606 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5613 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5607 label='status.copied')
5614 label='status.copied')
5608 fm.end()
5615 fm.end()
5609
5616
5610 @command('^summary|sum',
5617 @command('^summary|sum',
5611 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5618 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5612 def summary(ui, repo, **opts):
5619 def summary(ui, repo, **opts):
5613 """summarize working directory state
5620 """summarize working directory state
5614
5621
5615 This generates a brief summary of the working directory state,
5622 This generates a brief summary of the working directory state,
5616 including parents, branch, commit status, and available updates.
5623 including parents, branch, commit status, and available updates.
5617
5624
5618 With the --remote option, this will check the default paths for
5625 With the --remote option, this will check the default paths for
5619 incoming and outgoing changes. This can be time-consuming.
5626 incoming and outgoing changes. This can be time-consuming.
5620
5627
5621 Returns 0 on success.
5628 Returns 0 on success.
5622 """
5629 """
5623
5630
5624 ctx = repo[None]
5631 ctx = repo[None]
5625 parents = ctx.parents()
5632 parents = ctx.parents()
5626 pnode = parents[0].node()
5633 pnode = parents[0].node()
5627 marks = []
5634 marks = []
5628
5635
5629 for p in parents:
5636 for p in parents:
5630 # label with log.changeset (instead of log.parent) since this
5637 # label with log.changeset (instead of log.parent) since this
5631 # shows a working directory parent *changeset*:
5638 # shows a working directory parent *changeset*:
5632 # i18n: column positioning for "hg summary"
5639 # i18n: column positioning for "hg summary"
5633 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5640 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5634 label='log.changeset changeset.%s' % p.phasestr())
5641 label='log.changeset changeset.%s' % p.phasestr())
5635 ui.write(' '.join(p.tags()), label='log.tag')
5642 ui.write(' '.join(p.tags()), label='log.tag')
5636 if p.bookmarks():
5643 if p.bookmarks():
5637 marks.extend(p.bookmarks())
5644 marks.extend(p.bookmarks())
5638 if p.rev() == -1:
5645 if p.rev() == -1:
5639 if not len(repo):
5646 if not len(repo):
5640 ui.write(_(' (empty repository)'))
5647 ui.write(_(' (empty repository)'))
5641 else:
5648 else:
5642 ui.write(_(' (no revision checked out)'))
5649 ui.write(_(' (no revision checked out)'))
5643 ui.write('\n')
5650 ui.write('\n')
5644 if p.description():
5651 if p.description():
5645 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5652 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5646 label='log.summary')
5653 label='log.summary')
5647
5654
5648 branch = ctx.branch()
5655 branch = ctx.branch()
5649 bheads = repo.branchheads(branch)
5656 bheads = repo.branchheads(branch)
5650 # i18n: column positioning for "hg summary"
5657 # i18n: column positioning for "hg summary"
5651 m = _('branch: %s\n') % branch
5658 m = _('branch: %s\n') % branch
5652 if branch != 'default':
5659 if branch != 'default':
5653 ui.write(m, label='log.branch')
5660 ui.write(m, label='log.branch')
5654 else:
5661 else:
5655 ui.status(m, label='log.branch')
5662 ui.status(m, label='log.branch')
5656
5663
5657 if marks:
5664 if marks:
5658 current = repo._bookmarkcurrent
5665 current = repo._bookmarkcurrent
5659 # i18n: column positioning for "hg summary"
5666 # i18n: column positioning for "hg summary"
5660 ui.write(_('bookmarks:'), label='log.bookmark')
5667 ui.write(_('bookmarks:'), label='log.bookmark')
5661 if current is not None:
5668 if current is not None:
5662 if current in marks:
5669 if current in marks:
5663 ui.write(' *' + current, label='bookmarks.current')
5670 ui.write(' *' + current, label='bookmarks.current')
5664 marks.remove(current)
5671 marks.remove(current)
5665 else:
5672 else:
5666 ui.write(' [%s]' % current, label='bookmarks.current')
5673 ui.write(' [%s]' % current, label='bookmarks.current')
5667 for m in marks:
5674 for m in marks:
5668 ui.write(' ' + m, label='log.bookmark')
5675 ui.write(' ' + m, label='log.bookmark')
5669 ui.write('\n', label='log.bookmark')
5676 ui.write('\n', label='log.bookmark')
5670
5677
5671 st = list(repo.status(unknown=True))[:6]
5678 st = list(repo.status(unknown=True))[:6]
5672
5679
5673 c = repo.dirstate.copies()
5680 c = repo.dirstate.copies()
5674 copied, renamed = [], []
5681 copied, renamed = [], []
5675 for d, s in c.iteritems():
5682 for d, s in c.iteritems():
5676 if s in st[2]:
5683 if s in st[2]:
5677 st[2].remove(s)
5684 st[2].remove(s)
5678 renamed.append(d)
5685 renamed.append(d)
5679 else:
5686 else:
5680 copied.append(d)
5687 copied.append(d)
5681 if d in st[1]:
5688 if d in st[1]:
5682 st[1].remove(d)
5689 st[1].remove(d)
5683 st.insert(3, renamed)
5690 st.insert(3, renamed)
5684 st.insert(4, copied)
5691 st.insert(4, copied)
5685
5692
5686 ms = mergemod.mergestate(repo)
5693 ms = mergemod.mergestate(repo)
5687 st.append([f for f in ms if ms[f] == 'u'])
5694 st.append([f for f in ms if ms[f] == 'u'])
5688
5695
5689 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5696 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5690 st.append(subs)
5697 st.append(subs)
5691
5698
5692 labels = [ui.label(_('%d modified'), 'status.modified'),
5699 labels = [ui.label(_('%d modified'), 'status.modified'),
5693 ui.label(_('%d added'), 'status.added'),
5700 ui.label(_('%d added'), 'status.added'),
5694 ui.label(_('%d removed'), 'status.removed'),
5701 ui.label(_('%d removed'), 'status.removed'),
5695 ui.label(_('%d renamed'), 'status.copied'),
5702 ui.label(_('%d renamed'), 'status.copied'),
5696 ui.label(_('%d copied'), 'status.copied'),
5703 ui.label(_('%d copied'), 'status.copied'),
5697 ui.label(_('%d deleted'), 'status.deleted'),
5704 ui.label(_('%d deleted'), 'status.deleted'),
5698 ui.label(_('%d unknown'), 'status.unknown'),
5705 ui.label(_('%d unknown'), 'status.unknown'),
5699 ui.label(_('%d ignored'), 'status.ignored'),
5706 ui.label(_('%d ignored'), 'status.ignored'),
5700 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5707 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5701 ui.label(_('%d subrepos'), 'status.modified')]
5708 ui.label(_('%d subrepos'), 'status.modified')]
5702 t = []
5709 t = []
5703 for s, l in zip(st, labels):
5710 for s, l in zip(st, labels):
5704 if s:
5711 if s:
5705 t.append(l % len(s))
5712 t.append(l % len(s))
5706
5713
5707 t = ', '.join(t)
5714 t = ', '.join(t)
5708 cleanworkdir = False
5715 cleanworkdir = False
5709
5716
5710 if repo.vfs.exists('updatestate'):
5717 if repo.vfs.exists('updatestate'):
5711 t += _(' (interrupted update)')
5718 t += _(' (interrupted update)')
5712 elif len(parents) > 1:
5719 elif len(parents) > 1:
5713 t += _(' (merge)')
5720 t += _(' (merge)')
5714 elif branch != parents[0].branch():
5721 elif branch != parents[0].branch():
5715 t += _(' (new branch)')
5722 t += _(' (new branch)')
5716 elif (parents[0].closesbranch() and
5723 elif (parents[0].closesbranch() and
5717 pnode in repo.branchheads(branch, closed=True)):
5724 pnode in repo.branchheads(branch, closed=True)):
5718 t += _(' (head closed)')
5725 t += _(' (head closed)')
5719 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5726 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5720 t += _(' (clean)')
5727 t += _(' (clean)')
5721 cleanworkdir = True
5728 cleanworkdir = True
5722 elif pnode not in bheads:
5729 elif pnode not in bheads:
5723 t += _(' (new branch head)')
5730 t += _(' (new branch head)')
5724
5731
5725 if cleanworkdir:
5732 if cleanworkdir:
5726 # i18n: column positioning for "hg summary"
5733 # i18n: column positioning for "hg summary"
5727 ui.status(_('commit: %s\n') % t.strip())
5734 ui.status(_('commit: %s\n') % t.strip())
5728 else:
5735 else:
5729 # i18n: column positioning for "hg summary"
5736 # i18n: column positioning for "hg summary"
5730 ui.write(_('commit: %s\n') % t.strip())
5737 ui.write(_('commit: %s\n') % t.strip())
5731
5738
5732 # all ancestors of branch heads - all ancestors of parent = new csets
5739 # all ancestors of branch heads - all ancestors of parent = new csets
5733 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5740 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5734 bheads))
5741 bheads))
5735
5742
5736 if new == 0:
5743 if new == 0:
5737 # i18n: column positioning for "hg summary"
5744 # i18n: column positioning for "hg summary"
5738 ui.status(_('update: (current)\n'))
5745 ui.status(_('update: (current)\n'))
5739 elif pnode not in bheads:
5746 elif pnode not in bheads:
5740 # i18n: column positioning for "hg summary"
5747 # i18n: column positioning for "hg summary"
5741 ui.write(_('update: %d new changesets (update)\n') % new)
5748 ui.write(_('update: %d new changesets (update)\n') % new)
5742 else:
5749 else:
5743 # i18n: column positioning for "hg summary"
5750 # i18n: column positioning for "hg summary"
5744 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5751 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5745 (new, len(bheads)))
5752 (new, len(bheads)))
5746
5753
5747 cmdutil.summaryhooks(ui, repo)
5754 cmdutil.summaryhooks(ui, repo)
5748
5755
5749 if opts.get('remote'):
5756 if opts.get('remote'):
5750 needsincoming, needsoutgoing = True, True
5757 needsincoming, needsoutgoing = True, True
5751 else:
5758 else:
5752 needsincoming, needsoutgoing = False, False
5759 needsincoming, needsoutgoing = False, False
5753 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5760 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5754 if i:
5761 if i:
5755 needsincoming = True
5762 needsincoming = True
5756 if o:
5763 if o:
5757 needsoutgoing = True
5764 needsoutgoing = True
5758 if not needsincoming and not needsoutgoing:
5765 if not needsincoming and not needsoutgoing:
5759 return
5766 return
5760
5767
5761 def getincoming():
5768 def getincoming():
5762 source, branches = hg.parseurl(ui.expandpath('default'))
5769 source, branches = hg.parseurl(ui.expandpath('default'))
5763 sbranch = branches[0]
5770 sbranch = branches[0]
5764 try:
5771 try:
5765 other = hg.peer(repo, {}, source)
5772 other = hg.peer(repo, {}, source)
5766 except error.RepoError:
5773 except error.RepoError:
5767 if opts.get('remote'):
5774 if opts.get('remote'):
5768 raise
5775 raise
5769 return source, sbranch, None, None, None
5776 return source, sbranch, None, None, None
5770 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5777 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5771 if revs:
5778 if revs:
5772 revs = [other.lookup(rev) for rev in revs]
5779 revs = [other.lookup(rev) for rev in revs]
5773 ui.debug('comparing with %s\n' % util.hidepassword(source))
5780 ui.debug('comparing with %s\n' % util.hidepassword(source))
5774 repo.ui.pushbuffer()
5781 repo.ui.pushbuffer()
5775 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5782 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5776 repo.ui.popbuffer()
5783 repo.ui.popbuffer()
5777 return source, sbranch, other, commoninc, commoninc[1]
5784 return source, sbranch, other, commoninc, commoninc[1]
5778
5785
5779 if needsincoming:
5786 if needsincoming:
5780 source, sbranch, sother, commoninc, incoming = getincoming()
5787 source, sbranch, sother, commoninc, incoming = getincoming()
5781 else:
5788 else:
5782 source = sbranch = sother = commoninc = incoming = None
5789 source = sbranch = sother = commoninc = incoming = None
5783
5790
5784 def getoutgoing():
5791 def getoutgoing():
5785 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5792 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5786 dbranch = branches[0]
5793 dbranch = branches[0]
5787 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5794 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5788 if source != dest:
5795 if source != dest:
5789 try:
5796 try:
5790 dother = hg.peer(repo, {}, dest)
5797 dother = hg.peer(repo, {}, dest)
5791 except error.RepoError:
5798 except error.RepoError:
5792 if opts.get('remote'):
5799 if opts.get('remote'):
5793 raise
5800 raise
5794 return dest, dbranch, None, None
5801 return dest, dbranch, None, None
5795 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5802 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5796 elif sother is None:
5803 elif sother is None:
5797 # there is no explicit destination peer, but source one is invalid
5804 # there is no explicit destination peer, but source one is invalid
5798 return dest, dbranch, None, None
5805 return dest, dbranch, None, None
5799 else:
5806 else:
5800 dother = sother
5807 dother = sother
5801 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5808 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5802 common = None
5809 common = None
5803 else:
5810 else:
5804 common = commoninc
5811 common = commoninc
5805 if revs:
5812 if revs:
5806 revs = [repo.lookup(rev) for rev in revs]
5813 revs = [repo.lookup(rev) for rev in revs]
5807 repo.ui.pushbuffer()
5814 repo.ui.pushbuffer()
5808 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5815 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5809 commoninc=common)
5816 commoninc=common)
5810 repo.ui.popbuffer()
5817 repo.ui.popbuffer()
5811 return dest, dbranch, dother, outgoing
5818 return dest, dbranch, dother, outgoing
5812
5819
5813 if needsoutgoing:
5820 if needsoutgoing:
5814 dest, dbranch, dother, outgoing = getoutgoing()
5821 dest, dbranch, dother, outgoing = getoutgoing()
5815 else:
5822 else:
5816 dest = dbranch = dother = outgoing = None
5823 dest = dbranch = dother = outgoing = None
5817
5824
5818 if opts.get('remote'):
5825 if opts.get('remote'):
5819 t = []
5826 t = []
5820 if incoming:
5827 if incoming:
5821 t.append(_('1 or more incoming'))
5828 t.append(_('1 or more incoming'))
5822 o = outgoing.missing
5829 o = outgoing.missing
5823 if o:
5830 if o:
5824 t.append(_('%d outgoing') % len(o))
5831 t.append(_('%d outgoing') % len(o))
5825 other = dother or sother
5832 other = dother or sother
5826 if 'bookmarks' in other.listkeys('namespaces'):
5833 if 'bookmarks' in other.listkeys('namespaces'):
5827 lmarks = repo.listkeys('bookmarks')
5834 lmarks = repo.listkeys('bookmarks')
5828 rmarks = other.listkeys('bookmarks')
5835 rmarks = other.listkeys('bookmarks')
5829 diff = set(rmarks) - set(lmarks)
5836 diff = set(rmarks) - set(lmarks)
5830 if len(diff) > 0:
5837 if len(diff) > 0:
5831 t.append(_('%d incoming bookmarks') % len(diff))
5838 t.append(_('%d incoming bookmarks') % len(diff))
5832 diff = set(lmarks) - set(rmarks)
5839 diff = set(lmarks) - set(rmarks)
5833 if len(diff) > 0:
5840 if len(diff) > 0:
5834 t.append(_('%d outgoing bookmarks') % len(diff))
5841 t.append(_('%d outgoing bookmarks') % len(diff))
5835
5842
5836 if t:
5843 if t:
5837 # i18n: column positioning for "hg summary"
5844 # i18n: column positioning for "hg summary"
5838 ui.write(_('remote: %s\n') % (', '.join(t)))
5845 ui.write(_('remote: %s\n') % (', '.join(t)))
5839 else:
5846 else:
5840 # i18n: column positioning for "hg summary"
5847 # i18n: column positioning for "hg summary"
5841 ui.status(_('remote: (synced)\n'))
5848 ui.status(_('remote: (synced)\n'))
5842
5849
5843 cmdutil.summaryremotehooks(ui, repo, opts,
5850 cmdutil.summaryremotehooks(ui, repo, opts,
5844 ((source, sbranch, sother, commoninc),
5851 ((source, sbranch, sother, commoninc),
5845 (dest, dbranch, dother, outgoing)))
5852 (dest, dbranch, dother, outgoing)))
5846
5853
5847 @command('tag',
5854 @command('tag',
5848 [('f', 'force', None, _('force tag')),
5855 [('f', 'force', None, _('force tag')),
5849 ('l', 'local', None, _('make the tag local')),
5856 ('l', 'local', None, _('make the tag local')),
5850 ('r', 'rev', '', _('revision to tag'), _('REV')),
5857 ('r', 'rev', '', _('revision to tag'), _('REV')),
5851 ('', 'remove', None, _('remove a tag')),
5858 ('', 'remove', None, _('remove a tag')),
5852 # -l/--local is already there, commitopts cannot be used
5859 # -l/--local is already there, commitopts cannot be used
5853 ('e', 'edit', None, _('invoke editor on commit messages')),
5860 ('e', 'edit', None, _('invoke editor on commit messages')),
5854 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5861 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5855 ] + commitopts2,
5862 ] + commitopts2,
5856 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5863 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5857 def tag(ui, repo, name1, *names, **opts):
5864 def tag(ui, repo, name1, *names, **opts):
5858 """add one or more tags for the current or given revision
5865 """add one or more tags for the current or given revision
5859
5866
5860 Name a particular revision using <name>.
5867 Name a particular revision using <name>.
5861
5868
5862 Tags are used to name particular revisions of the repository and are
5869 Tags are used to name particular revisions of the repository and are
5863 very useful to compare different revisions, to go back to significant
5870 very useful to compare different revisions, to go back to significant
5864 earlier versions or to mark branch points as releases, etc. Changing
5871 earlier versions or to mark branch points as releases, etc. Changing
5865 an existing tag is normally disallowed; use -f/--force to override.
5872 an existing tag is normally disallowed; use -f/--force to override.
5866
5873
5867 If no revision is given, the parent of the working directory is
5874 If no revision is given, the parent of the working directory is
5868 used.
5875 used.
5869
5876
5870 To facilitate version control, distribution, and merging of tags,
5877 To facilitate version control, distribution, and merging of tags,
5871 they are stored as a file named ".hgtags" which is managed similarly
5878 they are stored as a file named ".hgtags" which is managed similarly
5872 to other project files and can be hand-edited if necessary. This
5879 to other project files and can be hand-edited if necessary. This
5873 also means that tagging creates a new commit. The file
5880 also means that tagging creates a new commit. The file
5874 ".hg/localtags" is used for local tags (not shared among
5881 ".hg/localtags" is used for local tags (not shared among
5875 repositories).
5882 repositories).
5876
5883
5877 Tag commits are usually made at the head of a branch. If the parent
5884 Tag commits are usually made at the head of a branch. If the parent
5878 of the working directory is not a branch head, :hg:`tag` aborts; use
5885 of the working directory is not a branch head, :hg:`tag` aborts; use
5879 -f/--force to force the tag commit to be based on a non-head
5886 -f/--force to force the tag commit to be based on a non-head
5880 changeset.
5887 changeset.
5881
5888
5882 See :hg:`help dates` for a list of formats valid for -d/--date.
5889 See :hg:`help dates` for a list of formats valid for -d/--date.
5883
5890
5884 Since tag names have priority over branch names during revision
5891 Since tag names have priority over branch names during revision
5885 lookup, using an existing branch name as a tag name is discouraged.
5892 lookup, using an existing branch name as a tag name is discouraged.
5886
5893
5887 Returns 0 on success.
5894 Returns 0 on success.
5888 """
5895 """
5889 wlock = lock = None
5896 wlock = lock = None
5890 try:
5897 try:
5891 wlock = repo.wlock()
5898 wlock = repo.wlock()
5892 lock = repo.lock()
5899 lock = repo.lock()
5893 rev_ = "."
5900 rev_ = "."
5894 names = [t.strip() for t in (name1,) + names]
5901 names = [t.strip() for t in (name1,) + names]
5895 if len(names) != len(set(names)):
5902 if len(names) != len(set(names)):
5896 raise util.Abort(_('tag names must be unique'))
5903 raise util.Abort(_('tag names must be unique'))
5897 for n in names:
5904 for n in names:
5898 scmutil.checknewlabel(repo, n, 'tag')
5905 scmutil.checknewlabel(repo, n, 'tag')
5899 if not n:
5906 if not n:
5900 raise util.Abort(_('tag names cannot consist entirely of '
5907 raise util.Abort(_('tag names cannot consist entirely of '
5901 'whitespace'))
5908 'whitespace'))
5902 if opts.get('rev') and opts.get('remove'):
5909 if opts.get('rev') and opts.get('remove'):
5903 raise util.Abort(_("--rev and --remove are incompatible"))
5910 raise util.Abort(_("--rev and --remove are incompatible"))
5904 if opts.get('rev'):
5911 if opts.get('rev'):
5905 rev_ = opts['rev']
5912 rev_ = opts['rev']
5906 message = opts.get('message')
5913 message = opts.get('message')
5907 if opts.get('remove'):
5914 if opts.get('remove'):
5908 expectedtype = opts.get('local') and 'local' or 'global'
5915 expectedtype = opts.get('local') and 'local' or 'global'
5909 for n in names:
5916 for n in names:
5910 if not repo.tagtype(n):
5917 if not repo.tagtype(n):
5911 raise util.Abort(_("tag '%s' does not exist") % n)
5918 raise util.Abort(_("tag '%s' does not exist") % n)
5912 if repo.tagtype(n) != expectedtype:
5919 if repo.tagtype(n) != expectedtype:
5913 if expectedtype == 'global':
5920 if expectedtype == 'global':
5914 raise util.Abort(_("tag '%s' is not a global tag") % n)
5921 raise util.Abort(_("tag '%s' is not a global tag") % n)
5915 else:
5922 else:
5916 raise util.Abort(_("tag '%s' is not a local tag") % n)
5923 raise util.Abort(_("tag '%s' is not a local tag") % n)
5917 rev_ = nullid
5924 rev_ = nullid
5918 if not message:
5925 if not message:
5919 # we don't translate commit messages
5926 # we don't translate commit messages
5920 message = 'Removed tag %s' % ', '.join(names)
5927 message = 'Removed tag %s' % ', '.join(names)
5921 elif not opts.get('force'):
5928 elif not opts.get('force'):
5922 for n in names:
5929 for n in names:
5923 if n in repo.tags():
5930 if n in repo.tags():
5924 raise util.Abort(_("tag '%s' already exists "
5931 raise util.Abort(_("tag '%s' already exists "
5925 "(use -f to force)") % n)
5932 "(use -f to force)") % n)
5926 if not opts.get('local'):
5933 if not opts.get('local'):
5927 p1, p2 = repo.dirstate.parents()
5934 p1, p2 = repo.dirstate.parents()
5928 if p2 != nullid:
5935 if p2 != nullid:
5929 raise util.Abort(_('uncommitted merge'))
5936 raise util.Abort(_('uncommitted merge'))
5930 bheads = repo.branchheads()
5937 bheads = repo.branchheads()
5931 if not opts.get('force') and bheads and p1 not in bheads:
5938 if not opts.get('force') and bheads and p1 not in bheads:
5932 raise util.Abort(_('not at a branch head (use -f to force)'))
5939 raise util.Abort(_('not at a branch head (use -f to force)'))
5933 r = scmutil.revsingle(repo, rev_).node()
5940 r = scmutil.revsingle(repo, rev_).node()
5934
5941
5935 if not message:
5942 if not message:
5936 # we don't translate commit messages
5943 # we don't translate commit messages
5937 message = ('Added tag %s for changeset %s' %
5944 message = ('Added tag %s for changeset %s' %
5938 (', '.join(names), short(r)))
5945 (', '.join(names), short(r)))
5939
5946
5940 date = opts.get('date')
5947 date = opts.get('date')
5941 if date:
5948 if date:
5942 date = util.parsedate(date)
5949 date = util.parsedate(date)
5943
5950
5944 if opts.get('remove'):
5951 if opts.get('remove'):
5945 editform = 'tag.remove'
5952 editform = 'tag.remove'
5946 else:
5953 else:
5947 editform = 'tag.add'
5954 editform = 'tag.add'
5948 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5955 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5949
5956
5950 # don't allow tagging the null rev
5957 # don't allow tagging the null rev
5951 if (not opts.get('remove') and
5958 if (not opts.get('remove') and
5952 scmutil.revsingle(repo, rev_).rev() == nullrev):
5959 scmutil.revsingle(repo, rev_).rev() == nullrev):
5953 raise util.Abort(_("cannot tag null revision"))
5960 raise util.Abort(_("cannot tag null revision"))
5954
5961
5955 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5962 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5956 editor=editor)
5963 editor=editor)
5957 finally:
5964 finally:
5958 release(lock, wlock)
5965 release(lock, wlock)
5959
5966
5960 @command('tags', [], '')
5967 @command('tags', formatteropts, '')
5961 def tags(ui, repo, **opts):
5968 def tags(ui, repo, **opts):
5962 """list repository tags
5969 """list repository tags
5963
5970
5964 This lists both regular and local tags. When the -v/--verbose
5971 This lists both regular and local tags. When the -v/--verbose
5965 switch is used, a third column "local" is printed for local tags.
5972 switch is used, a third column "local" is printed for local tags.
5966
5973
5967 Returns 0 on success.
5974 Returns 0 on success.
5968 """
5975 """
5969
5976
5970 fm = ui.formatter('tags', opts)
5977 fm = ui.formatter('tags', opts)
5971 hexfunc = ui.debugflag and hex or short
5978 hexfunc = ui.debugflag and hex or short
5972 tagtype = ""
5979 tagtype = ""
5973
5980
5974 for t, n in reversed(repo.tagslist()):
5981 for t, n in reversed(repo.tagslist()):
5975 hn = hexfunc(n)
5982 hn = hexfunc(n)
5976 label = 'tags.normal'
5983 label = 'tags.normal'
5977 tagtype = ''
5984 tagtype = ''
5978 if repo.tagtype(t) == 'local':
5985 if repo.tagtype(t) == 'local':
5979 label = 'tags.local'
5986 label = 'tags.local'
5980 tagtype = 'local'
5987 tagtype = 'local'
5981
5988
5982 fm.startitem()
5989 fm.startitem()
5983 fm.write('tag', '%s', t, label=label)
5990 fm.write('tag', '%s', t, label=label)
5984 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5991 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5985 fm.condwrite(not ui.quiet, 'rev id', fmt,
5992 fm.condwrite(not ui.quiet, 'rev id', fmt,
5986 repo.changelog.rev(n), hn, label=label)
5993 repo.changelog.rev(n), hn, label=label)
5987 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5994 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5988 tagtype, label=label)
5995 tagtype, label=label)
5989 fm.plain('\n')
5996 fm.plain('\n')
5990 fm.end()
5997 fm.end()
5991
5998
5992 @command('tip',
5999 @command('tip',
5993 [('p', 'patch', None, _('show patch')),
6000 [('p', 'patch', None, _('show patch')),
5994 ('g', 'git', None, _('use git extended diff format')),
6001 ('g', 'git', None, _('use git extended diff format')),
5995 ] + templateopts,
6002 ] + templateopts,
5996 _('[-p] [-g]'))
6003 _('[-p] [-g]'))
5997 def tip(ui, repo, **opts):
6004 def tip(ui, repo, **opts):
5998 """show the tip revision (DEPRECATED)
6005 """show the tip revision (DEPRECATED)
5999
6006
6000 The tip revision (usually just called the tip) is the changeset
6007 The tip revision (usually just called the tip) is the changeset
6001 most recently added to the repository (and therefore the most
6008 most recently added to the repository (and therefore the most
6002 recently changed head).
6009 recently changed head).
6003
6010
6004 If you have just made a commit, that commit will be the tip. If
6011 If you have just made a commit, that commit will be the tip. If
6005 you have just pulled changes from another repository, the tip of
6012 you have just pulled changes from another repository, the tip of
6006 that repository becomes the current tip. The "tip" tag is special
6013 that repository becomes the current tip. The "tip" tag is special
6007 and cannot be renamed or assigned to a different changeset.
6014 and cannot be renamed or assigned to a different changeset.
6008
6015
6009 This command is deprecated, please use :hg:`heads` instead.
6016 This command is deprecated, please use :hg:`heads` instead.
6010
6017
6011 Returns 0 on success.
6018 Returns 0 on success.
6012 """
6019 """
6013 displayer = cmdutil.show_changeset(ui, repo, opts)
6020 displayer = cmdutil.show_changeset(ui, repo, opts)
6014 displayer.show(repo['tip'])
6021 displayer.show(repo['tip'])
6015 displayer.close()
6022 displayer.close()
6016
6023
6017 @command('unbundle',
6024 @command('unbundle',
6018 [('u', 'update', None,
6025 [('u', 'update', None,
6019 _('update to new branch head if changesets were unbundled'))],
6026 _('update to new branch head if changesets were unbundled'))],
6020 _('[-u] FILE...'))
6027 _('[-u] FILE...'))
6021 def unbundle(ui, repo, fname1, *fnames, **opts):
6028 def unbundle(ui, repo, fname1, *fnames, **opts):
6022 """apply one or more changegroup files
6029 """apply one or more changegroup files
6023
6030
6024 Apply one or more compressed changegroup files generated by the
6031 Apply one or more compressed changegroup files generated by the
6025 bundle command.
6032 bundle command.
6026
6033
6027 Returns 0 on success, 1 if an update has unresolved files.
6034 Returns 0 on success, 1 if an update has unresolved files.
6028 """
6035 """
6029 fnames = (fname1,) + fnames
6036 fnames = (fname1,) + fnames
6030
6037
6031 lock = repo.lock()
6038 lock = repo.lock()
6032 try:
6039 try:
6033 for fname in fnames:
6040 for fname in fnames:
6034 f = hg.openpath(ui, fname)
6041 f = hg.openpath(ui, fname)
6035 gen = exchange.readbundle(ui, f, fname)
6042 gen = exchange.readbundle(ui, f, fname)
6036 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6043 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6037 'bundle:' + fname)
6044 'bundle:' + fname)
6038 finally:
6045 finally:
6039 lock.release()
6046 lock.release()
6040
6047
6041 return postincoming(ui, repo, modheads, opts.get('update'), None)
6048 return postincoming(ui, repo, modheads, opts.get('update'), None)
6042
6049
6043 @command('^update|up|checkout|co',
6050 @command('^update|up|checkout|co',
6044 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6051 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6045 ('c', 'check', None,
6052 ('c', 'check', None,
6046 _('update across branches if no uncommitted changes')),
6053 _('update across branches if no uncommitted changes')),
6047 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6054 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6048 ('r', 'rev', '', _('revision'), _('REV'))
6055 ('r', 'rev', '', _('revision'), _('REV'))
6049 ] + mergetoolopts,
6056 ] + mergetoolopts,
6050 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6057 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6051 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6058 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6052 tool=None):
6059 tool=None):
6053 """update working directory (or switch revisions)
6060 """update working directory (or switch revisions)
6054
6061
6055 Update the repository's working directory to the specified
6062 Update the repository's working directory to the specified
6056 changeset. If no changeset is specified, update to the tip of the
6063 changeset. If no changeset is specified, update to the tip of the
6057 current named branch and move the current bookmark (see :hg:`help
6064 current named branch and move the current bookmark (see :hg:`help
6058 bookmarks`).
6065 bookmarks`).
6059
6066
6060 Update sets the working directory's parent revision to the specified
6067 Update sets the working directory's parent revision to the specified
6061 changeset (see :hg:`help parents`).
6068 changeset (see :hg:`help parents`).
6062
6069
6063 If the changeset is not a descendant or ancestor of the working
6070 If the changeset is not a descendant or ancestor of the working
6064 directory's parent, the update is aborted. With the -c/--check
6071 directory's parent, the update is aborted. With the -c/--check
6065 option, the working directory is checked for uncommitted changes; if
6072 option, the working directory is checked for uncommitted changes; if
6066 none are found, the working directory is updated to the specified
6073 none are found, the working directory is updated to the specified
6067 changeset.
6074 changeset.
6068
6075
6069 .. container:: verbose
6076 .. container:: verbose
6070
6077
6071 The following rules apply when the working directory contains
6078 The following rules apply when the working directory contains
6072 uncommitted changes:
6079 uncommitted changes:
6073
6080
6074 1. If neither -c/--check nor -C/--clean is specified, and if
6081 1. If neither -c/--check nor -C/--clean is specified, and if
6075 the requested changeset is an ancestor or descendant of
6082 the requested changeset is an ancestor or descendant of
6076 the working directory's parent, the uncommitted changes
6083 the working directory's parent, the uncommitted changes
6077 are merged into the requested changeset and the merged
6084 are merged into the requested changeset and the merged
6078 result is left uncommitted. If the requested changeset is
6085 result is left uncommitted. If the requested changeset is
6079 not an ancestor or descendant (that is, it is on another
6086 not an ancestor or descendant (that is, it is on another
6080 branch), the update is aborted and the uncommitted changes
6087 branch), the update is aborted and the uncommitted changes
6081 are preserved.
6088 are preserved.
6082
6089
6083 2. With the -c/--check option, the update is aborted and the
6090 2. With the -c/--check option, the update is aborted and the
6084 uncommitted changes are preserved.
6091 uncommitted changes are preserved.
6085
6092
6086 3. With the -C/--clean option, uncommitted changes are discarded and
6093 3. With the -C/--clean option, uncommitted changes are discarded and
6087 the working directory is updated to the requested changeset.
6094 the working directory is updated to the requested changeset.
6088
6095
6089 To cancel an uncommitted merge (and lose your changes), use
6096 To cancel an uncommitted merge (and lose your changes), use
6090 :hg:`update --clean .`.
6097 :hg:`update --clean .`.
6091
6098
6092 Use null as the changeset to remove the working directory (like
6099 Use null as the changeset to remove the working directory (like
6093 :hg:`clone -U`).
6100 :hg:`clone -U`).
6094
6101
6095 If you want to revert just one file to an older revision, use
6102 If you want to revert just one file to an older revision, use
6096 :hg:`revert [-r REV] NAME`.
6103 :hg:`revert [-r REV] NAME`.
6097
6104
6098 See :hg:`help dates` for a list of formats valid for -d/--date.
6105 See :hg:`help dates` for a list of formats valid for -d/--date.
6099
6106
6100 Returns 0 on success, 1 if there are unresolved files.
6107 Returns 0 on success, 1 if there are unresolved files.
6101 """
6108 """
6102 if rev and node:
6109 if rev and node:
6103 raise util.Abort(_("please specify just one revision"))
6110 raise util.Abort(_("please specify just one revision"))
6104
6111
6105 if rev is None or rev == '':
6112 if rev is None or rev == '':
6106 rev = node
6113 rev = node
6107
6114
6108 cmdutil.clearunfinished(repo)
6115 cmdutil.clearunfinished(repo)
6109
6116
6110 # with no argument, we also move the current bookmark, if any
6117 # with no argument, we also move the current bookmark, if any
6111 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6118 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6112
6119
6113 # if we defined a bookmark, we have to remember the original bookmark name
6120 # if we defined a bookmark, we have to remember the original bookmark name
6114 brev = rev
6121 brev = rev
6115 rev = scmutil.revsingle(repo, rev, rev).rev()
6122 rev = scmutil.revsingle(repo, rev, rev).rev()
6116
6123
6117 if check and clean:
6124 if check and clean:
6118 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6125 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6119
6126
6120 if date:
6127 if date:
6121 if rev is not None:
6128 if rev is not None:
6122 raise util.Abort(_("you can't specify a revision and a date"))
6129 raise util.Abort(_("you can't specify a revision and a date"))
6123 rev = cmdutil.finddate(ui, repo, date)
6130 rev = cmdutil.finddate(ui, repo, date)
6124
6131
6125 if check:
6132 if check:
6126 c = repo[None]
6133 c = repo[None]
6127 if c.dirty(merge=False, branch=False, missing=True):
6134 if c.dirty(merge=False, branch=False, missing=True):
6128 raise util.Abort(_("uncommitted changes"))
6135 raise util.Abort(_("uncommitted changes"))
6129 if rev is None:
6136 if rev is None:
6130 rev = repo[repo[None].branch()].rev()
6137 rev = repo[repo[None].branch()].rev()
6131 mergemod._checkunknown(repo, repo[None], repo[rev])
6138 mergemod._checkunknown(repo, repo[None], repo[rev])
6132
6139
6133 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6140 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6134
6141
6135 if clean:
6142 if clean:
6136 ret = hg.clean(repo, rev)
6143 ret = hg.clean(repo, rev)
6137 else:
6144 else:
6138 ret = hg.update(repo, rev)
6145 ret = hg.update(repo, rev)
6139
6146
6140 if not ret and movemarkfrom:
6147 if not ret and movemarkfrom:
6141 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6148 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6142 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6149 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6143 elif brev in repo._bookmarks:
6150 elif brev in repo._bookmarks:
6144 bookmarks.setcurrent(repo, brev)
6151 bookmarks.setcurrent(repo, brev)
6145 ui.status(_("(activating bookmark %s)\n") % brev)
6152 ui.status(_("(activating bookmark %s)\n") % brev)
6146 elif brev:
6153 elif brev:
6147 if repo._bookmarkcurrent:
6154 if repo._bookmarkcurrent:
6148 ui.status(_("(leaving bookmark %s)\n") %
6155 ui.status(_("(leaving bookmark %s)\n") %
6149 repo._bookmarkcurrent)
6156 repo._bookmarkcurrent)
6150 bookmarks.unsetcurrent(repo)
6157 bookmarks.unsetcurrent(repo)
6151
6158
6152 return ret
6159 return ret
6153
6160
6154 @command('verify', [])
6161 @command('verify', [])
6155 def verify(ui, repo):
6162 def verify(ui, repo):
6156 """verify the integrity of the repository
6163 """verify the integrity of the repository
6157
6164
6158 Verify the integrity of the current repository.
6165 Verify the integrity of the current repository.
6159
6166
6160 This will perform an extensive check of the repository's
6167 This will perform an extensive check of the repository's
6161 integrity, validating the hashes and checksums of each entry in
6168 integrity, validating the hashes and checksums of each entry in
6162 the changelog, manifest, and tracked files, as well as the
6169 the changelog, manifest, and tracked files, as well as the
6163 integrity of their crosslinks and indices.
6170 integrity of their crosslinks and indices.
6164
6171
6165 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6172 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6166 for more information about recovery from corruption of the
6173 for more information about recovery from corruption of the
6167 repository.
6174 repository.
6168
6175
6169 Returns 0 on success, 1 if errors are encountered.
6176 Returns 0 on success, 1 if errors are encountered.
6170 """
6177 """
6171 return hg.verify(repo)
6178 return hg.verify(repo)
6172
6179
6173 @command('version', [], norepo=True)
6180 @command('version', [], norepo=True)
6174 def version_(ui):
6181 def version_(ui):
6175 """output version and copyright information"""
6182 """output version and copyright information"""
6176 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6183 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6177 % util.version())
6184 % util.version())
6178 ui.status(_(
6185 ui.status(_(
6179 "(see http://mercurial.selenic.com for more information)\n"
6186 "(see http://mercurial.selenic.com for more information)\n"
6180 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6187 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6181 "This is free software; see the source for copying conditions. "
6188 "This is free software; see the source for copying conditions. "
6182 "There is NO\nwarranty; "
6189 "There is NO\nwarranty; "
6183 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6190 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6184 ))
6191 ))
6185
6192
6186 ui.note(_("\nEnabled extensions:\n\n"))
6193 ui.note(_("\nEnabled extensions:\n\n"))
6187 if ui.verbose:
6194 if ui.verbose:
6188 # format names and versions into columns
6195 # format names and versions into columns
6189 names = []
6196 names = []
6190 vers = []
6197 vers = []
6191 for name, module in extensions.extensions():
6198 for name, module in extensions.extensions():
6192 names.append(name)
6199 names.append(name)
6193 vers.append(extensions.moduleversion(module))
6200 vers.append(extensions.moduleversion(module))
6194 if names:
6201 if names:
6195 maxnamelen = max(len(n) for n in names)
6202 maxnamelen = max(len(n) for n in names)
6196 for i, name in enumerate(names):
6203 for i, name in enumerate(names):
6197 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6204 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,334 +1,334
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 config
16 config
17 copy
17 copy
18 diff
18 diff
19 export
19 export
20 files
20 files
21 forget
21 forget
22 graft
22 graft
23 grep
23 grep
24 heads
24 heads
25 help
25 help
26 identify
26 identify
27 import
27 import
28 incoming
28 incoming
29 init
29 init
30 locate
30 locate
31 log
31 log
32 manifest
32 manifest
33 merge
33 merge
34 outgoing
34 outgoing
35 parents
35 parents
36 paths
36 paths
37 phase
37 phase
38 pull
38 pull
39 push
39 push
40 recover
40 recover
41 remove
41 remove
42 rename
42 rename
43 resolve
43 resolve
44 revert
44 revert
45 rollback
45 rollback
46 root
46 root
47 serve
47 serve
48 status
48 status
49 summary
49 summary
50 tag
50 tag
51 tags
51 tags
52 tip
52 tip
53 unbundle
53 unbundle
54 update
54 update
55 verify
55 verify
56 version
56 version
57
57
58 Show all commands that start with "a"
58 Show all commands that start with "a"
59 $ hg debugcomplete a
59 $ hg debugcomplete a
60 add
60 add
61 addremove
61 addremove
62 annotate
62 annotate
63 archive
63 archive
64
64
65 Do not show debug commands if there are other candidates
65 Do not show debug commands if there are other candidates
66 $ hg debugcomplete d
66 $ hg debugcomplete d
67 diff
67 diff
68
68
69 Show debug commands if there are no other candidates
69 Show debug commands if there are no other candidates
70 $ hg debugcomplete debug
70 $ hg debugcomplete debug
71 debugancestor
71 debugancestor
72 debugbuilddag
72 debugbuilddag
73 debugbundle
73 debugbundle
74 debugcheckstate
74 debugcheckstate
75 debugcommands
75 debugcommands
76 debugcomplete
76 debugcomplete
77 debugconfig
77 debugconfig
78 debugdag
78 debugdag
79 debugdata
79 debugdata
80 debugdate
80 debugdate
81 debugdirstate
81 debugdirstate
82 debugdiscovery
82 debugdiscovery
83 debugfileset
83 debugfileset
84 debugfsinfo
84 debugfsinfo
85 debuggetbundle
85 debuggetbundle
86 debugignore
86 debugignore
87 debugindex
87 debugindex
88 debugindexdot
88 debugindexdot
89 debuginstall
89 debuginstall
90 debugknown
90 debugknown
91 debuglabelcomplete
91 debuglabelcomplete
92 debugobsolete
92 debugobsolete
93 debugpathcomplete
93 debugpathcomplete
94 debugpushkey
94 debugpushkey
95 debugpvec
95 debugpvec
96 debugrebuilddirstate
96 debugrebuilddirstate
97 debugrename
97 debugrename
98 debugrevlog
98 debugrevlog
99 debugrevspec
99 debugrevspec
100 debugsetparents
100 debugsetparents
101 debugsub
101 debugsub
102 debugsuccessorssets
102 debugsuccessorssets
103 debugwalk
103 debugwalk
104 debugwireargs
104 debugwireargs
105
105
106 Do not show the alias of a debug command if there are other candidates
106 Do not show the alias of a debug command if there are other candidates
107 (this should hide rawcommit)
107 (this should hide rawcommit)
108 $ hg debugcomplete r
108 $ hg debugcomplete r
109 recover
109 recover
110 remove
110 remove
111 rename
111 rename
112 resolve
112 resolve
113 revert
113 revert
114 rollback
114 rollback
115 root
115 root
116 Show the alias of a debug command if there are no other candidates
116 Show the alias of a debug command if there are no other candidates
117 $ hg debugcomplete rawc
117 $ hg debugcomplete rawc
118
118
119
119
120 Show the global options
120 Show the global options
121 $ hg debugcomplete --options | sort
121 $ hg debugcomplete --options | sort
122 --config
122 --config
123 --cwd
123 --cwd
124 --debug
124 --debug
125 --debugger
125 --debugger
126 --encoding
126 --encoding
127 --encodingmode
127 --encodingmode
128 --help
128 --help
129 --hidden
129 --hidden
130 --noninteractive
130 --noninteractive
131 --profile
131 --profile
132 --quiet
132 --quiet
133 --repository
133 --repository
134 --time
134 --time
135 --traceback
135 --traceback
136 --verbose
136 --verbose
137 --version
137 --version
138 -R
138 -R
139 -h
139 -h
140 -q
140 -q
141 -v
141 -v
142 -y
142 -y
143
143
144 Show the options for the "serve" command
144 Show the options for the "serve" command
145 $ hg debugcomplete --options serve | sort
145 $ hg debugcomplete --options serve | sort
146 --accesslog
146 --accesslog
147 --address
147 --address
148 --certificate
148 --certificate
149 --cmdserver
149 --cmdserver
150 --config
150 --config
151 --cwd
151 --cwd
152 --daemon
152 --daemon
153 --daemon-pipefds
153 --daemon-pipefds
154 --debug
154 --debug
155 --debugger
155 --debugger
156 --encoding
156 --encoding
157 --encodingmode
157 --encodingmode
158 --errorlog
158 --errorlog
159 --help
159 --help
160 --hidden
160 --hidden
161 --ipv6
161 --ipv6
162 --name
162 --name
163 --noninteractive
163 --noninteractive
164 --pid-file
164 --pid-file
165 --port
165 --port
166 --prefix
166 --prefix
167 --profile
167 --profile
168 --quiet
168 --quiet
169 --repository
169 --repository
170 --stdio
170 --stdio
171 --style
171 --style
172 --templates
172 --templates
173 --time
173 --time
174 --traceback
174 --traceback
175 --verbose
175 --verbose
176 --version
176 --version
177 --web-conf
177 --web-conf
178 -6
178 -6
179 -A
179 -A
180 -E
180 -E
181 -R
181 -R
182 -a
182 -a
183 -d
183 -d
184 -h
184 -h
185 -n
185 -n
186 -p
186 -p
187 -q
187 -q
188 -t
188 -t
189 -v
189 -v
190 -y
190 -y
191
191
192 Show an error if we use --options with an ambiguous abbreviation
192 Show an error if we use --options with an ambiguous abbreviation
193 $ hg debugcomplete --options s
193 $ hg debugcomplete --options s
194 hg: command 's' is ambiguous:
194 hg: command 's' is ambiguous:
195 serve showconfig status summary
195 serve showconfig status summary
196 [255]
196 [255]
197
197
198 Show all commands + options
198 Show all commands + options
199 $ hg debugcommands
199 $ hg debugcommands
200 add: include, exclude, subrepos, dry-run
200 add: include, exclude, subrepos, dry-run
201 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude
201 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude
202 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
202 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
203 commit: addremove, close-branch, amend, secret, edit, include, exclude, message, logfile, date, user, subrepos
203 commit: addremove, close-branch, amend, secret, edit, include, exclude, message, logfile, date, user, subrepos
204 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
204 diff: rev, change, text, git, nodates, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
205 export: output, switch-parent, rev, text, git, nodates
205 export: output, switch-parent, rev, text, git, nodates
206 forget: include, exclude
206 forget: include, exclude
207 init: ssh, remotecmd, insecure
207 init: ssh, remotecmd, insecure
208 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
208 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
209 merge: force, rev, preview, tool
209 merge: force, rev, preview, tool
210 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
210 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
211 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
211 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
212 remove: after, force, include, exclude
212 remove: after, force, include, exclude
213 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
213 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
214 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos
214 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
215 summary: remote
215 summary: remote
216 update: clean, check, date, rev, tool
216 update: clean, check, date, rev, tool
217 addremove: similarity, include, exclude, dry-run
217 addremove: similarity, include, exclude, dry-run
218 archive: no-decode, prefix, rev, type, subrepos, include, exclude
218 archive: no-decode, prefix, rev, type, subrepos, include, exclude
219 backout: merge, parent, rev, edit, tool, include, exclude, message, logfile, date, user
219 backout: merge, parent, rev, edit, tool, include, exclude, message, logfile, date, user
220 bisect: reset, good, bad, skip, extend, command, noupdate
220 bisect: reset, good, bad, skip, extend, command, noupdate
221 bookmarks: force, rev, delete, rename, inactive
221 bookmarks: force, rev, delete, rename, inactive
222 branch: force, clean
222 branch: force, clean
223 branches: active, closed
223 branches: active, closed
224 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
224 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
225 cat: output, rev, decode, include, exclude
225 cat: output, rev, decode, include, exclude
226 config: untrusted, edit, local, global
226 config: untrusted, edit, local, global
227 copy: after, force, include, exclude, dry-run
227 copy: after, force, include, exclude, dry-run
228 debugancestor:
228 debugancestor:
229 debugbuilddag: mergeable-file, overwritten-file, new-file
229 debugbuilddag: mergeable-file, overwritten-file, new-file
230 debugbundle: all
230 debugbundle: all
231 debugcheckstate:
231 debugcheckstate:
232 debugcommands:
232 debugcommands:
233 debugcomplete: options
233 debugcomplete: options
234 debugdag: tags, branches, dots, spaces
234 debugdag: tags, branches, dots, spaces
235 debugdata: changelog, manifest
235 debugdata: changelog, manifest
236 debugdate: extended
236 debugdate: extended
237 debugdirstate: nodates, datesort
237 debugdirstate: nodates, datesort
238 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
238 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
239 debugfileset: rev
239 debugfileset: rev
240 debugfsinfo:
240 debugfsinfo:
241 debuggetbundle: head, common, type
241 debuggetbundle: head, common, type
242 debugignore:
242 debugignore:
243 debugindex: changelog, manifest, format
243 debugindex: changelog, manifest, format
244 debugindexdot:
244 debugindexdot:
245 debuginstall:
245 debuginstall:
246 debugknown:
246 debugknown:
247 debuglabelcomplete:
247 debuglabelcomplete:
248 debugobsolete: flags, record-parents, rev, date, user
248 debugobsolete: flags, record-parents, rev, date, user
249 debugpathcomplete: full, normal, added, removed
249 debugpathcomplete: full, normal, added, removed
250 debugpushkey:
250 debugpushkey:
251 debugpvec:
251 debugpvec:
252 debugrebuilddirstate: rev
252 debugrebuilddirstate: rev
253 debugrename: rev
253 debugrename: rev
254 debugrevlog: changelog, manifest, dump
254 debugrevlog: changelog, manifest, dump
255 debugrevspec: optimize
255 debugrevspec: optimize
256 debugsetparents:
256 debugsetparents:
257 debugsub: rev
257 debugsub: rev
258 debugsuccessorssets:
258 debugsuccessorssets:
259 debugwalk: include, exclude
259 debugwalk: include, exclude
260 debugwireargs: three, four, five, ssh, remotecmd, insecure
260 debugwireargs: three, four, five, ssh, remotecmd, insecure
261 files: rev, print0, include, exclude
261 files: rev, print0, include, exclude, template
262 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
262 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
263 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
263 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
264 heads: rev, topo, active, closed, style, template
264 heads: rev, topo, active, closed, style, template
265 help: extension, command, keyword
265 help: extension, command, keyword
266 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
266 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
267 import: strip, base, edit, force, no-commit, bypass, partial, exact, import-branch, message, logfile, date, user, similarity
267 import: strip, base, edit, force, no-commit, bypass, partial, exact, import-branch, message, logfile, date, user, similarity
268 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
268 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
269 locate: rev, print0, fullpath, include, exclude
269 locate: rev, print0, fullpath, include, exclude
270 manifest: rev, all
270 manifest: rev, all, template
271 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
271 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
272 parents: rev, style, template
272 parents: rev, style, template
273 paths:
273 paths:
274 phase: public, draft, secret, force, rev
274 phase: public, draft, secret, force, rev
275 recover:
275 recover:
276 rename: after, force, include, exclude, dry-run
276 rename: after, force, include, exclude, dry-run
277 resolve: all, list, mark, unmark, no-status, tool, include, exclude
277 resolve: all, list, mark, unmark, no-status, tool, include, exclude
278 revert: all, date, rev, no-backup, include, exclude, dry-run
278 revert: all, date, rev, no-backup, include, exclude, dry-run
279 rollback: dry-run, force
279 rollback: dry-run, force
280 root:
280 root:
281 tag: force, local, rev, remove, edit, message, date, user
281 tag: force, local, rev, remove, edit, message, date, user
282 tags:
282 tags: template
283 tip: patch, git, style, template
283 tip: patch, git, style, template
284 unbundle: update
284 unbundle: update
285 verify:
285 verify:
286 version:
286 version:
287
287
288 $ hg init a
288 $ hg init a
289 $ cd a
289 $ cd a
290 $ echo fee > fee
290 $ echo fee > fee
291 $ hg ci -q -Amfee
291 $ hg ci -q -Amfee
292 $ hg tag fee
292 $ hg tag fee
293 $ mkdir fie
293 $ mkdir fie
294 $ echo dead > fie/dead
294 $ echo dead > fie/dead
295 $ echo live > fie/live
295 $ echo live > fie/live
296 $ hg bookmark fo
296 $ hg bookmark fo
297 $ hg branch -q fie
297 $ hg branch -q fie
298 $ hg ci -q -Amfie
298 $ hg ci -q -Amfie
299 $ echo fo > fo
299 $ echo fo > fo
300 $ hg branch -qf default
300 $ hg branch -qf default
301 $ hg ci -q -Amfo
301 $ hg ci -q -Amfo
302 $ echo Fum > Fum
302 $ echo Fum > Fum
303 $ hg ci -q -AmFum
303 $ hg ci -q -AmFum
304 $ hg bookmark Fum
304 $ hg bookmark Fum
305
305
306 Test debugpathcomplete
306 Test debugpathcomplete
307
307
308 $ hg debugpathcomplete f
308 $ hg debugpathcomplete f
309 fee
309 fee
310 fie
310 fie
311 fo
311 fo
312 $ hg debugpathcomplete -f f
312 $ hg debugpathcomplete -f f
313 fee
313 fee
314 fie/dead
314 fie/dead
315 fie/live
315 fie/live
316 fo
316 fo
317
317
318 $ hg rm Fum
318 $ hg rm Fum
319 $ hg debugpathcomplete -r F
319 $ hg debugpathcomplete -r F
320 Fum
320 Fum
321
321
322 Test debuglabelcomplete
322 Test debuglabelcomplete
323
323
324 $ hg debuglabelcomplete
324 $ hg debuglabelcomplete
325 Fum
325 Fum
326 default
326 default
327 fee
327 fee
328 fie
328 fie
329 fo
329 fo
330 tip
330 tip
331 $ hg debuglabelcomplete f
331 $ hg debuglabelcomplete f
332 fee
332 fee
333 fie
333 fie
334 fo
334 fo
@@ -1,256 +1,274
1 Test character encoding
1 Test character encoding
2
2
3 $ hg init t
3 $ hg init t
4 $ cd t
4 $ cd t
5
5
6 we need a repo with some legacy latin-1 changesets
6 we need a repo with some legacy latin-1 changesets
7
7
8 $ hg unbundle "$TESTDIR/bundles/legacy-encoding.hg"
8 $ hg unbundle "$TESTDIR/bundles/legacy-encoding.hg"
9 adding changesets
9 adding changesets
10 adding manifests
10 adding manifests
11 adding file changes
11 adding file changes
12 added 2 changesets with 2 changes to 1 files
12 added 2 changesets with 2 changes to 1 files
13 (run 'hg update' to get a working copy)
13 (run 'hg update' to get a working copy)
14 $ hg co
14 $ hg co
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 $ python << EOF
16 $ python << EOF
17 > f = file('latin-1', 'w'); f.write("latin-1 e' encoded: \xe9"); f.close()
17 > f = file('latin-1', 'w'); f.write("latin-1 e' encoded: \xe9"); f.close()
18 > f = file('utf-8', 'w'); f.write("utf-8 e' encoded: \xc3\xa9"); f.close()
18 > f = file('utf-8', 'w'); f.write("utf-8 e' encoded: \xc3\xa9"); f.close()
19 > f = file('latin-1-tag', 'w'); f.write("\xe9"); f.close()
19 > f = file('latin-1-tag', 'w'); f.write("\xe9"); f.close()
20 > EOF
20 > EOF
21
21
22 should fail with encoding error
22 should fail with encoding error
23
23
24 $ echo "plain old ascii" > a
24 $ echo "plain old ascii" > a
25 $ hg st
25 $ hg st
26 M a
26 M a
27 ? latin-1
27 ? latin-1
28 ? latin-1-tag
28 ? latin-1-tag
29 ? utf-8
29 ? utf-8
30 $ HGENCODING=ascii hg ci -l latin-1
30 $ HGENCODING=ascii hg ci -l latin-1
31 transaction abort!
31 transaction abort!
32 rollback completed
32 rollback completed
33 abort: decoding near ' encoded: \xe9': 'ascii' codec can't decode byte 0xe9 in position 20: ordinal not in range(128)! (esc)
33 abort: decoding near ' encoded: \xe9': 'ascii' codec can't decode byte 0xe9 in position 20: ordinal not in range(128)! (esc)
34 [255]
34 [255]
35
35
36 these should work
36 these should work
37
37
38 $ echo "latin-1" > a
38 $ echo "latin-1" > a
39 $ HGENCODING=latin-1 hg ci -l latin-1
39 $ HGENCODING=latin-1 hg ci -l latin-1
40 $ echo "utf-8" > a
40 $ echo "utf-8" > a
41 $ HGENCODING=utf-8 hg ci -l utf-8
41 $ HGENCODING=utf-8 hg ci -l utf-8
42 $ HGENCODING=latin-1 hg tag `cat latin-1-tag`
42 $ HGENCODING=latin-1 hg tag `cat latin-1-tag`
43 $ HGENCODING=latin-1 hg branch `cat latin-1-tag`
43 $ HGENCODING=latin-1 hg branch `cat latin-1-tag`
44 marked working directory as branch \xe9 (esc)
44 marked working directory as branch \xe9 (esc)
45 (branches are permanent and global, did you want a bookmark?)
45 (branches are permanent and global, did you want a bookmark?)
46 $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
46 $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
47 $ hg -q rollback
47 $ hg -q rollback
48 $ HGENCODING=latin-1 hg branch
48 $ HGENCODING=latin-1 hg branch
49 \xe9 (esc)
49 \xe9 (esc)
50 $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
50 $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
51 $ rm .hg/branch
51 $ rm .hg/branch
52
52
53 hg log (ascii)
53 hg log (ascii)
54
54
55 $ hg --encoding ascii log
55 $ hg --encoding ascii log
56 changeset: 5:a52c0692f24a
56 changeset: 5:a52c0692f24a
57 branch: ?
57 branch: ?
58 tag: tip
58 tag: tip
59 user: test
59 user: test
60 date: Thu Jan 01 00:00:00 1970 +0000
60 date: Thu Jan 01 00:00:00 1970 +0000
61 summary: latin1 branch
61 summary: latin1 branch
62
62
63 changeset: 4:94db611b4196
63 changeset: 4:94db611b4196
64 user: test
64 user: test
65 date: Thu Jan 01 00:00:00 1970 +0000
65 date: Thu Jan 01 00:00:00 1970 +0000
66 summary: Added tag ? for changeset ca661e7520de
66 summary: Added tag ? for changeset ca661e7520de
67
67
68 changeset: 3:ca661e7520de
68 changeset: 3:ca661e7520de
69 tag: ?
69 tag: ?
70 user: test
70 user: test
71 date: Thu Jan 01 00:00:00 1970 +0000
71 date: Thu Jan 01 00:00:00 1970 +0000
72 summary: utf-8 e' encoded: ?
72 summary: utf-8 e' encoded: ?
73
73
74 changeset: 2:650c6f3d55dd
74 changeset: 2:650c6f3d55dd
75 user: test
75 user: test
76 date: Thu Jan 01 00:00:00 1970 +0000
76 date: Thu Jan 01 00:00:00 1970 +0000
77 summary: latin-1 e' encoded: ?
77 summary: latin-1 e' encoded: ?
78
78
79 changeset: 1:0e5b7e3f9c4a
79 changeset: 1:0e5b7e3f9c4a
80 user: test
80 user: test
81 date: Mon Jan 12 13:46:40 1970 +0000
81 date: Mon Jan 12 13:46:40 1970 +0000
82 summary: koi8-r: ????? = u'\u0440\u0442\u0443\u0442\u044c'
82 summary: koi8-r: ????? = u'\u0440\u0442\u0443\u0442\u044c'
83
83
84 changeset: 0:1e78a93102a3
84 changeset: 0:1e78a93102a3
85 user: test
85 user: test
86 date: Mon Jan 12 13:46:40 1970 +0000
86 date: Mon Jan 12 13:46:40 1970 +0000
87 summary: latin-1 e': ? = u'\xe9'
87 summary: latin-1 e': ? = u'\xe9'
88
88
89
89
90 hg log (latin-1)
90 hg log (latin-1)
91
91
92 $ hg --encoding latin-1 log
92 $ hg --encoding latin-1 log
93 changeset: 5:a52c0692f24a
93 changeset: 5:a52c0692f24a
94 branch: \xe9 (esc)
94 branch: \xe9 (esc)
95 tag: tip
95 tag: tip
96 user: test
96 user: test
97 date: Thu Jan 01 00:00:00 1970 +0000
97 date: Thu Jan 01 00:00:00 1970 +0000
98 summary: latin1 branch
98 summary: latin1 branch
99
99
100 changeset: 4:94db611b4196
100 changeset: 4:94db611b4196
101 user: test
101 user: test
102 date: Thu Jan 01 00:00:00 1970 +0000
102 date: Thu Jan 01 00:00:00 1970 +0000
103 summary: Added tag \xe9 for changeset ca661e7520de (esc)
103 summary: Added tag \xe9 for changeset ca661e7520de (esc)
104
104
105 changeset: 3:ca661e7520de
105 changeset: 3:ca661e7520de
106 tag: \xe9 (esc)
106 tag: \xe9 (esc)
107 user: test
107 user: test
108 date: Thu Jan 01 00:00:00 1970 +0000
108 date: Thu Jan 01 00:00:00 1970 +0000
109 summary: utf-8 e' encoded: \xe9 (esc)
109 summary: utf-8 e' encoded: \xe9 (esc)
110
110
111 changeset: 2:650c6f3d55dd
111 changeset: 2:650c6f3d55dd
112 user: test
112 user: test
113 date: Thu Jan 01 00:00:00 1970 +0000
113 date: Thu Jan 01 00:00:00 1970 +0000
114 summary: latin-1 e' encoded: \xe9 (esc)
114 summary: latin-1 e' encoded: \xe9 (esc)
115
115
116 changeset: 1:0e5b7e3f9c4a
116 changeset: 1:0e5b7e3f9c4a
117 user: test
117 user: test
118 date: Mon Jan 12 13:46:40 1970 +0000
118 date: Mon Jan 12 13:46:40 1970 +0000
119 summary: koi8-r: \xd2\xd4\xd5\xd4\xd8 = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
119 summary: koi8-r: \xd2\xd4\xd5\xd4\xd8 = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
120
120
121 changeset: 0:1e78a93102a3
121 changeset: 0:1e78a93102a3
122 user: test
122 user: test
123 date: Mon Jan 12 13:46:40 1970 +0000
123 date: Mon Jan 12 13:46:40 1970 +0000
124 summary: latin-1 e': \xe9 = u'\\xe9' (esc)
124 summary: latin-1 e': \xe9 = u'\\xe9' (esc)
125
125
126
126
127 hg log (utf-8)
127 hg log (utf-8)
128
128
129 $ hg --encoding utf-8 log
129 $ hg --encoding utf-8 log
130 changeset: 5:a52c0692f24a
130 changeset: 5:a52c0692f24a
131 branch: \xc3\xa9 (esc)
131 branch: \xc3\xa9 (esc)
132 tag: tip
132 tag: tip
133 user: test
133 user: test
134 date: Thu Jan 01 00:00:00 1970 +0000
134 date: Thu Jan 01 00:00:00 1970 +0000
135 summary: latin1 branch
135 summary: latin1 branch
136
136
137 changeset: 4:94db611b4196
137 changeset: 4:94db611b4196
138 user: test
138 user: test
139 date: Thu Jan 01 00:00:00 1970 +0000
139 date: Thu Jan 01 00:00:00 1970 +0000
140 summary: Added tag \xc3\xa9 for changeset ca661e7520de (esc)
140 summary: Added tag \xc3\xa9 for changeset ca661e7520de (esc)
141
141
142 changeset: 3:ca661e7520de
142 changeset: 3:ca661e7520de
143 tag: \xc3\xa9 (esc)
143 tag: \xc3\xa9 (esc)
144 user: test
144 user: test
145 date: Thu Jan 01 00:00:00 1970 +0000
145 date: Thu Jan 01 00:00:00 1970 +0000
146 summary: utf-8 e' encoded: \xc3\xa9 (esc)
146 summary: utf-8 e' encoded: \xc3\xa9 (esc)
147
147
148 changeset: 2:650c6f3d55dd
148 changeset: 2:650c6f3d55dd
149 user: test
149 user: test
150 date: Thu Jan 01 00:00:00 1970 +0000
150 date: Thu Jan 01 00:00:00 1970 +0000
151 summary: latin-1 e' encoded: \xc3\xa9 (esc)
151 summary: latin-1 e' encoded: \xc3\xa9 (esc)
152
152
153 changeset: 1:0e5b7e3f9c4a
153 changeset: 1:0e5b7e3f9c4a
154 user: test
154 user: test
155 date: Mon Jan 12 13:46:40 1970 +0000
155 date: Mon Jan 12 13:46:40 1970 +0000
156 summary: koi8-r: \xc3\x92\xc3\x94\xc3\x95\xc3\x94\xc3\x98 = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
156 summary: koi8-r: \xc3\x92\xc3\x94\xc3\x95\xc3\x94\xc3\x98 = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
157
157
158 changeset: 0:1e78a93102a3
158 changeset: 0:1e78a93102a3
159 user: test
159 user: test
160 date: Mon Jan 12 13:46:40 1970 +0000
160 date: Mon Jan 12 13:46:40 1970 +0000
161 summary: latin-1 e': \xc3\xa9 = u'\\xe9' (esc)
161 summary: latin-1 e': \xc3\xa9 = u'\\xe9' (esc)
162
162
163
163
164 hg tags (ascii)
164 hg tags (ascii)
165
165
166 $ HGENCODING=ascii hg tags
166 $ HGENCODING=ascii hg tags
167 tip 5:a52c0692f24a
167 tip 5:a52c0692f24a
168 ? 3:ca661e7520de
168 ? 3:ca661e7520de
169
169
170 hg tags (latin-1)
170 hg tags (latin-1)
171
171
172 $ HGENCODING=latin-1 hg tags
172 $ HGENCODING=latin-1 hg tags
173 tip 5:a52c0692f24a
173 tip 5:a52c0692f24a
174 \xe9 3:ca661e7520de (esc)
174 \xe9 3:ca661e7520de (esc)
175
175
176 hg tags (utf-8)
176 hg tags (utf-8)
177
177
178 $ HGENCODING=utf-8 hg tags
178 $ HGENCODING=utf-8 hg tags
179 tip 5:a52c0692f24a
179 tip 5:a52c0692f24a
180 \xc3\xa9 3:ca661e7520de (esc)
180 \xc3\xa9 3:ca661e7520de (esc)
181
181
182 hg tags (JSON)
183
184 $ hg tags -Tjson
185 [
186 {
187 "id": "a52c0692f24a",
188 "rev": 5,
189 "tag": "tip",
190 "type": ""
191 },
192 {
193 "id": "ca661e7520de",
194 "rev": 3,
195 "tag": "\xc3\xa9", (esc)
196 "type": ""
197 }
198 ]
199
182 hg branches (ascii)
200 hg branches (ascii)
183
201
184 $ HGENCODING=ascii hg branches
202 $ HGENCODING=ascii hg branches
185 ? 5:a52c0692f24a
203 ? 5:a52c0692f24a
186 default 4:94db611b4196 (inactive)
204 default 4:94db611b4196 (inactive)
187
205
188 hg branches (latin-1)
206 hg branches (latin-1)
189
207
190 $ HGENCODING=latin-1 hg branches
208 $ HGENCODING=latin-1 hg branches
191 \xe9 5:a52c0692f24a (esc)
209 \xe9 5:a52c0692f24a (esc)
192 default 4:94db611b4196 (inactive)
210 default 4:94db611b4196 (inactive)
193
211
194 hg branches (utf-8)
212 hg branches (utf-8)
195
213
196 $ HGENCODING=utf-8 hg branches
214 $ HGENCODING=utf-8 hg branches
197 \xc3\xa9 5:a52c0692f24a (esc)
215 \xc3\xa9 5:a52c0692f24a (esc)
198 default 4:94db611b4196 (inactive)
216 default 4:94db611b4196 (inactive)
199 $ echo '[ui]' >> .hg/hgrc
217 $ echo '[ui]' >> .hg/hgrc
200 $ echo 'fallbackencoding = koi8-r' >> .hg/hgrc
218 $ echo 'fallbackencoding = koi8-r' >> .hg/hgrc
201
219
202 hg log (utf-8)
220 hg log (utf-8)
203
221
204 $ HGENCODING=utf-8 hg log
222 $ HGENCODING=utf-8 hg log
205 changeset: 5:a52c0692f24a
223 changeset: 5:a52c0692f24a
206 branch: \xc3\xa9 (esc)
224 branch: \xc3\xa9 (esc)
207 tag: tip
225 tag: tip
208 user: test
226 user: test
209 date: Thu Jan 01 00:00:00 1970 +0000
227 date: Thu Jan 01 00:00:00 1970 +0000
210 summary: latin1 branch
228 summary: latin1 branch
211
229
212 changeset: 4:94db611b4196
230 changeset: 4:94db611b4196
213 user: test
231 user: test
214 date: Thu Jan 01 00:00:00 1970 +0000
232 date: Thu Jan 01 00:00:00 1970 +0000
215 summary: Added tag \xc3\xa9 for changeset ca661e7520de (esc)
233 summary: Added tag \xc3\xa9 for changeset ca661e7520de (esc)
216
234
217 changeset: 3:ca661e7520de
235 changeset: 3:ca661e7520de
218 tag: \xc3\xa9 (esc)
236 tag: \xc3\xa9 (esc)
219 user: test
237 user: test
220 date: Thu Jan 01 00:00:00 1970 +0000
238 date: Thu Jan 01 00:00:00 1970 +0000
221 summary: utf-8 e' encoded: \xc3\xa9 (esc)
239 summary: utf-8 e' encoded: \xc3\xa9 (esc)
222
240
223 changeset: 2:650c6f3d55dd
241 changeset: 2:650c6f3d55dd
224 user: test
242 user: test
225 date: Thu Jan 01 00:00:00 1970 +0000
243 date: Thu Jan 01 00:00:00 1970 +0000
226 summary: latin-1 e' encoded: \xc3\xa9 (esc)
244 summary: latin-1 e' encoded: \xc3\xa9 (esc)
227
245
228 changeset: 1:0e5b7e3f9c4a
246 changeset: 1:0e5b7e3f9c4a
229 user: test
247 user: test
230 date: Mon Jan 12 13:46:40 1970 +0000
248 date: Mon Jan 12 13:46:40 1970 +0000
231 summary: koi8-r: \xd1\x80\xd1\x82\xd1\x83\xd1\x82\xd1\x8c = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
249 summary: koi8-r: \xd1\x80\xd1\x82\xd1\x83\xd1\x82\xd1\x8c = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
232
250
233 changeset: 0:1e78a93102a3
251 changeset: 0:1e78a93102a3
234 user: test
252 user: test
235 date: Mon Jan 12 13:46:40 1970 +0000
253 date: Mon Jan 12 13:46:40 1970 +0000
236 summary: latin-1 e': \xd0\x98 = u'\\xe9' (esc)
254 summary: latin-1 e': \xd0\x98 = u'\\xe9' (esc)
237
255
238
256
239 hg log (dolphin)
257 hg log (dolphin)
240
258
241 $ HGENCODING=dolphin hg log
259 $ HGENCODING=dolphin hg log
242 abort: unknown encoding: dolphin
260 abort: unknown encoding: dolphin
243 (please check your locale settings)
261 (please check your locale settings)
244 [255]
262 [255]
245 $ HGENCODING=ascii hg branch `cat latin-1-tag`
263 $ HGENCODING=ascii hg branch `cat latin-1-tag`
246 abort: decoding near '\xe9': 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)! (esc)
264 abort: decoding near '\xe9': 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)! (esc)
247 [255]
265 [255]
248 $ cp latin-1-tag .hg/branch
266 $ cp latin-1-tag .hg/branch
249 $ HGENCODING=latin-1 hg ci -m 'auto-promote legacy name'
267 $ HGENCODING=latin-1 hg ci -m 'auto-promote legacy name'
250
268
251 Test roundtrip encoding of lookup tables when not using UTF-8 (issue2763)
269 Test roundtrip encoding of lookup tables when not using UTF-8 (issue2763)
252
270
253 $ HGENCODING=latin-1 hg up `cat latin-1-tag`
271 $ HGENCODING=latin-1 hg up `cat latin-1-tag`
254 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
272 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
255
273
256 $ cd ..
274 $ cd ..
@@ -1,363 +1,399
1 $ hg init repo1
1 $ hg init repo1
2 $ cd repo1
2 $ cd repo1
3 $ mkdir a b a/1 b/1 b/2
3 $ mkdir a b a/1 b/1 b/2
4 $ touch in_root a/in_a b/in_b a/1/in_a_1 b/1/in_b_1 b/2/in_b_2
4 $ touch in_root a/in_a b/in_b a/1/in_a_1 b/1/in_b_1 b/2/in_b_2
5
5
6 hg status in repo root:
6 hg status in repo root:
7
7
8 $ hg status
8 $ hg status
9 ? a/1/in_a_1
9 ? a/1/in_a_1
10 ? a/in_a
10 ? a/in_a
11 ? b/1/in_b_1
11 ? b/1/in_b_1
12 ? b/2/in_b_2
12 ? b/2/in_b_2
13 ? b/in_b
13 ? b/in_b
14 ? in_root
14 ? in_root
15
15
16 hg status . in repo root:
16 hg status . in repo root:
17
17
18 $ hg status .
18 $ hg status .
19 ? a/1/in_a_1
19 ? a/1/in_a_1
20 ? a/in_a
20 ? a/in_a
21 ? b/1/in_b_1
21 ? b/1/in_b_1
22 ? b/2/in_b_2
22 ? b/2/in_b_2
23 ? b/in_b
23 ? b/in_b
24 ? in_root
24 ? in_root
25
25
26 $ hg status --cwd a
26 $ hg status --cwd a
27 ? a/1/in_a_1
27 ? a/1/in_a_1
28 ? a/in_a
28 ? a/in_a
29 ? b/1/in_b_1
29 ? b/1/in_b_1
30 ? b/2/in_b_2
30 ? b/2/in_b_2
31 ? b/in_b
31 ? b/in_b
32 ? in_root
32 ? in_root
33 $ hg status --cwd a .
33 $ hg status --cwd a .
34 ? 1/in_a_1
34 ? 1/in_a_1
35 ? in_a
35 ? in_a
36 $ hg status --cwd a ..
36 $ hg status --cwd a ..
37 ? 1/in_a_1
37 ? 1/in_a_1
38 ? in_a
38 ? in_a
39 ? ../b/1/in_b_1
39 ? ../b/1/in_b_1
40 ? ../b/2/in_b_2
40 ? ../b/2/in_b_2
41 ? ../b/in_b
41 ? ../b/in_b
42 ? ../in_root
42 ? ../in_root
43
43
44 $ hg status --cwd b
44 $ hg status --cwd b
45 ? a/1/in_a_1
45 ? a/1/in_a_1
46 ? a/in_a
46 ? a/in_a
47 ? b/1/in_b_1
47 ? b/1/in_b_1
48 ? b/2/in_b_2
48 ? b/2/in_b_2
49 ? b/in_b
49 ? b/in_b
50 ? in_root
50 ? in_root
51 $ hg status --cwd b .
51 $ hg status --cwd b .
52 ? 1/in_b_1
52 ? 1/in_b_1
53 ? 2/in_b_2
53 ? 2/in_b_2
54 ? in_b
54 ? in_b
55 $ hg status --cwd b ..
55 $ hg status --cwd b ..
56 ? ../a/1/in_a_1
56 ? ../a/1/in_a_1
57 ? ../a/in_a
57 ? ../a/in_a
58 ? 1/in_b_1
58 ? 1/in_b_1
59 ? 2/in_b_2
59 ? 2/in_b_2
60 ? in_b
60 ? in_b
61 ? ../in_root
61 ? ../in_root
62
62
63 $ hg status --cwd a/1
63 $ hg status --cwd a/1
64 ? a/1/in_a_1
64 ? a/1/in_a_1
65 ? a/in_a
65 ? a/in_a
66 ? b/1/in_b_1
66 ? b/1/in_b_1
67 ? b/2/in_b_2
67 ? b/2/in_b_2
68 ? b/in_b
68 ? b/in_b
69 ? in_root
69 ? in_root
70 $ hg status --cwd a/1 .
70 $ hg status --cwd a/1 .
71 ? in_a_1
71 ? in_a_1
72 $ hg status --cwd a/1 ..
72 $ hg status --cwd a/1 ..
73 ? in_a_1
73 ? in_a_1
74 ? ../in_a
74 ? ../in_a
75
75
76 $ hg status --cwd b/1
76 $ hg status --cwd b/1
77 ? a/1/in_a_1
77 ? a/1/in_a_1
78 ? a/in_a
78 ? a/in_a
79 ? b/1/in_b_1
79 ? b/1/in_b_1
80 ? b/2/in_b_2
80 ? b/2/in_b_2
81 ? b/in_b
81 ? b/in_b
82 ? in_root
82 ? in_root
83 $ hg status --cwd b/1 .
83 $ hg status --cwd b/1 .
84 ? in_b_1
84 ? in_b_1
85 $ hg status --cwd b/1 ..
85 $ hg status --cwd b/1 ..
86 ? in_b_1
86 ? in_b_1
87 ? ../2/in_b_2
87 ? ../2/in_b_2
88 ? ../in_b
88 ? ../in_b
89
89
90 $ hg status --cwd b/2
90 $ hg status --cwd b/2
91 ? a/1/in_a_1
91 ? a/1/in_a_1
92 ? a/in_a
92 ? a/in_a
93 ? b/1/in_b_1
93 ? b/1/in_b_1
94 ? b/2/in_b_2
94 ? b/2/in_b_2
95 ? b/in_b
95 ? b/in_b
96 ? in_root
96 ? in_root
97 $ hg status --cwd b/2 .
97 $ hg status --cwd b/2 .
98 ? in_b_2
98 ? in_b_2
99 $ hg status --cwd b/2 ..
99 $ hg status --cwd b/2 ..
100 ? ../1/in_b_1
100 ? ../1/in_b_1
101 ? in_b_2
101 ? in_b_2
102 ? ../in_b
102 ? ../in_b
103
103
104 combining patterns with root and patterns without a root works
104 combining patterns with root and patterns without a root works
105
105
106 $ hg st a/in_a re:.*b$
106 $ hg st a/in_a re:.*b$
107 ? a/in_a
107 ? a/in_a
108 ? b/in_b
108 ? b/in_b
109
109
110 $ cd ..
110 $ cd ..
111
111
112 $ hg init repo2
112 $ hg init repo2
113 $ cd repo2
113 $ cd repo2
114 $ touch modified removed deleted ignored
114 $ touch modified removed deleted ignored
115 $ echo "^ignored$" > .hgignore
115 $ echo "^ignored$" > .hgignore
116 $ hg ci -A -m 'initial checkin'
116 $ hg ci -A -m 'initial checkin'
117 adding .hgignore
117 adding .hgignore
118 adding deleted
118 adding deleted
119 adding modified
119 adding modified
120 adding removed
120 adding removed
121 $ touch modified added unknown ignored
121 $ touch modified added unknown ignored
122 $ hg add added
122 $ hg add added
123 $ hg remove removed
123 $ hg remove removed
124 $ rm deleted
124 $ rm deleted
125
125
126 hg status:
126 hg status:
127
127
128 $ hg status
128 $ hg status
129 A added
129 A added
130 R removed
130 R removed
131 ! deleted
131 ! deleted
132 ? unknown
132 ? unknown
133
133
134 hg status modified added removed deleted unknown never-existed ignored:
134 hg status modified added removed deleted unknown never-existed ignored:
135
135
136 $ hg status modified added removed deleted unknown never-existed ignored
136 $ hg status modified added removed deleted unknown never-existed ignored
137 never-existed: * (glob)
137 never-existed: * (glob)
138 A added
138 A added
139 R removed
139 R removed
140 ! deleted
140 ! deleted
141 ? unknown
141 ? unknown
142
142
143 $ hg copy modified copied
143 $ hg copy modified copied
144
144
145 hg status -C:
145 hg status -C:
146
146
147 $ hg status -C
147 $ hg status -C
148 A added
148 A added
149 A copied
149 A copied
150 modified
150 modified
151 R removed
151 R removed
152 ! deleted
152 ! deleted
153 ? unknown
153 ? unknown
154
154
155 hg status -A:
155 hg status -A:
156
156
157 $ hg status -A
157 $ hg status -A
158 A added
158 A added
159 A copied
159 A copied
160 modified
160 modified
161 R removed
161 R removed
162 ! deleted
162 ! deleted
163 ? unknown
163 ? unknown
164 I ignored
164 I ignored
165 C .hgignore
165 C .hgignore
166 C modified
166 C modified
167
167
168 $ hg status -A -Tjson
169 [
170 {
171 "path": "added",
172 "status": "A"
173 },
174 {
175 "copy": "modified",
176 "path": "copied",
177 "status": "A"
178 },
179 {
180 "path": "removed",
181 "status": "R"
182 },
183 {
184 "path": "deleted",
185 "status": "!"
186 },
187 {
188 "path": "unknown",
189 "status": "?"
190 },
191 {
192 "path": "ignored",
193 "status": "I"
194 },
195 {
196 "path": ".hgignore",
197 "status": "C"
198 },
199 {
200 "path": "modified",
201 "status": "C"
202 }
203 ]
168
204
169 $ echo "^ignoreddir$" > .hgignore
205 $ echo "^ignoreddir$" > .hgignore
170 $ mkdir ignoreddir
206 $ mkdir ignoreddir
171 $ touch ignoreddir/file
207 $ touch ignoreddir/file
172
208
173 hg status ignoreddir/file:
209 hg status ignoreddir/file:
174
210
175 $ hg status ignoreddir/file
211 $ hg status ignoreddir/file
176
212
177 hg status -i ignoreddir/file:
213 hg status -i ignoreddir/file:
178
214
179 $ hg status -i ignoreddir/file
215 $ hg status -i ignoreddir/file
180 I ignoreddir/file
216 I ignoreddir/file
181 $ cd ..
217 $ cd ..
182
218
183 Check 'status -q' and some combinations
219 Check 'status -q' and some combinations
184
220
185 $ hg init repo3
221 $ hg init repo3
186 $ cd repo3
222 $ cd repo3
187 $ touch modified removed deleted ignored
223 $ touch modified removed deleted ignored
188 $ echo "^ignored$" > .hgignore
224 $ echo "^ignored$" > .hgignore
189 $ hg commit -A -m 'initial checkin'
225 $ hg commit -A -m 'initial checkin'
190 adding .hgignore
226 adding .hgignore
191 adding deleted
227 adding deleted
192 adding modified
228 adding modified
193 adding removed
229 adding removed
194 $ touch added unknown ignored
230 $ touch added unknown ignored
195 $ hg add added
231 $ hg add added
196 $ echo "test" >> modified
232 $ echo "test" >> modified
197 $ hg remove removed
233 $ hg remove removed
198 $ rm deleted
234 $ rm deleted
199 $ hg copy modified copied
235 $ hg copy modified copied
200
236
201 Run status with 2 different flags.
237 Run status with 2 different flags.
202 Check if result is the same or different.
238 Check if result is the same or different.
203 If result is not as expected, raise error
239 If result is not as expected, raise error
204
240
205 $ assert() {
241 $ assert() {
206 > hg status $1 > ../a
242 > hg status $1 > ../a
207 > hg status $2 > ../b
243 > hg status $2 > ../b
208 > if diff ../a ../b > /dev/null; then
244 > if diff ../a ../b > /dev/null; then
209 > out=0
245 > out=0
210 > else
246 > else
211 > out=1
247 > out=1
212 > fi
248 > fi
213 > if [ $3 -eq 0 ]; then
249 > if [ $3 -eq 0 ]; then
214 > df="same"
250 > df="same"
215 > else
251 > else
216 > df="different"
252 > df="different"
217 > fi
253 > fi
218 > if [ $out -ne $3 ]; then
254 > if [ $out -ne $3 ]; then
219 > echo "Error on $1 and $2, should be $df."
255 > echo "Error on $1 and $2, should be $df."
220 > fi
256 > fi
221 > }
257 > }
222
258
223 Assert flag1 flag2 [0-same | 1-different]
259 Assert flag1 flag2 [0-same | 1-different]
224
260
225 $ assert "-q" "-mard" 0
261 $ assert "-q" "-mard" 0
226 $ assert "-A" "-marduicC" 0
262 $ assert "-A" "-marduicC" 0
227 $ assert "-qA" "-mardcC" 0
263 $ assert "-qA" "-mardcC" 0
228 $ assert "-qAui" "-A" 0
264 $ assert "-qAui" "-A" 0
229 $ assert "-qAu" "-marducC" 0
265 $ assert "-qAu" "-marducC" 0
230 $ assert "-qAi" "-mardicC" 0
266 $ assert "-qAi" "-mardicC" 0
231 $ assert "-qu" "-u" 0
267 $ assert "-qu" "-u" 0
232 $ assert "-q" "-u" 1
268 $ assert "-q" "-u" 1
233 $ assert "-m" "-a" 1
269 $ assert "-m" "-a" 1
234 $ assert "-r" "-d" 1
270 $ assert "-r" "-d" 1
235 $ cd ..
271 $ cd ..
236
272
237 $ hg init repo4
273 $ hg init repo4
238 $ cd repo4
274 $ cd repo4
239 $ touch modified removed deleted
275 $ touch modified removed deleted
240 $ hg ci -q -A -m 'initial checkin'
276 $ hg ci -q -A -m 'initial checkin'
241 $ touch added unknown
277 $ touch added unknown
242 $ hg add added
278 $ hg add added
243 $ hg remove removed
279 $ hg remove removed
244 $ rm deleted
280 $ rm deleted
245 $ echo x > modified
281 $ echo x > modified
246 $ hg copy modified copied
282 $ hg copy modified copied
247 $ hg ci -m 'test checkin' -d "1000001 0"
283 $ hg ci -m 'test checkin' -d "1000001 0"
248 $ rm *
284 $ rm *
249 $ touch unrelated
285 $ touch unrelated
250 $ hg ci -q -A -m 'unrelated checkin' -d "1000002 0"
286 $ hg ci -q -A -m 'unrelated checkin' -d "1000002 0"
251
287
252 hg status --change 1:
288 hg status --change 1:
253
289
254 $ hg status --change 1
290 $ hg status --change 1
255 M modified
291 M modified
256 A added
292 A added
257 A copied
293 A copied
258 R removed
294 R removed
259
295
260 hg status --change 1 unrelated:
296 hg status --change 1 unrelated:
261
297
262 $ hg status --change 1 unrelated
298 $ hg status --change 1 unrelated
263
299
264 hg status -C --change 1 added modified copied removed deleted:
300 hg status -C --change 1 added modified copied removed deleted:
265
301
266 $ hg status -C --change 1 added modified copied removed deleted
302 $ hg status -C --change 1 added modified copied removed deleted
267 M modified
303 M modified
268 A added
304 A added
269 A copied
305 A copied
270 modified
306 modified
271 R removed
307 R removed
272
308
273 hg status -A --change 1 and revset:
309 hg status -A --change 1 and revset:
274
310
275 $ hg status -A --change '1|1'
311 $ hg status -A --change '1|1'
276 M modified
312 M modified
277 A added
313 A added
278 A copied
314 A copied
279 modified
315 modified
280 R removed
316 R removed
281 C deleted
317 C deleted
282
318
283 status against non-parent with unknown file (issue4321)
319 status against non-parent with unknown file (issue4321)
284
320
285 $ touch unknown
321 $ touch unknown
286 $ hg status --rev 0 unknown
322 $ hg status --rev 0 unknown
287 ? unknown
323 ? unknown
288
324
289 status of removed but existing in working directory. "? removed" should
325 status of removed but existing in working directory. "? removed" should
290 not be included:
326 not be included:
291
327
292 $ touch removed
328 $ touch removed
293 $ hg status --rev 0 removed
329 $ hg status --rev 0 removed
294 R removed
330 R removed
295
331
296 $ cd ..
332 $ cd ..
297
333
298 hg status of binary file starting with '\1\n', a separator for metadata:
334 hg status of binary file starting with '\1\n', a separator for metadata:
299
335
300 $ hg init repo5
336 $ hg init repo5
301 $ cd repo5
337 $ cd repo5
302 >>> open("010a", "wb").write("\1\nfoo")
338 >>> open("010a", "wb").write("\1\nfoo")
303 $ hg ci -q -A -m 'initial checkin'
339 $ hg ci -q -A -m 'initial checkin'
304 $ hg status -A
340 $ hg status -A
305 C 010a
341 C 010a
306
342
307 >>> open("010a", "wb").write("\1\nbar")
343 >>> open("010a", "wb").write("\1\nbar")
308 $ hg status -A
344 $ hg status -A
309 M 010a
345 M 010a
310 $ hg ci -q -m 'modify 010a'
346 $ hg ci -q -m 'modify 010a'
311 $ hg status -A --rev 0:1
347 $ hg status -A --rev 0:1
312 M 010a
348 M 010a
313
349
314 $ touch empty
350 $ touch empty
315 $ hg ci -q -A -m 'add another file'
351 $ hg ci -q -A -m 'add another file'
316 $ hg status -A --rev 1:2 010a
352 $ hg status -A --rev 1:2 010a
317 C 010a
353 C 010a
318
354
319 $ cd ..
355 $ cd ..
320
356
321 test "hg status" with "directory pattern" which matches against files
357 test "hg status" with "directory pattern" which matches against files
322 only known on target revision.
358 only known on target revision.
323
359
324 $ hg init repo6
360 $ hg init repo6
325 $ cd repo6
361 $ cd repo6
326
362
327 $ echo a > a.txt
363 $ echo a > a.txt
328 $ hg add a.txt
364 $ hg add a.txt
329 $ hg commit -m '#0'
365 $ hg commit -m '#0'
330 $ mkdir -p 1/2/3/4/5
366 $ mkdir -p 1/2/3/4/5
331 $ echo b > 1/2/3/4/5/b.txt
367 $ echo b > 1/2/3/4/5/b.txt
332 $ hg add 1/2/3/4/5/b.txt
368 $ hg add 1/2/3/4/5/b.txt
333 $ hg commit -m '#1'
369 $ hg commit -m '#1'
334
370
335 $ hg update -C 0 > /dev/null
371 $ hg update -C 0 > /dev/null
336 $ hg status -A
372 $ hg status -A
337 C a.txt
373 C a.txt
338
374
339 the directory matching against specified pattern should be removed,
375 the directory matching against specified pattern should be removed,
340 because directory existence prevents 'dirstate.walk()' from showing
376 because directory existence prevents 'dirstate.walk()' from showing
341 warning message about such pattern.
377 warning message about such pattern.
342
378
343 $ test ! -d 1
379 $ test ! -d 1
344 $ hg status -A --rev 1 1/2/3/4/5/b.txt
380 $ hg status -A --rev 1 1/2/3/4/5/b.txt
345 R 1/2/3/4/5/b.txt
381 R 1/2/3/4/5/b.txt
346 $ hg status -A --rev 1 1/2/3/4/5
382 $ hg status -A --rev 1 1/2/3/4/5
347 R 1/2/3/4/5/b.txt
383 R 1/2/3/4/5/b.txt
348 $ hg status -A --rev 1 1/2/3
384 $ hg status -A --rev 1 1/2/3
349 R 1/2/3/4/5/b.txt
385 R 1/2/3/4/5/b.txt
350 $ hg status -A --rev 1 1
386 $ hg status -A --rev 1 1
351 R 1/2/3/4/5/b.txt
387 R 1/2/3/4/5/b.txt
352
388
353 $ hg status --config ui.formatdebug=True --rev 1 1
389 $ hg status --config ui.formatdebug=True --rev 1 1
354 status = [
390 status = [
355 {*'path': '1/2/3/4/5/b.txt'*}, (glob)
391 {*'path': '1/2/3/4/5/b.txt'*}, (glob)
356 ]
392 ]
357
393
358 #if windows
394 #if windows
359 $ hg --config ui.slash=false status -A --rev 1 1
395 $ hg --config ui.slash=false status -A --rev 1 1
360 R 1\2\3\4\5\b.txt
396 R 1\2\3\4\5\b.txt
361 #endif
397 #endif
362
398
363 $ cd ..
399 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now