##// END OF EJS Templates
branches: simplify with repo.branchmap().iterbranches()...
Brodie Rao -
r20192:38fad5e7 default
parent child Browse files
Show More
@@ -1,5911 +1,5903 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno
11 import os, re, difflib, time, tempfile, errno
12 import hg, scmutil, util, revlog, copies, error, bookmarks
12 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import patch, help, encoding, templatekw, discovery
13 import patch, help, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, hbisect
14 import archival, changegroup, cmdutil, hbisect
15 import sshserver, hgweb, commandserver
15 import sshserver, hgweb, commandserver
16 from hgweb import server as hgweb_server
16 from hgweb import server as hgweb_server
17 import merge as mergemod
17 import merge as mergemod
18 import minirst, revset, fileset
18 import minirst, revset, fileset
19 import dagparser, context, simplemerge, graphmod
19 import dagparser, context, simplemerge, graphmod
20 import random
20 import random
21 import setdiscovery, treediscovery, dagutil, pvec, localrepo
21 import setdiscovery, treediscovery, dagutil, pvec, localrepo
22 import phases, obsolete
22 import phases, obsolete
23
23
24 table = {}
24 table = {}
25
25
26 command = cmdutil.command(table)
26 command = cmdutil.command(table)
27
27
28 # common command options
28 # common command options
29
29
30 globalopts = [
30 globalopts = [
31 ('R', 'repository', '',
31 ('R', 'repository', '',
32 _('repository root directory or name of overlay bundle file'),
32 _('repository root directory or name of overlay bundle file'),
33 _('REPO')),
33 _('REPO')),
34 ('', 'cwd', '',
34 ('', 'cwd', '',
35 _('change working directory'), _('DIR')),
35 _('change working directory'), _('DIR')),
36 ('y', 'noninteractive', None,
36 ('y', 'noninteractive', None,
37 _('do not prompt, automatically pick the first choice for all prompts')),
37 _('do not prompt, automatically pick the first choice for all prompts')),
38 ('q', 'quiet', None, _('suppress output')),
38 ('q', 'quiet', None, _('suppress output')),
39 ('v', 'verbose', None, _('enable additional output')),
39 ('v', 'verbose', None, _('enable additional output')),
40 ('', 'config', [],
40 ('', 'config', [],
41 _('set/override config option (use \'section.name=value\')'),
41 _('set/override config option (use \'section.name=value\')'),
42 _('CONFIG')),
42 _('CONFIG')),
43 ('', 'debug', None, _('enable debugging output')),
43 ('', 'debug', None, _('enable debugging output')),
44 ('', 'debugger', None, _('start debugger')),
44 ('', 'debugger', None, _('start debugger')),
45 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
45 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
46 _('ENCODE')),
46 _('ENCODE')),
47 ('', 'encodingmode', encoding.encodingmode,
47 ('', 'encodingmode', encoding.encodingmode,
48 _('set the charset encoding mode'), _('MODE')),
48 _('set the charset encoding mode'), _('MODE')),
49 ('', 'traceback', None, _('always print a traceback on exception')),
49 ('', 'traceback', None, _('always print a traceback on exception')),
50 ('', 'time', None, _('time how long the command takes')),
50 ('', 'time', None, _('time how long the command takes')),
51 ('', 'profile', None, _('print command execution profile')),
51 ('', 'profile', None, _('print command execution profile')),
52 ('', 'version', None, _('output version information and exit')),
52 ('', 'version', None, _('output version information and exit')),
53 ('h', 'help', None, _('display help and exit')),
53 ('h', 'help', None, _('display help and exit')),
54 ('', 'hidden', False, _('consider hidden changesets')),
54 ('', 'hidden', False, _('consider hidden changesets')),
55 ]
55 ]
56
56
57 dryrunopts = [('n', 'dry-run', None,
57 dryrunopts = [('n', 'dry-run', None,
58 _('do not perform actions, just print output'))]
58 _('do not perform actions, just print output'))]
59
59
60 remoteopts = [
60 remoteopts = [
61 ('e', 'ssh', '',
61 ('e', 'ssh', '',
62 _('specify ssh command to use'), _('CMD')),
62 _('specify ssh command to use'), _('CMD')),
63 ('', 'remotecmd', '',
63 ('', 'remotecmd', '',
64 _('specify hg command to run on the remote side'), _('CMD')),
64 _('specify hg command to run on the remote side'), _('CMD')),
65 ('', 'insecure', None,
65 ('', 'insecure', None,
66 _('do not verify server certificate (ignoring web.cacerts config)')),
66 _('do not verify server certificate (ignoring web.cacerts config)')),
67 ]
67 ]
68
68
69 walkopts = [
69 walkopts = [
70 ('I', 'include', [],
70 ('I', 'include', [],
71 _('include names matching the given patterns'), _('PATTERN')),
71 _('include names matching the given patterns'), _('PATTERN')),
72 ('X', 'exclude', [],
72 ('X', 'exclude', [],
73 _('exclude names matching the given patterns'), _('PATTERN')),
73 _('exclude names matching the given patterns'), _('PATTERN')),
74 ]
74 ]
75
75
76 commitopts = [
76 commitopts = [
77 ('m', 'message', '',
77 ('m', 'message', '',
78 _('use text as commit message'), _('TEXT')),
78 _('use text as commit message'), _('TEXT')),
79 ('l', 'logfile', '',
79 ('l', 'logfile', '',
80 _('read commit message from file'), _('FILE')),
80 _('read commit message from file'), _('FILE')),
81 ]
81 ]
82
82
83 commitopts2 = [
83 commitopts2 = [
84 ('d', 'date', '',
84 ('d', 'date', '',
85 _('record the specified date as commit date'), _('DATE')),
85 _('record the specified date as commit date'), _('DATE')),
86 ('u', 'user', '',
86 ('u', 'user', '',
87 _('record the specified user as committer'), _('USER')),
87 _('record the specified user as committer'), _('USER')),
88 ]
88 ]
89
89
90 templateopts = [
90 templateopts = [
91 ('', 'style', '',
91 ('', 'style', '',
92 _('display using template map file'), _('STYLE')),
92 _('display using template map file'), _('STYLE')),
93 ('', 'template', '',
93 ('', 'template', '',
94 _('display with template'), _('TEMPLATE')),
94 _('display with template'), _('TEMPLATE')),
95 ]
95 ]
96
96
97 logopts = [
97 logopts = [
98 ('p', 'patch', None, _('show patch')),
98 ('p', 'patch', None, _('show patch')),
99 ('g', 'git', None, _('use git extended diff format')),
99 ('g', 'git', None, _('use git extended diff format')),
100 ('l', 'limit', '',
100 ('l', 'limit', '',
101 _('limit number of changes displayed'), _('NUM')),
101 _('limit number of changes displayed'), _('NUM')),
102 ('M', 'no-merges', None, _('do not show merges')),
102 ('M', 'no-merges', None, _('do not show merges')),
103 ('', 'stat', None, _('output diffstat-style summary of changes')),
103 ('', 'stat', None, _('output diffstat-style summary of changes')),
104 ('G', 'graph', None, _("show the revision DAG")),
104 ('G', 'graph', None, _("show the revision DAG")),
105 ] + templateopts
105 ] + templateopts
106
106
107 diffopts = [
107 diffopts = [
108 ('a', 'text', None, _('treat all files as text')),
108 ('a', 'text', None, _('treat all files as text')),
109 ('g', 'git', None, _('use git extended diff format')),
109 ('g', 'git', None, _('use git extended diff format')),
110 ('', 'nodates', None, _('omit dates from diff headers'))
110 ('', 'nodates', None, _('omit dates from diff headers'))
111 ]
111 ]
112
112
113 diffwsopts = [
113 diffwsopts = [
114 ('w', 'ignore-all-space', None,
114 ('w', 'ignore-all-space', None,
115 _('ignore white space when comparing lines')),
115 _('ignore white space when comparing lines')),
116 ('b', 'ignore-space-change', None,
116 ('b', 'ignore-space-change', None,
117 _('ignore changes in the amount of white space')),
117 _('ignore changes in the amount of white space')),
118 ('B', 'ignore-blank-lines', None,
118 ('B', 'ignore-blank-lines', None,
119 _('ignore changes whose lines are all blank')),
119 _('ignore changes whose lines are all blank')),
120 ]
120 ]
121
121
122 diffopts2 = [
122 diffopts2 = [
123 ('p', 'show-function', None, _('show which function each change is in')),
123 ('p', 'show-function', None, _('show which function each change is in')),
124 ('', 'reverse', None, _('produce a diff that undoes the changes')),
124 ('', 'reverse', None, _('produce a diff that undoes the changes')),
125 ] + diffwsopts + [
125 ] + diffwsopts + [
126 ('U', 'unified', '',
126 ('U', 'unified', '',
127 _('number of lines of context to show'), _('NUM')),
127 _('number of lines of context to show'), _('NUM')),
128 ('', 'stat', None, _('output diffstat-style summary of changes')),
128 ('', 'stat', None, _('output diffstat-style summary of changes')),
129 ]
129 ]
130
130
131 mergetoolopts = [
131 mergetoolopts = [
132 ('t', 'tool', '', _('specify merge tool')),
132 ('t', 'tool', '', _('specify merge tool')),
133 ]
133 ]
134
134
135 similarityopts = [
135 similarityopts = [
136 ('s', 'similarity', '',
136 ('s', 'similarity', '',
137 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
137 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
138 ]
138 ]
139
139
140 subrepoopts = [
140 subrepoopts = [
141 ('S', 'subrepos', None,
141 ('S', 'subrepos', None,
142 _('recurse into subrepositories'))
142 _('recurse into subrepositories'))
143 ]
143 ]
144
144
145 # Commands start here, listed alphabetically
145 # Commands start here, listed alphabetically
146
146
147 @command('^add',
147 @command('^add',
148 walkopts + subrepoopts + dryrunopts,
148 walkopts + subrepoopts + dryrunopts,
149 _('[OPTION]... [FILE]...'))
149 _('[OPTION]... [FILE]...'))
150 def add(ui, repo, *pats, **opts):
150 def add(ui, repo, *pats, **opts):
151 """add the specified files on the next commit
151 """add the specified files on the next commit
152
152
153 Schedule files to be version controlled and added to the
153 Schedule files to be version controlled and added to the
154 repository.
154 repository.
155
155
156 The files will be added to the repository at the next commit. To
156 The files will be added to the repository at the next commit. To
157 undo an add before that, see :hg:`forget`.
157 undo an add before that, see :hg:`forget`.
158
158
159 If no names are given, add all files to the repository.
159 If no names are given, add all files to the repository.
160
160
161 .. container:: verbose
161 .. container:: verbose
162
162
163 An example showing how new (unknown) files are added
163 An example showing how new (unknown) files are added
164 automatically by :hg:`add`::
164 automatically by :hg:`add`::
165
165
166 $ ls
166 $ ls
167 foo.c
167 foo.c
168 $ hg status
168 $ hg status
169 ? foo.c
169 ? foo.c
170 $ hg add
170 $ hg add
171 adding foo.c
171 adding foo.c
172 $ hg status
172 $ hg status
173 A foo.c
173 A foo.c
174
174
175 Returns 0 if all files are successfully added.
175 Returns 0 if all files are successfully added.
176 """
176 """
177
177
178 m = scmutil.match(repo[None], pats, opts)
178 m = scmutil.match(repo[None], pats, opts)
179 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
179 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
180 opts.get('subrepos'), prefix="", explicitonly=False)
180 opts.get('subrepos'), prefix="", explicitonly=False)
181 return rejected and 1 or 0
181 return rejected and 1 or 0
182
182
183 @command('addremove',
183 @command('addremove',
184 similarityopts + walkopts + dryrunopts,
184 similarityopts + walkopts + dryrunopts,
185 _('[OPTION]... [FILE]...'))
185 _('[OPTION]... [FILE]...'))
186 def addremove(ui, repo, *pats, **opts):
186 def addremove(ui, repo, *pats, **opts):
187 """add all new files, delete all missing files
187 """add all new files, delete all missing files
188
188
189 Add all new files and remove all missing files from the
189 Add all new files and remove all missing files from the
190 repository.
190 repository.
191
191
192 New files are ignored if they match any of the patterns in
192 New files are ignored if they match any of the patterns in
193 ``.hgignore``. As with add, these changes take effect at the next
193 ``.hgignore``. As with add, these changes take effect at the next
194 commit.
194 commit.
195
195
196 Use the -s/--similarity option to detect renamed files. This
196 Use the -s/--similarity option to detect renamed files. This
197 option takes a percentage between 0 (disabled) and 100 (files must
197 option takes a percentage between 0 (disabled) and 100 (files must
198 be identical) as its parameter. With a parameter greater than 0,
198 be identical) as its parameter. With a parameter greater than 0,
199 this compares every removed file with every added file and records
199 this compares every removed file with every added file and records
200 those similar enough as renames. Detecting renamed files this way
200 those similar enough as renames. Detecting renamed files this way
201 can be expensive. After using this option, :hg:`status -C` can be
201 can be expensive. After using this option, :hg:`status -C` can be
202 used to check which files were identified as moved or renamed. If
202 used to check which files were identified as moved or renamed. If
203 not specified, -s/--similarity defaults to 100 and only renames of
203 not specified, -s/--similarity defaults to 100 and only renames of
204 identical files are detected.
204 identical files are detected.
205
205
206 Returns 0 if all files are successfully added.
206 Returns 0 if all files are successfully added.
207 """
207 """
208 try:
208 try:
209 sim = float(opts.get('similarity') or 100)
209 sim = float(opts.get('similarity') or 100)
210 except ValueError:
210 except ValueError:
211 raise util.Abort(_('similarity must be a number'))
211 raise util.Abort(_('similarity must be a number'))
212 if sim < 0 or sim > 100:
212 if sim < 0 or sim > 100:
213 raise util.Abort(_('similarity must be between 0 and 100'))
213 raise util.Abort(_('similarity must be between 0 and 100'))
214 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
214 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
215
215
216 @command('^annotate|blame',
216 @command('^annotate|blame',
217 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
217 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
218 ('', 'follow', None,
218 ('', 'follow', None,
219 _('follow copies/renames and list the filename (DEPRECATED)')),
219 _('follow copies/renames and list the filename (DEPRECATED)')),
220 ('', 'no-follow', None, _("don't follow copies and renames")),
220 ('', 'no-follow', None, _("don't follow copies and renames")),
221 ('a', 'text', None, _('treat all files as text')),
221 ('a', 'text', None, _('treat all files as text')),
222 ('u', 'user', None, _('list the author (long with -v)')),
222 ('u', 'user', None, _('list the author (long with -v)')),
223 ('f', 'file', None, _('list the filename')),
223 ('f', 'file', None, _('list the filename')),
224 ('d', 'date', None, _('list the date (short with -q)')),
224 ('d', 'date', None, _('list the date (short with -q)')),
225 ('n', 'number', None, _('list the revision number (default)')),
225 ('n', 'number', None, _('list the revision number (default)')),
226 ('c', 'changeset', None, _('list the changeset')),
226 ('c', 'changeset', None, _('list the changeset')),
227 ('l', 'line-number', None, _('show line number at the first appearance'))
227 ('l', 'line-number', None, _('show line number at the first appearance'))
228 ] + diffwsopts + walkopts,
228 ] + diffwsopts + walkopts,
229 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
229 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'))
230 def annotate(ui, repo, *pats, **opts):
230 def annotate(ui, repo, *pats, **opts):
231 """show changeset information by line for each file
231 """show changeset information by line for each file
232
232
233 List changes in files, showing the revision id responsible for
233 List changes in files, showing the revision id responsible for
234 each line
234 each line
235
235
236 This command is useful for discovering when a change was made and
236 This command is useful for discovering when a change was made and
237 by whom.
237 by whom.
238
238
239 Without the -a/--text option, annotate will avoid processing files
239 Without the -a/--text option, annotate will avoid processing files
240 it detects as binary. With -a, annotate will annotate the file
240 it detects as binary. With -a, annotate will annotate the file
241 anyway, although the results will probably be neither useful
241 anyway, although the results will probably be neither useful
242 nor desirable.
242 nor desirable.
243
243
244 Returns 0 on success.
244 Returns 0 on success.
245 """
245 """
246 if opts.get('follow'):
246 if opts.get('follow'):
247 # --follow is deprecated and now just an alias for -f/--file
247 # --follow is deprecated and now just an alias for -f/--file
248 # to mimic the behavior of Mercurial before version 1.5
248 # to mimic the behavior of Mercurial before version 1.5
249 opts['file'] = True
249 opts['file'] = True
250
250
251 datefunc = ui.quiet and util.shortdate or util.datestr
251 datefunc = ui.quiet and util.shortdate or util.datestr
252 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
252 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
253
253
254 if not pats:
254 if not pats:
255 raise util.Abort(_('at least one filename or pattern is required'))
255 raise util.Abort(_('at least one filename or pattern is required'))
256
256
257 hexfn = ui.debugflag and hex or short
257 hexfn = ui.debugflag and hex or short
258
258
259 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
259 opmap = [('user', ' ', lambda x: ui.shortuser(x[0].user())),
260 ('number', ' ', lambda x: str(x[0].rev())),
260 ('number', ' ', lambda x: str(x[0].rev())),
261 ('changeset', ' ', lambda x: hexfn(x[0].node())),
261 ('changeset', ' ', lambda x: hexfn(x[0].node())),
262 ('date', ' ', getdate),
262 ('date', ' ', getdate),
263 ('file', ' ', lambda x: x[0].path()),
263 ('file', ' ', lambda x: x[0].path()),
264 ('line_number', ':', lambda x: str(x[1])),
264 ('line_number', ':', lambda x: str(x[1])),
265 ]
265 ]
266
266
267 if (not opts.get('user') and not opts.get('changeset')
267 if (not opts.get('user') and not opts.get('changeset')
268 and not opts.get('date') and not opts.get('file')):
268 and not opts.get('date') and not opts.get('file')):
269 opts['number'] = True
269 opts['number'] = True
270
270
271 linenumber = opts.get('line_number') is not None
271 linenumber = opts.get('line_number') is not None
272 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
272 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
273 raise util.Abort(_('at least one of -n/-c is required for -l'))
273 raise util.Abort(_('at least one of -n/-c is required for -l'))
274
274
275 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
275 funcmap = [(func, sep) for op, sep, func in opmap if opts.get(op)]
276 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
276 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
277
277
278 def bad(x, y):
278 def bad(x, y):
279 raise util.Abort("%s: %s" % (x, y))
279 raise util.Abort("%s: %s" % (x, y))
280
280
281 ctx = scmutil.revsingle(repo, opts.get('rev'))
281 ctx = scmutil.revsingle(repo, opts.get('rev'))
282 m = scmutil.match(ctx, pats, opts)
282 m = scmutil.match(ctx, pats, opts)
283 m.bad = bad
283 m.bad = bad
284 follow = not opts.get('no_follow')
284 follow = not opts.get('no_follow')
285 diffopts = patch.diffopts(ui, opts, section='annotate')
285 diffopts = patch.diffopts(ui, opts, section='annotate')
286 for abs in ctx.walk(m):
286 for abs in ctx.walk(m):
287 fctx = ctx[abs]
287 fctx = ctx[abs]
288 if not opts.get('text') and util.binary(fctx.data()):
288 if not opts.get('text') and util.binary(fctx.data()):
289 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
289 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
290 continue
290 continue
291
291
292 lines = fctx.annotate(follow=follow, linenumber=linenumber,
292 lines = fctx.annotate(follow=follow, linenumber=linenumber,
293 diffopts=diffopts)
293 diffopts=diffopts)
294 pieces = []
294 pieces = []
295
295
296 for f, sep in funcmap:
296 for f, sep in funcmap:
297 l = [f(n) for n, dummy in lines]
297 l = [f(n) for n, dummy in lines]
298 if l:
298 if l:
299 sized = [(x, encoding.colwidth(x)) for x in l]
299 sized = [(x, encoding.colwidth(x)) for x in l]
300 ml = max([w for x, w in sized])
300 ml = max([w for x, w in sized])
301 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
301 pieces.append(["%s%s%s" % (sep, ' ' * (ml - w), x)
302 for x, w in sized])
302 for x, w in sized])
303
303
304 if pieces:
304 if pieces:
305 for p, l in zip(zip(*pieces), lines):
305 for p, l in zip(zip(*pieces), lines):
306 ui.write("%s: %s" % ("".join(p), l[1]))
306 ui.write("%s: %s" % ("".join(p), l[1]))
307
307
308 if lines and not lines[-1][1].endswith('\n'):
308 if lines and not lines[-1][1].endswith('\n'):
309 ui.write('\n')
309 ui.write('\n')
310
310
311 @command('archive',
311 @command('archive',
312 [('', 'no-decode', None, _('do not pass files through decoders')),
312 [('', 'no-decode', None, _('do not pass files through decoders')),
313 ('p', 'prefix', '', _('directory prefix for files in archive'),
313 ('p', 'prefix', '', _('directory prefix for files in archive'),
314 _('PREFIX')),
314 _('PREFIX')),
315 ('r', 'rev', '', _('revision to distribute'), _('REV')),
315 ('r', 'rev', '', _('revision to distribute'), _('REV')),
316 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
316 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
317 ] + subrepoopts + walkopts,
317 ] + subrepoopts + walkopts,
318 _('[OPTION]... DEST'))
318 _('[OPTION]... DEST'))
319 def archive(ui, repo, dest, **opts):
319 def archive(ui, repo, dest, **opts):
320 '''create an unversioned archive of a repository revision
320 '''create an unversioned archive of a repository revision
321
321
322 By default, the revision used is the parent of the working
322 By default, the revision used is the parent of the working
323 directory; use -r/--rev to specify a different revision.
323 directory; use -r/--rev to specify a different revision.
324
324
325 The archive type is automatically detected based on file
325 The archive type is automatically detected based on file
326 extension (or override using -t/--type).
326 extension (or override using -t/--type).
327
327
328 .. container:: verbose
328 .. container:: verbose
329
329
330 Examples:
330 Examples:
331
331
332 - create a zip file containing the 1.0 release::
332 - create a zip file containing the 1.0 release::
333
333
334 hg archive -r 1.0 project-1.0.zip
334 hg archive -r 1.0 project-1.0.zip
335
335
336 - create a tarball excluding .hg files::
336 - create a tarball excluding .hg files::
337
337
338 hg archive project.tar.gz -X ".hg*"
338 hg archive project.tar.gz -X ".hg*"
339
339
340 Valid types are:
340 Valid types are:
341
341
342 :``files``: a directory full of files (default)
342 :``files``: a directory full of files (default)
343 :``tar``: tar archive, uncompressed
343 :``tar``: tar archive, uncompressed
344 :``tbz2``: tar archive, compressed using bzip2
344 :``tbz2``: tar archive, compressed using bzip2
345 :``tgz``: tar archive, compressed using gzip
345 :``tgz``: tar archive, compressed using gzip
346 :``uzip``: zip archive, uncompressed
346 :``uzip``: zip archive, uncompressed
347 :``zip``: zip archive, compressed using deflate
347 :``zip``: zip archive, compressed using deflate
348
348
349 The exact name of the destination archive or directory is given
349 The exact name of the destination archive or directory is given
350 using a format string; see :hg:`help export` for details.
350 using a format string; see :hg:`help export` for details.
351
351
352 Each member added to an archive file has a directory prefix
352 Each member added to an archive file has a directory prefix
353 prepended. Use -p/--prefix to specify a format string for the
353 prepended. Use -p/--prefix to specify a format string for the
354 prefix. The default is the basename of the archive, with suffixes
354 prefix. The default is the basename of the archive, with suffixes
355 removed.
355 removed.
356
356
357 Returns 0 on success.
357 Returns 0 on success.
358 '''
358 '''
359
359
360 ctx = scmutil.revsingle(repo, opts.get('rev'))
360 ctx = scmutil.revsingle(repo, opts.get('rev'))
361 if not ctx:
361 if not ctx:
362 raise util.Abort(_('no working directory: please specify a revision'))
362 raise util.Abort(_('no working directory: please specify a revision'))
363 node = ctx.node()
363 node = ctx.node()
364 dest = cmdutil.makefilename(repo, dest, node)
364 dest = cmdutil.makefilename(repo, dest, node)
365 if os.path.realpath(dest) == repo.root:
365 if os.path.realpath(dest) == repo.root:
366 raise util.Abort(_('repository root cannot be destination'))
366 raise util.Abort(_('repository root cannot be destination'))
367
367
368 kind = opts.get('type') or archival.guesskind(dest) or 'files'
368 kind = opts.get('type') or archival.guesskind(dest) or 'files'
369 prefix = opts.get('prefix')
369 prefix = opts.get('prefix')
370
370
371 if dest == '-':
371 if dest == '-':
372 if kind == 'files':
372 if kind == 'files':
373 raise util.Abort(_('cannot archive plain files to stdout'))
373 raise util.Abort(_('cannot archive plain files to stdout'))
374 dest = cmdutil.makefileobj(repo, dest)
374 dest = cmdutil.makefileobj(repo, dest)
375 if not prefix:
375 if not prefix:
376 prefix = os.path.basename(repo.root) + '-%h'
376 prefix = os.path.basename(repo.root) + '-%h'
377
377
378 prefix = cmdutil.makefilename(repo, prefix, node)
378 prefix = cmdutil.makefilename(repo, prefix, node)
379 matchfn = scmutil.match(ctx, [], opts)
379 matchfn = scmutil.match(ctx, [], opts)
380 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
380 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
381 matchfn, prefix, subrepos=opts.get('subrepos'))
381 matchfn, prefix, subrepos=opts.get('subrepos'))
382
382
383 @command('backout',
383 @command('backout',
384 [('', 'merge', None, _('merge with old dirstate parent after backout')),
384 [('', 'merge', None, _('merge with old dirstate parent after backout')),
385 ('', 'parent', '',
385 ('', 'parent', '',
386 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
386 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
387 ('r', 'rev', '', _('revision to backout'), _('REV')),
387 ('r', 'rev', '', _('revision to backout'), _('REV')),
388 ] + mergetoolopts + walkopts + commitopts + commitopts2,
388 ] + mergetoolopts + walkopts + commitopts + commitopts2,
389 _('[OPTION]... [-r] REV'))
389 _('[OPTION]... [-r] REV'))
390 def backout(ui, repo, node=None, rev=None, **opts):
390 def backout(ui, repo, node=None, rev=None, **opts):
391 '''reverse effect of earlier changeset
391 '''reverse effect of earlier changeset
392
392
393 Prepare a new changeset with the effect of REV undone in the
393 Prepare a new changeset with the effect of REV undone in the
394 current working directory.
394 current working directory.
395
395
396 If REV is the parent of the working directory, then this new changeset
396 If REV is the parent of the working directory, then this new changeset
397 is committed automatically. Otherwise, hg needs to merge the
397 is committed automatically. Otherwise, hg needs to merge the
398 changes and the merged result is left uncommitted.
398 changes and the merged result is left uncommitted.
399
399
400 .. note::
400 .. note::
401
401
402 backout cannot be used to fix either an unwanted or
402 backout cannot be used to fix either an unwanted or
403 incorrect merge.
403 incorrect merge.
404
404
405 .. container:: verbose
405 .. container:: verbose
406
406
407 By default, the pending changeset will have one parent,
407 By default, the pending changeset will have one parent,
408 maintaining a linear history. With --merge, the pending
408 maintaining a linear history. With --merge, the pending
409 changeset will instead have two parents: the old parent of the
409 changeset will instead have two parents: the old parent of the
410 working directory and a new child of REV that simply undoes REV.
410 working directory and a new child of REV that simply undoes REV.
411
411
412 Before version 1.7, the behavior without --merge was equivalent
412 Before version 1.7, the behavior without --merge was equivalent
413 to specifying --merge followed by :hg:`update --clean .` to
413 to specifying --merge followed by :hg:`update --clean .` to
414 cancel the merge and leave the child of REV as a head to be
414 cancel the merge and leave the child of REV as a head to be
415 merged separately.
415 merged separately.
416
416
417 See :hg:`help dates` for a list of formats valid for -d/--date.
417 See :hg:`help dates` for a list of formats valid for -d/--date.
418
418
419 Returns 0 on success.
419 Returns 0 on success.
420 '''
420 '''
421 if rev and node:
421 if rev and node:
422 raise util.Abort(_("please specify just one revision"))
422 raise util.Abort(_("please specify just one revision"))
423
423
424 if not rev:
424 if not rev:
425 rev = node
425 rev = node
426
426
427 if not rev:
427 if not rev:
428 raise util.Abort(_("please specify a revision to backout"))
428 raise util.Abort(_("please specify a revision to backout"))
429
429
430 date = opts.get('date')
430 date = opts.get('date')
431 if date:
431 if date:
432 opts['date'] = util.parsedate(date)
432 opts['date'] = util.parsedate(date)
433
433
434 cmdutil.checkunfinished(repo)
434 cmdutil.checkunfinished(repo)
435 cmdutil.bailifchanged(repo)
435 cmdutil.bailifchanged(repo)
436 node = scmutil.revsingle(repo, rev).node()
436 node = scmutil.revsingle(repo, rev).node()
437
437
438 op1, op2 = repo.dirstate.parents()
438 op1, op2 = repo.dirstate.parents()
439 a = repo.changelog.ancestor(op1, node)
439 a = repo.changelog.ancestor(op1, node)
440 if a != node:
440 if a != node:
441 raise util.Abort(_('cannot backout change on a different branch'))
441 raise util.Abort(_('cannot backout change on a different branch'))
442
442
443 p1, p2 = repo.changelog.parents(node)
443 p1, p2 = repo.changelog.parents(node)
444 if p1 == nullid:
444 if p1 == nullid:
445 raise util.Abort(_('cannot backout a change with no parents'))
445 raise util.Abort(_('cannot backout a change with no parents'))
446 if p2 != nullid:
446 if p2 != nullid:
447 if not opts.get('parent'):
447 if not opts.get('parent'):
448 raise util.Abort(_('cannot backout a merge changeset'))
448 raise util.Abort(_('cannot backout a merge changeset'))
449 p = repo.lookup(opts['parent'])
449 p = repo.lookup(opts['parent'])
450 if p not in (p1, p2):
450 if p not in (p1, p2):
451 raise util.Abort(_('%s is not a parent of %s') %
451 raise util.Abort(_('%s is not a parent of %s') %
452 (short(p), short(node)))
452 (short(p), short(node)))
453 parent = p
453 parent = p
454 else:
454 else:
455 if opts.get('parent'):
455 if opts.get('parent'):
456 raise util.Abort(_('cannot use --parent on non-merge changeset'))
456 raise util.Abort(_('cannot use --parent on non-merge changeset'))
457 parent = p1
457 parent = p1
458
458
459 # the backout should appear on the same branch
459 # the backout should appear on the same branch
460 wlock = repo.wlock()
460 wlock = repo.wlock()
461 try:
461 try:
462 branch = repo.dirstate.branch()
462 branch = repo.dirstate.branch()
463 bheads = repo.branchheads(branch)
463 bheads = repo.branchheads(branch)
464 hg.clean(repo, node, show_stats=False)
464 hg.clean(repo, node, show_stats=False)
465 repo.dirstate.setbranch(branch)
465 repo.dirstate.setbranch(branch)
466 rctx = scmutil.revsingle(repo, hex(parent))
466 rctx = scmutil.revsingle(repo, hex(parent))
467 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
467 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
468 if not opts.get('merge') and op1 != node:
468 if not opts.get('merge') and op1 != node:
469 try:
469 try:
470 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
470 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
471 return hg.update(repo, op1)
471 return hg.update(repo, op1)
472 finally:
472 finally:
473 ui.setconfig('ui', 'forcemerge', '')
473 ui.setconfig('ui', 'forcemerge', '')
474
474
475 e = cmdutil.commiteditor
475 e = cmdutil.commiteditor
476 if not opts['message'] and not opts['logfile']:
476 if not opts['message'] and not opts['logfile']:
477 # we don't translate commit messages
477 # we don't translate commit messages
478 opts['message'] = "Backed out changeset %s" % short(node)
478 opts['message'] = "Backed out changeset %s" % short(node)
479 e = cmdutil.commitforceeditor
479 e = cmdutil.commitforceeditor
480
480
481 def commitfunc(ui, repo, message, match, opts):
481 def commitfunc(ui, repo, message, match, opts):
482 return repo.commit(message, opts.get('user'), opts.get('date'),
482 return repo.commit(message, opts.get('user'), opts.get('date'),
483 match, editor=e)
483 match, editor=e)
484 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
484 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
485 cmdutil.commitstatus(repo, newnode, branch, bheads)
485 cmdutil.commitstatus(repo, newnode, branch, bheads)
486
486
487 def nice(node):
487 def nice(node):
488 return '%d:%s' % (repo.changelog.rev(node), short(node))
488 return '%d:%s' % (repo.changelog.rev(node), short(node))
489 ui.status(_('changeset %s backs out changeset %s\n') %
489 ui.status(_('changeset %s backs out changeset %s\n') %
490 (nice(repo.changelog.tip()), nice(node)))
490 (nice(repo.changelog.tip()), nice(node)))
491 if opts.get('merge') and op1 != node:
491 if opts.get('merge') and op1 != node:
492 hg.clean(repo, op1, show_stats=False)
492 hg.clean(repo, op1, show_stats=False)
493 ui.status(_('merging with changeset %s\n')
493 ui.status(_('merging with changeset %s\n')
494 % nice(repo.changelog.tip()))
494 % nice(repo.changelog.tip()))
495 try:
495 try:
496 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
496 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
497 return hg.merge(repo, hex(repo.changelog.tip()))
497 return hg.merge(repo, hex(repo.changelog.tip()))
498 finally:
498 finally:
499 ui.setconfig('ui', 'forcemerge', '')
499 ui.setconfig('ui', 'forcemerge', '')
500 finally:
500 finally:
501 wlock.release()
501 wlock.release()
502 return 0
502 return 0
503
503
504 @command('bisect',
504 @command('bisect',
505 [('r', 'reset', False, _('reset bisect state')),
505 [('r', 'reset', False, _('reset bisect state')),
506 ('g', 'good', False, _('mark changeset good')),
506 ('g', 'good', False, _('mark changeset good')),
507 ('b', 'bad', False, _('mark changeset bad')),
507 ('b', 'bad', False, _('mark changeset bad')),
508 ('s', 'skip', False, _('skip testing changeset')),
508 ('s', 'skip', False, _('skip testing changeset')),
509 ('e', 'extend', False, _('extend the bisect range')),
509 ('e', 'extend', False, _('extend the bisect range')),
510 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
510 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
511 ('U', 'noupdate', False, _('do not update to target'))],
511 ('U', 'noupdate', False, _('do not update to target'))],
512 _("[-gbsr] [-U] [-c CMD] [REV]"))
512 _("[-gbsr] [-U] [-c CMD] [REV]"))
513 def bisect(ui, repo, rev=None, extra=None, command=None,
513 def bisect(ui, repo, rev=None, extra=None, command=None,
514 reset=None, good=None, bad=None, skip=None, extend=None,
514 reset=None, good=None, bad=None, skip=None, extend=None,
515 noupdate=None):
515 noupdate=None):
516 """subdivision search of changesets
516 """subdivision search of changesets
517
517
518 This command helps to find changesets which introduce problems. To
518 This command helps to find changesets which introduce problems. To
519 use, mark the earliest changeset you know exhibits the problem as
519 use, mark the earliest changeset you know exhibits the problem as
520 bad, then mark the latest changeset which is free from the problem
520 bad, then mark the latest changeset which is free from the problem
521 as good. Bisect will update your working directory to a revision
521 as good. Bisect will update your working directory to a revision
522 for testing (unless the -U/--noupdate option is specified). Once
522 for testing (unless the -U/--noupdate option is specified). Once
523 you have performed tests, mark the working directory as good or
523 you have performed tests, mark the working directory as good or
524 bad, and bisect will either update to another candidate changeset
524 bad, and bisect will either update to another candidate changeset
525 or announce that it has found the bad revision.
525 or announce that it has found the bad revision.
526
526
527 As a shortcut, you can also use the revision argument to mark a
527 As a shortcut, you can also use the revision argument to mark a
528 revision as good or bad without checking it out first.
528 revision as good or bad without checking it out first.
529
529
530 If you supply a command, it will be used for automatic bisection.
530 If you supply a command, it will be used for automatic bisection.
531 The environment variable HG_NODE will contain the ID of the
531 The environment variable HG_NODE will contain the ID of the
532 changeset being tested. The exit status of the command will be
532 changeset being tested. The exit status of the command will be
533 used to mark revisions as good or bad: status 0 means good, 125
533 used to mark revisions as good or bad: status 0 means good, 125
534 means to skip the revision, 127 (command not found) will abort the
534 means to skip the revision, 127 (command not found) will abort the
535 bisection, and any other non-zero exit status means the revision
535 bisection, and any other non-zero exit status means the revision
536 is bad.
536 is bad.
537
537
538 .. container:: verbose
538 .. container:: verbose
539
539
540 Some examples:
540 Some examples:
541
541
542 - start a bisection with known bad revision 34, and good revision 12::
542 - start a bisection with known bad revision 34, and good revision 12::
543
543
544 hg bisect --bad 34
544 hg bisect --bad 34
545 hg bisect --good 12
545 hg bisect --good 12
546
546
547 - advance the current bisection by marking current revision as good or
547 - advance the current bisection by marking current revision as good or
548 bad::
548 bad::
549
549
550 hg bisect --good
550 hg bisect --good
551 hg bisect --bad
551 hg bisect --bad
552
552
553 - mark the current revision, or a known revision, to be skipped (e.g. if
553 - mark the current revision, or a known revision, to be skipped (e.g. if
554 that revision is not usable because of another issue)::
554 that revision is not usable because of another issue)::
555
555
556 hg bisect --skip
556 hg bisect --skip
557 hg bisect --skip 23
557 hg bisect --skip 23
558
558
559 - skip all revisions that do not touch directories ``foo`` or ``bar``::
559 - skip all revisions that do not touch directories ``foo`` or ``bar``::
560
560
561 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
561 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
562
562
563 - forget the current bisection::
563 - forget the current bisection::
564
564
565 hg bisect --reset
565 hg bisect --reset
566
566
567 - use 'make && make tests' to automatically find the first broken
567 - use 'make && make tests' to automatically find the first broken
568 revision::
568 revision::
569
569
570 hg bisect --reset
570 hg bisect --reset
571 hg bisect --bad 34
571 hg bisect --bad 34
572 hg bisect --good 12
572 hg bisect --good 12
573 hg bisect --command "make && make tests"
573 hg bisect --command "make && make tests"
574
574
575 - see all changesets whose states are already known in the current
575 - see all changesets whose states are already known in the current
576 bisection::
576 bisection::
577
577
578 hg log -r "bisect(pruned)"
578 hg log -r "bisect(pruned)"
579
579
580 - see the changeset currently being bisected (especially useful
580 - see the changeset currently being bisected (especially useful
581 if running with -U/--noupdate)::
581 if running with -U/--noupdate)::
582
582
583 hg log -r "bisect(current)"
583 hg log -r "bisect(current)"
584
584
585 - see all changesets that took part in the current bisection::
585 - see all changesets that took part in the current bisection::
586
586
587 hg log -r "bisect(range)"
587 hg log -r "bisect(range)"
588
588
589 - you can even get a nice graph::
589 - you can even get a nice graph::
590
590
591 hg log --graph -r "bisect(range)"
591 hg log --graph -r "bisect(range)"
592
592
593 See :hg:`help revsets` for more about the `bisect()` keyword.
593 See :hg:`help revsets` for more about the `bisect()` keyword.
594
594
595 Returns 0 on success.
595 Returns 0 on success.
596 """
596 """
597 def extendbisectrange(nodes, good):
597 def extendbisectrange(nodes, good):
598 # bisect is incomplete when it ends on a merge node and
598 # bisect is incomplete when it ends on a merge node and
599 # one of the parent was not checked.
599 # one of the parent was not checked.
600 parents = repo[nodes[0]].parents()
600 parents = repo[nodes[0]].parents()
601 if len(parents) > 1:
601 if len(parents) > 1:
602 side = good and state['bad'] or state['good']
602 side = good and state['bad'] or state['good']
603 num = len(set(i.node() for i in parents) & set(side))
603 num = len(set(i.node() for i in parents) & set(side))
604 if num == 1:
604 if num == 1:
605 return parents[0].ancestor(parents[1])
605 return parents[0].ancestor(parents[1])
606 return None
606 return None
607
607
608 def print_result(nodes, good):
608 def print_result(nodes, good):
609 displayer = cmdutil.show_changeset(ui, repo, {})
609 displayer = cmdutil.show_changeset(ui, repo, {})
610 if len(nodes) == 1:
610 if len(nodes) == 1:
611 # narrowed it down to a single revision
611 # narrowed it down to a single revision
612 if good:
612 if good:
613 ui.write(_("The first good revision is:\n"))
613 ui.write(_("The first good revision is:\n"))
614 else:
614 else:
615 ui.write(_("The first bad revision is:\n"))
615 ui.write(_("The first bad revision is:\n"))
616 displayer.show(repo[nodes[0]])
616 displayer.show(repo[nodes[0]])
617 extendnode = extendbisectrange(nodes, good)
617 extendnode = extendbisectrange(nodes, good)
618 if extendnode is not None:
618 if extendnode is not None:
619 ui.write(_('Not all ancestors of this changeset have been'
619 ui.write(_('Not all ancestors of this changeset have been'
620 ' checked.\nUse bisect --extend to continue the '
620 ' checked.\nUse bisect --extend to continue the '
621 'bisection from\nthe common ancestor, %s.\n')
621 'bisection from\nthe common ancestor, %s.\n')
622 % extendnode)
622 % extendnode)
623 else:
623 else:
624 # multiple possible revisions
624 # multiple possible revisions
625 if good:
625 if good:
626 ui.write(_("Due to skipped revisions, the first "
626 ui.write(_("Due to skipped revisions, the first "
627 "good revision could be any of:\n"))
627 "good revision could be any of:\n"))
628 else:
628 else:
629 ui.write(_("Due to skipped revisions, the first "
629 ui.write(_("Due to skipped revisions, the first "
630 "bad revision could be any of:\n"))
630 "bad revision could be any of:\n"))
631 for n in nodes:
631 for n in nodes:
632 displayer.show(repo[n])
632 displayer.show(repo[n])
633 displayer.close()
633 displayer.close()
634
634
635 def check_state(state, interactive=True):
635 def check_state(state, interactive=True):
636 if not state['good'] or not state['bad']:
636 if not state['good'] or not state['bad']:
637 if (good or bad or skip or reset) and interactive:
637 if (good or bad or skip or reset) and interactive:
638 return
638 return
639 if not state['good']:
639 if not state['good']:
640 raise util.Abort(_('cannot bisect (no known good revisions)'))
640 raise util.Abort(_('cannot bisect (no known good revisions)'))
641 else:
641 else:
642 raise util.Abort(_('cannot bisect (no known bad revisions)'))
642 raise util.Abort(_('cannot bisect (no known bad revisions)'))
643 return True
643 return True
644
644
645 # backward compatibility
645 # backward compatibility
646 if rev in "good bad reset init".split():
646 if rev in "good bad reset init".split():
647 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
647 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
648 cmd, rev, extra = rev, extra, None
648 cmd, rev, extra = rev, extra, None
649 if cmd == "good":
649 if cmd == "good":
650 good = True
650 good = True
651 elif cmd == "bad":
651 elif cmd == "bad":
652 bad = True
652 bad = True
653 else:
653 else:
654 reset = True
654 reset = True
655 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
655 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
656 raise util.Abort(_('incompatible arguments'))
656 raise util.Abort(_('incompatible arguments'))
657
657
658 cmdutil.checkunfinished(repo)
658 cmdutil.checkunfinished(repo)
659
659
660 if reset:
660 if reset:
661 p = repo.join("bisect.state")
661 p = repo.join("bisect.state")
662 if os.path.exists(p):
662 if os.path.exists(p):
663 os.unlink(p)
663 os.unlink(p)
664 return
664 return
665
665
666 state = hbisect.load_state(repo)
666 state = hbisect.load_state(repo)
667
667
668 if command:
668 if command:
669 changesets = 1
669 changesets = 1
670 try:
670 try:
671 node = state['current'][0]
671 node = state['current'][0]
672 except LookupError:
672 except LookupError:
673 if noupdate:
673 if noupdate:
674 raise util.Abort(_('current bisect revision is unknown - '
674 raise util.Abort(_('current bisect revision is unknown - '
675 'start a new bisect to fix'))
675 'start a new bisect to fix'))
676 node, p2 = repo.dirstate.parents()
676 node, p2 = repo.dirstate.parents()
677 if p2 != nullid:
677 if p2 != nullid:
678 raise util.Abort(_('current bisect revision is a merge'))
678 raise util.Abort(_('current bisect revision is a merge'))
679 try:
679 try:
680 while changesets:
680 while changesets:
681 # update state
681 # update state
682 state['current'] = [node]
682 state['current'] = [node]
683 hbisect.save_state(repo, state)
683 hbisect.save_state(repo, state)
684 status = util.system(command,
684 status = util.system(command,
685 environ={'HG_NODE': hex(node)},
685 environ={'HG_NODE': hex(node)},
686 out=ui.fout)
686 out=ui.fout)
687 if status == 125:
687 if status == 125:
688 transition = "skip"
688 transition = "skip"
689 elif status == 0:
689 elif status == 0:
690 transition = "good"
690 transition = "good"
691 # status < 0 means process was killed
691 # status < 0 means process was killed
692 elif status == 127:
692 elif status == 127:
693 raise util.Abort(_("failed to execute %s") % command)
693 raise util.Abort(_("failed to execute %s") % command)
694 elif status < 0:
694 elif status < 0:
695 raise util.Abort(_("%s killed") % command)
695 raise util.Abort(_("%s killed") % command)
696 else:
696 else:
697 transition = "bad"
697 transition = "bad"
698 ctx = scmutil.revsingle(repo, rev, node)
698 ctx = scmutil.revsingle(repo, rev, node)
699 rev = None # clear for future iterations
699 rev = None # clear for future iterations
700 state[transition].append(ctx.node())
700 state[transition].append(ctx.node())
701 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
701 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
702 check_state(state, interactive=False)
702 check_state(state, interactive=False)
703 # bisect
703 # bisect
704 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
704 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
705 # update to next check
705 # update to next check
706 node = nodes[0]
706 node = nodes[0]
707 if not noupdate:
707 if not noupdate:
708 cmdutil.bailifchanged(repo)
708 cmdutil.bailifchanged(repo)
709 hg.clean(repo, node, show_stats=False)
709 hg.clean(repo, node, show_stats=False)
710 finally:
710 finally:
711 state['current'] = [node]
711 state['current'] = [node]
712 hbisect.save_state(repo, state)
712 hbisect.save_state(repo, state)
713 print_result(nodes, bgood)
713 print_result(nodes, bgood)
714 return
714 return
715
715
716 # update state
716 # update state
717
717
718 if rev:
718 if rev:
719 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
719 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
720 else:
720 else:
721 nodes = [repo.lookup('.')]
721 nodes = [repo.lookup('.')]
722
722
723 if good or bad or skip:
723 if good or bad or skip:
724 if good:
724 if good:
725 state['good'] += nodes
725 state['good'] += nodes
726 elif bad:
726 elif bad:
727 state['bad'] += nodes
727 state['bad'] += nodes
728 elif skip:
728 elif skip:
729 state['skip'] += nodes
729 state['skip'] += nodes
730 hbisect.save_state(repo, state)
730 hbisect.save_state(repo, state)
731
731
732 if not check_state(state):
732 if not check_state(state):
733 return
733 return
734
734
735 # actually bisect
735 # actually bisect
736 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
736 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
737 if extend:
737 if extend:
738 if not changesets:
738 if not changesets:
739 extendnode = extendbisectrange(nodes, good)
739 extendnode = extendbisectrange(nodes, good)
740 if extendnode is not None:
740 if extendnode is not None:
741 ui.write(_("Extending search to changeset %d:%s\n"
741 ui.write(_("Extending search to changeset %d:%s\n"
742 % (extendnode.rev(), extendnode)))
742 % (extendnode.rev(), extendnode)))
743 state['current'] = [extendnode.node()]
743 state['current'] = [extendnode.node()]
744 hbisect.save_state(repo, state)
744 hbisect.save_state(repo, state)
745 if noupdate:
745 if noupdate:
746 return
746 return
747 cmdutil.bailifchanged(repo)
747 cmdutil.bailifchanged(repo)
748 return hg.clean(repo, extendnode.node())
748 return hg.clean(repo, extendnode.node())
749 raise util.Abort(_("nothing to extend"))
749 raise util.Abort(_("nothing to extend"))
750
750
751 if changesets == 0:
751 if changesets == 0:
752 print_result(nodes, good)
752 print_result(nodes, good)
753 else:
753 else:
754 assert len(nodes) == 1 # only a single node can be tested next
754 assert len(nodes) == 1 # only a single node can be tested next
755 node = nodes[0]
755 node = nodes[0]
756 # compute the approximate number of remaining tests
756 # compute the approximate number of remaining tests
757 tests, size = 0, 2
757 tests, size = 0, 2
758 while size <= changesets:
758 while size <= changesets:
759 tests, size = tests + 1, size * 2
759 tests, size = tests + 1, size * 2
760 rev = repo.changelog.rev(node)
760 rev = repo.changelog.rev(node)
761 ui.write(_("Testing changeset %d:%s "
761 ui.write(_("Testing changeset %d:%s "
762 "(%d changesets remaining, ~%d tests)\n")
762 "(%d changesets remaining, ~%d tests)\n")
763 % (rev, short(node), changesets, tests))
763 % (rev, short(node), changesets, tests))
764 state['current'] = [node]
764 state['current'] = [node]
765 hbisect.save_state(repo, state)
765 hbisect.save_state(repo, state)
766 if not noupdate:
766 if not noupdate:
767 cmdutil.bailifchanged(repo)
767 cmdutil.bailifchanged(repo)
768 return hg.clean(repo, node)
768 return hg.clean(repo, node)
769
769
770 @command('bookmarks|bookmark',
770 @command('bookmarks|bookmark',
771 [('f', 'force', False, _('force')),
771 [('f', 'force', False, _('force')),
772 ('r', 'rev', '', _('revision'), _('REV')),
772 ('r', 'rev', '', _('revision'), _('REV')),
773 ('d', 'delete', False, _('delete a given bookmark')),
773 ('d', 'delete', False, _('delete a given bookmark')),
774 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
774 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
775 ('i', 'inactive', False, _('mark a bookmark inactive'))],
775 ('i', 'inactive', False, _('mark a bookmark inactive'))],
776 _('hg bookmarks [OPTIONS]... [NAME]...'))
776 _('hg bookmarks [OPTIONS]... [NAME]...'))
777 def bookmark(ui, repo, *names, **opts):
777 def bookmark(ui, repo, *names, **opts):
778 '''track a line of development with movable markers
778 '''track a line of development with movable markers
779
779
780 Bookmarks are pointers to certain commits that move when committing.
780 Bookmarks are pointers to certain commits that move when committing.
781 Bookmarks are local. They can be renamed, copied and deleted. It is
781 Bookmarks are local. They can be renamed, copied and deleted. It is
782 possible to use :hg:`merge NAME` to merge from a given bookmark, and
782 possible to use :hg:`merge NAME` to merge from a given bookmark, and
783 :hg:`update NAME` to update to a given bookmark.
783 :hg:`update NAME` to update to a given bookmark.
784
784
785 You can use :hg:`bookmark NAME` to set a bookmark on the working
785 You can use :hg:`bookmark NAME` to set a bookmark on the working
786 directory's parent revision with the given name. If you specify
786 directory's parent revision with the given name. If you specify
787 a revision using -r REV (where REV may be an existing bookmark),
787 a revision using -r REV (where REV may be an existing bookmark),
788 the bookmark is assigned to that revision.
788 the bookmark is assigned to that revision.
789
789
790 Bookmarks can be pushed and pulled between repositories (see :hg:`help
790 Bookmarks can be pushed and pulled between repositories (see :hg:`help
791 push` and :hg:`help pull`). This requires both the local and remote
791 push` and :hg:`help pull`). This requires both the local and remote
792 repositories to support bookmarks. For versions prior to 1.8, this means
792 repositories to support bookmarks. For versions prior to 1.8, this means
793 the bookmarks extension must be enabled.
793 the bookmarks extension must be enabled.
794
794
795 If you set a bookmark called '@', new clones of the repository will
795 If you set a bookmark called '@', new clones of the repository will
796 have that revision checked out (and the bookmark made active) by
796 have that revision checked out (and the bookmark made active) by
797 default.
797 default.
798
798
799 With -i/--inactive, the new bookmark will not be made the active
799 With -i/--inactive, the new bookmark will not be made the active
800 bookmark. If -r/--rev is given, the new bookmark will not be made
800 bookmark. If -r/--rev is given, the new bookmark will not be made
801 active even if -i/--inactive is not given. If no NAME is given, the
801 active even if -i/--inactive is not given. If no NAME is given, the
802 current active bookmark will be marked inactive.
802 current active bookmark will be marked inactive.
803 '''
803 '''
804 force = opts.get('force')
804 force = opts.get('force')
805 rev = opts.get('rev')
805 rev = opts.get('rev')
806 delete = opts.get('delete')
806 delete = opts.get('delete')
807 rename = opts.get('rename')
807 rename = opts.get('rename')
808 inactive = opts.get('inactive')
808 inactive = opts.get('inactive')
809
809
810 hexfn = ui.debugflag and hex or short
810 hexfn = ui.debugflag and hex or short
811 marks = repo._bookmarks
811 marks = repo._bookmarks
812 cur = repo.changectx('.').node()
812 cur = repo.changectx('.').node()
813
813
814 def checkformat(mark):
814 def checkformat(mark):
815 mark = mark.strip()
815 mark = mark.strip()
816 if not mark:
816 if not mark:
817 raise util.Abort(_("bookmark names cannot consist entirely of "
817 raise util.Abort(_("bookmark names cannot consist entirely of "
818 "whitespace"))
818 "whitespace"))
819 scmutil.checknewlabel(repo, mark, 'bookmark')
819 scmutil.checknewlabel(repo, mark, 'bookmark')
820 return mark
820 return mark
821
821
822 def checkconflict(repo, mark, force=False, target=None):
822 def checkconflict(repo, mark, force=False, target=None):
823 if mark in marks and not force:
823 if mark in marks and not force:
824 if target:
824 if target:
825 if marks[mark] == target and target == cur:
825 if marks[mark] == target and target == cur:
826 # re-activating a bookmark
826 # re-activating a bookmark
827 return
827 return
828 anc = repo.changelog.ancestors([repo[target].rev()])
828 anc = repo.changelog.ancestors([repo[target].rev()])
829 bmctx = repo[marks[mark]]
829 bmctx = repo[marks[mark]]
830 divs = [repo[b].node() for b in marks
830 divs = [repo[b].node() for b in marks
831 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
831 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
832
832
833 # allow resolving a single divergent bookmark even if moving
833 # allow resolving a single divergent bookmark even if moving
834 # the bookmark across branches when a revision is specified
834 # the bookmark across branches when a revision is specified
835 # that contains a divergent bookmark
835 # that contains a divergent bookmark
836 if bmctx.rev() not in anc and target in divs:
836 if bmctx.rev() not in anc and target in divs:
837 bookmarks.deletedivergent(repo, [target], mark)
837 bookmarks.deletedivergent(repo, [target], mark)
838 return
838 return
839
839
840 # consider successor changesets as well
840 # consider successor changesets as well
841 foreground = obsolete.foreground(repo, [marks[mark]])
841 foreground = obsolete.foreground(repo, [marks[mark]])
842 deletefrom = [b for b in divs
842 deletefrom = [b for b in divs
843 if repo[b].rev() in anc or b == target]
843 if repo[b].rev() in anc or b == target]
844 bookmarks.deletedivergent(repo, deletefrom, mark)
844 bookmarks.deletedivergent(repo, deletefrom, mark)
845 if bmctx.rev() in anc or target in foreground:
845 if bmctx.rev() in anc or target in foreground:
846 ui.status(_("moving bookmark '%s' forward from %s\n") %
846 ui.status(_("moving bookmark '%s' forward from %s\n") %
847 (mark, short(bmctx.node())))
847 (mark, short(bmctx.node())))
848 return
848 return
849 raise util.Abort(_("bookmark '%s' already exists "
849 raise util.Abort(_("bookmark '%s' already exists "
850 "(use -f to force)") % mark)
850 "(use -f to force)") % mark)
851 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
851 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
852 and not force):
852 and not force):
853 raise util.Abort(
853 raise util.Abort(
854 _("a bookmark cannot have the name of an existing branch"))
854 _("a bookmark cannot have the name of an existing branch"))
855
855
856 if delete and rename:
856 if delete and rename:
857 raise util.Abort(_("--delete and --rename are incompatible"))
857 raise util.Abort(_("--delete and --rename are incompatible"))
858 if delete and rev:
858 if delete and rev:
859 raise util.Abort(_("--rev is incompatible with --delete"))
859 raise util.Abort(_("--rev is incompatible with --delete"))
860 if rename and rev:
860 if rename and rev:
861 raise util.Abort(_("--rev is incompatible with --rename"))
861 raise util.Abort(_("--rev is incompatible with --rename"))
862 if not names and (delete or rev):
862 if not names and (delete or rev):
863 raise util.Abort(_("bookmark name required"))
863 raise util.Abort(_("bookmark name required"))
864
864
865 if delete:
865 if delete:
866 for mark in names:
866 for mark in names:
867 if mark not in marks:
867 if mark not in marks:
868 raise util.Abort(_("bookmark '%s' does not exist") % mark)
868 raise util.Abort(_("bookmark '%s' does not exist") % mark)
869 if mark == repo._bookmarkcurrent:
869 if mark == repo._bookmarkcurrent:
870 bookmarks.unsetcurrent(repo)
870 bookmarks.unsetcurrent(repo)
871 del marks[mark]
871 del marks[mark]
872 marks.write()
872 marks.write()
873
873
874 elif rename:
874 elif rename:
875 if not names:
875 if not names:
876 raise util.Abort(_("new bookmark name required"))
876 raise util.Abort(_("new bookmark name required"))
877 elif len(names) > 1:
877 elif len(names) > 1:
878 raise util.Abort(_("only one new bookmark name allowed"))
878 raise util.Abort(_("only one new bookmark name allowed"))
879 mark = checkformat(names[0])
879 mark = checkformat(names[0])
880 if rename not in marks:
880 if rename not in marks:
881 raise util.Abort(_("bookmark '%s' does not exist") % rename)
881 raise util.Abort(_("bookmark '%s' does not exist") % rename)
882 checkconflict(repo, mark, force)
882 checkconflict(repo, mark, force)
883 marks[mark] = marks[rename]
883 marks[mark] = marks[rename]
884 if repo._bookmarkcurrent == rename and not inactive:
884 if repo._bookmarkcurrent == rename and not inactive:
885 bookmarks.setcurrent(repo, mark)
885 bookmarks.setcurrent(repo, mark)
886 del marks[rename]
886 del marks[rename]
887 marks.write()
887 marks.write()
888
888
889 elif names:
889 elif names:
890 newact = None
890 newact = None
891 for mark in names:
891 for mark in names:
892 mark = checkformat(mark)
892 mark = checkformat(mark)
893 if newact is None:
893 if newact is None:
894 newact = mark
894 newact = mark
895 if inactive and mark == repo._bookmarkcurrent:
895 if inactive and mark == repo._bookmarkcurrent:
896 bookmarks.unsetcurrent(repo)
896 bookmarks.unsetcurrent(repo)
897 return
897 return
898 tgt = cur
898 tgt = cur
899 if rev:
899 if rev:
900 tgt = scmutil.revsingle(repo, rev).node()
900 tgt = scmutil.revsingle(repo, rev).node()
901 checkconflict(repo, mark, force, tgt)
901 checkconflict(repo, mark, force, tgt)
902 marks[mark] = tgt
902 marks[mark] = tgt
903 if not inactive and cur == marks[newact] and not rev:
903 if not inactive and cur == marks[newact] and not rev:
904 bookmarks.setcurrent(repo, newact)
904 bookmarks.setcurrent(repo, newact)
905 elif cur != tgt and newact == repo._bookmarkcurrent:
905 elif cur != tgt and newact == repo._bookmarkcurrent:
906 bookmarks.unsetcurrent(repo)
906 bookmarks.unsetcurrent(repo)
907 marks.write()
907 marks.write()
908
908
909 # Same message whether trying to deactivate the current bookmark (-i
909 # Same message whether trying to deactivate the current bookmark (-i
910 # with no NAME) or listing bookmarks
910 # with no NAME) or listing bookmarks
911 elif len(marks) == 0:
911 elif len(marks) == 0:
912 ui.status(_("no bookmarks set\n"))
912 ui.status(_("no bookmarks set\n"))
913
913
914 elif inactive:
914 elif inactive:
915 if not repo._bookmarkcurrent:
915 if not repo._bookmarkcurrent:
916 ui.status(_("no active bookmark\n"))
916 ui.status(_("no active bookmark\n"))
917 else:
917 else:
918 bookmarks.unsetcurrent(repo)
918 bookmarks.unsetcurrent(repo)
919
919
920 else: # show bookmarks
920 else: # show bookmarks
921 for bmark, n in sorted(marks.iteritems()):
921 for bmark, n in sorted(marks.iteritems()):
922 current = repo._bookmarkcurrent
922 current = repo._bookmarkcurrent
923 if bmark == current:
923 if bmark == current:
924 prefix, label = '*', 'bookmarks.current'
924 prefix, label = '*', 'bookmarks.current'
925 else:
925 else:
926 prefix, label = ' ', ''
926 prefix, label = ' ', ''
927
927
928 if ui.quiet:
928 if ui.quiet:
929 ui.write("%s\n" % bmark, label=label)
929 ui.write("%s\n" % bmark, label=label)
930 else:
930 else:
931 ui.write(" %s %-25s %d:%s\n" % (
931 ui.write(" %s %-25s %d:%s\n" % (
932 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
932 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
933 label=label)
933 label=label)
934
934
935 @command('branch',
935 @command('branch',
936 [('f', 'force', None,
936 [('f', 'force', None,
937 _('set branch name even if it shadows an existing branch')),
937 _('set branch name even if it shadows an existing branch')),
938 ('C', 'clean', None, _('reset branch name to parent branch name'))],
938 ('C', 'clean', None, _('reset branch name to parent branch name'))],
939 _('[-fC] [NAME]'))
939 _('[-fC] [NAME]'))
940 def branch(ui, repo, label=None, **opts):
940 def branch(ui, repo, label=None, **opts):
941 """set or show the current branch name
941 """set or show the current branch name
942
942
943 .. note::
943 .. note::
944
944
945 Branch names are permanent and global. Use :hg:`bookmark` to create a
945 Branch names are permanent and global. Use :hg:`bookmark` to create a
946 light-weight bookmark instead. See :hg:`help glossary` for more
946 light-weight bookmark instead. See :hg:`help glossary` for more
947 information about named branches and bookmarks.
947 information about named branches and bookmarks.
948
948
949 With no argument, show the current branch name. With one argument,
949 With no argument, show the current branch name. With one argument,
950 set the working directory branch name (the branch will not exist
950 set the working directory branch name (the branch will not exist
951 in the repository until the next commit). Standard practice
951 in the repository until the next commit). Standard practice
952 recommends that primary development take place on the 'default'
952 recommends that primary development take place on the 'default'
953 branch.
953 branch.
954
954
955 Unless -f/--force is specified, branch will not let you set a
955 Unless -f/--force is specified, branch will not let you set a
956 branch name that already exists, even if it's inactive.
956 branch name that already exists, even if it's inactive.
957
957
958 Use -C/--clean to reset the working directory branch to that of
958 Use -C/--clean to reset the working directory branch to that of
959 the parent of the working directory, negating a previous branch
959 the parent of the working directory, negating a previous branch
960 change.
960 change.
961
961
962 Use the command :hg:`update` to switch to an existing branch. Use
962 Use the command :hg:`update` to switch to an existing branch. Use
963 :hg:`commit --close-branch` to mark this branch as closed.
963 :hg:`commit --close-branch` to mark this branch as closed.
964
964
965 Returns 0 on success.
965 Returns 0 on success.
966 """
966 """
967 if label:
967 if label:
968 label = label.strip()
968 label = label.strip()
969
969
970 if not opts.get('clean') and not label:
970 if not opts.get('clean') and not label:
971 ui.write("%s\n" % repo.dirstate.branch())
971 ui.write("%s\n" % repo.dirstate.branch())
972 return
972 return
973
973
974 wlock = repo.wlock()
974 wlock = repo.wlock()
975 try:
975 try:
976 if opts.get('clean'):
976 if opts.get('clean'):
977 label = repo[None].p1().branch()
977 label = repo[None].p1().branch()
978 repo.dirstate.setbranch(label)
978 repo.dirstate.setbranch(label)
979 ui.status(_('reset working directory to branch %s\n') % label)
979 ui.status(_('reset working directory to branch %s\n') % label)
980 elif label:
980 elif label:
981 if not opts.get('force') and label in repo.branchmap():
981 if not opts.get('force') and label in repo.branchmap():
982 if label not in [p.branch() for p in repo.parents()]:
982 if label not in [p.branch() for p in repo.parents()]:
983 raise util.Abort(_('a branch of the same name already'
983 raise util.Abort(_('a branch of the same name already'
984 ' exists'),
984 ' exists'),
985 # i18n: "it" refers to an existing branch
985 # i18n: "it" refers to an existing branch
986 hint=_("use 'hg update' to switch to it"))
986 hint=_("use 'hg update' to switch to it"))
987 scmutil.checknewlabel(repo, label, 'branch')
987 scmutil.checknewlabel(repo, label, 'branch')
988 repo.dirstate.setbranch(label)
988 repo.dirstate.setbranch(label)
989 ui.status(_('marked working directory as branch %s\n') % label)
989 ui.status(_('marked working directory as branch %s\n') % label)
990 ui.status(_('(branches are permanent and global, '
990 ui.status(_('(branches are permanent and global, '
991 'did you want a bookmark?)\n'))
991 'did you want a bookmark?)\n'))
992 finally:
992 finally:
993 wlock.release()
993 wlock.release()
994
994
995 @command('branches',
995 @command('branches',
996 [('a', 'active', False, _('show only branches that have unmerged heads')),
996 [('a', 'active', False, _('show only branches that have unmerged heads')),
997 ('c', 'closed', False, _('show normal and closed branches'))],
997 ('c', 'closed', False, _('show normal and closed branches'))],
998 _('[-ac]'))
998 _('[-ac]'))
999 def branches(ui, repo, active=False, closed=False):
999 def branches(ui, repo, active=False, closed=False):
1000 """list repository named branches
1000 """list repository named branches
1001
1001
1002 List the repository's named branches, indicating which ones are
1002 List the repository's named branches, indicating which ones are
1003 inactive. If -c/--closed is specified, also list branches which have
1003 inactive. If -c/--closed is specified, also list branches which have
1004 been marked closed (see :hg:`commit --close-branch`).
1004 been marked closed (see :hg:`commit --close-branch`).
1005
1005
1006 If -a/--active is specified, only show active branches. A branch
1006 If -a/--active is specified, only show active branches. A branch
1007 is considered active if it contains repository heads.
1007 is considered active if it contains repository heads.
1008
1008
1009 Use the command :hg:`update` to switch to an existing branch.
1009 Use the command :hg:`update` to switch to an existing branch.
1010
1010
1011 Returns 0.
1011 Returns 0.
1012 """
1012 """
1013
1013
1014 hexfunc = ui.debugflag and hex or short
1014 hexfunc = ui.debugflag and hex or short
1015
1015
1016 allheads = set(repo.heads())
1016 allheads = set(repo.heads())
1017 branches = []
1017 branches = []
1018 for tag, heads in repo.branchmap().iteritems():
1018 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1019 for h in reversed(heads):
1019 isactive = not isclosed and bool(set(heads) & allheads)
1020 ctx = repo[h]
1020 branches.append((tag, repo[tip], isactive, not isclosed))
1021 isopen = not ctx.closesbranch()
1022 if isopen:
1023 tip = ctx
1024 break
1025 else:
1026 tip = repo[heads[-1]]
1027 isactive = isopen and bool(set(heads) & allheads)
1028 branches.append((tag, tip, isactive, isopen))
1029 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1021 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1030 reverse=True)
1022 reverse=True)
1031
1023
1032 for tag, ctx, isactive, isopen in branches:
1024 for tag, ctx, isactive, isopen in branches:
1033 if (not active) or isactive:
1025 if (not active) or isactive:
1034 if isactive:
1026 if isactive:
1035 label = 'branches.active'
1027 label = 'branches.active'
1036 notice = ''
1028 notice = ''
1037 elif not isopen:
1029 elif not isopen:
1038 if not closed:
1030 if not closed:
1039 continue
1031 continue
1040 label = 'branches.closed'
1032 label = 'branches.closed'
1041 notice = _(' (closed)')
1033 notice = _(' (closed)')
1042 else:
1034 else:
1043 label = 'branches.inactive'
1035 label = 'branches.inactive'
1044 notice = _(' (inactive)')
1036 notice = _(' (inactive)')
1045 if tag == repo.dirstate.branch():
1037 if tag == repo.dirstate.branch():
1046 label = 'branches.current'
1038 label = 'branches.current'
1047 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1039 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1048 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1040 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1049 'log.changeset changeset.%s' % ctx.phasestr())
1041 'log.changeset changeset.%s' % ctx.phasestr())
1050 labeledtag = ui.label(tag, label)
1042 labeledtag = ui.label(tag, label)
1051 if ui.quiet:
1043 if ui.quiet:
1052 ui.write("%s\n" % labeledtag)
1044 ui.write("%s\n" % labeledtag)
1053 else:
1045 else:
1054 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1046 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1055
1047
1056 @command('bundle',
1048 @command('bundle',
1057 [('f', 'force', None, _('run even when the destination is unrelated')),
1049 [('f', 'force', None, _('run even when the destination is unrelated')),
1058 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1050 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1059 _('REV')),
1051 _('REV')),
1060 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1052 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1061 _('BRANCH')),
1053 _('BRANCH')),
1062 ('', 'base', [],
1054 ('', 'base', [],
1063 _('a base changeset assumed to be available at the destination'),
1055 _('a base changeset assumed to be available at the destination'),
1064 _('REV')),
1056 _('REV')),
1065 ('a', 'all', None, _('bundle all changesets in the repository')),
1057 ('a', 'all', None, _('bundle all changesets in the repository')),
1066 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1058 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1067 ] + remoteopts,
1059 ] + remoteopts,
1068 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1060 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1069 def bundle(ui, repo, fname, dest=None, **opts):
1061 def bundle(ui, repo, fname, dest=None, **opts):
1070 """create a changegroup file
1062 """create a changegroup file
1071
1063
1072 Generate a compressed changegroup file collecting changesets not
1064 Generate a compressed changegroup file collecting changesets not
1073 known to be in another repository.
1065 known to be in another repository.
1074
1066
1075 If you omit the destination repository, then hg assumes the
1067 If you omit the destination repository, then hg assumes the
1076 destination will have all the nodes you specify with --base
1068 destination will have all the nodes you specify with --base
1077 parameters. To create a bundle containing all changesets, use
1069 parameters. To create a bundle containing all changesets, use
1078 -a/--all (or --base null).
1070 -a/--all (or --base null).
1079
1071
1080 You can change compression method with the -t/--type option.
1072 You can change compression method with the -t/--type option.
1081 The available compression methods are: none, bzip2, and
1073 The available compression methods are: none, bzip2, and
1082 gzip (by default, bundles are compressed using bzip2).
1074 gzip (by default, bundles are compressed using bzip2).
1083
1075
1084 The bundle file can then be transferred using conventional means
1076 The bundle file can then be transferred using conventional means
1085 and applied to another repository with the unbundle or pull
1077 and applied to another repository with the unbundle or pull
1086 command. This is useful when direct push and pull are not
1078 command. This is useful when direct push and pull are not
1087 available or when exporting an entire repository is undesirable.
1079 available or when exporting an entire repository is undesirable.
1088
1080
1089 Applying bundles preserves all changeset contents including
1081 Applying bundles preserves all changeset contents including
1090 permissions, copy/rename information, and revision history.
1082 permissions, copy/rename information, and revision history.
1091
1083
1092 Returns 0 on success, 1 if no changes found.
1084 Returns 0 on success, 1 if no changes found.
1093 """
1085 """
1094 revs = None
1086 revs = None
1095 if 'rev' in opts:
1087 if 'rev' in opts:
1096 revs = scmutil.revrange(repo, opts['rev'])
1088 revs = scmutil.revrange(repo, opts['rev'])
1097
1089
1098 bundletype = opts.get('type', 'bzip2').lower()
1090 bundletype = opts.get('type', 'bzip2').lower()
1099 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1091 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1100 bundletype = btypes.get(bundletype)
1092 bundletype = btypes.get(bundletype)
1101 if bundletype not in changegroup.bundletypes:
1093 if bundletype not in changegroup.bundletypes:
1102 raise util.Abort(_('unknown bundle type specified with --type'))
1094 raise util.Abort(_('unknown bundle type specified with --type'))
1103
1095
1104 if opts.get('all'):
1096 if opts.get('all'):
1105 base = ['null']
1097 base = ['null']
1106 else:
1098 else:
1107 base = scmutil.revrange(repo, opts.get('base'))
1099 base = scmutil.revrange(repo, opts.get('base'))
1108 # TODO: get desired bundlecaps from command line.
1100 # TODO: get desired bundlecaps from command line.
1109 bundlecaps = None
1101 bundlecaps = None
1110 if base:
1102 if base:
1111 if dest:
1103 if dest:
1112 raise util.Abort(_("--base is incompatible with specifying "
1104 raise util.Abort(_("--base is incompatible with specifying "
1113 "a destination"))
1105 "a destination"))
1114 common = [repo.lookup(rev) for rev in base]
1106 common = [repo.lookup(rev) for rev in base]
1115 heads = revs and map(repo.lookup, revs) or revs
1107 heads = revs and map(repo.lookup, revs) or revs
1116 cg = repo.getbundle('bundle', heads=heads, common=common,
1108 cg = repo.getbundle('bundle', heads=heads, common=common,
1117 bundlecaps=bundlecaps)
1109 bundlecaps=bundlecaps)
1118 outgoing = None
1110 outgoing = None
1119 else:
1111 else:
1120 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1112 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1121 dest, branches = hg.parseurl(dest, opts.get('branch'))
1113 dest, branches = hg.parseurl(dest, opts.get('branch'))
1122 other = hg.peer(repo, opts, dest)
1114 other = hg.peer(repo, opts, dest)
1123 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1115 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1124 heads = revs and map(repo.lookup, revs) or revs
1116 heads = revs and map(repo.lookup, revs) or revs
1125 outgoing = discovery.findcommonoutgoing(repo, other,
1117 outgoing = discovery.findcommonoutgoing(repo, other,
1126 onlyheads=heads,
1118 onlyheads=heads,
1127 force=opts.get('force'),
1119 force=opts.get('force'),
1128 portable=True)
1120 portable=True)
1129 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1121 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1130 if not cg:
1122 if not cg:
1131 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1123 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1132 return 1
1124 return 1
1133
1125
1134 changegroup.writebundle(cg, fname, bundletype)
1126 changegroup.writebundle(cg, fname, bundletype)
1135
1127
1136 @command('cat',
1128 @command('cat',
1137 [('o', 'output', '',
1129 [('o', 'output', '',
1138 _('print output to file with formatted name'), _('FORMAT')),
1130 _('print output to file with formatted name'), _('FORMAT')),
1139 ('r', 'rev', '', _('print the given revision'), _('REV')),
1131 ('r', 'rev', '', _('print the given revision'), _('REV')),
1140 ('', 'decode', None, _('apply any matching decode filter')),
1132 ('', 'decode', None, _('apply any matching decode filter')),
1141 ] + walkopts,
1133 ] + walkopts,
1142 _('[OPTION]... FILE...'))
1134 _('[OPTION]... FILE...'))
1143 def cat(ui, repo, file1, *pats, **opts):
1135 def cat(ui, repo, file1, *pats, **opts):
1144 """output the current or given revision of files
1136 """output the current or given revision of files
1145
1137
1146 Print the specified files as they were at the given revision. If
1138 Print the specified files as they were at the given revision. If
1147 no revision is given, the parent of the working directory is used.
1139 no revision is given, the parent of the working directory is used.
1148
1140
1149 Output may be to a file, in which case the name of the file is
1141 Output may be to a file, in which case the name of the file is
1150 given using a format string. The formatting rules are the same as
1142 given using a format string. The formatting rules are the same as
1151 for the export command, with the following additions:
1143 for the export command, with the following additions:
1152
1144
1153 :``%s``: basename of file being printed
1145 :``%s``: basename of file being printed
1154 :``%d``: dirname of file being printed, or '.' if in repository root
1146 :``%d``: dirname of file being printed, or '.' if in repository root
1155 :``%p``: root-relative path name of file being printed
1147 :``%p``: root-relative path name of file being printed
1156
1148
1157 Returns 0 on success.
1149 Returns 0 on success.
1158 """
1150 """
1159 ctx = scmutil.revsingle(repo, opts.get('rev'))
1151 ctx = scmutil.revsingle(repo, opts.get('rev'))
1160 err = 1
1152 err = 1
1161 m = scmutil.match(ctx, (file1,) + pats, opts)
1153 m = scmutil.match(ctx, (file1,) + pats, opts)
1162 for abs in ctx.walk(m):
1154 for abs in ctx.walk(m):
1163 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1155 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1164 pathname=abs)
1156 pathname=abs)
1165 data = ctx[abs].data()
1157 data = ctx[abs].data()
1166 if opts.get('decode'):
1158 if opts.get('decode'):
1167 data = repo.wwritedata(abs, data)
1159 data = repo.wwritedata(abs, data)
1168 fp.write(data)
1160 fp.write(data)
1169 fp.close()
1161 fp.close()
1170 err = 0
1162 err = 0
1171 return err
1163 return err
1172
1164
1173 @command('^clone',
1165 @command('^clone',
1174 [('U', 'noupdate', None,
1166 [('U', 'noupdate', None,
1175 _('the clone will include an empty working copy (only a repository)')),
1167 _('the clone will include an empty working copy (only a repository)')),
1176 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1168 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1177 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1169 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1178 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1170 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1179 ('', 'pull', None, _('use pull protocol to copy metadata')),
1171 ('', 'pull', None, _('use pull protocol to copy metadata')),
1180 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1172 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1181 ] + remoteopts,
1173 ] + remoteopts,
1182 _('[OPTION]... SOURCE [DEST]'))
1174 _('[OPTION]... SOURCE [DEST]'))
1183 def clone(ui, source, dest=None, **opts):
1175 def clone(ui, source, dest=None, **opts):
1184 """make a copy of an existing repository
1176 """make a copy of an existing repository
1185
1177
1186 Create a copy of an existing repository in a new directory.
1178 Create a copy of an existing repository in a new directory.
1187
1179
1188 If no destination directory name is specified, it defaults to the
1180 If no destination directory name is specified, it defaults to the
1189 basename of the source.
1181 basename of the source.
1190
1182
1191 The location of the source is added to the new repository's
1183 The location of the source is added to the new repository's
1192 ``.hg/hgrc`` file, as the default to be used for future pulls.
1184 ``.hg/hgrc`` file, as the default to be used for future pulls.
1193
1185
1194 Only local paths and ``ssh://`` URLs are supported as
1186 Only local paths and ``ssh://`` URLs are supported as
1195 destinations. For ``ssh://`` destinations, no working directory or
1187 destinations. For ``ssh://`` destinations, no working directory or
1196 ``.hg/hgrc`` will be created on the remote side.
1188 ``.hg/hgrc`` will be created on the remote side.
1197
1189
1198 To pull only a subset of changesets, specify one or more revisions
1190 To pull only a subset of changesets, specify one or more revisions
1199 identifiers with -r/--rev or branches with -b/--branch. The
1191 identifiers with -r/--rev or branches with -b/--branch. The
1200 resulting clone will contain only the specified changesets and
1192 resulting clone will contain only the specified changesets and
1201 their ancestors. These options (or 'clone src#rev dest') imply
1193 their ancestors. These options (or 'clone src#rev dest') imply
1202 --pull, even for local source repositories. Note that specifying a
1194 --pull, even for local source repositories. Note that specifying a
1203 tag will include the tagged changeset but not the changeset
1195 tag will include the tagged changeset but not the changeset
1204 containing the tag.
1196 containing the tag.
1205
1197
1206 If the source repository has a bookmark called '@' set, that
1198 If the source repository has a bookmark called '@' set, that
1207 revision will be checked out in the new repository by default.
1199 revision will be checked out in the new repository by default.
1208
1200
1209 To check out a particular version, use -u/--update, or
1201 To check out a particular version, use -u/--update, or
1210 -U/--noupdate to create a clone with no working directory.
1202 -U/--noupdate to create a clone with no working directory.
1211
1203
1212 .. container:: verbose
1204 .. container:: verbose
1213
1205
1214 For efficiency, hardlinks are used for cloning whenever the
1206 For efficiency, hardlinks are used for cloning whenever the
1215 source and destination are on the same filesystem (note this
1207 source and destination are on the same filesystem (note this
1216 applies only to the repository data, not to the working
1208 applies only to the repository data, not to the working
1217 directory). Some filesystems, such as AFS, implement hardlinking
1209 directory). Some filesystems, such as AFS, implement hardlinking
1218 incorrectly, but do not report errors. In these cases, use the
1210 incorrectly, but do not report errors. In these cases, use the
1219 --pull option to avoid hardlinking.
1211 --pull option to avoid hardlinking.
1220
1212
1221 In some cases, you can clone repositories and the working
1213 In some cases, you can clone repositories and the working
1222 directory using full hardlinks with ::
1214 directory using full hardlinks with ::
1223
1215
1224 $ cp -al REPO REPOCLONE
1216 $ cp -al REPO REPOCLONE
1225
1217
1226 This is the fastest way to clone, but it is not always safe. The
1218 This is the fastest way to clone, but it is not always safe. The
1227 operation is not atomic (making sure REPO is not modified during
1219 operation is not atomic (making sure REPO is not modified during
1228 the operation is up to you) and you have to make sure your
1220 the operation is up to you) and you have to make sure your
1229 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1221 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1230 so). Also, this is not compatible with certain extensions that
1222 so). Also, this is not compatible with certain extensions that
1231 place their metadata under the .hg directory, such as mq.
1223 place their metadata under the .hg directory, such as mq.
1232
1224
1233 Mercurial will update the working directory to the first applicable
1225 Mercurial will update the working directory to the first applicable
1234 revision from this list:
1226 revision from this list:
1235
1227
1236 a) null if -U or the source repository has no changesets
1228 a) null if -U or the source repository has no changesets
1237 b) if -u . and the source repository is local, the first parent of
1229 b) if -u . and the source repository is local, the first parent of
1238 the source repository's working directory
1230 the source repository's working directory
1239 c) the changeset specified with -u (if a branch name, this means the
1231 c) the changeset specified with -u (if a branch name, this means the
1240 latest head of that branch)
1232 latest head of that branch)
1241 d) the changeset specified with -r
1233 d) the changeset specified with -r
1242 e) the tipmost head specified with -b
1234 e) the tipmost head specified with -b
1243 f) the tipmost head specified with the url#branch source syntax
1235 f) the tipmost head specified with the url#branch source syntax
1244 g) the revision marked with the '@' bookmark, if present
1236 g) the revision marked with the '@' bookmark, if present
1245 h) the tipmost head of the default branch
1237 h) the tipmost head of the default branch
1246 i) tip
1238 i) tip
1247
1239
1248 Examples:
1240 Examples:
1249
1241
1250 - clone a remote repository to a new directory named hg/::
1242 - clone a remote repository to a new directory named hg/::
1251
1243
1252 hg clone http://selenic.com/hg
1244 hg clone http://selenic.com/hg
1253
1245
1254 - create a lightweight local clone::
1246 - create a lightweight local clone::
1255
1247
1256 hg clone project/ project-feature/
1248 hg clone project/ project-feature/
1257
1249
1258 - clone from an absolute path on an ssh server (note double-slash)::
1250 - clone from an absolute path on an ssh server (note double-slash)::
1259
1251
1260 hg clone ssh://user@server//home/projects/alpha/
1252 hg clone ssh://user@server//home/projects/alpha/
1261
1253
1262 - do a high-speed clone over a LAN while checking out a
1254 - do a high-speed clone over a LAN while checking out a
1263 specified version::
1255 specified version::
1264
1256
1265 hg clone --uncompressed http://server/repo -u 1.5
1257 hg clone --uncompressed http://server/repo -u 1.5
1266
1258
1267 - create a repository without changesets after a particular revision::
1259 - create a repository without changesets after a particular revision::
1268
1260
1269 hg clone -r 04e544 experimental/ good/
1261 hg clone -r 04e544 experimental/ good/
1270
1262
1271 - clone (and track) a particular named branch::
1263 - clone (and track) a particular named branch::
1272
1264
1273 hg clone http://selenic.com/hg#stable
1265 hg clone http://selenic.com/hg#stable
1274
1266
1275 See :hg:`help urls` for details on specifying URLs.
1267 See :hg:`help urls` for details on specifying URLs.
1276
1268
1277 Returns 0 on success.
1269 Returns 0 on success.
1278 """
1270 """
1279 if opts.get('noupdate') and opts.get('updaterev'):
1271 if opts.get('noupdate') and opts.get('updaterev'):
1280 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1272 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1281
1273
1282 r = hg.clone(ui, opts, source, dest,
1274 r = hg.clone(ui, opts, source, dest,
1283 pull=opts.get('pull'),
1275 pull=opts.get('pull'),
1284 stream=opts.get('uncompressed'),
1276 stream=opts.get('uncompressed'),
1285 rev=opts.get('rev'),
1277 rev=opts.get('rev'),
1286 update=opts.get('updaterev') or not opts.get('noupdate'),
1278 update=opts.get('updaterev') or not opts.get('noupdate'),
1287 branch=opts.get('branch'))
1279 branch=opts.get('branch'))
1288
1280
1289 return r is None
1281 return r is None
1290
1282
1291 @command('^commit|ci',
1283 @command('^commit|ci',
1292 [('A', 'addremove', None,
1284 [('A', 'addremove', None,
1293 _('mark new/missing files as added/removed before committing')),
1285 _('mark new/missing files as added/removed before committing')),
1294 ('', 'close-branch', None,
1286 ('', 'close-branch', None,
1295 _('mark a branch as closed, hiding it from the branch list')),
1287 _('mark a branch as closed, hiding it from the branch list')),
1296 ('', 'amend', None, _('amend the parent of the working dir')),
1288 ('', 'amend', None, _('amend the parent of the working dir')),
1297 ('s', 'secret', None, _('use the secret phase for committing')),
1289 ('s', 'secret', None, _('use the secret phase for committing')),
1298 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1290 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1299 _('[OPTION]... [FILE]...'))
1291 _('[OPTION]... [FILE]...'))
1300 def commit(ui, repo, *pats, **opts):
1292 def commit(ui, repo, *pats, **opts):
1301 """commit the specified files or all outstanding changes
1293 """commit the specified files or all outstanding changes
1302
1294
1303 Commit changes to the given files into the repository. Unlike a
1295 Commit changes to the given files into the repository. Unlike a
1304 centralized SCM, this operation is a local operation. See
1296 centralized SCM, this operation is a local operation. See
1305 :hg:`push` for a way to actively distribute your changes.
1297 :hg:`push` for a way to actively distribute your changes.
1306
1298
1307 If a list of files is omitted, all changes reported by :hg:`status`
1299 If a list of files is omitted, all changes reported by :hg:`status`
1308 will be committed.
1300 will be committed.
1309
1301
1310 If you are committing the result of a merge, do not provide any
1302 If you are committing the result of a merge, do not provide any
1311 filenames or -I/-X filters.
1303 filenames or -I/-X filters.
1312
1304
1313 If no commit message is specified, Mercurial starts your
1305 If no commit message is specified, Mercurial starts your
1314 configured editor where you can enter a message. In case your
1306 configured editor where you can enter a message. In case your
1315 commit fails, you will find a backup of your message in
1307 commit fails, you will find a backup of your message in
1316 ``.hg/last-message.txt``.
1308 ``.hg/last-message.txt``.
1317
1309
1318 The --amend flag can be used to amend the parent of the
1310 The --amend flag can be used to amend the parent of the
1319 working directory with a new commit that contains the changes
1311 working directory with a new commit that contains the changes
1320 in the parent in addition to those currently reported by :hg:`status`,
1312 in the parent in addition to those currently reported by :hg:`status`,
1321 if there are any. The old commit is stored in a backup bundle in
1313 if there are any. The old commit is stored in a backup bundle in
1322 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1314 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1323 on how to restore it).
1315 on how to restore it).
1324
1316
1325 Message, user and date are taken from the amended commit unless
1317 Message, user and date are taken from the amended commit unless
1326 specified. When a message isn't specified on the command line,
1318 specified. When a message isn't specified on the command line,
1327 the editor will open with the message of the amended commit.
1319 the editor will open with the message of the amended commit.
1328
1320
1329 It is not possible to amend public changesets (see :hg:`help phases`)
1321 It is not possible to amend public changesets (see :hg:`help phases`)
1330 or changesets that have children.
1322 or changesets that have children.
1331
1323
1332 See :hg:`help dates` for a list of formats valid for -d/--date.
1324 See :hg:`help dates` for a list of formats valid for -d/--date.
1333
1325
1334 Returns 0 on success, 1 if nothing changed.
1326 Returns 0 on success, 1 if nothing changed.
1335 """
1327 """
1336 if opts.get('subrepos'):
1328 if opts.get('subrepos'):
1337 if opts.get('amend'):
1329 if opts.get('amend'):
1338 raise util.Abort(_('cannot amend with --subrepos'))
1330 raise util.Abort(_('cannot amend with --subrepos'))
1339 # Let --subrepos on the command line override config setting.
1331 # Let --subrepos on the command line override config setting.
1340 ui.setconfig('ui', 'commitsubrepos', True)
1332 ui.setconfig('ui', 'commitsubrepos', True)
1341
1333
1342 # Save this for restoring it later
1334 # Save this for restoring it later
1343 oldcommitphase = ui.config('phases', 'new-commit')
1335 oldcommitphase = ui.config('phases', 'new-commit')
1344
1336
1345 cmdutil.checkunfinished(repo, commit=True)
1337 cmdutil.checkunfinished(repo, commit=True)
1346
1338
1347 branch = repo[None].branch()
1339 branch = repo[None].branch()
1348 bheads = repo.branchheads(branch)
1340 bheads = repo.branchheads(branch)
1349
1341
1350 extra = {}
1342 extra = {}
1351 if opts.get('close_branch'):
1343 if opts.get('close_branch'):
1352 extra['close'] = 1
1344 extra['close'] = 1
1353
1345
1354 if not bheads:
1346 if not bheads:
1355 raise util.Abort(_('can only close branch heads'))
1347 raise util.Abort(_('can only close branch heads'))
1356 elif opts.get('amend'):
1348 elif opts.get('amend'):
1357 if repo.parents()[0].p1().branch() != branch and \
1349 if repo.parents()[0].p1().branch() != branch and \
1358 repo.parents()[0].p2().branch() != branch:
1350 repo.parents()[0].p2().branch() != branch:
1359 raise util.Abort(_('can only close branch heads'))
1351 raise util.Abort(_('can only close branch heads'))
1360
1352
1361 if opts.get('amend'):
1353 if opts.get('amend'):
1362 if ui.configbool('ui', 'commitsubrepos'):
1354 if ui.configbool('ui', 'commitsubrepos'):
1363 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1355 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1364
1356
1365 old = repo['.']
1357 old = repo['.']
1366 if old.phase() == phases.public:
1358 if old.phase() == phases.public:
1367 raise util.Abort(_('cannot amend public changesets'))
1359 raise util.Abort(_('cannot amend public changesets'))
1368 if len(repo[None].parents()) > 1:
1360 if len(repo[None].parents()) > 1:
1369 raise util.Abort(_('cannot amend while merging'))
1361 raise util.Abort(_('cannot amend while merging'))
1370 if (not obsolete._enabled) and old.children():
1362 if (not obsolete._enabled) and old.children():
1371 raise util.Abort(_('cannot amend changeset with children'))
1363 raise util.Abort(_('cannot amend changeset with children'))
1372
1364
1373 e = cmdutil.commiteditor
1365 e = cmdutil.commiteditor
1374 if opts.get('force_editor'):
1366 if opts.get('force_editor'):
1375 e = cmdutil.commitforceeditor
1367 e = cmdutil.commitforceeditor
1376
1368
1377 def commitfunc(ui, repo, message, match, opts):
1369 def commitfunc(ui, repo, message, match, opts):
1378 editor = e
1370 editor = e
1379 # message contains text from -m or -l, if it's empty,
1371 # message contains text from -m or -l, if it's empty,
1380 # open the editor with the old message
1372 # open the editor with the old message
1381 if not message:
1373 if not message:
1382 message = old.description()
1374 message = old.description()
1383 editor = cmdutil.commitforceeditor
1375 editor = cmdutil.commitforceeditor
1384 try:
1376 try:
1385 if opts.get('secret'):
1377 if opts.get('secret'):
1386 ui.setconfig('phases', 'new-commit', 'secret')
1378 ui.setconfig('phases', 'new-commit', 'secret')
1387
1379
1388 return repo.commit(message,
1380 return repo.commit(message,
1389 opts.get('user') or old.user(),
1381 opts.get('user') or old.user(),
1390 opts.get('date') or old.date(),
1382 opts.get('date') or old.date(),
1391 match,
1383 match,
1392 editor=editor,
1384 editor=editor,
1393 extra=extra)
1385 extra=extra)
1394 finally:
1386 finally:
1395 ui.setconfig('phases', 'new-commit', oldcommitphase)
1387 ui.setconfig('phases', 'new-commit', oldcommitphase)
1396
1388
1397 current = repo._bookmarkcurrent
1389 current = repo._bookmarkcurrent
1398 marks = old.bookmarks()
1390 marks = old.bookmarks()
1399 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1391 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1400 if node == old.node():
1392 if node == old.node():
1401 ui.status(_("nothing changed\n"))
1393 ui.status(_("nothing changed\n"))
1402 return 1
1394 return 1
1403 elif marks:
1395 elif marks:
1404 ui.debug('moving bookmarks %r from %s to %s\n' %
1396 ui.debug('moving bookmarks %r from %s to %s\n' %
1405 (marks, old.hex(), hex(node)))
1397 (marks, old.hex(), hex(node)))
1406 newmarks = repo._bookmarks
1398 newmarks = repo._bookmarks
1407 for bm in marks:
1399 for bm in marks:
1408 newmarks[bm] = node
1400 newmarks[bm] = node
1409 if bm == current:
1401 if bm == current:
1410 bookmarks.setcurrent(repo, bm)
1402 bookmarks.setcurrent(repo, bm)
1411 newmarks.write()
1403 newmarks.write()
1412 else:
1404 else:
1413 e = cmdutil.commiteditor
1405 e = cmdutil.commiteditor
1414 if opts.get('force_editor'):
1406 if opts.get('force_editor'):
1415 e = cmdutil.commitforceeditor
1407 e = cmdutil.commitforceeditor
1416
1408
1417 def commitfunc(ui, repo, message, match, opts):
1409 def commitfunc(ui, repo, message, match, opts):
1418 try:
1410 try:
1419 if opts.get('secret'):
1411 if opts.get('secret'):
1420 ui.setconfig('phases', 'new-commit', 'secret')
1412 ui.setconfig('phases', 'new-commit', 'secret')
1421
1413
1422 return repo.commit(message, opts.get('user'), opts.get('date'),
1414 return repo.commit(message, opts.get('user'), opts.get('date'),
1423 match, editor=e, extra=extra)
1415 match, editor=e, extra=extra)
1424 finally:
1416 finally:
1425 ui.setconfig('phases', 'new-commit', oldcommitphase)
1417 ui.setconfig('phases', 'new-commit', oldcommitphase)
1426
1418
1427
1419
1428 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1420 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1429
1421
1430 if not node:
1422 if not node:
1431 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1423 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1432 if stat[3]:
1424 if stat[3]:
1433 ui.status(_("nothing changed (%d missing files, see "
1425 ui.status(_("nothing changed (%d missing files, see "
1434 "'hg status')\n") % len(stat[3]))
1426 "'hg status')\n") % len(stat[3]))
1435 else:
1427 else:
1436 ui.status(_("nothing changed\n"))
1428 ui.status(_("nothing changed\n"))
1437 return 1
1429 return 1
1438
1430
1439 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1431 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1440
1432
1441 @command('copy|cp',
1433 @command('copy|cp',
1442 [('A', 'after', None, _('record a copy that has already occurred')),
1434 [('A', 'after', None, _('record a copy that has already occurred')),
1443 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1435 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1444 ] + walkopts + dryrunopts,
1436 ] + walkopts + dryrunopts,
1445 _('[OPTION]... [SOURCE]... DEST'))
1437 _('[OPTION]... [SOURCE]... DEST'))
1446 def copy(ui, repo, *pats, **opts):
1438 def copy(ui, repo, *pats, **opts):
1447 """mark files as copied for the next commit
1439 """mark files as copied for the next commit
1448
1440
1449 Mark dest as having copies of source files. If dest is a
1441 Mark dest as having copies of source files. If dest is a
1450 directory, copies are put in that directory. If dest is a file,
1442 directory, copies are put in that directory. If dest is a file,
1451 the source must be a single file.
1443 the source must be a single file.
1452
1444
1453 By default, this command copies the contents of files as they
1445 By default, this command copies the contents of files as they
1454 exist in the working directory. If invoked with -A/--after, the
1446 exist in the working directory. If invoked with -A/--after, the
1455 operation is recorded, but no copying is performed.
1447 operation is recorded, but no copying is performed.
1456
1448
1457 This command takes effect with the next commit. To undo a copy
1449 This command takes effect with the next commit. To undo a copy
1458 before that, see :hg:`revert`.
1450 before that, see :hg:`revert`.
1459
1451
1460 Returns 0 on success, 1 if errors are encountered.
1452 Returns 0 on success, 1 if errors are encountered.
1461 """
1453 """
1462 wlock = repo.wlock(False)
1454 wlock = repo.wlock(False)
1463 try:
1455 try:
1464 return cmdutil.copy(ui, repo, pats, opts)
1456 return cmdutil.copy(ui, repo, pats, opts)
1465 finally:
1457 finally:
1466 wlock.release()
1458 wlock.release()
1467
1459
1468 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1460 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1469 def debugancestor(ui, repo, *args):
1461 def debugancestor(ui, repo, *args):
1470 """find the ancestor revision of two revisions in a given index"""
1462 """find the ancestor revision of two revisions in a given index"""
1471 if len(args) == 3:
1463 if len(args) == 3:
1472 index, rev1, rev2 = args
1464 index, rev1, rev2 = args
1473 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1465 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1474 lookup = r.lookup
1466 lookup = r.lookup
1475 elif len(args) == 2:
1467 elif len(args) == 2:
1476 if not repo:
1468 if not repo:
1477 raise util.Abort(_("there is no Mercurial repository here "
1469 raise util.Abort(_("there is no Mercurial repository here "
1478 "(.hg not found)"))
1470 "(.hg not found)"))
1479 rev1, rev2 = args
1471 rev1, rev2 = args
1480 r = repo.changelog
1472 r = repo.changelog
1481 lookup = repo.lookup
1473 lookup = repo.lookup
1482 else:
1474 else:
1483 raise util.Abort(_('either two or three arguments required'))
1475 raise util.Abort(_('either two or three arguments required'))
1484 a = r.ancestor(lookup(rev1), lookup(rev2))
1476 a = r.ancestor(lookup(rev1), lookup(rev2))
1485 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1477 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1486
1478
1487 @command('debugbuilddag',
1479 @command('debugbuilddag',
1488 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1480 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1489 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1481 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1490 ('n', 'new-file', None, _('add new file at each rev'))],
1482 ('n', 'new-file', None, _('add new file at each rev'))],
1491 _('[OPTION]... [TEXT]'))
1483 _('[OPTION]... [TEXT]'))
1492 def debugbuilddag(ui, repo, text=None,
1484 def debugbuilddag(ui, repo, text=None,
1493 mergeable_file=False,
1485 mergeable_file=False,
1494 overwritten_file=False,
1486 overwritten_file=False,
1495 new_file=False):
1487 new_file=False):
1496 """builds a repo with a given DAG from scratch in the current empty repo
1488 """builds a repo with a given DAG from scratch in the current empty repo
1497
1489
1498 The description of the DAG is read from stdin if not given on the
1490 The description of the DAG is read from stdin if not given on the
1499 command line.
1491 command line.
1500
1492
1501 Elements:
1493 Elements:
1502
1494
1503 - "+n" is a linear run of n nodes based on the current default parent
1495 - "+n" is a linear run of n nodes based on the current default parent
1504 - "." is a single node based on the current default parent
1496 - "." is a single node based on the current default parent
1505 - "$" resets the default parent to null (implied at the start);
1497 - "$" resets the default parent to null (implied at the start);
1506 otherwise the default parent is always the last node created
1498 otherwise the default parent is always the last node created
1507 - "<p" sets the default parent to the backref p
1499 - "<p" sets the default parent to the backref p
1508 - "*p" is a fork at parent p, which is a backref
1500 - "*p" is a fork at parent p, which is a backref
1509 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1501 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1510 - "/p2" is a merge of the preceding node and p2
1502 - "/p2" is a merge of the preceding node and p2
1511 - ":tag" defines a local tag for the preceding node
1503 - ":tag" defines a local tag for the preceding node
1512 - "@branch" sets the named branch for subsequent nodes
1504 - "@branch" sets the named branch for subsequent nodes
1513 - "#...\\n" is a comment up to the end of the line
1505 - "#...\\n" is a comment up to the end of the line
1514
1506
1515 Whitespace between the above elements is ignored.
1507 Whitespace between the above elements is ignored.
1516
1508
1517 A backref is either
1509 A backref is either
1518
1510
1519 - a number n, which references the node curr-n, where curr is the current
1511 - a number n, which references the node curr-n, where curr is the current
1520 node, or
1512 node, or
1521 - the name of a local tag you placed earlier using ":tag", or
1513 - the name of a local tag you placed earlier using ":tag", or
1522 - empty to denote the default parent.
1514 - empty to denote the default parent.
1523
1515
1524 All string valued-elements are either strictly alphanumeric, or must
1516 All string valued-elements are either strictly alphanumeric, or must
1525 be enclosed in double quotes ("..."), with "\\" as escape character.
1517 be enclosed in double quotes ("..."), with "\\" as escape character.
1526 """
1518 """
1527
1519
1528 if text is None:
1520 if text is None:
1529 ui.status(_("reading DAG from stdin\n"))
1521 ui.status(_("reading DAG from stdin\n"))
1530 text = ui.fin.read()
1522 text = ui.fin.read()
1531
1523
1532 cl = repo.changelog
1524 cl = repo.changelog
1533 if len(cl) > 0:
1525 if len(cl) > 0:
1534 raise util.Abort(_('repository is not empty'))
1526 raise util.Abort(_('repository is not empty'))
1535
1527
1536 # determine number of revs in DAG
1528 # determine number of revs in DAG
1537 total = 0
1529 total = 0
1538 for type, data in dagparser.parsedag(text):
1530 for type, data in dagparser.parsedag(text):
1539 if type == 'n':
1531 if type == 'n':
1540 total += 1
1532 total += 1
1541
1533
1542 if mergeable_file:
1534 if mergeable_file:
1543 linesperrev = 2
1535 linesperrev = 2
1544 # make a file with k lines per rev
1536 # make a file with k lines per rev
1545 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1537 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1546 initialmergedlines.append("")
1538 initialmergedlines.append("")
1547
1539
1548 tags = []
1540 tags = []
1549
1541
1550 lock = tr = None
1542 lock = tr = None
1551 try:
1543 try:
1552 lock = repo.lock()
1544 lock = repo.lock()
1553 tr = repo.transaction("builddag")
1545 tr = repo.transaction("builddag")
1554
1546
1555 at = -1
1547 at = -1
1556 atbranch = 'default'
1548 atbranch = 'default'
1557 nodeids = []
1549 nodeids = []
1558 id = 0
1550 id = 0
1559 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1551 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1560 for type, data in dagparser.parsedag(text):
1552 for type, data in dagparser.parsedag(text):
1561 if type == 'n':
1553 if type == 'n':
1562 ui.note(('node %s\n' % str(data)))
1554 ui.note(('node %s\n' % str(data)))
1563 id, ps = data
1555 id, ps = data
1564
1556
1565 files = []
1557 files = []
1566 fctxs = {}
1558 fctxs = {}
1567
1559
1568 p2 = None
1560 p2 = None
1569 if mergeable_file:
1561 if mergeable_file:
1570 fn = "mf"
1562 fn = "mf"
1571 p1 = repo[ps[0]]
1563 p1 = repo[ps[0]]
1572 if len(ps) > 1:
1564 if len(ps) > 1:
1573 p2 = repo[ps[1]]
1565 p2 = repo[ps[1]]
1574 pa = p1.ancestor(p2)
1566 pa = p1.ancestor(p2)
1575 base, local, other = [x[fn].data() for x in (pa, p1,
1567 base, local, other = [x[fn].data() for x in (pa, p1,
1576 p2)]
1568 p2)]
1577 m3 = simplemerge.Merge3Text(base, local, other)
1569 m3 = simplemerge.Merge3Text(base, local, other)
1578 ml = [l.strip() for l in m3.merge_lines()]
1570 ml = [l.strip() for l in m3.merge_lines()]
1579 ml.append("")
1571 ml.append("")
1580 elif at > 0:
1572 elif at > 0:
1581 ml = p1[fn].data().split("\n")
1573 ml = p1[fn].data().split("\n")
1582 else:
1574 else:
1583 ml = initialmergedlines
1575 ml = initialmergedlines
1584 ml[id * linesperrev] += " r%i" % id
1576 ml[id * linesperrev] += " r%i" % id
1585 mergedtext = "\n".join(ml)
1577 mergedtext = "\n".join(ml)
1586 files.append(fn)
1578 files.append(fn)
1587 fctxs[fn] = context.memfilectx(fn, mergedtext)
1579 fctxs[fn] = context.memfilectx(fn, mergedtext)
1588
1580
1589 if overwritten_file:
1581 if overwritten_file:
1590 fn = "of"
1582 fn = "of"
1591 files.append(fn)
1583 files.append(fn)
1592 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1584 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1593
1585
1594 if new_file:
1586 if new_file:
1595 fn = "nf%i" % id
1587 fn = "nf%i" % id
1596 files.append(fn)
1588 files.append(fn)
1597 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1589 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1598 if len(ps) > 1:
1590 if len(ps) > 1:
1599 if not p2:
1591 if not p2:
1600 p2 = repo[ps[1]]
1592 p2 = repo[ps[1]]
1601 for fn in p2:
1593 for fn in p2:
1602 if fn.startswith("nf"):
1594 if fn.startswith("nf"):
1603 files.append(fn)
1595 files.append(fn)
1604 fctxs[fn] = p2[fn]
1596 fctxs[fn] = p2[fn]
1605
1597
1606 def fctxfn(repo, cx, path):
1598 def fctxfn(repo, cx, path):
1607 return fctxs.get(path)
1599 return fctxs.get(path)
1608
1600
1609 if len(ps) == 0 or ps[0] < 0:
1601 if len(ps) == 0 or ps[0] < 0:
1610 pars = [None, None]
1602 pars = [None, None]
1611 elif len(ps) == 1:
1603 elif len(ps) == 1:
1612 pars = [nodeids[ps[0]], None]
1604 pars = [nodeids[ps[0]], None]
1613 else:
1605 else:
1614 pars = [nodeids[p] for p in ps]
1606 pars = [nodeids[p] for p in ps]
1615 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1607 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1616 date=(id, 0),
1608 date=(id, 0),
1617 user="debugbuilddag",
1609 user="debugbuilddag",
1618 extra={'branch': atbranch})
1610 extra={'branch': atbranch})
1619 nodeid = repo.commitctx(cx)
1611 nodeid = repo.commitctx(cx)
1620 nodeids.append(nodeid)
1612 nodeids.append(nodeid)
1621 at = id
1613 at = id
1622 elif type == 'l':
1614 elif type == 'l':
1623 id, name = data
1615 id, name = data
1624 ui.note(('tag %s\n' % name))
1616 ui.note(('tag %s\n' % name))
1625 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1617 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1626 elif type == 'a':
1618 elif type == 'a':
1627 ui.note(('branch %s\n' % data))
1619 ui.note(('branch %s\n' % data))
1628 atbranch = data
1620 atbranch = data
1629 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1621 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1630 tr.close()
1622 tr.close()
1631
1623
1632 if tags:
1624 if tags:
1633 repo.opener.write("localtags", "".join(tags))
1625 repo.opener.write("localtags", "".join(tags))
1634 finally:
1626 finally:
1635 ui.progress(_('building'), None)
1627 ui.progress(_('building'), None)
1636 release(tr, lock)
1628 release(tr, lock)
1637
1629
1638 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1630 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1639 def debugbundle(ui, bundlepath, all=None, **opts):
1631 def debugbundle(ui, bundlepath, all=None, **opts):
1640 """lists the contents of a bundle"""
1632 """lists the contents of a bundle"""
1641 f = hg.openpath(ui, bundlepath)
1633 f = hg.openpath(ui, bundlepath)
1642 try:
1634 try:
1643 gen = changegroup.readbundle(f, bundlepath)
1635 gen = changegroup.readbundle(f, bundlepath)
1644 if all:
1636 if all:
1645 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1637 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1646
1638
1647 def showchunks(named):
1639 def showchunks(named):
1648 ui.write("\n%s\n" % named)
1640 ui.write("\n%s\n" % named)
1649 chain = None
1641 chain = None
1650 while True:
1642 while True:
1651 chunkdata = gen.deltachunk(chain)
1643 chunkdata = gen.deltachunk(chain)
1652 if not chunkdata:
1644 if not chunkdata:
1653 break
1645 break
1654 node = chunkdata['node']
1646 node = chunkdata['node']
1655 p1 = chunkdata['p1']
1647 p1 = chunkdata['p1']
1656 p2 = chunkdata['p2']
1648 p2 = chunkdata['p2']
1657 cs = chunkdata['cs']
1649 cs = chunkdata['cs']
1658 deltabase = chunkdata['deltabase']
1650 deltabase = chunkdata['deltabase']
1659 delta = chunkdata['delta']
1651 delta = chunkdata['delta']
1660 ui.write("%s %s %s %s %s %s\n" %
1652 ui.write("%s %s %s %s %s %s\n" %
1661 (hex(node), hex(p1), hex(p2),
1653 (hex(node), hex(p1), hex(p2),
1662 hex(cs), hex(deltabase), len(delta)))
1654 hex(cs), hex(deltabase), len(delta)))
1663 chain = node
1655 chain = node
1664
1656
1665 chunkdata = gen.changelogheader()
1657 chunkdata = gen.changelogheader()
1666 showchunks("changelog")
1658 showchunks("changelog")
1667 chunkdata = gen.manifestheader()
1659 chunkdata = gen.manifestheader()
1668 showchunks("manifest")
1660 showchunks("manifest")
1669 while True:
1661 while True:
1670 chunkdata = gen.filelogheader()
1662 chunkdata = gen.filelogheader()
1671 if not chunkdata:
1663 if not chunkdata:
1672 break
1664 break
1673 fname = chunkdata['filename']
1665 fname = chunkdata['filename']
1674 showchunks(fname)
1666 showchunks(fname)
1675 else:
1667 else:
1676 chunkdata = gen.changelogheader()
1668 chunkdata = gen.changelogheader()
1677 chain = None
1669 chain = None
1678 while True:
1670 while True:
1679 chunkdata = gen.deltachunk(chain)
1671 chunkdata = gen.deltachunk(chain)
1680 if not chunkdata:
1672 if not chunkdata:
1681 break
1673 break
1682 node = chunkdata['node']
1674 node = chunkdata['node']
1683 ui.write("%s\n" % hex(node))
1675 ui.write("%s\n" % hex(node))
1684 chain = node
1676 chain = node
1685 finally:
1677 finally:
1686 f.close()
1678 f.close()
1687
1679
1688 @command('debugcheckstate', [], '')
1680 @command('debugcheckstate', [], '')
1689 def debugcheckstate(ui, repo):
1681 def debugcheckstate(ui, repo):
1690 """validate the correctness of the current dirstate"""
1682 """validate the correctness of the current dirstate"""
1691 parent1, parent2 = repo.dirstate.parents()
1683 parent1, parent2 = repo.dirstate.parents()
1692 m1 = repo[parent1].manifest()
1684 m1 = repo[parent1].manifest()
1693 m2 = repo[parent2].manifest()
1685 m2 = repo[parent2].manifest()
1694 errors = 0
1686 errors = 0
1695 for f in repo.dirstate:
1687 for f in repo.dirstate:
1696 state = repo.dirstate[f]
1688 state = repo.dirstate[f]
1697 if state in "nr" and f not in m1:
1689 if state in "nr" and f not in m1:
1698 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1690 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1699 errors += 1
1691 errors += 1
1700 if state in "a" and f in m1:
1692 if state in "a" and f in m1:
1701 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1693 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1702 errors += 1
1694 errors += 1
1703 if state in "m" and f not in m1 and f not in m2:
1695 if state in "m" and f not in m1 and f not in m2:
1704 ui.warn(_("%s in state %s, but not in either manifest\n") %
1696 ui.warn(_("%s in state %s, but not in either manifest\n") %
1705 (f, state))
1697 (f, state))
1706 errors += 1
1698 errors += 1
1707 for f in m1:
1699 for f in m1:
1708 state = repo.dirstate[f]
1700 state = repo.dirstate[f]
1709 if state not in "nrm":
1701 if state not in "nrm":
1710 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1702 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1711 errors += 1
1703 errors += 1
1712 if errors:
1704 if errors:
1713 error = _(".hg/dirstate inconsistent with current parent's manifest")
1705 error = _(".hg/dirstate inconsistent with current parent's manifest")
1714 raise util.Abort(error)
1706 raise util.Abort(error)
1715
1707
1716 @command('debugcommands', [], _('[COMMAND]'))
1708 @command('debugcommands', [], _('[COMMAND]'))
1717 def debugcommands(ui, cmd='', *args):
1709 def debugcommands(ui, cmd='', *args):
1718 """list all available commands and options"""
1710 """list all available commands and options"""
1719 for cmd, vals in sorted(table.iteritems()):
1711 for cmd, vals in sorted(table.iteritems()):
1720 cmd = cmd.split('|')[0].strip('^')
1712 cmd = cmd.split('|')[0].strip('^')
1721 opts = ', '.join([i[1] for i in vals[1]])
1713 opts = ', '.join([i[1] for i in vals[1]])
1722 ui.write('%s: %s\n' % (cmd, opts))
1714 ui.write('%s: %s\n' % (cmd, opts))
1723
1715
1724 @command('debugcomplete',
1716 @command('debugcomplete',
1725 [('o', 'options', None, _('show the command options'))],
1717 [('o', 'options', None, _('show the command options'))],
1726 _('[-o] CMD'))
1718 _('[-o] CMD'))
1727 def debugcomplete(ui, cmd='', **opts):
1719 def debugcomplete(ui, cmd='', **opts):
1728 """returns the completion list associated with the given command"""
1720 """returns the completion list associated with the given command"""
1729
1721
1730 if opts.get('options'):
1722 if opts.get('options'):
1731 options = []
1723 options = []
1732 otables = [globalopts]
1724 otables = [globalopts]
1733 if cmd:
1725 if cmd:
1734 aliases, entry = cmdutil.findcmd(cmd, table, False)
1726 aliases, entry = cmdutil.findcmd(cmd, table, False)
1735 otables.append(entry[1])
1727 otables.append(entry[1])
1736 for t in otables:
1728 for t in otables:
1737 for o in t:
1729 for o in t:
1738 if "(DEPRECATED)" in o[3]:
1730 if "(DEPRECATED)" in o[3]:
1739 continue
1731 continue
1740 if o[0]:
1732 if o[0]:
1741 options.append('-%s' % o[0])
1733 options.append('-%s' % o[0])
1742 options.append('--%s' % o[1])
1734 options.append('--%s' % o[1])
1743 ui.write("%s\n" % "\n".join(options))
1735 ui.write("%s\n" % "\n".join(options))
1744 return
1736 return
1745
1737
1746 cmdlist = cmdutil.findpossible(cmd, table)
1738 cmdlist = cmdutil.findpossible(cmd, table)
1747 if ui.verbose:
1739 if ui.verbose:
1748 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1740 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1749 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1741 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1750
1742
1751 @command('debugdag',
1743 @command('debugdag',
1752 [('t', 'tags', None, _('use tags as labels')),
1744 [('t', 'tags', None, _('use tags as labels')),
1753 ('b', 'branches', None, _('annotate with branch names')),
1745 ('b', 'branches', None, _('annotate with branch names')),
1754 ('', 'dots', None, _('use dots for runs')),
1746 ('', 'dots', None, _('use dots for runs')),
1755 ('s', 'spaces', None, _('separate elements by spaces'))],
1747 ('s', 'spaces', None, _('separate elements by spaces'))],
1756 _('[OPTION]... [FILE [REV]...]'))
1748 _('[OPTION]... [FILE [REV]...]'))
1757 def debugdag(ui, repo, file_=None, *revs, **opts):
1749 def debugdag(ui, repo, file_=None, *revs, **opts):
1758 """format the changelog or an index DAG as a concise textual description
1750 """format the changelog or an index DAG as a concise textual description
1759
1751
1760 If you pass a revlog index, the revlog's DAG is emitted. If you list
1752 If you pass a revlog index, the revlog's DAG is emitted. If you list
1761 revision numbers, they get labeled in the output as rN.
1753 revision numbers, they get labeled in the output as rN.
1762
1754
1763 Otherwise, the changelog DAG of the current repo is emitted.
1755 Otherwise, the changelog DAG of the current repo is emitted.
1764 """
1756 """
1765 spaces = opts.get('spaces')
1757 spaces = opts.get('spaces')
1766 dots = opts.get('dots')
1758 dots = opts.get('dots')
1767 if file_:
1759 if file_:
1768 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1760 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1769 revs = set((int(r) for r in revs))
1761 revs = set((int(r) for r in revs))
1770 def events():
1762 def events():
1771 for r in rlog:
1763 for r in rlog:
1772 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1764 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1773 if p != -1)))
1765 if p != -1)))
1774 if r in revs:
1766 if r in revs:
1775 yield 'l', (r, "r%i" % r)
1767 yield 'l', (r, "r%i" % r)
1776 elif repo:
1768 elif repo:
1777 cl = repo.changelog
1769 cl = repo.changelog
1778 tags = opts.get('tags')
1770 tags = opts.get('tags')
1779 branches = opts.get('branches')
1771 branches = opts.get('branches')
1780 if tags:
1772 if tags:
1781 labels = {}
1773 labels = {}
1782 for l, n in repo.tags().items():
1774 for l, n in repo.tags().items():
1783 labels.setdefault(cl.rev(n), []).append(l)
1775 labels.setdefault(cl.rev(n), []).append(l)
1784 def events():
1776 def events():
1785 b = "default"
1777 b = "default"
1786 for r in cl:
1778 for r in cl:
1787 if branches:
1779 if branches:
1788 newb = cl.read(cl.node(r))[5]['branch']
1780 newb = cl.read(cl.node(r))[5]['branch']
1789 if newb != b:
1781 if newb != b:
1790 yield 'a', newb
1782 yield 'a', newb
1791 b = newb
1783 b = newb
1792 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1784 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1793 if p != -1)))
1785 if p != -1)))
1794 if tags:
1786 if tags:
1795 ls = labels.get(r)
1787 ls = labels.get(r)
1796 if ls:
1788 if ls:
1797 for l in ls:
1789 for l in ls:
1798 yield 'l', (r, l)
1790 yield 'l', (r, l)
1799 else:
1791 else:
1800 raise util.Abort(_('need repo for changelog dag'))
1792 raise util.Abort(_('need repo for changelog dag'))
1801
1793
1802 for line in dagparser.dagtextlines(events(),
1794 for line in dagparser.dagtextlines(events(),
1803 addspaces=spaces,
1795 addspaces=spaces,
1804 wraplabels=True,
1796 wraplabels=True,
1805 wrapannotations=True,
1797 wrapannotations=True,
1806 wrapnonlinear=dots,
1798 wrapnonlinear=dots,
1807 usedots=dots,
1799 usedots=dots,
1808 maxlinewidth=70):
1800 maxlinewidth=70):
1809 ui.write(line)
1801 ui.write(line)
1810 ui.write("\n")
1802 ui.write("\n")
1811
1803
1812 @command('debugdata',
1804 @command('debugdata',
1813 [('c', 'changelog', False, _('open changelog')),
1805 [('c', 'changelog', False, _('open changelog')),
1814 ('m', 'manifest', False, _('open manifest'))],
1806 ('m', 'manifest', False, _('open manifest'))],
1815 _('-c|-m|FILE REV'))
1807 _('-c|-m|FILE REV'))
1816 def debugdata(ui, repo, file_, rev=None, **opts):
1808 def debugdata(ui, repo, file_, rev=None, **opts):
1817 """dump the contents of a data file revision"""
1809 """dump the contents of a data file revision"""
1818 if opts.get('changelog') or opts.get('manifest'):
1810 if opts.get('changelog') or opts.get('manifest'):
1819 file_, rev = None, file_
1811 file_, rev = None, file_
1820 elif rev is None:
1812 elif rev is None:
1821 raise error.CommandError('debugdata', _('invalid arguments'))
1813 raise error.CommandError('debugdata', _('invalid arguments'))
1822 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1814 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1823 try:
1815 try:
1824 ui.write(r.revision(r.lookup(rev)))
1816 ui.write(r.revision(r.lookup(rev)))
1825 except KeyError:
1817 except KeyError:
1826 raise util.Abort(_('invalid revision identifier %s') % rev)
1818 raise util.Abort(_('invalid revision identifier %s') % rev)
1827
1819
1828 @command('debugdate',
1820 @command('debugdate',
1829 [('e', 'extended', None, _('try extended date formats'))],
1821 [('e', 'extended', None, _('try extended date formats'))],
1830 _('[-e] DATE [RANGE]'))
1822 _('[-e] DATE [RANGE]'))
1831 def debugdate(ui, date, range=None, **opts):
1823 def debugdate(ui, date, range=None, **opts):
1832 """parse and display a date"""
1824 """parse and display a date"""
1833 if opts["extended"]:
1825 if opts["extended"]:
1834 d = util.parsedate(date, util.extendeddateformats)
1826 d = util.parsedate(date, util.extendeddateformats)
1835 else:
1827 else:
1836 d = util.parsedate(date)
1828 d = util.parsedate(date)
1837 ui.write(("internal: %s %s\n") % d)
1829 ui.write(("internal: %s %s\n") % d)
1838 ui.write(("standard: %s\n") % util.datestr(d))
1830 ui.write(("standard: %s\n") % util.datestr(d))
1839 if range:
1831 if range:
1840 m = util.matchdate(range)
1832 m = util.matchdate(range)
1841 ui.write(("match: %s\n") % m(d[0]))
1833 ui.write(("match: %s\n") % m(d[0]))
1842
1834
1843 @command('debugdiscovery',
1835 @command('debugdiscovery',
1844 [('', 'old', None, _('use old-style discovery')),
1836 [('', 'old', None, _('use old-style discovery')),
1845 ('', 'nonheads', None,
1837 ('', 'nonheads', None,
1846 _('use old-style discovery with non-heads included')),
1838 _('use old-style discovery with non-heads included')),
1847 ] + remoteopts,
1839 ] + remoteopts,
1848 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1840 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1849 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1841 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1850 """runs the changeset discovery protocol in isolation"""
1842 """runs the changeset discovery protocol in isolation"""
1851 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1843 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1852 opts.get('branch'))
1844 opts.get('branch'))
1853 remote = hg.peer(repo, opts, remoteurl)
1845 remote = hg.peer(repo, opts, remoteurl)
1854 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1846 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1855
1847
1856 # make sure tests are repeatable
1848 # make sure tests are repeatable
1857 random.seed(12323)
1849 random.seed(12323)
1858
1850
1859 def doit(localheads, remoteheads, remote=remote):
1851 def doit(localheads, remoteheads, remote=remote):
1860 if opts.get('old'):
1852 if opts.get('old'):
1861 if localheads:
1853 if localheads:
1862 raise util.Abort('cannot use localheads with old style '
1854 raise util.Abort('cannot use localheads with old style '
1863 'discovery')
1855 'discovery')
1864 if not util.safehasattr(remote, 'branches'):
1856 if not util.safehasattr(remote, 'branches'):
1865 # enable in-client legacy support
1857 # enable in-client legacy support
1866 remote = localrepo.locallegacypeer(remote.local())
1858 remote = localrepo.locallegacypeer(remote.local())
1867 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1859 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1868 force=True)
1860 force=True)
1869 common = set(common)
1861 common = set(common)
1870 if not opts.get('nonheads'):
1862 if not opts.get('nonheads'):
1871 ui.write(("unpruned common: %s\n") %
1863 ui.write(("unpruned common: %s\n") %
1872 " ".join(sorted(short(n) for n in common)))
1864 " ".join(sorted(short(n) for n in common)))
1873 dag = dagutil.revlogdag(repo.changelog)
1865 dag = dagutil.revlogdag(repo.changelog)
1874 all = dag.ancestorset(dag.internalizeall(common))
1866 all = dag.ancestorset(dag.internalizeall(common))
1875 common = dag.externalizeall(dag.headsetofconnecteds(all))
1867 common = dag.externalizeall(dag.headsetofconnecteds(all))
1876 else:
1868 else:
1877 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1869 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1878 common = set(common)
1870 common = set(common)
1879 rheads = set(hds)
1871 rheads = set(hds)
1880 lheads = set(repo.heads())
1872 lheads = set(repo.heads())
1881 ui.write(("common heads: %s\n") %
1873 ui.write(("common heads: %s\n") %
1882 " ".join(sorted(short(n) for n in common)))
1874 " ".join(sorted(short(n) for n in common)))
1883 if lheads <= common:
1875 if lheads <= common:
1884 ui.write(("local is subset\n"))
1876 ui.write(("local is subset\n"))
1885 elif rheads <= common:
1877 elif rheads <= common:
1886 ui.write(("remote is subset\n"))
1878 ui.write(("remote is subset\n"))
1887
1879
1888 serverlogs = opts.get('serverlog')
1880 serverlogs = opts.get('serverlog')
1889 if serverlogs:
1881 if serverlogs:
1890 for filename in serverlogs:
1882 for filename in serverlogs:
1891 logfile = open(filename, 'r')
1883 logfile = open(filename, 'r')
1892 try:
1884 try:
1893 line = logfile.readline()
1885 line = logfile.readline()
1894 while line:
1886 while line:
1895 parts = line.strip().split(';')
1887 parts = line.strip().split(';')
1896 op = parts[1]
1888 op = parts[1]
1897 if op == 'cg':
1889 if op == 'cg':
1898 pass
1890 pass
1899 elif op == 'cgss':
1891 elif op == 'cgss':
1900 doit(parts[2].split(' '), parts[3].split(' '))
1892 doit(parts[2].split(' '), parts[3].split(' '))
1901 elif op == 'unb':
1893 elif op == 'unb':
1902 doit(parts[3].split(' '), parts[2].split(' '))
1894 doit(parts[3].split(' '), parts[2].split(' '))
1903 line = logfile.readline()
1895 line = logfile.readline()
1904 finally:
1896 finally:
1905 logfile.close()
1897 logfile.close()
1906
1898
1907 else:
1899 else:
1908 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1900 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1909 opts.get('remote_head'))
1901 opts.get('remote_head'))
1910 localrevs = opts.get('local_head')
1902 localrevs = opts.get('local_head')
1911 doit(localrevs, remoterevs)
1903 doit(localrevs, remoterevs)
1912
1904
1913 @command('debugfileset',
1905 @command('debugfileset',
1914 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1906 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1915 _('[-r REV] FILESPEC'))
1907 _('[-r REV] FILESPEC'))
1916 def debugfileset(ui, repo, expr, **opts):
1908 def debugfileset(ui, repo, expr, **opts):
1917 '''parse and apply a fileset specification'''
1909 '''parse and apply a fileset specification'''
1918 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1910 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1919 if ui.verbose:
1911 if ui.verbose:
1920 tree = fileset.parse(expr)[0]
1912 tree = fileset.parse(expr)[0]
1921 ui.note(tree, "\n")
1913 ui.note(tree, "\n")
1922
1914
1923 for f in fileset.getfileset(ctx, expr):
1915 for f in fileset.getfileset(ctx, expr):
1924 ui.write("%s\n" % f)
1916 ui.write("%s\n" % f)
1925
1917
1926 @command('debugfsinfo', [], _('[PATH]'))
1918 @command('debugfsinfo', [], _('[PATH]'))
1927 def debugfsinfo(ui, path="."):
1919 def debugfsinfo(ui, path="."):
1928 """show information detected about current filesystem"""
1920 """show information detected about current filesystem"""
1929 util.writefile('.debugfsinfo', '')
1921 util.writefile('.debugfsinfo', '')
1930 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1922 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1931 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1923 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1932 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1924 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1933 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1925 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1934 and 'yes' or 'no'))
1926 and 'yes' or 'no'))
1935 os.unlink('.debugfsinfo')
1927 os.unlink('.debugfsinfo')
1936
1928
1937 @command('debuggetbundle',
1929 @command('debuggetbundle',
1938 [('H', 'head', [], _('id of head node'), _('ID')),
1930 [('H', 'head', [], _('id of head node'), _('ID')),
1939 ('C', 'common', [], _('id of common node'), _('ID')),
1931 ('C', 'common', [], _('id of common node'), _('ID')),
1940 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1932 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1941 _('REPO FILE [-H|-C ID]...'))
1933 _('REPO FILE [-H|-C ID]...'))
1942 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1934 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1943 """retrieves a bundle from a repo
1935 """retrieves a bundle from a repo
1944
1936
1945 Every ID must be a full-length hex node id string. Saves the bundle to the
1937 Every ID must be a full-length hex node id string. Saves the bundle to the
1946 given file.
1938 given file.
1947 """
1939 """
1948 repo = hg.peer(ui, opts, repopath)
1940 repo = hg.peer(ui, opts, repopath)
1949 if not repo.capable('getbundle'):
1941 if not repo.capable('getbundle'):
1950 raise util.Abort("getbundle() not supported by target repository")
1942 raise util.Abort("getbundle() not supported by target repository")
1951 args = {}
1943 args = {}
1952 if common:
1944 if common:
1953 args['common'] = [bin(s) for s in common]
1945 args['common'] = [bin(s) for s in common]
1954 if head:
1946 if head:
1955 args['heads'] = [bin(s) for s in head]
1947 args['heads'] = [bin(s) for s in head]
1956 # TODO: get desired bundlecaps from command line.
1948 # TODO: get desired bundlecaps from command line.
1957 args['bundlecaps'] = None
1949 args['bundlecaps'] = None
1958 bundle = repo.getbundle('debug', **args)
1950 bundle = repo.getbundle('debug', **args)
1959
1951
1960 bundletype = opts.get('type', 'bzip2').lower()
1952 bundletype = opts.get('type', 'bzip2').lower()
1961 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1953 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1962 bundletype = btypes.get(bundletype)
1954 bundletype = btypes.get(bundletype)
1963 if bundletype not in changegroup.bundletypes:
1955 if bundletype not in changegroup.bundletypes:
1964 raise util.Abort(_('unknown bundle type specified with --type'))
1956 raise util.Abort(_('unknown bundle type specified with --type'))
1965 changegroup.writebundle(bundle, bundlepath, bundletype)
1957 changegroup.writebundle(bundle, bundlepath, bundletype)
1966
1958
1967 @command('debugignore', [], '')
1959 @command('debugignore', [], '')
1968 def debugignore(ui, repo, *values, **opts):
1960 def debugignore(ui, repo, *values, **opts):
1969 """display the combined ignore pattern"""
1961 """display the combined ignore pattern"""
1970 ignore = repo.dirstate._ignore
1962 ignore = repo.dirstate._ignore
1971 includepat = getattr(ignore, 'includepat', None)
1963 includepat = getattr(ignore, 'includepat', None)
1972 if includepat is not None:
1964 if includepat is not None:
1973 ui.write("%s\n" % includepat)
1965 ui.write("%s\n" % includepat)
1974 else:
1966 else:
1975 raise util.Abort(_("no ignore patterns found"))
1967 raise util.Abort(_("no ignore patterns found"))
1976
1968
1977 @command('debugindex',
1969 @command('debugindex',
1978 [('c', 'changelog', False, _('open changelog')),
1970 [('c', 'changelog', False, _('open changelog')),
1979 ('m', 'manifest', False, _('open manifest')),
1971 ('m', 'manifest', False, _('open manifest')),
1980 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1972 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1981 _('[-f FORMAT] -c|-m|FILE'))
1973 _('[-f FORMAT] -c|-m|FILE'))
1982 def debugindex(ui, repo, file_=None, **opts):
1974 def debugindex(ui, repo, file_=None, **opts):
1983 """dump the contents of an index file"""
1975 """dump the contents of an index file"""
1984 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1976 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1985 format = opts.get('format', 0)
1977 format = opts.get('format', 0)
1986 if format not in (0, 1):
1978 if format not in (0, 1):
1987 raise util.Abort(_("unknown format %d") % format)
1979 raise util.Abort(_("unknown format %d") % format)
1988
1980
1989 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1981 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1990 if generaldelta:
1982 if generaldelta:
1991 basehdr = ' delta'
1983 basehdr = ' delta'
1992 else:
1984 else:
1993 basehdr = ' base'
1985 basehdr = ' base'
1994
1986
1995 if format == 0:
1987 if format == 0:
1996 ui.write(" rev offset length " + basehdr + " linkrev"
1988 ui.write(" rev offset length " + basehdr + " linkrev"
1997 " nodeid p1 p2\n")
1989 " nodeid p1 p2\n")
1998 elif format == 1:
1990 elif format == 1:
1999 ui.write(" rev flag offset length"
1991 ui.write(" rev flag offset length"
2000 " size " + basehdr + " link p1 p2"
1992 " size " + basehdr + " link p1 p2"
2001 " nodeid\n")
1993 " nodeid\n")
2002
1994
2003 for i in r:
1995 for i in r:
2004 node = r.node(i)
1996 node = r.node(i)
2005 if generaldelta:
1997 if generaldelta:
2006 base = r.deltaparent(i)
1998 base = r.deltaparent(i)
2007 else:
1999 else:
2008 base = r.chainbase(i)
2000 base = r.chainbase(i)
2009 if format == 0:
2001 if format == 0:
2010 try:
2002 try:
2011 pp = r.parents(node)
2003 pp = r.parents(node)
2012 except Exception:
2004 except Exception:
2013 pp = [nullid, nullid]
2005 pp = [nullid, nullid]
2014 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2006 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2015 i, r.start(i), r.length(i), base, r.linkrev(i),
2007 i, r.start(i), r.length(i), base, r.linkrev(i),
2016 short(node), short(pp[0]), short(pp[1])))
2008 short(node), short(pp[0]), short(pp[1])))
2017 elif format == 1:
2009 elif format == 1:
2018 pr = r.parentrevs(i)
2010 pr = r.parentrevs(i)
2019 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2011 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2020 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2012 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2021 base, r.linkrev(i), pr[0], pr[1], short(node)))
2013 base, r.linkrev(i), pr[0], pr[1], short(node)))
2022
2014
2023 @command('debugindexdot', [], _('FILE'))
2015 @command('debugindexdot', [], _('FILE'))
2024 def debugindexdot(ui, repo, file_):
2016 def debugindexdot(ui, repo, file_):
2025 """dump an index DAG as a graphviz dot file"""
2017 """dump an index DAG as a graphviz dot file"""
2026 r = None
2018 r = None
2027 if repo:
2019 if repo:
2028 filelog = repo.file(file_)
2020 filelog = repo.file(file_)
2029 if len(filelog):
2021 if len(filelog):
2030 r = filelog
2022 r = filelog
2031 if not r:
2023 if not r:
2032 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2024 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2033 ui.write(("digraph G {\n"))
2025 ui.write(("digraph G {\n"))
2034 for i in r:
2026 for i in r:
2035 node = r.node(i)
2027 node = r.node(i)
2036 pp = r.parents(node)
2028 pp = r.parents(node)
2037 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2029 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2038 if pp[1] != nullid:
2030 if pp[1] != nullid:
2039 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2031 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2040 ui.write("}\n")
2032 ui.write("}\n")
2041
2033
2042 @command('debuginstall', [], '')
2034 @command('debuginstall', [], '')
2043 def debuginstall(ui):
2035 def debuginstall(ui):
2044 '''test Mercurial installation
2036 '''test Mercurial installation
2045
2037
2046 Returns 0 on success.
2038 Returns 0 on success.
2047 '''
2039 '''
2048
2040
2049 def writetemp(contents):
2041 def writetemp(contents):
2050 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2042 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2051 f = os.fdopen(fd, "wb")
2043 f = os.fdopen(fd, "wb")
2052 f.write(contents)
2044 f.write(contents)
2053 f.close()
2045 f.close()
2054 return name
2046 return name
2055
2047
2056 problems = 0
2048 problems = 0
2057
2049
2058 # encoding
2050 # encoding
2059 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2051 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2060 try:
2052 try:
2061 encoding.fromlocal("test")
2053 encoding.fromlocal("test")
2062 except util.Abort, inst:
2054 except util.Abort, inst:
2063 ui.write(" %s\n" % inst)
2055 ui.write(" %s\n" % inst)
2064 ui.write(_(" (check that your locale is properly set)\n"))
2056 ui.write(_(" (check that your locale is properly set)\n"))
2065 problems += 1
2057 problems += 1
2066
2058
2067 # Python lib
2059 # Python lib
2068 ui.status(_("checking Python lib (%s)...\n")
2060 ui.status(_("checking Python lib (%s)...\n")
2069 % os.path.dirname(os.__file__))
2061 % os.path.dirname(os.__file__))
2070
2062
2071 # compiled modules
2063 # compiled modules
2072 ui.status(_("checking installed modules (%s)...\n")
2064 ui.status(_("checking installed modules (%s)...\n")
2073 % os.path.dirname(__file__))
2065 % os.path.dirname(__file__))
2074 try:
2066 try:
2075 import bdiff, mpatch, base85, osutil
2067 import bdiff, mpatch, base85, osutil
2076 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2068 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2077 except Exception, inst:
2069 except Exception, inst:
2078 ui.write(" %s\n" % inst)
2070 ui.write(" %s\n" % inst)
2079 ui.write(_(" One or more extensions could not be found"))
2071 ui.write(_(" One or more extensions could not be found"))
2080 ui.write(_(" (check that you compiled the extensions)\n"))
2072 ui.write(_(" (check that you compiled the extensions)\n"))
2081 problems += 1
2073 problems += 1
2082
2074
2083 # templates
2075 # templates
2084 import templater
2076 import templater
2085 p = templater.templatepath()
2077 p = templater.templatepath()
2086 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2078 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2087 try:
2079 try:
2088 templater.templater(templater.templatepath("map-cmdline.default"))
2080 templater.templater(templater.templatepath("map-cmdline.default"))
2089 except Exception, inst:
2081 except Exception, inst:
2090 ui.write(" %s\n" % inst)
2082 ui.write(" %s\n" % inst)
2091 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2083 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2092 problems += 1
2084 problems += 1
2093
2085
2094 # editor
2086 # editor
2095 ui.status(_("checking commit editor...\n"))
2087 ui.status(_("checking commit editor...\n"))
2096 editor = ui.geteditor()
2088 editor = ui.geteditor()
2097 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2089 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2098 if not cmdpath:
2090 if not cmdpath:
2099 if editor == 'vi':
2091 if editor == 'vi':
2100 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2092 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2101 ui.write(_(" (specify a commit editor in your configuration"
2093 ui.write(_(" (specify a commit editor in your configuration"
2102 " file)\n"))
2094 " file)\n"))
2103 else:
2095 else:
2104 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2096 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2105 ui.write(_(" (specify a commit editor in your configuration"
2097 ui.write(_(" (specify a commit editor in your configuration"
2106 " file)\n"))
2098 " file)\n"))
2107 problems += 1
2099 problems += 1
2108
2100
2109 # check username
2101 # check username
2110 ui.status(_("checking username...\n"))
2102 ui.status(_("checking username...\n"))
2111 try:
2103 try:
2112 ui.username()
2104 ui.username()
2113 except util.Abort, e:
2105 except util.Abort, e:
2114 ui.write(" %s\n" % e)
2106 ui.write(" %s\n" % e)
2115 ui.write(_(" (specify a username in your configuration file)\n"))
2107 ui.write(_(" (specify a username in your configuration file)\n"))
2116 problems += 1
2108 problems += 1
2117
2109
2118 if not problems:
2110 if not problems:
2119 ui.status(_("no problems detected\n"))
2111 ui.status(_("no problems detected\n"))
2120 else:
2112 else:
2121 ui.write(_("%s problems detected,"
2113 ui.write(_("%s problems detected,"
2122 " please check your install!\n") % problems)
2114 " please check your install!\n") % problems)
2123
2115
2124 return problems
2116 return problems
2125
2117
2126 @command('debugknown', [], _('REPO ID...'))
2118 @command('debugknown', [], _('REPO ID...'))
2127 def debugknown(ui, repopath, *ids, **opts):
2119 def debugknown(ui, repopath, *ids, **opts):
2128 """test whether node ids are known to a repo
2120 """test whether node ids are known to a repo
2129
2121
2130 Every ID must be a full-length hex node id string. Returns a list of 0s
2122 Every ID must be a full-length hex node id string. Returns a list of 0s
2131 and 1s indicating unknown/known.
2123 and 1s indicating unknown/known.
2132 """
2124 """
2133 repo = hg.peer(ui, opts, repopath)
2125 repo = hg.peer(ui, opts, repopath)
2134 if not repo.capable('known'):
2126 if not repo.capable('known'):
2135 raise util.Abort("known() not supported by target repository")
2127 raise util.Abort("known() not supported by target repository")
2136 flags = repo.known([bin(s) for s in ids])
2128 flags = repo.known([bin(s) for s in ids])
2137 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2129 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2138
2130
2139 @command('debuglabelcomplete', [], _('LABEL...'))
2131 @command('debuglabelcomplete', [], _('LABEL...'))
2140 def debuglabelcomplete(ui, repo, *args):
2132 def debuglabelcomplete(ui, repo, *args):
2141 '''complete "labels" - tags, open branch names, bookmark names'''
2133 '''complete "labels" - tags, open branch names, bookmark names'''
2142
2134
2143 labels = set()
2135 labels = set()
2144 labels.update(t[0] for t in repo.tagslist())
2136 labels.update(t[0] for t in repo.tagslist())
2145 labels.update(repo._bookmarks.keys())
2137 labels.update(repo._bookmarks.keys())
2146 labels.update(tag for (tag, heads, tip, closed)
2138 labels.update(tag for (tag, heads, tip, closed)
2147 in repo.branchmap().iterbranches() if not closed)
2139 in repo.branchmap().iterbranches() if not closed)
2148 completions = set()
2140 completions = set()
2149 if not args:
2141 if not args:
2150 args = ['']
2142 args = ['']
2151 for a in args:
2143 for a in args:
2152 completions.update(l for l in labels if l.startswith(a))
2144 completions.update(l for l in labels if l.startswith(a))
2153 ui.write('\n'.join(sorted(completions)))
2145 ui.write('\n'.join(sorted(completions)))
2154 ui.write('\n')
2146 ui.write('\n')
2155
2147
2156 @command('debugobsolete',
2148 @command('debugobsolete',
2157 [('', 'flags', 0, _('markers flag')),
2149 [('', 'flags', 0, _('markers flag')),
2158 ] + commitopts2,
2150 ] + commitopts2,
2159 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2151 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2160 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2152 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2161 """create arbitrary obsolete marker
2153 """create arbitrary obsolete marker
2162
2154
2163 With no arguments, displays the list of obsolescence markers."""
2155 With no arguments, displays the list of obsolescence markers."""
2164 def parsenodeid(s):
2156 def parsenodeid(s):
2165 try:
2157 try:
2166 # We do not use revsingle/revrange functions here to accept
2158 # We do not use revsingle/revrange functions here to accept
2167 # arbitrary node identifiers, possibly not present in the
2159 # arbitrary node identifiers, possibly not present in the
2168 # local repository.
2160 # local repository.
2169 n = bin(s)
2161 n = bin(s)
2170 if len(n) != len(nullid):
2162 if len(n) != len(nullid):
2171 raise TypeError()
2163 raise TypeError()
2172 return n
2164 return n
2173 except TypeError:
2165 except TypeError:
2174 raise util.Abort('changeset references must be full hexadecimal '
2166 raise util.Abort('changeset references must be full hexadecimal '
2175 'node identifiers')
2167 'node identifiers')
2176
2168
2177 if precursor is not None:
2169 if precursor is not None:
2178 metadata = {}
2170 metadata = {}
2179 if 'date' in opts:
2171 if 'date' in opts:
2180 metadata['date'] = opts['date']
2172 metadata['date'] = opts['date']
2181 metadata['user'] = opts['user'] or ui.username()
2173 metadata['user'] = opts['user'] or ui.username()
2182 succs = tuple(parsenodeid(succ) for succ in successors)
2174 succs = tuple(parsenodeid(succ) for succ in successors)
2183 l = repo.lock()
2175 l = repo.lock()
2184 try:
2176 try:
2185 tr = repo.transaction('debugobsolete')
2177 tr = repo.transaction('debugobsolete')
2186 try:
2178 try:
2187 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2179 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2188 opts['flags'], metadata)
2180 opts['flags'], metadata)
2189 tr.close()
2181 tr.close()
2190 finally:
2182 finally:
2191 tr.release()
2183 tr.release()
2192 finally:
2184 finally:
2193 l.release()
2185 l.release()
2194 else:
2186 else:
2195 for m in obsolete.allmarkers(repo):
2187 for m in obsolete.allmarkers(repo):
2196 ui.write(hex(m.precnode()))
2188 ui.write(hex(m.precnode()))
2197 for repl in m.succnodes():
2189 for repl in m.succnodes():
2198 ui.write(' ')
2190 ui.write(' ')
2199 ui.write(hex(repl))
2191 ui.write(hex(repl))
2200 ui.write(' %X ' % m._data[2])
2192 ui.write(' %X ' % m._data[2])
2201 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2193 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2202 sorted(m.metadata().items()))))
2194 sorted(m.metadata().items()))))
2203 ui.write('\n')
2195 ui.write('\n')
2204
2196
2205 @command('debugpathcomplete',
2197 @command('debugpathcomplete',
2206 [('f', 'full', None, _('complete an entire path')),
2198 [('f', 'full', None, _('complete an entire path')),
2207 ('n', 'normal', None, _('show only normal files')),
2199 ('n', 'normal', None, _('show only normal files')),
2208 ('a', 'added', None, _('show only added files')),
2200 ('a', 'added', None, _('show only added files')),
2209 ('r', 'removed', None, _('show only removed files'))],
2201 ('r', 'removed', None, _('show only removed files'))],
2210 _('FILESPEC...'))
2202 _('FILESPEC...'))
2211 def debugpathcomplete(ui, repo, *specs, **opts):
2203 def debugpathcomplete(ui, repo, *specs, **opts):
2212 '''complete part or all of a tracked path
2204 '''complete part or all of a tracked path
2213
2205
2214 This command supports shells that offer path name completion. It
2206 This command supports shells that offer path name completion. It
2215 currently completes only files already known to the dirstate.
2207 currently completes only files already known to the dirstate.
2216
2208
2217 Completion extends only to the next path segment unless
2209 Completion extends only to the next path segment unless
2218 --full is specified, in which case entire paths are used.'''
2210 --full is specified, in which case entire paths are used.'''
2219
2211
2220 def complete(path, acceptable):
2212 def complete(path, acceptable):
2221 dirstate = repo.dirstate
2213 dirstate = repo.dirstate
2222 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2214 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2223 rootdir = repo.root + os.sep
2215 rootdir = repo.root + os.sep
2224 if spec != repo.root and not spec.startswith(rootdir):
2216 if spec != repo.root and not spec.startswith(rootdir):
2225 return [], []
2217 return [], []
2226 if os.path.isdir(spec):
2218 if os.path.isdir(spec):
2227 spec += '/'
2219 spec += '/'
2228 spec = spec[len(rootdir):]
2220 spec = spec[len(rootdir):]
2229 fixpaths = os.sep != '/'
2221 fixpaths = os.sep != '/'
2230 if fixpaths:
2222 if fixpaths:
2231 spec = spec.replace(os.sep, '/')
2223 spec = spec.replace(os.sep, '/')
2232 speclen = len(spec)
2224 speclen = len(spec)
2233 fullpaths = opts['full']
2225 fullpaths = opts['full']
2234 files, dirs = set(), set()
2226 files, dirs = set(), set()
2235 adddir, addfile = dirs.add, files.add
2227 adddir, addfile = dirs.add, files.add
2236 for f, st in dirstate.iteritems():
2228 for f, st in dirstate.iteritems():
2237 if f.startswith(spec) and st[0] in acceptable:
2229 if f.startswith(spec) and st[0] in acceptable:
2238 if fixpaths:
2230 if fixpaths:
2239 f = f.replace('/', os.sep)
2231 f = f.replace('/', os.sep)
2240 if fullpaths:
2232 if fullpaths:
2241 addfile(f)
2233 addfile(f)
2242 continue
2234 continue
2243 s = f.find(os.sep, speclen)
2235 s = f.find(os.sep, speclen)
2244 if s >= 0:
2236 if s >= 0:
2245 adddir(f[:s])
2237 adddir(f[:s])
2246 else:
2238 else:
2247 addfile(f)
2239 addfile(f)
2248 return files, dirs
2240 return files, dirs
2249
2241
2250 acceptable = ''
2242 acceptable = ''
2251 if opts['normal']:
2243 if opts['normal']:
2252 acceptable += 'nm'
2244 acceptable += 'nm'
2253 if opts['added']:
2245 if opts['added']:
2254 acceptable += 'a'
2246 acceptable += 'a'
2255 if opts['removed']:
2247 if opts['removed']:
2256 acceptable += 'r'
2248 acceptable += 'r'
2257 cwd = repo.getcwd()
2249 cwd = repo.getcwd()
2258 if not specs:
2250 if not specs:
2259 specs = ['.']
2251 specs = ['.']
2260
2252
2261 files, dirs = set(), set()
2253 files, dirs = set(), set()
2262 for spec in specs:
2254 for spec in specs:
2263 f, d = complete(spec, acceptable or 'nmar')
2255 f, d = complete(spec, acceptable or 'nmar')
2264 files.update(f)
2256 files.update(f)
2265 dirs.update(d)
2257 dirs.update(d)
2266 files.update(dirs)
2258 files.update(dirs)
2267 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2259 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2268 ui.write('\n')
2260 ui.write('\n')
2269
2261
2270 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2262 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2271 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2263 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2272 '''access the pushkey key/value protocol
2264 '''access the pushkey key/value protocol
2273
2265
2274 With two args, list the keys in the given namespace.
2266 With two args, list the keys in the given namespace.
2275
2267
2276 With five args, set a key to new if it currently is set to old.
2268 With five args, set a key to new if it currently is set to old.
2277 Reports success or failure.
2269 Reports success or failure.
2278 '''
2270 '''
2279
2271
2280 target = hg.peer(ui, {}, repopath)
2272 target = hg.peer(ui, {}, repopath)
2281 if keyinfo:
2273 if keyinfo:
2282 key, old, new = keyinfo
2274 key, old, new = keyinfo
2283 r = target.pushkey(namespace, key, old, new)
2275 r = target.pushkey(namespace, key, old, new)
2284 ui.status(str(r) + '\n')
2276 ui.status(str(r) + '\n')
2285 return not r
2277 return not r
2286 else:
2278 else:
2287 for k, v in sorted(target.listkeys(namespace).iteritems()):
2279 for k, v in sorted(target.listkeys(namespace).iteritems()):
2288 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2280 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2289 v.encode('string-escape')))
2281 v.encode('string-escape')))
2290
2282
2291 @command('debugpvec', [], _('A B'))
2283 @command('debugpvec', [], _('A B'))
2292 def debugpvec(ui, repo, a, b=None):
2284 def debugpvec(ui, repo, a, b=None):
2293 ca = scmutil.revsingle(repo, a)
2285 ca = scmutil.revsingle(repo, a)
2294 cb = scmutil.revsingle(repo, b)
2286 cb = scmutil.revsingle(repo, b)
2295 pa = pvec.ctxpvec(ca)
2287 pa = pvec.ctxpvec(ca)
2296 pb = pvec.ctxpvec(cb)
2288 pb = pvec.ctxpvec(cb)
2297 if pa == pb:
2289 if pa == pb:
2298 rel = "="
2290 rel = "="
2299 elif pa > pb:
2291 elif pa > pb:
2300 rel = ">"
2292 rel = ">"
2301 elif pa < pb:
2293 elif pa < pb:
2302 rel = "<"
2294 rel = "<"
2303 elif pa | pb:
2295 elif pa | pb:
2304 rel = "|"
2296 rel = "|"
2305 ui.write(_("a: %s\n") % pa)
2297 ui.write(_("a: %s\n") % pa)
2306 ui.write(_("b: %s\n") % pb)
2298 ui.write(_("b: %s\n") % pb)
2307 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2299 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2308 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2300 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2309 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2301 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2310 pa.distance(pb), rel))
2302 pa.distance(pb), rel))
2311
2303
2312 @command('debugrebuilddirstate|debugrebuildstate',
2304 @command('debugrebuilddirstate|debugrebuildstate',
2313 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2305 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2314 _('[-r REV]'))
2306 _('[-r REV]'))
2315 def debugrebuilddirstate(ui, repo, rev):
2307 def debugrebuilddirstate(ui, repo, rev):
2316 """rebuild the dirstate as it would look like for the given revision
2308 """rebuild the dirstate as it would look like for the given revision
2317
2309
2318 If no revision is specified the first current parent will be used.
2310 If no revision is specified the first current parent will be used.
2319
2311
2320 The dirstate will be set to the files of the given revision.
2312 The dirstate will be set to the files of the given revision.
2321 The actual working directory content or existing dirstate
2313 The actual working directory content or existing dirstate
2322 information such as adds or removes is not considered.
2314 information such as adds or removes is not considered.
2323
2315
2324 One use of this command is to make the next :hg:`status` invocation
2316 One use of this command is to make the next :hg:`status` invocation
2325 check the actual file content.
2317 check the actual file content.
2326 """
2318 """
2327 ctx = scmutil.revsingle(repo, rev)
2319 ctx = scmutil.revsingle(repo, rev)
2328 wlock = repo.wlock()
2320 wlock = repo.wlock()
2329 try:
2321 try:
2330 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2322 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2331 finally:
2323 finally:
2332 wlock.release()
2324 wlock.release()
2333
2325
2334 @command('debugrename',
2326 @command('debugrename',
2335 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2327 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2336 _('[-r REV] FILE'))
2328 _('[-r REV] FILE'))
2337 def debugrename(ui, repo, file1, *pats, **opts):
2329 def debugrename(ui, repo, file1, *pats, **opts):
2338 """dump rename information"""
2330 """dump rename information"""
2339
2331
2340 ctx = scmutil.revsingle(repo, opts.get('rev'))
2332 ctx = scmutil.revsingle(repo, opts.get('rev'))
2341 m = scmutil.match(ctx, (file1,) + pats, opts)
2333 m = scmutil.match(ctx, (file1,) + pats, opts)
2342 for abs in ctx.walk(m):
2334 for abs in ctx.walk(m):
2343 fctx = ctx[abs]
2335 fctx = ctx[abs]
2344 o = fctx.filelog().renamed(fctx.filenode())
2336 o = fctx.filelog().renamed(fctx.filenode())
2345 rel = m.rel(abs)
2337 rel = m.rel(abs)
2346 if o:
2338 if o:
2347 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2339 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2348 else:
2340 else:
2349 ui.write(_("%s not renamed\n") % rel)
2341 ui.write(_("%s not renamed\n") % rel)
2350
2342
2351 @command('debugrevlog',
2343 @command('debugrevlog',
2352 [('c', 'changelog', False, _('open changelog')),
2344 [('c', 'changelog', False, _('open changelog')),
2353 ('m', 'manifest', False, _('open manifest')),
2345 ('m', 'manifest', False, _('open manifest')),
2354 ('d', 'dump', False, _('dump index data'))],
2346 ('d', 'dump', False, _('dump index data'))],
2355 _('-c|-m|FILE'))
2347 _('-c|-m|FILE'))
2356 def debugrevlog(ui, repo, file_=None, **opts):
2348 def debugrevlog(ui, repo, file_=None, **opts):
2357 """show data and statistics about a revlog"""
2349 """show data and statistics about a revlog"""
2358 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2350 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2359
2351
2360 if opts.get("dump"):
2352 if opts.get("dump"):
2361 numrevs = len(r)
2353 numrevs = len(r)
2362 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2354 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2363 " rawsize totalsize compression heads\n")
2355 " rawsize totalsize compression heads\n")
2364 ts = 0
2356 ts = 0
2365 heads = set()
2357 heads = set()
2366 for rev in xrange(numrevs):
2358 for rev in xrange(numrevs):
2367 dbase = r.deltaparent(rev)
2359 dbase = r.deltaparent(rev)
2368 if dbase == -1:
2360 if dbase == -1:
2369 dbase = rev
2361 dbase = rev
2370 cbase = r.chainbase(rev)
2362 cbase = r.chainbase(rev)
2371 p1, p2 = r.parentrevs(rev)
2363 p1, p2 = r.parentrevs(rev)
2372 rs = r.rawsize(rev)
2364 rs = r.rawsize(rev)
2373 ts = ts + rs
2365 ts = ts + rs
2374 heads -= set(r.parentrevs(rev))
2366 heads -= set(r.parentrevs(rev))
2375 heads.add(rev)
2367 heads.add(rev)
2376 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2368 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2377 (rev, p1, p2, r.start(rev), r.end(rev),
2369 (rev, p1, p2, r.start(rev), r.end(rev),
2378 r.start(dbase), r.start(cbase),
2370 r.start(dbase), r.start(cbase),
2379 r.start(p1), r.start(p2),
2371 r.start(p1), r.start(p2),
2380 rs, ts, ts / r.end(rev), len(heads)))
2372 rs, ts, ts / r.end(rev), len(heads)))
2381 return 0
2373 return 0
2382
2374
2383 v = r.version
2375 v = r.version
2384 format = v & 0xFFFF
2376 format = v & 0xFFFF
2385 flags = []
2377 flags = []
2386 gdelta = False
2378 gdelta = False
2387 if v & revlog.REVLOGNGINLINEDATA:
2379 if v & revlog.REVLOGNGINLINEDATA:
2388 flags.append('inline')
2380 flags.append('inline')
2389 if v & revlog.REVLOGGENERALDELTA:
2381 if v & revlog.REVLOGGENERALDELTA:
2390 gdelta = True
2382 gdelta = True
2391 flags.append('generaldelta')
2383 flags.append('generaldelta')
2392 if not flags:
2384 if not flags:
2393 flags = ['(none)']
2385 flags = ['(none)']
2394
2386
2395 nummerges = 0
2387 nummerges = 0
2396 numfull = 0
2388 numfull = 0
2397 numprev = 0
2389 numprev = 0
2398 nump1 = 0
2390 nump1 = 0
2399 nump2 = 0
2391 nump2 = 0
2400 numother = 0
2392 numother = 0
2401 nump1prev = 0
2393 nump1prev = 0
2402 nump2prev = 0
2394 nump2prev = 0
2403 chainlengths = []
2395 chainlengths = []
2404
2396
2405 datasize = [None, 0, 0L]
2397 datasize = [None, 0, 0L]
2406 fullsize = [None, 0, 0L]
2398 fullsize = [None, 0, 0L]
2407 deltasize = [None, 0, 0L]
2399 deltasize = [None, 0, 0L]
2408
2400
2409 def addsize(size, l):
2401 def addsize(size, l):
2410 if l[0] is None or size < l[0]:
2402 if l[0] is None or size < l[0]:
2411 l[0] = size
2403 l[0] = size
2412 if size > l[1]:
2404 if size > l[1]:
2413 l[1] = size
2405 l[1] = size
2414 l[2] += size
2406 l[2] += size
2415
2407
2416 numrevs = len(r)
2408 numrevs = len(r)
2417 for rev in xrange(numrevs):
2409 for rev in xrange(numrevs):
2418 p1, p2 = r.parentrevs(rev)
2410 p1, p2 = r.parentrevs(rev)
2419 delta = r.deltaparent(rev)
2411 delta = r.deltaparent(rev)
2420 if format > 0:
2412 if format > 0:
2421 addsize(r.rawsize(rev), datasize)
2413 addsize(r.rawsize(rev), datasize)
2422 if p2 != nullrev:
2414 if p2 != nullrev:
2423 nummerges += 1
2415 nummerges += 1
2424 size = r.length(rev)
2416 size = r.length(rev)
2425 if delta == nullrev:
2417 if delta == nullrev:
2426 chainlengths.append(0)
2418 chainlengths.append(0)
2427 numfull += 1
2419 numfull += 1
2428 addsize(size, fullsize)
2420 addsize(size, fullsize)
2429 else:
2421 else:
2430 chainlengths.append(chainlengths[delta] + 1)
2422 chainlengths.append(chainlengths[delta] + 1)
2431 addsize(size, deltasize)
2423 addsize(size, deltasize)
2432 if delta == rev - 1:
2424 if delta == rev - 1:
2433 numprev += 1
2425 numprev += 1
2434 if delta == p1:
2426 if delta == p1:
2435 nump1prev += 1
2427 nump1prev += 1
2436 elif delta == p2:
2428 elif delta == p2:
2437 nump2prev += 1
2429 nump2prev += 1
2438 elif delta == p1:
2430 elif delta == p1:
2439 nump1 += 1
2431 nump1 += 1
2440 elif delta == p2:
2432 elif delta == p2:
2441 nump2 += 1
2433 nump2 += 1
2442 elif delta != nullrev:
2434 elif delta != nullrev:
2443 numother += 1
2435 numother += 1
2444
2436
2445 # Adjust size min value for empty cases
2437 # Adjust size min value for empty cases
2446 for size in (datasize, fullsize, deltasize):
2438 for size in (datasize, fullsize, deltasize):
2447 if size[0] is None:
2439 if size[0] is None:
2448 size[0] = 0
2440 size[0] = 0
2449
2441
2450 numdeltas = numrevs - numfull
2442 numdeltas = numrevs - numfull
2451 numoprev = numprev - nump1prev - nump2prev
2443 numoprev = numprev - nump1prev - nump2prev
2452 totalrawsize = datasize[2]
2444 totalrawsize = datasize[2]
2453 datasize[2] /= numrevs
2445 datasize[2] /= numrevs
2454 fulltotal = fullsize[2]
2446 fulltotal = fullsize[2]
2455 fullsize[2] /= numfull
2447 fullsize[2] /= numfull
2456 deltatotal = deltasize[2]
2448 deltatotal = deltasize[2]
2457 if numrevs - numfull > 0:
2449 if numrevs - numfull > 0:
2458 deltasize[2] /= numrevs - numfull
2450 deltasize[2] /= numrevs - numfull
2459 totalsize = fulltotal + deltatotal
2451 totalsize = fulltotal + deltatotal
2460 avgchainlen = sum(chainlengths) / numrevs
2452 avgchainlen = sum(chainlengths) / numrevs
2461 compratio = totalrawsize / totalsize
2453 compratio = totalrawsize / totalsize
2462
2454
2463 basedfmtstr = '%%%dd\n'
2455 basedfmtstr = '%%%dd\n'
2464 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2456 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2465
2457
2466 def dfmtstr(max):
2458 def dfmtstr(max):
2467 return basedfmtstr % len(str(max))
2459 return basedfmtstr % len(str(max))
2468 def pcfmtstr(max, padding=0):
2460 def pcfmtstr(max, padding=0):
2469 return basepcfmtstr % (len(str(max)), ' ' * padding)
2461 return basepcfmtstr % (len(str(max)), ' ' * padding)
2470
2462
2471 def pcfmt(value, total):
2463 def pcfmt(value, total):
2472 return (value, 100 * float(value) / total)
2464 return (value, 100 * float(value) / total)
2473
2465
2474 ui.write(('format : %d\n') % format)
2466 ui.write(('format : %d\n') % format)
2475 ui.write(('flags : %s\n') % ', '.join(flags))
2467 ui.write(('flags : %s\n') % ', '.join(flags))
2476
2468
2477 ui.write('\n')
2469 ui.write('\n')
2478 fmt = pcfmtstr(totalsize)
2470 fmt = pcfmtstr(totalsize)
2479 fmt2 = dfmtstr(totalsize)
2471 fmt2 = dfmtstr(totalsize)
2480 ui.write(('revisions : ') + fmt2 % numrevs)
2472 ui.write(('revisions : ') + fmt2 % numrevs)
2481 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2473 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2482 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2474 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2483 ui.write(('revisions : ') + fmt2 % numrevs)
2475 ui.write(('revisions : ') + fmt2 % numrevs)
2484 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2476 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2485 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2477 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2486 ui.write(('revision size : ') + fmt2 % totalsize)
2478 ui.write(('revision size : ') + fmt2 % totalsize)
2487 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2479 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2488 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2480 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2489
2481
2490 ui.write('\n')
2482 ui.write('\n')
2491 fmt = dfmtstr(max(avgchainlen, compratio))
2483 fmt = dfmtstr(max(avgchainlen, compratio))
2492 ui.write(('avg chain length : ') + fmt % avgchainlen)
2484 ui.write(('avg chain length : ') + fmt % avgchainlen)
2493 ui.write(('compression ratio : ') + fmt % compratio)
2485 ui.write(('compression ratio : ') + fmt % compratio)
2494
2486
2495 if format > 0:
2487 if format > 0:
2496 ui.write('\n')
2488 ui.write('\n')
2497 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2489 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2498 % tuple(datasize))
2490 % tuple(datasize))
2499 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2491 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2500 % tuple(fullsize))
2492 % tuple(fullsize))
2501 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2493 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2502 % tuple(deltasize))
2494 % tuple(deltasize))
2503
2495
2504 if numdeltas > 0:
2496 if numdeltas > 0:
2505 ui.write('\n')
2497 ui.write('\n')
2506 fmt = pcfmtstr(numdeltas)
2498 fmt = pcfmtstr(numdeltas)
2507 fmt2 = pcfmtstr(numdeltas, 4)
2499 fmt2 = pcfmtstr(numdeltas, 4)
2508 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2500 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2509 if numprev > 0:
2501 if numprev > 0:
2510 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2502 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2511 numprev))
2503 numprev))
2512 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2504 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2513 numprev))
2505 numprev))
2514 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2506 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2515 numprev))
2507 numprev))
2516 if gdelta:
2508 if gdelta:
2517 ui.write(('deltas against p1 : ')
2509 ui.write(('deltas against p1 : ')
2518 + fmt % pcfmt(nump1, numdeltas))
2510 + fmt % pcfmt(nump1, numdeltas))
2519 ui.write(('deltas against p2 : ')
2511 ui.write(('deltas against p2 : ')
2520 + fmt % pcfmt(nump2, numdeltas))
2512 + fmt % pcfmt(nump2, numdeltas))
2521 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2513 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2522 numdeltas))
2514 numdeltas))
2523
2515
2524 @command('debugrevspec', [], ('REVSPEC'))
2516 @command('debugrevspec', [], ('REVSPEC'))
2525 def debugrevspec(ui, repo, expr):
2517 def debugrevspec(ui, repo, expr):
2526 """parse and apply a revision specification
2518 """parse and apply a revision specification
2527
2519
2528 Use --verbose to print the parsed tree before and after aliases
2520 Use --verbose to print the parsed tree before and after aliases
2529 expansion.
2521 expansion.
2530 """
2522 """
2531 if ui.verbose:
2523 if ui.verbose:
2532 tree = revset.parse(expr)[0]
2524 tree = revset.parse(expr)[0]
2533 ui.note(revset.prettyformat(tree), "\n")
2525 ui.note(revset.prettyformat(tree), "\n")
2534 newtree = revset.findaliases(ui, tree)
2526 newtree = revset.findaliases(ui, tree)
2535 if newtree != tree:
2527 if newtree != tree:
2536 ui.note(revset.prettyformat(newtree), "\n")
2528 ui.note(revset.prettyformat(newtree), "\n")
2537 func = revset.match(ui, expr)
2529 func = revset.match(ui, expr)
2538 for c in func(repo, range(len(repo))):
2530 for c in func(repo, range(len(repo))):
2539 ui.write("%s\n" % c)
2531 ui.write("%s\n" % c)
2540
2532
2541 @command('debugsetparents', [], _('REV1 [REV2]'))
2533 @command('debugsetparents', [], _('REV1 [REV2]'))
2542 def debugsetparents(ui, repo, rev1, rev2=None):
2534 def debugsetparents(ui, repo, rev1, rev2=None):
2543 """manually set the parents of the current working directory
2535 """manually set the parents of the current working directory
2544
2536
2545 This is useful for writing repository conversion tools, but should
2537 This is useful for writing repository conversion tools, but should
2546 be used with care.
2538 be used with care.
2547
2539
2548 Returns 0 on success.
2540 Returns 0 on success.
2549 """
2541 """
2550
2542
2551 r1 = scmutil.revsingle(repo, rev1).node()
2543 r1 = scmutil.revsingle(repo, rev1).node()
2552 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2544 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2553
2545
2554 wlock = repo.wlock()
2546 wlock = repo.wlock()
2555 try:
2547 try:
2556 repo.setparents(r1, r2)
2548 repo.setparents(r1, r2)
2557 finally:
2549 finally:
2558 wlock.release()
2550 wlock.release()
2559
2551
2560 @command('debugdirstate|debugstate',
2552 @command('debugdirstate|debugstate',
2561 [('', 'nodates', None, _('do not display the saved mtime')),
2553 [('', 'nodates', None, _('do not display the saved mtime')),
2562 ('', 'datesort', None, _('sort by saved mtime'))],
2554 ('', 'datesort', None, _('sort by saved mtime'))],
2563 _('[OPTION]...'))
2555 _('[OPTION]...'))
2564 def debugstate(ui, repo, nodates=None, datesort=None):
2556 def debugstate(ui, repo, nodates=None, datesort=None):
2565 """show the contents of the current dirstate"""
2557 """show the contents of the current dirstate"""
2566 timestr = ""
2558 timestr = ""
2567 showdate = not nodates
2559 showdate = not nodates
2568 if datesort:
2560 if datesort:
2569 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2561 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2570 else:
2562 else:
2571 keyfunc = None # sort by filename
2563 keyfunc = None # sort by filename
2572 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2564 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2573 if showdate:
2565 if showdate:
2574 if ent[3] == -1:
2566 if ent[3] == -1:
2575 # Pad or slice to locale representation
2567 # Pad or slice to locale representation
2576 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2568 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2577 time.localtime(0)))
2569 time.localtime(0)))
2578 timestr = 'unset'
2570 timestr = 'unset'
2579 timestr = (timestr[:locale_len] +
2571 timestr = (timestr[:locale_len] +
2580 ' ' * (locale_len - len(timestr)))
2572 ' ' * (locale_len - len(timestr)))
2581 else:
2573 else:
2582 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2574 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2583 time.localtime(ent[3]))
2575 time.localtime(ent[3]))
2584 if ent[1] & 020000:
2576 if ent[1] & 020000:
2585 mode = 'lnk'
2577 mode = 'lnk'
2586 else:
2578 else:
2587 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2579 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2588 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2580 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2589 for f in repo.dirstate.copies():
2581 for f in repo.dirstate.copies():
2590 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2582 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2591
2583
2592 @command('debugsub',
2584 @command('debugsub',
2593 [('r', 'rev', '',
2585 [('r', 'rev', '',
2594 _('revision to check'), _('REV'))],
2586 _('revision to check'), _('REV'))],
2595 _('[-r REV] [REV]'))
2587 _('[-r REV] [REV]'))
2596 def debugsub(ui, repo, rev=None):
2588 def debugsub(ui, repo, rev=None):
2597 ctx = scmutil.revsingle(repo, rev, None)
2589 ctx = scmutil.revsingle(repo, rev, None)
2598 for k, v in sorted(ctx.substate.items()):
2590 for k, v in sorted(ctx.substate.items()):
2599 ui.write(('path %s\n') % k)
2591 ui.write(('path %s\n') % k)
2600 ui.write((' source %s\n') % v[0])
2592 ui.write((' source %s\n') % v[0])
2601 ui.write((' revision %s\n') % v[1])
2593 ui.write((' revision %s\n') % v[1])
2602
2594
2603 @command('debugsuccessorssets',
2595 @command('debugsuccessorssets',
2604 [],
2596 [],
2605 _('[REV]'))
2597 _('[REV]'))
2606 def debugsuccessorssets(ui, repo, *revs):
2598 def debugsuccessorssets(ui, repo, *revs):
2607 """show set of successors for revision
2599 """show set of successors for revision
2608
2600
2609 A successors set of changeset A is a consistent group of revisions that
2601 A successors set of changeset A is a consistent group of revisions that
2610 succeed A. It contains non-obsolete changesets only.
2602 succeed A. It contains non-obsolete changesets only.
2611
2603
2612 In most cases a changeset A has a single successors set containing a single
2604 In most cases a changeset A has a single successors set containing a single
2613 successor (changeset A replaced by A').
2605 successor (changeset A replaced by A').
2614
2606
2615 A changeset that is made obsolete with no successors are called "pruned".
2607 A changeset that is made obsolete with no successors are called "pruned".
2616 Such changesets have no successors sets at all.
2608 Such changesets have no successors sets at all.
2617
2609
2618 A changeset that has been "split" will have a successors set containing
2610 A changeset that has been "split" will have a successors set containing
2619 more than one successor.
2611 more than one successor.
2620
2612
2621 A changeset that has been rewritten in multiple different ways is called
2613 A changeset that has been rewritten in multiple different ways is called
2622 "divergent". Such changesets have multiple successor sets (each of which
2614 "divergent". Such changesets have multiple successor sets (each of which
2623 may also be split, i.e. have multiple successors).
2615 may also be split, i.e. have multiple successors).
2624
2616
2625 Results are displayed as follows::
2617 Results are displayed as follows::
2626
2618
2627 <rev1>
2619 <rev1>
2628 <successors-1A>
2620 <successors-1A>
2629 <rev2>
2621 <rev2>
2630 <successors-2A>
2622 <successors-2A>
2631 <successors-2B1> <successors-2B2> <successors-2B3>
2623 <successors-2B1> <successors-2B2> <successors-2B3>
2632
2624
2633 Here rev2 has two possible (i.e. divergent) successors sets. The first
2625 Here rev2 has two possible (i.e. divergent) successors sets. The first
2634 holds one element, whereas the second holds three (i.e. the changeset has
2626 holds one element, whereas the second holds three (i.e. the changeset has
2635 been split).
2627 been split).
2636 """
2628 """
2637 # passed to successorssets caching computation from one call to another
2629 # passed to successorssets caching computation from one call to another
2638 cache = {}
2630 cache = {}
2639 ctx2str = str
2631 ctx2str = str
2640 node2str = short
2632 node2str = short
2641 if ui.debug():
2633 if ui.debug():
2642 def ctx2str(ctx):
2634 def ctx2str(ctx):
2643 return ctx.hex()
2635 return ctx.hex()
2644 node2str = hex
2636 node2str = hex
2645 for rev in scmutil.revrange(repo, revs):
2637 for rev in scmutil.revrange(repo, revs):
2646 ctx = repo[rev]
2638 ctx = repo[rev]
2647 ui.write('%s\n'% ctx2str(ctx))
2639 ui.write('%s\n'% ctx2str(ctx))
2648 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2640 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2649 if succsset:
2641 if succsset:
2650 ui.write(' ')
2642 ui.write(' ')
2651 ui.write(node2str(succsset[0]))
2643 ui.write(node2str(succsset[0]))
2652 for node in succsset[1:]:
2644 for node in succsset[1:]:
2653 ui.write(' ')
2645 ui.write(' ')
2654 ui.write(node2str(node))
2646 ui.write(node2str(node))
2655 ui.write('\n')
2647 ui.write('\n')
2656
2648
2657 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2649 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2658 def debugwalk(ui, repo, *pats, **opts):
2650 def debugwalk(ui, repo, *pats, **opts):
2659 """show how files match on given patterns"""
2651 """show how files match on given patterns"""
2660 m = scmutil.match(repo[None], pats, opts)
2652 m = scmutil.match(repo[None], pats, opts)
2661 items = list(repo.walk(m))
2653 items = list(repo.walk(m))
2662 if not items:
2654 if not items:
2663 return
2655 return
2664 f = lambda fn: fn
2656 f = lambda fn: fn
2665 if ui.configbool('ui', 'slash') and os.sep != '/':
2657 if ui.configbool('ui', 'slash') and os.sep != '/':
2666 f = lambda fn: util.normpath(fn)
2658 f = lambda fn: util.normpath(fn)
2667 fmt = 'f %%-%ds %%-%ds %%s' % (
2659 fmt = 'f %%-%ds %%-%ds %%s' % (
2668 max([len(abs) for abs in items]),
2660 max([len(abs) for abs in items]),
2669 max([len(m.rel(abs)) for abs in items]))
2661 max([len(m.rel(abs)) for abs in items]))
2670 for abs in items:
2662 for abs in items:
2671 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2663 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2672 ui.write("%s\n" % line.rstrip())
2664 ui.write("%s\n" % line.rstrip())
2673
2665
2674 @command('debugwireargs',
2666 @command('debugwireargs',
2675 [('', 'three', '', 'three'),
2667 [('', 'three', '', 'three'),
2676 ('', 'four', '', 'four'),
2668 ('', 'four', '', 'four'),
2677 ('', 'five', '', 'five'),
2669 ('', 'five', '', 'five'),
2678 ] + remoteopts,
2670 ] + remoteopts,
2679 _('REPO [OPTIONS]... [ONE [TWO]]'))
2671 _('REPO [OPTIONS]... [ONE [TWO]]'))
2680 def debugwireargs(ui, repopath, *vals, **opts):
2672 def debugwireargs(ui, repopath, *vals, **opts):
2681 repo = hg.peer(ui, opts, repopath)
2673 repo = hg.peer(ui, opts, repopath)
2682 for opt in remoteopts:
2674 for opt in remoteopts:
2683 del opts[opt[1]]
2675 del opts[opt[1]]
2684 args = {}
2676 args = {}
2685 for k, v in opts.iteritems():
2677 for k, v in opts.iteritems():
2686 if v:
2678 if v:
2687 args[k] = v
2679 args[k] = v
2688 # run twice to check that we don't mess up the stream for the next command
2680 # run twice to check that we don't mess up the stream for the next command
2689 res1 = repo.debugwireargs(*vals, **args)
2681 res1 = repo.debugwireargs(*vals, **args)
2690 res2 = repo.debugwireargs(*vals, **args)
2682 res2 = repo.debugwireargs(*vals, **args)
2691 ui.write("%s\n" % res1)
2683 ui.write("%s\n" % res1)
2692 if res1 != res2:
2684 if res1 != res2:
2693 ui.warn("%s\n" % res2)
2685 ui.warn("%s\n" % res2)
2694
2686
2695 @command('^diff',
2687 @command('^diff',
2696 [('r', 'rev', [], _('revision'), _('REV')),
2688 [('r', 'rev', [], _('revision'), _('REV')),
2697 ('c', 'change', '', _('change made by revision'), _('REV'))
2689 ('c', 'change', '', _('change made by revision'), _('REV'))
2698 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2690 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2699 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2691 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2700 def diff(ui, repo, *pats, **opts):
2692 def diff(ui, repo, *pats, **opts):
2701 """diff repository (or selected files)
2693 """diff repository (or selected files)
2702
2694
2703 Show differences between revisions for the specified files.
2695 Show differences between revisions for the specified files.
2704
2696
2705 Differences between files are shown using the unified diff format.
2697 Differences between files are shown using the unified diff format.
2706
2698
2707 .. note::
2699 .. note::
2708
2700
2709 diff may generate unexpected results for merges, as it will
2701 diff may generate unexpected results for merges, as it will
2710 default to comparing against the working directory's first
2702 default to comparing against the working directory's first
2711 parent changeset if no revisions are specified.
2703 parent changeset if no revisions are specified.
2712
2704
2713 When two revision arguments are given, then changes are shown
2705 When two revision arguments are given, then changes are shown
2714 between those revisions. If only one revision is specified then
2706 between those revisions. If only one revision is specified then
2715 that revision is compared to the working directory, and, when no
2707 that revision is compared to the working directory, and, when no
2716 revisions are specified, the working directory files are compared
2708 revisions are specified, the working directory files are compared
2717 to its parent.
2709 to its parent.
2718
2710
2719 Alternatively you can specify -c/--change with a revision to see
2711 Alternatively you can specify -c/--change with a revision to see
2720 the changes in that changeset relative to its first parent.
2712 the changes in that changeset relative to its first parent.
2721
2713
2722 Without the -a/--text option, diff will avoid generating diffs of
2714 Without the -a/--text option, diff will avoid generating diffs of
2723 files it detects as binary. With -a, diff will generate a diff
2715 files it detects as binary. With -a, diff will generate a diff
2724 anyway, probably with undesirable results.
2716 anyway, probably with undesirable results.
2725
2717
2726 Use the -g/--git option to generate diffs in the git extended diff
2718 Use the -g/--git option to generate diffs in the git extended diff
2727 format. For more information, read :hg:`help diffs`.
2719 format. For more information, read :hg:`help diffs`.
2728
2720
2729 .. container:: verbose
2721 .. container:: verbose
2730
2722
2731 Examples:
2723 Examples:
2732
2724
2733 - compare a file in the current working directory to its parent::
2725 - compare a file in the current working directory to its parent::
2734
2726
2735 hg diff foo.c
2727 hg diff foo.c
2736
2728
2737 - compare two historical versions of a directory, with rename info::
2729 - compare two historical versions of a directory, with rename info::
2738
2730
2739 hg diff --git -r 1.0:1.2 lib/
2731 hg diff --git -r 1.0:1.2 lib/
2740
2732
2741 - get change stats relative to the last change on some date::
2733 - get change stats relative to the last change on some date::
2742
2734
2743 hg diff --stat -r "date('may 2')"
2735 hg diff --stat -r "date('may 2')"
2744
2736
2745 - diff all newly-added files that contain a keyword::
2737 - diff all newly-added files that contain a keyword::
2746
2738
2747 hg diff "set:added() and grep(GNU)"
2739 hg diff "set:added() and grep(GNU)"
2748
2740
2749 - compare a revision and its parents::
2741 - compare a revision and its parents::
2750
2742
2751 hg diff -c 9353 # compare against first parent
2743 hg diff -c 9353 # compare against first parent
2752 hg diff -r 9353^:9353 # same using revset syntax
2744 hg diff -r 9353^:9353 # same using revset syntax
2753 hg diff -r 9353^2:9353 # compare against the second parent
2745 hg diff -r 9353^2:9353 # compare against the second parent
2754
2746
2755 Returns 0 on success.
2747 Returns 0 on success.
2756 """
2748 """
2757
2749
2758 revs = opts.get('rev')
2750 revs = opts.get('rev')
2759 change = opts.get('change')
2751 change = opts.get('change')
2760 stat = opts.get('stat')
2752 stat = opts.get('stat')
2761 reverse = opts.get('reverse')
2753 reverse = opts.get('reverse')
2762
2754
2763 if revs and change:
2755 if revs and change:
2764 msg = _('cannot specify --rev and --change at the same time')
2756 msg = _('cannot specify --rev and --change at the same time')
2765 raise util.Abort(msg)
2757 raise util.Abort(msg)
2766 elif change:
2758 elif change:
2767 node2 = scmutil.revsingle(repo, change, None).node()
2759 node2 = scmutil.revsingle(repo, change, None).node()
2768 node1 = repo[node2].p1().node()
2760 node1 = repo[node2].p1().node()
2769 else:
2761 else:
2770 node1, node2 = scmutil.revpair(repo, revs)
2762 node1, node2 = scmutil.revpair(repo, revs)
2771
2763
2772 if reverse:
2764 if reverse:
2773 node1, node2 = node2, node1
2765 node1, node2 = node2, node1
2774
2766
2775 diffopts = patch.diffopts(ui, opts)
2767 diffopts = patch.diffopts(ui, opts)
2776 m = scmutil.match(repo[node2], pats, opts)
2768 m = scmutil.match(repo[node2], pats, opts)
2777 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2769 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2778 listsubrepos=opts.get('subrepos'))
2770 listsubrepos=opts.get('subrepos'))
2779
2771
2780 @command('^export',
2772 @command('^export',
2781 [('o', 'output', '',
2773 [('o', 'output', '',
2782 _('print output to file with formatted name'), _('FORMAT')),
2774 _('print output to file with formatted name'), _('FORMAT')),
2783 ('', 'switch-parent', None, _('diff against the second parent')),
2775 ('', 'switch-parent', None, _('diff against the second parent')),
2784 ('r', 'rev', [], _('revisions to export'), _('REV')),
2776 ('r', 'rev', [], _('revisions to export'), _('REV')),
2785 ] + diffopts,
2777 ] + diffopts,
2786 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2778 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2787 def export(ui, repo, *changesets, **opts):
2779 def export(ui, repo, *changesets, **opts):
2788 """dump the header and diffs for one or more changesets
2780 """dump the header and diffs for one or more changesets
2789
2781
2790 Print the changeset header and diffs for one or more revisions.
2782 Print the changeset header and diffs for one or more revisions.
2791 If no revision is given, the parent of the working directory is used.
2783 If no revision is given, the parent of the working directory is used.
2792
2784
2793 The information shown in the changeset header is: author, date,
2785 The information shown in the changeset header is: author, date,
2794 branch name (if non-default), changeset hash, parent(s) and commit
2786 branch name (if non-default), changeset hash, parent(s) and commit
2795 comment.
2787 comment.
2796
2788
2797 .. note::
2789 .. note::
2798
2790
2799 export may generate unexpected diff output for merge
2791 export may generate unexpected diff output for merge
2800 changesets, as it will compare the merge changeset against its
2792 changesets, as it will compare the merge changeset against its
2801 first parent only.
2793 first parent only.
2802
2794
2803 Output may be to a file, in which case the name of the file is
2795 Output may be to a file, in which case the name of the file is
2804 given using a format string. The formatting rules are as follows:
2796 given using a format string. The formatting rules are as follows:
2805
2797
2806 :``%%``: literal "%" character
2798 :``%%``: literal "%" character
2807 :``%H``: changeset hash (40 hexadecimal digits)
2799 :``%H``: changeset hash (40 hexadecimal digits)
2808 :``%N``: number of patches being generated
2800 :``%N``: number of patches being generated
2809 :``%R``: changeset revision number
2801 :``%R``: changeset revision number
2810 :``%b``: basename of the exporting repository
2802 :``%b``: basename of the exporting repository
2811 :``%h``: short-form changeset hash (12 hexadecimal digits)
2803 :``%h``: short-form changeset hash (12 hexadecimal digits)
2812 :``%m``: first line of the commit message (only alphanumeric characters)
2804 :``%m``: first line of the commit message (only alphanumeric characters)
2813 :``%n``: zero-padded sequence number, starting at 1
2805 :``%n``: zero-padded sequence number, starting at 1
2814 :``%r``: zero-padded changeset revision number
2806 :``%r``: zero-padded changeset revision number
2815
2807
2816 Without the -a/--text option, export will avoid generating diffs
2808 Without the -a/--text option, export will avoid generating diffs
2817 of files it detects as binary. With -a, export will generate a
2809 of files it detects as binary. With -a, export will generate a
2818 diff anyway, probably with undesirable results.
2810 diff anyway, probably with undesirable results.
2819
2811
2820 Use the -g/--git option to generate diffs in the git extended diff
2812 Use the -g/--git option to generate diffs in the git extended diff
2821 format. See :hg:`help diffs` for more information.
2813 format. See :hg:`help diffs` for more information.
2822
2814
2823 With the --switch-parent option, the diff will be against the
2815 With the --switch-parent option, the diff will be against the
2824 second parent. It can be useful to review a merge.
2816 second parent. It can be useful to review a merge.
2825
2817
2826 .. container:: verbose
2818 .. container:: verbose
2827
2819
2828 Examples:
2820 Examples:
2829
2821
2830 - use export and import to transplant a bugfix to the current
2822 - use export and import to transplant a bugfix to the current
2831 branch::
2823 branch::
2832
2824
2833 hg export -r 9353 | hg import -
2825 hg export -r 9353 | hg import -
2834
2826
2835 - export all the changesets between two revisions to a file with
2827 - export all the changesets between two revisions to a file with
2836 rename information::
2828 rename information::
2837
2829
2838 hg export --git -r 123:150 > changes.txt
2830 hg export --git -r 123:150 > changes.txt
2839
2831
2840 - split outgoing changes into a series of patches with
2832 - split outgoing changes into a series of patches with
2841 descriptive names::
2833 descriptive names::
2842
2834
2843 hg export -r "outgoing()" -o "%n-%m.patch"
2835 hg export -r "outgoing()" -o "%n-%m.patch"
2844
2836
2845 Returns 0 on success.
2837 Returns 0 on success.
2846 """
2838 """
2847 changesets += tuple(opts.get('rev', []))
2839 changesets += tuple(opts.get('rev', []))
2848 if not changesets:
2840 if not changesets:
2849 changesets = ['.']
2841 changesets = ['.']
2850 revs = scmutil.revrange(repo, changesets)
2842 revs = scmutil.revrange(repo, changesets)
2851 if not revs:
2843 if not revs:
2852 raise util.Abort(_("export requires at least one changeset"))
2844 raise util.Abort(_("export requires at least one changeset"))
2853 if len(revs) > 1:
2845 if len(revs) > 1:
2854 ui.note(_('exporting patches:\n'))
2846 ui.note(_('exporting patches:\n'))
2855 else:
2847 else:
2856 ui.note(_('exporting patch:\n'))
2848 ui.note(_('exporting patch:\n'))
2857 cmdutil.export(repo, revs, template=opts.get('output'),
2849 cmdutil.export(repo, revs, template=opts.get('output'),
2858 switch_parent=opts.get('switch_parent'),
2850 switch_parent=opts.get('switch_parent'),
2859 opts=patch.diffopts(ui, opts))
2851 opts=patch.diffopts(ui, opts))
2860
2852
2861 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2853 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2862 def forget(ui, repo, *pats, **opts):
2854 def forget(ui, repo, *pats, **opts):
2863 """forget the specified files on the next commit
2855 """forget the specified files on the next commit
2864
2856
2865 Mark the specified files so they will no longer be tracked
2857 Mark the specified files so they will no longer be tracked
2866 after the next commit.
2858 after the next commit.
2867
2859
2868 This only removes files from the current branch, not from the
2860 This only removes files from the current branch, not from the
2869 entire project history, and it does not delete them from the
2861 entire project history, and it does not delete them from the
2870 working directory.
2862 working directory.
2871
2863
2872 To undo a forget before the next commit, see :hg:`add`.
2864 To undo a forget before the next commit, see :hg:`add`.
2873
2865
2874 .. container:: verbose
2866 .. container:: verbose
2875
2867
2876 Examples:
2868 Examples:
2877
2869
2878 - forget newly-added binary files::
2870 - forget newly-added binary files::
2879
2871
2880 hg forget "set:added() and binary()"
2872 hg forget "set:added() and binary()"
2881
2873
2882 - forget files that would be excluded by .hgignore::
2874 - forget files that would be excluded by .hgignore::
2883
2875
2884 hg forget "set:hgignore()"
2876 hg forget "set:hgignore()"
2885
2877
2886 Returns 0 on success.
2878 Returns 0 on success.
2887 """
2879 """
2888
2880
2889 if not pats:
2881 if not pats:
2890 raise util.Abort(_('no files specified'))
2882 raise util.Abort(_('no files specified'))
2891
2883
2892 m = scmutil.match(repo[None], pats, opts)
2884 m = scmutil.match(repo[None], pats, opts)
2893 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2885 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2894 return rejected and 1 or 0
2886 return rejected and 1 or 0
2895
2887
2896 @command(
2888 @command(
2897 'graft',
2889 'graft',
2898 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2890 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2899 ('c', 'continue', False, _('resume interrupted graft')),
2891 ('c', 'continue', False, _('resume interrupted graft')),
2900 ('e', 'edit', False, _('invoke editor on commit messages')),
2892 ('e', 'edit', False, _('invoke editor on commit messages')),
2901 ('', 'log', None, _('append graft info to log message')),
2893 ('', 'log', None, _('append graft info to log message')),
2902 ('D', 'currentdate', False,
2894 ('D', 'currentdate', False,
2903 _('record the current date as commit date')),
2895 _('record the current date as commit date')),
2904 ('U', 'currentuser', False,
2896 ('U', 'currentuser', False,
2905 _('record the current user as committer'), _('DATE'))]
2897 _('record the current user as committer'), _('DATE'))]
2906 + commitopts2 + mergetoolopts + dryrunopts,
2898 + commitopts2 + mergetoolopts + dryrunopts,
2907 _('[OPTION]... [-r] REV...'))
2899 _('[OPTION]... [-r] REV...'))
2908 def graft(ui, repo, *revs, **opts):
2900 def graft(ui, repo, *revs, **opts):
2909 '''copy changes from other branches onto the current branch
2901 '''copy changes from other branches onto the current branch
2910
2902
2911 This command uses Mercurial's merge logic to copy individual
2903 This command uses Mercurial's merge logic to copy individual
2912 changes from other branches without merging branches in the
2904 changes from other branches without merging branches in the
2913 history graph. This is sometimes known as 'backporting' or
2905 history graph. This is sometimes known as 'backporting' or
2914 'cherry-picking'. By default, graft will copy user, date, and
2906 'cherry-picking'. By default, graft will copy user, date, and
2915 description from the source changesets.
2907 description from the source changesets.
2916
2908
2917 Changesets that are ancestors of the current revision, that have
2909 Changesets that are ancestors of the current revision, that have
2918 already been grafted, or that are merges will be skipped.
2910 already been grafted, or that are merges will be skipped.
2919
2911
2920 If --log is specified, log messages will have a comment appended
2912 If --log is specified, log messages will have a comment appended
2921 of the form::
2913 of the form::
2922
2914
2923 (grafted from CHANGESETHASH)
2915 (grafted from CHANGESETHASH)
2924
2916
2925 If a graft merge results in conflicts, the graft process is
2917 If a graft merge results in conflicts, the graft process is
2926 interrupted so that the current merge can be manually resolved.
2918 interrupted so that the current merge can be manually resolved.
2927 Once all conflicts are addressed, the graft process can be
2919 Once all conflicts are addressed, the graft process can be
2928 continued with the -c/--continue option.
2920 continued with the -c/--continue option.
2929
2921
2930 .. note::
2922 .. note::
2931
2923
2932 The -c/--continue option does not reapply earlier options.
2924 The -c/--continue option does not reapply earlier options.
2933
2925
2934 .. container:: verbose
2926 .. container:: verbose
2935
2927
2936 Examples:
2928 Examples:
2937
2929
2938 - copy a single change to the stable branch and edit its description::
2930 - copy a single change to the stable branch and edit its description::
2939
2931
2940 hg update stable
2932 hg update stable
2941 hg graft --edit 9393
2933 hg graft --edit 9393
2942
2934
2943 - graft a range of changesets with one exception, updating dates::
2935 - graft a range of changesets with one exception, updating dates::
2944
2936
2945 hg graft -D "2085::2093 and not 2091"
2937 hg graft -D "2085::2093 and not 2091"
2946
2938
2947 - continue a graft after resolving conflicts::
2939 - continue a graft after resolving conflicts::
2948
2940
2949 hg graft -c
2941 hg graft -c
2950
2942
2951 - show the source of a grafted changeset::
2943 - show the source of a grafted changeset::
2952
2944
2953 hg log --debug -r .
2945 hg log --debug -r .
2954
2946
2955 Returns 0 on successful completion.
2947 Returns 0 on successful completion.
2956 '''
2948 '''
2957
2949
2958 revs = list(revs)
2950 revs = list(revs)
2959 revs.extend(opts['rev'])
2951 revs.extend(opts['rev'])
2960
2952
2961 if not opts.get('user') and opts.get('currentuser'):
2953 if not opts.get('user') and opts.get('currentuser'):
2962 opts['user'] = ui.username()
2954 opts['user'] = ui.username()
2963 if not opts.get('date') and opts.get('currentdate'):
2955 if not opts.get('date') and opts.get('currentdate'):
2964 opts['date'] = "%d %d" % util.makedate()
2956 opts['date'] = "%d %d" % util.makedate()
2965
2957
2966 editor = None
2958 editor = None
2967 if opts.get('edit'):
2959 if opts.get('edit'):
2968 editor = cmdutil.commitforceeditor
2960 editor = cmdutil.commitforceeditor
2969
2961
2970 cont = False
2962 cont = False
2971 if opts['continue']:
2963 if opts['continue']:
2972 cont = True
2964 cont = True
2973 if revs:
2965 if revs:
2974 raise util.Abort(_("can't specify --continue and revisions"))
2966 raise util.Abort(_("can't specify --continue and revisions"))
2975 # read in unfinished revisions
2967 # read in unfinished revisions
2976 try:
2968 try:
2977 nodes = repo.opener.read('graftstate').splitlines()
2969 nodes = repo.opener.read('graftstate').splitlines()
2978 revs = [repo[node].rev() for node in nodes]
2970 revs = [repo[node].rev() for node in nodes]
2979 except IOError, inst:
2971 except IOError, inst:
2980 if inst.errno != errno.ENOENT:
2972 if inst.errno != errno.ENOENT:
2981 raise
2973 raise
2982 raise util.Abort(_("no graft state found, can't continue"))
2974 raise util.Abort(_("no graft state found, can't continue"))
2983 else:
2975 else:
2984 cmdutil.checkunfinished(repo)
2976 cmdutil.checkunfinished(repo)
2985 cmdutil.bailifchanged(repo)
2977 cmdutil.bailifchanged(repo)
2986 if not revs:
2978 if not revs:
2987 raise util.Abort(_('no revisions specified'))
2979 raise util.Abort(_('no revisions specified'))
2988 revs = scmutil.revrange(repo, revs)
2980 revs = scmutil.revrange(repo, revs)
2989
2981
2990 # check for merges
2982 # check for merges
2991 for rev in repo.revs('%ld and merge()', revs):
2983 for rev in repo.revs('%ld and merge()', revs):
2992 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2984 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2993 revs.remove(rev)
2985 revs.remove(rev)
2994 if not revs:
2986 if not revs:
2995 return -1
2987 return -1
2996
2988
2997 # check for ancestors of dest branch
2989 # check for ancestors of dest branch
2998 crev = repo['.'].rev()
2990 crev = repo['.'].rev()
2999 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2991 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3000 # don't mutate while iterating, create a copy
2992 # don't mutate while iterating, create a copy
3001 for rev in list(revs):
2993 for rev in list(revs):
3002 if rev in ancestors:
2994 if rev in ancestors:
3003 ui.warn(_('skipping ancestor revision %s\n') % rev)
2995 ui.warn(_('skipping ancestor revision %s\n') % rev)
3004 revs.remove(rev)
2996 revs.remove(rev)
3005 if not revs:
2997 if not revs:
3006 return -1
2998 return -1
3007
2999
3008 # analyze revs for earlier grafts
3000 # analyze revs for earlier grafts
3009 ids = {}
3001 ids = {}
3010 for ctx in repo.set("%ld", revs):
3002 for ctx in repo.set("%ld", revs):
3011 ids[ctx.hex()] = ctx.rev()
3003 ids[ctx.hex()] = ctx.rev()
3012 n = ctx.extra().get('source')
3004 n = ctx.extra().get('source')
3013 if n:
3005 if n:
3014 ids[n] = ctx.rev()
3006 ids[n] = ctx.rev()
3015
3007
3016 # check ancestors for earlier grafts
3008 # check ancestors for earlier grafts
3017 ui.debug('scanning for duplicate grafts\n')
3009 ui.debug('scanning for duplicate grafts\n')
3018
3010
3019 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3011 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3020 ctx = repo[rev]
3012 ctx = repo[rev]
3021 n = ctx.extra().get('source')
3013 n = ctx.extra().get('source')
3022 if n in ids:
3014 if n in ids:
3023 r = repo[n].rev()
3015 r = repo[n].rev()
3024 if r in revs:
3016 if r in revs:
3025 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3017 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3026 % (r, rev))
3018 % (r, rev))
3027 revs.remove(r)
3019 revs.remove(r)
3028 elif ids[n] in revs:
3020 elif ids[n] in revs:
3029 ui.warn(_('skipping already grafted revision %s '
3021 ui.warn(_('skipping already grafted revision %s '
3030 '(%s also has origin %d)\n') % (ids[n], rev, r))
3022 '(%s also has origin %d)\n') % (ids[n], rev, r))
3031 revs.remove(ids[n])
3023 revs.remove(ids[n])
3032 elif ctx.hex() in ids:
3024 elif ctx.hex() in ids:
3033 r = ids[ctx.hex()]
3025 r = ids[ctx.hex()]
3034 ui.warn(_('skipping already grafted revision %s '
3026 ui.warn(_('skipping already grafted revision %s '
3035 '(was grafted from %d)\n') % (r, rev))
3027 '(was grafted from %d)\n') % (r, rev))
3036 revs.remove(r)
3028 revs.remove(r)
3037 if not revs:
3029 if not revs:
3038 return -1
3030 return -1
3039
3031
3040 wlock = repo.wlock()
3032 wlock = repo.wlock()
3041 try:
3033 try:
3042 current = repo['.']
3034 current = repo['.']
3043 for pos, ctx in enumerate(repo.set("%ld", revs)):
3035 for pos, ctx in enumerate(repo.set("%ld", revs)):
3044
3036
3045 ui.status(_('grafting revision %s\n') % ctx.rev())
3037 ui.status(_('grafting revision %s\n') % ctx.rev())
3046 if opts.get('dry_run'):
3038 if opts.get('dry_run'):
3047 continue
3039 continue
3048
3040
3049 source = ctx.extra().get('source')
3041 source = ctx.extra().get('source')
3050 if not source:
3042 if not source:
3051 source = ctx.hex()
3043 source = ctx.hex()
3052 extra = {'source': source}
3044 extra = {'source': source}
3053 user = ctx.user()
3045 user = ctx.user()
3054 if opts.get('user'):
3046 if opts.get('user'):
3055 user = opts['user']
3047 user = opts['user']
3056 date = ctx.date()
3048 date = ctx.date()
3057 if opts.get('date'):
3049 if opts.get('date'):
3058 date = opts['date']
3050 date = opts['date']
3059 message = ctx.description()
3051 message = ctx.description()
3060 if opts.get('log'):
3052 if opts.get('log'):
3061 message += '\n(grafted from %s)' % ctx.hex()
3053 message += '\n(grafted from %s)' % ctx.hex()
3062
3054
3063 # we don't merge the first commit when continuing
3055 # we don't merge the first commit when continuing
3064 if not cont:
3056 if not cont:
3065 # perform the graft merge with p1(rev) as 'ancestor'
3057 # perform the graft merge with p1(rev) as 'ancestor'
3066 try:
3058 try:
3067 # ui.forcemerge is an internal variable, do not document
3059 # ui.forcemerge is an internal variable, do not document
3068 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3060 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3069 stats = mergemod.update(repo, ctx.node(), True, True, False,
3061 stats = mergemod.update(repo, ctx.node(), True, True, False,
3070 ctx.p1().node())
3062 ctx.p1().node())
3071 finally:
3063 finally:
3072 repo.ui.setconfig('ui', 'forcemerge', '')
3064 repo.ui.setconfig('ui', 'forcemerge', '')
3073 # report any conflicts
3065 # report any conflicts
3074 if stats and stats[3] > 0:
3066 if stats and stats[3] > 0:
3075 # write out state for --continue
3067 # write out state for --continue
3076 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3068 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3077 repo.opener.write('graftstate', ''.join(nodelines))
3069 repo.opener.write('graftstate', ''.join(nodelines))
3078 raise util.Abort(
3070 raise util.Abort(
3079 _("unresolved conflicts, can't continue"),
3071 _("unresolved conflicts, can't continue"),
3080 hint=_('use hg resolve and hg graft --continue'))
3072 hint=_('use hg resolve and hg graft --continue'))
3081 else:
3073 else:
3082 cont = False
3074 cont = False
3083
3075
3084 # drop the second merge parent
3076 # drop the second merge parent
3085 repo.setparents(current.node(), nullid)
3077 repo.setparents(current.node(), nullid)
3086 repo.dirstate.write()
3078 repo.dirstate.write()
3087 # fix up dirstate for copies and renames
3079 # fix up dirstate for copies and renames
3088 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3080 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3089
3081
3090 # commit
3082 # commit
3091 node = repo.commit(text=message, user=user,
3083 node = repo.commit(text=message, user=user,
3092 date=date, extra=extra, editor=editor)
3084 date=date, extra=extra, editor=editor)
3093 if node is None:
3085 if node is None:
3094 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3086 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3095 else:
3087 else:
3096 current = repo[node]
3088 current = repo[node]
3097 finally:
3089 finally:
3098 wlock.release()
3090 wlock.release()
3099
3091
3100 # remove state when we complete successfully
3092 # remove state when we complete successfully
3101 if not opts.get('dry_run'):
3093 if not opts.get('dry_run'):
3102 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3094 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3103
3095
3104 return 0
3096 return 0
3105
3097
3106 @command('grep',
3098 @command('grep',
3107 [('0', 'print0', None, _('end fields with NUL')),
3099 [('0', 'print0', None, _('end fields with NUL')),
3108 ('', 'all', None, _('print all revisions that match')),
3100 ('', 'all', None, _('print all revisions that match')),
3109 ('a', 'text', None, _('treat all files as text')),
3101 ('a', 'text', None, _('treat all files as text')),
3110 ('f', 'follow', None,
3102 ('f', 'follow', None,
3111 _('follow changeset history,'
3103 _('follow changeset history,'
3112 ' or file history across copies and renames')),
3104 ' or file history across copies and renames')),
3113 ('i', 'ignore-case', None, _('ignore case when matching')),
3105 ('i', 'ignore-case', None, _('ignore case when matching')),
3114 ('l', 'files-with-matches', None,
3106 ('l', 'files-with-matches', None,
3115 _('print only filenames and revisions that match')),
3107 _('print only filenames and revisions that match')),
3116 ('n', 'line-number', None, _('print matching line numbers')),
3108 ('n', 'line-number', None, _('print matching line numbers')),
3117 ('r', 'rev', [],
3109 ('r', 'rev', [],
3118 _('only search files changed within revision range'), _('REV')),
3110 _('only search files changed within revision range'), _('REV')),
3119 ('u', 'user', None, _('list the author (long with -v)')),
3111 ('u', 'user', None, _('list the author (long with -v)')),
3120 ('d', 'date', None, _('list the date (short with -q)')),
3112 ('d', 'date', None, _('list the date (short with -q)')),
3121 ] + walkopts,
3113 ] + walkopts,
3122 _('[OPTION]... PATTERN [FILE]...'))
3114 _('[OPTION]... PATTERN [FILE]...'))
3123 def grep(ui, repo, pattern, *pats, **opts):
3115 def grep(ui, repo, pattern, *pats, **opts):
3124 """search for a pattern in specified files and revisions
3116 """search for a pattern in specified files and revisions
3125
3117
3126 Search revisions of files for a regular expression.
3118 Search revisions of files for a regular expression.
3127
3119
3128 This command behaves differently than Unix grep. It only accepts
3120 This command behaves differently than Unix grep. It only accepts
3129 Python/Perl regexps. It searches repository history, not the
3121 Python/Perl regexps. It searches repository history, not the
3130 working directory. It always prints the revision number in which a
3122 working directory. It always prints the revision number in which a
3131 match appears.
3123 match appears.
3132
3124
3133 By default, grep only prints output for the first revision of a
3125 By default, grep only prints output for the first revision of a
3134 file in which it finds a match. To get it to print every revision
3126 file in which it finds a match. To get it to print every revision
3135 that contains a change in match status ("-" for a match that
3127 that contains a change in match status ("-" for a match that
3136 becomes a non-match, or "+" for a non-match that becomes a match),
3128 becomes a non-match, or "+" for a non-match that becomes a match),
3137 use the --all flag.
3129 use the --all flag.
3138
3130
3139 Returns 0 if a match is found, 1 otherwise.
3131 Returns 0 if a match is found, 1 otherwise.
3140 """
3132 """
3141 reflags = re.M
3133 reflags = re.M
3142 if opts.get('ignore_case'):
3134 if opts.get('ignore_case'):
3143 reflags |= re.I
3135 reflags |= re.I
3144 try:
3136 try:
3145 regexp = util.compilere(pattern, reflags)
3137 regexp = util.compilere(pattern, reflags)
3146 except re.error, inst:
3138 except re.error, inst:
3147 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3139 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3148 return 1
3140 return 1
3149 sep, eol = ':', '\n'
3141 sep, eol = ':', '\n'
3150 if opts.get('print0'):
3142 if opts.get('print0'):
3151 sep = eol = '\0'
3143 sep = eol = '\0'
3152
3144
3153 getfile = util.lrucachefunc(repo.file)
3145 getfile = util.lrucachefunc(repo.file)
3154
3146
3155 def matchlines(body):
3147 def matchlines(body):
3156 begin = 0
3148 begin = 0
3157 linenum = 0
3149 linenum = 0
3158 while begin < len(body):
3150 while begin < len(body):
3159 match = regexp.search(body, begin)
3151 match = regexp.search(body, begin)
3160 if not match:
3152 if not match:
3161 break
3153 break
3162 mstart, mend = match.span()
3154 mstart, mend = match.span()
3163 linenum += body.count('\n', begin, mstart) + 1
3155 linenum += body.count('\n', begin, mstart) + 1
3164 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3156 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3165 begin = body.find('\n', mend) + 1 or len(body) + 1
3157 begin = body.find('\n', mend) + 1 or len(body) + 1
3166 lend = begin - 1
3158 lend = begin - 1
3167 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3159 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3168
3160
3169 class linestate(object):
3161 class linestate(object):
3170 def __init__(self, line, linenum, colstart, colend):
3162 def __init__(self, line, linenum, colstart, colend):
3171 self.line = line
3163 self.line = line
3172 self.linenum = linenum
3164 self.linenum = linenum
3173 self.colstart = colstart
3165 self.colstart = colstart
3174 self.colend = colend
3166 self.colend = colend
3175
3167
3176 def __hash__(self):
3168 def __hash__(self):
3177 return hash((self.linenum, self.line))
3169 return hash((self.linenum, self.line))
3178
3170
3179 def __eq__(self, other):
3171 def __eq__(self, other):
3180 return self.line == other.line
3172 return self.line == other.line
3181
3173
3182 matches = {}
3174 matches = {}
3183 copies = {}
3175 copies = {}
3184 def grepbody(fn, rev, body):
3176 def grepbody(fn, rev, body):
3185 matches[rev].setdefault(fn, [])
3177 matches[rev].setdefault(fn, [])
3186 m = matches[rev][fn]
3178 m = matches[rev][fn]
3187 for lnum, cstart, cend, line in matchlines(body):
3179 for lnum, cstart, cend, line in matchlines(body):
3188 s = linestate(line, lnum, cstart, cend)
3180 s = linestate(line, lnum, cstart, cend)
3189 m.append(s)
3181 m.append(s)
3190
3182
3191 def difflinestates(a, b):
3183 def difflinestates(a, b):
3192 sm = difflib.SequenceMatcher(None, a, b)
3184 sm = difflib.SequenceMatcher(None, a, b)
3193 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3185 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3194 if tag == 'insert':
3186 if tag == 'insert':
3195 for i in xrange(blo, bhi):
3187 for i in xrange(blo, bhi):
3196 yield ('+', b[i])
3188 yield ('+', b[i])
3197 elif tag == 'delete':
3189 elif tag == 'delete':
3198 for i in xrange(alo, ahi):
3190 for i in xrange(alo, ahi):
3199 yield ('-', a[i])
3191 yield ('-', a[i])
3200 elif tag == 'replace':
3192 elif tag == 'replace':
3201 for i in xrange(alo, ahi):
3193 for i in xrange(alo, ahi):
3202 yield ('-', a[i])
3194 yield ('-', a[i])
3203 for i in xrange(blo, bhi):
3195 for i in xrange(blo, bhi):
3204 yield ('+', b[i])
3196 yield ('+', b[i])
3205
3197
3206 def display(fn, ctx, pstates, states):
3198 def display(fn, ctx, pstates, states):
3207 rev = ctx.rev()
3199 rev = ctx.rev()
3208 datefunc = ui.quiet and util.shortdate or util.datestr
3200 datefunc = ui.quiet and util.shortdate or util.datestr
3209 found = False
3201 found = False
3210 filerevmatches = {}
3202 filerevmatches = {}
3211 def binary():
3203 def binary():
3212 flog = getfile(fn)
3204 flog = getfile(fn)
3213 return util.binary(flog.read(ctx.filenode(fn)))
3205 return util.binary(flog.read(ctx.filenode(fn)))
3214
3206
3215 if opts.get('all'):
3207 if opts.get('all'):
3216 iter = difflinestates(pstates, states)
3208 iter = difflinestates(pstates, states)
3217 else:
3209 else:
3218 iter = [('', l) for l in states]
3210 iter = [('', l) for l in states]
3219 for change, l in iter:
3211 for change, l in iter:
3220 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3212 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3221 before, match, after = None, None, None
3213 before, match, after = None, None, None
3222
3214
3223 if opts.get('line_number'):
3215 if opts.get('line_number'):
3224 cols.append((str(l.linenum), 'grep.linenumber'))
3216 cols.append((str(l.linenum), 'grep.linenumber'))
3225 if opts.get('all'):
3217 if opts.get('all'):
3226 cols.append((change, 'grep.change'))
3218 cols.append((change, 'grep.change'))
3227 if opts.get('user'):
3219 if opts.get('user'):
3228 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3220 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3229 if opts.get('date'):
3221 if opts.get('date'):
3230 cols.append((datefunc(ctx.date()), 'grep.date'))
3222 cols.append((datefunc(ctx.date()), 'grep.date'))
3231 if opts.get('files_with_matches'):
3223 if opts.get('files_with_matches'):
3232 c = (fn, rev)
3224 c = (fn, rev)
3233 if c in filerevmatches:
3225 if c in filerevmatches:
3234 continue
3226 continue
3235 filerevmatches[c] = 1
3227 filerevmatches[c] = 1
3236 else:
3228 else:
3237 before = l.line[:l.colstart]
3229 before = l.line[:l.colstart]
3238 match = l.line[l.colstart:l.colend]
3230 match = l.line[l.colstart:l.colend]
3239 after = l.line[l.colend:]
3231 after = l.line[l.colend:]
3240 for col, label in cols[:-1]:
3232 for col, label in cols[:-1]:
3241 ui.write(col, label=label)
3233 ui.write(col, label=label)
3242 ui.write(sep, label='grep.sep')
3234 ui.write(sep, label='grep.sep')
3243 ui.write(cols[-1][0], label=cols[-1][1])
3235 ui.write(cols[-1][0], label=cols[-1][1])
3244 if before is not None:
3236 if before is not None:
3245 ui.write(sep, label='grep.sep')
3237 ui.write(sep, label='grep.sep')
3246 if not opts.get('text') and binary():
3238 if not opts.get('text') and binary():
3247 ui.write(" Binary file matches")
3239 ui.write(" Binary file matches")
3248 else:
3240 else:
3249 ui.write(before)
3241 ui.write(before)
3250 ui.write(match, label='grep.match')
3242 ui.write(match, label='grep.match')
3251 ui.write(after)
3243 ui.write(after)
3252 ui.write(eol)
3244 ui.write(eol)
3253 found = True
3245 found = True
3254 return found
3246 return found
3255
3247
3256 skip = {}
3248 skip = {}
3257 revfiles = {}
3249 revfiles = {}
3258 matchfn = scmutil.match(repo[None], pats, opts)
3250 matchfn = scmutil.match(repo[None], pats, opts)
3259 found = False
3251 found = False
3260 follow = opts.get('follow')
3252 follow = opts.get('follow')
3261
3253
3262 def prep(ctx, fns):
3254 def prep(ctx, fns):
3263 rev = ctx.rev()
3255 rev = ctx.rev()
3264 pctx = ctx.p1()
3256 pctx = ctx.p1()
3265 parent = pctx.rev()
3257 parent = pctx.rev()
3266 matches.setdefault(rev, {})
3258 matches.setdefault(rev, {})
3267 matches.setdefault(parent, {})
3259 matches.setdefault(parent, {})
3268 files = revfiles.setdefault(rev, [])
3260 files = revfiles.setdefault(rev, [])
3269 for fn in fns:
3261 for fn in fns:
3270 flog = getfile(fn)
3262 flog = getfile(fn)
3271 try:
3263 try:
3272 fnode = ctx.filenode(fn)
3264 fnode = ctx.filenode(fn)
3273 except error.LookupError:
3265 except error.LookupError:
3274 continue
3266 continue
3275
3267
3276 copied = flog.renamed(fnode)
3268 copied = flog.renamed(fnode)
3277 copy = follow and copied and copied[0]
3269 copy = follow and copied and copied[0]
3278 if copy:
3270 if copy:
3279 copies.setdefault(rev, {})[fn] = copy
3271 copies.setdefault(rev, {})[fn] = copy
3280 if fn in skip:
3272 if fn in skip:
3281 if copy:
3273 if copy:
3282 skip[copy] = True
3274 skip[copy] = True
3283 continue
3275 continue
3284 files.append(fn)
3276 files.append(fn)
3285
3277
3286 if fn not in matches[rev]:
3278 if fn not in matches[rev]:
3287 grepbody(fn, rev, flog.read(fnode))
3279 grepbody(fn, rev, flog.read(fnode))
3288
3280
3289 pfn = copy or fn
3281 pfn = copy or fn
3290 if pfn not in matches[parent]:
3282 if pfn not in matches[parent]:
3291 try:
3283 try:
3292 fnode = pctx.filenode(pfn)
3284 fnode = pctx.filenode(pfn)
3293 grepbody(pfn, parent, flog.read(fnode))
3285 grepbody(pfn, parent, flog.read(fnode))
3294 except error.LookupError:
3286 except error.LookupError:
3295 pass
3287 pass
3296
3288
3297 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3289 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3298 rev = ctx.rev()
3290 rev = ctx.rev()
3299 parent = ctx.p1().rev()
3291 parent = ctx.p1().rev()
3300 for fn in sorted(revfiles.get(rev, [])):
3292 for fn in sorted(revfiles.get(rev, [])):
3301 states = matches[rev][fn]
3293 states = matches[rev][fn]
3302 copy = copies.get(rev, {}).get(fn)
3294 copy = copies.get(rev, {}).get(fn)
3303 if fn in skip:
3295 if fn in skip:
3304 if copy:
3296 if copy:
3305 skip[copy] = True
3297 skip[copy] = True
3306 continue
3298 continue
3307 pstates = matches.get(parent, {}).get(copy or fn, [])
3299 pstates = matches.get(parent, {}).get(copy or fn, [])
3308 if pstates or states:
3300 if pstates or states:
3309 r = display(fn, ctx, pstates, states)
3301 r = display(fn, ctx, pstates, states)
3310 found = found or r
3302 found = found or r
3311 if r and not opts.get('all'):
3303 if r and not opts.get('all'):
3312 skip[fn] = True
3304 skip[fn] = True
3313 if copy:
3305 if copy:
3314 skip[copy] = True
3306 skip[copy] = True
3315 del matches[rev]
3307 del matches[rev]
3316 del revfiles[rev]
3308 del revfiles[rev]
3317
3309
3318 return not found
3310 return not found
3319
3311
3320 @command('heads',
3312 @command('heads',
3321 [('r', 'rev', '',
3313 [('r', 'rev', '',
3322 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3314 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3323 ('t', 'topo', False, _('show topological heads only')),
3315 ('t', 'topo', False, _('show topological heads only')),
3324 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3316 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3325 ('c', 'closed', False, _('show normal and closed branch heads')),
3317 ('c', 'closed', False, _('show normal and closed branch heads')),
3326 ] + templateopts,
3318 ] + templateopts,
3327 _('[-ct] [-r STARTREV] [REV]...'))
3319 _('[-ct] [-r STARTREV] [REV]...'))
3328 def heads(ui, repo, *branchrevs, **opts):
3320 def heads(ui, repo, *branchrevs, **opts):
3329 """show branch heads
3321 """show branch heads
3330
3322
3331 With no arguments, show all open branch heads in the repository.
3323 With no arguments, show all open branch heads in the repository.
3332 Branch heads are changesets that have no descendants on the
3324 Branch heads are changesets that have no descendants on the
3333 same branch. They are where development generally takes place and
3325 same branch. They are where development generally takes place and
3334 are the usual targets for update and merge operations.
3326 are the usual targets for update and merge operations.
3335
3327
3336 If one or more REVs are given, only open branch heads on the
3328 If one or more REVs are given, only open branch heads on the
3337 branches associated with the specified changesets are shown. This
3329 branches associated with the specified changesets are shown. This
3338 means that you can use :hg:`heads .` to see the heads on the
3330 means that you can use :hg:`heads .` to see the heads on the
3339 currently checked-out branch.
3331 currently checked-out branch.
3340
3332
3341 If -c/--closed is specified, also show branch heads marked closed
3333 If -c/--closed is specified, also show branch heads marked closed
3342 (see :hg:`commit --close-branch`).
3334 (see :hg:`commit --close-branch`).
3343
3335
3344 If STARTREV is specified, only those heads that are descendants of
3336 If STARTREV is specified, only those heads that are descendants of
3345 STARTREV will be displayed.
3337 STARTREV will be displayed.
3346
3338
3347 If -t/--topo is specified, named branch mechanics will be ignored and only
3339 If -t/--topo is specified, named branch mechanics will be ignored and only
3348 topological heads (changesets with no children) will be shown.
3340 topological heads (changesets with no children) will be shown.
3349
3341
3350 Returns 0 if matching heads are found, 1 if not.
3342 Returns 0 if matching heads are found, 1 if not.
3351 """
3343 """
3352
3344
3353 start = None
3345 start = None
3354 if 'rev' in opts:
3346 if 'rev' in opts:
3355 start = scmutil.revsingle(repo, opts['rev'], None).node()
3347 start = scmutil.revsingle(repo, opts['rev'], None).node()
3356
3348
3357 if opts.get('topo'):
3349 if opts.get('topo'):
3358 heads = [repo[h] for h in repo.heads(start)]
3350 heads = [repo[h] for h in repo.heads(start)]
3359 else:
3351 else:
3360 heads = []
3352 heads = []
3361 for branch in repo.branchmap():
3353 for branch in repo.branchmap():
3362 heads += repo.branchheads(branch, start, opts.get('closed'))
3354 heads += repo.branchheads(branch, start, opts.get('closed'))
3363 heads = [repo[h] for h in heads]
3355 heads = [repo[h] for h in heads]
3364
3356
3365 if branchrevs:
3357 if branchrevs:
3366 branches = set(repo[br].branch() for br in branchrevs)
3358 branches = set(repo[br].branch() for br in branchrevs)
3367 heads = [h for h in heads if h.branch() in branches]
3359 heads = [h for h in heads if h.branch() in branches]
3368
3360
3369 if opts.get('active') and branchrevs:
3361 if opts.get('active') and branchrevs:
3370 dagheads = repo.heads(start)
3362 dagheads = repo.heads(start)
3371 heads = [h for h in heads if h.node() in dagheads]
3363 heads = [h for h in heads if h.node() in dagheads]
3372
3364
3373 if branchrevs:
3365 if branchrevs:
3374 haveheads = set(h.branch() for h in heads)
3366 haveheads = set(h.branch() for h in heads)
3375 if branches - haveheads:
3367 if branches - haveheads:
3376 headless = ', '.join(b for b in branches - haveheads)
3368 headless = ', '.join(b for b in branches - haveheads)
3377 msg = _('no open branch heads found on branches %s')
3369 msg = _('no open branch heads found on branches %s')
3378 if opts.get('rev'):
3370 if opts.get('rev'):
3379 msg += _(' (started at %s)') % opts['rev']
3371 msg += _(' (started at %s)') % opts['rev']
3380 ui.warn((msg + '\n') % headless)
3372 ui.warn((msg + '\n') % headless)
3381
3373
3382 if not heads:
3374 if not heads:
3383 return 1
3375 return 1
3384
3376
3385 heads = sorted(heads, key=lambda x: -x.rev())
3377 heads = sorted(heads, key=lambda x: -x.rev())
3386 displayer = cmdutil.show_changeset(ui, repo, opts)
3378 displayer = cmdutil.show_changeset(ui, repo, opts)
3387 for ctx in heads:
3379 for ctx in heads:
3388 displayer.show(ctx)
3380 displayer.show(ctx)
3389 displayer.close()
3381 displayer.close()
3390
3382
3391 @command('help',
3383 @command('help',
3392 [('e', 'extension', None, _('show only help for extensions')),
3384 [('e', 'extension', None, _('show only help for extensions')),
3393 ('c', 'command', None, _('show only help for commands')),
3385 ('c', 'command', None, _('show only help for commands')),
3394 ('k', 'keyword', '', _('show topics matching keyword')),
3386 ('k', 'keyword', '', _('show topics matching keyword')),
3395 ],
3387 ],
3396 _('[-ec] [TOPIC]'))
3388 _('[-ec] [TOPIC]'))
3397 def help_(ui, name=None, **opts):
3389 def help_(ui, name=None, **opts):
3398 """show help for a given topic or a help overview
3390 """show help for a given topic or a help overview
3399
3391
3400 With no arguments, print a list of commands with short help messages.
3392 With no arguments, print a list of commands with short help messages.
3401
3393
3402 Given a topic, extension, or command name, print help for that
3394 Given a topic, extension, or command name, print help for that
3403 topic.
3395 topic.
3404
3396
3405 Returns 0 if successful.
3397 Returns 0 if successful.
3406 """
3398 """
3407
3399
3408 textwidth = min(ui.termwidth(), 80) - 2
3400 textwidth = min(ui.termwidth(), 80) - 2
3409
3401
3410 keep = ui.verbose and ['verbose'] or []
3402 keep = ui.verbose and ['verbose'] or []
3411 text = help.help_(ui, name, **opts)
3403 text = help.help_(ui, name, **opts)
3412
3404
3413 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3405 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3414 if 'verbose' in pruned:
3406 if 'verbose' in pruned:
3415 keep.append('omitted')
3407 keep.append('omitted')
3416 else:
3408 else:
3417 keep.append('notomitted')
3409 keep.append('notomitted')
3418 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3410 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3419 ui.write(formatted)
3411 ui.write(formatted)
3420
3412
3421
3413
3422 @command('identify|id',
3414 @command('identify|id',
3423 [('r', 'rev', '',
3415 [('r', 'rev', '',
3424 _('identify the specified revision'), _('REV')),
3416 _('identify the specified revision'), _('REV')),
3425 ('n', 'num', None, _('show local revision number')),
3417 ('n', 'num', None, _('show local revision number')),
3426 ('i', 'id', None, _('show global revision id')),
3418 ('i', 'id', None, _('show global revision id')),
3427 ('b', 'branch', None, _('show branch')),
3419 ('b', 'branch', None, _('show branch')),
3428 ('t', 'tags', None, _('show tags')),
3420 ('t', 'tags', None, _('show tags')),
3429 ('B', 'bookmarks', None, _('show bookmarks')),
3421 ('B', 'bookmarks', None, _('show bookmarks')),
3430 ] + remoteopts,
3422 ] + remoteopts,
3431 _('[-nibtB] [-r REV] [SOURCE]'))
3423 _('[-nibtB] [-r REV] [SOURCE]'))
3432 def identify(ui, repo, source=None, rev=None,
3424 def identify(ui, repo, source=None, rev=None,
3433 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3425 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3434 """identify the working copy or specified revision
3426 """identify the working copy or specified revision
3435
3427
3436 Print a summary identifying the repository state at REV using one or
3428 Print a summary identifying the repository state at REV using one or
3437 two parent hash identifiers, followed by a "+" if the working
3429 two parent hash identifiers, followed by a "+" if the working
3438 directory has uncommitted changes, the branch name (if not default),
3430 directory has uncommitted changes, the branch name (if not default),
3439 a list of tags, and a list of bookmarks.
3431 a list of tags, and a list of bookmarks.
3440
3432
3441 When REV is not given, print a summary of the current state of the
3433 When REV is not given, print a summary of the current state of the
3442 repository.
3434 repository.
3443
3435
3444 Specifying a path to a repository root or Mercurial bundle will
3436 Specifying a path to a repository root or Mercurial bundle will
3445 cause lookup to operate on that repository/bundle.
3437 cause lookup to operate on that repository/bundle.
3446
3438
3447 .. container:: verbose
3439 .. container:: verbose
3448
3440
3449 Examples:
3441 Examples:
3450
3442
3451 - generate a build identifier for the working directory::
3443 - generate a build identifier for the working directory::
3452
3444
3453 hg id --id > build-id.dat
3445 hg id --id > build-id.dat
3454
3446
3455 - find the revision corresponding to a tag::
3447 - find the revision corresponding to a tag::
3456
3448
3457 hg id -n -r 1.3
3449 hg id -n -r 1.3
3458
3450
3459 - check the most recent revision of a remote repository::
3451 - check the most recent revision of a remote repository::
3460
3452
3461 hg id -r tip http://selenic.com/hg/
3453 hg id -r tip http://selenic.com/hg/
3462
3454
3463 Returns 0 if successful.
3455 Returns 0 if successful.
3464 """
3456 """
3465
3457
3466 if not repo and not source:
3458 if not repo and not source:
3467 raise util.Abort(_("there is no Mercurial repository here "
3459 raise util.Abort(_("there is no Mercurial repository here "
3468 "(.hg not found)"))
3460 "(.hg not found)"))
3469
3461
3470 hexfunc = ui.debugflag and hex or short
3462 hexfunc = ui.debugflag and hex or short
3471 default = not (num or id or branch or tags or bookmarks)
3463 default = not (num or id or branch or tags or bookmarks)
3472 output = []
3464 output = []
3473 revs = []
3465 revs = []
3474
3466
3475 if source:
3467 if source:
3476 source, branches = hg.parseurl(ui.expandpath(source))
3468 source, branches = hg.parseurl(ui.expandpath(source))
3477 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3469 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3478 repo = peer.local()
3470 repo = peer.local()
3479 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3471 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3480
3472
3481 if not repo:
3473 if not repo:
3482 if num or branch or tags:
3474 if num or branch or tags:
3483 raise util.Abort(
3475 raise util.Abort(
3484 _("can't query remote revision number, branch, or tags"))
3476 _("can't query remote revision number, branch, or tags"))
3485 if not rev and revs:
3477 if not rev and revs:
3486 rev = revs[0]
3478 rev = revs[0]
3487 if not rev:
3479 if not rev:
3488 rev = "tip"
3480 rev = "tip"
3489
3481
3490 remoterev = peer.lookup(rev)
3482 remoterev = peer.lookup(rev)
3491 if default or id:
3483 if default or id:
3492 output = [hexfunc(remoterev)]
3484 output = [hexfunc(remoterev)]
3493
3485
3494 def getbms():
3486 def getbms():
3495 bms = []
3487 bms = []
3496
3488
3497 if 'bookmarks' in peer.listkeys('namespaces'):
3489 if 'bookmarks' in peer.listkeys('namespaces'):
3498 hexremoterev = hex(remoterev)
3490 hexremoterev = hex(remoterev)
3499 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3491 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3500 if bmr == hexremoterev]
3492 if bmr == hexremoterev]
3501
3493
3502 return sorted(bms)
3494 return sorted(bms)
3503
3495
3504 if bookmarks:
3496 if bookmarks:
3505 output.extend(getbms())
3497 output.extend(getbms())
3506 elif default and not ui.quiet:
3498 elif default and not ui.quiet:
3507 # multiple bookmarks for a single parent separated by '/'
3499 # multiple bookmarks for a single parent separated by '/'
3508 bm = '/'.join(getbms())
3500 bm = '/'.join(getbms())
3509 if bm:
3501 if bm:
3510 output.append(bm)
3502 output.append(bm)
3511 else:
3503 else:
3512 if not rev:
3504 if not rev:
3513 ctx = repo[None]
3505 ctx = repo[None]
3514 parents = ctx.parents()
3506 parents = ctx.parents()
3515 changed = ""
3507 changed = ""
3516 if default or id or num:
3508 if default or id or num:
3517 if (util.any(repo.status())
3509 if (util.any(repo.status())
3518 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3510 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3519 changed = '+'
3511 changed = '+'
3520 if default or id:
3512 if default or id:
3521 output = ["%s%s" %
3513 output = ["%s%s" %
3522 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3514 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3523 if num:
3515 if num:
3524 output.append("%s%s" %
3516 output.append("%s%s" %
3525 ('+'.join([str(p.rev()) for p in parents]), changed))
3517 ('+'.join([str(p.rev()) for p in parents]), changed))
3526 else:
3518 else:
3527 ctx = scmutil.revsingle(repo, rev)
3519 ctx = scmutil.revsingle(repo, rev)
3528 if default or id:
3520 if default or id:
3529 output = [hexfunc(ctx.node())]
3521 output = [hexfunc(ctx.node())]
3530 if num:
3522 if num:
3531 output.append(str(ctx.rev()))
3523 output.append(str(ctx.rev()))
3532
3524
3533 if default and not ui.quiet:
3525 if default and not ui.quiet:
3534 b = ctx.branch()
3526 b = ctx.branch()
3535 if b != 'default':
3527 if b != 'default':
3536 output.append("(%s)" % b)
3528 output.append("(%s)" % b)
3537
3529
3538 # multiple tags for a single parent separated by '/'
3530 # multiple tags for a single parent separated by '/'
3539 t = '/'.join(ctx.tags())
3531 t = '/'.join(ctx.tags())
3540 if t:
3532 if t:
3541 output.append(t)
3533 output.append(t)
3542
3534
3543 # multiple bookmarks for a single parent separated by '/'
3535 # multiple bookmarks for a single parent separated by '/'
3544 bm = '/'.join(ctx.bookmarks())
3536 bm = '/'.join(ctx.bookmarks())
3545 if bm:
3537 if bm:
3546 output.append(bm)
3538 output.append(bm)
3547 else:
3539 else:
3548 if branch:
3540 if branch:
3549 output.append(ctx.branch())
3541 output.append(ctx.branch())
3550
3542
3551 if tags:
3543 if tags:
3552 output.extend(ctx.tags())
3544 output.extend(ctx.tags())
3553
3545
3554 if bookmarks:
3546 if bookmarks:
3555 output.extend(ctx.bookmarks())
3547 output.extend(ctx.bookmarks())
3556
3548
3557 ui.write("%s\n" % ' '.join(output))
3549 ui.write("%s\n" % ' '.join(output))
3558
3550
3559 @command('import|patch',
3551 @command('import|patch',
3560 [('p', 'strip', 1,
3552 [('p', 'strip', 1,
3561 _('directory strip option for patch. This has the same '
3553 _('directory strip option for patch. This has the same '
3562 'meaning as the corresponding patch option'), _('NUM')),
3554 'meaning as the corresponding patch option'), _('NUM')),
3563 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3555 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3564 ('e', 'edit', False, _('invoke editor on commit messages')),
3556 ('e', 'edit', False, _('invoke editor on commit messages')),
3565 ('f', 'force', None,
3557 ('f', 'force', None,
3566 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3558 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3567 ('', 'no-commit', None,
3559 ('', 'no-commit', None,
3568 _("don't commit, just update the working directory")),
3560 _("don't commit, just update the working directory")),
3569 ('', 'bypass', None,
3561 ('', 'bypass', None,
3570 _("apply patch without touching the working directory")),
3562 _("apply patch without touching the working directory")),
3571 ('', 'exact', None,
3563 ('', 'exact', None,
3572 _('apply patch to the nodes from which it was generated')),
3564 _('apply patch to the nodes from which it was generated')),
3573 ('', 'import-branch', None,
3565 ('', 'import-branch', None,
3574 _('use any branch information in patch (implied by --exact)'))] +
3566 _('use any branch information in patch (implied by --exact)'))] +
3575 commitopts + commitopts2 + similarityopts,
3567 commitopts + commitopts2 + similarityopts,
3576 _('[OPTION]... PATCH...'))
3568 _('[OPTION]... PATCH...'))
3577 def import_(ui, repo, patch1=None, *patches, **opts):
3569 def import_(ui, repo, patch1=None, *patches, **opts):
3578 """import an ordered set of patches
3570 """import an ordered set of patches
3579
3571
3580 Import a list of patches and commit them individually (unless
3572 Import a list of patches and commit them individually (unless
3581 --no-commit is specified).
3573 --no-commit is specified).
3582
3574
3583 Because import first applies changes to the working directory,
3575 Because import first applies changes to the working directory,
3584 import will abort if there are outstanding changes.
3576 import will abort if there are outstanding changes.
3585
3577
3586 You can import a patch straight from a mail message. Even patches
3578 You can import a patch straight from a mail message. Even patches
3587 as attachments work (to use the body part, it must have type
3579 as attachments work (to use the body part, it must have type
3588 text/plain or text/x-patch). From and Subject headers of email
3580 text/plain or text/x-patch). From and Subject headers of email
3589 message are used as default committer and commit message. All
3581 message are used as default committer and commit message. All
3590 text/plain body parts before first diff are added to commit
3582 text/plain body parts before first diff are added to commit
3591 message.
3583 message.
3592
3584
3593 If the imported patch was generated by :hg:`export`, user and
3585 If the imported patch was generated by :hg:`export`, user and
3594 description from patch override values from message headers and
3586 description from patch override values from message headers and
3595 body. Values given on command line with -m/--message and -u/--user
3587 body. Values given on command line with -m/--message and -u/--user
3596 override these.
3588 override these.
3597
3589
3598 If --exact is specified, import will set the working directory to
3590 If --exact is specified, import will set the working directory to
3599 the parent of each patch before applying it, and will abort if the
3591 the parent of each patch before applying it, and will abort if the
3600 resulting changeset has a different ID than the one recorded in
3592 resulting changeset has a different ID than the one recorded in
3601 the patch. This may happen due to character set problems or other
3593 the patch. This may happen due to character set problems or other
3602 deficiencies in the text patch format.
3594 deficiencies in the text patch format.
3603
3595
3604 Use --bypass to apply and commit patches directly to the
3596 Use --bypass to apply and commit patches directly to the
3605 repository, not touching the working directory. Without --exact,
3597 repository, not touching the working directory. Without --exact,
3606 patches will be applied on top of the working directory parent
3598 patches will be applied on top of the working directory parent
3607 revision.
3599 revision.
3608
3600
3609 With -s/--similarity, hg will attempt to discover renames and
3601 With -s/--similarity, hg will attempt to discover renames and
3610 copies in the patch in the same way as :hg:`addremove`.
3602 copies in the patch in the same way as :hg:`addremove`.
3611
3603
3612 To read a patch from standard input, use "-" as the patch name. If
3604 To read a patch from standard input, use "-" as the patch name. If
3613 a URL is specified, the patch will be downloaded from it.
3605 a URL is specified, the patch will be downloaded from it.
3614 See :hg:`help dates` for a list of formats valid for -d/--date.
3606 See :hg:`help dates` for a list of formats valid for -d/--date.
3615
3607
3616 .. container:: verbose
3608 .. container:: verbose
3617
3609
3618 Examples:
3610 Examples:
3619
3611
3620 - import a traditional patch from a website and detect renames::
3612 - import a traditional patch from a website and detect renames::
3621
3613
3622 hg import -s 80 http://example.com/bugfix.patch
3614 hg import -s 80 http://example.com/bugfix.patch
3623
3615
3624 - import a changeset from an hgweb server::
3616 - import a changeset from an hgweb server::
3625
3617
3626 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3618 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3627
3619
3628 - import all the patches in an Unix-style mbox::
3620 - import all the patches in an Unix-style mbox::
3629
3621
3630 hg import incoming-patches.mbox
3622 hg import incoming-patches.mbox
3631
3623
3632 - attempt to exactly restore an exported changeset (not always
3624 - attempt to exactly restore an exported changeset (not always
3633 possible)::
3625 possible)::
3634
3626
3635 hg import --exact proposed-fix.patch
3627 hg import --exact proposed-fix.patch
3636
3628
3637 Returns 0 on success.
3629 Returns 0 on success.
3638 """
3630 """
3639
3631
3640 if not patch1:
3632 if not patch1:
3641 raise util.Abort(_('need at least one patch to import'))
3633 raise util.Abort(_('need at least one patch to import'))
3642
3634
3643 patches = (patch1,) + patches
3635 patches = (patch1,) + patches
3644
3636
3645 date = opts.get('date')
3637 date = opts.get('date')
3646 if date:
3638 if date:
3647 opts['date'] = util.parsedate(date)
3639 opts['date'] = util.parsedate(date)
3648
3640
3649 editor = cmdutil.commiteditor
3641 editor = cmdutil.commiteditor
3650 if opts.get('edit'):
3642 if opts.get('edit'):
3651 editor = cmdutil.commitforceeditor
3643 editor = cmdutil.commitforceeditor
3652
3644
3653 update = not opts.get('bypass')
3645 update = not opts.get('bypass')
3654 if not update and opts.get('no_commit'):
3646 if not update and opts.get('no_commit'):
3655 raise util.Abort(_('cannot use --no-commit with --bypass'))
3647 raise util.Abort(_('cannot use --no-commit with --bypass'))
3656 try:
3648 try:
3657 sim = float(opts.get('similarity') or 0)
3649 sim = float(opts.get('similarity') or 0)
3658 except ValueError:
3650 except ValueError:
3659 raise util.Abort(_('similarity must be a number'))
3651 raise util.Abort(_('similarity must be a number'))
3660 if sim < 0 or sim > 100:
3652 if sim < 0 or sim > 100:
3661 raise util.Abort(_('similarity must be between 0 and 100'))
3653 raise util.Abort(_('similarity must be between 0 and 100'))
3662 if sim and not update:
3654 if sim and not update:
3663 raise util.Abort(_('cannot use --similarity with --bypass'))
3655 raise util.Abort(_('cannot use --similarity with --bypass'))
3664
3656
3665 if update:
3657 if update:
3666 cmdutil.checkunfinished(repo)
3658 cmdutil.checkunfinished(repo)
3667 if (opts.get('exact') or not opts.get('force')) and update:
3659 if (opts.get('exact') or not opts.get('force')) and update:
3668 cmdutil.bailifchanged(repo)
3660 cmdutil.bailifchanged(repo)
3669
3661
3670 base = opts["base"]
3662 base = opts["base"]
3671 strip = opts["strip"]
3663 strip = opts["strip"]
3672 wlock = lock = tr = None
3664 wlock = lock = tr = None
3673 msgs = []
3665 msgs = []
3674
3666
3675 def tryone(ui, hunk, parents):
3667 def tryone(ui, hunk, parents):
3676 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3668 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3677 patch.extract(ui, hunk)
3669 patch.extract(ui, hunk)
3678
3670
3679 if not tmpname:
3671 if not tmpname:
3680 return (None, None)
3672 return (None, None)
3681 msg = _('applied to working directory')
3673 msg = _('applied to working directory')
3682
3674
3683 try:
3675 try:
3684 cmdline_message = cmdutil.logmessage(ui, opts)
3676 cmdline_message = cmdutil.logmessage(ui, opts)
3685 if cmdline_message:
3677 if cmdline_message:
3686 # pickup the cmdline msg
3678 # pickup the cmdline msg
3687 message = cmdline_message
3679 message = cmdline_message
3688 elif message:
3680 elif message:
3689 # pickup the patch msg
3681 # pickup the patch msg
3690 message = message.strip()
3682 message = message.strip()
3691 else:
3683 else:
3692 # launch the editor
3684 # launch the editor
3693 message = None
3685 message = None
3694 ui.debug('message:\n%s\n' % message)
3686 ui.debug('message:\n%s\n' % message)
3695
3687
3696 if len(parents) == 1:
3688 if len(parents) == 1:
3697 parents.append(repo[nullid])
3689 parents.append(repo[nullid])
3698 if opts.get('exact'):
3690 if opts.get('exact'):
3699 if not nodeid or not p1:
3691 if not nodeid or not p1:
3700 raise util.Abort(_('not a Mercurial patch'))
3692 raise util.Abort(_('not a Mercurial patch'))
3701 p1 = repo[p1]
3693 p1 = repo[p1]
3702 p2 = repo[p2 or nullid]
3694 p2 = repo[p2 or nullid]
3703 elif p2:
3695 elif p2:
3704 try:
3696 try:
3705 p1 = repo[p1]
3697 p1 = repo[p1]
3706 p2 = repo[p2]
3698 p2 = repo[p2]
3707 # Without any options, consider p2 only if the
3699 # Without any options, consider p2 only if the
3708 # patch is being applied on top of the recorded
3700 # patch is being applied on top of the recorded
3709 # first parent.
3701 # first parent.
3710 if p1 != parents[0]:
3702 if p1 != parents[0]:
3711 p1 = parents[0]
3703 p1 = parents[0]
3712 p2 = repo[nullid]
3704 p2 = repo[nullid]
3713 except error.RepoError:
3705 except error.RepoError:
3714 p1, p2 = parents
3706 p1, p2 = parents
3715 else:
3707 else:
3716 p1, p2 = parents
3708 p1, p2 = parents
3717
3709
3718 n = None
3710 n = None
3719 if update:
3711 if update:
3720 if p1 != parents[0]:
3712 if p1 != parents[0]:
3721 hg.clean(repo, p1.node())
3713 hg.clean(repo, p1.node())
3722 if p2 != parents[1]:
3714 if p2 != parents[1]:
3723 repo.setparents(p1.node(), p2.node())
3715 repo.setparents(p1.node(), p2.node())
3724
3716
3725 if opts.get('exact') or opts.get('import_branch'):
3717 if opts.get('exact') or opts.get('import_branch'):
3726 repo.dirstate.setbranch(branch or 'default')
3718 repo.dirstate.setbranch(branch or 'default')
3727
3719
3728 files = set()
3720 files = set()
3729 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3721 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3730 eolmode=None, similarity=sim / 100.0)
3722 eolmode=None, similarity=sim / 100.0)
3731 files = list(files)
3723 files = list(files)
3732 if opts.get('no_commit'):
3724 if opts.get('no_commit'):
3733 if message:
3725 if message:
3734 msgs.append(message)
3726 msgs.append(message)
3735 else:
3727 else:
3736 if opts.get('exact') or p2:
3728 if opts.get('exact') or p2:
3737 # If you got here, you either use --force and know what
3729 # If you got here, you either use --force and know what
3738 # you are doing or used --exact or a merge patch while
3730 # you are doing or used --exact or a merge patch while
3739 # being updated to its first parent.
3731 # being updated to its first parent.
3740 m = None
3732 m = None
3741 else:
3733 else:
3742 m = scmutil.matchfiles(repo, files or [])
3734 m = scmutil.matchfiles(repo, files or [])
3743 n = repo.commit(message, opts.get('user') or user,
3735 n = repo.commit(message, opts.get('user') or user,
3744 opts.get('date') or date, match=m,
3736 opts.get('date') or date, match=m,
3745 editor=editor)
3737 editor=editor)
3746 else:
3738 else:
3747 if opts.get('exact') or opts.get('import_branch'):
3739 if opts.get('exact') or opts.get('import_branch'):
3748 branch = branch or 'default'
3740 branch = branch or 'default'
3749 else:
3741 else:
3750 branch = p1.branch()
3742 branch = p1.branch()
3751 store = patch.filestore()
3743 store = patch.filestore()
3752 try:
3744 try:
3753 files = set()
3745 files = set()
3754 try:
3746 try:
3755 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3747 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3756 files, eolmode=None)
3748 files, eolmode=None)
3757 except patch.PatchError, e:
3749 except patch.PatchError, e:
3758 raise util.Abort(str(e))
3750 raise util.Abort(str(e))
3759 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3751 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3760 message,
3752 message,
3761 opts.get('user') or user,
3753 opts.get('user') or user,
3762 opts.get('date') or date,
3754 opts.get('date') or date,
3763 branch, files, store,
3755 branch, files, store,
3764 editor=cmdutil.commiteditor)
3756 editor=cmdutil.commiteditor)
3765 repo.savecommitmessage(memctx.description())
3757 repo.savecommitmessage(memctx.description())
3766 n = memctx.commit()
3758 n = memctx.commit()
3767 finally:
3759 finally:
3768 store.close()
3760 store.close()
3769 if opts.get('exact') and hex(n) != nodeid:
3761 if opts.get('exact') and hex(n) != nodeid:
3770 raise util.Abort(_('patch is damaged or loses information'))
3762 raise util.Abort(_('patch is damaged or loses information'))
3771 if n:
3763 if n:
3772 # i18n: refers to a short changeset id
3764 # i18n: refers to a short changeset id
3773 msg = _('created %s') % short(n)
3765 msg = _('created %s') % short(n)
3774 return (msg, n)
3766 return (msg, n)
3775 finally:
3767 finally:
3776 os.unlink(tmpname)
3768 os.unlink(tmpname)
3777
3769
3778 try:
3770 try:
3779 try:
3771 try:
3780 wlock = repo.wlock()
3772 wlock = repo.wlock()
3781 if not opts.get('no_commit'):
3773 if not opts.get('no_commit'):
3782 lock = repo.lock()
3774 lock = repo.lock()
3783 tr = repo.transaction('import')
3775 tr = repo.transaction('import')
3784 parents = repo.parents()
3776 parents = repo.parents()
3785 for patchurl in patches:
3777 for patchurl in patches:
3786 if patchurl == '-':
3778 if patchurl == '-':
3787 ui.status(_('applying patch from stdin\n'))
3779 ui.status(_('applying patch from stdin\n'))
3788 patchfile = ui.fin
3780 patchfile = ui.fin
3789 patchurl = 'stdin' # for error message
3781 patchurl = 'stdin' # for error message
3790 else:
3782 else:
3791 patchurl = os.path.join(base, patchurl)
3783 patchurl = os.path.join(base, patchurl)
3792 ui.status(_('applying %s\n') % patchurl)
3784 ui.status(_('applying %s\n') % patchurl)
3793 patchfile = hg.openpath(ui, patchurl)
3785 patchfile = hg.openpath(ui, patchurl)
3794
3786
3795 haspatch = False
3787 haspatch = False
3796 for hunk in patch.split(patchfile):
3788 for hunk in patch.split(patchfile):
3797 (msg, node) = tryone(ui, hunk, parents)
3789 (msg, node) = tryone(ui, hunk, parents)
3798 if msg:
3790 if msg:
3799 haspatch = True
3791 haspatch = True
3800 ui.note(msg + '\n')
3792 ui.note(msg + '\n')
3801 if update or opts.get('exact'):
3793 if update or opts.get('exact'):
3802 parents = repo.parents()
3794 parents = repo.parents()
3803 else:
3795 else:
3804 parents = [repo[node]]
3796 parents = [repo[node]]
3805
3797
3806 if not haspatch:
3798 if not haspatch:
3807 raise util.Abort(_('%s: no diffs found') % patchurl)
3799 raise util.Abort(_('%s: no diffs found') % patchurl)
3808
3800
3809 if tr:
3801 if tr:
3810 tr.close()
3802 tr.close()
3811 if msgs:
3803 if msgs:
3812 repo.savecommitmessage('\n* * *\n'.join(msgs))
3804 repo.savecommitmessage('\n* * *\n'.join(msgs))
3813 except: # re-raises
3805 except: # re-raises
3814 # wlock.release() indirectly calls dirstate.write(): since
3806 # wlock.release() indirectly calls dirstate.write(): since
3815 # we're crashing, we do not want to change the working dir
3807 # we're crashing, we do not want to change the working dir
3816 # parent after all, so make sure it writes nothing
3808 # parent after all, so make sure it writes nothing
3817 repo.dirstate.invalidate()
3809 repo.dirstate.invalidate()
3818 raise
3810 raise
3819 finally:
3811 finally:
3820 if tr:
3812 if tr:
3821 tr.release()
3813 tr.release()
3822 release(lock, wlock)
3814 release(lock, wlock)
3823
3815
3824 @command('incoming|in',
3816 @command('incoming|in',
3825 [('f', 'force', None,
3817 [('f', 'force', None,
3826 _('run even if remote repository is unrelated')),
3818 _('run even if remote repository is unrelated')),
3827 ('n', 'newest-first', None, _('show newest record first')),
3819 ('n', 'newest-first', None, _('show newest record first')),
3828 ('', 'bundle', '',
3820 ('', 'bundle', '',
3829 _('file to store the bundles into'), _('FILE')),
3821 _('file to store the bundles into'), _('FILE')),
3830 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3822 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3831 ('B', 'bookmarks', False, _("compare bookmarks")),
3823 ('B', 'bookmarks', False, _("compare bookmarks")),
3832 ('b', 'branch', [],
3824 ('b', 'branch', [],
3833 _('a specific branch you would like to pull'), _('BRANCH')),
3825 _('a specific branch you would like to pull'), _('BRANCH')),
3834 ] + logopts + remoteopts + subrepoopts,
3826 ] + logopts + remoteopts + subrepoopts,
3835 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3827 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3836 def incoming(ui, repo, source="default", **opts):
3828 def incoming(ui, repo, source="default", **opts):
3837 """show new changesets found in source
3829 """show new changesets found in source
3838
3830
3839 Show new changesets found in the specified path/URL or the default
3831 Show new changesets found in the specified path/URL or the default
3840 pull location. These are the changesets that would have been pulled
3832 pull location. These are the changesets that would have been pulled
3841 if a pull at the time you issued this command.
3833 if a pull at the time you issued this command.
3842
3834
3843 For remote repository, using --bundle avoids downloading the
3835 For remote repository, using --bundle avoids downloading the
3844 changesets twice if the incoming is followed by a pull.
3836 changesets twice if the incoming is followed by a pull.
3845
3837
3846 See pull for valid source format details.
3838 See pull for valid source format details.
3847
3839
3848 Returns 0 if there are incoming changes, 1 otherwise.
3840 Returns 0 if there are incoming changes, 1 otherwise.
3849 """
3841 """
3850 if opts.get('graph'):
3842 if opts.get('graph'):
3851 cmdutil.checkunsupportedgraphflags([], opts)
3843 cmdutil.checkunsupportedgraphflags([], opts)
3852 def display(other, chlist, displayer):
3844 def display(other, chlist, displayer):
3853 revdag = cmdutil.graphrevs(other, chlist, opts)
3845 revdag = cmdutil.graphrevs(other, chlist, opts)
3854 showparents = [ctx.node() for ctx in repo[None].parents()]
3846 showparents = [ctx.node() for ctx in repo[None].parents()]
3855 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3847 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3856 graphmod.asciiedges)
3848 graphmod.asciiedges)
3857
3849
3858 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3850 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3859 return 0
3851 return 0
3860
3852
3861 if opts.get('bundle') and opts.get('subrepos'):
3853 if opts.get('bundle') and opts.get('subrepos'):
3862 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3854 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3863
3855
3864 if opts.get('bookmarks'):
3856 if opts.get('bookmarks'):
3865 source, branches = hg.parseurl(ui.expandpath(source),
3857 source, branches = hg.parseurl(ui.expandpath(source),
3866 opts.get('branch'))
3858 opts.get('branch'))
3867 other = hg.peer(repo, opts, source)
3859 other = hg.peer(repo, opts, source)
3868 if 'bookmarks' not in other.listkeys('namespaces'):
3860 if 'bookmarks' not in other.listkeys('namespaces'):
3869 ui.warn(_("remote doesn't support bookmarks\n"))
3861 ui.warn(_("remote doesn't support bookmarks\n"))
3870 return 0
3862 return 0
3871 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3863 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3872 return bookmarks.diff(ui, repo, other)
3864 return bookmarks.diff(ui, repo, other)
3873
3865
3874 repo._subtoppath = ui.expandpath(source)
3866 repo._subtoppath = ui.expandpath(source)
3875 try:
3867 try:
3876 return hg.incoming(ui, repo, source, opts)
3868 return hg.incoming(ui, repo, source, opts)
3877 finally:
3869 finally:
3878 del repo._subtoppath
3870 del repo._subtoppath
3879
3871
3880
3872
3881 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3873 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3882 def init(ui, dest=".", **opts):
3874 def init(ui, dest=".", **opts):
3883 """create a new repository in the given directory
3875 """create a new repository in the given directory
3884
3876
3885 Initialize a new repository in the given directory. If the given
3877 Initialize a new repository in the given directory. If the given
3886 directory does not exist, it will be created.
3878 directory does not exist, it will be created.
3887
3879
3888 If no directory is given, the current directory is used.
3880 If no directory is given, the current directory is used.
3889
3881
3890 It is possible to specify an ``ssh://`` URL as the destination.
3882 It is possible to specify an ``ssh://`` URL as the destination.
3891 See :hg:`help urls` for more information.
3883 See :hg:`help urls` for more information.
3892
3884
3893 Returns 0 on success.
3885 Returns 0 on success.
3894 """
3886 """
3895 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3887 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3896
3888
3897 @command('locate',
3889 @command('locate',
3898 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3890 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3899 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3891 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3900 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3892 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3901 ] + walkopts,
3893 ] + walkopts,
3902 _('[OPTION]... [PATTERN]...'))
3894 _('[OPTION]... [PATTERN]...'))
3903 def locate(ui, repo, *pats, **opts):
3895 def locate(ui, repo, *pats, **opts):
3904 """locate files matching specific patterns
3896 """locate files matching specific patterns
3905
3897
3906 Print files under Mercurial control in the working directory whose
3898 Print files under Mercurial control in the working directory whose
3907 names match the given patterns.
3899 names match the given patterns.
3908
3900
3909 By default, this command searches all directories in the working
3901 By default, this command searches all directories in the working
3910 directory. To search just the current directory and its
3902 directory. To search just the current directory and its
3911 subdirectories, use "--include .".
3903 subdirectories, use "--include .".
3912
3904
3913 If no patterns are given to match, this command prints the names
3905 If no patterns are given to match, this command prints the names
3914 of all files under Mercurial control in the working directory.
3906 of all files under Mercurial control in the working directory.
3915
3907
3916 If you want to feed the output of this command into the "xargs"
3908 If you want to feed the output of this command into the "xargs"
3917 command, use the -0 option to both this command and "xargs". This
3909 command, use the -0 option to both this command and "xargs". This
3918 will avoid the problem of "xargs" treating single filenames that
3910 will avoid the problem of "xargs" treating single filenames that
3919 contain whitespace as multiple filenames.
3911 contain whitespace as multiple filenames.
3920
3912
3921 Returns 0 if a match is found, 1 otherwise.
3913 Returns 0 if a match is found, 1 otherwise.
3922 """
3914 """
3923 end = opts.get('print0') and '\0' or '\n'
3915 end = opts.get('print0') and '\0' or '\n'
3924 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3916 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3925
3917
3926 ret = 1
3918 ret = 1
3927 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3919 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3928 m.bad = lambda x, y: False
3920 m.bad = lambda x, y: False
3929 for abs in repo[rev].walk(m):
3921 for abs in repo[rev].walk(m):
3930 if not rev and abs not in repo.dirstate:
3922 if not rev and abs not in repo.dirstate:
3931 continue
3923 continue
3932 if opts.get('fullpath'):
3924 if opts.get('fullpath'):
3933 ui.write(repo.wjoin(abs), end)
3925 ui.write(repo.wjoin(abs), end)
3934 else:
3926 else:
3935 ui.write(((pats and m.rel(abs)) or abs), end)
3927 ui.write(((pats and m.rel(abs)) or abs), end)
3936 ret = 0
3928 ret = 0
3937
3929
3938 return ret
3930 return ret
3939
3931
3940 @command('^log|history',
3932 @command('^log|history',
3941 [('f', 'follow', None,
3933 [('f', 'follow', None,
3942 _('follow changeset history, or file history across copies and renames')),
3934 _('follow changeset history, or file history across copies and renames')),
3943 ('', 'follow-first', None,
3935 ('', 'follow-first', None,
3944 _('only follow the first parent of merge changesets (DEPRECATED)')),
3936 _('only follow the first parent of merge changesets (DEPRECATED)')),
3945 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3937 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3946 ('C', 'copies', None, _('show copied files')),
3938 ('C', 'copies', None, _('show copied files')),
3947 ('k', 'keyword', [],
3939 ('k', 'keyword', [],
3948 _('do case-insensitive search for a given text'), _('TEXT')),
3940 _('do case-insensitive search for a given text'), _('TEXT')),
3949 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3941 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3950 ('', 'removed', None, _('include revisions where files were removed')),
3942 ('', 'removed', None, _('include revisions where files were removed')),
3951 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3943 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3952 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3944 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3953 ('', 'only-branch', [],
3945 ('', 'only-branch', [],
3954 _('show only changesets within the given named branch (DEPRECATED)'),
3946 _('show only changesets within the given named branch (DEPRECATED)'),
3955 _('BRANCH')),
3947 _('BRANCH')),
3956 ('b', 'branch', [],
3948 ('b', 'branch', [],
3957 _('show changesets within the given named branch'), _('BRANCH')),
3949 _('show changesets within the given named branch'), _('BRANCH')),
3958 ('P', 'prune', [],
3950 ('P', 'prune', [],
3959 _('do not display revision or any of its ancestors'), _('REV')),
3951 _('do not display revision or any of its ancestors'), _('REV')),
3960 ] + logopts + walkopts,
3952 ] + logopts + walkopts,
3961 _('[OPTION]... [FILE]'))
3953 _('[OPTION]... [FILE]'))
3962 def log(ui, repo, *pats, **opts):
3954 def log(ui, repo, *pats, **opts):
3963 """show revision history of entire repository or files
3955 """show revision history of entire repository or files
3964
3956
3965 Print the revision history of the specified files or the entire
3957 Print the revision history of the specified files or the entire
3966 project.
3958 project.
3967
3959
3968 If no revision range is specified, the default is ``tip:0`` unless
3960 If no revision range is specified, the default is ``tip:0`` unless
3969 --follow is set, in which case the working directory parent is
3961 --follow is set, in which case the working directory parent is
3970 used as the starting revision.
3962 used as the starting revision.
3971
3963
3972 File history is shown without following rename or copy history of
3964 File history is shown without following rename or copy history of
3973 files. Use -f/--follow with a filename to follow history across
3965 files. Use -f/--follow with a filename to follow history across
3974 renames and copies. --follow without a filename will only show
3966 renames and copies. --follow without a filename will only show
3975 ancestors or descendants of the starting revision.
3967 ancestors or descendants of the starting revision.
3976
3968
3977 By default this command prints revision number and changeset id,
3969 By default this command prints revision number and changeset id,
3978 tags, non-trivial parents, user, date and time, and a summary for
3970 tags, non-trivial parents, user, date and time, and a summary for
3979 each commit. When the -v/--verbose switch is used, the list of
3971 each commit. When the -v/--verbose switch is used, the list of
3980 changed files and full commit message are shown.
3972 changed files and full commit message are shown.
3981
3973
3982 .. note::
3974 .. note::
3983
3975
3984 log -p/--patch may generate unexpected diff output for merge
3976 log -p/--patch may generate unexpected diff output for merge
3985 changesets, as it will only compare the merge changeset against
3977 changesets, as it will only compare the merge changeset against
3986 its first parent. Also, only files different from BOTH parents
3978 its first parent. Also, only files different from BOTH parents
3987 will appear in files:.
3979 will appear in files:.
3988
3980
3989 .. note::
3981 .. note::
3990
3982
3991 for performance reasons, log FILE may omit duplicate changes
3983 for performance reasons, log FILE may omit duplicate changes
3992 made on branches and will not show deletions. To see all
3984 made on branches and will not show deletions. To see all
3993 changes including duplicates and deletions, use the --removed
3985 changes including duplicates and deletions, use the --removed
3994 switch.
3986 switch.
3995
3987
3996 .. container:: verbose
3988 .. container:: verbose
3997
3989
3998 Some examples:
3990 Some examples:
3999
3991
4000 - changesets with full descriptions and file lists::
3992 - changesets with full descriptions and file lists::
4001
3993
4002 hg log -v
3994 hg log -v
4003
3995
4004 - changesets ancestral to the working directory::
3996 - changesets ancestral to the working directory::
4005
3997
4006 hg log -f
3998 hg log -f
4007
3999
4008 - last 10 commits on the current branch::
4000 - last 10 commits on the current branch::
4009
4001
4010 hg log -l 10 -b .
4002 hg log -l 10 -b .
4011
4003
4012 - changesets showing all modifications of a file, including removals::
4004 - changesets showing all modifications of a file, including removals::
4013
4005
4014 hg log --removed file.c
4006 hg log --removed file.c
4015
4007
4016 - all changesets that touch a directory, with diffs, excluding merges::
4008 - all changesets that touch a directory, with diffs, excluding merges::
4017
4009
4018 hg log -Mp lib/
4010 hg log -Mp lib/
4019
4011
4020 - all revision numbers that match a keyword::
4012 - all revision numbers that match a keyword::
4021
4013
4022 hg log -k bug --template "{rev}\\n"
4014 hg log -k bug --template "{rev}\\n"
4023
4015
4024 - check if a given changeset is included is a tagged release::
4016 - check if a given changeset is included is a tagged release::
4025
4017
4026 hg log -r "a21ccf and ancestor(1.9)"
4018 hg log -r "a21ccf and ancestor(1.9)"
4027
4019
4028 - find all changesets by some user in a date range::
4020 - find all changesets by some user in a date range::
4029
4021
4030 hg log -k alice -d "may 2008 to jul 2008"
4022 hg log -k alice -d "may 2008 to jul 2008"
4031
4023
4032 - summary of all changesets after the last tag::
4024 - summary of all changesets after the last tag::
4033
4025
4034 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4026 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4035
4027
4036 See :hg:`help dates` for a list of formats valid for -d/--date.
4028 See :hg:`help dates` for a list of formats valid for -d/--date.
4037
4029
4038 See :hg:`help revisions` and :hg:`help revsets` for more about
4030 See :hg:`help revisions` and :hg:`help revsets` for more about
4039 specifying revisions.
4031 specifying revisions.
4040
4032
4041 See :hg:`help templates` for more about pre-packaged styles and
4033 See :hg:`help templates` for more about pre-packaged styles and
4042 specifying custom templates.
4034 specifying custom templates.
4043
4035
4044 Returns 0 on success.
4036 Returns 0 on success.
4045 """
4037 """
4046 if opts.get('graph'):
4038 if opts.get('graph'):
4047 return cmdutil.graphlog(ui, repo, *pats, **opts)
4039 return cmdutil.graphlog(ui, repo, *pats, **opts)
4048
4040
4049 matchfn = scmutil.match(repo[None], pats, opts)
4041 matchfn = scmutil.match(repo[None], pats, opts)
4050 limit = cmdutil.loglimit(opts)
4042 limit = cmdutil.loglimit(opts)
4051 count = 0
4043 count = 0
4052
4044
4053 getrenamed, endrev = None, None
4045 getrenamed, endrev = None, None
4054 if opts.get('copies'):
4046 if opts.get('copies'):
4055 if opts.get('rev'):
4047 if opts.get('rev'):
4056 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4048 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4057 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4049 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4058
4050
4059 df = False
4051 df = False
4060 if opts.get("date"):
4052 if opts.get("date"):
4061 df = util.matchdate(opts["date"])
4053 df = util.matchdate(opts["date"])
4062
4054
4063 branches = opts.get('branch', []) + opts.get('only_branch', [])
4055 branches = opts.get('branch', []) + opts.get('only_branch', [])
4064 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4056 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4065
4057
4066 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4058 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4067 def prep(ctx, fns):
4059 def prep(ctx, fns):
4068 rev = ctx.rev()
4060 rev = ctx.rev()
4069 parents = [p for p in repo.changelog.parentrevs(rev)
4061 parents = [p for p in repo.changelog.parentrevs(rev)
4070 if p != nullrev]
4062 if p != nullrev]
4071 if opts.get('no_merges') and len(parents) == 2:
4063 if opts.get('no_merges') and len(parents) == 2:
4072 return
4064 return
4073 if opts.get('only_merges') and len(parents) != 2:
4065 if opts.get('only_merges') and len(parents) != 2:
4074 return
4066 return
4075 if opts.get('branch') and ctx.branch() not in opts['branch']:
4067 if opts.get('branch') and ctx.branch() not in opts['branch']:
4076 return
4068 return
4077 if df and not df(ctx.date()[0]):
4069 if df and not df(ctx.date()[0]):
4078 return
4070 return
4079
4071
4080 lower = encoding.lower
4072 lower = encoding.lower
4081 if opts.get('user'):
4073 if opts.get('user'):
4082 luser = lower(ctx.user())
4074 luser = lower(ctx.user())
4083 for k in [lower(x) for x in opts['user']]:
4075 for k in [lower(x) for x in opts['user']]:
4084 if (k in luser):
4076 if (k in luser):
4085 break
4077 break
4086 else:
4078 else:
4087 return
4079 return
4088 if opts.get('keyword'):
4080 if opts.get('keyword'):
4089 luser = lower(ctx.user())
4081 luser = lower(ctx.user())
4090 ldesc = lower(ctx.description())
4082 ldesc = lower(ctx.description())
4091 lfiles = lower(" ".join(ctx.files()))
4083 lfiles = lower(" ".join(ctx.files()))
4092 for k in [lower(x) for x in opts['keyword']]:
4084 for k in [lower(x) for x in opts['keyword']]:
4093 if (k in luser or k in ldesc or k in lfiles):
4085 if (k in luser or k in ldesc or k in lfiles):
4094 break
4086 break
4095 else:
4087 else:
4096 return
4088 return
4097
4089
4098 copies = None
4090 copies = None
4099 if getrenamed is not None and rev:
4091 if getrenamed is not None and rev:
4100 copies = []
4092 copies = []
4101 for fn in ctx.files():
4093 for fn in ctx.files():
4102 rename = getrenamed(fn, rev)
4094 rename = getrenamed(fn, rev)
4103 if rename:
4095 if rename:
4104 copies.append((fn, rename[0]))
4096 copies.append((fn, rename[0]))
4105
4097
4106 revmatchfn = None
4098 revmatchfn = None
4107 if opts.get('patch') or opts.get('stat'):
4099 if opts.get('patch') or opts.get('stat'):
4108 if opts.get('follow') or opts.get('follow_first'):
4100 if opts.get('follow') or opts.get('follow_first'):
4109 # note: this might be wrong when following through merges
4101 # note: this might be wrong when following through merges
4110 revmatchfn = scmutil.match(repo[None], fns, default='path')
4102 revmatchfn = scmutil.match(repo[None], fns, default='path')
4111 else:
4103 else:
4112 revmatchfn = matchfn
4104 revmatchfn = matchfn
4113
4105
4114 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4106 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4115
4107
4116 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4108 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4117 if displayer.flush(ctx.rev()):
4109 if displayer.flush(ctx.rev()):
4118 count += 1
4110 count += 1
4119 if count == limit:
4111 if count == limit:
4120 break
4112 break
4121 displayer.close()
4113 displayer.close()
4122
4114
4123 @command('manifest',
4115 @command('manifest',
4124 [('r', 'rev', '', _('revision to display'), _('REV')),
4116 [('r', 'rev', '', _('revision to display'), _('REV')),
4125 ('', 'all', False, _("list files from all revisions"))],
4117 ('', 'all', False, _("list files from all revisions"))],
4126 _('[-r REV]'))
4118 _('[-r REV]'))
4127 def manifest(ui, repo, node=None, rev=None, **opts):
4119 def manifest(ui, repo, node=None, rev=None, **opts):
4128 """output the current or given revision of the project manifest
4120 """output the current or given revision of the project manifest
4129
4121
4130 Print a list of version controlled files for the given revision.
4122 Print a list of version controlled files for the given revision.
4131 If no revision is given, the first parent of the working directory
4123 If no revision is given, the first parent of the working directory
4132 is used, or the null revision if no revision is checked out.
4124 is used, or the null revision if no revision is checked out.
4133
4125
4134 With -v, print file permissions, symlink and executable bits.
4126 With -v, print file permissions, symlink and executable bits.
4135 With --debug, print file revision hashes.
4127 With --debug, print file revision hashes.
4136
4128
4137 If option --all is specified, the list of all files from all revisions
4129 If option --all is specified, the list of all files from all revisions
4138 is printed. This includes deleted and renamed files.
4130 is printed. This includes deleted and renamed files.
4139
4131
4140 Returns 0 on success.
4132 Returns 0 on success.
4141 """
4133 """
4142
4134
4143 fm = ui.formatter('manifest', opts)
4135 fm = ui.formatter('manifest', opts)
4144
4136
4145 if opts.get('all'):
4137 if opts.get('all'):
4146 if rev or node:
4138 if rev or node:
4147 raise util.Abort(_("can't specify a revision with --all"))
4139 raise util.Abort(_("can't specify a revision with --all"))
4148
4140
4149 res = []
4141 res = []
4150 prefix = "data/"
4142 prefix = "data/"
4151 suffix = ".i"
4143 suffix = ".i"
4152 plen = len(prefix)
4144 plen = len(prefix)
4153 slen = len(suffix)
4145 slen = len(suffix)
4154 lock = repo.lock()
4146 lock = repo.lock()
4155 try:
4147 try:
4156 for fn, b, size in repo.store.datafiles():
4148 for fn, b, size in repo.store.datafiles():
4157 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4149 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4158 res.append(fn[plen:-slen])
4150 res.append(fn[plen:-slen])
4159 finally:
4151 finally:
4160 lock.release()
4152 lock.release()
4161 for f in res:
4153 for f in res:
4162 fm.startitem()
4154 fm.startitem()
4163 fm.write("path", '%s\n', f)
4155 fm.write("path", '%s\n', f)
4164 fm.end()
4156 fm.end()
4165 return
4157 return
4166
4158
4167 if rev and node:
4159 if rev and node:
4168 raise util.Abort(_("please specify just one revision"))
4160 raise util.Abort(_("please specify just one revision"))
4169
4161
4170 if not node:
4162 if not node:
4171 node = rev
4163 node = rev
4172
4164
4173 char = {'l': '@', 'x': '*', '': ''}
4165 char = {'l': '@', 'x': '*', '': ''}
4174 mode = {'l': '644', 'x': '755', '': '644'}
4166 mode = {'l': '644', 'x': '755', '': '644'}
4175 ctx = scmutil.revsingle(repo, node)
4167 ctx = scmutil.revsingle(repo, node)
4176 mf = ctx.manifest()
4168 mf = ctx.manifest()
4177 for f in ctx:
4169 for f in ctx:
4178 fm.startitem()
4170 fm.startitem()
4179 fl = ctx[f].flags()
4171 fl = ctx[f].flags()
4180 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4172 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4181 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4173 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4182 fm.write('path', '%s\n', f)
4174 fm.write('path', '%s\n', f)
4183 fm.end()
4175 fm.end()
4184
4176
4185 @command('^merge',
4177 @command('^merge',
4186 [('f', 'force', None,
4178 [('f', 'force', None,
4187 _('force a merge including outstanding changes (DEPRECATED)')),
4179 _('force a merge including outstanding changes (DEPRECATED)')),
4188 ('r', 'rev', '', _('revision to merge'), _('REV')),
4180 ('r', 'rev', '', _('revision to merge'), _('REV')),
4189 ('P', 'preview', None,
4181 ('P', 'preview', None,
4190 _('review revisions to merge (no merge is performed)'))
4182 _('review revisions to merge (no merge is performed)'))
4191 ] + mergetoolopts,
4183 ] + mergetoolopts,
4192 _('[-P] [-f] [[-r] REV]'))
4184 _('[-P] [-f] [[-r] REV]'))
4193 def merge(ui, repo, node=None, **opts):
4185 def merge(ui, repo, node=None, **opts):
4194 """merge working directory with another revision
4186 """merge working directory with another revision
4195
4187
4196 The current working directory is updated with all changes made in
4188 The current working directory is updated with all changes made in
4197 the requested revision since the last common predecessor revision.
4189 the requested revision since the last common predecessor revision.
4198
4190
4199 Files that changed between either parent are marked as changed for
4191 Files that changed between either parent are marked as changed for
4200 the next commit and a commit must be performed before any further
4192 the next commit and a commit must be performed before any further
4201 updates to the repository are allowed. The next commit will have
4193 updates to the repository are allowed. The next commit will have
4202 two parents.
4194 two parents.
4203
4195
4204 ``--tool`` can be used to specify the merge tool used for file
4196 ``--tool`` can be used to specify the merge tool used for file
4205 merges. It overrides the HGMERGE environment variable and your
4197 merges. It overrides the HGMERGE environment variable and your
4206 configuration files. See :hg:`help merge-tools` for options.
4198 configuration files. See :hg:`help merge-tools` for options.
4207
4199
4208 If no revision is specified, the working directory's parent is a
4200 If no revision is specified, the working directory's parent is a
4209 head revision, and the current branch contains exactly one other
4201 head revision, and the current branch contains exactly one other
4210 head, the other head is merged with by default. Otherwise, an
4202 head, the other head is merged with by default. Otherwise, an
4211 explicit revision with which to merge with must be provided.
4203 explicit revision with which to merge with must be provided.
4212
4204
4213 :hg:`resolve` must be used to resolve unresolved files.
4205 :hg:`resolve` must be used to resolve unresolved files.
4214
4206
4215 To undo an uncommitted merge, use :hg:`update --clean .` which
4207 To undo an uncommitted merge, use :hg:`update --clean .` which
4216 will check out a clean copy of the original merge parent, losing
4208 will check out a clean copy of the original merge parent, losing
4217 all changes.
4209 all changes.
4218
4210
4219 Returns 0 on success, 1 if there are unresolved files.
4211 Returns 0 on success, 1 if there are unresolved files.
4220 """
4212 """
4221
4213
4222 if opts.get('rev') and node:
4214 if opts.get('rev') and node:
4223 raise util.Abort(_("please specify just one revision"))
4215 raise util.Abort(_("please specify just one revision"))
4224 if not node:
4216 if not node:
4225 node = opts.get('rev')
4217 node = opts.get('rev')
4226
4218
4227 if node:
4219 if node:
4228 node = scmutil.revsingle(repo, node).node()
4220 node = scmutil.revsingle(repo, node).node()
4229
4221
4230 if not node and repo._bookmarkcurrent:
4222 if not node and repo._bookmarkcurrent:
4231 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4223 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4232 curhead = repo[repo._bookmarkcurrent].node()
4224 curhead = repo[repo._bookmarkcurrent].node()
4233 if len(bmheads) == 2:
4225 if len(bmheads) == 2:
4234 if curhead == bmheads[0]:
4226 if curhead == bmheads[0]:
4235 node = bmheads[1]
4227 node = bmheads[1]
4236 else:
4228 else:
4237 node = bmheads[0]
4229 node = bmheads[0]
4238 elif len(bmheads) > 2:
4230 elif len(bmheads) > 2:
4239 raise util.Abort(_("multiple matching bookmarks to merge - "
4231 raise util.Abort(_("multiple matching bookmarks to merge - "
4240 "please merge with an explicit rev or bookmark"),
4232 "please merge with an explicit rev or bookmark"),
4241 hint=_("run 'hg heads' to see all heads"))
4233 hint=_("run 'hg heads' to see all heads"))
4242 elif len(bmheads) <= 1:
4234 elif len(bmheads) <= 1:
4243 raise util.Abort(_("no matching bookmark to merge - "
4235 raise util.Abort(_("no matching bookmark to merge - "
4244 "please merge with an explicit rev or bookmark"),
4236 "please merge with an explicit rev or bookmark"),
4245 hint=_("run 'hg heads' to see all heads"))
4237 hint=_("run 'hg heads' to see all heads"))
4246
4238
4247 if not node and not repo._bookmarkcurrent:
4239 if not node and not repo._bookmarkcurrent:
4248 branch = repo[None].branch()
4240 branch = repo[None].branch()
4249 bheads = repo.branchheads(branch)
4241 bheads = repo.branchheads(branch)
4250 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4242 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4251
4243
4252 if len(nbhs) > 2:
4244 if len(nbhs) > 2:
4253 raise util.Abort(_("branch '%s' has %d heads - "
4245 raise util.Abort(_("branch '%s' has %d heads - "
4254 "please merge with an explicit rev")
4246 "please merge with an explicit rev")
4255 % (branch, len(bheads)),
4247 % (branch, len(bheads)),
4256 hint=_("run 'hg heads .' to see heads"))
4248 hint=_("run 'hg heads .' to see heads"))
4257
4249
4258 parent = repo.dirstate.p1()
4250 parent = repo.dirstate.p1()
4259 if len(nbhs) <= 1:
4251 if len(nbhs) <= 1:
4260 if len(bheads) > 1:
4252 if len(bheads) > 1:
4261 raise util.Abort(_("heads are bookmarked - "
4253 raise util.Abort(_("heads are bookmarked - "
4262 "please merge with an explicit rev"),
4254 "please merge with an explicit rev"),
4263 hint=_("run 'hg heads' to see all heads"))
4255 hint=_("run 'hg heads' to see all heads"))
4264 if len(repo.heads()) > 1:
4256 if len(repo.heads()) > 1:
4265 raise util.Abort(_("branch '%s' has one head - "
4257 raise util.Abort(_("branch '%s' has one head - "
4266 "please merge with an explicit rev")
4258 "please merge with an explicit rev")
4267 % branch,
4259 % branch,
4268 hint=_("run 'hg heads' to see all heads"))
4260 hint=_("run 'hg heads' to see all heads"))
4269 msg, hint = _('nothing to merge'), None
4261 msg, hint = _('nothing to merge'), None
4270 if parent != repo.lookup(branch):
4262 if parent != repo.lookup(branch):
4271 hint = _("use 'hg update' instead")
4263 hint = _("use 'hg update' instead")
4272 raise util.Abort(msg, hint=hint)
4264 raise util.Abort(msg, hint=hint)
4273
4265
4274 if parent not in bheads:
4266 if parent not in bheads:
4275 raise util.Abort(_('working directory not at a head revision'),
4267 raise util.Abort(_('working directory not at a head revision'),
4276 hint=_("use 'hg update' or merge with an "
4268 hint=_("use 'hg update' or merge with an "
4277 "explicit revision"))
4269 "explicit revision"))
4278 if parent == nbhs[0]:
4270 if parent == nbhs[0]:
4279 node = nbhs[-1]
4271 node = nbhs[-1]
4280 else:
4272 else:
4281 node = nbhs[0]
4273 node = nbhs[0]
4282
4274
4283 if opts.get('preview'):
4275 if opts.get('preview'):
4284 # find nodes that are ancestors of p2 but not of p1
4276 # find nodes that are ancestors of p2 but not of p1
4285 p1 = repo.lookup('.')
4277 p1 = repo.lookup('.')
4286 p2 = repo.lookup(node)
4278 p2 = repo.lookup(node)
4287 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4279 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4288
4280
4289 displayer = cmdutil.show_changeset(ui, repo, opts)
4281 displayer = cmdutil.show_changeset(ui, repo, opts)
4290 for node in nodes:
4282 for node in nodes:
4291 displayer.show(repo[node])
4283 displayer.show(repo[node])
4292 displayer.close()
4284 displayer.close()
4293 return 0
4285 return 0
4294
4286
4295 try:
4287 try:
4296 # ui.forcemerge is an internal variable, do not document
4288 # ui.forcemerge is an internal variable, do not document
4297 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4289 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4298 return hg.merge(repo, node, force=opts.get('force'))
4290 return hg.merge(repo, node, force=opts.get('force'))
4299 finally:
4291 finally:
4300 ui.setconfig('ui', 'forcemerge', '')
4292 ui.setconfig('ui', 'forcemerge', '')
4301
4293
4302 @command('outgoing|out',
4294 @command('outgoing|out',
4303 [('f', 'force', None, _('run even when the destination is unrelated')),
4295 [('f', 'force', None, _('run even when the destination is unrelated')),
4304 ('r', 'rev', [],
4296 ('r', 'rev', [],
4305 _('a changeset intended to be included in the destination'), _('REV')),
4297 _('a changeset intended to be included in the destination'), _('REV')),
4306 ('n', 'newest-first', None, _('show newest record first')),
4298 ('n', 'newest-first', None, _('show newest record first')),
4307 ('B', 'bookmarks', False, _('compare bookmarks')),
4299 ('B', 'bookmarks', False, _('compare bookmarks')),
4308 ('b', 'branch', [], _('a specific branch you would like to push'),
4300 ('b', 'branch', [], _('a specific branch you would like to push'),
4309 _('BRANCH')),
4301 _('BRANCH')),
4310 ] + logopts + remoteopts + subrepoopts,
4302 ] + logopts + remoteopts + subrepoopts,
4311 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4303 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4312 def outgoing(ui, repo, dest=None, **opts):
4304 def outgoing(ui, repo, dest=None, **opts):
4313 """show changesets not found in the destination
4305 """show changesets not found in the destination
4314
4306
4315 Show changesets not found in the specified destination repository
4307 Show changesets not found in the specified destination repository
4316 or the default push location. These are the changesets that would
4308 or the default push location. These are the changesets that would
4317 be pushed if a push was requested.
4309 be pushed if a push was requested.
4318
4310
4319 See pull for details of valid destination formats.
4311 See pull for details of valid destination formats.
4320
4312
4321 Returns 0 if there are outgoing changes, 1 otherwise.
4313 Returns 0 if there are outgoing changes, 1 otherwise.
4322 """
4314 """
4323 if opts.get('graph'):
4315 if opts.get('graph'):
4324 cmdutil.checkunsupportedgraphflags([], opts)
4316 cmdutil.checkunsupportedgraphflags([], opts)
4325 o = hg._outgoing(ui, repo, dest, opts)
4317 o = hg._outgoing(ui, repo, dest, opts)
4326 if o is None:
4318 if o is None:
4327 return
4319 return
4328
4320
4329 revdag = cmdutil.graphrevs(repo, o, opts)
4321 revdag = cmdutil.graphrevs(repo, o, opts)
4330 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4322 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4331 showparents = [ctx.node() for ctx in repo[None].parents()]
4323 showparents = [ctx.node() for ctx in repo[None].parents()]
4332 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4324 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4333 graphmod.asciiedges)
4325 graphmod.asciiedges)
4334 return 0
4326 return 0
4335
4327
4336 if opts.get('bookmarks'):
4328 if opts.get('bookmarks'):
4337 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4329 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4338 dest, branches = hg.parseurl(dest, opts.get('branch'))
4330 dest, branches = hg.parseurl(dest, opts.get('branch'))
4339 other = hg.peer(repo, opts, dest)
4331 other = hg.peer(repo, opts, dest)
4340 if 'bookmarks' not in other.listkeys('namespaces'):
4332 if 'bookmarks' not in other.listkeys('namespaces'):
4341 ui.warn(_("remote doesn't support bookmarks\n"))
4333 ui.warn(_("remote doesn't support bookmarks\n"))
4342 return 0
4334 return 0
4343 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4335 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4344 return bookmarks.diff(ui, other, repo)
4336 return bookmarks.diff(ui, other, repo)
4345
4337
4346 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4338 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4347 try:
4339 try:
4348 return hg.outgoing(ui, repo, dest, opts)
4340 return hg.outgoing(ui, repo, dest, opts)
4349 finally:
4341 finally:
4350 del repo._subtoppath
4342 del repo._subtoppath
4351
4343
4352 @command('parents',
4344 @command('parents',
4353 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4345 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4354 ] + templateopts,
4346 ] + templateopts,
4355 _('[-r REV] [FILE]'))
4347 _('[-r REV] [FILE]'))
4356 def parents(ui, repo, file_=None, **opts):
4348 def parents(ui, repo, file_=None, **opts):
4357 """show the parents of the working directory or revision
4349 """show the parents of the working directory or revision
4358
4350
4359 Print the working directory's parent revisions. If a revision is
4351 Print the working directory's parent revisions. If a revision is
4360 given via -r/--rev, the parent of that revision will be printed.
4352 given via -r/--rev, the parent of that revision will be printed.
4361 If a file argument is given, the revision in which the file was
4353 If a file argument is given, the revision in which the file was
4362 last changed (before the working directory revision or the
4354 last changed (before the working directory revision or the
4363 argument to --rev if given) is printed.
4355 argument to --rev if given) is printed.
4364
4356
4365 Returns 0 on success.
4357 Returns 0 on success.
4366 """
4358 """
4367
4359
4368 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4360 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4369
4361
4370 if file_:
4362 if file_:
4371 m = scmutil.match(ctx, (file_,), opts)
4363 m = scmutil.match(ctx, (file_,), opts)
4372 if m.anypats() or len(m.files()) != 1:
4364 if m.anypats() or len(m.files()) != 1:
4373 raise util.Abort(_('can only specify an explicit filename'))
4365 raise util.Abort(_('can only specify an explicit filename'))
4374 file_ = m.files()[0]
4366 file_ = m.files()[0]
4375 filenodes = []
4367 filenodes = []
4376 for cp in ctx.parents():
4368 for cp in ctx.parents():
4377 if not cp:
4369 if not cp:
4378 continue
4370 continue
4379 try:
4371 try:
4380 filenodes.append(cp.filenode(file_))
4372 filenodes.append(cp.filenode(file_))
4381 except error.LookupError:
4373 except error.LookupError:
4382 pass
4374 pass
4383 if not filenodes:
4375 if not filenodes:
4384 raise util.Abort(_("'%s' not found in manifest!") % file_)
4376 raise util.Abort(_("'%s' not found in manifest!") % file_)
4385 p = []
4377 p = []
4386 for fn in filenodes:
4378 for fn in filenodes:
4387 fctx = repo.filectx(file_, fileid=fn)
4379 fctx = repo.filectx(file_, fileid=fn)
4388 p.append(fctx.node())
4380 p.append(fctx.node())
4389 else:
4381 else:
4390 p = [cp.node() for cp in ctx.parents()]
4382 p = [cp.node() for cp in ctx.parents()]
4391
4383
4392 displayer = cmdutil.show_changeset(ui, repo, opts)
4384 displayer = cmdutil.show_changeset(ui, repo, opts)
4393 for n in p:
4385 for n in p:
4394 if n != nullid:
4386 if n != nullid:
4395 displayer.show(repo[n])
4387 displayer.show(repo[n])
4396 displayer.close()
4388 displayer.close()
4397
4389
4398 @command('paths', [], _('[NAME]'))
4390 @command('paths', [], _('[NAME]'))
4399 def paths(ui, repo, search=None):
4391 def paths(ui, repo, search=None):
4400 """show aliases for remote repositories
4392 """show aliases for remote repositories
4401
4393
4402 Show definition of symbolic path name NAME. If no name is given,
4394 Show definition of symbolic path name NAME. If no name is given,
4403 show definition of all available names.
4395 show definition of all available names.
4404
4396
4405 Option -q/--quiet suppresses all output when searching for NAME
4397 Option -q/--quiet suppresses all output when searching for NAME
4406 and shows only the path names when listing all definitions.
4398 and shows only the path names when listing all definitions.
4407
4399
4408 Path names are defined in the [paths] section of your
4400 Path names are defined in the [paths] section of your
4409 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4401 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4410 repository, ``.hg/hgrc`` is used, too.
4402 repository, ``.hg/hgrc`` is used, too.
4411
4403
4412 The path names ``default`` and ``default-push`` have a special
4404 The path names ``default`` and ``default-push`` have a special
4413 meaning. When performing a push or pull operation, they are used
4405 meaning. When performing a push or pull operation, they are used
4414 as fallbacks if no location is specified on the command-line.
4406 as fallbacks if no location is specified on the command-line.
4415 When ``default-push`` is set, it will be used for push and
4407 When ``default-push`` is set, it will be used for push and
4416 ``default`` will be used for pull; otherwise ``default`` is used
4408 ``default`` will be used for pull; otherwise ``default`` is used
4417 as the fallback for both. When cloning a repository, the clone
4409 as the fallback for both. When cloning a repository, the clone
4418 source is written as ``default`` in ``.hg/hgrc``. Note that
4410 source is written as ``default`` in ``.hg/hgrc``. Note that
4419 ``default`` and ``default-push`` apply to all inbound (e.g.
4411 ``default`` and ``default-push`` apply to all inbound (e.g.
4420 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4412 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4421 :hg:`bundle`) operations.
4413 :hg:`bundle`) operations.
4422
4414
4423 See :hg:`help urls` for more information.
4415 See :hg:`help urls` for more information.
4424
4416
4425 Returns 0 on success.
4417 Returns 0 on success.
4426 """
4418 """
4427 if search:
4419 if search:
4428 for name, path in ui.configitems("paths"):
4420 for name, path in ui.configitems("paths"):
4429 if name == search:
4421 if name == search:
4430 ui.status("%s\n" % util.hidepassword(path))
4422 ui.status("%s\n" % util.hidepassword(path))
4431 return
4423 return
4432 if not ui.quiet:
4424 if not ui.quiet:
4433 ui.warn(_("not found!\n"))
4425 ui.warn(_("not found!\n"))
4434 return 1
4426 return 1
4435 else:
4427 else:
4436 for name, path in ui.configitems("paths"):
4428 for name, path in ui.configitems("paths"):
4437 if ui.quiet:
4429 if ui.quiet:
4438 ui.write("%s\n" % name)
4430 ui.write("%s\n" % name)
4439 else:
4431 else:
4440 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4432 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4441
4433
4442 @command('phase',
4434 @command('phase',
4443 [('p', 'public', False, _('set changeset phase to public')),
4435 [('p', 'public', False, _('set changeset phase to public')),
4444 ('d', 'draft', False, _('set changeset phase to draft')),
4436 ('d', 'draft', False, _('set changeset phase to draft')),
4445 ('s', 'secret', False, _('set changeset phase to secret')),
4437 ('s', 'secret', False, _('set changeset phase to secret')),
4446 ('f', 'force', False, _('allow to move boundary backward')),
4438 ('f', 'force', False, _('allow to move boundary backward')),
4447 ('r', 'rev', [], _('target revision'), _('REV')),
4439 ('r', 'rev', [], _('target revision'), _('REV')),
4448 ],
4440 ],
4449 _('[-p|-d|-s] [-f] [-r] REV...'))
4441 _('[-p|-d|-s] [-f] [-r] REV...'))
4450 def phase(ui, repo, *revs, **opts):
4442 def phase(ui, repo, *revs, **opts):
4451 """set or show the current phase name
4443 """set or show the current phase name
4452
4444
4453 With no argument, show the phase name of specified revisions.
4445 With no argument, show the phase name of specified revisions.
4454
4446
4455 With one of -p/--public, -d/--draft or -s/--secret, change the
4447 With one of -p/--public, -d/--draft or -s/--secret, change the
4456 phase value of the specified revisions.
4448 phase value of the specified revisions.
4457
4449
4458 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4450 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4459 lower phase to an higher phase. Phases are ordered as follows::
4451 lower phase to an higher phase. Phases are ordered as follows::
4460
4452
4461 public < draft < secret
4453 public < draft < secret
4462
4454
4463 Return 0 on success, 1 if no phases were changed or some could not
4455 Return 0 on success, 1 if no phases were changed or some could not
4464 be changed.
4456 be changed.
4465 """
4457 """
4466 # search for a unique phase argument
4458 # search for a unique phase argument
4467 targetphase = None
4459 targetphase = None
4468 for idx, name in enumerate(phases.phasenames):
4460 for idx, name in enumerate(phases.phasenames):
4469 if opts[name]:
4461 if opts[name]:
4470 if targetphase is not None:
4462 if targetphase is not None:
4471 raise util.Abort(_('only one phase can be specified'))
4463 raise util.Abort(_('only one phase can be specified'))
4472 targetphase = idx
4464 targetphase = idx
4473
4465
4474 # look for specified revision
4466 # look for specified revision
4475 revs = list(revs)
4467 revs = list(revs)
4476 revs.extend(opts['rev'])
4468 revs.extend(opts['rev'])
4477 if not revs:
4469 if not revs:
4478 raise util.Abort(_('no revisions specified'))
4470 raise util.Abort(_('no revisions specified'))
4479
4471
4480 revs = scmutil.revrange(repo, revs)
4472 revs = scmutil.revrange(repo, revs)
4481
4473
4482 lock = None
4474 lock = None
4483 ret = 0
4475 ret = 0
4484 if targetphase is None:
4476 if targetphase is None:
4485 # display
4477 # display
4486 for r in revs:
4478 for r in revs:
4487 ctx = repo[r]
4479 ctx = repo[r]
4488 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4480 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4489 else:
4481 else:
4490 lock = repo.lock()
4482 lock = repo.lock()
4491 try:
4483 try:
4492 # set phase
4484 # set phase
4493 if not revs:
4485 if not revs:
4494 raise util.Abort(_('empty revision set'))
4486 raise util.Abort(_('empty revision set'))
4495 nodes = [repo[r].node() for r in revs]
4487 nodes = [repo[r].node() for r in revs]
4496 olddata = repo._phasecache.getphaserevs(repo)[:]
4488 olddata = repo._phasecache.getphaserevs(repo)[:]
4497 phases.advanceboundary(repo, targetphase, nodes)
4489 phases.advanceboundary(repo, targetphase, nodes)
4498 if opts['force']:
4490 if opts['force']:
4499 phases.retractboundary(repo, targetphase, nodes)
4491 phases.retractboundary(repo, targetphase, nodes)
4500 finally:
4492 finally:
4501 lock.release()
4493 lock.release()
4502 # moving revision from public to draft may hide them
4494 # moving revision from public to draft may hide them
4503 # We have to check result on an unfiltered repository
4495 # We have to check result on an unfiltered repository
4504 unfi = repo.unfiltered()
4496 unfi = repo.unfiltered()
4505 newdata = repo._phasecache.getphaserevs(unfi)
4497 newdata = repo._phasecache.getphaserevs(unfi)
4506 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4498 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4507 cl = unfi.changelog
4499 cl = unfi.changelog
4508 rejected = [n for n in nodes
4500 rejected = [n for n in nodes
4509 if newdata[cl.rev(n)] < targetphase]
4501 if newdata[cl.rev(n)] < targetphase]
4510 if rejected:
4502 if rejected:
4511 ui.warn(_('cannot move %i changesets to a higher '
4503 ui.warn(_('cannot move %i changesets to a higher '
4512 'phase, use --force\n') % len(rejected))
4504 'phase, use --force\n') % len(rejected))
4513 ret = 1
4505 ret = 1
4514 if changes:
4506 if changes:
4515 msg = _('phase changed for %i changesets\n') % changes
4507 msg = _('phase changed for %i changesets\n') % changes
4516 if ret:
4508 if ret:
4517 ui.status(msg)
4509 ui.status(msg)
4518 else:
4510 else:
4519 ui.note(msg)
4511 ui.note(msg)
4520 else:
4512 else:
4521 ui.warn(_('no phases changed\n'))
4513 ui.warn(_('no phases changed\n'))
4522 ret = 1
4514 ret = 1
4523 return ret
4515 return ret
4524
4516
4525 def postincoming(ui, repo, modheads, optupdate, checkout):
4517 def postincoming(ui, repo, modheads, optupdate, checkout):
4526 if modheads == 0:
4518 if modheads == 0:
4527 return
4519 return
4528 if optupdate:
4520 if optupdate:
4529 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4521 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4530 try:
4522 try:
4531 ret = hg.update(repo, checkout)
4523 ret = hg.update(repo, checkout)
4532 except util.Abort, inst:
4524 except util.Abort, inst:
4533 ui.warn(_("not updating: %s\n") % str(inst))
4525 ui.warn(_("not updating: %s\n") % str(inst))
4534 if inst.hint:
4526 if inst.hint:
4535 ui.warn(_("(%s)\n") % inst.hint)
4527 ui.warn(_("(%s)\n") % inst.hint)
4536 return 0
4528 return 0
4537 if not ret and not checkout:
4529 if not ret and not checkout:
4538 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4530 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4539 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4531 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4540 return ret
4532 return ret
4541 if modheads > 1:
4533 if modheads > 1:
4542 currentbranchheads = len(repo.branchheads())
4534 currentbranchheads = len(repo.branchheads())
4543 if currentbranchheads == modheads:
4535 if currentbranchheads == modheads:
4544 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4536 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4545 elif currentbranchheads > 1:
4537 elif currentbranchheads > 1:
4546 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4538 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4547 "merge)\n"))
4539 "merge)\n"))
4548 else:
4540 else:
4549 ui.status(_("(run 'hg heads' to see heads)\n"))
4541 ui.status(_("(run 'hg heads' to see heads)\n"))
4550 else:
4542 else:
4551 ui.status(_("(run 'hg update' to get a working copy)\n"))
4543 ui.status(_("(run 'hg update' to get a working copy)\n"))
4552
4544
4553 @command('^pull',
4545 @command('^pull',
4554 [('u', 'update', None,
4546 [('u', 'update', None,
4555 _('update to new branch head if changesets were pulled')),
4547 _('update to new branch head if changesets were pulled')),
4556 ('f', 'force', None, _('run even when remote repository is unrelated')),
4548 ('f', 'force', None, _('run even when remote repository is unrelated')),
4557 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4549 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4558 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4550 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4559 ('b', 'branch', [], _('a specific branch you would like to pull'),
4551 ('b', 'branch', [], _('a specific branch you would like to pull'),
4560 _('BRANCH')),
4552 _('BRANCH')),
4561 ] + remoteopts,
4553 ] + remoteopts,
4562 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4554 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4563 def pull(ui, repo, source="default", **opts):
4555 def pull(ui, repo, source="default", **opts):
4564 """pull changes from the specified source
4556 """pull changes from the specified source
4565
4557
4566 Pull changes from a remote repository to a local one.
4558 Pull changes from a remote repository to a local one.
4567
4559
4568 This finds all changes from the repository at the specified path
4560 This finds all changes from the repository at the specified path
4569 or URL and adds them to a local repository (the current one unless
4561 or URL and adds them to a local repository (the current one unless
4570 -R is specified). By default, this does not update the copy of the
4562 -R is specified). By default, this does not update the copy of the
4571 project in the working directory.
4563 project in the working directory.
4572
4564
4573 Use :hg:`incoming` if you want to see what would have been added
4565 Use :hg:`incoming` if you want to see what would have been added
4574 by a pull at the time you issued this command. If you then decide
4566 by a pull at the time you issued this command. If you then decide
4575 to add those changes to the repository, you should use :hg:`pull
4567 to add those changes to the repository, you should use :hg:`pull
4576 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4568 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4577
4569
4578 If SOURCE is omitted, the 'default' path will be used.
4570 If SOURCE is omitted, the 'default' path will be used.
4579 See :hg:`help urls` for more information.
4571 See :hg:`help urls` for more information.
4580
4572
4581 Returns 0 on success, 1 if an update had unresolved files.
4573 Returns 0 on success, 1 if an update had unresolved files.
4582 """
4574 """
4583 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4575 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4584 other = hg.peer(repo, opts, source)
4576 other = hg.peer(repo, opts, source)
4585 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4577 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4586 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4578 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4587
4579
4588 remotebookmarks = other.listkeys('bookmarks')
4580 remotebookmarks = other.listkeys('bookmarks')
4589
4581
4590 if opts.get('bookmark'):
4582 if opts.get('bookmark'):
4591 if not revs:
4583 if not revs:
4592 revs = []
4584 revs = []
4593 for b in opts['bookmark']:
4585 for b in opts['bookmark']:
4594 if b not in remotebookmarks:
4586 if b not in remotebookmarks:
4595 raise util.Abort(_('remote bookmark %s not found!') % b)
4587 raise util.Abort(_('remote bookmark %s not found!') % b)
4596 revs.append(remotebookmarks[b])
4588 revs.append(remotebookmarks[b])
4597
4589
4598 if revs:
4590 if revs:
4599 try:
4591 try:
4600 revs = [other.lookup(rev) for rev in revs]
4592 revs = [other.lookup(rev) for rev in revs]
4601 except error.CapabilityError:
4593 except error.CapabilityError:
4602 err = _("other repository doesn't support revision lookup, "
4594 err = _("other repository doesn't support revision lookup, "
4603 "so a rev cannot be specified.")
4595 "so a rev cannot be specified.")
4604 raise util.Abort(err)
4596 raise util.Abort(err)
4605
4597
4606 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4598 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4607 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4599 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4608 if checkout:
4600 if checkout:
4609 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4601 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4610 repo._subtoppath = source
4602 repo._subtoppath = source
4611 try:
4603 try:
4612 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4604 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4613
4605
4614 finally:
4606 finally:
4615 del repo._subtoppath
4607 del repo._subtoppath
4616
4608
4617 # update specified bookmarks
4609 # update specified bookmarks
4618 if opts.get('bookmark'):
4610 if opts.get('bookmark'):
4619 marks = repo._bookmarks
4611 marks = repo._bookmarks
4620 for b in opts['bookmark']:
4612 for b in opts['bookmark']:
4621 # explicit pull overrides local bookmark if any
4613 # explicit pull overrides local bookmark if any
4622 ui.status(_("importing bookmark %s\n") % b)
4614 ui.status(_("importing bookmark %s\n") % b)
4623 marks[b] = repo[remotebookmarks[b]].node()
4615 marks[b] = repo[remotebookmarks[b]].node()
4624 marks.write()
4616 marks.write()
4625
4617
4626 return ret
4618 return ret
4627
4619
4628 @command('^push',
4620 @command('^push',
4629 [('f', 'force', None, _('force push')),
4621 [('f', 'force', None, _('force push')),
4630 ('r', 'rev', [],
4622 ('r', 'rev', [],
4631 _('a changeset intended to be included in the destination'),
4623 _('a changeset intended to be included in the destination'),
4632 _('REV')),
4624 _('REV')),
4633 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4625 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4634 ('b', 'branch', [],
4626 ('b', 'branch', [],
4635 _('a specific branch you would like to push'), _('BRANCH')),
4627 _('a specific branch you would like to push'), _('BRANCH')),
4636 ('', 'new-branch', False, _('allow pushing a new branch')),
4628 ('', 'new-branch', False, _('allow pushing a new branch')),
4637 ] + remoteopts,
4629 ] + remoteopts,
4638 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4630 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4639 def push(ui, repo, dest=None, **opts):
4631 def push(ui, repo, dest=None, **opts):
4640 """push changes to the specified destination
4632 """push changes to the specified destination
4641
4633
4642 Push changesets from the local repository to the specified
4634 Push changesets from the local repository to the specified
4643 destination.
4635 destination.
4644
4636
4645 This operation is symmetrical to pull: it is identical to a pull
4637 This operation is symmetrical to pull: it is identical to a pull
4646 in the destination repository from the current one.
4638 in the destination repository from the current one.
4647
4639
4648 By default, push will not allow creation of new heads at the
4640 By default, push will not allow creation of new heads at the
4649 destination, since multiple heads would make it unclear which head
4641 destination, since multiple heads would make it unclear which head
4650 to use. In this situation, it is recommended to pull and merge
4642 to use. In this situation, it is recommended to pull and merge
4651 before pushing.
4643 before pushing.
4652
4644
4653 Use --new-branch if you want to allow push to create a new named
4645 Use --new-branch if you want to allow push to create a new named
4654 branch that is not present at the destination. This allows you to
4646 branch that is not present at the destination. This allows you to
4655 only create a new branch without forcing other changes.
4647 only create a new branch without forcing other changes.
4656
4648
4657 .. note::
4649 .. note::
4658
4650
4659 Extra care should be taken with the -f/--force option,
4651 Extra care should be taken with the -f/--force option,
4660 which will push all new heads on all branches, an action which will
4652 which will push all new heads on all branches, an action which will
4661 almost always cause confusion for collaborators.
4653 almost always cause confusion for collaborators.
4662
4654
4663 If -r/--rev is used, the specified revision and all its ancestors
4655 If -r/--rev is used, the specified revision and all its ancestors
4664 will be pushed to the remote repository.
4656 will be pushed to the remote repository.
4665
4657
4666 If -B/--bookmark is used, the specified bookmarked revision, its
4658 If -B/--bookmark is used, the specified bookmarked revision, its
4667 ancestors, and the bookmark will be pushed to the remote
4659 ancestors, and the bookmark will be pushed to the remote
4668 repository.
4660 repository.
4669
4661
4670 Please see :hg:`help urls` for important details about ``ssh://``
4662 Please see :hg:`help urls` for important details about ``ssh://``
4671 URLs. If DESTINATION is omitted, a default path will be used.
4663 URLs. If DESTINATION is omitted, a default path will be used.
4672
4664
4673 Returns 0 if push was successful, 1 if nothing to push.
4665 Returns 0 if push was successful, 1 if nothing to push.
4674 """
4666 """
4675
4667
4676 if opts.get('bookmark'):
4668 if opts.get('bookmark'):
4677 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4669 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4678 for b in opts['bookmark']:
4670 for b in opts['bookmark']:
4679 # translate -B options to -r so changesets get pushed
4671 # translate -B options to -r so changesets get pushed
4680 if b in repo._bookmarks:
4672 if b in repo._bookmarks:
4681 opts.setdefault('rev', []).append(b)
4673 opts.setdefault('rev', []).append(b)
4682 else:
4674 else:
4683 # if we try to push a deleted bookmark, translate it to null
4675 # if we try to push a deleted bookmark, translate it to null
4684 # this lets simultaneous -r, -b options continue working
4676 # this lets simultaneous -r, -b options continue working
4685 opts.setdefault('rev', []).append("null")
4677 opts.setdefault('rev', []).append("null")
4686
4678
4687 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4679 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4688 dest, branches = hg.parseurl(dest, opts.get('branch'))
4680 dest, branches = hg.parseurl(dest, opts.get('branch'))
4689 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4681 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4690 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4682 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4691 other = hg.peer(repo, opts, dest)
4683 other = hg.peer(repo, opts, dest)
4692 if revs:
4684 if revs:
4693 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4685 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4694
4686
4695 repo._subtoppath = dest
4687 repo._subtoppath = dest
4696 try:
4688 try:
4697 # push subrepos depth-first for coherent ordering
4689 # push subrepos depth-first for coherent ordering
4698 c = repo['']
4690 c = repo['']
4699 subs = c.substate # only repos that are committed
4691 subs = c.substate # only repos that are committed
4700 for s in sorted(subs):
4692 for s in sorted(subs):
4701 if c.sub(s).push(opts) == 0:
4693 if c.sub(s).push(opts) == 0:
4702 return False
4694 return False
4703 finally:
4695 finally:
4704 del repo._subtoppath
4696 del repo._subtoppath
4705 result = repo.push(other, opts.get('force'), revs=revs,
4697 result = repo.push(other, opts.get('force'), revs=revs,
4706 newbranch=opts.get('new_branch'))
4698 newbranch=opts.get('new_branch'))
4707
4699
4708 result = not result
4700 result = not result
4709
4701
4710 if opts.get('bookmark'):
4702 if opts.get('bookmark'):
4711 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4703 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4712 if bresult == 2:
4704 if bresult == 2:
4713 return 2
4705 return 2
4714 if not result and bresult:
4706 if not result and bresult:
4715 result = 2
4707 result = 2
4716
4708
4717 return result
4709 return result
4718
4710
4719 @command('recover', [])
4711 @command('recover', [])
4720 def recover(ui, repo):
4712 def recover(ui, repo):
4721 """roll back an interrupted transaction
4713 """roll back an interrupted transaction
4722
4714
4723 Recover from an interrupted commit or pull.
4715 Recover from an interrupted commit or pull.
4724
4716
4725 This command tries to fix the repository status after an
4717 This command tries to fix the repository status after an
4726 interrupted operation. It should only be necessary when Mercurial
4718 interrupted operation. It should only be necessary when Mercurial
4727 suggests it.
4719 suggests it.
4728
4720
4729 Returns 0 if successful, 1 if nothing to recover or verify fails.
4721 Returns 0 if successful, 1 if nothing to recover or verify fails.
4730 """
4722 """
4731 if repo.recover():
4723 if repo.recover():
4732 return hg.verify(repo)
4724 return hg.verify(repo)
4733 return 1
4725 return 1
4734
4726
4735 @command('^remove|rm',
4727 @command('^remove|rm',
4736 [('A', 'after', None, _('record delete for missing files')),
4728 [('A', 'after', None, _('record delete for missing files')),
4737 ('f', 'force', None,
4729 ('f', 'force', None,
4738 _('remove (and delete) file even if added or modified')),
4730 _('remove (and delete) file even if added or modified')),
4739 ] + walkopts,
4731 ] + walkopts,
4740 _('[OPTION]... FILE...'))
4732 _('[OPTION]... FILE...'))
4741 def remove(ui, repo, *pats, **opts):
4733 def remove(ui, repo, *pats, **opts):
4742 """remove the specified files on the next commit
4734 """remove the specified files on the next commit
4743
4735
4744 Schedule the indicated files for removal from the current branch.
4736 Schedule the indicated files for removal from the current branch.
4745
4737
4746 This command schedules the files to be removed at the next commit.
4738 This command schedules the files to be removed at the next commit.
4747 To undo a remove before that, see :hg:`revert`. To undo added
4739 To undo a remove before that, see :hg:`revert`. To undo added
4748 files, see :hg:`forget`.
4740 files, see :hg:`forget`.
4749
4741
4750 .. container:: verbose
4742 .. container:: verbose
4751
4743
4752 -A/--after can be used to remove only files that have already
4744 -A/--after can be used to remove only files that have already
4753 been deleted, -f/--force can be used to force deletion, and -Af
4745 been deleted, -f/--force can be used to force deletion, and -Af
4754 can be used to remove files from the next revision without
4746 can be used to remove files from the next revision without
4755 deleting them from the working directory.
4747 deleting them from the working directory.
4756
4748
4757 The following table details the behavior of remove for different
4749 The following table details the behavior of remove for different
4758 file states (columns) and option combinations (rows). The file
4750 file states (columns) and option combinations (rows). The file
4759 states are Added [A], Clean [C], Modified [M] and Missing [!]
4751 states are Added [A], Clean [C], Modified [M] and Missing [!]
4760 (as reported by :hg:`status`). The actions are Warn, Remove
4752 (as reported by :hg:`status`). The actions are Warn, Remove
4761 (from branch) and Delete (from disk):
4753 (from branch) and Delete (from disk):
4762
4754
4763 ========= == == == ==
4755 ========= == == == ==
4764 opt/state A C M !
4756 opt/state A C M !
4765 ========= == == == ==
4757 ========= == == == ==
4766 none W RD W R
4758 none W RD W R
4767 -f R RD RD R
4759 -f R RD RD R
4768 -A W W W R
4760 -A W W W R
4769 -Af R R R R
4761 -Af R R R R
4770 ========= == == == ==
4762 ========= == == == ==
4771
4763
4772 Note that remove never deletes files in Added [A] state from the
4764 Note that remove never deletes files in Added [A] state from the
4773 working directory, not even if option --force is specified.
4765 working directory, not even if option --force is specified.
4774
4766
4775 Returns 0 on success, 1 if any warnings encountered.
4767 Returns 0 on success, 1 if any warnings encountered.
4776 """
4768 """
4777
4769
4778 ret = 0
4770 ret = 0
4779 after, force = opts.get('after'), opts.get('force')
4771 after, force = opts.get('after'), opts.get('force')
4780 if not pats and not after:
4772 if not pats and not after:
4781 raise util.Abort(_('no files specified'))
4773 raise util.Abort(_('no files specified'))
4782
4774
4783 m = scmutil.match(repo[None], pats, opts)
4775 m = scmutil.match(repo[None], pats, opts)
4784 s = repo.status(match=m, clean=True)
4776 s = repo.status(match=m, clean=True)
4785 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4777 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4786
4778
4787 # warn about failure to delete explicit files/dirs
4779 # warn about failure to delete explicit files/dirs
4788 wctx = repo[None]
4780 wctx = repo[None]
4789 for f in m.files():
4781 for f in m.files():
4790 if f in repo.dirstate or f in wctx.dirs():
4782 if f in repo.dirstate or f in wctx.dirs():
4791 continue
4783 continue
4792 if os.path.exists(m.rel(f)):
4784 if os.path.exists(m.rel(f)):
4793 if os.path.isdir(m.rel(f)):
4785 if os.path.isdir(m.rel(f)):
4794 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4786 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4795 else:
4787 else:
4796 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4788 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4797 # missing files will generate a warning elsewhere
4789 # missing files will generate a warning elsewhere
4798 ret = 1
4790 ret = 1
4799
4791
4800 if force:
4792 if force:
4801 list = modified + deleted + clean + added
4793 list = modified + deleted + clean + added
4802 elif after:
4794 elif after:
4803 list = deleted
4795 list = deleted
4804 for f in modified + added + clean:
4796 for f in modified + added + clean:
4805 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4797 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4806 ret = 1
4798 ret = 1
4807 else:
4799 else:
4808 list = deleted + clean
4800 list = deleted + clean
4809 for f in modified:
4801 for f in modified:
4810 ui.warn(_('not removing %s: file is modified (use -f'
4802 ui.warn(_('not removing %s: file is modified (use -f'
4811 ' to force removal)\n') % m.rel(f))
4803 ' to force removal)\n') % m.rel(f))
4812 ret = 1
4804 ret = 1
4813 for f in added:
4805 for f in added:
4814 ui.warn(_('not removing %s: file has been marked for add'
4806 ui.warn(_('not removing %s: file has been marked for add'
4815 ' (use forget to undo)\n') % m.rel(f))
4807 ' (use forget to undo)\n') % m.rel(f))
4816 ret = 1
4808 ret = 1
4817
4809
4818 for f in sorted(list):
4810 for f in sorted(list):
4819 if ui.verbose or not m.exact(f):
4811 if ui.verbose or not m.exact(f):
4820 ui.status(_('removing %s\n') % m.rel(f))
4812 ui.status(_('removing %s\n') % m.rel(f))
4821
4813
4822 wlock = repo.wlock()
4814 wlock = repo.wlock()
4823 try:
4815 try:
4824 if not after:
4816 if not after:
4825 for f in list:
4817 for f in list:
4826 if f in added:
4818 if f in added:
4827 continue # we never unlink added files on remove
4819 continue # we never unlink added files on remove
4828 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4820 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4829 repo[None].forget(list)
4821 repo[None].forget(list)
4830 finally:
4822 finally:
4831 wlock.release()
4823 wlock.release()
4832
4824
4833 return ret
4825 return ret
4834
4826
4835 @command('rename|move|mv',
4827 @command('rename|move|mv',
4836 [('A', 'after', None, _('record a rename that has already occurred')),
4828 [('A', 'after', None, _('record a rename that has already occurred')),
4837 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4829 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4838 ] + walkopts + dryrunopts,
4830 ] + walkopts + dryrunopts,
4839 _('[OPTION]... SOURCE... DEST'))
4831 _('[OPTION]... SOURCE... DEST'))
4840 def rename(ui, repo, *pats, **opts):
4832 def rename(ui, repo, *pats, **opts):
4841 """rename files; equivalent of copy + remove
4833 """rename files; equivalent of copy + remove
4842
4834
4843 Mark dest as copies of sources; mark sources for deletion. If dest
4835 Mark dest as copies of sources; mark sources for deletion. If dest
4844 is a directory, copies are put in that directory. If dest is a
4836 is a directory, copies are put in that directory. If dest is a
4845 file, there can only be one source.
4837 file, there can only be one source.
4846
4838
4847 By default, this command copies the contents of files as they
4839 By default, this command copies the contents of files as they
4848 exist in the working directory. If invoked with -A/--after, the
4840 exist in the working directory. If invoked with -A/--after, the
4849 operation is recorded, but no copying is performed.
4841 operation is recorded, but no copying is performed.
4850
4842
4851 This command takes effect at the next commit. To undo a rename
4843 This command takes effect at the next commit. To undo a rename
4852 before that, see :hg:`revert`.
4844 before that, see :hg:`revert`.
4853
4845
4854 Returns 0 on success, 1 if errors are encountered.
4846 Returns 0 on success, 1 if errors are encountered.
4855 """
4847 """
4856 wlock = repo.wlock(False)
4848 wlock = repo.wlock(False)
4857 try:
4849 try:
4858 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4850 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4859 finally:
4851 finally:
4860 wlock.release()
4852 wlock.release()
4861
4853
4862 @command('resolve',
4854 @command('resolve',
4863 [('a', 'all', None, _('select all unresolved files')),
4855 [('a', 'all', None, _('select all unresolved files')),
4864 ('l', 'list', None, _('list state of files needing merge')),
4856 ('l', 'list', None, _('list state of files needing merge')),
4865 ('m', 'mark', None, _('mark files as resolved')),
4857 ('m', 'mark', None, _('mark files as resolved')),
4866 ('u', 'unmark', None, _('mark files as unresolved')),
4858 ('u', 'unmark', None, _('mark files as unresolved')),
4867 ('n', 'no-status', None, _('hide status prefix'))]
4859 ('n', 'no-status', None, _('hide status prefix'))]
4868 + mergetoolopts + walkopts,
4860 + mergetoolopts + walkopts,
4869 _('[OPTION]... [FILE]...'))
4861 _('[OPTION]... [FILE]...'))
4870 def resolve(ui, repo, *pats, **opts):
4862 def resolve(ui, repo, *pats, **opts):
4871 """redo merges or set/view the merge status of files
4863 """redo merges or set/view the merge status of files
4872
4864
4873 Merges with unresolved conflicts are often the result of
4865 Merges with unresolved conflicts are often the result of
4874 non-interactive merging using the ``internal:merge`` configuration
4866 non-interactive merging using the ``internal:merge`` configuration
4875 setting, or a command-line merge tool like ``diff3``. The resolve
4867 setting, or a command-line merge tool like ``diff3``. The resolve
4876 command is used to manage the files involved in a merge, after
4868 command is used to manage the files involved in a merge, after
4877 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4869 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4878 working directory must have two parents). See :hg:`help
4870 working directory must have two parents). See :hg:`help
4879 merge-tools` for information on configuring merge tools.
4871 merge-tools` for information on configuring merge tools.
4880
4872
4881 The resolve command can be used in the following ways:
4873 The resolve command can be used in the following ways:
4882
4874
4883 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4875 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4884 files, discarding any previous merge attempts. Re-merging is not
4876 files, discarding any previous merge attempts. Re-merging is not
4885 performed for files already marked as resolved. Use ``--all/-a``
4877 performed for files already marked as resolved. Use ``--all/-a``
4886 to select all unresolved files. ``--tool`` can be used to specify
4878 to select all unresolved files. ``--tool`` can be used to specify
4887 the merge tool used for the given files. It overrides the HGMERGE
4879 the merge tool used for the given files. It overrides the HGMERGE
4888 environment variable and your configuration files. Previous file
4880 environment variable and your configuration files. Previous file
4889 contents are saved with a ``.orig`` suffix.
4881 contents are saved with a ``.orig`` suffix.
4890
4882
4891 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4883 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4892 (e.g. after having manually fixed-up the files). The default is
4884 (e.g. after having manually fixed-up the files). The default is
4893 to mark all unresolved files.
4885 to mark all unresolved files.
4894
4886
4895 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4887 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4896 default is to mark all resolved files.
4888 default is to mark all resolved files.
4897
4889
4898 - :hg:`resolve -l`: list files which had or still have conflicts.
4890 - :hg:`resolve -l`: list files which had or still have conflicts.
4899 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4891 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4900
4892
4901 Note that Mercurial will not let you commit files with unresolved
4893 Note that Mercurial will not let you commit files with unresolved
4902 merge conflicts. You must use :hg:`resolve -m ...` before you can
4894 merge conflicts. You must use :hg:`resolve -m ...` before you can
4903 commit after a conflicting merge.
4895 commit after a conflicting merge.
4904
4896
4905 Returns 0 on success, 1 if any files fail a resolve attempt.
4897 Returns 0 on success, 1 if any files fail a resolve attempt.
4906 """
4898 """
4907
4899
4908 all, mark, unmark, show, nostatus = \
4900 all, mark, unmark, show, nostatus = \
4909 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4901 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4910
4902
4911 if (show and (mark or unmark)) or (mark and unmark):
4903 if (show and (mark or unmark)) or (mark and unmark):
4912 raise util.Abort(_("too many options specified"))
4904 raise util.Abort(_("too many options specified"))
4913 if pats and all:
4905 if pats and all:
4914 raise util.Abort(_("can't specify --all and patterns"))
4906 raise util.Abort(_("can't specify --all and patterns"))
4915 if not (all or pats or show or mark or unmark):
4907 if not (all or pats or show or mark or unmark):
4916 raise util.Abort(_('no files or directories specified; '
4908 raise util.Abort(_('no files or directories specified; '
4917 'use --all to remerge all files'))
4909 'use --all to remerge all files'))
4918
4910
4919 ms = mergemod.mergestate(repo)
4911 ms = mergemod.mergestate(repo)
4920 m = scmutil.match(repo[None], pats, opts)
4912 m = scmutil.match(repo[None], pats, opts)
4921 ret = 0
4913 ret = 0
4922
4914
4923 for f in ms:
4915 for f in ms:
4924 if m(f):
4916 if m(f):
4925 if show:
4917 if show:
4926 if nostatus:
4918 if nostatus:
4927 ui.write("%s\n" % f)
4919 ui.write("%s\n" % f)
4928 else:
4920 else:
4929 ui.write("%s %s\n" % (ms[f].upper(), f),
4921 ui.write("%s %s\n" % (ms[f].upper(), f),
4930 label='resolve.' +
4922 label='resolve.' +
4931 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4923 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4932 elif mark:
4924 elif mark:
4933 ms.mark(f, "r")
4925 ms.mark(f, "r")
4934 elif unmark:
4926 elif unmark:
4935 ms.mark(f, "u")
4927 ms.mark(f, "u")
4936 else:
4928 else:
4937 wctx = repo[None]
4929 wctx = repo[None]
4938 mctx = wctx.parents()[-1]
4930 mctx = wctx.parents()[-1]
4939
4931
4940 # backup pre-resolve (merge uses .orig for its own purposes)
4932 # backup pre-resolve (merge uses .orig for its own purposes)
4941 a = repo.wjoin(f)
4933 a = repo.wjoin(f)
4942 util.copyfile(a, a + ".resolve")
4934 util.copyfile(a, a + ".resolve")
4943
4935
4944 try:
4936 try:
4945 # resolve file
4937 # resolve file
4946 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4938 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4947 if ms.resolve(f, wctx, mctx):
4939 if ms.resolve(f, wctx, mctx):
4948 ret = 1
4940 ret = 1
4949 finally:
4941 finally:
4950 ui.setconfig('ui', 'forcemerge', '')
4942 ui.setconfig('ui', 'forcemerge', '')
4951 ms.commit()
4943 ms.commit()
4952
4944
4953 # replace filemerge's .orig file with our resolve file
4945 # replace filemerge's .orig file with our resolve file
4954 util.rename(a + ".resolve", a + ".orig")
4946 util.rename(a + ".resolve", a + ".orig")
4955
4947
4956 ms.commit()
4948 ms.commit()
4957 return ret
4949 return ret
4958
4950
4959 @command('revert',
4951 @command('revert',
4960 [('a', 'all', None, _('revert all changes when no arguments given')),
4952 [('a', 'all', None, _('revert all changes when no arguments given')),
4961 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4953 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4962 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4954 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4963 ('C', 'no-backup', None, _('do not save backup copies of files')),
4955 ('C', 'no-backup', None, _('do not save backup copies of files')),
4964 ] + walkopts + dryrunopts,
4956 ] + walkopts + dryrunopts,
4965 _('[OPTION]... [-r REV] [NAME]...'))
4957 _('[OPTION]... [-r REV] [NAME]...'))
4966 def revert(ui, repo, *pats, **opts):
4958 def revert(ui, repo, *pats, **opts):
4967 """restore files to their checkout state
4959 """restore files to their checkout state
4968
4960
4969 .. note::
4961 .. note::
4970
4962
4971 To check out earlier revisions, you should use :hg:`update REV`.
4963 To check out earlier revisions, you should use :hg:`update REV`.
4972 To cancel an uncommitted merge (and lose your changes),
4964 To cancel an uncommitted merge (and lose your changes),
4973 use :hg:`update --clean .`.
4965 use :hg:`update --clean .`.
4974
4966
4975 With no revision specified, revert the specified files or directories
4967 With no revision specified, revert the specified files or directories
4976 to the contents they had in the parent of the working directory.
4968 to the contents they had in the parent of the working directory.
4977 This restores the contents of files to an unmodified
4969 This restores the contents of files to an unmodified
4978 state and unschedules adds, removes, copies, and renames. If the
4970 state and unschedules adds, removes, copies, and renames. If the
4979 working directory has two parents, you must explicitly specify a
4971 working directory has two parents, you must explicitly specify a
4980 revision.
4972 revision.
4981
4973
4982 Using the -r/--rev or -d/--date options, revert the given files or
4974 Using the -r/--rev or -d/--date options, revert the given files or
4983 directories to their states as of a specific revision. Because
4975 directories to their states as of a specific revision. Because
4984 revert does not change the working directory parents, this will
4976 revert does not change the working directory parents, this will
4985 cause these files to appear modified. This can be helpful to "back
4977 cause these files to appear modified. This can be helpful to "back
4986 out" some or all of an earlier change. See :hg:`backout` for a
4978 out" some or all of an earlier change. See :hg:`backout` for a
4987 related method.
4979 related method.
4988
4980
4989 Modified files are saved with a .orig suffix before reverting.
4981 Modified files are saved with a .orig suffix before reverting.
4990 To disable these backups, use --no-backup.
4982 To disable these backups, use --no-backup.
4991
4983
4992 See :hg:`help dates` for a list of formats valid for -d/--date.
4984 See :hg:`help dates` for a list of formats valid for -d/--date.
4993
4985
4994 Returns 0 on success.
4986 Returns 0 on success.
4995 """
4987 """
4996
4988
4997 if opts.get("date"):
4989 if opts.get("date"):
4998 if opts.get("rev"):
4990 if opts.get("rev"):
4999 raise util.Abort(_("you can't specify a revision and a date"))
4991 raise util.Abort(_("you can't specify a revision and a date"))
5000 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4992 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5001
4993
5002 parent, p2 = repo.dirstate.parents()
4994 parent, p2 = repo.dirstate.parents()
5003 if not opts.get('rev') and p2 != nullid:
4995 if not opts.get('rev') and p2 != nullid:
5004 # revert after merge is a trap for new users (issue2915)
4996 # revert after merge is a trap for new users (issue2915)
5005 raise util.Abort(_('uncommitted merge with no revision specified'),
4997 raise util.Abort(_('uncommitted merge with no revision specified'),
5006 hint=_('use "hg update" or see "hg help revert"'))
4998 hint=_('use "hg update" or see "hg help revert"'))
5007
4999
5008 ctx = scmutil.revsingle(repo, opts.get('rev'))
5000 ctx = scmutil.revsingle(repo, opts.get('rev'))
5009
5001
5010 if not pats and not opts.get('all'):
5002 if not pats and not opts.get('all'):
5011 msg = _("no files or directories specified")
5003 msg = _("no files or directories specified")
5012 if p2 != nullid:
5004 if p2 != nullid:
5013 hint = _("uncommitted merge, use --all to discard all changes,"
5005 hint = _("uncommitted merge, use --all to discard all changes,"
5014 " or 'hg update -C .' to abort the merge")
5006 " or 'hg update -C .' to abort the merge")
5015 raise util.Abort(msg, hint=hint)
5007 raise util.Abort(msg, hint=hint)
5016 dirty = util.any(repo.status())
5008 dirty = util.any(repo.status())
5017 node = ctx.node()
5009 node = ctx.node()
5018 if node != parent:
5010 if node != parent:
5019 if dirty:
5011 if dirty:
5020 hint = _("uncommitted changes, use --all to discard all"
5012 hint = _("uncommitted changes, use --all to discard all"
5021 " changes, or 'hg update %s' to update") % ctx.rev()
5013 " changes, or 'hg update %s' to update") % ctx.rev()
5022 else:
5014 else:
5023 hint = _("use --all to revert all files,"
5015 hint = _("use --all to revert all files,"
5024 " or 'hg update %s' to update") % ctx.rev()
5016 " or 'hg update %s' to update") % ctx.rev()
5025 elif dirty:
5017 elif dirty:
5026 hint = _("uncommitted changes, use --all to discard all changes")
5018 hint = _("uncommitted changes, use --all to discard all changes")
5027 else:
5019 else:
5028 hint = _("use --all to revert all files")
5020 hint = _("use --all to revert all files")
5029 raise util.Abort(msg, hint=hint)
5021 raise util.Abort(msg, hint=hint)
5030
5022
5031 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5023 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5032
5024
5033 @command('rollback', dryrunopts +
5025 @command('rollback', dryrunopts +
5034 [('f', 'force', False, _('ignore safety measures'))])
5026 [('f', 'force', False, _('ignore safety measures'))])
5035 def rollback(ui, repo, **opts):
5027 def rollback(ui, repo, **opts):
5036 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5028 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5037
5029
5038 Please use :hg:`commit --amend` instead of rollback to correct
5030 Please use :hg:`commit --amend` instead of rollback to correct
5039 mistakes in the last commit.
5031 mistakes in the last commit.
5040
5032
5041 This command should be used with care. There is only one level of
5033 This command should be used with care. There is only one level of
5042 rollback, and there is no way to undo a rollback. It will also
5034 rollback, and there is no way to undo a rollback. It will also
5043 restore the dirstate at the time of the last transaction, losing
5035 restore the dirstate at the time of the last transaction, losing
5044 any dirstate changes since that time. This command does not alter
5036 any dirstate changes since that time. This command does not alter
5045 the working directory.
5037 the working directory.
5046
5038
5047 Transactions are used to encapsulate the effects of all commands
5039 Transactions are used to encapsulate the effects of all commands
5048 that create new changesets or propagate existing changesets into a
5040 that create new changesets or propagate existing changesets into a
5049 repository.
5041 repository.
5050
5042
5051 .. container:: verbose
5043 .. container:: verbose
5052
5044
5053 For example, the following commands are transactional, and their
5045 For example, the following commands are transactional, and their
5054 effects can be rolled back:
5046 effects can be rolled back:
5055
5047
5056 - commit
5048 - commit
5057 - import
5049 - import
5058 - pull
5050 - pull
5059 - push (with this repository as the destination)
5051 - push (with this repository as the destination)
5060 - unbundle
5052 - unbundle
5061
5053
5062 To avoid permanent data loss, rollback will refuse to rollback a
5054 To avoid permanent data loss, rollback will refuse to rollback a
5063 commit transaction if it isn't checked out. Use --force to
5055 commit transaction if it isn't checked out. Use --force to
5064 override this protection.
5056 override this protection.
5065
5057
5066 This command is not intended for use on public repositories. Once
5058 This command is not intended for use on public repositories. Once
5067 changes are visible for pull by other users, rolling a transaction
5059 changes are visible for pull by other users, rolling a transaction
5068 back locally is ineffective (someone else may already have pulled
5060 back locally is ineffective (someone else may already have pulled
5069 the changes). Furthermore, a race is possible with readers of the
5061 the changes). Furthermore, a race is possible with readers of the
5070 repository; for example an in-progress pull from the repository
5062 repository; for example an in-progress pull from the repository
5071 may fail if a rollback is performed.
5063 may fail if a rollback is performed.
5072
5064
5073 Returns 0 on success, 1 if no rollback data is available.
5065 Returns 0 on success, 1 if no rollback data is available.
5074 """
5066 """
5075 return repo.rollback(dryrun=opts.get('dry_run'),
5067 return repo.rollback(dryrun=opts.get('dry_run'),
5076 force=opts.get('force'))
5068 force=opts.get('force'))
5077
5069
5078 @command('root', [])
5070 @command('root', [])
5079 def root(ui, repo):
5071 def root(ui, repo):
5080 """print the root (top) of the current working directory
5072 """print the root (top) of the current working directory
5081
5073
5082 Print the root directory of the current repository.
5074 Print the root directory of the current repository.
5083
5075
5084 Returns 0 on success.
5076 Returns 0 on success.
5085 """
5077 """
5086 ui.write(repo.root + "\n")
5078 ui.write(repo.root + "\n")
5087
5079
5088 @command('^serve',
5080 @command('^serve',
5089 [('A', 'accesslog', '', _('name of access log file to write to'),
5081 [('A', 'accesslog', '', _('name of access log file to write to'),
5090 _('FILE')),
5082 _('FILE')),
5091 ('d', 'daemon', None, _('run server in background')),
5083 ('d', 'daemon', None, _('run server in background')),
5092 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5084 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5093 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5085 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5094 # use string type, then we can check if something was passed
5086 # use string type, then we can check if something was passed
5095 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5087 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5096 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5088 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5097 _('ADDR')),
5089 _('ADDR')),
5098 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5090 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5099 _('PREFIX')),
5091 _('PREFIX')),
5100 ('n', 'name', '',
5092 ('n', 'name', '',
5101 _('name to show in web pages (default: working directory)'), _('NAME')),
5093 _('name to show in web pages (default: working directory)'), _('NAME')),
5102 ('', 'web-conf', '',
5094 ('', 'web-conf', '',
5103 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5095 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5104 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5096 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5105 _('FILE')),
5097 _('FILE')),
5106 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5098 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5107 ('', 'stdio', None, _('for remote clients')),
5099 ('', 'stdio', None, _('for remote clients')),
5108 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5100 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5109 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5101 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5110 ('', 'style', '', _('template style to use'), _('STYLE')),
5102 ('', 'style', '', _('template style to use'), _('STYLE')),
5111 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5103 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5112 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5104 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5113 _('[OPTION]...'))
5105 _('[OPTION]...'))
5114 def serve(ui, repo, **opts):
5106 def serve(ui, repo, **opts):
5115 """start stand-alone webserver
5107 """start stand-alone webserver
5116
5108
5117 Start a local HTTP repository browser and pull server. You can use
5109 Start a local HTTP repository browser and pull server. You can use
5118 this for ad-hoc sharing and browsing of repositories. It is
5110 this for ad-hoc sharing and browsing of repositories. It is
5119 recommended to use a real web server to serve a repository for
5111 recommended to use a real web server to serve a repository for
5120 longer periods of time.
5112 longer periods of time.
5121
5113
5122 Please note that the server does not implement access control.
5114 Please note that the server does not implement access control.
5123 This means that, by default, anybody can read from the server and
5115 This means that, by default, anybody can read from the server and
5124 nobody can write to it by default. Set the ``web.allow_push``
5116 nobody can write to it by default. Set the ``web.allow_push``
5125 option to ``*`` to allow everybody to push to the server. You
5117 option to ``*`` to allow everybody to push to the server. You
5126 should use a real web server if you need to authenticate users.
5118 should use a real web server if you need to authenticate users.
5127
5119
5128 By default, the server logs accesses to stdout and errors to
5120 By default, the server logs accesses to stdout and errors to
5129 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5121 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5130 files.
5122 files.
5131
5123
5132 To have the server choose a free port number to listen on, specify
5124 To have the server choose a free port number to listen on, specify
5133 a port number of 0; in this case, the server will print the port
5125 a port number of 0; in this case, the server will print the port
5134 number it uses.
5126 number it uses.
5135
5127
5136 Returns 0 on success.
5128 Returns 0 on success.
5137 """
5129 """
5138
5130
5139 if opts["stdio"] and opts["cmdserver"]:
5131 if opts["stdio"] and opts["cmdserver"]:
5140 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5132 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5141
5133
5142 def checkrepo():
5134 def checkrepo():
5143 if repo is None:
5135 if repo is None:
5144 raise error.RepoError(_("there is no Mercurial repository here"
5136 raise error.RepoError(_("there is no Mercurial repository here"
5145 " (.hg not found)"))
5137 " (.hg not found)"))
5146
5138
5147 if opts["stdio"]:
5139 if opts["stdio"]:
5148 checkrepo()
5140 checkrepo()
5149 s = sshserver.sshserver(ui, repo)
5141 s = sshserver.sshserver(ui, repo)
5150 s.serve_forever()
5142 s.serve_forever()
5151
5143
5152 if opts["cmdserver"]:
5144 if opts["cmdserver"]:
5153 checkrepo()
5145 checkrepo()
5154 s = commandserver.server(ui, repo, opts["cmdserver"])
5146 s = commandserver.server(ui, repo, opts["cmdserver"])
5155 return s.serve()
5147 return s.serve()
5156
5148
5157 # this way we can check if something was given in the command-line
5149 # this way we can check if something was given in the command-line
5158 if opts.get('port'):
5150 if opts.get('port'):
5159 opts['port'] = util.getport(opts.get('port'))
5151 opts['port'] = util.getport(opts.get('port'))
5160
5152
5161 baseui = repo and repo.baseui or ui
5153 baseui = repo and repo.baseui or ui
5162 optlist = ("name templates style address port prefix ipv6"
5154 optlist = ("name templates style address port prefix ipv6"
5163 " accesslog errorlog certificate encoding")
5155 " accesslog errorlog certificate encoding")
5164 for o in optlist.split():
5156 for o in optlist.split():
5165 val = opts.get(o, '')
5157 val = opts.get(o, '')
5166 if val in (None, ''): # should check against default options instead
5158 if val in (None, ''): # should check against default options instead
5167 continue
5159 continue
5168 baseui.setconfig("web", o, val)
5160 baseui.setconfig("web", o, val)
5169 if repo and repo.ui != baseui:
5161 if repo and repo.ui != baseui:
5170 repo.ui.setconfig("web", o, val)
5162 repo.ui.setconfig("web", o, val)
5171
5163
5172 o = opts.get('web_conf') or opts.get('webdir_conf')
5164 o = opts.get('web_conf') or opts.get('webdir_conf')
5173 if not o:
5165 if not o:
5174 if not repo:
5166 if not repo:
5175 raise error.RepoError(_("there is no Mercurial repository"
5167 raise error.RepoError(_("there is no Mercurial repository"
5176 " here (.hg not found)"))
5168 " here (.hg not found)"))
5177 o = repo
5169 o = repo
5178
5170
5179 app = hgweb.hgweb(o, baseui=baseui)
5171 app = hgweb.hgweb(o, baseui=baseui)
5180 service = httpservice(ui, app, opts)
5172 service = httpservice(ui, app, opts)
5181 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5173 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5182
5174
5183 class httpservice(object):
5175 class httpservice(object):
5184 def __init__(self, ui, app, opts):
5176 def __init__(self, ui, app, opts):
5185 self.ui = ui
5177 self.ui = ui
5186 self.app = app
5178 self.app = app
5187 self.opts = opts
5179 self.opts = opts
5188
5180
5189 def init(self):
5181 def init(self):
5190 util.setsignalhandler()
5182 util.setsignalhandler()
5191 self.httpd = hgweb_server.create_server(self.ui, self.app)
5183 self.httpd = hgweb_server.create_server(self.ui, self.app)
5192
5184
5193 if self.opts['port'] and not self.ui.verbose:
5185 if self.opts['port'] and not self.ui.verbose:
5194 return
5186 return
5195
5187
5196 if self.httpd.prefix:
5188 if self.httpd.prefix:
5197 prefix = self.httpd.prefix.strip('/') + '/'
5189 prefix = self.httpd.prefix.strip('/') + '/'
5198 else:
5190 else:
5199 prefix = ''
5191 prefix = ''
5200
5192
5201 port = ':%d' % self.httpd.port
5193 port = ':%d' % self.httpd.port
5202 if port == ':80':
5194 if port == ':80':
5203 port = ''
5195 port = ''
5204
5196
5205 bindaddr = self.httpd.addr
5197 bindaddr = self.httpd.addr
5206 if bindaddr == '0.0.0.0':
5198 if bindaddr == '0.0.0.0':
5207 bindaddr = '*'
5199 bindaddr = '*'
5208 elif ':' in bindaddr: # IPv6
5200 elif ':' in bindaddr: # IPv6
5209 bindaddr = '[%s]' % bindaddr
5201 bindaddr = '[%s]' % bindaddr
5210
5202
5211 fqaddr = self.httpd.fqaddr
5203 fqaddr = self.httpd.fqaddr
5212 if ':' in fqaddr:
5204 if ':' in fqaddr:
5213 fqaddr = '[%s]' % fqaddr
5205 fqaddr = '[%s]' % fqaddr
5214 if self.opts['port']:
5206 if self.opts['port']:
5215 write = self.ui.status
5207 write = self.ui.status
5216 else:
5208 else:
5217 write = self.ui.write
5209 write = self.ui.write
5218 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5210 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5219 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5211 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5220
5212
5221 def run(self):
5213 def run(self):
5222 self.httpd.serve_forever()
5214 self.httpd.serve_forever()
5223
5215
5224
5216
5225 @command('showconfig|debugconfig',
5217 @command('showconfig|debugconfig',
5226 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5218 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5227 _('[-u] [NAME]...'))
5219 _('[-u] [NAME]...'))
5228 def showconfig(ui, repo, *values, **opts):
5220 def showconfig(ui, repo, *values, **opts):
5229 """show combined config settings from all hgrc files
5221 """show combined config settings from all hgrc files
5230
5222
5231 With no arguments, print names and values of all config items.
5223 With no arguments, print names and values of all config items.
5232
5224
5233 With one argument of the form section.name, print just the value
5225 With one argument of the form section.name, print just the value
5234 of that config item.
5226 of that config item.
5235
5227
5236 With multiple arguments, print names and values of all config
5228 With multiple arguments, print names and values of all config
5237 items with matching section names.
5229 items with matching section names.
5238
5230
5239 With --debug, the source (filename and line number) is printed
5231 With --debug, the source (filename and line number) is printed
5240 for each config item.
5232 for each config item.
5241
5233
5242 Returns 0 on success.
5234 Returns 0 on success.
5243 """
5235 """
5244
5236
5245 for f in scmutil.rcpath():
5237 for f in scmutil.rcpath():
5246 ui.debug('read config from: %s\n' % f)
5238 ui.debug('read config from: %s\n' % f)
5247 untrusted = bool(opts.get('untrusted'))
5239 untrusted = bool(opts.get('untrusted'))
5248 if values:
5240 if values:
5249 sections = [v for v in values if '.' not in v]
5241 sections = [v for v in values if '.' not in v]
5250 items = [v for v in values if '.' in v]
5242 items = [v for v in values if '.' in v]
5251 if len(items) > 1 or items and sections:
5243 if len(items) > 1 or items and sections:
5252 raise util.Abort(_('only one config item permitted'))
5244 raise util.Abort(_('only one config item permitted'))
5253 for section, name, value in ui.walkconfig(untrusted=untrusted):
5245 for section, name, value in ui.walkconfig(untrusted=untrusted):
5254 value = str(value).replace('\n', '\\n')
5246 value = str(value).replace('\n', '\\n')
5255 sectname = section + '.' + name
5247 sectname = section + '.' + name
5256 if values:
5248 if values:
5257 for v in values:
5249 for v in values:
5258 if v == section:
5250 if v == section:
5259 ui.debug('%s: ' %
5251 ui.debug('%s: ' %
5260 ui.configsource(section, name, untrusted))
5252 ui.configsource(section, name, untrusted))
5261 ui.write('%s=%s\n' % (sectname, value))
5253 ui.write('%s=%s\n' % (sectname, value))
5262 elif v == sectname:
5254 elif v == sectname:
5263 ui.debug('%s: ' %
5255 ui.debug('%s: ' %
5264 ui.configsource(section, name, untrusted))
5256 ui.configsource(section, name, untrusted))
5265 ui.write(value, '\n')
5257 ui.write(value, '\n')
5266 else:
5258 else:
5267 ui.debug('%s: ' %
5259 ui.debug('%s: ' %
5268 ui.configsource(section, name, untrusted))
5260 ui.configsource(section, name, untrusted))
5269 ui.write('%s=%s\n' % (sectname, value))
5261 ui.write('%s=%s\n' % (sectname, value))
5270
5262
5271 @command('^status|st',
5263 @command('^status|st',
5272 [('A', 'all', None, _('show status of all files')),
5264 [('A', 'all', None, _('show status of all files')),
5273 ('m', 'modified', None, _('show only modified files')),
5265 ('m', 'modified', None, _('show only modified files')),
5274 ('a', 'added', None, _('show only added files')),
5266 ('a', 'added', None, _('show only added files')),
5275 ('r', 'removed', None, _('show only removed files')),
5267 ('r', 'removed', None, _('show only removed files')),
5276 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5268 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5277 ('c', 'clean', None, _('show only files without changes')),
5269 ('c', 'clean', None, _('show only files without changes')),
5278 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5270 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5279 ('i', 'ignored', None, _('show only ignored files')),
5271 ('i', 'ignored', None, _('show only ignored files')),
5280 ('n', 'no-status', None, _('hide status prefix')),
5272 ('n', 'no-status', None, _('hide status prefix')),
5281 ('C', 'copies', None, _('show source of copied files')),
5273 ('C', 'copies', None, _('show source of copied files')),
5282 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5274 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5283 ('', 'rev', [], _('show difference from revision'), _('REV')),
5275 ('', 'rev', [], _('show difference from revision'), _('REV')),
5284 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5276 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5285 ] + walkopts + subrepoopts,
5277 ] + walkopts + subrepoopts,
5286 _('[OPTION]... [FILE]...'))
5278 _('[OPTION]... [FILE]...'))
5287 def status(ui, repo, *pats, **opts):
5279 def status(ui, repo, *pats, **opts):
5288 """show changed files in the working directory
5280 """show changed files in the working directory
5289
5281
5290 Show status of files in the repository. If names are given, only
5282 Show status of files in the repository. If names are given, only
5291 files that match are shown. Files that are clean or ignored or
5283 files that match are shown. Files that are clean or ignored or
5292 the source of a copy/move operation, are not listed unless
5284 the source of a copy/move operation, are not listed unless
5293 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5285 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5294 Unless options described with "show only ..." are given, the
5286 Unless options described with "show only ..." are given, the
5295 options -mardu are used.
5287 options -mardu are used.
5296
5288
5297 Option -q/--quiet hides untracked (unknown and ignored) files
5289 Option -q/--quiet hides untracked (unknown and ignored) files
5298 unless explicitly requested with -u/--unknown or -i/--ignored.
5290 unless explicitly requested with -u/--unknown or -i/--ignored.
5299
5291
5300 .. note::
5292 .. note::
5301
5293
5302 status may appear to disagree with diff if permissions have
5294 status may appear to disagree with diff if permissions have
5303 changed or a merge has occurred. The standard diff format does
5295 changed or a merge has occurred. The standard diff format does
5304 not report permission changes and diff only reports changes
5296 not report permission changes and diff only reports changes
5305 relative to one merge parent.
5297 relative to one merge parent.
5306
5298
5307 If one revision is given, it is used as the base revision.
5299 If one revision is given, it is used as the base revision.
5308 If two revisions are given, the differences between them are
5300 If two revisions are given, the differences between them are
5309 shown. The --change option can also be used as a shortcut to list
5301 shown. The --change option can also be used as a shortcut to list
5310 the changed files of a revision from its first parent.
5302 the changed files of a revision from its first parent.
5311
5303
5312 The codes used to show the status of files are::
5304 The codes used to show the status of files are::
5313
5305
5314 M = modified
5306 M = modified
5315 A = added
5307 A = added
5316 R = removed
5308 R = removed
5317 C = clean
5309 C = clean
5318 ! = missing (deleted by non-hg command, but still tracked)
5310 ! = missing (deleted by non-hg command, but still tracked)
5319 ? = not tracked
5311 ? = not tracked
5320 I = ignored
5312 I = ignored
5321 = origin of the previous file listed as A (added)
5313 = origin of the previous file listed as A (added)
5322
5314
5323 .. container:: verbose
5315 .. container:: verbose
5324
5316
5325 Examples:
5317 Examples:
5326
5318
5327 - show changes in the working directory relative to a
5319 - show changes in the working directory relative to a
5328 changeset::
5320 changeset::
5329
5321
5330 hg status --rev 9353
5322 hg status --rev 9353
5331
5323
5332 - show all changes including copies in an existing changeset::
5324 - show all changes including copies in an existing changeset::
5333
5325
5334 hg status --copies --change 9353
5326 hg status --copies --change 9353
5335
5327
5336 - get a NUL separated list of added files, suitable for xargs::
5328 - get a NUL separated list of added files, suitable for xargs::
5337
5329
5338 hg status -an0
5330 hg status -an0
5339
5331
5340 Returns 0 on success.
5332 Returns 0 on success.
5341 """
5333 """
5342
5334
5343 revs = opts.get('rev')
5335 revs = opts.get('rev')
5344 change = opts.get('change')
5336 change = opts.get('change')
5345
5337
5346 if revs and change:
5338 if revs and change:
5347 msg = _('cannot specify --rev and --change at the same time')
5339 msg = _('cannot specify --rev and --change at the same time')
5348 raise util.Abort(msg)
5340 raise util.Abort(msg)
5349 elif change:
5341 elif change:
5350 node2 = scmutil.revsingle(repo, change, None).node()
5342 node2 = scmutil.revsingle(repo, change, None).node()
5351 node1 = repo[node2].p1().node()
5343 node1 = repo[node2].p1().node()
5352 else:
5344 else:
5353 node1, node2 = scmutil.revpair(repo, revs)
5345 node1, node2 = scmutil.revpair(repo, revs)
5354
5346
5355 cwd = (pats and repo.getcwd()) or ''
5347 cwd = (pats and repo.getcwd()) or ''
5356 end = opts.get('print0') and '\0' or '\n'
5348 end = opts.get('print0') and '\0' or '\n'
5357 copy = {}
5349 copy = {}
5358 states = 'modified added removed deleted unknown ignored clean'.split()
5350 states = 'modified added removed deleted unknown ignored clean'.split()
5359 show = [k for k in states if opts.get(k)]
5351 show = [k for k in states if opts.get(k)]
5360 if opts.get('all'):
5352 if opts.get('all'):
5361 show += ui.quiet and (states[:4] + ['clean']) or states
5353 show += ui.quiet and (states[:4] + ['clean']) or states
5362 if not show:
5354 if not show:
5363 show = ui.quiet and states[:4] or states[:5]
5355 show = ui.quiet and states[:4] or states[:5]
5364
5356
5365 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5357 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5366 'ignored' in show, 'clean' in show, 'unknown' in show,
5358 'ignored' in show, 'clean' in show, 'unknown' in show,
5367 opts.get('subrepos'))
5359 opts.get('subrepos'))
5368 changestates = zip(states, 'MAR!?IC', stat)
5360 changestates = zip(states, 'MAR!?IC', stat)
5369
5361
5370 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5362 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5371 copy = copies.pathcopies(repo[node1], repo[node2])
5363 copy = copies.pathcopies(repo[node1], repo[node2])
5372
5364
5373 fm = ui.formatter('status', opts)
5365 fm = ui.formatter('status', opts)
5374 fmt = '%s' + end
5366 fmt = '%s' + end
5375 showchar = not opts.get('no_status')
5367 showchar = not opts.get('no_status')
5376
5368
5377 for state, char, files in changestates:
5369 for state, char, files in changestates:
5378 if state in show:
5370 if state in show:
5379 label = 'status.' + state
5371 label = 'status.' + state
5380 for f in files:
5372 for f in files:
5381 fm.startitem()
5373 fm.startitem()
5382 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5374 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5383 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5375 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5384 if f in copy:
5376 if f in copy:
5385 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5377 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5386 label='status.copied')
5378 label='status.copied')
5387 fm.end()
5379 fm.end()
5388
5380
5389 @command('^summary|sum',
5381 @command('^summary|sum',
5390 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5382 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5391 def summary(ui, repo, **opts):
5383 def summary(ui, repo, **opts):
5392 """summarize working directory state
5384 """summarize working directory state
5393
5385
5394 This generates a brief summary of the working directory state,
5386 This generates a brief summary of the working directory state,
5395 including parents, branch, commit status, and available updates.
5387 including parents, branch, commit status, and available updates.
5396
5388
5397 With the --remote option, this will check the default paths for
5389 With the --remote option, this will check the default paths for
5398 incoming and outgoing changes. This can be time-consuming.
5390 incoming and outgoing changes. This can be time-consuming.
5399
5391
5400 Returns 0 on success.
5392 Returns 0 on success.
5401 """
5393 """
5402
5394
5403 ctx = repo[None]
5395 ctx = repo[None]
5404 parents = ctx.parents()
5396 parents = ctx.parents()
5405 pnode = parents[0].node()
5397 pnode = parents[0].node()
5406 marks = []
5398 marks = []
5407
5399
5408 for p in parents:
5400 for p in parents:
5409 # label with log.changeset (instead of log.parent) since this
5401 # label with log.changeset (instead of log.parent) since this
5410 # shows a working directory parent *changeset*:
5402 # shows a working directory parent *changeset*:
5411 # i18n: column positioning for "hg summary"
5403 # i18n: column positioning for "hg summary"
5412 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5404 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5413 label='log.changeset changeset.%s' % p.phasestr())
5405 label='log.changeset changeset.%s' % p.phasestr())
5414 ui.write(' '.join(p.tags()), label='log.tag')
5406 ui.write(' '.join(p.tags()), label='log.tag')
5415 if p.bookmarks():
5407 if p.bookmarks():
5416 marks.extend(p.bookmarks())
5408 marks.extend(p.bookmarks())
5417 if p.rev() == -1:
5409 if p.rev() == -1:
5418 if not len(repo):
5410 if not len(repo):
5419 ui.write(_(' (empty repository)'))
5411 ui.write(_(' (empty repository)'))
5420 else:
5412 else:
5421 ui.write(_(' (no revision checked out)'))
5413 ui.write(_(' (no revision checked out)'))
5422 ui.write('\n')
5414 ui.write('\n')
5423 if p.description():
5415 if p.description():
5424 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5416 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5425 label='log.summary')
5417 label='log.summary')
5426
5418
5427 branch = ctx.branch()
5419 branch = ctx.branch()
5428 bheads = repo.branchheads(branch)
5420 bheads = repo.branchheads(branch)
5429 # i18n: column positioning for "hg summary"
5421 # i18n: column positioning for "hg summary"
5430 m = _('branch: %s\n') % branch
5422 m = _('branch: %s\n') % branch
5431 if branch != 'default':
5423 if branch != 'default':
5432 ui.write(m, label='log.branch')
5424 ui.write(m, label='log.branch')
5433 else:
5425 else:
5434 ui.status(m, label='log.branch')
5426 ui.status(m, label='log.branch')
5435
5427
5436 if marks:
5428 if marks:
5437 current = repo._bookmarkcurrent
5429 current = repo._bookmarkcurrent
5438 # i18n: column positioning for "hg summary"
5430 # i18n: column positioning for "hg summary"
5439 ui.write(_('bookmarks:'), label='log.bookmark')
5431 ui.write(_('bookmarks:'), label='log.bookmark')
5440 if current is not None:
5432 if current is not None:
5441 if current in marks:
5433 if current in marks:
5442 ui.write(' *' + current, label='bookmarks.current')
5434 ui.write(' *' + current, label='bookmarks.current')
5443 marks.remove(current)
5435 marks.remove(current)
5444 else:
5436 else:
5445 ui.write(' [%s]' % current, label='bookmarks.current')
5437 ui.write(' [%s]' % current, label='bookmarks.current')
5446 for m in marks:
5438 for m in marks:
5447 ui.write(' ' + m, label='log.bookmark')
5439 ui.write(' ' + m, label='log.bookmark')
5448 ui.write('\n', label='log.bookmark')
5440 ui.write('\n', label='log.bookmark')
5449
5441
5450 st = list(repo.status(unknown=True))[:6]
5442 st = list(repo.status(unknown=True))[:6]
5451
5443
5452 c = repo.dirstate.copies()
5444 c = repo.dirstate.copies()
5453 copied, renamed = [], []
5445 copied, renamed = [], []
5454 for d, s in c.iteritems():
5446 for d, s in c.iteritems():
5455 if s in st[2]:
5447 if s in st[2]:
5456 st[2].remove(s)
5448 st[2].remove(s)
5457 renamed.append(d)
5449 renamed.append(d)
5458 else:
5450 else:
5459 copied.append(d)
5451 copied.append(d)
5460 if d in st[1]:
5452 if d in st[1]:
5461 st[1].remove(d)
5453 st[1].remove(d)
5462 st.insert(3, renamed)
5454 st.insert(3, renamed)
5463 st.insert(4, copied)
5455 st.insert(4, copied)
5464
5456
5465 ms = mergemod.mergestate(repo)
5457 ms = mergemod.mergestate(repo)
5466 st.append([f for f in ms if ms[f] == 'u'])
5458 st.append([f for f in ms if ms[f] == 'u'])
5467
5459
5468 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5460 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5469 st.append(subs)
5461 st.append(subs)
5470
5462
5471 labels = [ui.label(_('%d modified'), 'status.modified'),
5463 labels = [ui.label(_('%d modified'), 'status.modified'),
5472 ui.label(_('%d added'), 'status.added'),
5464 ui.label(_('%d added'), 'status.added'),
5473 ui.label(_('%d removed'), 'status.removed'),
5465 ui.label(_('%d removed'), 'status.removed'),
5474 ui.label(_('%d renamed'), 'status.copied'),
5466 ui.label(_('%d renamed'), 'status.copied'),
5475 ui.label(_('%d copied'), 'status.copied'),
5467 ui.label(_('%d copied'), 'status.copied'),
5476 ui.label(_('%d deleted'), 'status.deleted'),
5468 ui.label(_('%d deleted'), 'status.deleted'),
5477 ui.label(_('%d unknown'), 'status.unknown'),
5469 ui.label(_('%d unknown'), 'status.unknown'),
5478 ui.label(_('%d ignored'), 'status.ignored'),
5470 ui.label(_('%d ignored'), 'status.ignored'),
5479 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5471 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5480 ui.label(_('%d subrepos'), 'status.modified')]
5472 ui.label(_('%d subrepos'), 'status.modified')]
5481 t = []
5473 t = []
5482 for s, l in zip(st, labels):
5474 for s, l in zip(st, labels):
5483 if s:
5475 if s:
5484 t.append(l % len(s))
5476 t.append(l % len(s))
5485
5477
5486 t = ', '.join(t)
5478 t = ', '.join(t)
5487 cleanworkdir = False
5479 cleanworkdir = False
5488
5480
5489 if repo.vfs.exists('updatestate'):
5481 if repo.vfs.exists('updatestate'):
5490 t += _(' (interrupted update)')
5482 t += _(' (interrupted update)')
5491 elif len(parents) > 1:
5483 elif len(parents) > 1:
5492 t += _(' (merge)')
5484 t += _(' (merge)')
5493 elif branch != parents[0].branch():
5485 elif branch != parents[0].branch():
5494 t += _(' (new branch)')
5486 t += _(' (new branch)')
5495 elif (parents[0].closesbranch() and
5487 elif (parents[0].closesbranch() and
5496 pnode in repo.branchheads(branch, closed=True)):
5488 pnode in repo.branchheads(branch, closed=True)):
5497 t += _(' (head closed)')
5489 t += _(' (head closed)')
5498 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5490 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5499 t += _(' (clean)')
5491 t += _(' (clean)')
5500 cleanworkdir = True
5492 cleanworkdir = True
5501 elif pnode not in bheads:
5493 elif pnode not in bheads:
5502 t += _(' (new branch head)')
5494 t += _(' (new branch head)')
5503
5495
5504 if cleanworkdir:
5496 if cleanworkdir:
5505 # i18n: column positioning for "hg summary"
5497 # i18n: column positioning for "hg summary"
5506 ui.status(_('commit: %s\n') % t.strip())
5498 ui.status(_('commit: %s\n') % t.strip())
5507 else:
5499 else:
5508 # i18n: column positioning for "hg summary"
5500 # i18n: column positioning for "hg summary"
5509 ui.write(_('commit: %s\n') % t.strip())
5501 ui.write(_('commit: %s\n') % t.strip())
5510
5502
5511 # all ancestors of branch heads - all ancestors of parent = new csets
5503 # all ancestors of branch heads - all ancestors of parent = new csets
5512 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5504 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5513 bheads))
5505 bheads))
5514
5506
5515 if new == 0:
5507 if new == 0:
5516 # i18n: column positioning for "hg summary"
5508 # i18n: column positioning for "hg summary"
5517 ui.status(_('update: (current)\n'))
5509 ui.status(_('update: (current)\n'))
5518 elif pnode not in bheads:
5510 elif pnode not in bheads:
5519 # i18n: column positioning for "hg summary"
5511 # i18n: column positioning for "hg summary"
5520 ui.write(_('update: %d new changesets (update)\n') % new)
5512 ui.write(_('update: %d new changesets (update)\n') % new)
5521 else:
5513 else:
5522 # i18n: column positioning for "hg summary"
5514 # i18n: column positioning for "hg summary"
5523 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5515 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5524 (new, len(bheads)))
5516 (new, len(bheads)))
5525
5517
5526 cmdutil.summaryhooks(ui, repo)
5518 cmdutil.summaryhooks(ui, repo)
5527
5519
5528 if opts.get('remote'):
5520 if opts.get('remote'):
5529 t = []
5521 t = []
5530 source, branches = hg.parseurl(ui.expandpath('default'))
5522 source, branches = hg.parseurl(ui.expandpath('default'))
5531 sbranch = branches[0]
5523 sbranch = branches[0]
5532 other = hg.peer(repo, {}, source)
5524 other = hg.peer(repo, {}, source)
5533 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5525 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5534 if revs:
5526 if revs:
5535 revs = [other.lookup(rev) for rev in revs]
5527 revs = [other.lookup(rev) for rev in revs]
5536 ui.debug('comparing with %s\n' % util.hidepassword(source))
5528 ui.debug('comparing with %s\n' % util.hidepassword(source))
5537 repo.ui.pushbuffer()
5529 repo.ui.pushbuffer()
5538 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5530 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5539 _common, incoming, _rheads = commoninc
5531 _common, incoming, _rheads = commoninc
5540 repo.ui.popbuffer()
5532 repo.ui.popbuffer()
5541 if incoming:
5533 if incoming:
5542 t.append(_('1 or more incoming'))
5534 t.append(_('1 or more incoming'))
5543
5535
5544 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5536 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5545 dbranch = branches[0]
5537 dbranch = branches[0]
5546 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5538 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5547 if source != dest:
5539 if source != dest:
5548 other = hg.peer(repo, {}, dest)
5540 other = hg.peer(repo, {}, dest)
5549 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5541 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5550 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5542 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5551 commoninc = None
5543 commoninc = None
5552 if revs:
5544 if revs:
5553 revs = [repo.lookup(rev) for rev in revs]
5545 revs = [repo.lookup(rev) for rev in revs]
5554 repo.ui.pushbuffer()
5546 repo.ui.pushbuffer()
5555 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5547 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5556 commoninc=commoninc)
5548 commoninc=commoninc)
5557 repo.ui.popbuffer()
5549 repo.ui.popbuffer()
5558 o = outgoing.missing
5550 o = outgoing.missing
5559 if o:
5551 if o:
5560 t.append(_('%d outgoing') % len(o))
5552 t.append(_('%d outgoing') % len(o))
5561 if 'bookmarks' in other.listkeys('namespaces'):
5553 if 'bookmarks' in other.listkeys('namespaces'):
5562 lmarks = repo.listkeys('bookmarks')
5554 lmarks = repo.listkeys('bookmarks')
5563 rmarks = other.listkeys('bookmarks')
5555 rmarks = other.listkeys('bookmarks')
5564 diff = set(rmarks) - set(lmarks)
5556 diff = set(rmarks) - set(lmarks)
5565 if len(diff) > 0:
5557 if len(diff) > 0:
5566 t.append(_('%d incoming bookmarks') % len(diff))
5558 t.append(_('%d incoming bookmarks') % len(diff))
5567 diff = set(lmarks) - set(rmarks)
5559 diff = set(lmarks) - set(rmarks)
5568 if len(diff) > 0:
5560 if len(diff) > 0:
5569 t.append(_('%d outgoing bookmarks') % len(diff))
5561 t.append(_('%d outgoing bookmarks') % len(diff))
5570
5562
5571 if t:
5563 if t:
5572 # i18n: column positioning for "hg summary"
5564 # i18n: column positioning for "hg summary"
5573 ui.write(_('remote: %s\n') % (', '.join(t)))
5565 ui.write(_('remote: %s\n') % (', '.join(t)))
5574 else:
5566 else:
5575 # i18n: column positioning for "hg summary"
5567 # i18n: column positioning for "hg summary"
5576 ui.status(_('remote: (synced)\n'))
5568 ui.status(_('remote: (synced)\n'))
5577
5569
5578 @command('tag',
5570 @command('tag',
5579 [('f', 'force', None, _('force tag')),
5571 [('f', 'force', None, _('force tag')),
5580 ('l', 'local', None, _('make the tag local')),
5572 ('l', 'local', None, _('make the tag local')),
5581 ('r', 'rev', '', _('revision to tag'), _('REV')),
5573 ('r', 'rev', '', _('revision to tag'), _('REV')),
5582 ('', 'remove', None, _('remove a tag')),
5574 ('', 'remove', None, _('remove a tag')),
5583 # -l/--local is already there, commitopts cannot be used
5575 # -l/--local is already there, commitopts cannot be used
5584 ('e', 'edit', None, _('edit commit message')),
5576 ('e', 'edit', None, _('edit commit message')),
5585 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5577 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5586 ] + commitopts2,
5578 ] + commitopts2,
5587 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5579 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5588 def tag(ui, repo, name1, *names, **opts):
5580 def tag(ui, repo, name1, *names, **opts):
5589 """add one or more tags for the current or given revision
5581 """add one or more tags for the current or given revision
5590
5582
5591 Name a particular revision using <name>.
5583 Name a particular revision using <name>.
5592
5584
5593 Tags are used to name particular revisions of the repository and are
5585 Tags are used to name particular revisions of the repository and are
5594 very useful to compare different revisions, to go back to significant
5586 very useful to compare different revisions, to go back to significant
5595 earlier versions or to mark branch points as releases, etc. Changing
5587 earlier versions or to mark branch points as releases, etc. Changing
5596 an existing tag is normally disallowed; use -f/--force to override.
5588 an existing tag is normally disallowed; use -f/--force to override.
5597
5589
5598 If no revision is given, the parent of the working directory is
5590 If no revision is given, the parent of the working directory is
5599 used.
5591 used.
5600
5592
5601 To facilitate version control, distribution, and merging of tags,
5593 To facilitate version control, distribution, and merging of tags,
5602 they are stored as a file named ".hgtags" which is managed similarly
5594 they are stored as a file named ".hgtags" which is managed similarly
5603 to other project files and can be hand-edited if necessary. This
5595 to other project files and can be hand-edited if necessary. This
5604 also means that tagging creates a new commit. The file
5596 also means that tagging creates a new commit. The file
5605 ".hg/localtags" is used for local tags (not shared among
5597 ".hg/localtags" is used for local tags (not shared among
5606 repositories).
5598 repositories).
5607
5599
5608 Tag commits are usually made at the head of a branch. If the parent
5600 Tag commits are usually made at the head of a branch. If the parent
5609 of the working directory is not a branch head, :hg:`tag` aborts; use
5601 of the working directory is not a branch head, :hg:`tag` aborts; use
5610 -f/--force to force the tag commit to be based on a non-head
5602 -f/--force to force the tag commit to be based on a non-head
5611 changeset.
5603 changeset.
5612
5604
5613 See :hg:`help dates` for a list of formats valid for -d/--date.
5605 See :hg:`help dates` for a list of formats valid for -d/--date.
5614
5606
5615 Since tag names have priority over branch names during revision
5607 Since tag names have priority over branch names during revision
5616 lookup, using an existing branch name as a tag name is discouraged.
5608 lookup, using an existing branch name as a tag name is discouraged.
5617
5609
5618 Returns 0 on success.
5610 Returns 0 on success.
5619 """
5611 """
5620 wlock = lock = None
5612 wlock = lock = None
5621 try:
5613 try:
5622 wlock = repo.wlock()
5614 wlock = repo.wlock()
5623 lock = repo.lock()
5615 lock = repo.lock()
5624 rev_ = "."
5616 rev_ = "."
5625 names = [t.strip() for t in (name1,) + names]
5617 names = [t.strip() for t in (name1,) + names]
5626 if len(names) != len(set(names)):
5618 if len(names) != len(set(names)):
5627 raise util.Abort(_('tag names must be unique'))
5619 raise util.Abort(_('tag names must be unique'))
5628 for n in names:
5620 for n in names:
5629 scmutil.checknewlabel(repo, n, 'tag')
5621 scmutil.checknewlabel(repo, n, 'tag')
5630 if not n:
5622 if not n:
5631 raise util.Abort(_('tag names cannot consist entirely of '
5623 raise util.Abort(_('tag names cannot consist entirely of '
5632 'whitespace'))
5624 'whitespace'))
5633 if opts.get('rev') and opts.get('remove'):
5625 if opts.get('rev') and opts.get('remove'):
5634 raise util.Abort(_("--rev and --remove are incompatible"))
5626 raise util.Abort(_("--rev and --remove are incompatible"))
5635 if opts.get('rev'):
5627 if opts.get('rev'):
5636 rev_ = opts['rev']
5628 rev_ = opts['rev']
5637 message = opts.get('message')
5629 message = opts.get('message')
5638 if opts.get('remove'):
5630 if opts.get('remove'):
5639 expectedtype = opts.get('local') and 'local' or 'global'
5631 expectedtype = opts.get('local') and 'local' or 'global'
5640 for n in names:
5632 for n in names:
5641 if not repo.tagtype(n):
5633 if not repo.tagtype(n):
5642 raise util.Abort(_("tag '%s' does not exist") % n)
5634 raise util.Abort(_("tag '%s' does not exist") % n)
5643 if repo.tagtype(n) != expectedtype:
5635 if repo.tagtype(n) != expectedtype:
5644 if expectedtype == 'global':
5636 if expectedtype == 'global':
5645 raise util.Abort(_("tag '%s' is not a global tag") % n)
5637 raise util.Abort(_("tag '%s' is not a global tag") % n)
5646 else:
5638 else:
5647 raise util.Abort(_("tag '%s' is not a local tag") % n)
5639 raise util.Abort(_("tag '%s' is not a local tag") % n)
5648 rev_ = nullid
5640 rev_ = nullid
5649 if not message:
5641 if not message:
5650 # we don't translate commit messages
5642 # we don't translate commit messages
5651 message = 'Removed tag %s' % ', '.join(names)
5643 message = 'Removed tag %s' % ', '.join(names)
5652 elif not opts.get('force'):
5644 elif not opts.get('force'):
5653 for n in names:
5645 for n in names:
5654 if n in repo.tags():
5646 if n in repo.tags():
5655 raise util.Abort(_("tag '%s' already exists "
5647 raise util.Abort(_("tag '%s' already exists "
5656 "(use -f to force)") % n)
5648 "(use -f to force)") % n)
5657 if not opts.get('local'):
5649 if not opts.get('local'):
5658 p1, p2 = repo.dirstate.parents()
5650 p1, p2 = repo.dirstate.parents()
5659 if p2 != nullid:
5651 if p2 != nullid:
5660 raise util.Abort(_('uncommitted merge'))
5652 raise util.Abort(_('uncommitted merge'))
5661 bheads = repo.branchheads()
5653 bheads = repo.branchheads()
5662 if not opts.get('force') and bheads and p1 not in bheads:
5654 if not opts.get('force') and bheads and p1 not in bheads:
5663 raise util.Abort(_('not at a branch head (use -f to force)'))
5655 raise util.Abort(_('not at a branch head (use -f to force)'))
5664 r = scmutil.revsingle(repo, rev_).node()
5656 r = scmutil.revsingle(repo, rev_).node()
5665
5657
5666 if not message:
5658 if not message:
5667 # we don't translate commit messages
5659 # we don't translate commit messages
5668 message = ('Added tag %s for changeset %s' %
5660 message = ('Added tag %s for changeset %s' %
5669 (', '.join(names), short(r)))
5661 (', '.join(names), short(r)))
5670
5662
5671 date = opts.get('date')
5663 date = opts.get('date')
5672 if date:
5664 if date:
5673 date = util.parsedate(date)
5665 date = util.parsedate(date)
5674
5666
5675 if opts.get('edit'):
5667 if opts.get('edit'):
5676 message = ui.edit(message, ui.username())
5668 message = ui.edit(message, ui.username())
5677
5669
5678 # don't allow tagging the null rev
5670 # don't allow tagging the null rev
5679 if (not opts.get('remove') and
5671 if (not opts.get('remove') and
5680 scmutil.revsingle(repo, rev_).rev() == nullrev):
5672 scmutil.revsingle(repo, rev_).rev() == nullrev):
5681 raise util.Abort(_("cannot tag null revision"))
5673 raise util.Abort(_("cannot tag null revision"))
5682
5674
5683 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5675 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5684 finally:
5676 finally:
5685 release(lock, wlock)
5677 release(lock, wlock)
5686
5678
5687 @command('tags', [], '')
5679 @command('tags', [], '')
5688 def tags(ui, repo, **opts):
5680 def tags(ui, repo, **opts):
5689 """list repository tags
5681 """list repository tags
5690
5682
5691 This lists both regular and local tags. When the -v/--verbose
5683 This lists both regular and local tags. When the -v/--verbose
5692 switch is used, a third column "local" is printed for local tags.
5684 switch is used, a third column "local" is printed for local tags.
5693
5685
5694 Returns 0 on success.
5686 Returns 0 on success.
5695 """
5687 """
5696
5688
5697 fm = ui.formatter('tags', opts)
5689 fm = ui.formatter('tags', opts)
5698 hexfunc = ui.debugflag and hex or short
5690 hexfunc = ui.debugflag and hex or short
5699 tagtype = ""
5691 tagtype = ""
5700
5692
5701 for t, n in reversed(repo.tagslist()):
5693 for t, n in reversed(repo.tagslist()):
5702 hn = hexfunc(n)
5694 hn = hexfunc(n)
5703 label = 'tags.normal'
5695 label = 'tags.normal'
5704 tagtype = ''
5696 tagtype = ''
5705 if repo.tagtype(t) == 'local':
5697 if repo.tagtype(t) == 'local':
5706 label = 'tags.local'
5698 label = 'tags.local'
5707 tagtype = 'local'
5699 tagtype = 'local'
5708
5700
5709 fm.startitem()
5701 fm.startitem()
5710 fm.write('tag', '%s', t, label=label)
5702 fm.write('tag', '%s', t, label=label)
5711 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5703 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5712 fm.condwrite(not ui.quiet, 'rev id', fmt,
5704 fm.condwrite(not ui.quiet, 'rev id', fmt,
5713 repo.changelog.rev(n), hn, label=label)
5705 repo.changelog.rev(n), hn, label=label)
5714 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5706 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5715 tagtype, label=label)
5707 tagtype, label=label)
5716 fm.plain('\n')
5708 fm.plain('\n')
5717 fm.end()
5709 fm.end()
5718
5710
5719 @command('tip',
5711 @command('tip',
5720 [('p', 'patch', None, _('show patch')),
5712 [('p', 'patch', None, _('show patch')),
5721 ('g', 'git', None, _('use git extended diff format')),
5713 ('g', 'git', None, _('use git extended diff format')),
5722 ] + templateopts,
5714 ] + templateopts,
5723 _('[-p] [-g]'))
5715 _('[-p] [-g]'))
5724 def tip(ui, repo, **opts):
5716 def tip(ui, repo, **opts):
5725 """show the tip revision (DEPRECATED)
5717 """show the tip revision (DEPRECATED)
5726
5718
5727 The tip revision (usually just called the tip) is the changeset
5719 The tip revision (usually just called the tip) is the changeset
5728 most recently added to the repository (and therefore the most
5720 most recently added to the repository (and therefore the most
5729 recently changed head).
5721 recently changed head).
5730
5722
5731 If you have just made a commit, that commit will be the tip. If
5723 If you have just made a commit, that commit will be the tip. If
5732 you have just pulled changes from another repository, the tip of
5724 you have just pulled changes from another repository, the tip of
5733 that repository becomes the current tip. The "tip" tag is special
5725 that repository becomes the current tip. The "tip" tag is special
5734 and cannot be renamed or assigned to a different changeset.
5726 and cannot be renamed or assigned to a different changeset.
5735
5727
5736 This command is deprecated, please use :hg:`heads` instead.
5728 This command is deprecated, please use :hg:`heads` instead.
5737
5729
5738 Returns 0 on success.
5730 Returns 0 on success.
5739 """
5731 """
5740 displayer = cmdutil.show_changeset(ui, repo, opts)
5732 displayer = cmdutil.show_changeset(ui, repo, opts)
5741 displayer.show(repo['tip'])
5733 displayer.show(repo['tip'])
5742 displayer.close()
5734 displayer.close()
5743
5735
5744 @command('unbundle',
5736 @command('unbundle',
5745 [('u', 'update', None,
5737 [('u', 'update', None,
5746 _('update to new branch head if changesets were unbundled'))],
5738 _('update to new branch head if changesets were unbundled'))],
5747 _('[-u] FILE...'))
5739 _('[-u] FILE...'))
5748 def unbundle(ui, repo, fname1, *fnames, **opts):
5740 def unbundle(ui, repo, fname1, *fnames, **opts):
5749 """apply one or more changegroup files
5741 """apply one or more changegroup files
5750
5742
5751 Apply one or more compressed changegroup files generated by the
5743 Apply one or more compressed changegroup files generated by the
5752 bundle command.
5744 bundle command.
5753
5745
5754 Returns 0 on success, 1 if an update has unresolved files.
5746 Returns 0 on success, 1 if an update has unresolved files.
5755 """
5747 """
5756 fnames = (fname1,) + fnames
5748 fnames = (fname1,) + fnames
5757
5749
5758 lock = repo.lock()
5750 lock = repo.lock()
5759 wc = repo['.']
5751 wc = repo['.']
5760 try:
5752 try:
5761 for fname in fnames:
5753 for fname in fnames:
5762 f = hg.openpath(ui, fname)
5754 f = hg.openpath(ui, fname)
5763 gen = changegroup.readbundle(f, fname)
5755 gen = changegroup.readbundle(f, fname)
5764 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5756 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5765 finally:
5757 finally:
5766 lock.release()
5758 lock.release()
5767 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5759 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5768 return postincoming(ui, repo, modheads, opts.get('update'), None)
5760 return postincoming(ui, repo, modheads, opts.get('update'), None)
5769
5761
5770 @command('^update|up|checkout|co',
5762 @command('^update|up|checkout|co',
5771 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5763 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5772 ('c', 'check', None,
5764 ('c', 'check', None,
5773 _('update across branches if no uncommitted changes')),
5765 _('update across branches if no uncommitted changes')),
5774 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5766 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5775 ('r', 'rev', '', _('revision'), _('REV'))],
5767 ('r', 'rev', '', _('revision'), _('REV'))],
5776 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5768 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5777 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5769 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5778 """update working directory (or switch revisions)
5770 """update working directory (or switch revisions)
5779
5771
5780 Update the repository's working directory to the specified
5772 Update the repository's working directory to the specified
5781 changeset. If no changeset is specified, update to the tip of the
5773 changeset. If no changeset is specified, update to the tip of the
5782 current named branch and move the current bookmark (see :hg:`help
5774 current named branch and move the current bookmark (see :hg:`help
5783 bookmarks`).
5775 bookmarks`).
5784
5776
5785 Update sets the working directory's parent revision to the specified
5777 Update sets the working directory's parent revision to the specified
5786 changeset (see :hg:`help parents`).
5778 changeset (see :hg:`help parents`).
5787
5779
5788 If the changeset is not a descendant or ancestor of the working
5780 If the changeset is not a descendant or ancestor of the working
5789 directory's parent, the update is aborted. With the -c/--check
5781 directory's parent, the update is aborted. With the -c/--check
5790 option, the working directory is checked for uncommitted changes; if
5782 option, the working directory is checked for uncommitted changes; if
5791 none are found, the working directory is updated to the specified
5783 none are found, the working directory is updated to the specified
5792 changeset.
5784 changeset.
5793
5785
5794 .. container:: verbose
5786 .. container:: verbose
5795
5787
5796 The following rules apply when the working directory contains
5788 The following rules apply when the working directory contains
5797 uncommitted changes:
5789 uncommitted changes:
5798
5790
5799 1. If neither -c/--check nor -C/--clean is specified, and if
5791 1. If neither -c/--check nor -C/--clean is specified, and if
5800 the requested changeset is an ancestor or descendant of
5792 the requested changeset is an ancestor or descendant of
5801 the working directory's parent, the uncommitted changes
5793 the working directory's parent, the uncommitted changes
5802 are merged into the requested changeset and the merged
5794 are merged into the requested changeset and the merged
5803 result is left uncommitted. If the requested changeset is
5795 result is left uncommitted. If the requested changeset is
5804 not an ancestor or descendant (that is, it is on another
5796 not an ancestor or descendant (that is, it is on another
5805 branch), the update is aborted and the uncommitted changes
5797 branch), the update is aborted and the uncommitted changes
5806 are preserved.
5798 are preserved.
5807
5799
5808 2. With the -c/--check option, the update is aborted and the
5800 2. With the -c/--check option, the update is aborted and the
5809 uncommitted changes are preserved.
5801 uncommitted changes are preserved.
5810
5802
5811 3. With the -C/--clean option, uncommitted changes are discarded and
5803 3. With the -C/--clean option, uncommitted changes are discarded and
5812 the working directory is updated to the requested changeset.
5804 the working directory is updated to the requested changeset.
5813
5805
5814 To cancel an uncommitted merge (and lose your changes), use
5806 To cancel an uncommitted merge (and lose your changes), use
5815 :hg:`update --clean .`.
5807 :hg:`update --clean .`.
5816
5808
5817 Use null as the changeset to remove the working directory (like
5809 Use null as the changeset to remove the working directory (like
5818 :hg:`clone -U`).
5810 :hg:`clone -U`).
5819
5811
5820 If you want to revert just one file to an older revision, use
5812 If you want to revert just one file to an older revision, use
5821 :hg:`revert [-r REV] NAME`.
5813 :hg:`revert [-r REV] NAME`.
5822
5814
5823 See :hg:`help dates` for a list of formats valid for -d/--date.
5815 See :hg:`help dates` for a list of formats valid for -d/--date.
5824
5816
5825 Returns 0 on success, 1 if there are unresolved files.
5817 Returns 0 on success, 1 if there are unresolved files.
5826 """
5818 """
5827 if rev and node:
5819 if rev and node:
5828 raise util.Abort(_("please specify just one revision"))
5820 raise util.Abort(_("please specify just one revision"))
5829
5821
5830 if rev is None or rev == '':
5822 if rev is None or rev == '':
5831 rev = node
5823 rev = node
5832
5824
5833 cmdutil.clearunfinished(repo)
5825 cmdutil.clearunfinished(repo)
5834
5826
5835 # with no argument, we also move the current bookmark, if any
5827 # with no argument, we also move the current bookmark, if any
5836 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5828 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5837
5829
5838 # if we defined a bookmark, we have to remember the original bookmark name
5830 # if we defined a bookmark, we have to remember the original bookmark name
5839 brev = rev
5831 brev = rev
5840 rev = scmutil.revsingle(repo, rev, rev).rev()
5832 rev = scmutil.revsingle(repo, rev, rev).rev()
5841
5833
5842 if check and clean:
5834 if check and clean:
5843 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5835 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5844
5836
5845 if date:
5837 if date:
5846 if rev is not None:
5838 if rev is not None:
5847 raise util.Abort(_("you can't specify a revision and a date"))
5839 raise util.Abort(_("you can't specify a revision and a date"))
5848 rev = cmdutil.finddate(ui, repo, date)
5840 rev = cmdutil.finddate(ui, repo, date)
5849
5841
5850 if check:
5842 if check:
5851 c = repo[None]
5843 c = repo[None]
5852 if c.dirty(merge=False, branch=False, missing=True):
5844 if c.dirty(merge=False, branch=False, missing=True):
5853 raise util.Abort(_("uncommitted changes"))
5845 raise util.Abort(_("uncommitted changes"))
5854 if rev is None:
5846 if rev is None:
5855 rev = repo[repo[None].branch()].rev()
5847 rev = repo[repo[None].branch()].rev()
5856 mergemod._checkunknown(repo, repo[None], repo[rev])
5848 mergemod._checkunknown(repo, repo[None], repo[rev])
5857
5849
5858 if clean:
5850 if clean:
5859 ret = hg.clean(repo, rev)
5851 ret = hg.clean(repo, rev)
5860 else:
5852 else:
5861 ret = hg.update(repo, rev)
5853 ret = hg.update(repo, rev)
5862
5854
5863 if not ret and movemarkfrom:
5855 if not ret and movemarkfrom:
5864 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5856 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5865 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5857 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5866 elif brev in repo._bookmarks:
5858 elif brev in repo._bookmarks:
5867 bookmarks.setcurrent(repo, brev)
5859 bookmarks.setcurrent(repo, brev)
5868 elif brev:
5860 elif brev:
5869 bookmarks.unsetcurrent(repo)
5861 bookmarks.unsetcurrent(repo)
5870
5862
5871 return ret
5863 return ret
5872
5864
5873 @command('verify', [])
5865 @command('verify', [])
5874 def verify(ui, repo):
5866 def verify(ui, repo):
5875 """verify the integrity of the repository
5867 """verify the integrity of the repository
5876
5868
5877 Verify the integrity of the current repository.
5869 Verify the integrity of the current repository.
5878
5870
5879 This will perform an extensive check of the repository's
5871 This will perform an extensive check of the repository's
5880 integrity, validating the hashes and checksums of each entry in
5872 integrity, validating the hashes and checksums of each entry in
5881 the changelog, manifest, and tracked files, as well as the
5873 the changelog, manifest, and tracked files, as well as the
5882 integrity of their crosslinks and indices.
5874 integrity of their crosslinks and indices.
5883
5875
5884 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5876 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5885 for more information about recovery from corruption of the
5877 for more information about recovery from corruption of the
5886 repository.
5878 repository.
5887
5879
5888 Returns 0 on success, 1 if errors are encountered.
5880 Returns 0 on success, 1 if errors are encountered.
5889 """
5881 """
5890 return hg.verify(repo)
5882 return hg.verify(repo)
5891
5883
5892 @command('version', [])
5884 @command('version', [])
5893 def version_(ui):
5885 def version_(ui):
5894 """output version and copyright information"""
5886 """output version and copyright information"""
5895 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5887 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5896 % util.version())
5888 % util.version())
5897 ui.status(_(
5889 ui.status(_(
5898 "(see http://mercurial.selenic.com for more information)\n"
5890 "(see http://mercurial.selenic.com for more information)\n"
5899 "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
5891 "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
5900 "This is free software; see the source for copying conditions. "
5892 "This is free software; see the source for copying conditions. "
5901 "There is NO\nwarranty; "
5893 "There is NO\nwarranty; "
5902 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5894 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5903 ))
5895 ))
5904
5896
5905 norepo = ("clone init version help debugcommands debugcomplete"
5897 norepo = ("clone init version help debugcommands debugcomplete"
5906 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5898 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5907 " debugknown debuggetbundle debugbundle")
5899 " debugknown debuggetbundle debugbundle")
5908 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5900 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5909 " debugdata debugindex debugindexdot debugrevlog")
5901 " debugdata debugindex debugindexdot debugrevlog")
5910 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5902 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5911 " remove resolve status debugwalk")
5903 " remove resolve status debugwalk")
General Comments 0
You need to be logged in to leave comments. Login now