##// END OF EJS Templates
backout: avoid update on simple case....
Pierre-Yves David -
r20275:2123d27f default
parent child Browse files
Show More
@@ -1,5909 +1,5916 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)
465 repo.dirstate.setbranch(branch)
466 rctx = scmutil.revsingle(repo, hex(parent))
464 rctx = scmutil.revsingle(repo, hex(parent))
467 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
468 if not opts.get('merge') and op1 != node:
465 if not opts.get('merge') and op1 != node:
469 try:
466 try:
470 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
467 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
471 return hg.update(repo, op1)
468 stats = mergemod.update(repo, parent, True, True, False, node, False)
469 repo.setparents(op1, op2)
470 hg._showstats(repo, stats)
471 if stats[3]:
472 repo.ui.status(_("use 'hg resolve' to retry unresolved file merges\n"))
473 return stats[3] > 0
472 finally:
474 finally:
473 ui.setconfig('ui', 'forcemerge', '')
475 ui.setconfig('ui', 'forcemerge', '')
476 else:
477 hg.clean(repo, node, show_stats=False)
478 repo.dirstate.setbranch(branch)
479 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
480
474
481
475 e = cmdutil.commiteditor
482 e = cmdutil.commiteditor
476 if not opts['message'] and not opts['logfile']:
483 if not opts['message'] and not opts['logfile']:
477 # we don't translate commit messages
484 # we don't translate commit messages
478 opts['message'] = "Backed out changeset %s" % short(node)
485 opts['message'] = "Backed out changeset %s" % short(node)
479 e = cmdutil.commitforceeditor
486 e = cmdutil.commitforceeditor
480
487
481 def commitfunc(ui, repo, message, match, opts):
488 def commitfunc(ui, repo, message, match, opts):
482 return repo.commit(message, opts.get('user'), opts.get('date'),
489 return repo.commit(message, opts.get('user'), opts.get('date'),
483 match, editor=e)
490 match, editor=e)
484 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
491 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
485 cmdutil.commitstatus(repo, newnode, branch, bheads)
492 cmdutil.commitstatus(repo, newnode, branch, bheads)
486
493
487 def nice(node):
494 def nice(node):
488 return '%d:%s' % (repo.changelog.rev(node), short(node))
495 return '%d:%s' % (repo.changelog.rev(node), short(node))
489 ui.status(_('changeset %s backs out changeset %s\n') %
496 ui.status(_('changeset %s backs out changeset %s\n') %
490 (nice(repo.changelog.tip()), nice(node)))
497 (nice(repo.changelog.tip()), nice(node)))
491 if opts.get('merge') and op1 != node:
498 if opts.get('merge') and op1 != node:
492 hg.clean(repo, op1, show_stats=False)
499 hg.clean(repo, op1, show_stats=False)
493 ui.status(_('merging with changeset %s\n')
500 ui.status(_('merging with changeset %s\n')
494 % nice(repo.changelog.tip()))
501 % nice(repo.changelog.tip()))
495 try:
502 try:
496 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
503 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
497 return hg.merge(repo, hex(repo.changelog.tip()))
504 return hg.merge(repo, hex(repo.changelog.tip()))
498 finally:
505 finally:
499 ui.setconfig('ui', 'forcemerge', '')
506 ui.setconfig('ui', 'forcemerge', '')
500 finally:
507 finally:
501 wlock.release()
508 wlock.release()
502 return 0
509 return 0
503
510
504 @command('bisect',
511 @command('bisect',
505 [('r', 'reset', False, _('reset bisect state')),
512 [('r', 'reset', False, _('reset bisect state')),
506 ('g', 'good', False, _('mark changeset good')),
513 ('g', 'good', False, _('mark changeset good')),
507 ('b', 'bad', False, _('mark changeset bad')),
514 ('b', 'bad', False, _('mark changeset bad')),
508 ('s', 'skip', False, _('skip testing changeset')),
515 ('s', 'skip', False, _('skip testing changeset')),
509 ('e', 'extend', False, _('extend the bisect range')),
516 ('e', 'extend', False, _('extend the bisect range')),
510 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
517 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
511 ('U', 'noupdate', False, _('do not update to target'))],
518 ('U', 'noupdate', False, _('do not update to target'))],
512 _("[-gbsr] [-U] [-c CMD] [REV]"))
519 _("[-gbsr] [-U] [-c CMD] [REV]"))
513 def bisect(ui, repo, rev=None, extra=None, command=None,
520 def bisect(ui, repo, rev=None, extra=None, command=None,
514 reset=None, good=None, bad=None, skip=None, extend=None,
521 reset=None, good=None, bad=None, skip=None, extend=None,
515 noupdate=None):
522 noupdate=None):
516 """subdivision search of changesets
523 """subdivision search of changesets
517
524
518 This command helps to find changesets which introduce problems. To
525 This command helps to find changesets which introduce problems. To
519 use, mark the earliest changeset you know exhibits the problem as
526 use, mark the earliest changeset you know exhibits the problem as
520 bad, then mark the latest changeset which is free from the problem
527 bad, then mark the latest changeset which is free from the problem
521 as good. Bisect will update your working directory to a revision
528 as good. Bisect will update your working directory to a revision
522 for testing (unless the -U/--noupdate option is specified). Once
529 for testing (unless the -U/--noupdate option is specified). Once
523 you have performed tests, mark the working directory as good or
530 you have performed tests, mark the working directory as good or
524 bad, and bisect will either update to another candidate changeset
531 bad, and bisect will either update to another candidate changeset
525 or announce that it has found the bad revision.
532 or announce that it has found the bad revision.
526
533
527 As a shortcut, you can also use the revision argument to mark a
534 As a shortcut, you can also use the revision argument to mark a
528 revision as good or bad without checking it out first.
535 revision as good or bad without checking it out first.
529
536
530 If you supply a command, it will be used for automatic bisection.
537 If you supply a command, it will be used for automatic bisection.
531 The environment variable HG_NODE will contain the ID of the
538 The environment variable HG_NODE will contain the ID of the
532 changeset being tested. The exit status of the command will be
539 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
540 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
541 means to skip the revision, 127 (command not found) will abort the
535 bisection, and any other non-zero exit status means the revision
542 bisection, and any other non-zero exit status means the revision
536 is bad.
543 is bad.
537
544
538 .. container:: verbose
545 .. container:: verbose
539
546
540 Some examples:
547 Some examples:
541
548
542 - start a bisection with known bad revision 34, and good revision 12::
549 - start a bisection with known bad revision 34, and good revision 12::
543
550
544 hg bisect --bad 34
551 hg bisect --bad 34
545 hg bisect --good 12
552 hg bisect --good 12
546
553
547 - advance the current bisection by marking current revision as good or
554 - advance the current bisection by marking current revision as good or
548 bad::
555 bad::
549
556
550 hg bisect --good
557 hg bisect --good
551 hg bisect --bad
558 hg bisect --bad
552
559
553 - mark the current revision, or a known revision, to be skipped (e.g. if
560 - mark the current revision, or a known revision, to be skipped (e.g. if
554 that revision is not usable because of another issue)::
561 that revision is not usable because of another issue)::
555
562
556 hg bisect --skip
563 hg bisect --skip
557 hg bisect --skip 23
564 hg bisect --skip 23
558
565
559 - skip all revisions that do not touch directories ``foo`` or ``bar``::
566 - skip all revisions that do not touch directories ``foo`` or ``bar``::
560
567
561 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
568 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
562
569
563 - forget the current bisection::
570 - forget the current bisection::
564
571
565 hg bisect --reset
572 hg bisect --reset
566
573
567 - use 'make && make tests' to automatically find the first broken
574 - use 'make && make tests' to automatically find the first broken
568 revision::
575 revision::
569
576
570 hg bisect --reset
577 hg bisect --reset
571 hg bisect --bad 34
578 hg bisect --bad 34
572 hg bisect --good 12
579 hg bisect --good 12
573 hg bisect --command "make && make tests"
580 hg bisect --command "make && make tests"
574
581
575 - see all changesets whose states are already known in the current
582 - see all changesets whose states are already known in the current
576 bisection::
583 bisection::
577
584
578 hg log -r "bisect(pruned)"
585 hg log -r "bisect(pruned)"
579
586
580 - see the changeset currently being bisected (especially useful
587 - see the changeset currently being bisected (especially useful
581 if running with -U/--noupdate)::
588 if running with -U/--noupdate)::
582
589
583 hg log -r "bisect(current)"
590 hg log -r "bisect(current)"
584
591
585 - see all changesets that took part in the current bisection::
592 - see all changesets that took part in the current bisection::
586
593
587 hg log -r "bisect(range)"
594 hg log -r "bisect(range)"
588
595
589 - you can even get a nice graph::
596 - you can even get a nice graph::
590
597
591 hg log --graph -r "bisect(range)"
598 hg log --graph -r "bisect(range)"
592
599
593 See :hg:`help revsets` for more about the `bisect()` keyword.
600 See :hg:`help revsets` for more about the `bisect()` keyword.
594
601
595 Returns 0 on success.
602 Returns 0 on success.
596 """
603 """
597 def extendbisectrange(nodes, good):
604 def extendbisectrange(nodes, good):
598 # bisect is incomplete when it ends on a merge node and
605 # bisect is incomplete when it ends on a merge node and
599 # one of the parent was not checked.
606 # one of the parent was not checked.
600 parents = repo[nodes[0]].parents()
607 parents = repo[nodes[0]].parents()
601 if len(parents) > 1:
608 if len(parents) > 1:
602 side = good and state['bad'] or state['good']
609 side = good and state['bad'] or state['good']
603 num = len(set(i.node() for i in parents) & set(side))
610 num = len(set(i.node() for i in parents) & set(side))
604 if num == 1:
611 if num == 1:
605 return parents[0].ancestor(parents[1])
612 return parents[0].ancestor(parents[1])
606 return None
613 return None
607
614
608 def print_result(nodes, good):
615 def print_result(nodes, good):
609 displayer = cmdutil.show_changeset(ui, repo, {})
616 displayer = cmdutil.show_changeset(ui, repo, {})
610 if len(nodes) == 1:
617 if len(nodes) == 1:
611 # narrowed it down to a single revision
618 # narrowed it down to a single revision
612 if good:
619 if good:
613 ui.write(_("The first good revision is:\n"))
620 ui.write(_("The first good revision is:\n"))
614 else:
621 else:
615 ui.write(_("The first bad revision is:\n"))
622 ui.write(_("The first bad revision is:\n"))
616 displayer.show(repo[nodes[0]])
623 displayer.show(repo[nodes[0]])
617 extendnode = extendbisectrange(nodes, good)
624 extendnode = extendbisectrange(nodes, good)
618 if extendnode is not None:
625 if extendnode is not None:
619 ui.write(_('Not all ancestors of this changeset have been'
626 ui.write(_('Not all ancestors of this changeset have been'
620 ' checked.\nUse bisect --extend to continue the '
627 ' checked.\nUse bisect --extend to continue the '
621 'bisection from\nthe common ancestor, %s.\n')
628 'bisection from\nthe common ancestor, %s.\n')
622 % extendnode)
629 % extendnode)
623 else:
630 else:
624 # multiple possible revisions
631 # multiple possible revisions
625 if good:
632 if good:
626 ui.write(_("Due to skipped revisions, the first "
633 ui.write(_("Due to skipped revisions, the first "
627 "good revision could be any of:\n"))
634 "good revision could be any of:\n"))
628 else:
635 else:
629 ui.write(_("Due to skipped revisions, the first "
636 ui.write(_("Due to skipped revisions, the first "
630 "bad revision could be any of:\n"))
637 "bad revision could be any of:\n"))
631 for n in nodes:
638 for n in nodes:
632 displayer.show(repo[n])
639 displayer.show(repo[n])
633 displayer.close()
640 displayer.close()
634
641
635 def check_state(state, interactive=True):
642 def check_state(state, interactive=True):
636 if not state['good'] or not state['bad']:
643 if not state['good'] or not state['bad']:
637 if (good or bad or skip or reset) and interactive:
644 if (good or bad or skip or reset) and interactive:
638 return
645 return
639 if not state['good']:
646 if not state['good']:
640 raise util.Abort(_('cannot bisect (no known good revisions)'))
647 raise util.Abort(_('cannot bisect (no known good revisions)'))
641 else:
648 else:
642 raise util.Abort(_('cannot bisect (no known bad revisions)'))
649 raise util.Abort(_('cannot bisect (no known bad revisions)'))
643 return True
650 return True
644
651
645 # backward compatibility
652 # backward compatibility
646 if rev in "good bad reset init".split():
653 if rev in "good bad reset init".split():
647 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
654 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
648 cmd, rev, extra = rev, extra, None
655 cmd, rev, extra = rev, extra, None
649 if cmd == "good":
656 if cmd == "good":
650 good = True
657 good = True
651 elif cmd == "bad":
658 elif cmd == "bad":
652 bad = True
659 bad = True
653 else:
660 else:
654 reset = True
661 reset = True
655 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
662 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
656 raise util.Abort(_('incompatible arguments'))
663 raise util.Abort(_('incompatible arguments'))
657
664
658 cmdutil.checkunfinished(repo)
665 cmdutil.checkunfinished(repo)
659
666
660 if reset:
667 if reset:
661 p = repo.join("bisect.state")
668 p = repo.join("bisect.state")
662 if os.path.exists(p):
669 if os.path.exists(p):
663 os.unlink(p)
670 os.unlink(p)
664 return
671 return
665
672
666 state = hbisect.load_state(repo)
673 state = hbisect.load_state(repo)
667
674
668 if command:
675 if command:
669 changesets = 1
676 changesets = 1
670 if noupdate:
677 if noupdate:
671 try:
678 try:
672 node = state['current'][0]
679 node = state['current'][0]
673 except LookupError:
680 except LookupError:
674 raise util.Abort(_('current bisect revision is unknown - '
681 raise util.Abort(_('current bisect revision is unknown - '
675 'start a new bisect to fix'))
682 'start a new bisect to fix'))
676 else:
683 else:
677 node, p2 = repo.dirstate.parents()
684 node, p2 = repo.dirstate.parents()
678 if p2 != nullid:
685 if p2 != nullid:
679 raise util.Abort(_('current bisect revision is a merge'))
686 raise util.Abort(_('current bisect revision is a merge'))
680 try:
687 try:
681 while changesets:
688 while changesets:
682 # update state
689 # update state
683 state['current'] = [node]
690 state['current'] = [node]
684 hbisect.save_state(repo, state)
691 hbisect.save_state(repo, state)
685 status = util.system(command,
692 status = util.system(command,
686 environ={'HG_NODE': hex(node)},
693 environ={'HG_NODE': hex(node)},
687 out=ui.fout)
694 out=ui.fout)
688 if status == 125:
695 if status == 125:
689 transition = "skip"
696 transition = "skip"
690 elif status == 0:
697 elif status == 0:
691 transition = "good"
698 transition = "good"
692 # status < 0 means process was killed
699 # status < 0 means process was killed
693 elif status == 127:
700 elif status == 127:
694 raise util.Abort(_("failed to execute %s") % command)
701 raise util.Abort(_("failed to execute %s") % command)
695 elif status < 0:
702 elif status < 0:
696 raise util.Abort(_("%s killed") % command)
703 raise util.Abort(_("%s killed") % command)
697 else:
704 else:
698 transition = "bad"
705 transition = "bad"
699 ctx = scmutil.revsingle(repo, rev, node)
706 ctx = scmutil.revsingle(repo, rev, node)
700 rev = None # clear for future iterations
707 rev = None # clear for future iterations
701 state[transition].append(ctx.node())
708 state[transition].append(ctx.node())
702 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
709 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
703 check_state(state, interactive=False)
710 check_state(state, interactive=False)
704 # bisect
711 # bisect
705 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
712 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
706 # update to next check
713 # update to next check
707 node = nodes[0]
714 node = nodes[0]
708 if not noupdate:
715 if not noupdate:
709 cmdutil.bailifchanged(repo)
716 cmdutil.bailifchanged(repo)
710 hg.clean(repo, node, show_stats=False)
717 hg.clean(repo, node, show_stats=False)
711 finally:
718 finally:
712 state['current'] = [node]
719 state['current'] = [node]
713 hbisect.save_state(repo, state)
720 hbisect.save_state(repo, state)
714 print_result(nodes, bgood)
721 print_result(nodes, bgood)
715 return
722 return
716
723
717 # update state
724 # update state
718
725
719 if rev:
726 if rev:
720 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
727 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
721 else:
728 else:
722 nodes = [repo.lookup('.')]
729 nodes = [repo.lookup('.')]
723
730
724 if good or bad or skip:
731 if good or bad or skip:
725 if good:
732 if good:
726 state['good'] += nodes
733 state['good'] += nodes
727 elif bad:
734 elif bad:
728 state['bad'] += nodes
735 state['bad'] += nodes
729 elif skip:
736 elif skip:
730 state['skip'] += nodes
737 state['skip'] += nodes
731 hbisect.save_state(repo, state)
738 hbisect.save_state(repo, state)
732
739
733 if not check_state(state):
740 if not check_state(state):
734 return
741 return
735
742
736 # actually bisect
743 # actually bisect
737 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
744 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
738 if extend:
745 if extend:
739 if not changesets:
746 if not changesets:
740 extendnode = extendbisectrange(nodes, good)
747 extendnode = extendbisectrange(nodes, good)
741 if extendnode is not None:
748 if extendnode is not None:
742 ui.write(_("Extending search to changeset %d:%s\n"
749 ui.write(_("Extending search to changeset %d:%s\n"
743 % (extendnode.rev(), extendnode)))
750 % (extendnode.rev(), extendnode)))
744 state['current'] = [extendnode.node()]
751 state['current'] = [extendnode.node()]
745 hbisect.save_state(repo, state)
752 hbisect.save_state(repo, state)
746 if noupdate:
753 if noupdate:
747 return
754 return
748 cmdutil.bailifchanged(repo)
755 cmdutil.bailifchanged(repo)
749 return hg.clean(repo, extendnode.node())
756 return hg.clean(repo, extendnode.node())
750 raise util.Abort(_("nothing to extend"))
757 raise util.Abort(_("nothing to extend"))
751
758
752 if changesets == 0:
759 if changesets == 0:
753 print_result(nodes, good)
760 print_result(nodes, good)
754 else:
761 else:
755 assert len(nodes) == 1 # only a single node can be tested next
762 assert len(nodes) == 1 # only a single node can be tested next
756 node = nodes[0]
763 node = nodes[0]
757 # compute the approximate number of remaining tests
764 # compute the approximate number of remaining tests
758 tests, size = 0, 2
765 tests, size = 0, 2
759 while size <= changesets:
766 while size <= changesets:
760 tests, size = tests + 1, size * 2
767 tests, size = tests + 1, size * 2
761 rev = repo.changelog.rev(node)
768 rev = repo.changelog.rev(node)
762 ui.write(_("Testing changeset %d:%s "
769 ui.write(_("Testing changeset %d:%s "
763 "(%d changesets remaining, ~%d tests)\n")
770 "(%d changesets remaining, ~%d tests)\n")
764 % (rev, short(node), changesets, tests))
771 % (rev, short(node), changesets, tests))
765 state['current'] = [node]
772 state['current'] = [node]
766 hbisect.save_state(repo, state)
773 hbisect.save_state(repo, state)
767 if not noupdate:
774 if not noupdate:
768 cmdutil.bailifchanged(repo)
775 cmdutil.bailifchanged(repo)
769 return hg.clean(repo, node)
776 return hg.clean(repo, node)
770
777
771 @command('bookmarks|bookmark',
778 @command('bookmarks|bookmark',
772 [('f', 'force', False, _('force')),
779 [('f', 'force', False, _('force')),
773 ('r', 'rev', '', _('revision'), _('REV')),
780 ('r', 'rev', '', _('revision'), _('REV')),
774 ('d', 'delete', False, _('delete a given bookmark')),
781 ('d', 'delete', False, _('delete a given bookmark')),
775 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
782 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
776 ('i', 'inactive', False, _('mark a bookmark inactive'))],
783 ('i', 'inactive', False, _('mark a bookmark inactive'))],
777 _('hg bookmarks [OPTIONS]... [NAME]...'))
784 _('hg bookmarks [OPTIONS]... [NAME]...'))
778 def bookmark(ui, repo, *names, **opts):
785 def bookmark(ui, repo, *names, **opts):
779 '''track a line of development with movable markers
786 '''track a line of development with movable markers
780
787
781 Bookmarks are pointers to certain commits that move when committing.
788 Bookmarks are pointers to certain commits that move when committing.
782 Bookmarks are local. They can be renamed, copied and deleted. It is
789 Bookmarks are local. They can be renamed, copied and deleted. It is
783 possible to use :hg:`merge NAME` to merge from a given bookmark, and
790 possible to use :hg:`merge NAME` to merge from a given bookmark, and
784 :hg:`update NAME` to update to a given bookmark.
791 :hg:`update NAME` to update to a given bookmark.
785
792
786 You can use :hg:`bookmark NAME` to set a bookmark on the working
793 You can use :hg:`bookmark NAME` to set a bookmark on the working
787 directory's parent revision with the given name. If you specify
794 directory's parent revision with the given name. If you specify
788 a revision using -r REV (where REV may be an existing bookmark),
795 a revision using -r REV (where REV may be an existing bookmark),
789 the bookmark is assigned to that revision.
796 the bookmark is assigned to that revision.
790
797
791 Bookmarks can be pushed and pulled between repositories (see :hg:`help
798 Bookmarks can be pushed and pulled between repositories (see :hg:`help
792 push` and :hg:`help pull`). This requires both the local and remote
799 push` and :hg:`help pull`). This requires both the local and remote
793 repositories to support bookmarks. For versions prior to 1.8, this means
800 repositories to support bookmarks. For versions prior to 1.8, this means
794 the bookmarks extension must be enabled.
801 the bookmarks extension must be enabled.
795
802
796 If you set a bookmark called '@', new clones of the repository will
803 If you set a bookmark called '@', new clones of the repository will
797 have that revision checked out (and the bookmark made active) by
804 have that revision checked out (and the bookmark made active) by
798 default.
805 default.
799
806
800 With -i/--inactive, the new bookmark will not be made the active
807 With -i/--inactive, the new bookmark will not be made the active
801 bookmark. If -r/--rev is given, the new bookmark will not be made
808 bookmark. If -r/--rev is given, the new bookmark will not be made
802 active even if -i/--inactive is not given. If no NAME is given, the
809 active even if -i/--inactive is not given. If no NAME is given, the
803 current active bookmark will be marked inactive.
810 current active bookmark will be marked inactive.
804 '''
811 '''
805 force = opts.get('force')
812 force = opts.get('force')
806 rev = opts.get('rev')
813 rev = opts.get('rev')
807 delete = opts.get('delete')
814 delete = opts.get('delete')
808 rename = opts.get('rename')
815 rename = opts.get('rename')
809 inactive = opts.get('inactive')
816 inactive = opts.get('inactive')
810
817
811 def checkformat(mark):
818 def checkformat(mark):
812 mark = mark.strip()
819 mark = mark.strip()
813 if not mark:
820 if not mark:
814 raise util.Abort(_("bookmark names cannot consist entirely of "
821 raise util.Abort(_("bookmark names cannot consist entirely of "
815 "whitespace"))
822 "whitespace"))
816 scmutil.checknewlabel(repo, mark, 'bookmark')
823 scmutil.checknewlabel(repo, mark, 'bookmark')
817 return mark
824 return mark
818
825
819 def checkconflict(repo, mark, cur, force=False, target=None):
826 def checkconflict(repo, mark, cur, force=False, target=None):
820 if mark in marks and not force:
827 if mark in marks and not force:
821 if target:
828 if target:
822 if marks[mark] == target and target == cur:
829 if marks[mark] == target and target == cur:
823 # re-activating a bookmark
830 # re-activating a bookmark
824 return
831 return
825 anc = repo.changelog.ancestors([repo[target].rev()])
832 anc = repo.changelog.ancestors([repo[target].rev()])
826 bmctx = repo[marks[mark]]
833 bmctx = repo[marks[mark]]
827 divs = [repo[b].node() for b in marks
834 divs = [repo[b].node() for b in marks
828 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
835 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
829
836
830 # allow resolving a single divergent bookmark even if moving
837 # allow resolving a single divergent bookmark even if moving
831 # the bookmark across branches when a revision is specified
838 # the bookmark across branches when a revision is specified
832 # that contains a divergent bookmark
839 # that contains a divergent bookmark
833 if bmctx.rev() not in anc and target in divs:
840 if bmctx.rev() not in anc and target in divs:
834 bookmarks.deletedivergent(repo, [target], mark)
841 bookmarks.deletedivergent(repo, [target], mark)
835 return
842 return
836
843
837 # consider successor changesets as well
844 # consider successor changesets as well
838 foreground = obsolete.foreground(repo, [marks[mark]])
845 foreground = obsolete.foreground(repo, [marks[mark]])
839 deletefrom = [b for b in divs
846 deletefrom = [b for b in divs
840 if repo[b].rev() in anc or b == target]
847 if repo[b].rev() in anc or b == target]
841 bookmarks.deletedivergent(repo, deletefrom, mark)
848 bookmarks.deletedivergent(repo, deletefrom, mark)
842 if bmctx.rev() in anc or target in foreground:
849 if bmctx.rev() in anc or target in foreground:
843 ui.status(_("moving bookmark '%s' forward from %s\n") %
850 ui.status(_("moving bookmark '%s' forward from %s\n") %
844 (mark, short(bmctx.node())))
851 (mark, short(bmctx.node())))
845 return
852 return
846 raise util.Abort(_("bookmark '%s' already exists "
853 raise util.Abort(_("bookmark '%s' already exists "
847 "(use -f to force)") % mark)
854 "(use -f to force)") % mark)
848 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
855 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
849 and not force):
856 and not force):
850 raise util.Abort(
857 raise util.Abort(
851 _("a bookmark cannot have the name of an existing branch"))
858 _("a bookmark cannot have the name of an existing branch"))
852
859
853 if delete and rename:
860 if delete and rename:
854 raise util.Abort(_("--delete and --rename are incompatible"))
861 raise util.Abort(_("--delete and --rename are incompatible"))
855 if delete and rev:
862 if delete and rev:
856 raise util.Abort(_("--rev is incompatible with --delete"))
863 raise util.Abort(_("--rev is incompatible with --delete"))
857 if rename and rev:
864 if rename and rev:
858 raise util.Abort(_("--rev is incompatible with --rename"))
865 raise util.Abort(_("--rev is incompatible with --rename"))
859 if not names and (delete or rev):
866 if not names and (delete or rev):
860 raise util.Abort(_("bookmark name required"))
867 raise util.Abort(_("bookmark name required"))
861
868
862 if delete or rename or names or inactive:
869 if delete or rename or names or inactive:
863 wlock = repo.wlock()
870 wlock = repo.wlock()
864 try:
871 try:
865 cur = repo.changectx('.').node()
872 cur = repo.changectx('.').node()
866 marks = repo._bookmarks
873 marks = repo._bookmarks
867 if delete:
874 if delete:
868 for mark in names:
875 for mark in names:
869 if mark not in marks:
876 if mark not in marks:
870 raise util.Abort(_("bookmark '%s' does not exist") %
877 raise util.Abort(_("bookmark '%s' does not exist") %
871 mark)
878 mark)
872 if mark == repo._bookmarkcurrent:
879 if mark == repo._bookmarkcurrent:
873 bookmarks.unsetcurrent(repo)
880 bookmarks.unsetcurrent(repo)
874 del marks[mark]
881 del marks[mark]
875 marks.write()
882 marks.write()
876
883
877 elif rename:
884 elif rename:
878 if not names:
885 if not names:
879 raise util.Abort(_("new bookmark name required"))
886 raise util.Abort(_("new bookmark name required"))
880 elif len(names) > 1:
887 elif len(names) > 1:
881 raise util.Abort(_("only one new bookmark name allowed"))
888 raise util.Abort(_("only one new bookmark name allowed"))
882 mark = checkformat(names[0])
889 mark = checkformat(names[0])
883 if rename not in marks:
890 if rename not in marks:
884 raise util.Abort(_("bookmark '%s' does not exist") % rename)
891 raise util.Abort(_("bookmark '%s' does not exist") % rename)
885 checkconflict(repo, mark, cur, force)
892 checkconflict(repo, mark, cur, force)
886 marks[mark] = marks[rename]
893 marks[mark] = marks[rename]
887 if repo._bookmarkcurrent == rename and not inactive:
894 if repo._bookmarkcurrent == rename and not inactive:
888 bookmarks.setcurrent(repo, mark)
895 bookmarks.setcurrent(repo, mark)
889 del marks[rename]
896 del marks[rename]
890 marks.write()
897 marks.write()
891
898
892 elif names:
899 elif names:
893 newact = None
900 newact = None
894 for mark in names:
901 for mark in names:
895 mark = checkformat(mark)
902 mark = checkformat(mark)
896 if newact is None:
903 if newact is None:
897 newact = mark
904 newact = mark
898 if inactive and mark == repo._bookmarkcurrent:
905 if inactive and mark == repo._bookmarkcurrent:
899 bookmarks.unsetcurrent(repo)
906 bookmarks.unsetcurrent(repo)
900 return
907 return
901 tgt = cur
908 tgt = cur
902 if rev:
909 if rev:
903 tgt = scmutil.revsingle(repo, rev).node()
910 tgt = scmutil.revsingle(repo, rev).node()
904 checkconflict(repo, mark, cur, force, tgt)
911 checkconflict(repo, mark, cur, force, tgt)
905 marks[mark] = tgt
912 marks[mark] = tgt
906 if not inactive and cur == marks[newact] and not rev:
913 if not inactive and cur == marks[newact] and not rev:
907 bookmarks.setcurrent(repo, newact)
914 bookmarks.setcurrent(repo, newact)
908 elif cur != tgt and newact == repo._bookmarkcurrent:
915 elif cur != tgt and newact == repo._bookmarkcurrent:
909 bookmarks.unsetcurrent(repo)
916 bookmarks.unsetcurrent(repo)
910 marks.write()
917 marks.write()
911
918
912 elif inactive:
919 elif inactive:
913 if len(marks) == 0:
920 if len(marks) == 0:
914 ui.status(_("no bookmarks set\n"))
921 ui.status(_("no bookmarks set\n"))
915 elif not repo._bookmarkcurrent:
922 elif not repo._bookmarkcurrent:
916 ui.status(_("no active bookmark\n"))
923 ui.status(_("no active bookmark\n"))
917 else:
924 else:
918 bookmarks.unsetcurrent(repo)
925 bookmarks.unsetcurrent(repo)
919 finally:
926 finally:
920 wlock.release()
927 wlock.release()
921 else: # show bookmarks
928 else: # show bookmarks
922 hexfn = ui.debugflag and hex or short
929 hexfn = ui.debugflag and hex or short
923 marks = repo._bookmarks
930 marks = repo._bookmarks
924 if len(marks) == 0:
931 if len(marks) == 0:
925 ui.status(_("no bookmarks set\n"))
932 ui.status(_("no bookmarks set\n"))
926 else:
933 else:
927 for bmark, n in sorted(marks.iteritems()):
934 for bmark, n in sorted(marks.iteritems()):
928 current = repo._bookmarkcurrent
935 current = repo._bookmarkcurrent
929 if bmark == current:
936 if bmark == current:
930 prefix, label = '*', 'bookmarks.current'
937 prefix, label = '*', 'bookmarks.current'
931 else:
938 else:
932 prefix, label = ' ', ''
939 prefix, label = ' ', ''
933
940
934 if ui.quiet:
941 if ui.quiet:
935 ui.write("%s\n" % bmark, label=label)
942 ui.write("%s\n" % bmark, label=label)
936 else:
943 else:
937 ui.write(" %s %-25s %d:%s\n" % (
944 ui.write(" %s %-25s %d:%s\n" % (
938 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
945 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
939 label=label)
946 label=label)
940
947
941 @command('branch',
948 @command('branch',
942 [('f', 'force', None,
949 [('f', 'force', None,
943 _('set branch name even if it shadows an existing branch')),
950 _('set branch name even if it shadows an existing branch')),
944 ('C', 'clean', None, _('reset branch name to parent branch name'))],
951 ('C', 'clean', None, _('reset branch name to parent branch name'))],
945 _('[-fC] [NAME]'))
952 _('[-fC] [NAME]'))
946 def branch(ui, repo, label=None, **opts):
953 def branch(ui, repo, label=None, **opts):
947 """set or show the current branch name
954 """set or show the current branch name
948
955
949 .. note::
956 .. note::
950
957
951 Branch names are permanent and global. Use :hg:`bookmark` to create a
958 Branch names are permanent and global. Use :hg:`bookmark` to create a
952 light-weight bookmark instead. See :hg:`help glossary` for more
959 light-weight bookmark instead. See :hg:`help glossary` for more
953 information about named branches and bookmarks.
960 information about named branches and bookmarks.
954
961
955 With no argument, show the current branch name. With one argument,
962 With no argument, show the current branch name. With one argument,
956 set the working directory branch name (the branch will not exist
963 set the working directory branch name (the branch will not exist
957 in the repository until the next commit). Standard practice
964 in the repository until the next commit). Standard practice
958 recommends that primary development take place on the 'default'
965 recommends that primary development take place on the 'default'
959 branch.
966 branch.
960
967
961 Unless -f/--force is specified, branch will not let you set a
968 Unless -f/--force is specified, branch will not let you set a
962 branch name that already exists, even if it's inactive.
969 branch name that already exists, even if it's inactive.
963
970
964 Use -C/--clean to reset the working directory branch to that of
971 Use -C/--clean to reset the working directory branch to that of
965 the parent of the working directory, negating a previous branch
972 the parent of the working directory, negating a previous branch
966 change.
973 change.
967
974
968 Use the command :hg:`update` to switch to an existing branch. Use
975 Use the command :hg:`update` to switch to an existing branch. Use
969 :hg:`commit --close-branch` to mark this branch as closed.
976 :hg:`commit --close-branch` to mark this branch as closed.
970
977
971 Returns 0 on success.
978 Returns 0 on success.
972 """
979 """
973 if label:
980 if label:
974 label = label.strip()
981 label = label.strip()
975
982
976 if not opts.get('clean') and not label:
983 if not opts.get('clean') and not label:
977 ui.write("%s\n" % repo.dirstate.branch())
984 ui.write("%s\n" % repo.dirstate.branch())
978 return
985 return
979
986
980 wlock = repo.wlock()
987 wlock = repo.wlock()
981 try:
988 try:
982 if opts.get('clean'):
989 if opts.get('clean'):
983 label = repo[None].p1().branch()
990 label = repo[None].p1().branch()
984 repo.dirstate.setbranch(label)
991 repo.dirstate.setbranch(label)
985 ui.status(_('reset working directory to branch %s\n') % label)
992 ui.status(_('reset working directory to branch %s\n') % label)
986 elif label:
993 elif label:
987 if not opts.get('force') and label in repo.branchmap():
994 if not opts.get('force') and label in repo.branchmap():
988 if label not in [p.branch() for p in repo.parents()]:
995 if label not in [p.branch() for p in repo.parents()]:
989 raise util.Abort(_('a branch of the same name already'
996 raise util.Abort(_('a branch of the same name already'
990 ' exists'),
997 ' exists'),
991 # i18n: "it" refers to an existing branch
998 # i18n: "it" refers to an existing branch
992 hint=_("use 'hg update' to switch to it"))
999 hint=_("use 'hg update' to switch to it"))
993 scmutil.checknewlabel(repo, label, 'branch')
1000 scmutil.checknewlabel(repo, label, 'branch')
994 repo.dirstate.setbranch(label)
1001 repo.dirstate.setbranch(label)
995 ui.status(_('marked working directory as branch %s\n') % label)
1002 ui.status(_('marked working directory as branch %s\n') % label)
996 ui.status(_('(branches are permanent and global, '
1003 ui.status(_('(branches are permanent and global, '
997 'did you want a bookmark?)\n'))
1004 'did you want a bookmark?)\n'))
998 finally:
1005 finally:
999 wlock.release()
1006 wlock.release()
1000
1007
1001 @command('branches',
1008 @command('branches',
1002 [('a', 'active', False, _('show only branches that have unmerged heads')),
1009 [('a', 'active', False, _('show only branches that have unmerged heads')),
1003 ('c', 'closed', False, _('show normal and closed branches'))],
1010 ('c', 'closed', False, _('show normal and closed branches'))],
1004 _('[-ac]'))
1011 _('[-ac]'))
1005 def branches(ui, repo, active=False, closed=False):
1012 def branches(ui, repo, active=False, closed=False):
1006 """list repository named branches
1013 """list repository named branches
1007
1014
1008 List the repository's named branches, indicating which ones are
1015 List the repository's named branches, indicating which ones are
1009 inactive. If -c/--closed is specified, also list branches which have
1016 inactive. If -c/--closed is specified, also list branches which have
1010 been marked closed (see :hg:`commit --close-branch`).
1017 been marked closed (see :hg:`commit --close-branch`).
1011
1018
1012 If -a/--active is specified, only show active branches. A branch
1019 If -a/--active is specified, only show active branches. A branch
1013 is considered active if it contains repository heads.
1020 is considered active if it contains repository heads.
1014
1021
1015 Use the command :hg:`update` to switch to an existing branch.
1022 Use the command :hg:`update` to switch to an existing branch.
1016
1023
1017 Returns 0.
1024 Returns 0.
1018 """
1025 """
1019
1026
1020 hexfunc = ui.debugflag and hex or short
1027 hexfunc = ui.debugflag and hex or short
1021
1028
1022 allheads = set(repo.heads())
1029 allheads = set(repo.heads())
1023 branches = []
1030 branches = []
1024 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1031 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1025 isactive = not isclosed and bool(set(heads) & allheads)
1032 isactive = not isclosed and bool(set(heads) & allheads)
1026 branches.append((tag, repo[tip], isactive, not isclosed))
1033 branches.append((tag, repo[tip], isactive, not isclosed))
1027 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1034 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1028 reverse=True)
1035 reverse=True)
1029
1036
1030 for tag, ctx, isactive, isopen in branches:
1037 for tag, ctx, isactive, isopen in branches:
1031 if (not active) or isactive:
1038 if (not active) or isactive:
1032 if isactive:
1039 if isactive:
1033 label = 'branches.active'
1040 label = 'branches.active'
1034 notice = ''
1041 notice = ''
1035 elif not isopen:
1042 elif not isopen:
1036 if not closed:
1043 if not closed:
1037 continue
1044 continue
1038 label = 'branches.closed'
1045 label = 'branches.closed'
1039 notice = _(' (closed)')
1046 notice = _(' (closed)')
1040 else:
1047 else:
1041 label = 'branches.inactive'
1048 label = 'branches.inactive'
1042 notice = _(' (inactive)')
1049 notice = _(' (inactive)')
1043 if tag == repo.dirstate.branch():
1050 if tag == repo.dirstate.branch():
1044 label = 'branches.current'
1051 label = 'branches.current'
1045 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1052 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1046 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1053 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1047 'log.changeset changeset.%s' % ctx.phasestr())
1054 'log.changeset changeset.%s' % ctx.phasestr())
1048 labeledtag = ui.label(tag, label)
1055 labeledtag = ui.label(tag, label)
1049 if ui.quiet:
1056 if ui.quiet:
1050 ui.write("%s\n" % labeledtag)
1057 ui.write("%s\n" % labeledtag)
1051 else:
1058 else:
1052 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1059 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1053
1060
1054 @command('bundle',
1061 @command('bundle',
1055 [('f', 'force', None, _('run even when the destination is unrelated')),
1062 [('f', 'force', None, _('run even when the destination is unrelated')),
1056 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1063 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1057 _('REV')),
1064 _('REV')),
1058 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1065 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1059 _('BRANCH')),
1066 _('BRANCH')),
1060 ('', 'base', [],
1067 ('', 'base', [],
1061 _('a base changeset assumed to be available at the destination'),
1068 _('a base changeset assumed to be available at the destination'),
1062 _('REV')),
1069 _('REV')),
1063 ('a', 'all', None, _('bundle all changesets in the repository')),
1070 ('a', 'all', None, _('bundle all changesets in the repository')),
1064 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1071 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1065 ] + remoteopts,
1072 ] + remoteopts,
1066 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1073 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1067 def bundle(ui, repo, fname, dest=None, **opts):
1074 def bundle(ui, repo, fname, dest=None, **opts):
1068 """create a changegroup file
1075 """create a changegroup file
1069
1076
1070 Generate a compressed changegroup file collecting changesets not
1077 Generate a compressed changegroup file collecting changesets not
1071 known to be in another repository.
1078 known to be in another repository.
1072
1079
1073 If you omit the destination repository, then hg assumes the
1080 If you omit the destination repository, then hg assumes the
1074 destination will have all the nodes you specify with --base
1081 destination will have all the nodes you specify with --base
1075 parameters. To create a bundle containing all changesets, use
1082 parameters. To create a bundle containing all changesets, use
1076 -a/--all (or --base null).
1083 -a/--all (or --base null).
1077
1084
1078 You can change compression method with the -t/--type option.
1085 You can change compression method with the -t/--type option.
1079 The available compression methods are: none, bzip2, and
1086 The available compression methods are: none, bzip2, and
1080 gzip (by default, bundles are compressed using bzip2).
1087 gzip (by default, bundles are compressed using bzip2).
1081
1088
1082 The bundle file can then be transferred using conventional means
1089 The bundle file can then be transferred using conventional means
1083 and applied to another repository with the unbundle or pull
1090 and applied to another repository with the unbundle or pull
1084 command. This is useful when direct push and pull are not
1091 command. This is useful when direct push and pull are not
1085 available or when exporting an entire repository is undesirable.
1092 available or when exporting an entire repository is undesirable.
1086
1093
1087 Applying bundles preserves all changeset contents including
1094 Applying bundles preserves all changeset contents including
1088 permissions, copy/rename information, and revision history.
1095 permissions, copy/rename information, and revision history.
1089
1096
1090 Returns 0 on success, 1 if no changes found.
1097 Returns 0 on success, 1 if no changes found.
1091 """
1098 """
1092 revs = None
1099 revs = None
1093 if 'rev' in opts:
1100 if 'rev' in opts:
1094 revs = scmutil.revrange(repo, opts['rev'])
1101 revs = scmutil.revrange(repo, opts['rev'])
1095
1102
1096 bundletype = opts.get('type', 'bzip2').lower()
1103 bundletype = opts.get('type', 'bzip2').lower()
1097 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1104 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1098 bundletype = btypes.get(bundletype)
1105 bundletype = btypes.get(bundletype)
1099 if bundletype not in changegroup.bundletypes:
1106 if bundletype not in changegroup.bundletypes:
1100 raise util.Abort(_('unknown bundle type specified with --type'))
1107 raise util.Abort(_('unknown bundle type specified with --type'))
1101
1108
1102 if opts.get('all'):
1109 if opts.get('all'):
1103 base = ['null']
1110 base = ['null']
1104 else:
1111 else:
1105 base = scmutil.revrange(repo, opts.get('base'))
1112 base = scmutil.revrange(repo, opts.get('base'))
1106 # TODO: get desired bundlecaps from command line.
1113 # TODO: get desired bundlecaps from command line.
1107 bundlecaps = None
1114 bundlecaps = None
1108 if base:
1115 if base:
1109 if dest:
1116 if dest:
1110 raise util.Abort(_("--base is incompatible with specifying "
1117 raise util.Abort(_("--base is incompatible with specifying "
1111 "a destination"))
1118 "a destination"))
1112 common = [repo.lookup(rev) for rev in base]
1119 common = [repo.lookup(rev) for rev in base]
1113 heads = revs and map(repo.lookup, revs) or revs
1120 heads = revs and map(repo.lookup, revs) or revs
1114 cg = repo.getbundle('bundle', heads=heads, common=common,
1121 cg = repo.getbundle('bundle', heads=heads, common=common,
1115 bundlecaps=bundlecaps)
1122 bundlecaps=bundlecaps)
1116 outgoing = None
1123 outgoing = None
1117 else:
1124 else:
1118 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1125 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1119 dest, branches = hg.parseurl(dest, opts.get('branch'))
1126 dest, branches = hg.parseurl(dest, opts.get('branch'))
1120 other = hg.peer(repo, opts, dest)
1127 other = hg.peer(repo, opts, dest)
1121 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1128 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1122 heads = revs and map(repo.lookup, revs) or revs
1129 heads = revs and map(repo.lookup, revs) or revs
1123 outgoing = discovery.findcommonoutgoing(repo, other,
1130 outgoing = discovery.findcommonoutgoing(repo, other,
1124 onlyheads=heads,
1131 onlyheads=heads,
1125 force=opts.get('force'),
1132 force=opts.get('force'),
1126 portable=True)
1133 portable=True)
1127 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1134 cg = repo.getlocalbundle('bundle', outgoing, bundlecaps)
1128 if not cg:
1135 if not cg:
1129 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1136 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1130 return 1
1137 return 1
1131
1138
1132 changegroup.writebundle(cg, fname, bundletype)
1139 changegroup.writebundle(cg, fname, bundletype)
1133
1140
1134 @command('cat',
1141 @command('cat',
1135 [('o', 'output', '',
1142 [('o', 'output', '',
1136 _('print output to file with formatted name'), _('FORMAT')),
1143 _('print output to file with formatted name'), _('FORMAT')),
1137 ('r', 'rev', '', _('print the given revision'), _('REV')),
1144 ('r', 'rev', '', _('print the given revision'), _('REV')),
1138 ('', 'decode', None, _('apply any matching decode filter')),
1145 ('', 'decode', None, _('apply any matching decode filter')),
1139 ] + walkopts,
1146 ] + walkopts,
1140 _('[OPTION]... FILE...'))
1147 _('[OPTION]... FILE...'))
1141 def cat(ui, repo, file1, *pats, **opts):
1148 def cat(ui, repo, file1, *pats, **opts):
1142 """output the current or given revision of files
1149 """output the current or given revision of files
1143
1150
1144 Print the specified files as they were at the given revision. If
1151 Print the specified files as they were at the given revision. If
1145 no revision is given, the parent of the working directory is used.
1152 no revision is given, the parent of the working directory is used.
1146
1153
1147 Output may be to a file, in which case the name of the file is
1154 Output may be to a file, in which case the name of the file is
1148 given using a format string. The formatting rules are the same as
1155 given using a format string. The formatting rules are the same as
1149 for the export command, with the following additions:
1156 for the export command, with the following additions:
1150
1157
1151 :``%s``: basename of file being printed
1158 :``%s``: basename of file being printed
1152 :``%d``: dirname of file being printed, or '.' if in repository root
1159 :``%d``: dirname of file being printed, or '.' if in repository root
1153 :``%p``: root-relative path name of file being printed
1160 :``%p``: root-relative path name of file being printed
1154
1161
1155 Returns 0 on success.
1162 Returns 0 on success.
1156 """
1163 """
1157 ctx = scmutil.revsingle(repo, opts.get('rev'))
1164 ctx = scmutil.revsingle(repo, opts.get('rev'))
1158 err = 1
1165 err = 1
1159 m = scmutil.match(ctx, (file1,) + pats, opts)
1166 m = scmutil.match(ctx, (file1,) + pats, opts)
1160 for abs in ctx.walk(m):
1167 for abs in ctx.walk(m):
1161 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1168 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1162 pathname=abs)
1169 pathname=abs)
1163 data = ctx[abs].data()
1170 data = ctx[abs].data()
1164 if opts.get('decode'):
1171 if opts.get('decode'):
1165 data = repo.wwritedata(abs, data)
1172 data = repo.wwritedata(abs, data)
1166 fp.write(data)
1173 fp.write(data)
1167 fp.close()
1174 fp.close()
1168 err = 0
1175 err = 0
1169 return err
1176 return err
1170
1177
1171 @command('^clone',
1178 @command('^clone',
1172 [('U', 'noupdate', None,
1179 [('U', 'noupdate', None,
1173 _('the clone will include an empty working copy (only a repository)')),
1180 _('the clone will include an empty working copy (only a repository)')),
1174 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1181 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1175 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1182 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1176 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1183 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1177 ('', 'pull', None, _('use pull protocol to copy metadata')),
1184 ('', 'pull', None, _('use pull protocol to copy metadata')),
1178 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1185 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1179 ] + remoteopts,
1186 ] + remoteopts,
1180 _('[OPTION]... SOURCE [DEST]'))
1187 _('[OPTION]... SOURCE [DEST]'))
1181 def clone(ui, source, dest=None, **opts):
1188 def clone(ui, source, dest=None, **opts):
1182 """make a copy of an existing repository
1189 """make a copy of an existing repository
1183
1190
1184 Create a copy of an existing repository in a new directory.
1191 Create a copy of an existing repository in a new directory.
1185
1192
1186 If no destination directory name is specified, it defaults to the
1193 If no destination directory name is specified, it defaults to the
1187 basename of the source.
1194 basename of the source.
1188
1195
1189 The location of the source is added to the new repository's
1196 The location of the source is added to the new repository's
1190 ``.hg/hgrc`` file, as the default to be used for future pulls.
1197 ``.hg/hgrc`` file, as the default to be used for future pulls.
1191
1198
1192 Only local paths and ``ssh://`` URLs are supported as
1199 Only local paths and ``ssh://`` URLs are supported as
1193 destinations. For ``ssh://`` destinations, no working directory or
1200 destinations. For ``ssh://`` destinations, no working directory or
1194 ``.hg/hgrc`` will be created on the remote side.
1201 ``.hg/hgrc`` will be created on the remote side.
1195
1202
1196 To pull only a subset of changesets, specify one or more revisions
1203 To pull only a subset of changesets, specify one or more revisions
1197 identifiers with -r/--rev or branches with -b/--branch. The
1204 identifiers with -r/--rev or branches with -b/--branch. The
1198 resulting clone will contain only the specified changesets and
1205 resulting clone will contain only the specified changesets and
1199 their ancestors. These options (or 'clone src#rev dest') imply
1206 their ancestors. These options (or 'clone src#rev dest') imply
1200 --pull, even for local source repositories. Note that specifying a
1207 --pull, even for local source repositories. Note that specifying a
1201 tag will include the tagged changeset but not the changeset
1208 tag will include the tagged changeset but not the changeset
1202 containing the tag.
1209 containing the tag.
1203
1210
1204 If the source repository has a bookmark called '@' set, that
1211 If the source repository has a bookmark called '@' set, that
1205 revision will be checked out in the new repository by default.
1212 revision will be checked out in the new repository by default.
1206
1213
1207 To check out a particular version, use -u/--update, or
1214 To check out a particular version, use -u/--update, or
1208 -U/--noupdate to create a clone with no working directory.
1215 -U/--noupdate to create a clone with no working directory.
1209
1216
1210 .. container:: verbose
1217 .. container:: verbose
1211
1218
1212 For efficiency, hardlinks are used for cloning whenever the
1219 For efficiency, hardlinks are used for cloning whenever the
1213 source and destination are on the same filesystem (note this
1220 source and destination are on the same filesystem (note this
1214 applies only to the repository data, not to the working
1221 applies only to the repository data, not to the working
1215 directory). Some filesystems, such as AFS, implement hardlinking
1222 directory). Some filesystems, such as AFS, implement hardlinking
1216 incorrectly, but do not report errors. In these cases, use the
1223 incorrectly, but do not report errors. In these cases, use the
1217 --pull option to avoid hardlinking.
1224 --pull option to avoid hardlinking.
1218
1225
1219 In some cases, you can clone repositories and the working
1226 In some cases, you can clone repositories and the working
1220 directory using full hardlinks with ::
1227 directory using full hardlinks with ::
1221
1228
1222 $ cp -al REPO REPOCLONE
1229 $ cp -al REPO REPOCLONE
1223
1230
1224 This is the fastest way to clone, but it is not always safe. The
1231 This is the fastest way to clone, but it is not always safe. The
1225 operation is not atomic (making sure REPO is not modified during
1232 operation is not atomic (making sure REPO is not modified during
1226 the operation is up to you) and you have to make sure your
1233 the operation is up to you) and you have to make sure your
1227 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1234 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1228 so). Also, this is not compatible with certain extensions that
1235 so). Also, this is not compatible with certain extensions that
1229 place their metadata under the .hg directory, such as mq.
1236 place their metadata under the .hg directory, such as mq.
1230
1237
1231 Mercurial will update the working directory to the first applicable
1238 Mercurial will update the working directory to the first applicable
1232 revision from this list:
1239 revision from this list:
1233
1240
1234 a) null if -U or the source repository has no changesets
1241 a) null if -U or the source repository has no changesets
1235 b) if -u . and the source repository is local, the first parent of
1242 b) if -u . and the source repository is local, the first parent of
1236 the source repository's working directory
1243 the source repository's working directory
1237 c) the changeset specified with -u (if a branch name, this means the
1244 c) the changeset specified with -u (if a branch name, this means the
1238 latest head of that branch)
1245 latest head of that branch)
1239 d) the changeset specified with -r
1246 d) the changeset specified with -r
1240 e) the tipmost head specified with -b
1247 e) the tipmost head specified with -b
1241 f) the tipmost head specified with the url#branch source syntax
1248 f) the tipmost head specified with the url#branch source syntax
1242 g) the revision marked with the '@' bookmark, if present
1249 g) the revision marked with the '@' bookmark, if present
1243 h) the tipmost head of the default branch
1250 h) the tipmost head of the default branch
1244 i) tip
1251 i) tip
1245
1252
1246 Examples:
1253 Examples:
1247
1254
1248 - clone a remote repository to a new directory named hg/::
1255 - clone a remote repository to a new directory named hg/::
1249
1256
1250 hg clone http://selenic.com/hg
1257 hg clone http://selenic.com/hg
1251
1258
1252 - create a lightweight local clone::
1259 - create a lightweight local clone::
1253
1260
1254 hg clone project/ project-feature/
1261 hg clone project/ project-feature/
1255
1262
1256 - clone from an absolute path on an ssh server (note double-slash)::
1263 - clone from an absolute path on an ssh server (note double-slash)::
1257
1264
1258 hg clone ssh://user@server//home/projects/alpha/
1265 hg clone ssh://user@server//home/projects/alpha/
1259
1266
1260 - do a high-speed clone over a LAN while checking out a
1267 - do a high-speed clone over a LAN while checking out a
1261 specified version::
1268 specified version::
1262
1269
1263 hg clone --uncompressed http://server/repo -u 1.5
1270 hg clone --uncompressed http://server/repo -u 1.5
1264
1271
1265 - create a repository without changesets after a particular revision::
1272 - create a repository without changesets after a particular revision::
1266
1273
1267 hg clone -r 04e544 experimental/ good/
1274 hg clone -r 04e544 experimental/ good/
1268
1275
1269 - clone (and track) a particular named branch::
1276 - clone (and track) a particular named branch::
1270
1277
1271 hg clone http://selenic.com/hg#stable
1278 hg clone http://selenic.com/hg#stable
1272
1279
1273 See :hg:`help urls` for details on specifying URLs.
1280 See :hg:`help urls` for details on specifying URLs.
1274
1281
1275 Returns 0 on success.
1282 Returns 0 on success.
1276 """
1283 """
1277 if opts.get('noupdate') and opts.get('updaterev'):
1284 if opts.get('noupdate') and opts.get('updaterev'):
1278 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1285 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1279
1286
1280 r = hg.clone(ui, opts, source, dest,
1287 r = hg.clone(ui, opts, source, dest,
1281 pull=opts.get('pull'),
1288 pull=opts.get('pull'),
1282 stream=opts.get('uncompressed'),
1289 stream=opts.get('uncompressed'),
1283 rev=opts.get('rev'),
1290 rev=opts.get('rev'),
1284 update=opts.get('updaterev') or not opts.get('noupdate'),
1291 update=opts.get('updaterev') or not opts.get('noupdate'),
1285 branch=opts.get('branch'))
1292 branch=opts.get('branch'))
1286
1293
1287 return r is None
1294 return r is None
1288
1295
1289 @command('^commit|ci',
1296 @command('^commit|ci',
1290 [('A', 'addremove', None,
1297 [('A', 'addremove', None,
1291 _('mark new/missing files as added/removed before committing')),
1298 _('mark new/missing files as added/removed before committing')),
1292 ('', 'close-branch', None,
1299 ('', 'close-branch', None,
1293 _('mark a branch as closed, hiding it from the branch list')),
1300 _('mark a branch as closed, hiding it from the branch list')),
1294 ('', 'amend', None, _('amend the parent of the working dir')),
1301 ('', 'amend', None, _('amend the parent of the working dir')),
1295 ('s', 'secret', None, _('use the secret phase for committing')),
1302 ('s', 'secret', None, _('use the secret phase for committing')),
1296 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1303 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1297 _('[OPTION]... [FILE]...'))
1304 _('[OPTION]... [FILE]...'))
1298 def commit(ui, repo, *pats, **opts):
1305 def commit(ui, repo, *pats, **opts):
1299 """commit the specified files or all outstanding changes
1306 """commit the specified files or all outstanding changes
1300
1307
1301 Commit changes to the given files into the repository. Unlike a
1308 Commit changes to the given files into the repository. Unlike a
1302 centralized SCM, this operation is a local operation. See
1309 centralized SCM, this operation is a local operation. See
1303 :hg:`push` for a way to actively distribute your changes.
1310 :hg:`push` for a way to actively distribute your changes.
1304
1311
1305 If a list of files is omitted, all changes reported by :hg:`status`
1312 If a list of files is omitted, all changes reported by :hg:`status`
1306 will be committed.
1313 will be committed.
1307
1314
1308 If you are committing the result of a merge, do not provide any
1315 If you are committing the result of a merge, do not provide any
1309 filenames or -I/-X filters.
1316 filenames or -I/-X filters.
1310
1317
1311 If no commit message is specified, Mercurial starts your
1318 If no commit message is specified, Mercurial starts your
1312 configured editor where you can enter a message. In case your
1319 configured editor where you can enter a message. In case your
1313 commit fails, you will find a backup of your message in
1320 commit fails, you will find a backup of your message in
1314 ``.hg/last-message.txt``.
1321 ``.hg/last-message.txt``.
1315
1322
1316 The --amend flag can be used to amend the parent of the
1323 The --amend flag can be used to amend the parent of the
1317 working directory with a new commit that contains the changes
1324 working directory with a new commit that contains the changes
1318 in the parent in addition to those currently reported by :hg:`status`,
1325 in the parent in addition to those currently reported by :hg:`status`,
1319 if there are any. The old commit is stored in a backup bundle in
1326 if there are any. The old commit is stored in a backup bundle in
1320 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1327 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1321 on how to restore it).
1328 on how to restore it).
1322
1329
1323 Message, user and date are taken from the amended commit unless
1330 Message, user and date are taken from the amended commit unless
1324 specified. When a message isn't specified on the command line,
1331 specified. When a message isn't specified on the command line,
1325 the editor will open with the message of the amended commit.
1332 the editor will open with the message of the amended commit.
1326
1333
1327 It is not possible to amend public changesets (see :hg:`help phases`)
1334 It is not possible to amend public changesets (see :hg:`help phases`)
1328 or changesets that have children.
1335 or changesets that have children.
1329
1336
1330 See :hg:`help dates` for a list of formats valid for -d/--date.
1337 See :hg:`help dates` for a list of formats valid for -d/--date.
1331
1338
1332 Returns 0 on success, 1 if nothing changed.
1339 Returns 0 on success, 1 if nothing changed.
1333 """
1340 """
1334 if opts.get('subrepos'):
1341 if opts.get('subrepos'):
1335 if opts.get('amend'):
1342 if opts.get('amend'):
1336 raise util.Abort(_('cannot amend with --subrepos'))
1343 raise util.Abort(_('cannot amend with --subrepos'))
1337 # Let --subrepos on the command line override config setting.
1344 # Let --subrepos on the command line override config setting.
1338 ui.setconfig('ui', 'commitsubrepos', True)
1345 ui.setconfig('ui', 'commitsubrepos', True)
1339
1346
1340 # Save this for restoring it later
1347 # Save this for restoring it later
1341 oldcommitphase = ui.config('phases', 'new-commit')
1348 oldcommitphase = ui.config('phases', 'new-commit')
1342
1349
1343 cmdutil.checkunfinished(repo, commit=True)
1350 cmdutil.checkunfinished(repo, commit=True)
1344
1351
1345 branch = repo[None].branch()
1352 branch = repo[None].branch()
1346 bheads = repo.branchheads(branch)
1353 bheads = repo.branchheads(branch)
1347
1354
1348 extra = {}
1355 extra = {}
1349 if opts.get('close_branch'):
1356 if opts.get('close_branch'):
1350 extra['close'] = 1
1357 extra['close'] = 1
1351
1358
1352 if not bheads:
1359 if not bheads:
1353 raise util.Abort(_('can only close branch heads'))
1360 raise util.Abort(_('can only close branch heads'))
1354 elif opts.get('amend'):
1361 elif opts.get('amend'):
1355 if repo.parents()[0].p1().branch() != branch and \
1362 if repo.parents()[0].p1().branch() != branch and \
1356 repo.parents()[0].p2().branch() != branch:
1363 repo.parents()[0].p2().branch() != branch:
1357 raise util.Abort(_('can only close branch heads'))
1364 raise util.Abort(_('can only close branch heads'))
1358
1365
1359 if opts.get('amend'):
1366 if opts.get('amend'):
1360 if ui.configbool('ui', 'commitsubrepos'):
1367 if ui.configbool('ui', 'commitsubrepos'):
1361 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1368 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1362
1369
1363 old = repo['.']
1370 old = repo['.']
1364 if old.phase() == phases.public:
1371 if old.phase() == phases.public:
1365 raise util.Abort(_('cannot amend public changesets'))
1372 raise util.Abort(_('cannot amend public changesets'))
1366 if len(repo[None].parents()) > 1:
1373 if len(repo[None].parents()) > 1:
1367 raise util.Abort(_('cannot amend while merging'))
1374 raise util.Abort(_('cannot amend while merging'))
1368 if (not obsolete._enabled) and old.children():
1375 if (not obsolete._enabled) and old.children():
1369 raise util.Abort(_('cannot amend changeset with children'))
1376 raise util.Abort(_('cannot amend changeset with children'))
1370
1377
1371 e = cmdutil.commiteditor
1378 e = cmdutil.commiteditor
1372 if opts.get('force_editor'):
1379 if opts.get('force_editor'):
1373 e = cmdutil.commitforceeditor
1380 e = cmdutil.commitforceeditor
1374
1381
1375 def commitfunc(ui, repo, message, match, opts):
1382 def commitfunc(ui, repo, message, match, opts):
1376 editor = e
1383 editor = e
1377 # message contains text from -m or -l, if it's empty,
1384 # message contains text from -m or -l, if it's empty,
1378 # open the editor with the old message
1385 # open the editor with the old message
1379 if not message:
1386 if not message:
1380 message = old.description()
1387 message = old.description()
1381 editor = cmdutil.commitforceeditor
1388 editor = cmdutil.commitforceeditor
1382 try:
1389 try:
1383 if opts.get('secret'):
1390 if opts.get('secret'):
1384 ui.setconfig('phases', 'new-commit', 'secret')
1391 ui.setconfig('phases', 'new-commit', 'secret')
1385
1392
1386 return repo.commit(message,
1393 return repo.commit(message,
1387 opts.get('user') or old.user(),
1394 opts.get('user') or old.user(),
1388 opts.get('date') or old.date(),
1395 opts.get('date') or old.date(),
1389 match,
1396 match,
1390 editor=editor,
1397 editor=editor,
1391 extra=extra)
1398 extra=extra)
1392 finally:
1399 finally:
1393 ui.setconfig('phases', 'new-commit', oldcommitphase)
1400 ui.setconfig('phases', 'new-commit', oldcommitphase)
1394
1401
1395 current = repo._bookmarkcurrent
1402 current = repo._bookmarkcurrent
1396 marks = old.bookmarks()
1403 marks = old.bookmarks()
1397 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1404 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1398 if node == old.node():
1405 if node == old.node():
1399 ui.status(_("nothing changed\n"))
1406 ui.status(_("nothing changed\n"))
1400 return 1
1407 return 1
1401 elif marks:
1408 elif marks:
1402 ui.debug('moving bookmarks %r from %s to %s\n' %
1409 ui.debug('moving bookmarks %r from %s to %s\n' %
1403 (marks, old.hex(), hex(node)))
1410 (marks, old.hex(), hex(node)))
1404 newmarks = repo._bookmarks
1411 newmarks = repo._bookmarks
1405 for bm in marks:
1412 for bm in marks:
1406 newmarks[bm] = node
1413 newmarks[bm] = node
1407 if bm == current:
1414 if bm == current:
1408 bookmarks.setcurrent(repo, bm)
1415 bookmarks.setcurrent(repo, bm)
1409 newmarks.write()
1416 newmarks.write()
1410 else:
1417 else:
1411 e = cmdutil.commiteditor
1418 e = cmdutil.commiteditor
1412 if opts.get('force_editor'):
1419 if opts.get('force_editor'):
1413 e = cmdutil.commitforceeditor
1420 e = cmdutil.commitforceeditor
1414
1421
1415 def commitfunc(ui, repo, message, match, opts):
1422 def commitfunc(ui, repo, message, match, opts):
1416 try:
1423 try:
1417 if opts.get('secret'):
1424 if opts.get('secret'):
1418 ui.setconfig('phases', 'new-commit', 'secret')
1425 ui.setconfig('phases', 'new-commit', 'secret')
1419
1426
1420 return repo.commit(message, opts.get('user'), opts.get('date'),
1427 return repo.commit(message, opts.get('user'), opts.get('date'),
1421 match, editor=e, extra=extra)
1428 match, editor=e, extra=extra)
1422 finally:
1429 finally:
1423 ui.setconfig('phases', 'new-commit', oldcommitphase)
1430 ui.setconfig('phases', 'new-commit', oldcommitphase)
1424
1431
1425
1432
1426 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1433 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1427
1434
1428 if not node:
1435 if not node:
1429 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1436 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1430 if stat[3]:
1437 if stat[3]:
1431 ui.status(_("nothing changed (%d missing files, see "
1438 ui.status(_("nothing changed (%d missing files, see "
1432 "'hg status')\n") % len(stat[3]))
1439 "'hg status')\n") % len(stat[3]))
1433 else:
1440 else:
1434 ui.status(_("nothing changed\n"))
1441 ui.status(_("nothing changed\n"))
1435 return 1
1442 return 1
1436
1443
1437 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1444 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1438
1445
1439 @command('copy|cp',
1446 @command('copy|cp',
1440 [('A', 'after', None, _('record a copy that has already occurred')),
1447 [('A', 'after', None, _('record a copy that has already occurred')),
1441 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1448 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1442 ] + walkopts + dryrunopts,
1449 ] + walkopts + dryrunopts,
1443 _('[OPTION]... [SOURCE]... DEST'))
1450 _('[OPTION]... [SOURCE]... DEST'))
1444 def copy(ui, repo, *pats, **opts):
1451 def copy(ui, repo, *pats, **opts):
1445 """mark files as copied for the next commit
1452 """mark files as copied for the next commit
1446
1453
1447 Mark dest as having copies of source files. If dest is a
1454 Mark dest as having copies of source files. If dest is a
1448 directory, copies are put in that directory. If dest is a file,
1455 directory, copies are put in that directory. If dest is a file,
1449 the source must be a single file.
1456 the source must be a single file.
1450
1457
1451 By default, this command copies the contents of files as they
1458 By default, this command copies the contents of files as they
1452 exist in the working directory. If invoked with -A/--after, the
1459 exist in the working directory. If invoked with -A/--after, the
1453 operation is recorded, but no copying is performed.
1460 operation is recorded, but no copying is performed.
1454
1461
1455 This command takes effect with the next commit. To undo a copy
1462 This command takes effect with the next commit. To undo a copy
1456 before that, see :hg:`revert`.
1463 before that, see :hg:`revert`.
1457
1464
1458 Returns 0 on success, 1 if errors are encountered.
1465 Returns 0 on success, 1 if errors are encountered.
1459 """
1466 """
1460 wlock = repo.wlock(False)
1467 wlock = repo.wlock(False)
1461 try:
1468 try:
1462 return cmdutil.copy(ui, repo, pats, opts)
1469 return cmdutil.copy(ui, repo, pats, opts)
1463 finally:
1470 finally:
1464 wlock.release()
1471 wlock.release()
1465
1472
1466 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1473 @command('debugancestor', [], _('[INDEX] REV1 REV2'))
1467 def debugancestor(ui, repo, *args):
1474 def debugancestor(ui, repo, *args):
1468 """find the ancestor revision of two revisions in a given index"""
1475 """find the ancestor revision of two revisions in a given index"""
1469 if len(args) == 3:
1476 if len(args) == 3:
1470 index, rev1, rev2 = args
1477 index, rev1, rev2 = args
1471 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1478 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1472 lookup = r.lookup
1479 lookup = r.lookup
1473 elif len(args) == 2:
1480 elif len(args) == 2:
1474 if not repo:
1481 if not repo:
1475 raise util.Abort(_("there is no Mercurial repository here "
1482 raise util.Abort(_("there is no Mercurial repository here "
1476 "(.hg not found)"))
1483 "(.hg not found)"))
1477 rev1, rev2 = args
1484 rev1, rev2 = args
1478 r = repo.changelog
1485 r = repo.changelog
1479 lookup = repo.lookup
1486 lookup = repo.lookup
1480 else:
1487 else:
1481 raise util.Abort(_('either two or three arguments required'))
1488 raise util.Abort(_('either two or three arguments required'))
1482 a = r.ancestor(lookup(rev1), lookup(rev2))
1489 a = r.ancestor(lookup(rev1), lookup(rev2))
1483 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1490 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1484
1491
1485 @command('debugbuilddag',
1492 @command('debugbuilddag',
1486 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1493 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1487 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1494 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1488 ('n', 'new-file', None, _('add new file at each rev'))],
1495 ('n', 'new-file', None, _('add new file at each rev'))],
1489 _('[OPTION]... [TEXT]'))
1496 _('[OPTION]... [TEXT]'))
1490 def debugbuilddag(ui, repo, text=None,
1497 def debugbuilddag(ui, repo, text=None,
1491 mergeable_file=False,
1498 mergeable_file=False,
1492 overwritten_file=False,
1499 overwritten_file=False,
1493 new_file=False):
1500 new_file=False):
1494 """builds a repo with a given DAG from scratch in the current empty repo
1501 """builds a repo with a given DAG from scratch in the current empty repo
1495
1502
1496 The description of the DAG is read from stdin if not given on the
1503 The description of the DAG is read from stdin if not given on the
1497 command line.
1504 command line.
1498
1505
1499 Elements:
1506 Elements:
1500
1507
1501 - "+n" is a linear run of n nodes based on the current default parent
1508 - "+n" is a linear run of n nodes based on the current default parent
1502 - "." is a single node based on the current default parent
1509 - "." is a single node based on the current default parent
1503 - "$" resets the default parent to null (implied at the start);
1510 - "$" resets the default parent to null (implied at the start);
1504 otherwise the default parent is always the last node created
1511 otherwise the default parent is always the last node created
1505 - "<p" sets the default parent to the backref p
1512 - "<p" sets the default parent to the backref p
1506 - "*p" is a fork at parent p, which is a backref
1513 - "*p" is a fork at parent p, which is a backref
1507 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1514 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1508 - "/p2" is a merge of the preceding node and p2
1515 - "/p2" is a merge of the preceding node and p2
1509 - ":tag" defines a local tag for the preceding node
1516 - ":tag" defines a local tag for the preceding node
1510 - "@branch" sets the named branch for subsequent nodes
1517 - "@branch" sets the named branch for subsequent nodes
1511 - "#...\\n" is a comment up to the end of the line
1518 - "#...\\n" is a comment up to the end of the line
1512
1519
1513 Whitespace between the above elements is ignored.
1520 Whitespace between the above elements is ignored.
1514
1521
1515 A backref is either
1522 A backref is either
1516
1523
1517 - a number n, which references the node curr-n, where curr is the current
1524 - a number n, which references the node curr-n, where curr is the current
1518 node, or
1525 node, or
1519 - the name of a local tag you placed earlier using ":tag", or
1526 - the name of a local tag you placed earlier using ":tag", or
1520 - empty to denote the default parent.
1527 - empty to denote the default parent.
1521
1528
1522 All string valued-elements are either strictly alphanumeric, or must
1529 All string valued-elements are either strictly alphanumeric, or must
1523 be enclosed in double quotes ("..."), with "\\" as escape character.
1530 be enclosed in double quotes ("..."), with "\\" as escape character.
1524 """
1531 """
1525
1532
1526 if text is None:
1533 if text is None:
1527 ui.status(_("reading DAG from stdin\n"))
1534 ui.status(_("reading DAG from stdin\n"))
1528 text = ui.fin.read()
1535 text = ui.fin.read()
1529
1536
1530 cl = repo.changelog
1537 cl = repo.changelog
1531 if len(cl) > 0:
1538 if len(cl) > 0:
1532 raise util.Abort(_('repository is not empty'))
1539 raise util.Abort(_('repository is not empty'))
1533
1540
1534 # determine number of revs in DAG
1541 # determine number of revs in DAG
1535 total = 0
1542 total = 0
1536 for type, data in dagparser.parsedag(text):
1543 for type, data in dagparser.parsedag(text):
1537 if type == 'n':
1544 if type == 'n':
1538 total += 1
1545 total += 1
1539
1546
1540 if mergeable_file:
1547 if mergeable_file:
1541 linesperrev = 2
1548 linesperrev = 2
1542 # make a file with k lines per rev
1549 # make a file with k lines per rev
1543 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1550 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1544 initialmergedlines.append("")
1551 initialmergedlines.append("")
1545
1552
1546 tags = []
1553 tags = []
1547
1554
1548 lock = tr = None
1555 lock = tr = None
1549 try:
1556 try:
1550 lock = repo.lock()
1557 lock = repo.lock()
1551 tr = repo.transaction("builddag")
1558 tr = repo.transaction("builddag")
1552
1559
1553 at = -1
1560 at = -1
1554 atbranch = 'default'
1561 atbranch = 'default'
1555 nodeids = []
1562 nodeids = []
1556 id = 0
1563 id = 0
1557 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1564 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1558 for type, data in dagparser.parsedag(text):
1565 for type, data in dagparser.parsedag(text):
1559 if type == 'n':
1566 if type == 'n':
1560 ui.note(('node %s\n' % str(data)))
1567 ui.note(('node %s\n' % str(data)))
1561 id, ps = data
1568 id, ps = data
1562
1569
1563 files = []
1570 files = []
1564 fctxs = {}
1571 fctxs = {}
1565
1572
1566 p2 = None
1573 p2 = None
1567 if mergeable_file:
1574 if mergeable_file:
1568 fn = "mf"
1575 fn = "mf"
1569 p1 = repo[ps[0]]
1576 p1 = repo[ps[0]]
1570 if len(ps) > 1:
1577 if len(ps) > 1:
1571 p2 = repo[ps[1]]
1578 p2 = repo[ps[1]]
1572 pa = p1.ancestor(p2)
1579 pa = p1.ancestor(p2)
1573 base, local, other = [x[fn].data() for x in (pa, p1,
1580 base, local, other = [x[fn].data() for x in (pa, p1,
1574 p2)]
1581 p2)]
1575 m3 = simplemerge.Merge3Text(base, local, other)
1582 m3 = simplemerge.Merge3Text(base, local, other)
1576 ml = [l.strip() for l in m3.merge_lines()]
1583 ml = [l.strip() for l in m3.merge_lines()]
1577 ml.append("")
1584 ml.append("")
1578 elif at > 0:
1585 elif at > 0:
1579 ml = p1[fn].data().split("\n")
1586 ml = p1[fn].data().split("\n")
1580 else:
1587 else:
1581 ml = initialmergedlines
1588 ml = initialmergedlines
1582 ml[id * linesperrev] += " r%i" % id
1589 ml[id * linesperrev] += " r%i" % id
1583 mergedtext = "\n".join(ml)
1590 mergedtext = "\n".join(ml)
1584 files.append(fn)
1591 files.append(fn)
1585 fctxs[fn] = context.memfilectx(fn, mergedtext)
1592 fctxs[fn] = context.memfilectx(fn, mergedtext)
1586
1593
1587 if overwritten_file:
1594 if overwritten_file:
1588 fn = "of"
1595 fn = "of"
1589 files.append(fn)
1596 files.append(fn)
1590 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1597 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1591
1598
1592 if new_file:
1599 if new_file:
1593 fn = "nf%i" % id
1600 fn = "nf%i" % id
1594 files.append(fn)
1601 files.append(fn)
1595 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1602 fctxs[fn] = context.memfilectx(fn, "r%i\n" % id)
1596 if len(ps) > 1:
1603 if len(ps) > 1:
1597 if not p2:
1604 if not p2:
1598 p2 = repo[ps[1]]
1605 p2 = repo[ps[1]]
1599 for fn in p2:
1606 for fn in p2:
1600 if fn.startswith("nf"):
1607 if fn.startswith("nf"):
1601 files.append(fn)
1608 files.append(fn)
1602 fctxs[fn] = p2[fn]
1609 fctxs[fn] = p2[fn]
1603
1610
1604 def fctxfn(repo, cx, path):
1611 def fctxfn(repo, cx, path):
1605 return fctxs.get(path)
1612 return fctxs.get(path)
1606
1613
1607 if len(ps) == 0 or ps[0] < 0:
1614 if len(ps) == 0 or ps[0] < 0:
1608 pars = [None, None]
1615 pars = [None, None]
1609 elif len(ps) == 1:
1616 elif len(ps) == 1:
1610 pars = [nodeids[ps[0]], None]
1617 pars = [nodeids[ps[0]], None]
1611 else:
1618 else:
1612 pars = [nodeids[p] for p in ps]
1619 pars = [nodeids[p] for p in ps]
1613 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1620 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1614 date=(id, 0),
1621 date=(id, 0),
1615 user="debugbuilddag",
1622 user="debugbuilddag",
1616 extra={'branch': atbranch})
1623 extra={'branch': atbranch})
1617 nodeid = repo.commitctx(cx)
1624 nodeid = repo.commitctx(cx)
1618 nodeids.append(nodeid)
1625 nodeids.append(nodeid)
1619 at = id
1626 at = id
1620 elif type == 'l':
1627 elif type == 'l':
1621 id, name = data
1628 id, name = data
1622 ui.note(('tag %s\n' % name))
1629 ui.note(('tag %s\n' % name))
1623 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1630 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1624 elif type == 'a':
1631 elif type == 'a':
1625 ui.note(('branch %s\n' % data))
1632 ui.note(('branch %s\n' % data))
1626 atbranch = data
1633 atbranch = data
1627 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1634 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1628 tr.close()
1635 tr.close()
1629
1636
1630 if tags:
1637 if tags:
1631 repo.opener.write("localtags", "".join(tags))
1638 repo.opener.write("localtags", "".join(tags))
1632 finally:
1639 finally:
1633 ui.progress(_('building'), None)
1640 ui.progress(_('building'), None)
1634 release(tr, lock)
1641 release(tr, lock)
1635
1642
1636 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1643 @command('debugbundle', [('a', 'all', None, _('show all details'))], _('FILE'))
1637 def debugbundle(ui, bundlepath, all=None, **opts):
1644 def debugbundle(ui, bundlepath, all=None, **opts):
1638 """lists the contents of a bundle"""
1645 """lists the contents of a bundle"""
1639 f = hg.openpath(ui, bundlepath)
1646 f = hg.openpath(ui, bundlepath)
1640 try:
1647 try:
1641 gen = changegroup.readbundle(f, bundlepath)
1648 gen = changegroup.readbundle(f, bundlepath)
1642 if all:
1649 if all:
1643 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1650 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1644
1651
1645 def showchunks(named):
1652 def showchunks(named):
1646 ui.write("\n%s\n" % named)
1653 ui.write("\n%s\n" % named)
1647 chain = None
1654 chain = None
1648 while True:
1655 while True:
1649 chunkdata = gen.deltachunk(chain)
1656 chunkdata = gen.deltachunk(chain)
1650 if not chunkdata:
1657 if not chunkdata:
1651 break
1658 break
1652 node = chunkdata['node']
1659 node = chunkdata['node']
1653 p1 = chunkdata['p1']
1660 p1 = chunkdata['p1']
1654 p2 = chunkdata['p2']
1661 p2 = chunkdata['p2']
1655 cs = chunkdata['cs']
1662 cs = chunkdata['cs']
1656 deltabase = chunkdata['deltabase']
1663 deltabase = chunkdata['deltabase']
1657 delta = chunkdata['delta']
1664 delta = chunkdata['delta']
1658 ui.write("%s %s %s %s %s %s\n" %
1665 ui.write("%s %s %s %s %s %s\n" %
1659 (hex(node), hex(p1), hex(p2),
1666 (hex(node), hex(p1), hex(p2),
1660 hex(cs), hex(deltabase), len(delta)))
1667 hex(cs), hex(deltabase), len(delta)))
1661 chain = node
1668 chain = node
1662
1669
1663 chunkdata = gen.changelogheader()
1670 chunkdata = gen.changelogheader()
1664 showchunks("changelog")
1671 showchunks("changelog")
1665 chunkdata = gen.manifestheader()
1672 chunkdata = gen.manifestheader()
1666 showchunks("manifest")
1673 showchunks("manifest")
1667 while True:
1674 while True:
1668 chunkdata = gen.filelogheader()
1675 chunkdata = gen.filelogheader()
1669 if not chunkdata:
1676 if not chunkdata:
1670 break
1677 break
1671 fname = chunkdata['filename']
1678 fname = chunkdata['filename']
1672 showchunks(fname)
1679 showchunks(fname)
1673 else:
1680 else:
1674 chunkdata = gen.changelogheader()
1681 chunkdata = gen.changelogheader()
1675 chain = None
1682 chain = None
1676 while True:
1683 while True:
1677 chunkdata = gen.deltachunk(chain)
1684 chunkdata = gen.deltachunk(chain)
1678 if not chunkdata:
1685 if not chunkdata:
1679 break
1686 break
1680 node = chunkdata['node']
1687 node = chunkdata['node']
1681 ui.write("%s\n" % hex(node))
1688 ui.write("%s\n" % hex(node))
1682 chain = node
1689 chain = node
1683 finally:
1690 finally:
1684 f.close()
1691 f.close()
1685
1692
1686 @command('debugcheckstate', [], '')
1693 @command('debugcheckstate', [], '')
1687 def debugcheckstate(ui, repo):
1694 def debugcheckstate(ui, repo):
1688 """validate the correctness of the current dirstate"""
1695 """validate the correctness of the current dirstate"""
1689 parent1, parent2 = repo.dirstate.parents()
1696 parent1, parent2 = repo.dirstate.parents()
1690 m1 = repo[parent1].manifest()
1697 m1 = repo[parent1].manifest()
1691 m2 = repo[parent2].manifest()
1698 m2 = repo[parent2].manifest()
1692 errors = 0
1699 errors = 0
1693 for f in repo.dirstate:
1700 for f in repo.dirstate:
1694 state = repo.dirstate[f]
1701 state = repo.dirstate[f]
1695 if state in "nr" and f not in m1:
1702 if state in "nr" and f not in m1:
1696 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1703 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1697 errors += 1
1704 errors += 1
1698 if state in "a" and f in m1:
1705 if state in "a" and f in m1:
1699 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1706 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1700 errors += 1
1707 errors += 1
1701 if state in "m" and f not in m1 and f not in m2:
1708 if state in "m" and f not in m1 and f not in m2:
1702 ui.warn(_("%s in state %s, but not in either manifest\n") %
1709 ui.warn(_("%s in state %s, but not in either manifest\n") %
1703 (f, state))
1710 (f, state))
1704 errors += 1
1711 errors += 1
1705 for f in m1:
1712 for f in m1:
1706 state = repo.dirstate[f]
1713 state = repo.dirstate[f]
1707 if state not in "nrm":
1714 if state not in "nrm":
1708 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1715 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1709 errors += 1
1716 errors += 1
1710 if errors:
1717 if errors:
1711 error = _(".hg/dirstate inconsistent with current parent's manifest")
1718 error = _(".hg/dirstate inconsistent with current parent's manifest")
1712 raise util.Abort(error)
1719 raise util.Abort(error)
1713
1720
1714 @command('debugcommands', [], _('[COMMAND]'))
1721 @command('debugcommands', [], _('[COMMAND]'))
1715 def debugcommands(ui, cmd='', *args):
1722 def debugcommands(ui, cmd='', *args):
1716 """list all available commands and options"""
1723 """list all available commands and options"""
1717 for cmd, vals in sorted(table.iteritems()):
1724 for cmd, vals in sorted(table.iteritems()):
1718 cmd = cmd.split('|')[0].strip('^')
1725 cmd = cmd.split('|')[0].strip('^')
1719 opts = ', '.join([i[1] for i in vals[1]])
1726 opts = ', '.join([i[1] for i in vals[1]])
1720 ui.write('%s: %s\n' % (cmd, opts))
1727 ui.write('%s: %s\n' % (cmd, opts))
1721
1728
1722 @command('debugcomplete',
1729 @command('debugcomplete',
1723 [('o', 'options', None, _('show the command options'))],
1730 [('o', 'options', None, _('show the command options'))],
1724 _('[-o] CMD'))
1731 _('[-o] CMD'))
1725 def debugcomplete(ui, cmd='', **opts):
1732 def debugcomplete(ui, cmd='', **opts):
1726 """returns the completion list associated with the given command"""
1733 """returns the completion list associated with the given command"""
1727
1734
1728 if opts.get('options'):
1735 if opts.get('options'):
1729 options = []
1736 options = []
1730 otables = [globalopts]
1737 otables = [globalopts]
1731 if cmd:
1738 if cmd:
1732 aliases, entry = cmdutil.findcmd(cmd, table, False)
1739 aliases, entry = cmdutil.findcmd(cmd, table, False)
1733 otables.append(entry[1])
1740 otables.append(entry[1])
1734 for t in otables:
1741 for t in otables:
1735 for o in t:
1742 for o in t:
1736 if "(DEPRECATED)" in o[3]:
1743 if "(DEPRECATED)" in o[3]:
1737 continue
1744 continue
1738 if o[0]:
1745 if o[0]:
1739 options.append('-%s' % o[0])
1746 options.append('-%s' % o[0])
1740 options.append('--%s' % o[1])
1747 options.append('--%s' % o[1])
1741 ui.write("%s\n" % "\n".join(options))
1748 ui.write("%s\n" % "\n".join(options))
1742 return
1749 return
1743
1750
1744 cmdlist = cmdutil.findpossible(cmd, table)
1751 cmdlist = cmdutil.findpossible(cmd, table)
1745 if ui.verbose:
1752 if ui.verbose:
1746 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1753 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1747 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1754 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1748
1755
1749 @command('debugdag',
1756 @command('debugdag',
1750 [('t', 'tags', None, _('use tags as labels')),
1757 [('t', 'tags', None, _('use tags as labels')),
1751 ('b', 'branches', None, _('annotate with branch names')),
1758 ('b', 'branches', None, _('annotate with branch names')),
1752 ('', 'dots', None, _('use dots for runs')),
1759 ('', 'dots', None, _('use dots for runs')),
1753 ('s', 'spaces', None, _('separate elements by spaces'))],
1760 ('s', 'spaces', None, _('separate elements by spaces'))],
1754 _('[OPTION]... [FILE [REV]...]'))
1761 _('[OPTION]... [FILE [REV]...]'))
1755 def debugdag(ui, repo, file_=None, *revs, **opts):
1762 def debugdag(ui, repo, file_=None, *revs, **opts):
1756 """format the changelog or an index DAG as a concise textual description
1763 """format the changelog or an index DAG as a concise textual description
1757
1764
1758 If you pass a revlog index, the revlog's DAG is emitted. If you list
1765 If you pass a revlog index, the revlog's DAG is emitted. If you list
1759 revision numbers, they get labeled in the output as rN.
1766 revision numbers, they get labeled in the output as rN.
1760
1767
1761 Otherwise, the changelog DAG of the current repo is emitted.
1768 Otherwise, the changelog DAG of the current repo is emitted.
1762 """
1769 """
1763 spaces = opts.get('spaces')
1770 spaces = opts.get('spaces')
1764 dots = opts.get('dots')
1771 dots = opts.get('dots')
1765 if file_:
1772 if file_:
1766 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1773 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1767 revs = set((int(r) for r in revs))
1774 revs = set((int(r) for r in revs))
1768 def events():
1775 def events():
1769 for r in rlog:
1776 for r in rlog:
1770 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1777 yield 'n', (r, list(set(p for p in rlog.parentrevs(r)
1771 if p != -1)))
1778 if p != -1)))
1772 if r in revs:
1779 if r in revs:
1773 yield 'l', (r, "r%i" % r)
1780 yield 'l', (r, "r%i" % r)
1774 elif repo:
1781 elif repo:
1775 cl = repo.changelog
1782 cl = repo.changelog
1776 tags = opts.get('tags')
1783 tags = opts.get('tags')
1777 branches = opts.get('branches')
1784 branches = opts.get('branches')
1778 if tags:
1785 if tags:
1779 labels = {}
1786 labels = {}
1780 for l, n in repo.tags().items():
1787 for l, n in repo.tags().items():
1781 labels.setdefault(cl.rev(n), []).append(l)
1788 labels.setdefault(cl.rev(n), []).append(l)
1782 def events():
1789 def events():
1783 b = "default"
1790 b = "default"
1784 for r in cl:
1791 for r in cl:
1785 if branches:
1792 if branches:
1786 newb = cl.read(cl.node(r))[5]['branch']
1793 newb = cl.read(cl.node(r))[5]['branch']
1787 if newb != b:
1794 if newb != b:
1788 yield 'a', newb
1795 yield 'a', newb
1789 b = newb
1796 b = newb
1790 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1797 yield 'n', (r, list(set(p for p in cl.parentrevs(r)
1791 if p != -1)))
1798 if p != -1)))
1792 if tags:
1799 if tags:
1793 ls = labels.get(r)
1800 ls = labels.get(r)
1794 if ls:
1801 if ls:
1795 for l in ls:
1802 for l in ls:
1796 yield 'l', (r, l)
1803 yield 'l', (r, l)
1797 else:
1804 else:
1798 raise util.Abort(_('need repo for changelog dag'))
1805 raise util.Abort(_('need repo for changelog dag'))
1799
1806
1800 for line in dagparser.dagtextlines(events(),
1807 for line in dagparser.dagtextlines(events(),
1801 addspaces=spaces,
1808 addspaces=spaces,
1802 wraplabels=True,
1809 wraplabels=True,
1803 wrapannotations=True,
1810 wrapannotations=True,
1804 wrapnonlinear=dots,
1811 wrapnonlinear=dots,
1805 usedots=dots,
1812 usedots=dots,
1806 maxlinewidth=70):
1813 maxlinewidth=70):
1807 ui.write(line)
1814 ui.write(line)
1808 ui.write("\n")
1815 ui.write("\n")
1809
1816
1810 @command('debugdata',
1817 @command('debugdata',
1811 [('c', 'changelog', False, _('open changelog')),
1818 [('c', 'changelog', False, _('open changelog')),
1812 ('m', 'manifest', False, _('open manifest'))],
1819 ('m', 'manifest', False, _('open manifest'))],
1813 _('-c|-m|FILE REV'))
1820 _('-c|-m|FILE REV'))
1814 def debugdata(ui, repo, file_, rev=None, **opts):
1821 def debugdata(ui, repo, file_, rev=None, **opts):
1815 """dump the contents of a data file revision"""
1822 """dump the contents of a data file revision"""
1816 if opts.get('changelog') or opts.get('manifest'):
1823 if opts.get('changelog') or opts.get('manifest'):
1817 file_, rev = None, file_
1824 file_, rev = None, file_
1818 elif rev is None:
1825 elif rev is None:
1819 raise error.CommandError('debugdata', _('invalid arguments'))
1826 raise error.CommandError('debugdata', _('invalid arguments'))
1820 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1827 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1821 try:
1828 try:
1822 ui.write(r.revision(r.lookup(rev)))
1829 ui.write(r.revision(r.lookup(rev)))
1823 except KeyError:
1830 except KeyError:
1824 raise util.Abort(_('invalid revision identifier %s') % rev)
1831 raise util.Abort(_('invalid revision identifier %s') % rev)
1825
1832
1826 @command('debugdate',
1833 @command('debugdate',
1827 [('e', 'extended', None, _('try extended date formats'))],
1834 [('e', 'extended', None, _('try extended date formats'))],
1828 _('[-e] DATE [RANGE]'))
1835 _('[-e] DATE [RANGE]'))
1829 def debugdate(ui, date, range=None, **opts):
1836 def debugdate(ui, date, range=None, **opts):
1830 """parse and display a date"""
1837 """parse and display a date"""
1831 if opts["extended"]:
1838 if opts["extended"]:
1832 d = util.parsedate(date, util.extendeddateformats)
1839 d = util.parsedate(date, util.extendeddateformats)
1833 else:
1840 else:
1834 d = util.parsedate(date)
1841 d = util.parsedate(date)
1835 ui.write(("internal: %s %s\n") % d)
1842 ui.write(("internal: %s %s\n") % d)
1836 ui.write(("standard: %s\n") % util.datestr(d))
1843 ui.write(("standard: %s\n") % util.datestr(d))
1837 if range:
1844 if range:
1838 m = util.matchdate(range)
1845 m = util.matchdate(range)
1839 ui.write(("match: %s\n") % m(d[0]))
1846 ui.write(("match: %s\n") % m(d[0]))
1840
1847
1841 @command('debugdiscovery',
1848 @command('debugdiscovery',
1842 [('', 'old', None, _('use old-style discovery')),
1849 [('', 'old', None, _('use old-style discovery')),
1843 ('', 'nonheads', None,
1850 ('', 'nonheads', None,
1844 _('use old-style discovery with non-heads included')),
1851 _('use old-style discovery with non-heads included')),
1845 ] + remoteopts,
1852 ] + remoteopts,
1846 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1853 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
1847 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1854 def debugdiscovery(ui, repo, remoteurl="default", **opts):
1848 """runs the changeset discovery protocol in isolation"""
1855 """runs the changeset discovery protocol in isolation"""
1849 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1856 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
1850 opts.get('branch'))
1857 opts.get('branch'))
1851 remote = hg.peer(repo, opts, remoteurl)
1858 remote = hg.peer(repo, opts, remoteurl)
1852 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1859 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
1853
1860
1854 # make sure tests are repeatable
1861 # make sure tests are repeatable
1855 random.seed(12323)
1862 random.seed(12323)
1856
1863
1857 def doit(localheads, remoteheads, remote=remote):
1864 def doit(localheads, remoteheads, remote=remote):
1858 if opts.get('old'):
1865 if opts.get('old'):
1859 if localheads:
1866 if localheads:
1860 raise util.Abort('cannot use localheads with old style '
1867 raise util.Abort('cannot use localheads with old style '
1861 'discovery')
1868 'discovery')
1862 if not util.safehasattr(remote, 'branches'):
1869 if not util.safehasattr(remote, 'branches'):
1863 # enable in-client legacy support
1870 # enable in-client legacy support
1864 remote = localrepo.locallegacypeer(remote.local())
1871 remote = localrepo.locallegacypeer(remote.local())
1865 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1872 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
1866 force=True)
1873 force=True)
1867 common = set(common)
1874 common = set(common)
1868 if not opts.get('nonheads'):
1875 if not opts.get('nonheads'):
1869 ui.write(("unpruned common: %s\n") %
1876 ui.write(("unpruned common: %s\n") %
1870 " ".join(sorted(short(n) for n in common)))
1877 " ".join(sorted(short(n) for n in common)))
1871 dag = dagutil.revlogdag(repo.changelog)
1878 dag = dagutil.revlogdag(repo.changelog)
1872 all = dag.ancestorset(dag.internalizeall(common))
1879 all = dag.ancestorset(dag.internalizeall(common))
1873 common = dag.externalizeall(dag.headsetofconnecteds(all))
1880 common = dag.externalizeall(dag.headsetofconnecteds(all))
1874 else:
1881 else:
1875 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1882 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
1876 common = set(common)
1883 common = set(common)
1877 rheads = set(hds)
1884 rheads = set(hds)
1878 lheads = set(repo.heads())
1885 lheads = set(repo.heads())
1879 ui.write(("common heads: %s\n") %
1886 ui.write(("common heads: %s\n") %
1880 " ".join(sorted(short(n) for n in common)))
1887 " ".join(sorted(short(n) for n in common)))
1881 if lheads <= common:
1888 if lheads <= common:
1882 ui.write(("local is subset\n"))
1889 ui.write(("local is subset\n"))
1883 elif rheads <= common:
1890 elif rheads <= common:
1884 ui.write(("remote is subset\n"))
1891 ui.write(("remote is subset\n"))
1885
1892
1886 serverlogs = opts.get('serverlog')
1893 serverlogs = opts.get('serverlog')
1887 if serverlogs:
1894 if serverlogs:
1888 for filename in serverlogs:
1895 for filename in serverlogs:
1889 logfile = open(filename, 'r')
1896 logfile = open(filename, 'r')
1890 try:
1897 try:
1891 line = logfile.readline()
1898 line = logfile.readline()
1892 while line:
1899 while line:
1893 parts = line.strip().split(';')
1900 parts = line.strip().split(';')
1894 op = parts[1]
1901 op = parts[1]
1895 if op == 'cg':
1902 if op == 'cg':
1896 pass
1903 pass
1897 elif op == 'cgss':
1904 elif op == 'cgss':
1898 doit(parts[2].split(' '), parts[3].split(' '))
1905 doit(parts[2].split(' '), parts[3].split(' '))
1899 elif op == 'unb':
1906 elif op == 'unb':
1900 doit(parts[3].split(' '), parts[2].split(' '))
1907 doit(parts[3].split(' '), parts[2].split(' '))
1901 line = logfile.readline()
1908 line = logfile.readline()
1902 finally:
1909 finally:
1903 logfile.close()
1910 logfile.close()
1904
1911
1905 else:
1912 else:
1906 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1913 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
1907 opts.get('remote_head'))
1914 opts.get('remote_head'))
1908 localrevs = opts.get('local_head')
1915 localrevs = opts.get('local_head')
1909 doit(localrevs, remoterevs)
1916 doit(localrevs, remoterevs)
1910
1917
1911 @command('debugfileset',
1918 @command('debugfileset',
1912 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1919 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
1913 _('[-r REV] FILESPEC'))
1920 _('[-r REV] FILESPEC'))
1914 def debugfileset(ui, repo, expr, **opts):
1921 def debugfileset(ui, repo, expr, **opts):
1915 '''parse and apply a fileset specification'''
1922 '''parse and apply a fileset specification'''
1916 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1923 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
1917 if ui.verbose:
1924 if ui.verbose:
1918 tree = fileset.parse(expr)[0]
1925 tree = fileset.parse(expr)[0]
1919 ui.note(tree, "\n")
1926 ui.note(tree, "\n")
1920
1927
1921 for f in fileset.getfileset(ctx, expr):
1928 for f in fileset.getfileset(ctx, expr):
1922 ui.write("%s\n" % f)
1929 ui.write("%s\n" % f)
1923
1930
1924 @command('debugfsinfo', [], _('[PATH]'))
1931 @command('debugfsinfo', [], _('[PATH]'))
1925 def debugfsinfo(ui, path="."):
1932 def debugfsinfo(ui, path="."):
1926 """show information detected about current filesystem"""
1933 """show information detected about current filesystem"""
1927 util.writefile('.debugfsinfo', '')
1934 util.writefile('.debugfsinfo', '')
1928 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1935 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
1929 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1936 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
1930 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1937 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
1931 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1938 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
1932 and 'yes' or 'no'))
1939 and 'yes' or 'no'))
1933 os.unlink('.debugfsinfo')
1940 os.unlink('.debugfsinfo')
1934
1941
1935 @command('debuggetbundle',
1942 @command('debuggetbundle',
1936 [('H', 'head', [], _('id of head node'), _('ID')),
1943 [('H', 'head', [], _('id of head node'), _('ID')),
1937 ('C', 'common', [], _('id of common node'), _('ID')),
1944 ('C', 'common', [], _('id of common node'), _('ID')),
1938 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1945 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
1939 _('REPO FILE [-H|-C ID]...'))
1946 _('REPO FILE [-H|-C ID]...'))
1940 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1947 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
1941 """retrieves a bundle from a repo
1948 """retrieves a bundle from a repo
1942
1949
1943 Every ID must be a full-length hex node id string. Saves the bundle to the
1950 Every ID must be a full-length hex node id string. Saves the bundle to the
1944 given file.
1951 given file.
1945 """
1952 """
1946 repo = hg.peer(ui, opts, repopath)
1953 repo = hg.peer(ui, opts, repopath)
1947 if not repo.capable('getbundle'):
1954 if not repo.capable('getbundle'):
1948 raise util.Abort("getbundle() not supported by target repository")
1955 raise util.Abort("getbundle() not supported by target repository")
1949 args = {}
1956 args = {}
1950 if common:
1957 if common:
1951 args['common'] = [bin(s) for s in common]
1958 args['common'] = [bin(s) for s in common]
1952 if head:
1959 if head:
1953 args['heads'] = [bin(s) for s in head]
1960 args['heads'] = [bin(s) for s in head]
1954 # TODO: get desired bundlecaps from command line.
1961 # TODO: get desired bundlecaps from command line.
1955 args['bundlecaps'] = None
1962 args['bundlecaps'] = None
1956 bundle = repo.getbundle('debug', **args)
1963 bundle = repo.getbundle('debug', **args)
1957
1964
1958 bundletype = opts.get('type', 'bzip2').lower()
1965 bundletype = opts.get('type', 'bzip2').lower()
1959 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1966 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1960 bundletype = btypes.get(bundletype)
1967 bundletype = btypes.get(bundletype)
1961 if bundletype not in changegroup.bundletypes:
1968 if bundletype not in changegroup.bundletypes:
1962 raise util.Abort(_('unknown bundle type specified with --type'))
1969 raise util.Abort(_('unknown bundle type specified with --type'))
1963 changegroup.writebundle(bundle, bundlepath, bundletype)
1970 changegroup.writebundle(bundle, bundlepath, bundletype)
1964
1971
1965 @command('debugignore', [], '')
1972 @command('debugignore', [], '')
1966 def debugignore(ui, repo, *values, **opts):
1973 def debugignore(ui, repo, *values, **opts):
1967 """display the combined ignore pattern"""
1974 """display the combined ignore pattern"""
1968 ignore = repo.dirstate._ignore
1975 ignore = repo.dirstate._ignore
1969 includepat = getattr(ignore, 'includepat', None)
1976 includepat = getattr(ignore, 'includepat', None)
1970 if includepat is not None:
1977 if includepat is not None:
1971 ui.write("%s\n" % includepat)
1978 ui.write("%s\n" % includepat)
1972 else:
1979 else:
1973 raise util.Abort(_("no ignore patterns found"))
1980 raise util.Abort(_("no ignore patterns found"))
1974
1981
1975 @command('debugindex',
1982 @command('debugindex',
1976 [('c', 'changelog', False, _('open changelog')),
1983 [('c', 'changelog', False, _('open changelog')),
1977 ('m', 'manifest', False, _('open manifest')),
1984 ('m', 'manifest', False, _('open manifest')),
1978 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1985 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
1979 _('[-f FORMAT] -c|-m|FILE'))
1986 _('[-f FORMAT] -c|-m|FILE'))
1980 def debugindex(ui, repo, file_=None, **opts):
1987 def debugindex(ui, repo, file_=None, **opts):
1981 """dump the contents of an index file"""
1988 """dump the contents of an index file"""
1982 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1989 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
1983 format = opts.get('format', 0)
1990 format = opts.get('format', 0)
1984 if format not in (0, 1):
1991 if format not in (0, 1):
1985 raise util.Abort(_("unknown format %d") % format)
1992 raise util.Abort(_("unknown format %d") % format)
1986
1993
1987 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1994 generaldelta = r.version & revlog.REVLOGGENERALDELTA
1988 if generaldelta:
1995 if generaldelta:
1989 basehdr = ' delta'
1996 basehdr = ' delta'
1990 else:
1997 else:
1991 basehdr = ' base'
1998 basehdr = ' base'
1992
1999
1993 if format == 0:
2000 if format == 0:
1994 ui.write(" rev offset length " + basehdr + " linkrev"
2001 ui.write(" rev offset length " + basehdr + " linkrev"
1995 " nodeid p1 p2\n")
2002 " nodeid p1 p2\n")
1996 elif format == 1:
2003 elif format == 1:
1997 ui.write(" rev flag offset length"
2004 ui.write(" rev flag offset length"
1998 " size " + basehdr + " link p1 p2"
2005 " size " + basehdr + " link p1 p2"
1999 " nodeid\n")
2006 " nodeid\n")
2000
2007
2001 for i in r:
2008 for i in r:
2002 node = r.node(i)
2009 node = r.node(i)
2003 if generaldelta:
2010 if generaldelta:
2004 base = r.deltaparent(i)
2011 base = r.deltaparent(i)
2005 else:
2012 else:
2006 base = r.chainbase(i)
2013 base = r.chainbase(i)
2007 if format == 0:
2014 if format == 0:
2008 try:
2015 try:
2009 pp = r.parents(node)
2016 pp = r.parents(node)
2010 except Exception:
2017 except Exception:
2011 pp = [nullid, nullid]
2018 pp = [nullid, nullid]
2012 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2019 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2013 i, r.start(i), r.length(i), base, r.linkrev(i),
2020 i, r.start(i), r.length(i), base, r.linkrev(i),
2014 short(node), short(pp[0]), short(pp[1])))
2021 short(node), short(pp[0]), short(pp[1])))
2015 elif format == 1:
2022 elif format == 1:
2016 pr = r.parentrevs(i)
2023 pr = r.parentrevs(i)
2017 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2024 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2018 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2025 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2019 base, r.linkrev(i), pr[0], pr[1], short(node)))
2026 base, r.linkrev(i), pr[0], pr[1], short(node)))
2020
2027
2021 @command('debugindexdot', [], _('FILE'))
2028 @command('debugindexdot', [], _('FILE'))
2022 def debugindexdot(ui, repo, file_):
2029 def debugindexdot(ui, repo, file_):
2023 """dump an index DAG as a graphviz dot file"""
2030 """dump an index DAG as a graphviz dot file"""
2024 r = None
2031 r = None
2025 if repo:
2032 if repo:
2026 filelog = repo.file(file_)
2033 filelog = repo.file(file_)
2027 if len(filelog):
2034 if len(filelog):
2028 r = filelog
2035 r = filelog
2029 if not r:
2036 if not r:
2030 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2037 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2031 ui.write(("digraph G {\n"))
2038 ui.write(("digraph G {\n"))
2032 for i in r:
2039 for i in r:
2033 node = r.node(i)
2040 node = r.node(i)
2034 pp = r.parents(node)
2041 pp = r.parents(node)
2035 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2042 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2036 if pp[1] != nullid:
2043 if pp[1] != nullid:
2037 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2044 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2038 ui.write("}\n")
2045 ui.write("}\n")
2039
2046
2040 @command('debuginstall', [], '')
2047 @command('debuginstall', [], '')
2041 def debuginstall(ui):
2048 def debuginstall(ui):
2042 '''test Mercurial installation
2049 '''test Mercurial installation
2043
2050
2044 Returns 0 on success.
2051 Returns 0 on success.
2045 '''
2052 '''
2046
2053
2047 def writetemp(contents):
2054 def writetemp(contents):
2048 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2055 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2049 f = os.fdopen(fd, "wb")
2056 f = os.fdopen(fd, "wb")
2050 f.write(contents)
2057 f.write(contents)
2051 f.close()
2058 f.close()
2052 return name
2059 return name
2053
2060
2054 problems = 0
2061 problems = 0
2055
2062
2056 # encoding
2063 # encoding
2057 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2064 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2058 try:
2065 try:
2059 encoding.fromlocal("test")
2066 encoding.fromlocal("test")
2060 except util.Abort, inst:
2067 except util.Abort, inst:
2061 ui.write(" %s\n" % inst)
2068 ui.write(" %s\n" % inst)
2062 ui.write(_(" (check that your locale is properly set)\n"))
2069 ui.write(_(" (check that your locale is properly set)\n"))
2063 problems += 1
2070 problems += 1
2064
2071
2065 # Python lib
2072 # Python lib
2066 ui.status(_("checking Python lib (%s)...\n")
2073 ui.status(_("checking Python lib (%s)...\n")
2067 % os.path.dirname(os.__file__))
2074 % os.path.dirname(os.__file__))
2068
2075
2069 # compiled modules
2076 # compiled modules
2070 ui.status(_("checking installed modules (%s)...\n")
2077 ui.status(_("checking installed modules (%s)...\n")
2071 % os.path.dirname(__file__))
2078 % os.path.dirname(__file__))
2072 try:
2079 try:
2073 import bdiff, mpatch, base85, osutil
2080 import bdiff, mpatch, base85, osutil
2074 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2081 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2075 except Exception, inst:
2082 except Exception, inst:
2076 ui.write(" %s\n" % inst)
2083 ui.write(" %s\n" % inst)
2077 ui.write(_(" One or more extensions could not be found"))
2084 ui.write(_(" One or more extensions could not be found"))
2078 ui.write(_(" (check that you compiled the extensions)\n"))
2085 ui.write(_(" (check that you compiled the extensions)\n"))
2079 problems += 1
2086 problems += 1
2080
2087
2081 # templates
2088 # templates
2082 import templater
2089 import templater
2083 p = templater.templatepath()
2090 p = templater.templatepath()
2084 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2091 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2085 try:
2092 try:
2086 templater.templater(templater.templatepath("map-cmdline.default"))
2093 templater.templater(templater.templatepath("map-cmdline.default"))
2087 except Exception, inst:
2094 except Exception, inst:
2088 ui.write(" %s\n" % inst)
2095 ui.write(" %s\n" % inst)
2089 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2096 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2090 problems += 1
2097 problems += 1
2091
2098
2092 # editor
2099 # editor
2093 ui.status(_("checking commit editor...\n"))
2100 ui.status(_("checking commit editor...\n"))
2094 editor = ui.geteditor()
2101 editor = ui.geteditor()
2095 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2102 cmdpath = util.findexe(editor) or util.findexe(editor.split()[0])
2096 if not cmdpath:
2103 if not cmdpath:
2097 if editor == 'vi':
2104 if editor == 'vi':
2098 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2105 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2099 ui.write(_(" (specify a commit editor in your configuration"
2106 ui.write(_(" (specify a commit editor in your configuration"
2100 " file)\n"))
2107 " file)\n"))
2101 else:
2108 else:
2102 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2109 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2103 ui.write(_(" (specify a commit editor in your configuration"
2110 ui.write(_(" (specify a commit editor in your configuration"
2104 " file)\n"))
2111 " file)\n"))
2105 problems += 1
2112 problems += 1
2106
2113
2107 # check username
2114 # check username
2108 ui.status(_("checking username...\n"))
2115 ui.status(_("checking username...\n"))
2109 try:
2116 try:
2110 ui.username()
2117 ui.username()
2111 except util.Abort, e:
2118 except util.Abort, e:
2112 ui.write(" %s\n" % e)
2119 ui.write(" %s\n" % e)
2113 ui.write(_(" (specify a username in your configuration file)\n"))
2120 ui.write(_(" (specify a username in your configuration file)\n"))
2114 problems += 1
2121 problems += 1
2115
2122
2116 if not problems:
2123 if not problems:
2117 ui.status(_("no problems detected\n"))
2124 ui.status(_("no problems detected\n"))
2118 else:
2125 else:
2119 ui.write(_("%s problems detected,"
2126 ui.write(_("%s problems detected,"
2120 " please check your install!\n") % problems)
2127 " please check your install!\n") % problems)
2121
2128
2122 return problems
2129 return problems
2123
2130
2124 @command('debugknown', [], _('REPO ID...'))
2131 @command('debugknown', [], _('REPO ID...'))
2125 def debugknown(ui, repopath, *ids, **opts):
2132 def debugknown(ui, repopath, *ids, **opts):
2126 """test whether node ids are known to a repo
2133 """test whether node ids are known to a repo
2127
2134
2128 Every ID must be a full-length hex node id string. Returns a list of 0s
2135 Every ID must be a full-length hex node id string. Returns a list of 0s
2129 and 1s indicating unknown/known.
2136 and 1s indicating unknown/known.
2130 """
2137 """
2131 repo = hg.peer(ui, opts, repopath)
2138 repo = hg.peer(ui, opts, repopath)
2132 if not repo.capable('known'):
2139 if not repo.capable('known'):
2133 raise util.Abort("known() not supported by target repository")
2140 raise util.Abort("known() not supported by target repository")
2134 flags = repo.known([bin(s) for s in ids])
2141 flags = repo.known([bin(s) for s in ids])
2135 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2142 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2136
2143
2137 @command('debuglabelcomplete', [], _('LABEL...'))
2144 @command('debuglabelcomplete', [], _('LABEL...'))
2138 def debuglabelcomplete(ui, repo, *args):
2145 def debuglabelcomplete(ui, repo, *args):
2139 '''complete "labels" - tags, open branch names, bookmark names'''
2146 '''complete "labels" - tags, open branch names, bookmark names'''
2140
2147
2141 labels = set()
2148 labels = set()
2142 labels.update(t[0] for t in repo.tagslist())
2149 labels.update(t[0] for t in repo.tagslist())
2143 labels.update(repo._bookmarks.keys())
2150 labels.update(repo._bookmarks.keys())
2144 labels.update(tag for (tag, heads, tip, closed)
2151 labels.update(tag for (tag, heads, tip, closed)
2145 in repo.branchmap().iterbranches() if not closed)
2152 in repo.branchmap().iterbranches() if not closed)
2146 completions = set()
2153 completions = set()
2147 if not args:
2154 if not args:
2148 args = ['']
2155 args = ['']
2149 for a in args:
2156 for a in args:
2150 completions.update(l for l in labels if l.startswith(a))
2157 completions.update(l for l in labels if l.startswith(a))
2151 ui.write('\n'.join(sorted(completions)))
2158 ui.write('\n'.join(sorted(completions)))
2152 ui.write('\n')
2159 ui.write('\n')
2153
2160
2154 @command('debugobsolete',
2161 @command('debugobsolete',
2155 [('', 'flags', 0, _('markers flag')),
2162 [('', 'flags', 0, _('markers flag')),
2156 ] + commitopts2,
2163 ] + commitopts2,
2157 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2164 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2158 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2165 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2159 """create arbitrary obsolete marker
2166 """create arbitrary obsolete marker
2160
2167
2161 With no arguments, displays the list of obsolescence markers."""
2168 With no arguments, displays the list of obsolescence markers."""
2162 def parsenodeid(s):
2169 def parsenodeid(s):
2163 try:
2170 try:
2164 # We do not use revsingle/revrange functions here to accept
2171 # We do not use revsingle/revrange functions here to accept
2165 # arbitrary node identifiers, possibly not present in the
2172 # arbitrary node identifiers, possibly not present in the
2166 # local repository.
2173 # local repository.
2167 n = bin(s)
2174 n = bin(s)
2168 if len(n) != len(nullid):
2175 if len(n) != len(nullid):
2169 raise TypeError()
2176 raise TypeError()
2170 return n
2177 return n
2171 except TypeError:
2178 except TypeError:
2172 raise util.Abort('changeset references must be full hexadecimal '
2179 raise util.Abort('changeset references must be full hexadecimal '
2173 'node identifiers')
2180 'node identifiers')
2174
2181
2175 if precursor is not None:
2182 if precursor is not None:
2176 metadata = {}
2183 metadata = {}
2177 if 'date' in opts:
2184 if 'date' in opts:
2178 metadata['date'] = opts['date']
2185 metadata['date'] = opts['date']
2179 metadata['user'] = opts['user'] or ui.username()
2186 metadata['user'] = opts['user'] or ui.username()
2180 succs = tuple(parsenodeid(succ) for succ in successors)
2187 succs = tuple(parsenodeid(succ) for succ in successors)
2181 l = repo.lock()
2188 l = repo.lock()
2182 try:
2189 try:
2183 tr = repo.transaction('debugobsolete')
2190 tr = repo.transaction('debugobsolete')
2184 try:
2191 try:
2185 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2192 repo.obsstore.create(tr, parsenodeid(precursor), succs,
2186 opts['flags'], metadata)
2193 opts['flags'], metadata)
2187 tr.close()
2194 tr.close()
2188 finally:
2195 finally:
2189 tr.release()
2196 tr.release()
2190 finally:
2197 finally:
2191 l.release()
2198 l.release()
2192 else:
2199 else:
2193 for m in obsolete.allmarkers(repo):
2200 for m in obsolete.allmarkers(repo):
2194 ui.write(hex(m.precnode()))
2201 ui.write(hex(m.precnode()))
2195 for repl in m.succnodes():
2202 for repl in m.succnodes():
2196 ui.write(' ')
2203 ui.write(' ')
2197 ui.write(hex(repl))
2204 ui.write(hex(repl))
2198 ui.write(' %X ' % m._data[2])
2205 ui.write(' %X ' % m._data[2])
2199 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2206 ui.write('{%s}' % (', '.join('%r: %r' % t for t in
2200 sorted(m.metadata().items()))))
2207 sorted(m.metadata().items()))))
2201 ui.write('\n')
2208 ui.write('\n')
2202
2209
2203 @command('debugpathcomplete',
2210 @command('debugpathcomplete',
2204 [('f', 'full', None, _('complete an entire path')),
2211 [('f', 'full', None, _('complete an entire path')),
2205 ('n', 'normal', None, _('show only normal files')),
2212 ('n', 'normal', None, _('show only normal files')),
2206 ('a', 'added', None, _('show only added files')),
2213 ('a', 'added', None, _('show only added files')),
2207 ('r', 'removed', None, _('show only removed files'))],
2214 ('r', 'removed', None, _('show only removed files'))],
2208 _('FILESPEC...'))
2215 _('FILESPEC...'))
2209 def debugpathcomplete(ui, repo, *specs, **opts):
2216 def debugpathcomplete(ui, repo, *specs, **opts):
2210 '''complete part or all of a tracked path
2217 '''complete part or all of a tracked path
2211
2218
2212 This command supports shells that offer path name completion. It
2219 This command supports shells that offer path name completion. It
2213 currently completes only files already known to the dirstate.
2220 currently completes only files already known to the dirstate.
2214
2221
2215 Completion extends only to the next path segment unless
2222 Completion extends only to the next path segment unless
2216 --full is specified, in which case entire paths are used.'''
2223 --full is specified, in which case entire paths are used.'''
2217
2224
2218 def complete(path, acceptable):
2225 def complete(path, acceptable):
2219 dirstate = repo.dirstate
2226 dirstate = repo.dirstate
2220 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2227 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2221 rootdir = repo.root + os.sep
2228 rootdir = repo.root + os.sep
2222 if spec != repo.root and not spec.startswith(rootdir):
2229 if spec != repo.root and not spec.startswith(rootdir):
2223 return [], []
2230 return [], []
2224 if os.path.isdir(spec):
2231 if os.path.isdir(spec):
2225 spec += '/'
2232 spec += '/'
2226 spec = spec[len(rootdir):]
2233 spec = spec[len(rootdir):]
2227 fixpaths = os.sep != '/'
2234 fixpaths = os.sep != '/'
2228 if fixpaths:
2235 if fixpaths:
2229 spec = spec.replace(os.sep, '/')
2236 spec = spec.replace(os.sep, '/')
2230 speclen = len(spec)
2237 speclen = len(spec)
2231 fullpaths = opts['full']
2238 fullpaths = opts['full']
2232 files, dirs = set(), set()
2239 files, dirs = set(), set()
2233 adddir, addfile = dirs.add, files.add
2240 adddir, addfile = dirs.add, files.add
2234 for f, st in dirstate.iteritems():
2241 for f, st in dirstate.iteritems():
2235 if f.startswith(spec) and st[0] in acceptable:
2242 if f.startswith(spec) and st[0] in acceptable:
2236 if fixpaths:
2243 if fixpaths:
2237 f = f.replace('/', os.sep)
2244 f = f.replace('/', os.sep)
2238 if fullpaths:
2245 if fullpaths:
2239 addfile(f)
2246 addfile(f)
2240 continue
2247 continue
2241 s = f.find(os.sep, speclen)
2248 s = f.find(os.sep, speclen)
2242 if s >= 0:
2249 if s >= 0:
2243 adddir(f[:s])
2250 adddir(f[:s])
2244 else:
2251 else:
2245 addfile(f)
2252 addfile(f)
2246 return files, dirs
2253 return files, dirs
2247
2254
2248 acceptable = ''
2255 acceptable = ''
2249 if opts['normal']:
2256 if opts['normal']:
2250 acceptable += 'nm'
2257 acceptable += 'nm'
2251 if opts['added']:
2258 if opts['added']:
2252 acceptable += 'a'
2259 acceptable += 'a'
2253 if opts['removed']:
2260 if opts['removed']:
2254 acceptable += 'r'
2261 acceptable += 'r'
2255 cwd = repo.getcwd()
2262 cwd = repo.getcwd()
2256 if not specs:
2263 if not specs:
2257 specs = ['.']
2264 specs = ['.']
2258
2265
2259 files, dirs = set(), set()
2266 files, dirs = set(), set()
2260 for spec in specs:
2267 for spec in specs:
2261 f, d = complete(spec, acceptable or 'nmar')
2268 f, d = complete(spec, acceptable or 'nmar')
2262 files.update(f)
2269 files.update(f)
2263 dirs.update(d)
2270 dirs.update(d)
2264 files.update(dirs)
2271 files.update(dirs)
2265 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2272 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2266 ui.write('\n')
2273 ui.write('\n')
2267
2274
2268 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2275 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'))
2269 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2276 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2270 '''access the pushkey key/value protocol
2277 '''access the pushkey key/value protocol
2271
2278
2272 With two args, list the keys in the given namespace.
2279 With two args, list the keys in the given namespace.
2273
2280
2274 With five args, set a key to new if it currently is set to old.
2281 With five args, set a key to new if it currently is set to old.
2275 Reports success or failure.
2282 Reports success or failure.
2276 '''
2283 '''
2277
2284
2278 target = hg.peer(ui, {}, repopath)
2285 target = hg.peer(ui, {}, repopath)
2279 if keyinfo:
2286 if keyinfo:
2280 key, old, new = keyinfo
2287 key, old, new = keyinfo
2281 r = target.pushkey(namespace, key, old, new)
2288 r = target.pushkey(namespace, key, old, new)
2282 ui.status(str(r) + '\n')
2289 ui.status(str(r) + '\n')
2283 return not r
2290 return not r
2284 else:
2291 else:
2285 for k, v in sorted(target.listkeys(namespace).iteritems()):
2292 for k, v in sorted(target.listkeys(namespace).iteritems()):
2286 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2293 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2287 v.encode('string-escape')))
2294 v.encode('string-escape')))
2288
2295
2289 @command('debugpvec', [], _('A B'))
2296 @command('debugpvec', [], _('A B'))
2290 def debugpvec(ui, repo, a, b=None):
2297 def debugpvec(ui, repo, a, b=None):
2291 ca = scmutil.revsingle(repo, a)
2298 ca = scmutil.revsingle(repo, a)
2292 cb = scmutil.revsingle(repo, b)
2299 cb = scmutil.revsingle(repo, b)
2293 pa = pvec.ctxpvec(ca)
2300 pa = pvec.ctxpvec(ca)
2294 pb = pvec.ctxpvec(cb)
2301 pb = pvec.ctxpvec(cb)
2295 if pa == pb:
2302 if pa == pb:
2296 rel = "="
2303 rel = "="
2297 elif pa > pb:
2304 elif pa > pb:
2298 rel = ">"
2305 rel = ">"
2299 elif pa < pb:
2306 elif pa < pb:
2300 rel = "<"
2307 rel = "<"
2301 elif pa | pb:
2308 elif pa | pb:
2302 rel = "|"
2309 rel = "|"
2303 ui.write(_("a: %s\n") % pa)
2310 ui.write(_("a: %s\n") % pa)
2304 ui.write(_("b: %s\n") % pb)
2311 ui.write(_("b: %s\n") % pb)
2305 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2312 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2306 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2313 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2307 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2314 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2308 pa.distance(pb), rel))
2315 pa.distance(pb), rel))
2309
2316
2310 @command('debugrebuilddirstate|debugrebuildstate',
2317 @command('debugrebuilddirstate|debugrebuildstate',
2311 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2318 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2312 _('[-r REV]'))
2319 _('[-r REV]'))
2313 def debugrebuilddirstate(ui, repo, rev):
2320 def debugrebuilddirstate(ui, repo, rev):
2314 """rebuild the dirstate as it would look like for the given revision
2321 """rebuild the dirstate as it would look like for the given revision
2315
2322
2316 If no revision is specified the first current parent will be used.
2323 If no revision is specified the first current parent will be used.
2317
2324
2318 The dirstate will be set to the files of the given revision.
2325 The dirstate will be set to the files of the given revision.
2319 The actual working directory content or existing dirstate
2326 The actual working directory content or existing dirstate
2320 information such as adds or removes is not considered.
2327 information such as adds or removes is not considered.
2321
2328
2322 One use of this command is to make the next :hg:`status` invocation
2329 One use of this command is to make the next :hg:`status` invocation
2323 check the actual file content.
2330 check the actual file content.
2324 """
2331 """
2325 ctx = scmutil.revsingle(repo, rev)
2332 ctx = scmutil.revsingle(repo, rev)
2326 wlock = repo.wlock()
2333 wlock = repo.wlock()
2327 try:
2334 try:
2328 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2335 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2329 finally:
2336 finally:
2330 wlock.release()
2337 wlock.release()
2331
2338
2332 @command('debugrename',
2339 @command('debugrename',
2333 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2340 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2334 _('[-r REV] FILE'))
2341 _('[-r REV] FILE'))
2335 def debugrename(ui, repo, file1, *pats, **opts):
2342 def debugrename(ui, repo, file1, *pats, **opts):
2336 """dump rename information"""
2343 """dump rename information"""
2337
2344
2338 ctx = scmutil.revsingle(repo, opts.get('rev'))
2345 ctx = scmutil.revsingle(repo, opts.get('rev'))
2339 m = scmutil.match(ctx, (file1,) + pats, opts)
2346 m = scmutil.match(ctx, (file1,) + pats, opts)
2340 for abs in ctx.walk(m):
2347 for abs in ctx.walk(m):
2341 fctx = ctx[abs]
2348 fctx = ctx[abs]
2342 o = fctx.filelog().renamed(fctx.filenode())
2349 o = fctx.filelog().renamed(fctx.filenode())
2343 rel = m.rel(abs)
2350 rel = m.rel(abs)
2344 if o:
2351 if o:
2345 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2352 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2346 else:
2353 else:
2347 ui.write(_("%s not renamed\n") % rel)
2354 ui.write(_("%s not renamed\n") % rel)
2348
2355
2349 @command('debugrevlog',
2356 @command('debugrevlog',
2350 [('c', 'changelog', False, _('open changelog')),
2357 [('c', 'changelog', False, _('open changelog')),
2351 ('m', 'manifest', False, _('open manifest')),
2358 ('m', 'manifest', False, _('open manifest')),
2352 ('d', 'dump', False, _('dump index data'))],
2359 ('d', 'dump', False, _('dump index data'))],
2353 _('-c|-m|FILE'))
2360 _('-c|-m|FILE'))
2354 def debugrevlog(ui, repo, file_=None, **opts):
2361 def debugrevlog(ui, repo, file_=None, **opts):
2355 """show data and statistics about a revlog"""
2362 """show data and statistics about a revlog"""
2356 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2363 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2357
2364
2358 if opts.get("dump"):
2365 if opts.get("dump"):
2359 numrevs = len(r)
2366 numrevs = len(r)
2360 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2367 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2361 " rawsize totalsize compression heads\n")
2368 " rawsize totalsize compression heads\n")
2362 ts = 0
2369 ts = 0
2363 heads = set()
2370 heads = set()
2364 for rev in xrange(numrevs):
2371 for rev in xrange(numrevs):
2365 dbase = r.deltaparent(rev)
2372 dbase = r.deltaparent(rev)
2366 if dbase == -1:
2373 if dbase == -1:
2367 dbase = rev
2374 dbase = rev
2368 cbase = r.chainbase(rev)
2375 cbase = r.chainbase(rev)
2369 p1, p2 = r.parentrevs(rev)
2376 p1, p2 = r.parentrevs(rev)
2370 rs = r.rawsize(rev)
2377 rs = r.rawsize(rev)
2371 ts = ts + rs
2378 ts = ts + rs
2372 heads -= set(r.parentrevs(rev))
2379 heads -= set(r.parentrevs(rev))
2373 heads.add(rev)
2380 heads.add(rev)
2374 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2381 ui.write("%d %d %d %d %d %d %d %d %d %d %d %d %d\n" %
2375 (rev, p1, p2, r.start(rev), r.end(rev),
2382 (rev, p1, p2, r.start(rev), r.end(rev),
2376 r.start(dbase), r.start(cbase),
2383 r.start(dbase), r.start(cbase),
2377 r.start(p1), r.start(p2),
2384 r.start(p1), r.start(p2),
2378 rs, ts, ts / r.end(rev), len(heads)))
2385 rs, ts, ts / r.end(rev), len(heads)))
2379 return 0
2386 return 0
2380
2387
2381 v = r.version
2388 v = r.version
2382 format = v & 0xFFFF
2389 format = v & 0xFFFF
2383 flags = []
2390 flags = []
2384 gdelta = False
2391 gdelta = False
2385 if v & revlog.REVLOGNGINLINEDATA:
2392 if v & revlog.REVLOGNGINLINEDATA:
2386 flags.append('inline')
2393 flags.append('inline')
2387 if v & revlog.REVLOGGENERALDELTA:
2394 if v & revlog.REVLOGGENERALDELTA:
2388 gdelta = True
2395 gdelta = True
2389 flags.append('generaldelta')
2396 flags.append('generaldelta')
2390 if not flags:
2397 if not flags:
2391 flags = ['(none)']
2398 flags = ['(none)']
2392
2399
2393 nummerges = 0
2400 nummerges = 0
2394 numfull = 0
2401 numfull = 0
2395 numprev = 0
2402 numprev = 0
2396 nump1 = 0
2403 nump1 = 0
2397 nump2 = 0
2404 nump2 = 0
2398 numother = 0
2405 numother = 0
2399 nump1prev = 0
2406 nump1prev = 0
2400 nump2prev = 0
2407 nump2prev = 0
2401 chainlengths = []
2408 chainlengths = []
2402
2409
2403 datasize = [None, 0, 0L]
2410 datasize = [None, 0, 0L]
2404 fullsize = [None, 0, 0L]
2411 fullsize = [None, 0, 0L]
2405 deltasize = [None, 0, 0L]
2412 deltasize = [None, 0, 0L]
2406
2413
2407 def addsize(size, l):
2414 def addsize(size, l):
2408 if l[0] is None or size < l[0]:
2415 if l[0] is None or size < l[0]:
2409 l[0] = size
2416 l[0] = size
2410 if size > l[1]:
2417 if size > l[1]:
2411 l[1] = size
2418 l[1] = size
2412 l[2] += size
2419 l[2] += size
2413
2420
2414 numrevs = len(r)
2421 numrevs = len(r)
2415 for rev in xrange(numrevs):
2422 for rev in xrange(numrevs):
2416 p1, p2 = r.parentrevs(rev)
2423 p1, p2 = r.parentrevs(rev)
2417 delta = r.deltaparent(rev)
2424 delta = r.deltaparent(rev)
2418 if format > 0:
2425 if format > 0:
2419 addsize(r.rawsize(rev), datasize)
2426 addsize(r.rawsize(rev), datasize)
2420 if p2 != nullrev:
2427 if p2 != nullrev:
2421 nummerges += 1
2428 nummerges += 1
2422 size = r.length(rev)
2429 size = r.length(rev)
2423 if delta == nullrev:
2430 if delta == nullrev:
2424 chainlengths.append(0)
2431 chainlengths.append(0)
2425 numfull += 1
2432 numfull += 1
2426 addsize(size, fullsize)
2433 addsize(size, fullsize)
2427 else:
2434 else:
2428 chainlengths.append(chainlengths[delta] + 1)
2435 chainlengths.append(chainlengths[delta] + 1)
2429 addsize(size, deltasize)
2436 addsize(size, deltasize)
2430 if delta == rev - 1:
2437 if delta == rev - 1:
2431 numprev += 1
2438 numprev += 1
2432 if delta == p1:
2439 if delta == p1:
2433 nump1prev += 1
2440 nump1prev += 1
2434 elif delta == p2:
2441 elif delta == p2:
2435 nump2prev += 1
2442 nump2prev += 1
2436 elif delta == p1:
2443 elif delta == p1:
2437 nump1 += 1
2444 nump1 += 1
2438 elif delta == p2:
2445 elif delta == p2:
2439 nump2 += 1
2446 nump2 += 1
2440 elif delta != nullrev:
2447 elif delta != nullrev:
2441 numother += 1
2448 numother += 1
2442
2449
2443 # Adjust size min value for empty cases
2450 # Adjust size min value for empty cases
2444 for size in (datasize, fullsize, deltasize):
2451 for size in (datasize, fullsize, deltasize):
2445 if size[0] is None:
2452 if size[0] is None:
2446 size[0] = 0
2453 size[0] = 0
2447
2454
2448 numdeltas = numrevs - numfull
2455 numdeltas = numrevs - numfull
2449 numoprev = numprev - nump1prev - nump2prev
2456 numoprev = numprev - nump1prev - nump2prev
2450 totalrawsize = datasize[2]
2457 totalrawsize = datasize[2]
2451 datasize[2] /= numrevs
2458 datasize[2] /= numrevs
2452 fulltotal = fullsize[2]
2459 fulltotal = fullsize[2]
2453 fullsize[2] /= numfull
2460 fullsize[2] /= numfull
2454 deltatotal = deltasize[2]
2461 deltatotal = deltasize[2]
2455 if numrevs - numfull > 0:
2462 if numrevs - numfull > 0:
2456 deltasize[2] /= numrevs - numfull
2463 deltasize[2] /= numrevs - numfull
2457 totalsize = fulltotal + deltatotal
2464 totalsize = fulltotal + deltatotal
2458 avgchainlen = sum(chainlengths) / numrevs
2465 avgchainlen = sum(chainlengths) / numrevs
2459 compratio = totalrawsize / totalsize
2466 compratio = totalrawsize / totalsize
2460
2467
2461 basedfmtstr = '%%%dd\n'
2468 basedfmtstr = '%%%dd\n'
2462 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2469 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2463
2470
2464 def dfmtstr(max):
2471 def dfmtstr(max):
2465 return basedfmtstr % len(str(max))
2472 return basedfmtstr % len(str(max))
2466 def pcfmtstr(max, padding=0):
2473 def pcfmtstr(max, padding=0):
2467 return basepcfmtstr % (len(str(max)), ' ' * padding)
2474 return basepcfmtstr % (len(str(max)), ' ' * padding)
2468
2475
2469 def pcfmt(value, total):
2476 def pcfmt(value, total):
2470 return (value, 100 * float(value) / total)
2477 return (value, 100 * float(value) / total)
2471
2478
2472 ui.write(('format : %d\n') % format)
2479 ui.write(('format : %d\n') % format)
2473 ui.write(('flags : %s\n') % ', '.join(flags))
2480 ui.write(('flags : %s\n') % ', '.join(flags))
2474
2481
2475 ui.write('\n')
2482 ui.write('\n')
2476 fmt = pcfmtstr(totalsize)
2483 fmt = pcfmtstr(totalsize)
2477 fmt2 = dfmtstr(totalsize)
2484 fmt2 = dfmtstr(totalsize)
2478 ui.write(('revisions : ') + fmt2 % numrevs)
2485 ui.write(('revisions : ') + fmt2 % numrevs)
2479 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2486 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2480 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2487 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2481 ui.write(('revisions : ') + fmt2 % numrevs)
2488 ui.write(('revisions : ') + fmt2 % numrevs)
2482 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2489 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2483 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2490 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2484 ui.write(('revision size : ') + fmt2 % totalsize)
2491 ui.write(('revision size : ') + fmt2 % totalsize)
2485 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2492 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2486 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2493 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2487
2494
2488 ui.write('\n')
2495 ui.write('\n')
2489 fmt = dfmtstr(max(avgchainlen, compratio))
2496 fmt = dfmtstr(max(avgchainlen, compratio))
2490 ui.write(('avg chain length : ') + fmt % avgchainlen)
2497 ui.write(('avg chain length : ') + fmt % avgchainlen)
2491 ui.write(('compression ratio : ') + fmt % compratio)
2498 ui.write(('compression ratio : ') + fmt % compratio)
2492
2499
2493 if format > 0:
2500 if format > 0:
2494 ui.write('\n')
2501 ui.write('\n')
2495 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2502 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2496 % tuple(datasize))
2503 % tuple(datasize))
2497 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2504 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2498 % tuple(fullsize))
2505 % tuple(fullsize))
2499 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2506 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2500 % tuple(deltasize))
2507 % tuple(deltasize))
2501
2508
2502 if numdeltas > 0:
2509 if numdeltas > 0:
2503 ui.write('\n')
2510 ui.write('\n')
2504 fmt = pcfmtstr(numdeltas)
2511 fmt = pcfmtstr(numdeltas)
2505 fmt2 = pcfmtstr(numdeltas, 4)
2512 fmt2 = pcfmtstr(numdeltas, 4)
2506 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2513 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2507 if numprev > 0:
2514 if numprev > 0:
2508 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2515 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2509 numprev))
2516 numprev))
2510 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2517 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2511 numprev))
2518 numprev))
2512 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2519 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2513 numprev))
2520 numprev))
2514 if gdelta:
2521 if gdelta:
2515 ui.write(('deltas against p1 : ')
2522 ui.write(('deltas against p1 : ')
2516 + fmt % pcfmt(nump1, numdeltas))
2523 + fmt % pcfmt(nump1, numdeltas))
2517 ui.write(('deltas against p2 : ')
2524 ui.write(('deltas against p2 : ')
2518 + fmt % pcfmt(nump2, numdeltas))
2525 + fmt % pcfmt(nump2, numdeltas))
2519 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2526 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2520 numdeltas))
2527 numdeltas))
2521
2528
2522 @command('debugrevspec', [], ('REVSPEC'))
2529 @command('debugrevspec', [], ('REVSPEC'))
2523 def debugrevspec(ui, repo, expr):
2530 def debugrevspec(ui, repo, expr):
2524 """parse and apply a revision specification
2531 """parse and apply a revision specification
2525
2532
2526 Use --verbose to print the parsed tree before and after aliases
2533 Use --verbose to print the parsed tree before and after aliases
2527 expansion.
2534 expansion.
2528 """
2535 """
2529 if ui.verbose:
2536 if ui.verbose:
2530 tree = revset.parse(expr)[0]
2537 tree = revset.parse(expr)[0]
2531 ui.note(revset.prettyformat(tree), "\n")
2538 ui.note(revset.prettyformat(tree), "\n")
2532 newtree = revset.findaliases(ui, tree)
2539 newtree = revset.findaliases(ui, tree)
2533 if newtree != tree:
2540 if newtree != tree:
2534 ui.note(revset.prettyformat(newtree), "\n")
2541 ui.note(revset.prettyformat(newtree), "\n")
2535 func = revset.match(ui, expr)
2542 func = revset.match(ui, expr)
2536 for c in func(repo, range(len(repo))):
2543 for c in func(repo, range(len(repo))):
2537 ui.write("%s\n" % c)
2544 ui.write("%s\n" % c)
2538
2545
2539 @command('debugsetparents', [], _('REV1 [REV2]'))
2546 @command('debugsetparents', [], _('REV1 [REV2]'))
2540 def debugsetparents(ui, repo, rev1, rev2=None):
2547 def debugsetparents(ui, repo, rev1, rev2=None):
2541 """manually set the parents of the current working directory
2548 """manually set the parents of the current working directory
2542
2549
2543 This is useful for writing repository conversion tools, but should
2550 This is useful for writing repository conversion tools, but should
2544 be used with care.
2551 be used with care.
2545
2552
2546 Returns 0 on success.
2553 Returns 0 on success.
2547 """
2554 """
2548
2555
2549 r1 = scmutil.revsingle(repo, rev1).node()
2556 r1 = scmutil.revsingle(repo, rev1).node()
2550 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2557 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2551
2558
2552 wlock = repo.wlock()
2559 wlock = repo.wlock()
2553 try:
2560 try:
2554 repo.setparents(r1, r2)
2561 repo.setparents(r1, r2)
2555 finally:
2562 finally:
2556 wlock.release()
2563 wlock.release()
2557
2564
2558 @command('debugdirstate|debugstate',
2565 @command('debugdirstate|debugstate',
2559 [('', 'nodates', None, _('do not display the saved mtime')),
2566 [('', 'nodates', None, _('do not display the saved mtime')),
2560 ('', 'datesort', None, _('sort by saved mtime'))],
2567 ('', 'datesort', None, _('sort by saved mtime'))],
2561 _('[OPTION]...'))
2568 _('[OPTION]...'))
2562 def debugstate(ui, repo, nodates=None, datesort=None):
2569 def debugstate(ui, repo, nodates=None, datesort=None):
2563 """show the contents of the current dirstate"""
2570 """show the contents of the current dirstate"""
2564 timestr = ""
2571 timestr = ""
2565 showdate = not nodates
2572 showdate = not nodates
2566 if datesort:
2573 if datesort:
2567 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2574 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2568 else:
2575 else:
2569 keyfunc = None # sort by filename
2576 keyfunc = None # sort by filename
2570 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2577 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2571 if showdate:
2578 if showdate:
2572 if ent[3] == -1:
2579 if ent[3] == -1:
2573 # Pad or slice to locale representation
2580 # Pad or slice to locale representation
2574 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2581 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2575 time.localtime(0)))
2582 time.localtime(0)))
2576 timestr = 'unset'
2583 timestr = 'unset'
2577 timestr = (timestr[:locale_len] +
2584 timestr = (timestr[:locale_len] +
2578 ' ' * (locale_len - len(timestr)))
2585 ' ' * (locale_len - len(timestr)))
2579 else:
2586 else:
2580 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2587 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2581 time.localtime(ent[3]))
2588 time.localtime(ent[3]))
2582 if ent[1] & 020000:
2589 if ent[1] & 020000:
2583 mode = 'lnk'
2590 mode = 'lnk'
2584 else:
2591 else:
2585 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2592 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2586 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2593 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2587 for f in repo.dirstate.copies():
2594 for f in repo.dirstate.copies():
2588 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2595 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2589
2596
2590 @command('debugsub',
2597 @command('debugsub',
2591 [('r', 'rev', '',
2598 [('r', 'rev', '',
2592 _('revision to check'), _('REV'))],
2599 _('revision to check'), _('REV'))],
2593 _('[-r REV] [REV]'))
2600 _('[-r REV] [REV]'))
2594 def debugsub(ui, repo, rev=None):
2601 def debugsub(ui, repo, rev=None):
2595 ctx = scmutil.revsingle(repo, rev, None)
2602 ctx = scmutil.revsingle(repo, rev, None)
2596 for k, v in sorted(ctx.substate.items()):
2603 for k, v in sorted(ctx.substate.items()):
2597 ui.write(('path %s\n') % k)
2604 ui.write(('path %s\n') % k)
2598 ui.write((' source %s\n') % v[0])
2605 ui.write((' source %s\n') % v[0])
2599 ui.write((' revision %s\n') % v[1])
2606 ui.write((' revision %s\n') % v[1])
2600
2607
2601 @command('debugsuccessorssets',
2608 @command('debugsuccessorssets',
2602 [],
2609 [],
2603 _('[REV]'))
2610 _('[REV]'))
2604 def debugsuccessorssets(ui, repo, *revs):
2611 def debugsuccessorssets(ui, repo, *revs):
2605 """show set of successors for revision
2612 """show set of successors for revision
2606
2613
2607 A successors set of changeset A is a consistent group of revisions that
2614 A successors set of changeset A is a consistent group of revisions that
2608 succeed A. It contains non-obsolete changesets only.
2615 succeed A. It contains non-obsolete changesets only.
2609
2616
2610 In most cases a changeset A has a single successors set containing a single
2617 In most cases a changeset A has a single successors set containing a single
2611 successor (changeset A replaced by A').
2618 successor (changeset A replaced by A').
2612
2619
2613 A changeset that is made obsolete with no successors are called "pruned".
2620 A changeset that is made obsolete with no successors are called "pruned".
2614 Such changesets have no successors sets at all.
2621 Such changesets have no successors sets at all.
2615
2622
2616 A changeset that has been "split" will have a successors set containing
2623 A changeset that has been "split" will have a successors set containing
2617 more than one successor.
2624 more than one successor.
2618
2625
2619 A changeset that has been rewritten in multiple different ways is called
2626 A changeset that has been rewritten in multiple different ways is called
2620 "divergent". Such changesets have multiple successor sets (each of which
2627 "divergent". Such changesets have multiple successor sets (each of which
2621 may also be split, i.e. have multiple successors).
2628 may also be split, i.e. have multiple successors).
2622
2629
2623 Results are displayed as follows::
2630 Results are displayed as follows::
2624
2631
2625 <rev1>
2632 <rev1>
2626 <successors-1A>
2633 <successors-1A>
2627 <rev2>
2634 <rev2>
2628 <successors-2A>
2635 <successors-2A>
2629 <successors-2B1> <successors-2B2> <successors-2B3>
2636 <successors-2B1> <successors-2B2> <successors-2B3>
2630
2637
2631 Here rev2 has two possible (i.e. divergent) successors sets. The first
2638 Here rev2 has two possible (i.e. divergent) successors sets. The first
2632 holds one element, whereas the second holds three (i.e. the changeset has
2639 holds one element, whereas the second holds three (i.e. the changeset has
2633 been split).
2640 been split).
2634 """
2641 """
2635 # passed to successorssets caching computation from one call to another
2642 # passed to successorssets caching computation from one call to another
2636 cache = {}
2643 cache = {}
2637 ctx2str = str
2644 ctx2str = str
2638 node2str = short
2645 node2str = short
2639 if ui.debug():
2646 if ui.debug():
2640 def ctx2str(ctx):
2647 def ctx2str(ctx):
2641 return ctx.hex()
2648 return ctx.hex()
2642 node2str = hex
2649 node2str = hex
2643 for rev in scmutil.revrange(repo, revs):
2650 for rev in scmutil.revrange(repo, revs):
2644 ctx = repo[rev]
2651 ctx = repo[rev]
2645 ui.write('%s\n'% ctx2str(ctx))
2652 ui.write('%s\n'% ctx2str(ctx))
2646 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2653 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2647 if succsset:
2654 if succsset:
2648 ui.write(' ')
2655 ui.write(' ')
2649 ui.write(node2str(succsset[0]))
2656 ui.write(node2str(succsset[0]))
2650 for node in succsset[1:]:
2657 for node in succsset[1:]:
2651 ui.write(' ')
2658 ui.write(' ')
2652 ui.write(node2str(node))
2659 ui.write(node2str(node))
2653 ui.write('\n')
2660 ui.write('\n')
2654
2661
2655 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2662 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'))
2656 def debugwalk(ui, repo, *pats, **opts):
2663 def debugwalk(ui, repo, *pats, **opts):
2657 """show how files match on given patterns"""
2664 """show how files match on given patterns"""
2658 m = scmutil.match(repo[None], pats, opts)
2665 m = scmutil.match(repo[None], pats, opts)
2659 items = list(repo.walk(m))
2666 items = list(repo.walk(m))
2660 if not items:
2667 if not items:
2661 return
2668 return
2662 f = lambda fn: fn
2669 f = lambda fn: fn
2663 if ui.configbool('ui', 'slash') and os.sep != '/':
2670 if ui.configbool('ui', 'slash') and os.sep != '/':
2664 f = lambda fn: util.normpath(fn)
2671 f = lambda fn: util.normpath(fn)
2665 fmt = 'f %%-%ds %%-%ds %%s' % (
2672 fmt = 'f %%-%ds %%-%ds %%s' % (
2666 max([len(abs) for abs in items]),
2673 max([len(abs) for abs in items]),
2667 max([len(m.rel(abs)) for abs in items]))
2674 max([len(m.rel(abs)) for abs in items]))
2668 for abs in items:
2675 for abs in items:
2669 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2676 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2670 ui.write("%s\n" % line.rstrip())
2677 ui.write("%s\n" % line.rstrip())
2671
2678
2672 @command('debugwireargs',
2679 @command('debugwireargs',
2673 [('', 'three', '', 'three'),
2680 [('', 'three', '', 'three'),
2674 ('', 'four', '', 'four'),
2681 ('', 'four', '', 'four'),
2675 ('', 'five', '', 'five'),
2682 ('', 'five', '', 'five'),
2676 ] + remoteopts,
2683 ] + remoteopts,
2677 _('REPO [OPTIONS]... [ONE [TWO]]'))
2684 _('REPO [OPTIONS]... [ONE [TWO]]'))
2678 def debugwireargs(ui, repopath, *vals, **opts):
2685 def debugwireargs(ui, repopath, *vals, **opts):
2679 repo = hg.peer(ui, opts, repopath)
2686 repo = hg.peer(ui, opts, repopath)
2680 for opt in remoteopts:
2687 for opt in remoteopts:
2681 del opts[opt[1]]
2688 del opts[opt[1]]
2682 args = {}
2689 args = {}
2683 for k, v in opts.iteritems():
2690 for k, v in opts.iteritems():
2684 if v:
2691 if v:
2685 args[k] = v
2692 args[k] = v
2686 # run twice to check that we don't mess up the stream for the next command
2693 # run twice to check that we don't mess up the stream for the next command
2687 res1 = repo.debugwireargs(*vals, **args)
2694 res1 = repo.debugwireargs(*vals, **args)
2688 res2 = repo.debugwireargs(*vals, **args)
2695 res2 = repo.debugwireargs(*vals, **args)
2689 ui.write("%s\n" % res1)
2696 ui.write("%s\n" % res1)
2690 if res1 != res2:
2697 if res1 != res2:
2691 ui.warn("%s\n" % res2)
2698 ui.warn("%s\n" % res2)
2692
2699
2693 @command('^diff',
2700 @command('^diff',
2694 [('r', 'rev', [], _('revision'), _('REV')),
2701 [('r', 'rev', [], _('revision'), _('REV')),
2695 ('c', 'change', '', _('change made by revision'), _('REV'))
2702 ('c', 'change', '', _('change made by revision'), _('REV'))
2696 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2703 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2697 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2704 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'))
2698 def diff(ui, repo, *pats, **opts):
2705 def diff(ui, repo, *pats, **opts):
2699 """diff repository (or selected files)
2706 """diff repository (or selected files)
2700
2707
2701 Show differences between revisions for the specified files.
2708 Show differences between revisions for the specified files.
2702
2709
2703 Differences between files are shown using the unified diff format.
2710 Differences between files are shown using the unified diff format.
2704
2711
2705 .. note::
2712 .. note::
2706
2713
2707 diff may generate unexpected results for merges, as it will
2714 diff may generate unexpected results for merges, as it will
2708 default to comparing against the working directory's first
2715 default to comparing against the working directory's first
2709 parent changeset if no revisions are specified.
2716 parent changeset if no revisions are specified.
2710
2717
2711 When two revision arguments are given, then changes are shown
2718 When two revision arguments are given, then changes are shown
2712 between those revisions. If only one revision is specified then
2719 between those revisions. If only one revision is specified then
2713 that revision is compared to the working directory, and, when no
2720 that revision is compared to the working directory, and, when no
2714 revisions are specified, the working directory files are compared
2721 revisions are specified, the working directory files are compared
2715 to its parent.
2722 to its parent.
2716
2723
2717 Alternatively you can specify -c/--change with a revision to see
2724 Alternatively you can specify -c/--change with a revision to see
2718 the changes in that changeset relative to its first parent.
2725 the changes in that changeset relative to its first parent.
2719
2726
2720 Without the -a/--text option, diff will avoid generating diffs of
2727 Without the -a/--text option, diff will avoid generating diffs of
2721 files it detects as binary. With -a, diff will generate a diff
2728 files it detects as binary. With -a, diff will generate a diff
2722 anyway, probably with undesirable results.
2729 anyway, probably with undesirable results.
2723
2730
2724 Use the -g/--git option to generate diffs in the git extended diff
2731 Use the -g/--git option to generate diffs in the git extended diff
2725 format. For more information, read :hg:`help diffs`.
2732 format. For more information, read :hg:`help diffs`.
2726
2733
2727 .. container:: verbose
2734 .. container:: verbose
2728
2735
2729 Examples:
2736 Examples:
2730
2737
2731 - compare a file in the current working directory to its parent::
2738 - compare a file in the current working directory to its parent::
2732
2739
2733 hg diff foo.c
2740 hg diff foo.c
2734
2741
2735 - compare two historical versions of a directory, with rename info::
2742 - compare two historical versions of a directory, with rename info::
2736
2743
2737 hg diff --git -r 1.0:1.2 lib/
2744 hg diff --git -r 1.0:1.2 lib/
2738
2745
2739 - get change stats relative to the last change on some date::
2746 - get change stats relative to the last change on some date::
2740
2747
2741 hg diff --stat -r "date('may 2')"
2748 hg diff --stat -r "date('may 2')"
2742
2749
2743 - diff all newly-added files that contain a keyword::
2750 - diff all newly-added files that contain a keyword::
2744
2751
2745 hg diff "set:added() and grep(GNU)"
2752 hg diff "set:added() and grep(GNU)"
2746
2753
2747 - compare a revision and its parents::
2754 - compare a revision and its parents::
2748
2755
2749 hg diff -c 9353 # compare against first parent
2756 hg diff -c 9353 # compare against first parent
2750 hg diff -r 9353^:9353 # same using revset syntax
2757 hg diff -r 9353^:9353 # same using revset syntax
2751 hg diff -r 9353^2:9353 # compare against the second parent
2758 hg diff -r 9353^2:9353 # compare against the second parent
2752
2759
2753 Returns 0 on success.
2760 Returns 0 on success.
2754 """
2761 """
2755
2762
2756 revs = opts.get('rev')
2763 revs = opts.get('rev')
2757 change = opts.get('change')
2764 change = opts.get('change')
2758 stat = opts.get('stat')
2765 stat = opts.get('stat')
2759 reverse = opts.get('reverse')
2766 reverse = opts.get('reverse')
2760
2767
2761 if revs and change:
2768 if revs and change:
2762 msg = _('cannot specify --rev and --change at the same time')
2769 msg = _('cannot specify --rev and --change at the same time')
2763 raise util.Abort(msg)
2770 raise util.Abort(msg)
2764 elif change:
2771 elif change:
2765 node2 = scmutil.revsingle(repo, change, None).node()
2772 node2 = scmutil.revsingle(repo, change, None).node()
2766 node1 = repo[node2].p1().node()
2773 node1 = repo[node2].p1().node()
2767 else:
2774 else:
2768 node1, node2 = scmutil.revpair(repo, revs)
2775 node1, node2 = scmutil.revpair(repo, revs)
2769
2776
2770 if reverse:
2777 if reverse:
2771 node1, node2 = node2, node1
2778 node1, node2 = node2, node1
2772
2779
2773 diffopts = patch.diffopts(ui, opts)
2780 diffopts = patch.diffopts(ui, opts)
2774 m = scmutil.match(repo[node2], pats, opts)
2781 m = scmutil.match(repo[node2], pats, opts)
2775 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2782 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
2776 listsubrepos=opts.get('subrepos'))
2783 listsubrepos=opts.get('subrepos'))
2777
2784
2778 @command('^export',
2785 @command('^export',
2779 [('o', 'output', '',
2786 [('o', 'output', '',
2780 _('print output to file with formatted name'), _('FORMAT')),
2787 _('print output to file with formatted name'), _('FORMAT')),
2781 ('', 'switch-parent', None, _('diff against the second parent')),
2788 ('', 'switch-parent', None, _('diff against the second parent')),
2782 ('r', 'rev', [], _('revisions to export'), _('REV')),
2789 ('r', 'rev', [], _('revisions to export'), _('REV')),
2783 ] + diffopts,
2790 ] + diffopts,
2784 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2791 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
2785 def export(ui, repo, *changesets, **opts):
2792 def export(ui, repo, *changesets, **opts):
2786 """dump the header and diffs for one or more changesets
2793 """dump the header and diffs for one or more changesets
2787
2794
2788 Print the changeset header and diffs for one or more revisions.
2795 Print the changeset header and diffs for one or more revisions.
2789 If no revision is given, the parent of the working directory is used.
2796 If no revision is given, the parent of the working directory is used.
2790
2797
2791 The information shown in the changeset header is: author, date,
2798 The information shown in the changeset header is: author, date,
2792 branch name (if non-default), changeset hash, parent(s) and commit
2799 branch name (if non-default), changeset hash, parent(s) and commit
2793 comment.
2800 comment.
2794
2801
2795 .. note::
2802 .. note::
2796
2803
2797 export may generate unexpected diff output for merge
2804 export may generate unexpected diff output for merge
2798 changesets, as it will compare the merge changeset against its
2805 changesets, as it will compare the merge changeset against its
2799 first parent only.
2806 first parent only.
2800
2807
2801 Output may be to a file, in which case the name of the file is
2808 Output may be to a file, in which case the name of the file is
2802 given using a format string. The formatting rules are as follows:
2809 given using a format string. The formatting rules are as follows:
2803
2810
2804 :``%%``: literal "%" character
2811 :``%%``: literal "%" character
2805 :``%H``: changeset hash (40 hexadecimal digits)
2812 :``%H``: changeset hash (40 hexadecimal digits)
2806 :``%N``: number of patches being generated
2813 :``%N``: number of patches being generated
2807 :``%R``: changeset revision number
2814 :``%R``: changeset revision number
2808 :``%b``: basename of the exporting repository
2815 :``%b``: basename of the exporting repository
2809 :``%h``: short-form changeset hash (12 hexadecimal digits)
2816 :``%h``: short-form changeset hash (12 hexadecimal digits)
2810 :``%m``: first line of the commit message (only alphanumeric characters)
2817 :``%m``: first line of the commit message (only alphanumeric characters)
2811 :``%n``: zero-padded sequence number, starting at 1
2818 :``%n``: zero-padded sequence number, starting at 1
2812 :``%r``: zero-padded changeset revision number
2819 :``%r``: zero-padded changeset revision number
2813
2820
2814 Without the -a/--text option, export will avoid generating diffs
2821 Without the -a/--text option, export will avoid generating diffs
2815 of files it detects as binary. With -a, export will generate a
2822 of files it detects as binary. With -a, export will generate a
2816 diff anyway, probably with undesirable results.
2823 diff anyway, probably with undesirable results.
2817
2824
2818 Use the -g/--git option to generate diffs in the git extended diff
2825 Use the -g/--git option to generate diffs in the git extended diff
2819 format. See :hg:`help diffs` for more information.
2826 format. See :hg:`help diffs` for more information.
2820
2827
2821 With the --switch-parent option, the diff will be against the
2828 With the --switch-parent option, the diff will be against the
2822 second parent. It can be useful to review a merge.
2829 second parent. It can be useful to review a merge.
2823
2830
2824 .. container:: verbose
2831 .. container:: verbose
2825
2832
2826 Examples:
2833 Examples:
2827
2834
2828 - use export and import to transplant a bugfix to the current
2835 - use export and import to transplant a bugfix to the current
2829 branch::
2836 branch::
2830
2837
2831 hg export -r 9353 | hg import -
2838 hg export -r 9353 | hg import -
2832
2839
2833 - export all the changesets between two revisions to a file with
2840 - export all the changesets between two revisions to a file with
2834 rename information::
2841 rename information::
2835
2842
2836 hg export --git -r 123:150 > changes.txt
2843 hg export --git -r 123:150 > changes.txt
2837
2844
2838 - split outgoing changes into a series of patches with
2845 - split outgoing changes into a series of patches with
2839 descriptive names::
2846 descriptive names::
2840
2847
2841 hg export -r "outgoing()" -o "%n-%m.patch"
2848 hg export -r "outgoing()" -o "%n-%m.patch"
2842
2849
2843 Returns 0 on success.
2850 Returns 0 on success.
2844 """
2851 """
2845 changesets += tuple(opts.get('rev', []))
2852 changesets += tuple(opts.get('rev', []))
2846 if not changesets:
2853 if not changesets:
2847 changesets = ['.']
2854 changesets = ['.']
2848 revs = scmutil.revrange(repo, changesets)
2855 revs = scmutil.revrange(repo, changesets)
2849 if not revs:
2856 if not revs:
2850 raise util.Abort(_("export requires at least one changeset"))
2857 raise util.Abort(_("export requires at least one changeset"))
2851 if len(revs) > 1:
2858 if len(revs) > 1:
2852 ui.note(_('exporting patches:\n'))
2859 ui.note(_('exporting patches:\n'))
2853 else:
2860 else:
2854 ui.note(_('exporting patch:\n'))
2861 ui.note(_('exporting patch:\n'))
2855 cmdutil.export(repo, revs, template=opts.get('output'),
2862 cmdutil.export(repo, revs, template=opts.get('output'),
2856 switch_parent=opts.get('switch_parent'),
2863 switch_parent=opts.get('switch_parent'),
2857 opts=patch.diffopts(ui, opts))
2864 opts=patch.diffopts(ui, opts))
2858
2865
2859 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2866 @command('^forget', walkopts, _('[OPTION]... FILE...'))
2860 def forget(ui, repo, *pats, **opts):
2867 def forget(ui, repo, *pats, **opts):
2861 """forget the specified files on the next commit
2868 """forget the specified files on the next commit
2862
2869
2863 Mark the specified files so they will no longer be tracked
2870 Mark the specified files so they will no longer be tracked
2864 after the next commit.
2871 after the next commit.
2865
2872
2866 This only removes files from the current branch, not from the
2873 This only removes files from the current branch, not from the
2867 entire project history, and it does not delete them from the
2874 entire project history, and it does not delete them from the
2868 working directory.
2875 working directory.
2869
2876
2870 To undo a forget before the next commit, see :hg:`add`.
2877 To undo a forget before the next commit, see :hg:`add`.
2871
2878
2872 .. container:: verbose
2879 .. container:: verbose
2873
2880
2874 Examples:
2881 Examples:
2875
2882
2876 - forget newly-added binary files::
2883 - forget newly-added binary files::
2877
2884
2878 hg forget "set:added() and binary()"
2885 hg forget "set:added() and binary()"
2879
2886
2880 - forget files that would be excluded by .hgignore::
2887 - forget files that would be excluded by .hgignore::
2881
2888
2882 hg forget "set:hgignore()"
2889 hg forget "set:hgignore()"
2883
2890
2884 Returns 0 on success.
2891 Returns 0 on success.
2885 """
2892 """
2886
2893
2887 if not pats:
2894 if not pats:
2888 raise util.Abort(_('no files specified'))
2895 raise util.Abort(_('no files specified'))
2889
2896
2890 m = scmutil.match(repo[None], pats, opts)
2897 m = scmutil.match(repo[None], pats, opts)
2891 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2898 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
2892 return rejected and 1 or 0
2899 return rejected and 1 or 0
2893
2900
2894 @command(
2901 @command(
2895 'graft',
2902 'graft',
2896 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2903 [('r', 'rev', [], _('revisions to graft'), _('REV')),
2897 ('c', 'continue', False, _('resume interrupted graft')),
2904 ('c', 'continue', False, _('resume interrupted graft')),
2898 ('e', 'edit', False, _('invoke editor on commit messages')),
2905 ('e', 'edit', False, _('invoke editor on commit messages')),
2899 ('', 'log', None, _('append graft info to log message')),
2906 ('', 'log', None, _('append graft info to log message')),
2900 ('D', 'currentdate', False,
2907 ('D', 'currentdate', False,
2901 _('record the current date as commit date')),
2908 _('record the current date as commit date')),
2902 ('U', 'currentuser', False,
2909 ('U', 'currentuser', False,
2903 _('record the current user as committer'), _('DATE'))]
2910 _('record the current user as committer'), _('DATE'))]
2904 + commitopts2 + mergetoolopts + dryrunopts,
2911 + commitopts2 + mergetoolopts + dryrunopts,
2905 _('[OPTION]... [-r] REV...'))
2912 _('[OPTION]... [-r] REV...'))
2906 def graft(ui, repo, *revs, **opts):
2913 def graft(ui, repo, *revs, **opts):
2907 '''copy changes from other branches onto the current branch
2914 '''copy changes from other branches onto the current branch
2908
2915
2909 This command uses Mercurial's merge logic to copy individual
2916 This command uses Mercurial's merge logic to copy individual
2910 changes from other branches without merging branches in the
2917 changes from other branches without merging branches in the
2911 history graph. This is sometimes known as 'backporting' or
2918 history graph. This is sometimes known as 'backporting' or
2912 'cherry-picking'. By default, graft will copy user, date, and
2919 'cherry-picking'. By default, graft will copy user, date, and
2913 description from the source changesets.
2920 description from the source changesets.
2914
2921
2915 Changesets that are ancestors of the current revision, that have
2922 Changesets that are ancestors of the current revision, that have
2916 already been grafted, or that are merges will be skipped.
2923 already been grafted, or that are merges will be skipped.
2917
2924
2918 If --log is specified, log messages will have a comment appended
2925 If --log is specified, log messages will have a comment appended
2919 of the form::
2926 of the form::
2920
2927
2921 (grafted from CHANGESETHASH)
2928 (grafted from CHANGESETHASH)
2922
2929
2923 If a graft merge results in conflicts, the graft process is
2930 If a graft merge results in conflicts, the graft process is
2924 interrupted so that the current merge can be manually resolved.
2931 interrupted so that the current merge can be manually resolved.
2925 Once all conflicts are addressed, the graft process can be
2932 Once all conflicts are addressed, the graft process can be
2926 continued with the -c/--continue option.
2933 continued with the -c/--continue option.
2927
2934
2928 .. note::
2935 .. note::
2929
2936
2930 The -c/--continue option does not reapply earlier options.
2937 The -c/--continue option does not reapply earlier options.
2931
2938
2932 .. container:: verbose
2939 .. container:: verbose
2933
2940
2934 Examples:
2941 Examples:
2935
2942
2936 - copy a single change to the stable branch and edit its description::
2943 - copy a single change to the stable branch and edit its description::
2937
2944
2938 hg update stable
2945 hg update stable
2939 hg graft --edit 9393
2946 hg graft --edit 9393
2940
2947
2941 - graft a range of changesets with one exception, updating dates::
2948 - graft a range of changesets with one exception, updating dates::
2942
2949
2943 hg graft -D "2085::2093 and not 2091"
2950 hg graft -D "2085::2093 and not 2091"
2944
2951
2945 - continue a graft after resolving conflicts::
2952 - continue a graft after resolving conflicts::
2946
2953
2947 hg graft -c
2954 hg graft -c
2948
2955
2949 - show the source of a grafted changeset::
2956 - show the source of a grafted changeset::
2950
2957
2951 hg log --debug -r .
2958 hg log --debug -r .
2952
2959
2953 Returns 0 on successful completion.
2960 Returns 0 on successful completion.
2954 '''
2961 '''
2955
2962
2956 revs = list(revs)
2963 revs = list(revs)
2957 revs.extend(opts['rev'])
2964 revs.extend(opts['rev'])
2958
2965
2959 if not opts.get('user') and opts.get('currentuser'):
2966 if not opts.get('user') and opts.get('currentuser'):
2960 opts['user'] = ui.username()
2967 opts['user'] = ui.username()
2961 if not opts.get('date') and opts.get('currentdate'):
2968 if not opts.get('date') and opts.get('currentdate'):
2962 opts['date'] = "%d %d" % util.makedate()
2969 opts['date'] = "%d %d" % util.makedate()
2963
2970
2964 editor = None
2971 editor = None
2965 if opts.get('edit'):
2972 if opts.get('edit'):
2966 editor = cmdutil.commitforceeditor
2973 editor = cmdutil.commitforceeditor
2967
2974
2968 cont = False
2975 cont = False
2969 if opts['continue']:
2976 if opts['continue']:
2970 cont = True
2977 cont = True
2971 if revs:
2978 if revs:
2972 raise util.Abort(_("can't specify --continue and revisions"))
2979 raise util.Abort(_("can't specify --continue and revisions"))
2973 # read in unfinished revisions
2980 # read in unfinished revisions
2974 try:
2981 try:
2975 nodes = repo.opener.read('graftstate').splitlines()
2982 nodes = repo.opener.read('graftstate').splitlines()
2976 revs = [repo[node].rev() for node in nodes]
2983 revs = [repo[node].rev() for node in nodes]
2977 except IOError, inst:
2984 except IOError, inst:
2978 if inst.errno != errno.ENOENT:
2985 if inst.errno != errno.ENOENT:
2979 raise
2986 raise
2980 raise util.Abort(_("no graft state found, can't continue"))
2987 raise util.Abort(_("no graft state found, can't continue"))
2981 else:
2988 else:
2982 cmdutil.checkunfinished(repo)
2989 cmdutil.checkunfinished(repo)
2983 cmdutil.bailifchanged(repo)
2990 cmdutil.bailifchanged(repo)
2984 if not revs:
2991 if not revs:
2985 raise util.Abort(_('no revisions specified'))
2992 raise util.Abort(_('no revisions specified'))
2986 revs = scmutil.revrange(repo, revs)
2993 revs = scmutil.revrange(repo, revs)
2987
2994
2988 # check for merges
2995 # check for merges
2989 for rev in repo.revs('%ld and merge()', revs):
2996 for rev in repo.revs('%ld and merge()', revs):
2990 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2997 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
2991 revs.remove(rev)
2998 revs.remove(rev)
2992 if not revs:
2999 if not revs:
2993 return -1
3000 return -1
2994
3001
2995 # check for ancestors of dest branch
3002 # check for ancestors of dest branch
2996 crev = repo['.'].rev()
3003 crev = repo['.'].rev()
2997 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3004 ancestors = repo.changelog.ancestors([crev], inclusive=True)
2998 # don't mutate while iterating, create a copy
3005 # don't mutate while iterating, create a copy
2999 for rev in list(revs):
3006 for rev in list(revs):
3000 if rev in ancestors:
3007 if rev in ancestors:
3001 ui.warn(_('skipping ancestor revision %s\n') % rev)
3008 ui.warn(_('skipping ancestor revision %s\n') % rev)
3002 revs.remove(rev)
3009 revs.remove(rev)
3003 if not revs:
3010 if not revs:
3004 return -1
3011 return -1
3005
3012
3006 # analyze revs for earlier grafts
3013 # analyze revs for earlier grafts
3007 ids = {}
3014 ids = {}
3008 for ctx in repo.set("%ld", revs):
3015 for ctx in repo.set("%ld", revs):
3009 ids[ctx.hex()] = ctx.rev()
3016 ids[ctx.hex()] = ctx.rev()
3010 n = ctx.extra().get('source')
3017 n = ctx.extra().get('source')
3011 if n:
3018 if n:
3012 ids[n] = ctx.rev()
3019 ids[n] = ctx.rev()
3013
3020
3014 # check ancestors for earlier grafts
3021 # check ancestors for earlier grafts
3015 ui.debug('scanning for duplicate grafts\n')
3022 ui.debug('scanning for duplicate grafts\n')
3016
3023
3017 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3024 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3018 ctx = repo[rev]
3025 ctx = repo[rev]
3019 n = ctx.extra().get('source')
3026 n = ctx.extra().get('source')
3020 if n in ids:
3027 if n in ids:
3021 r = repo[n].rev()
3028 r = repo[n].rev()
3022 if r in revs:
3029 if r in revs:
3023 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3030 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3024 % (r, rev))
3031 % (r, rev))
3025 revs.remove(r)
3032 revs.remove(r)
3026 elif ids[n] in revs:
3033 elif ids[n] in revs:
3027 ui.warn(_('skipping already grafted revision %s '
3034 ui.warn(_('skipping already grafted revision %s '
3028 '(%s also has origin %d)\n') % (ids[n], rev, r))
3035 '(%s also has origin %d)\n') % (ids[n], rev, r))
3029 revs.remove(ids[n])
3036 revs.remove(ids[n])
3030 elif ctx.hex() in ids:
3037 elif ctx.hex() in ids:
3031 r = ids[ctx.hex()]
3038 r = ids[ctx.hex()]
3032 ui.warn(_('skipping already grafted revision %s '
3039 ui.warn(_('skipping already grafted revision %s '
3033 '(was grafted from %d)\n') % (r, rev))
3040 '(was grafted from %d)\n') % (r, rev))
3034 revs.remove(r)
3041 revs.remove(r)
3035 if not revs:
3042 if not revs:
3036 return -1
3043 return -1
3037
3044
3038 wlock = repo.wlock()
3045 wlock = repo.wlock()
3039 try:
3046 try:
3040 current = repo['.']
3047 current = repo['.']
3041 for pos, ctx in enumerate(repo.set("%ld", revs)):
3048 for pos, ctx in enumerate(repo.set("%ld", revs)):
3042
3049
3043 ui.status(_('grafting revision %s\n') % ctx.rev())
3050 ui.status(_('grafting revision %s\n') % ctx.rev())
3044 if opts.get('dry_run'):
3051 if opts.get('dry_run'):
3045 continue
3052 continue
3046
3053
3047 source = ctx.extra().get('source')
3054 source = ctx.extra().get('source')
3048 if not source:
3055 if not source:
3049 source = ctx.hex()
3056 source = ctx.hex()
3050 extra = {'source': source}
3057 extra = {'source': source}
3051 user = ctx.user()
3058 user = ctx.user()
3052 if opts.get('user'):
3059 if opts.get('user'):
3053 user = opts['user']
3060 user = opts['user']
3054 date = ctx.date()
3061 date = ctx.date()
3055 if opts.get('date'):
3062 if opts.get('date'):
3056 date = opts['date']
3063 date = opts['date']
3057 message = ctx.description()
3064 message = ctx.description()
3058 if opts.get('log'):
3065 if opts.get('log'):
3059 message += '\n(grafted from %s)' % ctx.hex()
3066 message += '\n(grafted from %s)' % ctx.hex()
3060
3067
3061 # we don't merge the first commit when continuing
3068 # we don't merge the first commit when continuing
3062 if not cont:
3069 if not cont:
3063 # perform the graft merge with p1(rev) as 'ancestor'
3070 # perform the graft merge with p1(rev) as 'ancestor'
3064 try:
3071 try:
3065 # ui.forcemerge is an internal variable, do not document
3072 # ui.forcemerge is an internal variable, do not document
3066 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3073 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3067 stats = mergemod.update(repo, ctx.node(), True, True, False,
3074 stats = mergemod.update(repo, ctx.node(), True, True, False,
3068 ctx.p1().node())
3075 ctx.p1().node())
3069 finally:
3076 finally:
3070 repo.ui.setconfig('ui', 'forcemerge', '')
3077 repo.ui.setconfig('ui', 'forcemerge', '')
3071 # report any conflicts
3078 # report any conflicts
3072 if stats and stats[3] > 0:
3079 if stats and stats[3] > 0:
3073 # write out state for --continue
3080 # write out state for --continue
3074 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3081 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3075 repo.opener.write('graftstate', ''.join(nodelines))
3082 repo.opener.write('graftstate', ''.join(nodelines))
3076 raise util.Abort(
3083 raise util.Abort(
3077 _("unresolved conflicts, can't continue"),
3084 _("unresolved conflicts, can't continue"),
3078 hint=_('use hg resolve and hg graft --continue'))
3085 hint=_('use hg resolve and hg graft --continue'))
3079 else:
3086 else:
3080 cont = False
3087 cont = False
3081
3088
3082 # drop the second merge parent
3089 # drop the second merge parent
3083 repo.setparents(current.node(), nullid)
3090 repo.setparents(current.node(), nullid)
3084 repo.dirstate.write()
3091 repo.dirstate.write()
3085 # fix up dirstate for copies and renames
3092 # fix up dirstate for copies and renames
3086 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3093 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3087
3094
3088 # commit
3095 # commit
3089 node = repo.commit(text=message, user=user,
3096 node = repo.commit(text=message, user=user,
3090 date=date, extra=extra, editor=editor)
3097 date=date, extra=extra, editor=editor)
3091 if node is None:
3098 if node is None:
3092 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3099 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3093 else:
3100 else:
3094 current = repo[node]
3101 current = repo[node]
3095 finally:
3102 finally:
3096 wlock.release()
3103 wlock.release()
3097
3104
3098 # remove state when we complete successfully
3105 # remove state when we complete successfully
3099 if not opts.get('dry_run'):
3106 if not opts.get('dry_run'):
3100 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3107 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3101
3108
3102 return 0
3109 return 0
3103
3110
3104 @command('grep',
3111 @command('grep',
3105 [('0', 'print0', None, _('end fields with NUL')),
3112 [('0', 'print0', None, _('end fields with NUL')),
3106 ('', 'all', None, _('print all revisions that match')),
3113 ('', 'all', None, _('print all revisions that match')),
3107 ('a', 'text', None, _('treat all files as text')),
3114 ('a', 'text', None, _('treat all files as text')),
3108 ('f', 'follow', None,
3115 ('f', 'follow', None,
3109 _('follow changeset history,'
3116 _('follow changeset history,'
3110 ' or file history across copies and renames')),
3117 ' or file history across copies and renames')),
3111 ('i', 'ignore-case', None, _('ignore case when matching')),
3118 ('i', 'ignore-case', None, _('ignore case when matching')),
3112 ('l', 'files-with-matches', None,
3119 ('l', 'files-with-matches', None,
3113 _('print only filenames and revisions that match')),
3120 _('print only filenames and revisions that match')),
3114 ('n', 'line-number', None, _('print matching line numbers')),
3121 ('n', 'line-number', None, _('print matching line numbers')),
3115 ('r', 'rev', [],
3122 ('r', 'rev', [],
3116 _('only search files changed within revision range'), _('REV')),
3123 _('only search files changed within revision range'), _('REV')),
3117 ('u', 'user', None, _('list the author (long with -v)')),
3124 ('u', 'user', None, _('list the author (long with -v)')),
3118 ('d', 'date', None, _('list the date (short with -q)')),
3125 ('d', 'date', None, _('list the date (short with -q)')),
3119 ] + walkopts,
3126 ] + walkopts,
3120 _('[OPTION]... PATTERN [FILE]...'))
3127 _('[OPTION]... PATTERN [FILE]...'))
3121 def grep(ui, repo, pattern, *pats, **opts):
3128 def grep(ui, repo, pattern, *pats, **opts):
3122 """search for a pattern in specified files and revisions
3129 """search for a pattern in specified files and revisions
3123
3130
3124 Search revisions of files for a regular expression.
3131 Search revisions of files for a regular expression.
3125
3132
3126 This command behaves differently than Unix grep. It only accepts
3133 This command behaves differently than Unix grep. It only accepts
3127 Python/Perl regexps. It searches repository history, not the
3134 Python/Perl regexps. It searches repository history, not the
3128 working directory. It always prints the revision number in which a
3135 working directory. It always prints the revision number in which a
3129 match appears.
3136 match appears.
3130
3137
3131 By default, grep only prints output for the first revision of a
3138 By default, grep only prints output for the first revision of a
3132 file in which it finds a match. To get it to print every revision
3139 file in which it finds a match. To get it to print every revision
3133 that contains a change in match status ("-" for a match that
3140 that contains a change in match status ("-" for a match that
3134 becomes a non-match, or "+" for a non-match that becomes a match),
3141 becomes a non-match, or "+" for a non-match that becomes a match),
3135 use the --all flag.
3142 use the --all flag.
3136
3143
3137 Returns 0 if a match is found, 1 otherwise.
3144 Returns 0 if a match is found, 1 otherwise.
3138 """
3145 """
3139 reflags = re.M
3146 reflags = re.M
3140 if opts.get('ignore_case'):
3147 if opts.get('ignore_case'):
3141 reflags |= re.I
3148 reflags |= re.I
3142 try:
3149 try:
3143 regexp = util.compilere(pattern, reflags)
3150 regexp = util.compilere(pattern, reflags)
3144 except re.error, inst:
3151 except re.error, inst:
3145 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3152 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3146 return 1
3153 return 1
3147 sep, eol = ':', '\n'
3154 sep, eol = ':', '\n'
3148 if opts.get('print0'):
3155 if opts.get('print0'):
3149 sep = eol = '\0'
3156 sep = eol = '\0'
3150
3157
3151 getfile = util.lrucachefunc(repo.file)
3158 getfile = util.lrucachefunc(repo.file)
3152
3159
3153 def matchlines(body):
3160 def matchlines(body):
3154 begin = 0
3161 begin = 0
3155 linenum = 0
3162 linenum = 0
3156 while begin < len(body):
3163 while begin < len(body):
3157 match = regexp.search(body, begin)
3164 match = regexp.search(body, begin)
3158 if not match:
3165 if not match:
3159 break
3166 break
3160 mstart, mend = match.span()
3167 mstart, mend = match.span()
3161 linenum += body.count('\n', begin, mstart) + 1
3168 linenum += body.count('\n', begin, mstart) + 1
3162 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3169 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3163 begin = body.find('\n', mend) + 1 or len(body) + 1
3170 begin = body.find('\n', mend) + 1 or len(body) + 1
3164 lend = begin - 1
3171 lend = begin - 1
3165 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3172 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3166
3173
3167 class linestate(object):
3174 class linestate(object):
3168 def __init__(self, line, linenum, colstart, colend):
3175 def __init__(self, line, linenum, colstart, colend):
3169 self.line = line
3176 self.line = line
3170 self.linenum = linenum
3177 self.linenum = linenum
3171 self.colstart = colstart
3178 self.colstart = colstart
3172 self.colend = colend
3179 self.colend = colend
3173
3180
3174 def __hash__(self):
3181 def __hash__(self):
3175 return hash((self.linenum, self.line))
3182 return hash((self.linenum, self.line))
3176
3183
3177 def __eq__(self, other):
3184 def __eq__(self, other):
3178 return self.line == other.line
3185 return self.line == other.line
3179
3186
3180 matches = {}
3187 matches = {}
3181 copies = {}
3188 copies = {}
3182 def grepbody(fn, rev, body):
3189 def grepbody(fn, rev, body):
3183 matches[rev].setdefault(fn, [])
3190 matches[rev].setdefault(fn, [])
3184 m = matches[rev][fn]
3191 m = matches[rev][fn]
3185 for lnum, cstart, cend, line in matchlines(body):
3192 for lnum, cstart, cend, line in matchlines(body):
3186 s = linestate(line, lnum, cstart, cend)
3193 s = linestate(line, lnum, cstart, cend)
3187 m.append(s)
3194 m.append(s)
3188
3195
3189 def difflinestates(a, b):
3196 def difflinestates(a, b):
3190 sm = difflib.SequenceMatcher(None, a, b)
3197 sm = difflib.SequenceMatcher(None, a, b)
3191 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3198 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3192 if tag == 'insert':
3199 if tag == 'insert':
3193 for i in xrange(blo, bhi):
3200 for i in xrange(blo, bhi):
3194 yield ('+', b[i])
3201 yield ('+', b[i])
3195 elif tag == 'delete':
3202 elif tag == 'delete':
3196 for i in xrange(alo, ahi):
3203 for i in xrange(alo, ahi):
3197 yield ('-', a[i])
3204 yield ('-', a[i])
3198 elif tag == 'replace':
3205 elif tag == 'replace':
3199 for i in xrange(alo, ahi):
3206 for i in xrange(alo, ahi):
3200 yield ('-', a[i])
3207 yield ('-', a[i])
3201 for i in xrange(blo, bhi):
3208 for i in xrange(blo, bhi):
3202 yield ('+', b[i])
3209 yield ('+', b[i])
3203
3210
3204 def display(fn, ctx, pstates, states):
3211 def display(fn, ctx, pstates, states):
3205 rev = ctx.rev()
3212 rev = ctx.rev()
3206 datefunc = ui.quiet and util.shortdate or util.datestr
3213 datefunc = ui.quiet and util.shortdate or util.datestr
3207 found = False
3214 found = False
3208 filerevmatches = {}
3215 filerevmatches = {}
3209 def binary():
3216 def binary():
3210 flog = getfile(fn)
3217 flog = getfile(fn)
3211 return util.binary(flog.read(ctx.filenode(fn)))
3218 return util.binary(flog.read(ctx.filenode(fn)))
3212
3219
3213 if opts.get('all'):
3220 if opts.get('all'):
3214 iter = difflinestates(pstates, states)
3221 iter = difflinestates(pstates, states)
3215 else:
3222 else:
3216 iter = [('', l) for l in states]
3223 iter = [('', l) for l in states]
3217 for change, l in iter:
3224 for change, l in iter:
3218 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3225 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3219 before, match, after = None, None, None
3226 before, match, after = None, None, None
3220
3227
3221 if opts.get('line_number'):
3228 if opts.get('line_number'):
3222 cols.append((str(l.linenum), 'grep.linenumber'))
3229 cols.append((str(l.linenum), 'grep.linenumber'))
3223 if opts.get('all'):
3230 if opts.get('all'):
3224 cols.append((change, 'grep.change'))
3231 cols.append((change, 'grep.change'))
3225 if opts.get('user'):
3232 if opts.get('user'):
3226 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3233 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3227 if opts.get('date'):
3234 if opts.get('date'):
3228 cols.append((datefunc(ctx.date()), 'grep.date'))
3235 cols.append((datefunc(ctx.date()), 'grep.date'))
3229 if opts.get('files_with_matches'):
3236 if opts.get('files_with_matches'):
3230 c = (fn, rev)
3237 c = (fn, rev)
3231 if c in filerevmatches:
3238 if c in filerevmatches:
3232 continue
3239 continue
3233 filerevmatches[c] = 1
3240 filerevmatches[c] = 1
3234 else:
3241 else:
3235 before = l.line[:l.colstart]
3242 before = l.line[:l.colstart]
3236 match = l.line[l.colstart:l.colend]
3243 match = l.line[l.colstart:l.colend]
3237 after = l.line[l.colend:]
3244 after = l.line[l.colend:]
3238 for col, label in cols[:-1]:
3245 for col, label in cols[:-1]:
3239 ui.write(col, label=label)
3246 ui.write(col, label=label)
3240 ui.write(sep, label='grep.sep')
3247 ui.write(sep, label='grep.sep')
3241 ui.write(cols[-1][0], label=cols[-1][1])
3248 ui.write(cols[-1][0], label=cols[-1][1])
3242 if before is not None:
3249 if before is not None:
3243 ui.write(sep, label='grep.sep')
3250 ui.write(sep, label='grep.sep')
3244 if not opts.get('text') and binary():
3251 if not opts.get('text') and binary():
3245 ui.write(" Binary file matches")
3252 ui.write(" Binary file matches")
3246 else:
3253 else:
3247 ui.write(before)
3254 ui.write(before)
3248 ui.write(match, label='grep.match')
3255 ui.write(match, label='grep.match')
3249 ui.write(after)
3256 ui.write(after)
3250 ui.write(eol)
3257 ui.write(eol)
3251 found = True
3258 found = True
3252 return found
3259 return found
3253
3260
3254 skip = {}
3261 skip = {}
3255 revfiles = {}
3262 revfiles = {}
3256 matchfn = scmutil.match(repo[None], pats, opts)
3263 matchfn = scmutil.match(repo[None], pats, opts)
3257 found = False
3264 found = False
3258 follow = opts.get('follow')
3265 follow = opts.get('follow')
3259
3266
3260 def prep(ctx, fns):
3267 def prep(ctx, fns):
3261 rev = ctx.rev()
3268 rev = ctx.rev()
3262 pctx = ctx.p1()
3269 pctx = ctx.p1()
3263 parent = pctx.rev()
3270 parent = pctx.rev()
3264 matches.setdefault(rev, {})
3271 matches.setdefault(rev, {})
3265 matches.setdefault(parent, {})
3272 matches.setdefault(parent, {})
3266 files = revfiles.setdefault(rev, [])
3273 files = revfiles.setdefault(rev, [])
3267 for fn in fns:
3274 for fn in fns:
3268 flog = getfile(fn)
3275 flog = getfile(fn)
3269 try:
3276 try:
3270 fnode = ctx.filenode(fn)
3277 fnode = ctx.filenode(fn)
3271 except error.LookupError:
3278 except error.LookupError:
3272 continue
3279 continue
3273
3280
3274 copied = flog.renamed(fnode)
3281 copied = flog.renamed(fnode)
3275 copy = follow and copied and copied[0]
3282 copy = follow and copied and copied[0]
3276 if copy:
3283 if copy:
3277 copies.setdefault(rev, {})[fn] = copy
3284 copies.setdefault(rev, {})[fn] = copy
3278 if fn in skip:
3285 if fn in skip:
3279 if copy:
3286 if copy:
3280 skip[copy] = True
3287 skip[copy] = True
3281 continue
3288 continue
3282 files.append(fn)
3289 files.append(fn)
3283
3290
3284 if fn not in matches[rev]:
3291 if fn not in matches[rev]:
3285 grepbody(fn, rev, flog.read(fnode))
3292 grepbody(fn, rev, flog.read(fnode))
3286
3293
3287 pfn = copy or fn
3294 pfn = copy or fn
3288 if pfn not in matches[parent]:
3295 if pfn not in matches[parent]:
3289 try:
3296 try:
3290 fnode = pctx.filenode(pfn)
3297 fnode = pctx.filenode(pfn)
3291 grepbody(pfn, parent, flog.read(fnode))
3298 grepbody(pfn, parent, flog.read(fnode))
3292 except error.LookupError:
3299 except error.LookupError:
3293 pass
3300 pass
3294
3301
3295 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3302 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3296 rev = ctx.rev()
3303 rev = ctx.rev()
3297 parent = ctx.p1().rev()
3304 parent = ctx.p1().rev()
3298 for fn in sorted(revfiles.get(rev, [])):
3305 for fn in sorted(revfiles.get(rev, [])):
3299 states = matches[rev][fn]
3306 states = matches[rev][fn]
3300 copy = copies.get(rev, {}).get(fn)
3307 copy = copies.get(rev, {}).get(fn)
3301 if fn in skip:
3308 if fn in skip:
3302 if copy:
3309 if copy:
3303 skip[copy] = True
3310 skip[copy] = True
3304 continue
3311 continue
3305 pstates = matches.get(parent, {}).get(copy or fn, [])
3312 pstates = matches.get(parent, {}).get(copy or fn, [])
3306 if pstates or states:
3313 if pstates or states:
3307 r = display(fn, ctx, pstates, states)
3314 r = display(fn, ctx, pstates, states)
3308 found = found or r
3315 found = found or r
3309 if r and not opts.get('all'):
3316 if r and not opts.get('all'):
3310 skip[fn] = True
3317 skip[fn] = True
3311 if copy:
3318 if copy:
3312 skip[copy] = True
3319 skip[copy] = True
3313 del matches[rev]
3320 del matches[rev]
3314 del revfiles[rev]
3321 del revfiles[rev]
3315
3322
3316 return not found
3323 return not found
3317
3324
3318 @command('heads',
3325 @command('heads',
3319 [('r', 'rev', '',
3326 [('r', 'rev', '',
3320 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3327 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3321 ('t', 'topo', False, _('show topological heads only')),
3328 ('t', 'topo', False, _('show topological heads only')),
3322 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3329 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3323 ('c', 'closed', False, _('show normal and closed branch heads')),
3330 ('c', 'closed', False, _('show normal and closed branch heads')),
3324 ] + templateopts,
3331 ] + templateopts,
3325 _('[-ct] [-r STARTREV] [REV]...'))
3332 _('[-ct] [-r STARTREV] [REV]...'))
3326 def heads(ui, repo, *branchrevs, **opts):
3333 def heads(ui, repo, *branchrevs, **opts):
3327 """show branch heads
3334 """show branch heads
3328
3335
3329 With no arguments, show all open branch heads in the repository.
3336 With no arguments, show all open branch heads in the repository.
3330 Branch heads are changesets that have no descendants on the
3337 Branch heads are changesets that have no descendants on the
3331 same branch. They are where development generally takes place and
3338 same branch. They are where development generally takes place and
3332 are the usual targets for update and merge operations.
3339 are the usual targets for update and merge operations.
3333
3340
3334 If one or more REVs are given, only open branch heads on the
3341 If one or more REVs are given, only open branch heads on the
3335 branches associated with the specified changesets are shown. This
3342 branches associated with the specified changesets are shown. This
3336 means that you can use :hg:`heads .` to see the heads on the
3343 means that you can use :hg:`heads .` to see the heads on the
3337 currently checked-out branch.
3344 currently checked-out branch.
3338
3345
3339 If -c/--closed is specified, also show branch heads marked closed
3346 If -c/--closed is specified, also show branch heads marked closed
3340 (see :hg:`commit --close-branch`).
3347 (see :hg:`commit --close-branch`).
3341
3348
3342 If STARTREV is specified, only those heads that are descendants of
3349 If STARTREV is specified, only those heads that are descendants of
3343 STARTREV will be displayed.
3350 STARTREV will be displayed.
3344
3351
3345 If -t/--topo is specified, named branch mechanics will be ignored and only
3352 If -t/--topo is specified, named branch mechanics will be ignored and only
3346 topological heads (changesets with no children) will be shown.
3353 topological heads (changesets with no children) will be shown.
3347
3354
3348 Returns 0 if matching heads are found, 1 if not.
3355 Returns 0 if matching heads are found, 1 if not.
3349 """
3356 """
3350
3357
3351 start = None
3358 start = None
3352 if 'rev' in opts:
3359 if 'rev' in opts:
3353 start = scmutil.revsingle(repo, opts['rev'], None).node()
3360 start = scmutil.revsingle(repo, opts['rev'], None).node()
3354
3361
3355 if opts.get('topo'):
3362 if opts.get('topo'):
3356 heads = [repo[h] for h in repo.heads(start)]
3363 heads = [repo[h] for h in repo.heads(start)]
3357 else:
3364 else:
3358 heads = []
3365 heads = []
3359 for branch in repo.branchmap():
3366 for branch in repo.branchmap():
3360 heads += repo.branchheads(branch, start, opts.get('closed'))
3367 heads += repo.branchheads(branch, start, opts.get('closed'))
3361 heads = [repo[h] for h in heads]
3368 heads = [repo[h] for h in heads]
3362
3369
3363 if branchrevs:
3370 if branchrevs:
3364 branches = set(repo[br].branch() for br in branchrevs)
3371 branches = set(repo[br].branch() for br in branchrevs)
3365 heads = [h for h in heads if h.branch() in branches]
3372 heads = [h for h in heads if h.branch() in branches]
3366
3373
3367 if opts.get('active') and branchrevs:
3374 if opts.get('active') and branchrevs:
3368 dagheads = repo.heads(start)
3375 dagheads = repo.heads(start)
3369 heads = [h for h in heads if h.node() in dagheads]
3376 heads = [h for h in heads if h.node() in dagheads]
3370
3377
3371 if branchrevs:
3378 if branchrevs:
3372 haveheads = set(h.branch() for h in heads)
3379 haveheads = set(h.branch() for h in heads)
3373 if branches - haveheads:
3380 if branches - haveheads:
3374 headless = ', '.join(b for b in branches - haveheads)
3381 headless = ', '.join(b for b in branches - haveheads)
3375 msg = _('no open branch heads found on branches %s')
3382 msg = _('no open branch heads found on branches %s')
3376 if opts.get('rev'):
3383 if opts.get('rev'):
3377 msg += _(' (started at %s)') % opts['rev']
3384 msg += _(' (started at %s)') % opts['rev']
3378 ui.warn((msg + '\n') % headless)
3385 ui.warn((msg + '\n') % headless)
3379
3386
3380 if not heads:
3387 if not heads:
3381 return 1
3388 return 1
3382
3389
3383 heads = sorted(heads, key=lambda x: -x.rev())
3390 heads = sorted(heads, key=lambda x: -x.rev())
3384 displayer = cmdutil.show_changeset(ui, repo, opts)
3391 displayer = cmdutil.show_changeset(ui, repo, opts)
3385 for ctx in heads:
3392 for ctx in heads:
3386 displayer.show(ctx)
3393 displayer.show(ctx)
3387 displayer.close()
3394 displayer.close()
3388
3395
3389 @command('help',
3396 @command('help',
3390 [('e', 'extension', None, _('show only help for extensions')),
3397 [('e', 'extension', None, _('show only help for extensions')),
3391 ('c', 'command', None, _('show only help for commands')),
3398 ('c', 'command', None, _('show only help for commands')),
3392 ('k', 'keyword', '', _('show topics matching keyword')),
3399 ('k', 'keyword', '', _('show topics matching keyword')),
3393 ],
3400 ],
3394 _('[-ec] [TOPIC]'))
3401 _('[-ec] [TOPIC]'))
3395 def help_(ui, name=None, **opts):
3402 def help_(ui, name=None, **opts):
3396 """show help for a given topic or a help overview
3403 """show help for a given topic or a help overview
3397
3404
3398 With no arguments, print a list of commands with short help messages.
3405 With no arguments, print a list of commands with short help messages.
3399
3406
3400 Given a topic, extension, or command name, print help for that
3407 Given a topic, extension, or command name, print help for that
3401 topic.
3408 topic.
3402
3409
3403 Returns 0 if successful.
3410 Returns 0 if successful.
3404 """
3411 """
3405
3412
3406 textwidth = min(ui.termwidth(), 80) - 2
3413 textwidth = min(ui.termwidth(), 80) - 2
3407
3414
3408 keep = ui.verbose and ['verbose'] or []
3415 keep = ui.verbose and ['verbose'] or []
3409 text = help.help_(ui, name, **opts)
3416 text = help.help_(ui, name, **opts)
3410
3417
3411 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3418 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3412 if 'verbose' in pruned:
3419 if 'verbose' in pruned:
3413 keep.append('omitted')
3420 keep.append('omitted')
3414 else:
3421 else:
3415 keep.append('notomitted')
3422 keep.append('notomitted')
3416 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3423 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3417 ui.write(formatted)
3424 ui.write(formatted)
3418
3425
3419
3426
3420 @command('identify|id',
3427 @command('identify|id',
3421 [('r', 'rev', '',
3428 [('r', 'rev', '',
3422 _('identify the specified revision'), _('REV')),
3429 _('identify the specified revision'), _('REV')),
3423 ('n', 'num', None, _('show local revision number')),
3430 ('n', 'num', None, _('show local revision number')),
3424 ('i', 'id', None, _('show global revision id')),
3431 ('i', 'id', None, _('show global revision id')),
3425 ('b', 'branch', None, _('show branch')),
3432 ('b', 'branch', None, _('show branch')),
3426 ('t', 'tags', None, _('show tags')),
3433 ('t', 'tags', None, _('show tags')),
3427 ('B', 'bookmarks', None, _('show bookmarks')),
3434 ('B', 'bookmarks', None, _('show bookmarks')),
3428 ] + remoteopts,
3435 ] + remoteopts,
3429 _('[-nibtB] [-r REV] [SOURCE]'))
3436 _('[-nibtB] [-r REV] [SOURCE]'))
3430 def identify(ui, repo, source=None, rev=None,
3437 def identify(ui, repo, source=None, rev=None,
3431 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3438 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3432 """identify the working copy or specified revision
3439 """identify the working copy or specified revision
3433
3440
3434 Print a summary identifying the repository state at REV using one or
3441 Print a summary identifying the repository state at REV using one or
3435 two parent hash identifiers, followed by a "+" if the working
3442 two parent hash identifiers, followed by a "+" if the working
3436 directory has uncommitted changes, the branch name (if not default),
3443 directory has uncommitted changes, the branch name (if not default),
3437 a list of tags, and a list of bookmarks.
3444 a list of tags, and a list of bookmarks.
3438
3445
3439 When REV is not given, print a summary of the current state of the
3446 When REV is not given, print a summary of the current state of the
3440 repository.
3447 repository.
3441
3448
3442 Specifying a path to a repository root or Mercurial bundle will
3449 Specifying a path to a repository root or Mercurial bundle will
3443 cause lookup to operate on that repository/bundle.
3450 cause lookup to operate on that repository/bundle.
3444
3451
3445 .. container:: verbose
3452 .. container:: verbose
3446
3453
3447 Examples:
3454 Examples:
3448
3455
3449 - generate a build identifier for the working directory::
3456 - generate a build identifier for the working directory::
3450
3457
3451 hg id --id > build-id.dat
3458 hg id --id > build-id.dat
3452
3459
3453 - find the revision corresponding to a tag::
3460 - find the revision corresponding to a tag::
3454
3461
3455 hg id -n -r 1.3
3462 hg id -n -r 1.3
3456
3463
3457 - check the most recent revision of a remote repository::
3464 - check the most recent revision of a remote repository::
3458
3465
3459 hg id -r tip http://selenic.com/hg/
3466 hg id -r tip http://selenic.com/hg/
3460
3467
3461 Returns 0 if successful.
3468 Returns 0 if successful.
3462 """
3469 """
3463
3470
3464 if not repo and not source:
3471 if not repo and not source:
3465 raise util.Abort(_("there is no Mercurial repository here "
3472 raise util.Abort(_("there is no Mercurial repository here "
3466 "(.hg not found)"))
3473 "(.hg not found)"))
3467
3474
3468 hexfunc = ui.debugflag and hex or short
3475 hexfunc = ui.debugflag and hex or short
3469 default = not (num or id or branch or tags or bookmarks)
3476 default = not (num or id or branch or tags or bookmarks)
3470 output = []
3477 output = []
3471 revs = []
3478 revs = []
3472
3479
3473 if source:
3480 if source:
3474 source, branches = hg.parseurl(ui.expandpath(source))
3481 source, branches = hg.parseurl(ui.expandpath(source))
3475 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3482 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3476 repo = peer.local()
3483 repo = peer.local()
3477 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3484 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3478
3485
3479 if not repo:
3486 if not repo:
3480 if num or branch or tags:
3487 if num or branch or tags:
3481 raise util.Abort(
3488 raise util.Abort(
3482 _("can't query remote revision number, branch, or tags"))
3489 _("can't query remote revision number, branch, or tags"))
3483 if not rev and revs:
3490 if not rev and revs:
3484 rev = revs[0]
3491 rev = revs[0]
3485 if not rev:
3492 if not rev:
3486 rev = "tip"
3493 rev = "tip"
3487
3494
3488 remoterev = peer.lookup(rev)
3495 remoterev = peer.lookup(rev)
3489 if default or id:
3496 if default or id:
3490 output = [hexfunc(remoterev)]
3497 output = [hexfunc(remoterev)]
3491
3498
3492 def getbms():
3499 def getbms():
3493 bms = []
3500 bms = []
3494
3501
3495 if 'bookmarks' in peer.listkeys('namespaces'):
3502 if 'bookmarks' in peer.listkeys('namespaces'):
3496 hexremoterev = hex(remoterev)
3503 hexremoterev = hex(remoterev)
3497 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3504 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3498 if bmr == hexremoterev]
3505 if bmr == hexremoterev]
3499
3506
3500 return sorted(bms)
3507 return sorted(bms)
3501
3508
3502 if bookmarks:
3509 if bookmarks:
3503 output.extend(getbms())
3510 output.extend(getbms())
3504 elif default and not ui.quiet:
3511 elif default and not ui.quiet:
3505 # multiple bookmarks for a single parent separated by '/'
3512 # multiple bookmarks for a single parent separated by '/'
3506 bm = '/'.join(getbms())
3513 bm = '/'.join(getbms())
3507 if bm:
3514 if bm:
3508 output.append(bm)
3515 output.append(bm)
3509 else:
3516 else:
3510 if not rev:
3517 if not rev:
3511 ctx = repo[None]
3518 ctx = repo[None]
3512 parents = ctx.parents()
3519 parents = ctx.parents()
3513 changed = ""
3520 changed = ""
3514 if default or id or num:
3521 if default or id or num:
3515 if (util.any(repo.status())
3522 if (util.any(repo.status())
3516 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3523 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3517 changed = '+'
3524 changed = '+'
3518 if default or id:
3525 if default or id:
3519 output = ["%s%s" %
3526 output = ["%s%s" %
3520 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3527 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3521 if num:
3528 if num:
3522 output.append("%s%s" %
3529 output.append("%s%s" %
3523 ('+'.join([str(p.rev()) for p in parents]), changed))
3530 ('+'.join([str(p.rev()) for p in parents]), changed))
3524 else:
3531 else:
3525 ctx = scmutil.revsingle(repo, rev)
3532 ctx = scmutil.revsingle(repo, rev)
3526 if default or id:
3533 if default or id:
3527 output = [hexfunc(ctx.node())]
3534 output = [hexfunc(ctx.node())]
3528 if num:
3535 if num:
3529 output.append(str(ctx.rev()))
3536 output.append(str(ctx.rev()))
3530
3537
3531 if default and not ui.quiet:
3538 if default and not ui.quiet:
3532 b = ctx.branch()
3539 b = ctx.branch()
3533 if b != 'default':
3540 if b != 'default':
3534 output.append("(%s)" % b)
3541 output.append("(%s)" % b)
3535
3542
3536 # multiple tags for a single parent separated by '/'
3543 # multiple tags for a single parent separated by '/'
3537 t = '/'.join(ctx.tags())
3544 t = '/'.join(ctx.tags())
3538 if t:
3545 if t:
3539 output.append(t)
3546 output.append(t)
3540
3547
3541 # multiple bookmarks for a single parent separated by '/'
3548 # multiple bookmarks for a single parent separated by '/'
3542 bm = '/'.join(ctx.bookmarks())
3549 bm = '/'.join(ctx.bookmarks())
3543 if bm:
3550 if bm:
3544 output.append(bm)
3551 output.append(bm)
3545 else:
3552 else:
3546 if branch:
3553 if branch:
3547 output.append(ctx.branch())
3554 output.append(ctx.branch())
3548
3555
3549 if tags:
3556 if tags:
3550 output.extend(ctx.tags())
3557 output.extend(ctx.tags())
3551
3558
3552 if bookmarks:
3559 if bookmarks:
3553 output.extend(ctx.bookmarks())
3560 output.extend(ctx.bookmarks())
3554
3561
3555 ui.write("%s\n" % ' '.join(output))
3562 ui.write("%s\n" % ' '.join(output))
3556
3563
3557 @command('import|patch',
3564 @command('import|patch',
3558 [('p', 'strip', 1,
3565 [('p', 'strip', 1,
3559 _('directory strip option for patch. This has the same '
3566 _('directory strip option for patch. This has the same '
3560 'meaning as the corresponding patch option'), _('NUM')),
3567 'meaning as the corresponding patch option'), _('NUM')),
3561 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3568 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3562 ('e', 'edit', False, _('invoke editor on commit messages')),
3569 ('e', 'edit', False, _('invoke editor on commit messages')),
3563 ('f', 'force', None,
3570 ('f', 'force', None,
3564 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3571 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3565 ('', 'no-commit', None,
3572 ('', 'no-commit', None,
3566 _("don't commit, just update the working directory")),
3573 _("don't commit, just update the working directory")),
3567 ('', 'bypass', None,
3574 ('', 'bypass', None,
3568 _("apply patch without touching the working directory")),
3575 _("apply patch without touching the working directory")),
3569 ('', 'exact', None,
3576 ('', 'exact', None,
3570 _('apply patch to the nodes from which it was generated')),
3577 _('apply patch to the nodes from which it was generated')),
3571 ('', 'import-branch', None,
3578 ('', 'import-branch', None,
3572 _('use any branch information in patch (implied by --exact)'))] +
3579 _('use any branch information in patch (implied by --exact)'))] +
3573 commitopts + commitopts2 + similarityopts,
3580 commitopts + commitopts2 + similarityopts,
3574 _('[OPTION]... PATCH...'))
3581 _('[OPTION]... PATCH...'))
3575 def import_(ui, repo, patch1=None, *patches, **opts):
3582 def import_(ui, repo, patch1=None, *patches, **opts):
3576 """import an ordered set of patches
3583 """import an ordered set of patches
3577
3584
3578 Import a list of patches and commit them individually (unless
3585 Import a list of patches and commit them individually (unless
3579 --no-commit is specified).
3586 --no-commit is specified).
3580
3587
3581 Because import first applies changes to the working directory,
3588 Because import first applies changes to the working directory,
3582 import will abort if there are outstanding changes.
3589 import will abort if there are outstanding changes.
3583
3590
3584 You can import a patch straight from a mail message. Even patches
3591 You can import a patch straight from a mail message. Even patches
3585 as attachments work (to use the body part, it must have type
3592 as attachments work (to use the body part, it must have type
3586 text/plain or text/x-patch). From and Subject headers of email
3593 text/plain or text/x-patch). From and Subject headers of email
3587 message are used as default committer and commit message. All
3594 message are used as default committer and commit message. All
3588 text/plain body parts before first diff are added to commit
3595 text/plain body parts before first diff are added to commit
3589 message.
3596 message.
3590
3597
3591 If the imported patch was generated by :hg:`export`, user and
3598 If the imported patch was generated by :hg:`export`, user and
3592 description from patch override values from message headers and
3599 description from patch override values from message headers and
3593 body. Values given on command line with -m/--message and -u/--user
3600 body. Values given on command line with -m/--message and -u/--user
3594 override these.
3601 override these.
3595
3602
3596 If --exact is specified, import will set the working directory to
3603 If --exact is specified, import will set the working directory to
3597 the parent of each patch before applying it, and will abort if the
3604 the parent of each patch before applying it, and will abort if the
3598 resulting changeset has a different ID than the one recorded in
3605 resulting changeset has a different ID than the one recorded in
3599 the patch. This may happen due to character set problems or other
3606 the patch. This may happen due to character set problems or other
3600 deficiencies in the text patch format.
3607 deficiencies in the text patch format.
3601
3608
3602 Use --bypass to apply and commit patches directly to the
3609 Use --bypass to apply and commit patches directly to the
3603 repository, not touching the working directory. Without --exact,
3610 repository, not touching the working directory. Without --exact,
3604 patches will be applied on top of the working directory parent
3611 patches will be applied on top of the working directory parent
3605 revision.
3612 revision.
3606
3613
3607 With -s/--similarity, hg will attempt to discover renames and
3614 With -s/--similarity, hg will attempt to discover renames and
3608 copies in the patch in the same way as :hg:`addremove`.
3615 copies in the patch in the same way as :hg:`addremove`.
3609
3616
3610 To read a patch from standard input, use "-" as the patch name. If
3617 To read a patch from standard input, use "-" as the patch name. If
3611 a URL is specified, the patch will be downloaded from it.
3618 a URL is specified, the patch will be downloaded from it.
3612 See :hg:`help dates` for a list of formats valid for -d/--date.
3619 See :hg:`help dates` for a list of formats valid for -d/--date.
3613
3620
3614 .. container:: verbose
3621 .. container:: verbose
3615
3622
3616 Examples:
3623 Examples:
3617
3624
3618 - import a traditional patch from a website and detect renames::
3625 - import a traditional patch from a website and detect renames::
3619
3626
3620 hg import -s 80 http://example.com/bugfix.patch
3627 hg import -s 80 http://example.com/bugfix.patch
3621
3628
3622 - import a changeset from an hgweb server::
3629 - import a changeset from an hgweb server::
3623
3630
3624 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3631 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3625
3632
3626 - import all the patches in an Unix-style mbox::
3633 - import all the patches in an Unix-style mbox::
3627
3634
3628 hg import incoming-patches.mbox
3635 hg import incoming-patches.mbox
3629
3636
3630 - attempt to exactly restore an exported changeset (not always
3637 - attempt to exactly restore an exported changeset (not always
3631 possible)::
3638 possible)::
3632
3639
3633 hg import --exact proposed-fix.patch
3640 hg import --exact proposed-fix.patch
3634
3641
3635 Returns 0 on success.
3642 Returns 0 on success.
3636 """
3643 """
3637
3644
3638 if not patch1:
3645 if not patch1:
3639 raise util.Abort(_('need at least one patch to import'))
3646 raise util.Abort(_('need at least one patch to import'))
3640
3647
3641 patches = (patch1,) + patches
3648 patches = (patch1,) + patches
3642
3649
3643 date = opts.get('date')
3650 date = opts.get('date')
3644 if date:
3651 if date:
3645 opts['date'] = util.parsedate(date)
3652 opts['date'] = util.parsedate(date)
3646
3653
3647 editor = cmdutil.commiteditor
3654 editor = cmdutil.commiteditor
3648 if opts.get('edit'):
3655 if opts.get('edit'):
3649 editor = cmdutil.commitforceeditor
3656 editor = cmdutil.commitforceeditor
3650
3657
3651 update = not opts.get('bypass')
3658 update = not opts.get('bypass')
3652 if not update and opts.get('no_commit'):
3659 if not update and opts.get('no_commit'):
3653 raise util.Abort(_('cannot use --no-commit with --bypass'))
3660 raise util.Abort(_('cannot use --no-commit with --bypass'))
3654 try:
3661 try:
3655 sim = float(opts.get('similarity') or 0)
3662 sim = float(opts.get('similarity') or 0)
3656 except ValueError:
3663 except ValueError:
3657 raise util.Abort(_('similarity must be a number'))
3664 raise util.Abort(_('similarity must be a number'))
3658 if sim < 0 or sim > 100:
3665 if sim < 0 or sim > 100:
3659 raise util.Abort(_('similarity must be between 0 and 100'))
3666 raise util.Abort(_('similarity must be between 0 and 100'))
3660 if sim and not update:
3667 if sim and not update:
3661 raise util.Abort(_('cannot use --similarity with --bypass'))
3668 raise util.Abort(_('cannot use --similarity with --bypass'))
3662
3669
3663 if update:
3670 if update:
3664 cmdutil.checkunfinished(repo)
3671 cmdutil.checkunfinished(repo)
3665 if (opts.get('exact') or not opts.get('force')) and update:
3672 if (opts.get('exact') or not opts.get('force')) and update:
3666 cmdutil.bailifchanged(repo)
3673 cmdutil.bailifchanged(repo)
3667
3674
3668 base = opts["base"]
3675 base = opts["base"]
3669 strip = opts["strip"]
3676 strip = opts["strip"]
3670 wlock = lock = tr = None
3677 wlock = lock = tr = None
3671 msgs = []
3678 msgs = []
3672
3679
3673 def tryone(ui, hunk, parents):
3680 def tryone(ui, hunk, parents):
3674 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3681 tmpname, message, user, date, branch, nodeid, p1, p2 = \
3675 patch.extract(ui, hunk)
3682 patch.extract(ui, hunk)
3676
3683
3677 if not tmpname:
3684 if not tmpname:
3678 return (None, None)
3685 return (None, None)
3679 msg = _('applied to working directory')
3686 msg = _('applied to working directory')
3680
3687
3681 try:
3688 try:
3682 cmdline_message = cmdutil.logmessage(ui, opts)
3689 cmdline_message = cmdutil.logmessage(ui, opts)
3683 if cmdline_message:
3690 if cmdline_message:
3684 # pickup the cmdline msg
3691 # pickup the cmdline msg
3685 message = cmdline_message
3692 message = cmdline_message
3686 elif message:
3693 elif message:
3687 # pickup the patch msg
3694 # pickup the patch msg
3688 message = message.strip()
3695 message = message.strip()
3689 else:
3696 else:
3690 # launch the editor
3697 # launch the editor
3691 message = None
3698 message = None
3692 ui.debug('message:\n%s\n' % message)
3699 ui.debug('message:\n%s\n' % message)
3693
3700
3694 if len(parents) == 1:
3701 if len(parents) == 1:
3695 parents.append(repo[nullid])
3702 parents.append(repo[nullid])
3696 if opts.get('exact'):
3703 if opts.get('exact'):
3697 if not nodeid or not p1:
3704 if not nodeid or not p1:
3698 raise util.Abort(_('not a Mercurial patch'))
3705 raise util.Abort(_('not a Mercurial patch'))
3699 p1 = repo[p1]
3706 p1 = repo[p1]
3700 p2 = repo[p2 or nullid]
3707 p2 = repo[p2 or nullid]
3701 elif p2:
3708 elif p2:
3702 try:
3709 try:
3703 p1 = repo[p1]
3710 p1 = repo[p1]
3704 p2 = repo[p2]
3711 p2 = repo[p2]
3705 # Without any options, consider p2 only if the
3712 # Without any options, consider p2 only if the
3706 # patch is being applied on top of the recorded
3713 # patch is being applied on top of the recorded
3707 # first parent.
3714 # first parent.
3708 if p1 != parents[0]:
3715 if p1 != parents[0]:
3709 p1 = parents[0]
3716 p1 = parents[0]
3710 p2 = repo[nullid]
3717 p2 = repo[nullid]
3711 except error.RepoError:
3718 except error.RepoError:
3712 p1, p2 = parents
3719 p1, p2 = parents
3713 else:
3720 else:
3714 p1, p2 = parents
3721 p1, p2 = parents
3715
3722
3716 n = None
3723 n = None
3717 if update:
3724 if update:
3718 if p1 != parents[0]:
3725 if p1 != parents[0]:
3719 hg.clean(repo, p1.node())
3726 hg.clean(repo, p1.node())
3720 if p2 != parents[1]:
3727 if p2 != parents[1]:
3721 repo.setparents(p1.node(), p2.node())
3728 repo.setparents(p1.node(), p2.node())
3722
3729
3723 if opts.get('exact') or opts.get('import_branch'):
3730 if opts.get('exact') or opts.get('import_branch'):
3724 repo.dirstate.setbranch(branch or 'default')
3731 repo.dirstate.setbranch(branch or 'default')
3725
3732
3726 files = set()
3733 files = set()
3727 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3734 patch.patch(ui, repo, tmpname, strip=strip, files=files,
3728 eolmode=None, similarity=sim / 100.0)
3735 eolmode=None, similarity=sim / 100.0)
3729 files = list(files)
3736 files = list(files)
3730 if opts.get('no_commit'):
3737 if opts.get('no_commit'):
3731 if message:
3738 if message:
3732 msgs.append(message)
3739 msgs.append(message)
3733 else:
3740 else:
3734 if opts.get('exact') or p2:
3741 if opts.get('exact') or p2:
3735 # If you got here, you either use --force and know what
3742 # If you got here, you either use --force and know what
3736 # you are doing or used --exact or a merge patch while
3743 # you are doing or used --exact or a merge patch while
3737 # being updated to its first parent.
3744 # being updated to its first parent.
3738 m = None
3745 m = None
3739 else:
3746 else:
3740 m = scmutil.matchfiles(repo, files or [])
3747 m = scmutil.matchfiles(repo, files or [])
3741 n = repo.commit(message, opts.get('user') or user,
3748 n = repo.commit(message, opts.get('user') or user,
3742 opts.get('date') or date, match=m,
3749 opts.get('date') or date, match=m,
3743 editor=editor)
3750 editor=editor)
3744 else:
3751 else:
3745 if opts.get('exact') or opts.get('import_branch'):
3752 if opts.get('exact') or opts.get('import_branch'):
3746 branch = branch or 'default'
3753 branch = branch or 'default'
3747 else:
3754 else:
3748 branch = p1.branch()
3755 branch = p1.branch()
3749 store = patch.filestore()
3756 store = patch.filestore()
3750 try:
3757 try:
3751 files = set()
3758 files = set()
3752 try:
3759 try:
3753 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3760 patch.patchrepo(ui, repo, p1, store, tmpname, strip,
3754 files, eolmode=None)
3761 files, eolmode=None)
3755 except patch.PatchError, e:
3762 except patch.PatchError, e:
3756 raise util.Abort(str(e))
3763 raise util.Abort(str(e))
3757 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3764 memctx = context.makememctx(repo, (p1.node(), p2.node()),
3758 message,
3765 message,
3759 opts.get('user') or user,
3766 opts.get('user') or user,
3760 opts.get('date') or date,
3767 opts.get('date') or date,
3761 branch, files, store,
3768 branch, files, store,
3762 editor=cmdutil.commiteditor)
3769 editor=cmdutil.commiteditor)
3763 repo.savecommitmessage(memctx.description())
3770 repo.savecommitmessage(memctx.description())
3764 n = memctx.commit()
3771 n = memctx.commit()
3765 finally:
3772 finally:
3766 store.close()
3773 store.close()
3767 if opts.get('exact') and hex(n) != nodeid:
3774 if opts.get('exact') and hex(n) != nodeid:
3768 raise util.Abort(_('patch is damaged or loses information'))
3775 raise util.Abort(_('patch is damaged or loses information'))
3769 if n:
3776 if n:
3770 # i18n: refers to a short changeset id
3777 # i18n: refers to a short changeset id
3771 msg = _('created %s') % short(n)
3778 msg = _('created %s') % short(n)
3772 return (msg, n)
3779 return (msg, n)
3773 finally:
3780 finally:
3774 os.unlink(tmpname)
3781 os.unlink(tmpname)
3775
3782
3776 try:
3783 try:
3777 try:
3784 try:
3778 wlock = repo.wlock()
3785 wlock = repo.wlock()
3779 if not opts.get('no_commit'):
3786 if not opts.get('no_commit'):
3780 lock = repo.lock()
3787 lock = repo.lock()
3781 tr = repo.transaction('import')
3788 tr = repo.transaction('import')
3782 parents = repo.parents()
3789 parents = repo.parents()
3783 for patchurl in patches:
3790 for patchurl in patches:
3784 if patchurl == '-':
3791 if patchurl == '-':
3785 ui.status(_('applying patch from stdin\n'))
3792 ui.status(_('applying patch from stdin\n'))
3786 patchfile = ui.fin
3793 patchfile = ui.fin
3787 patchurl = 'stdin' # for error message
3794 patchurl = 'stdin' # for error message
3788 else:
3795 else:
3789 patchurl = os.path.join(base, patchurl)
3796 patchurl = os.path.join(base, patchurl)
3790 ui.status(_('applying %s\n') % patchurl)
3797 ui.status(_('applying %s\n') % patchurl)
3791 patchfile = hg.openpath(ui, patchurl)
3798 patchfile = hg.openpath(ui, patchurl)
3792
3799
3793 haspatch = False
3800 haspatch = False
3794 for hunk in patch.split(patchfile):
3801 for hunk in patch.split(patchfile):
3795 (msg, node) = tryone(ui, hunk, parents)
3802 (msg, node) = tryone(ui, hunk, parents)
3796 if msg:
3803 if msg:
3797 haspatch = True
3804 haspatch = True
3798 ui.note(msg + '\n')
3805 ui.note(msg + '\n')
3799 if update or opts.get('exact'):
3806 if update or opts.get('exact'):
3800 parents = repo.parents()
3807 parents = repo.parents()
3801 else:
3808 else:
3802 parents = [repo[node]]
3809 parents = [repo[node]]
3803
3810
3804 if not haspatch:
3811 if not haspatch:
3805 raise util.Abort(_('%s: no diffs found') % patchurl)
3812 raise util.Abort(_('%s: no diffs found') % patchurl)
3806
3813
3807 if tr:
3814 if tr:
3808 tr.close()
3815 tr.close()
3809 if msgs:
3816 if msgs:
3810 repo.savecommitmessage('\n* * *\n'.join(msgs))
3817 repo.savecommitmessage('\n* * *\n'.join(msgs))
3811 except: # re-raises
3818 except: # re-raises
3812 # wlock.release() indirectly calls dirstate.write(): since
3819 # wlock.release() indirectly calls dirstate.write(): since
3813 # we're crashing, we do not want to change the working dir
3820 # we're crashing, we do not want to change the working dir
3814 # parent after all, so make sure it writes nothing
3821 # parent after all, so make sure it writes nothing
3815 repo.dirstate.invalidate()
3822 repo.dirstate.invalidate()
3816 raise
3823 raise
3817 finally:
3824 finally:
3818 if tr:
3825 if tr:
3819 tr.release()
3826 tr.release()
3820 release(lock, wlock)
3827 release(lock, wlock)
3821
3828
3822 @command('incoming|in',
3829 @command('incoming|in',
3823 [('f', 'force', None,
3830 [('f', 'force', None,
3824 _('run even if remote repository is unrelated')),
3831 _('run even if remote repository is unrelated')),
3825 ('n', 'newest-first', None, _('show newest record first')),
3832 ('n', 'newest-first', None, _('show newest record first')),
3826 ('', 'bundle', '',
3833 ('', 'bundle', '',
3827 _('file to store the bundles into'), _('FILE')),
3834 _('file to store the bundles into'), _('FILE')),
3828 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3835 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
3829 ('B', 'bookmarks', False, _("compare bookmarks")),
3836 ('B', 'bookmarks', False, _("compare bookmarks")),
3830 ('b', 'branch', [],
3837 ('b', 'branch', [],
3831 _('a specific branch you would like to pull'), _('BRANCH')),
3838 _('a specific branch you would like to pull'), _('BRANCH')),
3832 ] + logopts + remoteopts + subrepoopts,
3839 ] + logopts + remoteopts + subrepoopts,
3833 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3840 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
3834 def incoming(ui, repo, source="default", **opts):
3841 def incoming(ui, repo, source="default", **opts):
3835 """show new changesets found in source
3842 """show new changesets found in source
3836
3843
3837 Show new changesets found in the specified path/URL or the default
3844 Show new changesets found in the specified path/URL or the default
3838 pull location. These are the changesets that would have been pulled
3845 pull location. These are the changesets that would have been pulled
3839 if a pull at the time you issued this command.
3846 if a pull at the time you issued this command.
3840
3847
3841 For remote repository, using --bundle avoids downloading the
3848 For remote repository, using --bundle avoids downloading the
3842 changesets twice if the incoming is followed by a pull.
3849 changesets twice if the incoming is followed by a pull.
3843
3850
3844 See pull for valid source format details.
3851 See pull for valid source format details.
3845
3852
3846 Returns 0 if there are incoming changes, 1 otherwise.
3853 Returns 0 if there are incoming changes, 1 otherwise.
3847 """
3854 """
3848 if opts.get('graph'):
3855 if opts.get('graph'):
3849 cmdutil.checkunsupportedgraphflags([], opts)
3856 cmdutil.checkunsupportedgraphflags([], opts)
3850 def display(other, chlist, displayer):
3857 def display(other, chlist, displayer):
3851 revdag = cmdutil.graphrevs(other, chlist, opts)
3858 revdag = cmdutil.graphrevs(other, chlist, opts)
3852 showparents = [ctx.node() for ctx in repo[None].parents()]
3859 showparents = [ctx.node() for ctx in repo[None].parents()]
3853 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3860 cmdutil.displaygraph(ui, revdag, displayer, showparents,
3854 graphmod.asciiedges)
3861 graphmod.asciiedges)
3855
3862
3856 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3863 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
3857 return 0
3864 return 0
3858
3865
3859 if opts.get('bundle') and opts.get('subrepos'):
3866 if opts.get('bundle') and opts.get('subrepos'):
3860 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3867 raise util.Abort(_('cannot combine --bundle and --subrepos'))
3861
3868
3862 if opts.get('bookmarks'):
3869 if opts.get('bookmarks'):
3863 source, branches = hg.parseurl(ui.expandpath(source),
3870 source, branches = hg.parseurl(ui.expandpath(source),
3864 opts.get('branch'))
3871 opts.get('branch'))
3865 other = hg.peer(repo, opts, source)
3872 other = hg.peer(repo, opts, source)
3866 if 'bookmarks' not in other.listkeys('namespaces'):
3873 if 'bookmarks' not in other.listkeys('namespaces'):
3867 ui.warn(_("remote doesn't support bookmarks\n"))
3874 ui.warn(_("remote doesn't support bookmarks\n"))
3868 return 0
3875 return 0
3869 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3876 ui.status(_('comparing with %s\n') % util.hidepassword(source))
3870 return bookmarks.diff(ui, repo, other)
3877 return bookmarks.diff(ui, repo, other)
3871
3878
3872 repo._subtoppath = ui.expandpath(source)
3879 repo._subtoppath = ui.expandpath(source)
3873 try:
3880 try:
3874 return hg.incoming(ui, repo, source, opts)
3881 return hg.incoming(ui, repo, source, opts)
3875 finally:
3882 finally:
3876 del repo._subtoppath
3883 del repo._subtoppath
3877
3884
3878
3885
3879 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3886 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'))
3880 def init(ui, dest=".", **opts):
3887 def init(ui, dest=".", **opts):
3881 """create a new repository in the given directory
3888 """create a new repository in the given directory
3882
3889
3883 Initialize a new repository in the given directory. If the given
3890 Initialize a new repository in the given directory. If the given
3884 directory does not exist, it will be created.
3891 directory does not exist, it will be created.
3885
3892
3886 If no directory is given, the current directory is used.
3893 If no directory is given, the current directory is used.
3887
3894
3888 It is possible to specify an ``ssh://`` URL as the destination.
3895 It is possible to specify an ``ssh://`` URL as the destination.
3889 See :hg:`help urls` for more information.
3896 See :hg:`help urls` for more information.
3890
3897
3891 Returns 0 on success.
3898 Returns 0 on success.
3892 """
3899 """
3893 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3900 hg.peer(ui, opts, ui.expandpath(dest), create=True)
3894
3901
3895 @command('locate',
3902 @command('locate',
3896 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3903 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3897 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3904 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3898 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3905 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
3899 ] + walkopts,
3906 ] + walkopts,
3900 _('[OPTION]... [PATTERN]...'))
3907 _('[OPTION]... [PATTERN]...'))
3901 def locate(ui, repo, *pats, **opts):
3908 def locate(ui, repo, *pats, **opts):
3902 """locate files matching specific patterns
3909 """locate files matching specific patterns
3903
3910
3904 Print files under Mercurial control in the working directory whose
3911 Print files under Mercurial control in the working directory whose
3905 names match the given patterns.
3912 names match the given patterns.
3906
3913
3907 By default, this command searches all directories in the working
3914 By default, this command searches all directories in the working
3908 directory. To search just the current directory and its
3915 directory. To search just the current directory and its
3909 subdirectories, use "--include .".
3916 subdirectories, use "--include .".
3910
3917
3911 If no patterns are given to match, this command prints the names
3918 If no patterns are given to match, this command prints the names
3912 of all files under Mercurial control in the working directory.
3919 of all files under Mercurial control in the working directory.
3913
3920
3914 If you want to feed the output of this command into the "xargs"
3921 If you want to feed the output of this command into the "xargs"
3915 command, use the -0 option to both this command and "xargs". This
3922 command, use the -0 option to both this command and "xargs". This
3916 will avoid the problem of "xargs" treating single filenames that
3923 will avoid the problem of "xargs" treating single filenames that
3917 contain whitespace as multiple filenames.
3924 contain whitespace as multiple filenames.
3918
3925
3919 Returns 0 if a match is found, 1 otherwise.
3926 Returns 0 if a match is found, 1 otherwise.
3920 """
3927 """
3921 end = opts.get('print0') and '\0' or '\n'
3928 end = opts.get('print0') and '\0' or '\n'
3922 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3929 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
3923
3930
3924 ret = 1
3931 ret = 1
3925 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3932 m = scmutil.match(repo[rev], pats, opts, default='relglob')
3926 m.bad = lambda x, y: False
3933 m.bad = lambda x, y: False
3927 for abs in repo[rev].walk(m):
3934 for abs in repo[rev].walk(m):
3928 if not rev and abs not in repo.dirstate:
3935 if not rev and abs not in repo.dirstate:
3929 continue
3936 continue
3930 if opts.get('fullpath'):
3937 if opts.get('fullpath'):
3931 ui.write(repo.wjoin(abs), end)
3938 ui.write(repo.wjoin(abs), end)
3932 else:
3939 else:
3933 ui.write(((pats and m.rel(abs)) or abs), end)
3940 ui.write(((pats and m.rel(abs)) or abs), end)
3934 ret = 0
3941 ret = 0
3935
3942
3936 return ret
3943 return ret
3937
3944
3938 @command('^log|history',
3945 @command('^log|history',
3939 [('f', 'follow', None,
3946 [('f', 'follow', None,
3940 _('follow changeset history, or file history across copies and renames')),
3947 _('follow changeset history, or file history across copies and renames')),
3941 ('', 'follow-first', None,
3948 ('', 'follow-first', None,
3942 _('only follow the first parent of merge changesets (DEPRECATED)')),
3949 _('only follow the first parent of merge changesets (DEPRECATED)')),
3943 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3950 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
3944 ('C', 'copies', None, _('show copied files')),
3951 ('C', 'copies', None, _('show copied files')),
3945 ('k', 'keyword', [],
3952 ('k', 'keyword', [],
3946 _('do case-insensitive search for a given text'), _('TEXT')),
3953 _('do case-insensitive search for a given text'), _('TEXT')),
3947 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3954 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
3948 ('', 'removed', None, _('include revisions where files were removed')),
3955 ('', 'removed', None, _('include revisions where files were removed')),
3949 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3956 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
3950 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3957 ('u', 'user', [], _('revisions committed by user'), _('USER')),
3951 ('', 'only-branch', [],
3958 ('', 'only-branch', [],
3952 _('show only changesets within the given named branch (DEPRECATED)'),
3959 _('show only changesets within the given named branch (DEPRECATED)'),
3953 _('BRANCH')),
3960 _('BRANCH')),
3954 ('b', 'branch', [],
3961 ('b', 'branch', [],
3955 _('show changesets within the given named branch'), _('BRANCH')),
3962 _('show changesets within the given named branch'), _('BRANCH')),
3956 ('P', 'prune', [],
3963 ('P', 'prune', [],
3957 _('do not display revision or any of its ancestors'), _('REV')),
3964 _('do not display revision or any of its ancestors'), _('REV')),
3958 ] + logopts + walkopts,
3965 ] + logopts + walkopts,
3959 _('[OPTION]... [FILE]'))
3966 _('[OPTION]... [FILE]'))
3960 def log(ui, repo, *pats, **opts):
3967 def log(ui, repo, *pats, **opts):
3961 """show revision history of entire repository or files
3968 """show revision history of entire repository or files
3962
3969
3963 Print the revision history of the specified files or the entire
3970 Print the revision history of the specified files or the entire
3964 project.
3971 project.
3965
3972
3966 If no revision range is specified, the default is ``tip:0`` unless
3973 If no revision range is specified, the default is ``tip:0`` unless
3967 --follow is set, in which case the working directory parent is
3974 --follow is set, in which case the working directory parent is
3968 used as the starting revision.
3975 used as the starting revision.
3969
3976
3970 File history is shown without following rename or copy history of
3977 File history is shown without following rename or copy history of
3971 files. Use -f/--follow with a filename to follow history across
3978 files. Use -f/--follow with a filename to follow history across
3972 renames and copies. --follow without a filename will only show
3979 renames and copies. --follow without a filename will only show
3973 ancestors or descendants of the starting revision.
3980 ancestors or descendants of the starting revision.
3974
3981
3975 By default this command prints revision number and changeset id,
3982 By default this command prints revision number and changeset id,
3976 tags, non-trivial parents, user, date and time, and a summary for
3983 tags, non-trivial parents, user, date and time, and a summary for
3977 each commit. When the -v/--verbose switch is used, the list of
3984 each commit. When the -v/--verbose switch is used, the list of
3978 changed files and full commit message are shown.
3985 changed files and full commit message are shown.
3979
3986
3980 .. note::
3987 .. note::
3981
3988
3982 log -p/--patch may generate unexpected diff output for merge
3989 log -p/--patch may generate unexpected diff output for merge
3983 changesets, as it will only compare the merge changeset against
3990 changesets, as it will only compare the merge changeset against
3984 its first parent. Also, only files different from BOTH parents
3991 its first parent. Also, only files different from BOTH parents
3985 will appear in files:.
3992 will appear in files:.
3986
3993
3987 .. note::
3994 .. note::
3988
3995
3989 for performance reasons, log FILE may omit duplicate changes
3996 for performance reasons, log FILE may omit duplicate changes
3990 made on branches and will not show deletions. To see all
3997 made on branches and will not show deletions. To see all
3991 changes including duplicates and deletions, use the --removed
3998 changes including duplicates and deletions, use the --removed
3992 switch.
3999 switch.
3993
4000
3994 .. container:: verbose
4001 .. container:: verbose
3995
4002
3996 Some examples:
4003 Some examples:
3997
4004
3998 - changesets with full descriptions and file lists::
4005 - changesets with full descriptions and file lists::
3999
4006
4000 hg log -v
4007 hg log -v
4001
4008
4002 - changesets ancestral to the working directory::
4009 - changesets ancestral to the working directory::
4003
4010
4004 hg log -f
4011 hg log -f
4005
4012
4006 - last 10 commits on the current branch::
4013 - last 10 commits on the current branch::
4007
4014
4008 hg log -l 10 -b .
4015 hg log -l 10 -b .
4009
4016
4010 - changesets showing all modifications of a file, including removals::
4017 - changesets showing all modifications of a file, including removals::
4011
4018
4012 hg log --removed file.c
4019 hg log --removed file.c
4013
4020
4014 - all changesets that touch a directory, with diffs, excluding merges::
4021 - all changesets that touch a directory, with diffs, excluding merges::
4015
4022
4016 hg log -Mp lib/
4023 hg log -Mp lib/
4017
4024
4018 - all revision numbers that match a keyword::
4025 - all revision numbers that match a keyword::
4019
4026
4020 hg log -k bug --template "{rev}\\n"
4027 hg log -k bug --template "{rev}\\n"
4021
4028
4022 - check if a given changeset is included is a tagged release::
4029 - check if a given changeset is included is a tagged release::
4023
4030
4024 hg log -r "a21ccf and ancestor(1.9)"
4031 hg log -r "a21ccf and ancestor(1.9)"
4025
4032
4026 - find all changesets by some user in a date range::
4033 - find all changesets by some user in a date range::
4027
4034
4028 hg log -k alice -d "may 2008 to jul 2008"
4035 hg log -k alice -d "may 2008 to jul 2008"
4029
4036
4030 - summary of all changesets after the last tag::
4037 - summary of all changesets after the last tag::
4031
4038
4032 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4039 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4033
4040
4034 See :hg:`help dates` for a list of formats valid for -d/--date.
4041 See :hg:`help dates` for a list of formats valid for -d/--date.
4035
4042
4036 See :hg:`help revisions` and :hg:`help revsets` for more about
4043 See :hg:`help revisions` and :hg:`help revsets` for more about
4037 specifying revisions.
4044 specifying revisions.
4038
4045
4039 See :hg:`help templates` for more about pre-packaged styles and
4046 See :hg:`help templates` for more about pre-packaged styles and
4040 specifying custom templates.
4047 specifying custom templates.
4041
4048
4042 Returns 0 on success.
4049 Returns 0 on success.
4043 """
4050 """
4044 if opts.get('graph'):
4051 if opts.get('graph'):
4045 return cmdutil.graphlog(ui, repo, *pats, **opts)
4052 return cmdutil.graphlog(ui, repo, *pats, **opts)
4046
4053
4047 matchfn = scmutil.match(repo[None], pats, opts)
4054 matchfn = scmutil.match(repo[None], pats, opts)
4048 limit = cmdutil.loglimit(opts)
4055 limit = cmdutil.loglimit(opts)
4049 count = 0
4056 count = 0
4050
4057
4051 getrenamed, endrev = None, None
4058 getrenamed, endrev = None, None
4052 if opts.get('copies'):
4059 if opts.get('copies'):
4053 if opts.get('rev'):
4060 if opts.get('rev'):
4054 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4061 endrev = max(scmutil.revrange(repo, opts.get('rev'))) + 1
4055 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4062 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4056
4063
4057 df = False
4064 df = False
4058 if opts.get("date"):
4065 if opts.get("date"):
4059 df = util.matchdate(opts["date"])
4066 df = util.matchdate(opts["date"])
4060
4067
4061 branches = opts.get('branch', []) + opts.get('only_branch', [])
4068 branches = opts.get('branch', []) + opts.get('only_branch', [])
4062 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4069 opts['branch'] = [repo.lookupbranch(b) for b in branches]
4063
4070
4064 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4071 displayer = cmdutil.show_changeset(ui, repo, opts, True)
4065 def prep(ctx, fns):
4072 def prep(ctx, fns):
4066 rev = ctx.rev()
4073 rev = ctx.rev()
4067 parents = [p for p in repo.changelog.parentrevs(rev)
4074 parents = [p for p in repo.changelog.parentrevs(rev)
4068 if p != nullrev]
4075 if p != nullrev]
4069 if opts.get('no_merges') and len(parents) == 2:
4076 if opts.get('no_merges') and len(parents) == 2:
4070 return
4077 return
4071 if opts.get('only_merges') and len(parents) != 2:
4078 if opts.get('only_merges') and len(parents) != 2:
4072 return
4079 return
4073 if opts.get('branch') and ctx.branch() not in opts['branch']:
4080 if opts.get('branch') and ctx.branch() not in opts['branch']:
4074 return
4081 return
4075 if df and not df(ctx.date()[0]):
4082 if df and not df(ctx.date()[0]):
4076 return
4083 return
4077
4084
4078 lower = encoding.lower
4085 lower = encoding.lower
4079 if opts.get('user'):
4086 if opts.get('user'):
4080 luser = lower(ctx.user())
4087 luser = lower(ctx.user())
4081 for k in [lower(x) for x in opts['user']]:
4088 for k in [lower(x) for x in opts['user']]:
4082 if (k in luser):
4089 if (k in luser):
4083 break
4090 break
4084 else:
4091 else:
4085 return
4092 return
4086 if opts.get('keyword'):
4093 if opts.get('keyword'):
4087 luser = lower(ctx.user())
4094 luser = lower(ctx.user())
4088 ldesc = lower(ctx.description())
4095 ldesc = lower(ctx.description())
4089 lfiles = lower(" ".join(ctx.files()))
4096 lfiles = lower(" ".join(ctx.files()))
4090 for k in [lower(x) for x in opts['keyword']]:
4097 for k in [lower(x) for x in opts['keyword']]:
4091 if (k in luser or k in ldesc or k in lfiles):
4098 if (k in luser or k in ldesc or k in lfiles):
4092 break
4099 break
4093 else:
4100 else:
4094 return
4101 return
4095
4102
4096 copies = None
4103 copies = None
4097 if getrenamed is not None and rev:
4104 if getrenamed is not None and rev:
4098 copies = []
4105 copies = []
4099 for fn in ctx.files():
4106 for fn in ctx.files():
4100 rename = getrenamed(fn, rev)
4107 rename = getrenamed(fn, rev)
4101 if rename:
4108 if rename:
4102 copies.append((fn, rename[0]))
4109 copies.append((fn, rename[0]))
4103
4110
4104 revmatchfn = None
4111 revmatchfn = None
4105 if opts.get('patch') or opts.get('stat'):
4112 if opts.get('patch') or opts.get('stat'):
4106 if opts.get('follow') or opts.get('follow_first'):
4113 if opts.get('follow') or opts.get('follow_first'):
4107 # note: this might be wrong when following through merges
4114 # note: this might be wrong when following through merges
4108 revmatchfn = scmutil.match(repo[None], fns, default='path')
4115 revmatchfn = scmutil.match(repo[None], fns, default='path')
4109 else:
4116 else:
4110 revmatchfn = matchfn
4117 revmatchfn = matchfn
4111
4118
4112 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4119 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4113
4120
4114 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4121 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4115 if displayer.flush(ctx.rev()):
4122 if displayer.flush(ctx.rev()):
4116 count += 1
4123 count += 1
4117 if count == limit:
4124 if count == limit:
4118 break
4125 break
4119 displayer.close()
4126 displayer.close()
4120
4127
4121 @command('manifest',
4128 @command('manifest',
4122 [('r', 'rev', '', _('revision to display'), _('REV')),
4129 [('r', 'rev', '', _('revision to display'), _('REV')),
4123 ('', 'all', False, _("list files from all revisions"))],
4130 ('', 'all', False, _("list files from all revisions"))],
4124 _('[-r REV]'))
4131 _('[-r REV]'))
4125 def manifest(ui, repo, node=None, rev=None, **opts):
4132 def manifest(ui, repo, node=None, rev=None, **opts):
4126 """output the current or given revision of the project manifest
4133 """output the current or given revision of the project manifest
4127
4134
4128 Print a list of version controlled files for the given revision.
4135 Print a list of version controlled files for the given revision.
4129 If no revision is given, the first parent of the working directory
4136 If no revision is given, the first parent of the working directory
4130 is used, or the null revision if no revision is checked out.
4137 is used, or the null revision if no revision is checked out.
4131
4138
4132 With -v, print file permissions, symlink and executable bits.
4139 With -v, print file permissions, symlink and executable bits.
4133 With --debug, print file revision hashes.
4140 With --debug, print file revision hashes.
4134
4141
4135 If option --all is specified, the list of all files from all revisions
4142 If option --all is specified, the list of all files from all revisions
4136 is printed. This includes deleted and renamed files.
4143 is printed. This includes deleted and renamed files.
4137
4144
4138 Returns 0 on success.
4145 Returns 0 on success.
4139 """
4146 """
4140
4147
4141 fm = ui.formatter('manifest', opts)
4148 fm = ui.formatter('manifest', opts)
4142
4149
4143 if opts.get('all'):
4150 if opts.get('all'):
4144 if rev or node:
4151 if rev or node:
4145 raise util.Abort(_("can't specify a revision with --all"))
4152 raise util.Abort(_("can't specify a revision with --all"))
4146
4153
4147 res = []
4154 res = []
4148 prefix = "data/"
4155 prefix = "data/"
4149 suffix = ".i"
4156 suffix = ".i"
4150 plen = len(prefix)
4157 plen = len(prefix)
4151 slen = len(suffix)
4158 slen = len(suffix)
4152 lock = repo.lock()
4159 lock = repo.lock()
4153 try:
4160 try:
4154 for fn, b, size in repo.store.datafiles():
4161 for fn, b, size in repo.store.datafiles():
4155 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4162 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4156 res.append(fn[plen:-slen])
4163 res.append(fn[plen:-slen])
4157 finally:
4164 finally:
4158 lock.release()
4165 lock.release()
4159 for f in res:
4166 for f in res:
4160 fm.startitem()
4167 fm.startitem()
4161 fm.write("path", '%s\n', f)
4168 fm.write("path", '%s\n', f)
4162 fm.end()
4169 fm.end()
4163 return
4170 return
4164
4171
4165 if rev and node:
4172 if rev and node:
4166 raise util.Abort(_("please specify just one revision"))
4173 raise util.Abort(_("please specify just one revision"))
4167
4174
4168 if not node:
4175 if not node:
4169 node = rev
4176 node = rev
4170
4177
4171 char = {'l': '@', 'x': '*', '': ''}
4178 char = {'l': '@', 'x': '*', '': ''}
4172 mode = {'l': '644', 'x': '755', '': '644'}
4179 mode = {'l': '644', 'x': '755', '': '644'}
4173 ctx = scmutil.revsingle(repo, node)
4180 ctx = scmutil.revsingle(repo, node)
4174 mf = ctx.manifest()
4181 mf = ctx.manifest()
4175 for f in ctx:
4182 for f in ctx:
4176 fm.startitem()
4183 fm.startitem()
4177 fl = ctx[f].flags()
4184 fl = ctx[f].flags()
4178 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4185 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4179 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4186 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4180 fm.write('path', '%s\n', f)
4187 fm.write('path', '%s\n', f)
4181 fm.end()
4188 fm.end()
4182
4189
4183 @command('^merge',
4190 @command('^merge',
4184 [('f', 'force', None,
4191 [('f', 'force', None,
4185 _('force a merge including outstanding changes (DEPRECATED)')),
4192 _('force a merge including outstanding changes (DEPRECATED)')),
4186 ('r', 'rev', '', _('revision to merge'), _('REV')),
4193 ('r', 'rev', '', _('revision to merge'), _('REV')),
4187 ('P', 'preview', None,
4194 ('P', 'preview', None,
4188 _('review revisions to merge (no merge is performed)'))
4195 _('review revisions to merge (no merge is performed)'))
4189 ] + mergetoolopts,
4196 ] + mergetoolopts,
4190 _('[-P] [-f] [[-r] REV]'))
4197 _('[-P] [-f] [[-r] REV]'))
4191 def merge(ui, repo, node=None, **opts):
4198 def merge(ui, repo, node=None, **opts):
4192 """merge working directory with another revision
4199 """merge working directory with another revision
4193
4200
4194 The current working directory is updated with all changes made in
4201 The current working directory is updated with all changes made in
4195 the requested revision since the last common predecessor revision.
4202 the requested revision since the last common predecessor revision.
4196
4203
4197 Files that changed between either parent are marked as changed for
4204 Files that changed between either parent are marked as changed for
4198 the next commit and a commit must be performed before any further
4205 the next commit and a commit must be performed before any further
4199 updates to the repository are allowed. The next commit will have
4206 updates to the repository are allowed. The next commit will have
4200 two parents.
4207 two parents.
4201
4208
4202 ``--tool`` can be used to specify the merge tool used for file
4209 ``--tool`` can be used to specify the merge tool used for file
4203 merges. It overrides the HGMERGE environment variable and your
4210 merges. It overrides the HGMERGE environment variable and your
4204 configuration files. See :hg:`help merge-tools` for options.
4211 configuration files. See :hg:`help merge-tools` for options.
4205
4212
4206 If no revision is specified, the working directory's parent is a
4213 If no revision is specified, the working directory's parent is a
4207 head revision, and the current branch contains exactly one other
4214 head revision, and the current branch contains exactly one other
4208 head, the other head is merged with by default. Otherwise, an
4215 head, the other head is merged with by default. Otherwise, an
4209 explicit revision with which to merge with must be provided.
4216 explicit revision with which to merge with must be provided.
4210
4217
4211 :hg:`resolve` must be used to resolve unresolved files.
4218 :hg:`resolve` must be used to resolve unresolved files.
4212
4219
4213 To undo an uncommitted merge, use :hg:`update --clean .` which
4220 To undo an uncommitted merge, use :hg:`update --clean .` which
4214 will check out a clean copy of the original merge parent, losing
4221 will check out a clean copy of the original merge parent, losing
4215 all changes.
4222 all changes.
4216
4223
4217 Returns 0 on success, 1 if there are unresolved files.
4224 Returns 0 on success, 1 if there are unresolved files.
4218 """
4225 """
4219
4226
4220 if opts.get('rev') and node:
4227 if opts.get('rev') and node:
4221 raise util.Abort(_("please specify just one revision"))
4228 raise util.Abort(_("please specify just one revision"))
4222 if not node:
4229 if not node:
4223 node = opts.get('rev')
4230 node = opts.get('rev')
4224
4231
4225 if node:
4232 if node:
4226 node = scmutil.revsingle(repo, node).node()
4233 node = scmutil.revsingle(repo, node).node()
4227
4234
4228 if not node and repo._bookmarkcurrent:
4235 if not node and repo._bookmarkcurrent:
4229 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4236 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4230 curhead = repo[repo._bookmarkcurrent].node()
4237 curhead = repo[repo._bookmarkcurrent].node()
4231 if len(bmheads) == 2:
4238 if len(bmheads) == 2:
4232 if curhead == bmheads[0]:
4239 if curhead == bmheads[0]:
4233 node = bmheads[1]
4240 node = bmheads[1]
4234 else:
4241 else:
4235 node = bmheads[0]
4242 node = bmheads[0]
4236 elif len(bmheads) > 2:
4243 elif len(bmheads) > 2:
4237 raise util.Abort(_("multiple matching bookmarks to merge - "
4244 raise util.Abort(_("multiple matching bookmarks to merge - "
4238 "please merge with an explicit rev or bookmark"),
4245 "please merge with an explicit rev or bookmark"),
4239 hint=_("run 'hg heads' to see all heads"))
4246 hint=_("run 'hg heads' to see all heads"))
4240 elif len(bmheads) <= 1:
4247 elif len(bmheads) <= 1:
4241 raise util.Abort(_("no matching bookmark to merge - "
4248 raise util.Abort(_("no matching bookmark to merge - "
4242 "please merge with an explicit rev or bookmark"),
4249 "please merge with an explicit rev or bookmark"),
4243 hint=_("run 'hg heads' to see all heads"))
4250 hint=_("run 'hg heads' to see all heads"))
4244
4251
4245 if not node and not repo._bookmarkcurrent:
4252 if not node and not repo._bookmarkcurrent:
4246 branch = repo[None].branch()
4253 branch = repo[None].branch()
4247 bheads = repo.branchheads(branch)
4254 bheads = repo.branchheads(branch)
4248 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4255 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4249
4256
4250 if len(nbhs) > 2:
4257 if len(nbhs) > 2:
4251 raise util.Abort(_("branch '%s' has %d heads - "
4258 raise util.Abort(_("branch '%s' has %d heads - "
4252 "please merge with an explicit rev")
4259 "please merge with an explicit rev")
4253 % (branch, len(bheads)),
4260 % (branch, len(bheads)),
4254 hint=_("run 'hg heads .' to see heads"))
4261 hint=_("run 'hg heads .' to see heads"))
4255
4262
4256 parent = repo.dirstate.p1()
4263 parent = repo.dirstate.p1()
4257 if len(nbhs) <= 1:
4264 if len(nbhs) <= 1:
4258 if len(bheads) > 1:
4265 if len(bheads) > 1:
4259 raise util.Abort(_("heads are bookmarked - "
4266 raise util.Abort(_("heads are bookmarked - "
4260 "please merge with an explicit rev"),
4267 "please merge with an explicit rev"),
4261 hint=_("run 'hg heads' to see all heads"))
4268 hint=_("run 'hg heads' to see all heads"))
4262 if len(repo.heads()) > 1:
4269 if len(repo.heads()) > 1:
4263 raise util.Abort(_("branch '%s' has one head - "
4270 raise util.Abort(_("branch '%s' has one head - "
4264 "please merge with an explicit rev")
4271 "please merge with an explicit rev")
4265 % branch,
4272 % branch,
4266 hint=_("run 'hg heads' to see all heads"))
4273 hint=_("run 'hg heads' to see all heads"))
4267 msg, hint = _('nothing to merge'), None
4274 msg, hint = _('nothing to merge'), None
4268 if parent != repo.lookup(branch):
4275 if parent != repo.lookup(branch):
4269 hint = _("use 'hg update' instead")
4276 hint = _("use 'hg update' instead")
4270 raise util.Abort(msg, hint=hint)
4277 raise util.Abort(msg, hint=hint)
4271
4278
4272 if parent not in bheads:
4279 if parent not in bheads:
4273 raise util.Abort(_('working directory not at a head revision'),
4280 raise util.Abort(_('working directory not at a head revision'),
4274 hint=_("use 'hg update' or merge with an "
4281 hint=_("use 'hg update' or merge with an "
4275 "explicit revision"))
4282 "explicit revision"))
4276 if parent == nbhs[0]:
4283 if parent == nbhs[0]:
4277 node = nbhs[-1]
4284 node = nbhs[-1]
4278 else:
4285 else:
4279 node = nbhs[0]
4286 node = nbhs[0]
4280
4287
4281 if opts.get('preview'):
4288 if opts.get('preview'):
4282 # find nodes that are ancestors of p2 but not of p1
4289 # find nodes that are ancestors of p2 but not of p1
4283 p1 = repo.lookup('.')
4290 p1 = repo.lookup('.')
4284 p2 = repo.lookup(node)
4291 p2 = repo.lookup(node)
4285 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4292 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4286
4293
4287 displayer = cmdutil.show_changeset(ui, repo, opts)
4294 displayer = cmdutil.show_changeset(ui, repo, opts)
4288 for node in nodes:
4295 for node in nodes:
4289 displayer.show(repo[node])
4296 displayer.show(repo[node])
4290 displayer.close()
4297 displayer.close()
4291 return 0
4298 return 0
4292
4299
4293 try:
4300 try:
4294 # ui.forcemerge is an internal variable, do not document
4301 # ui.forcemerge is an internal variable, do not document
4295 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4302 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4296 return hg.merge(repo, node, force=opts.get('force'))
4303 return hg.merge(repo, node, force=opts.get('force'))
4297 finally:
4304 finally:
4298 ui.setconfig('ui', 'forcemerge', '')
4305 ui.setconfig('ui', 'forcemerge', '')
4299
4306
4300 @command('outgoing|out',
4307 @command('outgoing|out',
4301 [('f', 'force', None, _('run even when the destination is unrelated')),
4308 [('f', 'force', None, _('run even when the destination is unrelated')),
4302 ('r', 'rev', [],
4309 ('r', 'rev', [],
4303 _('a changeset intended to be included in the destination'), _('REV')),
4310 _('a changeset intended to be included in the destination'), _('REV')),
4304 ('n', 'newest-first', None, _('show newest record first')),
4311 ('n', 'newest-first', None, _('show newest record first')),
4305 ('B', 'bookmarks', False, _('compare bookmarks')),
4312 ('B', 'bookmarks', False, _('compare bookmarks')),
4306 ('b', 'branch', [], _('a specific branch you would like to push'),
4313 ('b', 'branch', [], _('a specific branch you would like to push'),
4307 _('BRANCH')),
4314 _('BRANCH')),
4308 ] + logopts + remoteopts + subrepoopts,
4315 ] + logopts + remoteopts + subrepoopts,
4309 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4316 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4310 def outgoing(ui, repo, dest=None, **opts):
4317 def outgoing(ui, repo, dest=None, **opts):
4311 """show changesets not found in the destination
4318 """show changesets not found in the destination
4312
4319
4313 Show changesets not found in the specified destination repository
4320 Show changesets not found in the specified destination repository
4314 or the default push location. These are the changesets that would
4321 or the default push location. These are the changesets that would
4315 be pushed if a push was requested.
4322 be pushed if a push was requested.
4316
4323
4317 See pull for details of valid destination formats.
4324 See pull for details of valid destination formats.
4318
4325
4319 Returns 0 if there are outgoing changes, 1 otherwise.
4326 Returns 0 if there are outgoing changes, 1 otherwise.
4320 """
4327 """
4321 if opts.get('graph'):
4328 if opts.get('graph'):
4322 cmdutil.checkunsupportedgraphflags([], opts)
4329 cmdutil.checkunsupportedgraphflags([], opts)
4323 o = hg._outgoing(ui, repo, dest, opts)
4330 o = hg._outgoing(ui, repo, dest, opts)
4324 if o is None:
4331 if o is None:
4325 return
4332 return
4326
4333
4327 revdag = cmdutil.graphrevs(repo, o, opts)
4334 revdag = cmdutil.graphrevs(repo, o, opts)
4328 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4335 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4329 showparents = [ctx.node() for ctx in repo[None].parents()]
4336 showparents = [ctx.node() for ctx in repo[None].parents()]
4330 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4337 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4331 graphmod.asciiedges)
4338 graphmod.asciiedges)
4332 return 0
4339 return 0
4333
4340
4334 if opts.get('bookmarks'):
4341 if opts.get('bookmarks'):
4335 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4342 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4336 dest, branches = hg.parseurl(dest, opts.get('branch'))
4343 dest, branches = hg.parseurl(dest, opts.get('branch'))
4337 other = hg.peer(repo, opts, dest)
4344 other = hg.peer(repo, opts, dest)
4338 if 'bookmarks' not in other.listkeys('namespaces'):
4345 if 'bookmarks' not in other.listkeys('namespaces'):
4339 ui.warn(_("remote doesn't support bookmarks\n"))
4346 ui.warn(_("remote doesn't support bookmarks\n"))
4340 return 0
4347 return 0
4341 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4348 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4342 return bookmarks.diff(ui, other, repo)
4349 return bookmarks.diff(ui, other, repo)
4343
4350
4344 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4351 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4345 try:
4352 try:
4346 return hg.outgoing(ui, repo, dest, opts)
4353 return hg.outgoing(ui, repo, dest, opts)
4347 finally:
4354 finally:
4348 del repo._subtoppath
4355 del repo._subtoppath
4349
4356
4350 @command('parents',
4357 @command('parents',
4351 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4358 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4352 ] + templateopts,
4359 ] + templateopts,
4353 _('[-r REV] [FILE]'))
4360 _('[-r REV] [FILE]'))
4354 def parents(ui, repo, file_=None, **opts):
4361 def parents(ui, repo, file_=None, **opts):
4355 """show the parents of the working directory or revision
4362 """show the parents of the working directory or revision
4356
4363
4357 Print the working directory's parent revisions. If a revision is
4364 Print the working directory's parent revisions. If a revision is
4358 given via -r/--rev, the parent of that revision will be printed.
4365 given via -r/--rev, the parent of that revision will be printed.
4359 If a file argument is given, the revision in which the file was
4366 If a file argument is given, the revision in which the file was
4360 last changed (before the working directory revision or the
4367 last changed (before the working directory revision or the
4361 argument to --rev if given) is printed.
4368 argument to --rev if given) is printed.
4362
4369
4363 Returns 0 on success.
4370 Returns 0 on success.
4364 """
4371 """
4365
4372
4366 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4373 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4367
4374
4368 if file_:
4375 if file_:
4369 m = scmutil.match(ctx, (file_,), opts)
4376 m = scmutil.match(ctx, (file_,), opts)
4370 if m.anypats() or len(m.files()) != 1:
4377 if m.anypats() or len(m.files()) != 1:
4371 raise util.Abort(_('can only specify an explicit filename'))
4378 raise util.Abort(_('can only specify an explicit filename'))
4372 file_ = m.files()[0]
4379 file_ = m.files()[0]
4373 filenodes = []
4380 filenodes = []
4374 for cp in ctx.parents():
4381 for cp in ctx.parents():
4375 if not cp:
4382 if not cp:
4376 continue
4383 continue
4377 try:
4384 try:
4378 filenodes.append(cp.filenode(file_))
4385 filenodes.append(cp.filenode(file_))
4379 except error.LookupError:
4386 except error.LookupError:
4380 pass
4387 pass
4381 if not filenodes:
4388 if not filenodes:
4382 raise util.Abort(_("'%s' not found in manifest!") % file_)
4389 raise util.Abort(_("'%s' not found in manifest!") % file_)
4383 p = []
4390 p = []
4384 for fn in filenodes:
4391 for fn in filenodes:
4385 fctx = repo.filectx(file_, fileid=fn)
4392 fctx = repo.filectx(file_, fileid=fn)
4386 p.append(fctx.node())
4393 p.append(fctx.node())
4387 else:
4394 else:
4388 p = [cp.node() for cp in ctx.parents()]
4395 p = [cp.node() for cp in ctx.parents()]
4389
4396
4390 displayer = cmdutil.show_changeset(ui, repo, opts)
4397 displayer = cmdutil.show_changeset(ui, repo, opts)
4391 for n in p:
4398 for n in p:
4392 if n != nullid:
4399 if n != nullid:
4393 displayer.show(repo[n])
4400 displayer.show(repo[n])
4394 displayer.close()
4401 displayer.close()
4395
4402
4396 @command('paths', [], _('[NAME]'))
4403 @command('paths', [], _('[NAME]'))
4397 def paths(ui, repo, search=None):
4404 def paths(ui, repo, search=None):
4398 """show aliases for remote repositories
4405 """show aliases for remote repositories
4399
4406
4400 Show definition of symbolic path name NAME. If no name is given,
4407 Show definition of symbolic path name NAME. If no name is given,
4401 show definition of all available names.
4408 show definition of all available names.
4402
4409
4403 Option -q/--quiet suppresses all output when searching for NAME
4410 Option -q/--quiet suppresses all output when searching for NAME
4404 and shows only the path names when listing all definitions.
4411 and shows only the path names when listing all definitions.
4405
4412
4406 Path names are defined in the [paths] section of your
4413 Path names are defined in the [paths] section of your
4407 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4414 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4408 repository, ``.hg/hgrc`` is used, too.
4415 repository, ``.hg/hgrc`` is used, too.
4409
4416
4410 The path names ``default`` and ``default-push`` have a special
4417 The path names ``default`` and ``default-push`` have a special
4411 meaning. When performing a push or pull operation, they are used
4418 meaning. When performing a push or pull operation, they are used
4412 as fallbacks if no location is specified on the command-line.
4419 as fallbacks if no location is specified on the command-line.
4413 When ``default-push`` is set, it will be used for push and
4420 When ``default-push`` is set, it will be used for push and
4414 ``default`` will be used for pull; otherwise ``default`` is used
4421 ``default`` will be used for pull; otherwise ``default`` is used
4415 as the fallback for both. When cloning a repository, the clone
4422 as the fallback for both. When cloning a repository, the clone
4416 source is written as ``default`` in ``.hg/hgrc``. Note that
4423 source is written as ``default`` in ``.hg/hgrc``. Note that
4417 ``default`` and ``default-push`` apply to all inbound (e.g.
4424 ``default`` and ``default-push`` apply to all inbound (e.g.
4418 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4425 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4419 :hg:`bundle`) operations.
4426 :hg:`bundle`) operations.
4420
4427
4421 See :hg:`help urls` for more information.
4428 See :hg:`help urls` for more information.
4422
4429
4423 Returns 0 on success.
4430 Returns 0 on success.
4424 """
4431 """
4425 if search:
4432 if search:
4426 for name, path in ui.configitems("paths"):
4433 for name, path in ui.configitems("paths"):
4427 if name == search:
4434 if name == search:
4428 ui.status("%s\n" % util.hidepassword(path))
4435 ui.status("%s\n" % util.hidepassword(path))
4429 return
4436 return
4430 if not ui.quiet:
4437 if not ui.quiet:
4431 ui.warn(_("not found!\n"))
4438 ui.warn(_("not found!\n"))
4432 return 1
4439 return 1
4433 else:
4440 else:
4434 for name, path in ui.configitems("paths"):
4441 for name, path in ui.configitems("paths"):
4435 if ui.quiet:
4442 if ui.quiet:
4436 ui.write("%s\n" % name)
4443 ui.write("%s\n" % name)
4437 else:
4444 else:
4438 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4445 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4439
4446
4440 @command('phase',
4447 @command('phase',
4441 [('p', 'public', False, _('set changeset phase to public')),
4448 [('p', 'public', False, _('set changeset phase to public')),
4442 ('d', 'draft', False, _('set changeset phase to draft')),
4449 ('d', 'draft', False, _('set changeset phase to draft')),
4443 ('s', 'secret', False, _('set changeset phase to secret')),
4450 ('s', 'secret', False, _('set changeset phase to secret')),
4444 ('f', 'force', False, _('allow to move boundary backward')),
4451 ('f', 'force', False, _('allow to move boundary backward')),
4445 ('r', 'rev', [], _('target revision'), _('REV')),
4452 ('r', 'rev', [], _('target revision'), _('REV')),
4446 ],
4453 ],
4447 _('[-p|-d|-s] [-f] [-r] REV...'))
4454 _('[-p|-d|-s] [-f] [-r] REV...'))
4448 def phase(ui, repo, *revs, **opts):
4455 def phase(ui, repo, *revs, **opts):
4449 """set or show the current phase name
4456 """set or show the current phase name
4450
4457
4451 With no argument, show the phase name of specified revisions.
4458 With no argument, show the phase name of specified revisions.
4452
4459
4453 With one of -p/--public, -d/--draft or -s/--secret, change the
4460 With one of -p/--public, -d/--draft or -s/--secret, change the
4454 phase value of the specified revisions.
4461 phase value of the specified revisions.
4455
4462
4456 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4463 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4457 lower phase to an higher phase. Phases are ordered as follows::
4464 lower phase to an higher phase. Phases are ordered as follows::
4458
4465
4459 public < draft < secret
4466 public < draft < secret
4460
4467
4461 Return 0 on success, 1 if no phases were changed or some could not
4468 Return 0 on success, 1 if no phases were changed or some could not
4462 be changed.
4469 be changed.
4463 """
4470 """
4464 # search for a unique phase argument
4471 # search for a unique phase argument
4465 targetphase = None
4472 targetphase = None
4466 for idx, name in enumerate(phases.phasenames):
4473 for idx, name in enumerate(phases.phasenames):
4467 if opts[name]:
4474 if opts[name]:
4468 if targetphase is not None:
4475 if targetphase is not None:
4469 raise util.Abort(_('only one phase can be specified'))
4476 raise util.Abort(_('only one phase can be specified'))
4470 targetphase = idx
4477 targetphase = idx
4471
4478
4472 # look for specified revision
4479 # look for specified revision
4473 revs = list(revs)
4480 revs = list(revs)
4474 revs.extend(opts['rev'])
4481 revs.extend(opts['rev'])
4475 if not revs:
4482 if not revs:
4476 raise util.Abort(_('no revisions specified'))
4483 raise util.Abort(_('no revisions specified'))
4477
4484
4478 revs = scmutil.revrange(repo, revs)
4485 revs = scmutil.revrange(repo, revs)
4479
4486
4480 lock = None
4487 lock = None
4481 ret = 0
4488 ret = 0
4482 if targetphase is None:
4489 if targetphase is None:
4483 # display
4490 # display
4484 for r in revs:
4491 for r in revs:
4485 ctx = repo[r]
4492 ctx = repo[r]
4486 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4493 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4487 else:
4494 else:
4488 lock = repo.lock()
4495 lock = repo.lock()
4489 try:
4496 try:
4490 # set phase
4497 # set phase
4491 if not revs:
4498 if not revs:
4492 raise util.Abort(_('empty revision set'))
4499 raise util.Abort(_('empty revision set'))
4493 nodes = [repo[r].node() for r in revs]
4500 nodes = [repo[r].node() for r in revs]
4494 olddata = repo._phasecache.getphaserevs(repo)[:]
4501 olddata = repo._phasecache.getphaserevs(repo)[:]
4495 phases.advanceboundary(repo, targetphase, nodes)
4502 phases.advanceboundary(repo, targetphase, nodes)
4496 if opts['force']:
4503 if opts['force']:
4497 phases.retractboundary(repo, targetphase, nodes)
4504 phases.retractboundary(repo, targetphase, nodes)
4498 finally:
4505 finally:
4499 lock.release()
4506 lock.release()
4500 # moving revision from public to draft may hide them
4507 # moving revision from public to draft may hide them
4501 # We have to check result on an unfiltered repository
4508 # We have to check result on an unfiltered repository
4502 unfi = repo.unfiltered()
4509 unfi = repo.unfiltered()
4503 newdata = repo._phasecache.getphaserevs(unfi)
4510 newdata = repo._phasecache.getphaserevs(unfi)
4504 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4511 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4505 cl = unfi.changelog
4512 cl = unfi.changelog
4506 rejected = [n for n in nodes
4513 rejected = [n for n in nodes
4507 if newdata[cl.rev(n)] < targetphase]
4514 if newdata[cl.rev(n)] < targetphase]
4508 if rejected:
4515 if rejected:
4509 ui.warn(_('cannot move %i changesets to a higher '
4516 ui.warn(_('cannot move %i changesets to a higher '
4510 'phase, use --force\n') % len(rejected))
4517 'phase, use --force\n') % len(rejected))
4511 ret = 1
4518 ret = 1
4512 if changes:
4519 if changes:
4513 msg = _('phase changed for %i changesets\n') % changes
4520 msg = _('phase changed for %i changesets\n') % changes
4514 if ret:
4521 if ret:
4515 ui.status(msg)
4522 ui.status(msg)
4516 else:
4523 else:
4517 ui.note(msg)
4524 ui.note(msg)
4518 else:
4525 else:
4519 ui.warn(_('no phases changed\n'))
4526 ui.warn(_('no phases changed\n'))
4520 ret = 1
4527 ret = 1
4521 return ret
4528 return ret
4522
4529
4523 def postincoming(ui, repo, modheads, optupdate, checkout):
4530 def postincoming(ui, repo, modheads, optupdate, checkout):
4524 if modheads == 0:
4531 if modheads == 0:
4525 return
4532 return
4526 if optupdate:
4533 if optupdate:
4527 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4534 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4528 try:
4535 try:
4529 ret = hg.update(repo, checkout)
4536 ret = hg.update(repo, checkout)
4530 except util.Abort, inst:
4537 except util.Abort, inst:
4531 ui.warn(_("not updating: %s\n") % str(inst))
4538 ui.warn(_("not updating: %s\n") % str(inst))
4532 if inst.hint:
4539 if inst.hint:
4533 ui.warn(_("(%s)\n") % inst.hint)
4540 ui.warn(_("(%s)\n") % inst.hint)
4534 return 0
4541 return 0
4535 if not ret and not checkout:
4542 if not ret and not checkout:
4536 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4543 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4537 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4544 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4538 return ret
4545 return ret
4539 if modheads > 1:
4546 if modheads > 1:
4540 currentbranchheads = len(repo.branchheads())
4547 currentbranchheads = len(repo.branchheads())
4541 if currentbranchheads == modheads:
4548 if currentbranchheads == modheads:
4542 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4549 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4543 elif currentbranchheads > 1:
4550 elif currentbranchheads > 1:
4544 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4551 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4545 "merge)\n"))
4552 "merge)\n"))
4546 else:
4553 else:
4547 ui.status(_("(run 'hg heads' to see heads)\n"))
4554 ui.status(_("(run 'hg heads' to see heads)\n"))
4548 else:
4555 else:
4549 ui.status(_("(run 'hg update' to get a working copy)\n"))
4556 ui.status(_("(run 'hg update' to get a working copy)\n"))
4550
4557
4551 @command('^pull',
4558 @command('^pull',
4552 [('u', 'update', None,
4559 [('u', 'update', None,
4553 _('update to new branch head if changesets were pulled')),
4560 _('update to new branch head if changesets were pulled')),
4554 ('f', 'force', None, _('run even when remote repository is unrelated')),
4561 ('f', 'force', None, _('run even when remote repository is unrelated')),
4555 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4562 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4556 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4563 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4557 ('b', 'branch', [], _('a specific branch you would like to pull'),
4564 ('b', 'branch', [], _('a specific branch you would like to pull'),
4558 _('BRANCH')),
4565 _('BRANCH')),
4559 ] + remoteopts,
4566 ] + remoteopts,
4560 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4567 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4561 def pull(ui, repo, source="default", **opts):
4568 def pull(ui, repo, source="default", **opts):
4562 """pull changes from the specified source
4569 """pull changes from the specified source
4563
4570
4564 Pull changes from a remote repository to a local one.
4571 Pull changes from a remote repository to a local one.
4565
4572
4566 This finds all changes from the repository at the specified path
4573 This finds all changes from the repository at the specified path
4567 or URL and adds them to a local repository (the current one unless
4574 or URL and adds them to a local repository (the current one unless
4568 -R is specified). By default, this does not update the copy of the
4575 -R is specified). By default, this does not update the copy of the
4569 project in the working directory.
4576 project in the working directory.
4570
4577
4571 Use :hg:`incoming` if you want to see what would have been added
4578 Use :hg:`incoming` if you want to see what would have been added
4572 by a pull at the time you issued this command. If you then decide
4579 by a pull at the time you issued this command. If you then decide
4573 to add those changes to the repository, you should use :hg:`pull
4580 to add those changes to the repository, you should use :hg:`pull
4574 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4581 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4575
4582
4576 If SOURCE is omitted, the 'default' path will be used.
4583 If SOURCE is omitted, the 'default' path will be used.
4577 See :hg:`help urls` for more information.
4584 See :hg:`help urls` for more information.
4578
4585
4579 Returns 0 on success, 1 if an update had unresolved files.
4586 Returns 0 on success, 1 if an update had unresolved files.
4580 """
4587 """
4581 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4588 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4582 other = hg.peer(repo, opts, source)
4589 other = hg.peer(repo, opts, source)
4583 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4590 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4584 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4591 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
4585
4592
4586 remotebookmarks = other.listkeys('bookmarks')
4593 remotebookmarks = other.listkeys('bookmarks')
4587
4594
4588 if opts.get('bookmark'):
4595 if opts.get('bookmark'):
4589 if not revs:
4596 if not revs:
4590 revs = []
4597 revs = []
4591 for b in opts['bookmark']:
4598 for b in opts['bookmark']:
4592 if b not in remotebookmarks:
4599 if b not in remotebookmarks:
4593 raise util.Abort(_('remote bookmark %s not found!') % b)
4600 raise util.Abort(_('remote bookmark %s not found!') % b)
4594 revs.append(remotebookmarks[b])
4601 revs.append(remotebookmarks[b])
4595
4602
4596 if revs:
4603 if revs:
4597 try:
4604 try:
4598 revs = [other.lookup(rev) for rev in revs]
4605 revs = [other.lookup(rev) for rev in revs]
4599 except error.CapabilityError:
4606 except error.CapabilityError:
4600 err = _("other repository doesn't support revision lookup, "
4607 err = _("other repository doesn't support revision lookup, "
4601 "so a rev cannot be specified.")
4608 "so a rev cannot be specified.")
4602 raise util.Abort(err)
4609 raise util.Abort(err)
4603
4610
4604 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4611 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4605 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4612 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4606 if checkout:
4613 if checkout:
4607 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4614 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4608 repo._subtoppath = source
4615 repo._subtoppath = source
4609 try:
4616 try:
4610 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4617 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4611
4618
4612 finally:
4619 finally:
4613 del repo._subtoppath
4620 del repo._subtoppath
4614
4621
4615 # update specified bookmarks
4622 # update specified bookmarks
4616 if opts.get('bookmark'):
4623 if opts.get('bookmark'):
4617 marks = repo._bookmarks
4624 marks = repo._bookmarks
4618 for b in opts['bookmark']:
4625 for b in opts['bookmark']:
4619 # explicit pull overrides local bookmark if any
4626 # explicit pull overrides local bookmark if any
4620 ui.status(_("importing bookmark %s\n") % b)
4627 ui.status(_("importing bookmark %s\n") % b)
4621 marks[b] = repo[remotebookmarks[b]].node()
4628 marks[b] = repo[remotebookmarks[b]].node()
4622 marks.write()
4629 marks.write()
4623
4630
4624 return ret
4631 return ret
4625
4632
4626 @command('^push',
4633 @command('^push',
4627 [('f', 'force', None, _('force push')),
4634 [('f', 'force', None, _('force push')),
4628 ('r', 'rev', [],
4635 ('r', 'rev', [],
4629 _('a changeset intended to be included in the destination'),
4636 _('a changeset intended to be included in the destination'),
4630 _('REV')),
4637 _('REV')),
4631 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4638 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4632 ('b', 'branch', [],
4639 ('b', 'branch', [],
4633 _('a specific branch you would like to push'), _('BRANCH')),
4640 _('a specific branch you would like to push'), _('BRANCH')),
4634 ('', 'new-branch', False, _('allow pushing a new branch')),
4641 ('', 'new-branch', False, _('allow pushing a new branch')),
4635 ] + remoteopts,
4642 ] + remoteopts,
4636 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4643 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4637 def push(ui, repo, dest=None, **opts):
4644 def push(ui, repo, dest=None, **opts):
4638 """push changes to the specified destination
4645 """push changes to the specified destination
4639
4646
4640 Push changesets from the local repository to the specified
4647 Push changesets from the local repository to the specified
4641 destination.
4648 destination.
4642
4649
4643 This operation is symmetrical to pull: it is identical to a pull
4650 This operation is symmetrical to pull: it is identical to a pull
4644 in the destination repository from the current one.
4651 in the destination repository from the current one.
4645
4652
4646 By default, push will not allow creation of new heads at the
4653 By default, push will not allow creation of new heads at the
4647 destination, since multiple heads would make it unclear which head
4654 destination, since multiple heads would make it unclear which head
4648 to use. In this situation, it is recommended to pull and merge
4655 to use. In this situation, it is recommended to pull and merge
4649 before pushing.
4656 before pushing.
4650
4657
4651 Use --new-branch if you want to allow push to create a new named
4658 Use --new-branch if you want to allow push to create a new named
4652 branch that is not present at the destination. This allows you to
4659 branch that is not present at the destination. This allows you to
4653 only create a new branch without forcing other changes.
4660 only create a new branch without forcing other changes.
4654
4661
4655 .. note::
4662 .. note::
4656
4663
4657 Extra care should be taken with the -f/--force option,
4664 Extra care should be taken with the -f/--force option,
4658 which will push all new heads on all branches, an action which will
4665 which will push all new heads on all branches, an action which will
4659 almost always cause confusion for collaborators.
4666 almost always cause confusion for collaborators.
4660
4667
4661 If -r/--rev is used, the specified revision and all its ancestors
4668 If -r/--rev is used, the specified revision and all its ancestors
4662 will be pushed to the remote repository.
4669 will be pushed to the remote repository.
4663
4670
4664 If -B/--bookmark is used, the specified bookmarked revision, its
4671 If -B/--bookmark is used, the specified bookmarked revision, its
4665 ancestors, and the bookmark will be pushed to the remote
4672 ancestors, and the bookmark will be pushed to the remote
4666 repository.
4673 repository.
4667
4674
4668 Please see :hg:`help urls` for important details about ``ssh://``
4675 Please see :hg:`help urls` for important details about ``ssh://``
4669 URLs. If DESTINATION is omitted, a default path will be used.
4676 URLs. If DESTINATION is omitted, a default path will be used.
4670
4677
4671 Returns 0 if push was successful, 1 if nothing to push.
4678 Returns 0 if push was successful, 1 if nothing to push.
4672 """
4679 """
4673
4680
4674 if opts.get('bookmark'):
4681 if opts.get('bookmark'):
4675 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4682 ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
4676 for b in opts['bookmark']:
4683 for b in opts['bookmark']:
4677 # translate -B options to -r so changesets get pushed
4684 # translate -B options to -r so changesets get pushed
4678 if b in repo._bookmarks:
4685 if b in repo._bookmarks:
4679 opts.setdefault('rev', []).append(b)
4686 opts.setdefault('rev', []).append(b)
4680 else:
4687 else:
4681 # if we try to push a deleted bookmark, translate it to null
4688 # if we try to push a deleted bookmark, translate it to null
4682 # this lets simultaneous -r, -b options continue working
4689 # this lets simultaneous -r, -b options continue working
4683 opts.setdefault('rev', []).append("null")
4690 opts.setdefault('rev', []).append("null")
4684
4691
4685 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4692 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4686 dest, branches = hg.parseurl(dest, opts.get('branch'))
4693 dest, branches = hg.parseurl(dest, opts.get('branch'))
4687 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4694 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4688 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4695 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4689 other = hg.peer(repo, opts, dest)
4696 other = hg.peer(repo, opts, dest)
4690 if revs:
4697 if revs:
4691 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4698 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4692
4699
4693 repo._subtoppath = dest
4700 repo._subtoppath = dest
4694 try:
4701 try:
4695 # push subrepos depth-first for coherent ordering
4702 # push subrepos depth-first for coherent ordering
4696 c = repo['']
4703 c = repo['']
4697 subs = c.substate # only repos that are committed
4704 subs = c.substate # only repos that are committed
4698 for s in sorted(subs):
4705 for s in sorted(subs):
4699 if c.sub(s).push(opts) == 0:
4706 if c.sub(s).push(opts) == 0:
4700 return False
4707 return False
4701 finally:
4708 finally:
4702 del repo._subtoppath
4709 del repo._subtoppath
4703 result = repo.push(other, opts.get('force'), revs=revs,
4710 result = repo.push(other, opts.get('force'), revs=revs,
4704 newbranch=opts.get('new_branch'))
4711 newbranch=opts.get('new_branch'))
4705
4712
4706 result = not result
4713 result = not result
4707
4714
4708 if opts.get('bookmark'):
4715 if opts.get('bookmark'):
4709 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4716 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4710 if bresult == 2:
4717 if bresult == 2:
4711 return 2
4718 return 2
4712 if not result and bresult:
4719 if not result and bresult:
4713 result = 2
4720 result = 2
4714
4721
4715 return result
4722 return result
4716
4723
4717 @command('recover', [])
4724 @command('recover', [])
4718 def recover(ui, repo):
4725 def recover(ui, repo):
4719 """roll back an interrupted transaction
4726 """roll back an interrupted transaction
4720
4727
4721 Recover from an interrupted commit or pull.
4728 Recover from an interrupted commit or pull.
4722
4729
4723 This command tries to fix the repository status after an
4730 This command tries to fix the repository status after an
4724 interrupted operation. It should only be necessary when Mercurial
4731 interrupted operation. It should only be necessary when Mercurial
4725 suggests it.
4732 suggests it.
4726
4733
4727 Returns 0 if successful, 1 if nothing to recover or verify fails.
4734 Returns 0 if successful, 1 if nothing to recover or verify fails.
4728 """
4735 """
4729 if repo.recover():
4736 if repo.recover():
4730 return hg.verify(repo)
4737 return hg.verify(repo)
4731 return 1
4738 return 1
4732
4739
4733 @command('^remove|rm',
4740 @command('^remove|rm',
4734 [('A', 'after', None, _('record delete for missing files')),
4741 [('A', 'after', None, _('record delete for missing files')),
4735 ('f', 'force', None,
4742 ('f', 'force', None,
4736 _('remove (and delete) file even if added or modified')),
4743 _('remove (and delete) file even if added or modified')),
4737 ] + walkopts,
4744 ] + walkopts,
4738 _('[OPTION]... FILE...'))
4745 _('[OPTION]... FILE...'))
4739 def remove(ui, repo, *pats, **opts):
4746 def remove(ui, repo, *pats, **opts):
4740 """remove the specified files on the next commit
4747 """remove the specified files on the next commit
4741
4748
4742 Schedule the indicated files for removal from the current branch.
4749 Schedule the indicated files for removal from the current branch.
4743
4750
4744 This command schedules the files to be removed at the next commit.
4751 This command schedules the files to be removed at the next commit.
4745 To undo a remove before that, see :hg:`revert`. To undo added
4752 To undo a remove before that, see :hg:`revert`. To undo added
4746 files, see :hg:`forget`.
4753 files, see :hg:`forget`.
4747
4754
4748 .. container:: verbose
4755 .. container:: verbose
4749
4756
4750 -A/--after can be used to remove only files that have already
4757 -A/--after can be used to remove only files that have already
4751 been deleted, -f/--force can be used to force deletion, and -Af
4758 been deleted, -f/--force can be used to force deletion, and -Af
4752 can be used to remove files from the next revision without
4759 can be used to remove files from the next revision without
4753 deleting them from the working directory.
4760 deleting them from the working directory.
4754
4761
4755 The following table details the behavior of remove for different
4762 The following table details the behavior of remove for different
4756 file states (columns) and option combinations (rows). The file
4763 file states (columns) and option combinations (rows). The file
4757 states are Added [A], Clean [C], Modified [M] and Missing [!]
4764 states are Added [A], Clean [C], Modified [M] and Missing [!]
4758 (as reported by :hg:`status`). The actions are Warn, Remove
4765 (as reported by :hg:`status`). The actions are Warn, Remove
4759 (from branch) and Delete (from disk):
4766 (from branch) and Delete (from disk):
4760
4767
4761 ========= == == == ==
4768 ========= == == == ==
4762 opt/state A C M !
4769 opt/state A C M !
4763 ========= == == == ==
4770 ========= == == == ==
4764 none W RD W R
4771 none W RD W R
4765 -f R RD RD R
4772 -f R RD RD R
4766 -A W W W R
4773 -A W W W R
4767 -Af R R R R
4774 -Af R R R R
4768 ========= == == == ==
4775 ========= == == == ==
4769
4776
4770 Note that remove never deletes files in Added [A] state from the
4777 Note that remove never deletes files in Added [A] state from the
4771 working directory, not even if option --force is specified.
4778 working directory, not even if option --force is specified.
4772
4779
4773 Returns 0 on success, 1 if any warnings encountered.
4780 Returns 0 on success, 1 if any warnings encountered.
4774 """
4781 """
4775
4782
4776 ret = 0
4783 ret = 0
4777 after, force = opts.get('after'), opts.get('force')
4784 after, force = opts.get('after'), opts.get('force')
4778 if not pats and not after:
4785 if not pats and not after:
4779 raise util.Abort(_('no files specified'))
4786 raise util.Abort(_('no files specified'))
4780
4787
4781 m = scmutil.match(repo[None], pats, opts)
4788 m = scmutil.match(repo[None], pats, opts)
4782 s = repo.status(match=m, clean=True)
4789 s = repo.status(match=m, clean=True)
4783 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4790 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
4784
4791
4785 # warn about failure to delete explicit files/dirs
4792 # warn about failure to delete explicit files/dirs
4786 wctx = repo[None]
4793 wctx = repo[None]
4787 for f in m.files():
4794 for f in m.files():
4788 if f in repo.dirstate or f in wctx.dirs():
4795 if f in repo.dirstate or f in wctx.dirs():
4789 continue
4796 continue
4790 if os.path.exists(m.rel(f)):
4797 if os.path.exists(m.rel(f)):
4791 if os.path.isdir(m.rel(f)):
4798 if os.path.isdir(m.rel(f)):
4792 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4799 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
4793 else:
4800 else:
4794 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4801 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
4795 # missing files will generate a warning elsewhere
4802 # missing files will generate a warning elsewhere
4796 ret = 1
4803 ret = 1
4797
4804
4798 if force:
4805 if force:
4799 list = modified + deleted + clean + added
4806 list = modified + deleted + clean + added
4800 elif after:
4807 elif after:
4801 list = deleted
4808 list = deleted
4802 for f in modified + added + clean:
4809 for f in modified + added + clean:
4803 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4810 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
4804 ret = 1
4811 ret = 1
4805 else:
4812 else:
4806 list = deleted + clean
4813 list = deleted + clean
4807 for f in modified:
4814 for f in modified:
4808 ui.warn(_('not removing %s: file is modified (use -f'
4815 ui.warn(_('not removing %s: file is modified (use -f'
4809 ' to force removal)\n') % m.rel(f))
4816 ' to force removal)\n') % m.rel(f))
4810 ret = 1
4817 ret = 1
4811 for f in added:
4818 for f in added:
4812 ui.warn(_('not removing %s: file has been marked for add'
4819 ui.warn(_('not removing %s: file has been marked for add'
4813 ' (use forget to undo)\n') % m.rel(f))
4820 ' (use forget to undo)\n') % m.rel(f))
4814 ret = 1
4821 ret = 1
4815
4822
4816 for f in sorted(list):
4823 for f in sorted(list):
4817 if ui.verbose or not m.exact(f):
4824 if ui.verbose or not m.exact(f):
4818 ui.status(_('removing %s\n') % m.rel(f))
4825 ui.status(_('removing %s\n') % m.rel(f))
4819
4826
4820 wlock = repo.wlock()
4827 wlock = repo.wlock()
4821 try:
4828 try:
4822 if not after:
4829 if not after:
4823 for f in list:
4830 for f in list:
4824 if f in added:
4831 if f in added:
4825 continue # we never unlink added files on remove
4832 continue # we never unlink added files on remove
4826 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4833 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
4827 repo[None].forget(list)
4834 repo[None].forget(list)
4828 finally:
4835 finally:
4829 wlock.release()
4836 wlock.release()
4830
4837
4831 return ret
4838 return ret
4832
4839
4833 @command('rename|move|mv',
4840 @command('rename|move|mv',
4834 [('A', 'after', None, _('record a rename that has already occurred')),
4841 [('A', 'after', None, _('record a rename that has already occurred')),
4835 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4842 ('f', 'force', None, _('forcibly copy over an existing managed file')),
4836 ] + walkopts + dryrunopts,
4843 ] + walkopts + dryrunopts,
4837 _('[OPTION]... SOURCE... DEST'))
4844 _('[OPTION]... SOURCE... DEST'))
4838 def rename(ui, repo, *pats, **opts):
4845 def rename(ui, repo, *pats, **opts):
4839 """rename files; equivalent of copy + remove
4846 """rename files; equivalent of copy + remove
4840
4847
4841 Mark dest as copies of sources; mark sources for deletion. If dest
4848 Mark dest as copies of sources; mark sources for deletion. If dest
4842 is a directory, copies are put in that directory. If dest is a
4849 is a directory, copies are put in that directory. If dest is a
4843 file, there can only be one source.
4850 file, there can only be one source.
4844
4851
4845 By default, this command copies the contents of files as they
4852 By default, this command copies the contents of files as they
4846 exist in the working directory. If invoked with -A/--after, the
4853 exist in the working directory. If invoked with -A/--after, the
4847 operation is recorded, but no copying is performed.
4854 operation is recorded, but no copying is performed.
4848
4855
4849 This command takes effect at the next commit. To undo a rename
4856 This command takes effect at the next commit. To undo a rename
4850 before that, see :hg:`revert`.
4857 before that, see :hg:`revert`.
4851
4858
4852 Returns 0 on success, 1 if errors are encountered.
4859 Returns 0 on success, 1 if errors are encountered.
4853 """
4860 """
4854 wlock = repo.wlock(False)
4861 wlock = repo.wlock(False)
4855 try:
4862 try:
4856 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4863 return cmdutil.copy(ui, repo, pats, opts, rename=True)
4857 finally:
4864 finally:
4858 wlock.release()
4865 wlock.release()
4859
4866
4860 @command('resolve',
4867 @command('resolve',
4861 [('a', 'all', None, _('select all unresolved files')),
4868 [('a', 'all', None, _('select all unresolved files')),
4862 ('l', 'list', None, _('list state of files needing merge')),
4869 ('l', 'list', None, _('list state of files needing merge')),
4863 ('m', 'mark', None, _('mark files as resolved')),
4870 ('m', 'mark', None, _('mark files as resolved')),
4864 ('u', 'unmark', None, _('mark files as unresolved')),
4871 ('u', 'unmark', None, _('mark files as unresolved')),
4865 ('n', 'no-status', None, _('hide status prefix'))]
4872 ('n', 'no-status', None, _('hide status prefix'))]
4866 + mergetoolopts + walkopts,
4873 + mergetoolopts + walkopts,
4867 _('[OPTION]... [FILE]...'))
4874 _('[OPTION]... [FILE]...'))
4868 def resolve(ui, repo, *pats, **opts):
4875 def resolve(ui, repo, *pats, **opts):
4869 """redo merges or set/view the merge status of files
4876 """redo merges or set/view the merge status of files
4870
4877
4871 Merges with unresolved conflicts are often the result of
4878 Merges with unresolved conflicts are often the result of
4872 non-interactive merging using the ``internal:merge`` configuration
4879 non-interactive merging using the ``internal:merge`` configuration
4873 setting, or a command-line merge tool like ``diff3``. The resolve
4880 setting, or a command-line merge tool like ``diff3``. The resolve
4874 command is used to manage the files involved in a merge, after
4881 command is used to manage the files involved in a merge, after
4875 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4882 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
4876 working directory must have two parents). See :hg:`help
4883 working directory must have two parents). See :hg:`help
4877 merge-tools` for information on configuring merge tools.
4884 merge-tools` for information on configuring merge tools.
4878
4885
4879 The resolve command can be used in the following ways:
4886 The resolve command can be used in the following ways:
4880
4887
4881 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4888 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
4882 files, discarding any previous merge attempts. Re-merging is not
4889 files, discarding any previous merge attempts. Re-merging is not
4883 performed for files already marked as resolved. Use ``--all/-a``
4890 performed for files already marked as resolved. Use ``--all/-a``
4884 to select all unresolved files. ``--tool`` can be used to specify
4891 to select all unresolved files. ``--tool`` can be used to specify
4885 the merge tool used for the given files. It overrides the HGMERGE
4892 the merge tool used for the given files. It overrides the HGMERGE
4886 environment variable and your configuration files. Previous file
4893 environment variable and your configuration files. Previous file
4887 contents are saved with a ``.orig`` suffix.
4894 contents are saved with a ``.orig`` suffix.
4888
4895
4889 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4896 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
4890 (e.g. after having manually fixed-up the files). The default is
4897 (e.g. after having manually fixed-up the files). The default is
4891 to mark all unresolved files.
4898 to mark all unresolved files.
4892
4899
4893 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4900 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
4894 default is to mark all resolved files.
4901 default is to mark all resolved files.
4895
4902
4896 - :hg:`resolve -l`: list files which had or still have conflicts.
4903 - :hg:`resolve -l`: list files which had or still have conflicts.
4897 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4904 In the printed list, ``U`` = unresolved and ``R`` = resolved.
4898
4905
4899 Note that Mercurial will not let you commit files with unresolved
4906 Note that Mercurial will not let you commit files with unresolved
4900 merge conflicts. You must use :hg:`resolve -m ...` before you can
4907 merge conflicts. You must use :hg:`resolve -m ...` before you can
4901 commit after a conflicting merge.
4908 commit after a conflicting merge.
4902
4909
4903 Returns 0 on success, 1 if any files fail a resolve attempt.
4910 Returns 0 on success, 1 if any files fail a resolve attempt.
4904 """
4911 """
4905
4912
4906 all, mark, unmark, show, nostatus = \
4913 all, mark, unmark, show, nostatus = \
4907 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4914 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
4908
4915
4909 if (show and (mark or unmark)) or (mark and unmark):
4916 if (show and (mark or unmark)) or (mark and unmark):
4910 raise util.Abort(_("too many options specified"))
4917 raise util.Abort(_("too many options specified"))
4911 if pats and all:
4918 if pats and all:
4912 raise util.Abort(_("can't specify --all and patterns"))
4919 raise util.Abort(_("can't specify --all and patterns"))
4913 if not (all or pats or show or mark or unmark):
4920 if not (all or pats or show or mark or unmark):
4914 raise util.Abort(_('no files or directories specified; '
4921 raise util.Abort(_('no files or directories specified; '
4915 'use --all to remerge all files'))
4922 'use --all to remerge all files'))
4916
4923
4917 ms = mergemod.mergestate(repo)
4924 ms = mergemod.mergestate(repo)
4918 m = scmutil.match(repo[None], pats, opts)
4925 m = scmutil.match(repo[None], pats, opts)
4919 ret = 0
4926 ret = 0
4920
4927
4921 for f in ms:
4928 for f in ms:
4922 if m(f):
4929 if m(f):
4923 if show:
4930 if show:
4924 if nostatus:
4931 if nostatus:
4925 ui.write("%s\n" % f)
4932 ui.write("%s\n" % f)
4926 else:
4933 else:
4927 ui.write("%s %s\n" % (ms[f].upper(), f),
4934 ui.write("%s %s\n" % (ms[f].upper(), f),
4928 label='resolve.' +
4935 label='resolve.' +
4929 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4936 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
4930 elif mark:
4937 elif mark:
4931 ms.mark(f, "r")
4938 ms.mark(f, "r")
4932 elif unmark:
4939 elif unmark:
4933 ms.mark(f, "u")
4940 ms.mark(f, "u")
4934 else:
4941 else:
4935 wctx = repo[None]
4942 wctx = repo[None]
4936 mctx = wctx.parents()[-1]
4943 mctx = wctx.parents()[-1]
4937
4944
4938 # backup pre-resolve (merge uses .orig for its own purposes)
4945 # backup pre-resolve (merge uses .orig for its own purposes)
4939 a = repo.wjoin(f)
4946 a = repo.wjoin(f)
4940 util.copyfile(a, a + ".resolve")
4947 util.copyfile(a, a + ".resolve")
4941
4948
4942 try:
4949 try:
4943 # resolve file
4950 # resolve file
4944 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4951 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
4945 if ms.resolve(f, wctx, mctx):
4952 if ms.resolve(f, wctx, mctx):
4946 ret = 1
4953 ret = 1
4947 finally:
4954 finally:
4948 ui.setconfig('ui', 'forcemerge', '')
4955 ui.setconfig('ui', 'forcemerge', '')
4949 ms.commit()
4956 ms.commit()
4950
4957
4951 # replace filemerge's .orig file with our resolve file
4958 # replace filemerge's .orig file with our resolve file
4952 util.rename(a + ".resolve", a + ".orig")
4959 util.rename(a + ".resolve", a + ".orig")
4953
4960
4954 ms.commit()
4961 ms.commit()
4955 return ret
4962 return ret
4956
4963
4957 @command('revert',
4964 @command('revert',
4958 [('a', 'all', None, _('revert all changes when no arguments given')),
4965 [('a', 'all', None, _('revert all changes when no arguments given')),
4959 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4966 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
4960 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4967 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
4961 ('C', 'no-backup', None, _('do not save backup copies of files')),
4968 ('C', 'no-backup', None, _('do not save backup copies of files')),
4962 ] + walkopts + dryrunopts,
4969 ] + walkopts + dryrunopts,
4963 _('[OPTION]... [-r REV] [NAME]...'))
4970 _('[OPTION]... [-r REV] [NAME]...'))
4964 def revert(ui, repo, *pats, **opts):
4971 def revert(ui, repo, *pats, **opts):
4965 """restore files to their checkout state
4972 """restore files to their checkout state
4966
4973
4967 .. note::
4974 .. note::
4968
4975
4969 To check out earlier revisions, you should use :hg:`update REV`.
4976 To check out earlier revisions, you should use :hg:`update REV`.
4970 To cancel an uncommitted merge (and lose your changes),
4977 To cancel an uncommitted merge (and lose your changes),
4971 use :hg:`update --clean .`.
4978 use :hg:`update --clean .`.
4972
4979
4973 With no revision specified, revert the specified files or directories
4980 With no revision specified, revert the specified files or directories
4974 to the contents they had in the parent of the working directory.
4981 to the contents they had in the parent of the working directory.
4975 This restores the contents of files to an unmodified
4982 This restores the contents of files to an unmodified
4976 state and unschedules adds, removes, copies, and renames. If the
4983 state and unschedules adds, removes, copies, and renames. If the
4977 working directory has two parents, you must explicitly specify a
4984 working directory has two parents, you must explicitly specify a
4978 revision.
4985 revision.
4979
4986
4980 Using the -r/--rev or -d/--date options, revert the given files or
4987 Using the -r/--rev or -d/--date options, revert the given files or
4981 directories to their states as of a specific revision. Because
4988 directories to their states as of a specific revision. Because
4982 revert does not change the working directory parents, this will
4989 revert does not change the working directory parents, this will
4983 cause these files to appear modified. This can be helpful to "back
4990 cause these files to appear modified. This can be helpful to "back
4984 out" some or all of an earlier change. See :hg:`backout` for a
4991 out" some or all of an earlier change. See :hg:`backout` for a
4985 related method.
4992 related method.
4986
4993
4987 Modified files are saved with a .orig suffix before reverting.
4994 Modified files are saved with a .orig suffix before reverting.
4988 To disable these backups, use --no-backup.
4995 To disable these backups, use --no-backup.
4989
4996
4990 See :hg:`help dates` for a list of formats valid for -d/--date.
4997 See :hg:`help dates` for a list of formats valid for -d/--date.
4991
4998
4992 Returns 0 on success.
4999 Returns 0 on success.
4993 """
5000 """
4994
5001
4995 if opts.get("date"):
5002 if opts.get("date"):
4996 if opts.get("rev"):
5003 if opts.get("rev"):
4997 raise util.Abort(_("you can't specify a revision and a date"))
5004 raise util.Abort(_("you can't specify a revision and a date"))
4998 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5005 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
4999
5006
5000 parent, p2 = repo.dirstate.parents()
5007 parent, p2 = repo.dirstate.parents()
5001 if not opts.get('rev') and p2 != nullid:
5008 if not opts.get('rev') and p2 != nullid:
5002 # revert after merge is a trap for new users (issue2915)
5009 # revert after merge is a trap for new users (issue2915)
5003 raise util.Abort(_('uncommitted merge with no revision specified'),
5010 raise util.Abort(_('uncommitted merge with no revision specified'),
5004 hint=_('use "hg update" or see "hg help revert"'))
5011 hint=_('use "hg update" or see "hg help revert"'))
5005
5012
5006 ctx = scmutil.revsingle(repo, opts.get('rev'))
5013 ctx = scmutil.revsingle(repo, opts.get('rev'))
5007
5014
5008 if not pats and not opts.get('all'):
5015 if not pats and not opts.get('all'):
5009 msg = _("no files or directories specified")
5016 msg = _("no files or directories specified")
5010 if p2 != nullid:
5017 if p2 != nullid:
5011 hint = _("uncommitted merge, use --all to discard all changes,"
5018 hint = _("uncommitted merge, use --all to discard all changes,"
5012 " or 'hg update -C .' to abort the merge")
5019 " or 'hg update -C .' to abort the merge")
5013 raise util.Abort(msg, hint=hint)
5020 raise util.Abort(msg, hint=hint)
5014 dirty = util.any(repo.status())
5021 dirty = util.any(repo.status())
5015 node = ctx.node()
5022 node = ctx.node()
5016 if node != parent:
5023 if node != parent:
5017 if dirty:
5024 if dirty:
5018 hint = _("uncommitted changes, use --all to discard all"
5025 hint = _("uncommitted changes, use --all to discard all"
5019 " changes, or 'hg update %s' to update") % ctx.rev()
5026 " changes, or 'hg update %s' to update") % ctx.rev()
5020 else:
5027 else:
5021 hint = _("use --all to revert all files,"
5028 hint = _("use --all to revert all files,"
5022 " or 'hg update %s' to update") % ctx.rev()
5029 " or 'hg update %s' to update") % ctx.rev()
5023 elif dirty:
5030 elif dirty:
5024 hint = _("uncommitted changes, use --all to discard all changes")
5031 hint = _("uncommitted changes, use --all to discard all changes")
5025 else:
5032 else:
5026 hint = _("use --all to revert all files")
5033 hint = _("use --all to revert all files")
5027 raise util.Abort(msg, hint=hint)
5034 raise util.Abort(msg, hint=hint)
5028
5035
5029 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5036 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5030
5037
5031 @command('rollback', dryrunopts +
5038 @command('rollback', dryrunopts +
5032 [('f', 'force', False, _('ignore safety measures'))])
5039 [('f', 'force', False, _('ignore safety measures'))])
5033 def rollback(ui, repo, **opts):
5040 def rollback(ui, repo, **opts):
5034 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5041 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5035
5042
5036 Please use :hg:`commit --amend` instead of rollback to correct
5043 Please use :hg:`commit --amend` instead of rollback to correct
5037 mistakes in the last commit.
5044 mistakes in the last commit.
5038
5045
5039 This command should be used with care. There is only one level of
5046 This command should be used with care. There is only one level of
5040 rollback, and there is no way to undo a rollback. It will also
5047 rollback, and there is no way to undo a rollback. It will also
5041 restore the dirstate at the time of the last transaction, losing
5048 restore the dirstate at the time of the last transaction, losing
5042 any dirstate changes since that time. This command does not alter
5049 any dirstate changes since that time. This command does not alter
5043 the working directory.
5050 the working directory.
5044
5051
5045 Transactions are used to encapsulate the effects of all commands
5052 Transactions are used to encapsulate the effects of all commands
5046 that create new changesets or propagate existing changesets into a
5053 that create new changesets or propagate existing changesets into a
5047 repository.
5054 repository.
5048
5055
5049 .. container:: verbose
5056 .. container:: verbose
5050
5057
5051 For example, the following commands are transactional, and their
5058 For example, the following commands are transactional, and their
5052 effects can be rolled back:
5059 effects can be rolled back:
5053
5060
5054 - commit
5061 - commit
5055 - import
5062 - import
5056 - pull
5063 - pull
5057 - push (with this repository as the destination)
5064 - push (with this repository as the destination)
5058 - unbundle
5065 - unbundle
5059
5066
5060 To avoid permanent data loss, rollback will refuse to rollback a
5067 To avoid permanent data loss, rollback will refuse to rollback a
5061 commit transaction if it isn't checked out. Use --force to
5068 commit transaction if it isn't checked out. Use --force to
5062 override this protection.
5069 override this protection.
5063
5070
5064 This command is not intended for use on public repositories. Once
5071 This command is not intended for use on public repositories. Once
5065 changes are visible for pull by other users, rolling a transaction
5072 changes are visible for pull by other users, rolling a transaction
5066 back locally is ineffective (someone else may already have pulled
5073 back locally is ineffective (someone else may already have pulled
5067 the changes). Furthermore, a race is possible with readers of the
5074 the changes). Furthermore, a race is possible with readers of the
5068 repository; for example an in-progress pull from the repository
5075 repository; for example an in-progress pull from the repository
5069 may fail if a rollback is performed.
5076 may fail if a rollback is performed.
5070
5077
5071 Returns 0 on success, 1 if no rollback data is available.
5078 Returns 0 on success, 1 if no rollback data is available.
5072 """
5079 """
5073 return repo.rollback(dryrun=opts.get('dry_run'),
5080 return repo.rollback(dryrun=opts.get('dry_run'),
5074 force=opts.get('force'))
5081 force=opts.get('force'))
5075
5082
5076 @command('root', [])
5083 @command('root', [])
5077 def root(ui, repo):
5084 def root(ui, repo):
5078 """print the root (top) of the current working directory
5085 """print the root (top) of the current working directory
5079
5086
5080 Print the root directory of the current repository.
5087 Print the root directory of the current repository.
5081
5088
5082 Returns 0 on success.
5089 Returns 0 on success.
5083 """
5090 """
5084 ui.write(repo.root + "\n")
5091 ui.write(repo.root + "\n")
5085
5092
5086 @command('^serve',
5093 @command('^serve',
5087 [('A', 'accesslog', '', _('name of access log file to write to'),
5094 [('A', 'accesslog', '', _('name of access log file to write to'),
5088 _('FILE')),
5095 _('FILE')),
5089 ('d', 'daemon', None, _('run server in background')),
5096 ('d', 'daemon', None, _('run server in background')),
5090 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5097 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5091 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5098 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5092 # use string type, then we can check if something was passed
5099 # use string type, then we can check if something was passed
5093 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5100 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5094 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5101 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5095 _('ADDR')),
5102 _('ADDR')),
5096 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5103 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5097 _('PREFIX')),
5104 _('PREFIX')),
5098 ('n', 'name', '',
5105 ('n', 'name', '',
5099 _('name to show in web pages (default: working directory)'), _('NAME')),
5106 _('name to show in web pages (default: working directory)'), _('NAME')),
5100 ('', 'web-conf', '',
5107 ('', 'web-conf', '',
5101 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5108 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5102 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5109 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5103 _('FILE')),
5110 _('FILE')),
5104 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5111 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5105 ('', 'stdio', None, _('for remote clients')),
5112 ('', 'stdio', None, _('for remote clients')),
5106 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5113 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5107 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5114 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5108 ('', 'style', '', _('template style to use'), _('STYLE')),
5115 ('', 'style', '', _('template style to use'), _('STYLE')),
5109 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5116 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5110 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5117 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5111 _('[OPTION]...'))
5118 _('[OPTION]...'))
5112 def serve(ui, repo, **opts):
5119 def serve(ui, repo, **opts):
5113 """start stand-alone webserver
5120 """start stand-alone webserver
5114
5121
5115 Start a local HTTP repository browser and pull server. You can use
5122 Start a local HTTP repository browser and pull server. You can use
5116 this for ad-hoc sharing and browsing of repositories. It is
5123 this for ad-hoc sharing and browsing of repositories. It is
5117 recommended to use a real web server to serve a repository for
5124 recommended to use a real web server to serve a repository for
5118 longer periods of time.
5125 longer periods of time.
5119
5126
5120 Please note that the server does not implement access control.
5127 Please note that the server does not implement access control.
5121 This means that, by default, anybody can read from the server and
5128 This means that, by default, anybody can read from the server and
5122 nobody can write to it by default. Set the ``web.allow_push``
5129 nobody can write to it by default. Set the ``web.allow_push``
5123 option to ``*`` to allow everybody to push to the server. You
5130 option to ``*`` to allow everybody to push to the server. You
5124 should use a real web server if you need to authenticate users.
5131 should use a real web server if you need to authenticate users.
5125
5132
5126 By default, the server logs accesses to stdout and errors to
5133 By default, the server logs accesses to stdout and errors to
5127 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5134 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5128 files.
5135 files.
5129
5136
5130 To have the server choose a free port number to listen on, specify
5137 To have the server choose a free port number to listen on, specify
5131 a port number of 0; in this case, the server will print the port
5138 a port number of 0; in this case, the server will print the port
5132 number it uses.
5139 number it uses.
5133
5140
5134 Returns 0 on success.
5141 Returns 0 on success.
5135 """
5142 """
5136
5143
5137 if opts["stdio"] and opts["cmdserver"]:
5144 if opts["stdio"] and opts["cmdserver"]:
5138 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5145 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5139
5146
5140 def checkrepo():
5147 def checkrepo():
5141 if repo is None:
5148 if repo is None:
5142 raise error.RepoError(_("there is no Mercurial repository here"
5149 raise error.RepoError(_("there is no Mercurial repository here"
5143 " (.hg not found)"))
5150 " (.hg not found)"))
5144
5151
5145 if opts["stdio"]:
5152 if opts["stdio"]:
5146 checkrepo()
5153 checkrepo()
5147 s = sshserver.sshserver(ui, repo)
5154 s = sshserver.sshserver(ui, repo)
5148 s.serve_forever()
5155 s.serve_forever()
5149
5156
5150 if opts["cmdserver"]:
5157 if opts["cmdserver"]:
5151 checkrepo()
5158 checkrepo()
5152 s = commandserver.server(ui, repo, opts["cmdserver"])
5159 s = commandserver.server(ui, repo, opts["cmdserver"])
5153 return s.serve()
5160 return s.serve()
5154
5161
5155 # this way we can check if something was given in the command-line
5162 # this way we can check if something was given in the command-line
5156 if opts.get('port'):
5163 if opts.get('port'):
5157 opts['port'] = util.getport(opts.get('port'))
5164 opts['port'] = util.getport(opts.get('port'))
5158
5165
5159 baseui = repo and repo.baseui or ui
5166 baseui = repo and repo.baseui or ui
5160 optlist = ("name templates style address port prefix ipv6"
5167 optlist = ("name templates style address port prefix ipv6"
5161 " accesslog errorlog certificate encoding")
5168 " accesslog errorlog certificate encoding")
5162 for o in optlist.split():
5169 for o in optlist.split():
5163 val = opts.get(o, '')
5170 val = opts.get(o, '')
5164 if val in (None, ''): # should check against default options instead
5171 if val in (None, ''): # should check against default options instead
5165 continue
5172 continue
5166 baseui.setconfig("web", o, val)
5173 baseui.setconfig("web", o, val)
5167 if repo and repo.ui != baseui:
5174 if repo and repo.ui != baseui:
5168 repo.ui.setconfig("web", o, val)
5175 repo.ui.setconfig("web", o, val)
5169
5176
5170 o = opts.get('web_conf') or opts.get('webdir_conf')
5177 o = opts.get('web_conf') or opts.get('webdir_conf')
5171 if not o:
5178 if not o:
5172 if not repo:
5179 if not repo:
5173 raise error.RepoError(_("there is no Mercurial repository"
5180 raise error.RepoError(_("there is no Mercurial repository"
5174 " here (.hg not found)"))
5181 " here (.hg not found)"))
5175 o = repo
5182 o = repo
5176
5183
5177 app = hgweb.hgweb(o, baseui=baseui)
5184 app = hgweb.hgweb(o, baseui=baseui)
5178 service = httpservice(ui, app, opts)
5185 service = httpservice(ui, app, opts)
5179 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5186 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5180
5187
5181 class httpservice(object):
5188 class httpservice(object):
5182 def __init__(self, ui, app, opts):
5189 def __init__(self, ui, app, opts):
5183 self.ui = ui
5190 self.ui = ui
5184 self.app = app
5191 self.app = app
5185 self.opts = opts
5192 self.opts = opts
5186
5193
5187 def init(self):
5194 def init(self):
5188 util.setsignalhandler()
5195 util.setsignalhandler()
5189 self.httpd = hgweb_server.create_server(self.ui, self.app)
5196 self.httpd = hgweb_server.create_server(self.ui, self.app)
5190
5197
5191 if self.opts['port'] and not self.ui.verbose:
5198 if self.opts['port'] and not self.ui.verbose:
5192 return
5199 return
5193
5200
5194 if self.httpd.prefix:
5201 if self.httpd.prefix:
5195 prefix = self.httpd.prefix.strip('/') + '/'
5202 prefix = self.httpd.prefix.strip('/') + '/'
5196 else:
5203 else:
5197 prefix = ''
5204 prefix = ''
5198
5205
5199 port = ':%d' % self.httpd.port
5206 port = ':%d' % self.httpd.port
5200 if port == ':80':
5207 if port == ':80':
5201 port = ''
5208 port = ''
5202
5209
5203 bindaddr = self.httpd.addr
5210 bindaddr = self.httpd.addr
5204 if bindaddr == '0.0.0.0':
5211 if bindaddr == '0.0.0.0':
5205 bindaddr = '*'
5212 bindaddr = '*'
5206 elif ':' in bindaddr: # IPv6
5213 elif ':' in bindaddr: # IPv6
5207 bindaddr = '[%s]' % bindaddr
5214 bindaddr = '[%s]' % bindaddr
5208
5215
5209 fqaddr = self.httpd.fqaddr
5216 fqaddr = self.httpd.fqaddr
5210 if ':' in fqaddr:
5217 if ':' in fqaddr:
5211 fqaddr = '[%s]' % fqaddr
5218 fqaddr = '[%s]' % fqaddr
5212 if self.opts['port']:
5219 if self.opts['port']:
5213 write = self.ui.status
5220 write = self.ui.status
5214 else:
5221 else:
5215 write = self.ui.write
5222 write = self.ui.write
5216 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5223 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5217 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5224 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5218
5225
5219 def run(self):
5226 def run(self):
5220 self.httpd.serve_forever()
5227 self.httpd.serve_forever()
5221
5228
5222
5229
5223 @command('showconfig|debugconfig',
5230 @command('showconfig|debugconfig',
5224 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5231 [('u', 'untrusted', None, _('show untrusted configuration options'))],
5225 _('[-u] [NAME]...'))
5232 _('[-u] [NAME]...'))
5226 def showconfig(ui, repo, *values, **opts):
5233 def showconfig(ui, repo, *values, **opts):
5227 """show combined config settings from all hgrc files
5234 """show combined config settings from all hgrc files
5228
5235
5229 With no arguments, print names and values of all config items.
5236 With no arguments, print names and values of all config items.
5230
5237
5231 With one argument of the form section.name, print just the value
5238 With one argument of the form section.name, print just the value
5232 of that config item.
5239 of that config item.
5233
5240
5234 With multiple arguments, print names and values of all config
5241 With multiple arguments, print names and values of all config
5235 items with matching section names.
5242 items with matching section names.
5236
5243
5237 With --debug, the source (filename and line number) is printed
5244 With --debug, the source (filename and line number) is printed
5238 for each config item.
5245 for each config item.
5239
5246
5240 Returns 0 on success.
5247 Returns 0 on success.
5241 """
5248 """
5242
5249
5243 for f in scmutil.rcpath():
5250 for f in scmutil.rcpath():
5244 ui.debug('read config from: %s\n' % f)
5251 ui.debug('read config from: %s\n' % f)
5245 untrusted = bool(opts.get('untrusted'))
5252 untrusted = bool(opts.get('untrusted'))
5246 if values:
5253 if values:
5247 sections = [v for v in values if '.' not in v]
5254 sections = [v for v in values if '.' not in v]
5248 items = [v for v in values if '.' in v]
5255 items = [v for v in values if '.' in v]
5249 if len(items) > 1 or items and sections:
5256 if len(items) > 1 or items and sections:
5250 raise util.Abort(_('only one config item permitted'))
5257 raise util.Abort(_('only one config item permitted'))
5251 for section, name, value in ui.walkconfig(untrusted=untrusted):
5258 for section, name, value in ui.walkconfig(untrusted=untrusted):
5252 value = str(value).replace('\n', '\\n')
5259 value = str(value).replace('\n', '\\n')
5253 sectname = section + '.' + name
5260 sectname = section + '.' + name
5254 if values:
5261 if values:
5255 for v in values:
5262 for v in values:
5256 if v == section:
5263 if v == section:
5257 ui.debug('%s: ' %
5264 ui.debug('%s: ' %
5258 ui.configsource(section, name, untrusted))
5265 ui.configsource(section, name, untrusted))
5259 ui.write('%s=%s\n' % (sectname, value))
5266 ui.write('%s=%s\n' % (sectname, value))
5260 elif v == sectname:
5267 elif v == sectname:
5261 ui.debug('%s: ' %
5268 ui.debug('%s: ' %
5262 ui.configsource(section, name, untrusted))
5269 ui.configsource(section, name, untrusted))
5263 ui.write(value, '\n')
5270 ui.write(value, '\n')
5264 else:
5271 else:
5265 ui.debug('%s: ' %
5272 ui.debug('%s: ' %
5266 ui.configsource(section, name, untrusted))
5273 ui.configsource(section, name, untrusted))
5267 ui.write('%s=%s\n' % (sectname, value))
5274 ui.write('%s=%s\n' % (sectname, value))
5268
5275
5269 @command('^status|st',
5276 @command('^status|st',
5270 [('A', 'all', None, _('show status of all files')),
5277 [('A', 'all', None, _('show status of all files')),
5271 ('m', 'modified', None, _('show only modified files')),
5278 ('m', 'modified', None, _('show only modified files')),
5272 ('a', 'added', None, _('show only added files')),
5279 ('a', 'added', None, _('show only added files')),
5273 ('r', 'removed', None, _('show only removed files')),
5280 ('r', 'removed', None, _('show only removed files')),
5274 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5281 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5275 ('c', 'clean', None, _('show only files without changes')),
5282 ('c', 'clean', None, _('show only files without changes')),
5276 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5283 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5277 ('i', 'ignored', None, _('show only ignored files')),
5284 ('i', 'ignored', None, _('show only ignored files')),
5278 ('n', 'no-status', None, _('hide status prefix')),
5285 ('n', 'no-status', None, _('hide status prefix')),
5279 ('C', 'copies', None, _('show source of copied files')),
5286 ('C', 'copies', None, _('show source of copied files')),
5280 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5287 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5281 ('', 'rev', [], _('show difference from revision'), _('REV')),
5288 ('', 'rev', [], _('show difference from revision'), _('REV')),
5282 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5289 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5283 ] + walkopts + subrepoopts,
5290 ] + walkopts + subrepoopts,
5284 _('[OPTION]... [FILE]...'))
5291 _('[OPTION]... [FILE]...'))
5285 def status(ui, repo, *pats, **opts):
5292 def status(ui, repo, *pats, **opts):
5286 """show changed files in the working directory
5293 """show changed files in the working directory
5287
5294
5288 Show status of files in the repository. If names are given, only
5295 Show status of files in the repository. If names are given, only
5289 files that match are shown. Files that are clean or ignored or
5296 files that match are shown. Files that are clean or ignored or
5290 the source of a copy/move operation, are not listed unless
5297 the source of a copy/move operation, are not listed unless
5291 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5298 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5292 Unless options described with "show only ..." are given, the
5299 Unless options described with "show only ..." are given, the
5293 options -mardu are used.
5300 options -mardu are used.
5294
5301
5295 Option -q/--quiet hides untracked (unknown and ignored) files
5302 Option -q/--quiet hides untracked (unknown and ignored) files
5296 unless explicitly requested with -u/--unknown or -i/--ignored.
5303 unless explicitly requested with -u/--unknown or -i/--ignored.
5297
5304
5298 .. note::
5305 .. note::
5299
5306
5300 status may appear to disagree with diff if permissions have
5307 status may appear to disagree with diff if permissions have
5301 changed or a merge has occurred. The standard diff format does
5308 changed or a merge has occurred. The standard diff format does
5302 not report permission changes and diff only reports changes
5309 not report permission changes and diff only reports changes
5303 relative to one merge parent.
5310 relative to one merge parent.
5304
5311
5305 If one revision is given, it is used as the base revision.
5312 If one revision is given, it is used as the base revision.
5306 If two revisions are given, the differences between them are
5313 If two revisions are given, the differences between them are
5307 shown. The --change option can also be used as a shortcut to list
5314 shown. The --change option can also be used as a shortcut to list
5308 the changed files of a revision from its first parent.
5315 the changed files of a revision from its first parent.
5309
5316
5310 The codes used to show the status of files are::
5317 The codes used to show the status of files are::
5311
5318
5312 M = modified
5319 M = modified
5313 A = added
5320 A = added
5314 R = removed
5321 R = removed
5315 C = clean
5322 C = clean
5316 ! = missing (deleted by non-hg command, but still tracked)
5323 ! = missing (deleted by non-hg command, but still tracked)
5317 ? = not tracked
5324 ? = not tracked
5318 I = ignored
5325 I = ignored
5319 = origin of the previous file listed as A (added)
5326 = origin of the previous file listed as A (added)
5320
5327
5321 .. container:: verbose
5328 .. container:: verbose
5322
5329
5323 Examples:
5330 Examples:
5324
5331
5325 - show changes in the working directory relative to a
5332 - show changes in the working directory relative to a
5326 changeset::
5333 changeset::
5327
5334
5328 hg status --rev 9353
5335 hg status --rev 9353
5329
5336
5330 - show all changes including copies in an existing changeset::
5337 - show all changes including copies in an existing changeset::
5331
5338
5332 hg status --copies --change 9353
5339 hg status --copies --change 9353
5333
5340
5334 - get a NUL separated list of added files, suitable for xargs::
5341 - get a NUL separated list of added files, suitable for xargs::
5335
5342
5336 hg status -an0
5343 hg status -an0
5337
5344
5338 Returns 0 on success.
5345 Returns 0 on success.
5339 """
5346 """
5340
5347
5341 revs = opts.get('rev')
5348 revs = opts.get('rev')
5342 change = opts.get('change')
5349 change = opts.get('change')
5343
5350
5344 if revs and change:
5351 if revs and change:
5345 msg = _('cannot specify --rev and --change at the same time')
5352 msg = _('cannot specify --rev and --change at the same time')
5346 raise util.Abort(msg)
5353 raise util.Abort(msg)
5347 elif change:
5354 elif change:
5348 node2 = scmutil.revsingle(repo, change, None).node()
5355 node2 = scmutil.revsingle(repo, change, None).node()
5349 node1 = repo[node2].p1().node()
5356 node1 = repo[node2].p1().node()
5350 else:
5357 else:
5351 node1, node2 = scmutil.revpair(repo, revs)
5358 node1, node2 = scmutil.revpair(repo, revs)
5352
5359
5353 cwd = (pats and repo.getcwd()) or ''
5360 cwd = (pats and repo.getcwd()) or ''
5354 end = opts.get('print0') and '\0' or '\n'
5361 end = opts.get('print0') and '\0' or '\n'
5355 copy = {}
5362 copy = {}
5356 states = 'modified added removed deleted unknown ignored clean'.split()
5363 states = 'modified added removed deleted unknown ignored clean'.split()
5357 show = [k for k in states if opts.get(k)]
5364 show = [k for k in states if opts.get(k)]
5358 if opts.get('all'):
5365 if opts.get('all'):
5359 show += ui.quiet and (states[:4] + ['clean']) or states
5366 show += ui.quiet and (states[:4] + ['clean']) or states
5360 if not show:
5367 if not show:
5361 show = ui.quiet and states[:4] or states[:5]
5368 show = ui.quiet and states[:4] or states[:5]
5362
5369
5363 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5370 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5364 'ignored' in show, 'clean' in show, 'unknown' in show,
5371 'ignored' in show, 'clean' in show, 'unknown' in show,
5365 opts.get('subrepos'))
5372 opts.get('subrepos'))
5366 changestates = zip(states, 'MAR!?IC', stat)
5373 changestates = zip(states, 'MAR!?IC', stat)
5367
5374
5368 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5375 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5369 copy = copies.pathcopies(repo[node1], repo[node2])
5376 copy = copies.pathcopies(repo[node1], repo[node2])
5370
5377
5371 fm = ui.formatter('status', opts)
5378 fm = ui.formatter('status', opts)
5372 fmt = '%s' + end
5379 fmt = '%s' + end
5373 showchar = not opts.get('no_status')
5380 showchar = not opts.get('no_status')
5374
5381
5375 for state, char, files in changestates:
5382 for state, char, files in changestates:
5376 if state in show:
5383 if state in show:
5377 label = 'status.' + state
5384 label = 'status.' + state
5378 for f in files:
5385 for f in files:
5379 fm.startitem()
5386 fm.startitem()
5380 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5387 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5381 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5388 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5382 if f in copy:
5389 if f in copy:
5383 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5390 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5384 label='status.copied')
5391 label='status.copied')
5385 fm.end()
5392 fm.end()
5386
5393
5387 @command('^summary|sum',
5394 @command('^summary|sum',
5388 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5395 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5389 def summary(ui, repo, **opts):
5396 def summary(ui, repo, **opts):
5390 """summarize working directory state
5397 """summarize working directory state
5391
5398
5392 This generates a brief summary of the working directory state,
5399 This generates a brief summary of the working directory state,
5393 including parents, branch, commit status, and available updates.
5400 including parents, branch, commit status, and available updates.
5394
5401
5395 With the --remote option, this will check the default paths for
5402 With the --remote option, this will check the default paths for
5396 incoming and outgoing changes. This can be time-consuming.
5403 incoming and outgoing changes. This can be time-consuming.
5397
5404
5398 Returns 0 on success.
5405 Returns 0 on success.
5399 """
5406 """
5400
5407
5401 ctx = repo[None]
5408 ctx = repo[None]
5402 parents = ctx.parents()
5409 parents = ctx.parents()
5403 pnode = parents[0].node()
5410 pnode = parents[0].node()
5404 marks = []
5411 marks = []
5405
5412
5406 for p in parents:
5413 for p in parents:
5407 # label with log.changeset (instead of log.parent) since this
5414 # label with log.changeset (instead of log.parent) since this
5408 # shows a working directory parent *changeset*:
5415 # shows a working directory parent *changeset*:
5409 # i18n: column positioning for "hg summary"
5416 # i18n: column positioning for "hg summary"
5410 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5417 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5411 label='log.changeset changeset.%s' % p.phasestr())
5418 label='log.changeset changeset.%s' % p.phasestr())
5412 ui.write(' '.join(p.tags()), label='log.tag')
5419 ui.write(' '.join(p.tags()), label='log.tag')
5413 if p.bookmarks():
5420 if p.bookmarks():
5414 marks.extend(p.bookmarks())
5421 marks.extend(p.bookmarks())
5415 if p.rev() == -1:
5422 if p.rev() == -1:
5416 if not len(repo):
5423 if not len(repo):
5417 ui.write(_(' (empty repository)'))
5424 ui.write(_(' (empty repository)'))
5418 else:
5425 else:
5419 ui.write(_(' (no revision checked out)'))
5426 ui.write(_(' (no revision checked out)'))
5420 ui.write('\n')
5427 ui.write('\n')
5421 if p.description():
5428 if p.description():
5422 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5429 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5423 label='log.summary')
5430 label='log.summary')
5424
5431
5425 branch = ctx.branch()
5432 branch = ctx.branch()
5426 bheads = repo.branchheads(branch)
5433 bheads = repo.branchheads(branch)
5427 # i18n: column positioning for "hg summary"
5434 # i18n: column positioning for "hg summary"
5428 m = _('branch: %s\n') % branch
5435 m = _('branch: %s\n') % branch
5429 if branch != 'default':
5436 if branch != 'default':
5430 ui.write(m, label='log.branch')
5437 ui.write(m, label='log.branch')
5431 else:
5438 else:
5432 ui.status(m, label='log.branch')
5439 ui.status(m, label='log.branch')
5433
5440
5434 if marks:
5441 if marks:
5435 current = repo._bookmarkcurrent
5442 current = repo._bookmarkcurrent
5436 # i18n: column positioning for "hg summary"
5443 # i18n: column positioning for "hg summary"
5437 ui.write(_('bookmarks:'), label='log.bookmark')
5444 ui.write(_('bookmarks:'), label='log.bookmark')
5438 if current is not None:
5445 if current is not None:
5439 if current in marks:
5446 if current in marks:
5440 ui.write(' *' + current, label='bookmarks.current')
5447 ui.write(' *' + current, label='bookmarks.current')
5441 marks.remove(current)
5448 marks.remove(current)
5442 else:
5449 else:
5443 ui.write(' [%s]' % current, label='bookmarks.current')
5450 ui.write(' [%s]' % current, label='bookmarks.current')
5444 for m in marks:
5451 for m in marks:
5445 ui.write(' ' + m, label='log.bookmark')
5452 ui.write(' ' + m, label='log.bookmark')
5446 ui.write('\n', label='log.bookmark')
5453 ui.write('\n', label='log.bookmark')
5447
5454
5448 st = list(repo.status(unknown=True))[:6]
5455 st = list(repo.status(unknown=True))[:6]
5449
5456
5450 c = repo.dirstate.copies()
5457 c = repo.dirstate.copies()
5451 copied, renamed = [], []
5458 copied, renamed = [], []
5452 for d, s in c.iteritems():
5459 for d, s in c.iteritems():
5453 if s in st[2]:
5460 if s in st[2]:
5454 st[2].remove(s)
5461 st[2].remove(s)
5455 renamed.append(d)
5462 renamed.append(d)
5456 else:
5463 else:
5457 copied.append(d)
5464 copied.append(d)
5458 if d in st[1]:
5465 if d in st[1]:
5459 st[1].remove(d)
5466 st[1].remove(d)
5460 st.insert(3, renamed)
5467 st.insert(3, renamed)
5461 st.insert(4, copied)
5468 st.insert(4, copied)
5462
5469
5463 ms = mergemod.mergestate(repo)
5470 ms = mergemod.mergestate(repo)
5464 st.append([f for f in ms if ms[f] == 'u'])
5471 st.append([f for f in ms if ms[f] == 'u'])
5465
5472
5466 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5473 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5467 st.append(subs)
5474 st.append(subs)
5468
5475
5469 labels = [ui.label(_('%d modified'), 'status.modified'),
5476 labels = [ui.label(_('%d modified'), 'status.modified'),
5470 ui.label(_('%d added'), 'status.added'),
5477 ui.label(_('%d added'), 'status.added'),
5471 ui.label(_('%d removed'), 'status.removed'),
5478 ui.label(_('%d removed'), 'status.removed'),
5472 ui.label(_('%d renamed'), 'status.copied'),
5479 ui.label(_('%d renamed'), 'status.copied'),
5473 ui.label(_('%d copied'), 'status.copied'),
5480 ui.label(_('%d copied'), 'status.copied'),
5474 ui.label(_('%d deleted'), 'status.deleted'),
5481 ui.label(_('%d deleted'), 'status.deleted'),
5475 ui.label(_('%d unknown'), 'status.unknown'),
5482 ui.label(_('%d unknown'), 'status.unknown'),
5476 ui.label(_('%d ignored'), 'status.ignored'),
5483 ui.label(_('%d ignored'), 'status.ignored'),
5477 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5484 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5478 ui.label(_('%d subrepos'), 'status.modified')]
5485 ui.label(_('%d subrepos'), 'status.modified')]
5479 t = []
5486 t = []
5480 for s, l in zip(st, labels):
5487 for s, l in zip(st, labels):
5481 if s:
5488 if s:
5482 t.append(l % len(s))
5489 t.append(l % len(s))
5483
5490
5484 t = ', '.join(t)
5491 t = ', '.join(t)
5485 cleanworkdir = False
5492 cleanworkdir = False
5486
5493
5487 if repo.vfs.exists('updatestate'):
5494 if repo.vfs.exists('updatestate'):
5488 t += _(' (interrupted update)')
5495 t += _(' (interrupted update)')
5489 elif len(parents) > 1:
5496 elif len(parents) > 1:
5490 t += _(' (merge)')
5497 t += _(' (merge)')
5491 elif branch != parents[0].branch():
5498 elif branch != parents[0].branch():
5492 t += _(' (new branch)')
5499 t += _(' (new branch)')
5493 elif (parents[0].closesbranch() and
5500 elif (parents[0].closesbranch() and
5494 pnode in repo.branchheads(branch, closed=True)):
5501 pnode in repo.branchheads(branch, closed=True)):
5495 t += _(' (head closed)')
5502 t += _(' (head closed)')
5496 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5503 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5497 t += _(' (clean)')
5504 t += _(' (clean)')
5498 cleanworkdir = True
5505 cleanworkdir = True
5499 elif pnode not in bheads:
5506 elif pnode not in bheads:
5500 t += _(' (new branch head)')
5507 t += _(' (new branch head)')
5501
5508
5502 if cleanworkdir:
5509 if cleanworkdir:
5503 # i18n: column positioning for "hg summary"
5510 # i18n: column positioning for "hg summary"
5504 ui.status(_('commit: %s\n') % t.strip())
5511 ui.status(_('commit: %s\n') % t.strip())
5505 else:
5512 else:
5506 # i18n: column positioning for "hg summary"
5513 # i18n: column positioning for "hg summary"
5507 ui.write(_('commit: %s\n') % t.strip())
5514 ui.write(_('commit: %s\n') % t.strip())
5508
5515
5509 # all ancestors of branch heads - all ancestors of parent = new csets
5516 # all ancestors of branch heads - all ancestors of parent = new csets
5510 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5517 new = len(repo.changelog.findmissing([ctx.node() for ctx in parents],
5511 bheads))
5518 bheads))
5512
5519
5513 if new == 0:
5520 if new == 0:
5514 # i18n: column positioning for "hg summary"
5521 # i18n: column positioning for "hg summary"
5515 ui.status(_('update: (current)\n'))
5522 ui.status(_('update: (current)\n'))
5516 elif pnode not in bheads:
5523 elif pnode not in bheads:
5517 # i18n: column positioning for "hg summary"
5524 # i18n: column positioning for "hg summary"
5518 ui.write(_('update: %d new changesets (update)\n') % new)
5525 ui.write(_('update: %d new changesets (update)\n') % new)
5519 else:
5526 else:
5520 # i18n: column positioning for "hg summary"
5527 # i18n: column positioning for "hg summary"
5521 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5528 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5522 (new, len(bheads)))
5529 (new, len(bheads)))
5523
5530
5524 cmdutil.summaryhooks(ui, repo)
5531 cmdutil.summaryhooks(ui, repo)
5525
5532
5526 if opts.get('remote'):
5533 if opts.get('remote'):
5527 t = []
5534 t = []
5528 source, branches = hg.parseurl(ui.expandpath('default'))
5535 source, branches = hg.parseurl(ui.expandpath('default'))
5529 sbranch = branches[0]
5536 sbranch = branches[0]
5530 other = hg.peer(repo, {}, source)
5537 other = hg.peer(repo, {}, source)
5531 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5538 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5532 if revs:
5539 if revs:
5533 revs = [other.lookup(rev) for rev in revs]
5540 revs = [other.lookup(rev) for rev in revs]
5534 ui.debug('comparing with %s\n' % util.hidepassword(source))
5541 ui.debug('comparing with %s\n' % util.hidepassword(source))
5535 repo.ui.pushbuffer()
5542 repo.ui.pushbuffer()
5536 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5543 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5537 _common, incoming, _rheads = commoninc
5544 _common, incoming, _rheads = commoninc
5538 repo.ui.popbuffer()
5545 repo.ui.popbuffer()
5539 if incoming:
5546 if incoming:
5540 t.append(_('1 or more incoming'))
5547 t.append(_('1 or more incoming'))
5541
5548
5542 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5549 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5543 dbranch = branches[0]
5550 dbranch = branches[0]
5544 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5551 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5545 if source != dest:
5552 if source != dest:
5546 other = hg.peer(repo, {}, dest)
5553 other = hg.peer(repo, {}, dest)
5547 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5554 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5548 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5555 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5549 commoninc = None
5556 commoninc = None
5550 if revs:
5557 if revs:
5551 revs = [repo.lookup(rev) for rev in revs]
5558 revs = [repo.lookup(rev) for rev in revs]
5552 repo.ui.pushbuffer()
5559 repo.ui.pushbuffer()
5553 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5560 outgoing = discovery.findcommonoutgoing(repo, other, onlyheads=revs,
5554 commoninc=commoninc)
5561 commoninc=commoninc)
5555 repo.ui.popbuffer()
5562 repo.ui.popbuffer()
5556 o = outgoing.missing
5563 o = outgoing.missing
5557 if o:
5564 if o:
5558 t.append(_('%d outgoing') % len(o))
5565 t.append(_('%d outgoing') % len(o))
5559 if 'bookmarks' in other.listkeys('namespaces'):
5566 if 'bookmarks' in other.listkeys('namespaces'):
5560 lmarks = repo.listkeys('bookmarks')
5567 lmarks = repo.listkeys('bookmarks')
5561 rmarks = other.listkeys('bookmarks')
5568 rmarks = other.listkeys('bookmarks')
5562 diff = set(rmarks) - set(lmarks)
5569 diff = set(rmarks) - set(lmarks)
5563 if len(diff) > 0:
5570 if len(diff) > 0:
5564 t.append(_('%d incoming bookmarks') % len(diff))
5571 t.append(_('%d incoming bookmarks') % len(diff))
5565 diff = set(lmarks) - set(rmarks)
5572 diff = set(lmarks) - set(rmarks)
5566 if len(diff) > 0:
5573 if len(diff) > 0:
5567 t.append(_('%d outgoing bookmarks') % len(diff))
5574 t.append(_('%d outgoing bookmarks') % len(diff))
5568
5575
5569 if t:
5576 if t:
5570 # i18n: column positioning for "hg summary"
5577 # i18n: column positioning for "hg summary"
5571 ui.write(_('remote: %s\n') % (', '.join(t)))
5578 ui.write(_('remote: %s\n') % (', '.join(t)))
5572 else:
5579 else:
5573 # i18n: column positioning for "hg summary"
5580 # i18n: column positioning for "hg summary"
5574 ui.status(_('remote: (synced)\n'))
5581 ui.status(_('remote: (synced)\n'))
5575
5582
5576 @command('tag',
5583 @command('tag',
5577 [('f', 'force', None, _('force tag')),
5584 [('f', 'force', None, _('force tag')),
5578 ('l', 'local', None, _('make the tag local')),
5585 ('l', 'local', None, _('make the tag local')),
5579 ('r', 'rev', '', _('revision to tag'), _('REV')),
5586 ('r', 'rev', '', _('revision to tag'), _('REV')),
5580 ('', 'remove', None, _('remove a tag')),
5587 ('', 'remove', None, _('remove a tag')),
5581 # -l/--local is already there, commitopts cannot be used
5588 # -l/--local is already there, commitopts cannot be used
5582 ('e', 'edit', None, _('edit commit message')),
5589 ('e', 'edit', None, _('edit commit message')),
5583 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5590 ('m', 'message', '', _('use <text> as commit message'), _('TEXT')),
5584 ] + commitopts2,
5591 ] + commitopts2,
5585 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5592 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5586 def tag(ui, repo, name1, *names, **opts):
5593 def tag(ui, repo, name1, *names, **opts):
5587 """add one or more tags for the current or given revision
5594 """add one or more tags for the current or given revision
5588
5595
5589 Name a particular revision using <name>.
5596 Name a particular revision using <name>.
5590
5597
5591 Tags are used to name particular revisions of the repository and are
5598 Tags are used to name particular revisions of the repository and are
5592 very useful to compare different revisions, to go back to significant
5599 very useful to compare different revisions, to go back to significant
5593 earlier versions or to mark branch points as releases, etc. Changing
5600 earlier versions or to mark branch points as releases, etc. Changing
5594 an existing tag is normally disallowed; use -f/--force to override.
5601 an existing tag is normally disallowed; use -f/--force to override.
5595
5602
5596 If no revision is given, the parent of the working directory is
5603 If no revision is given, the parent of the working directory is
5597 used.
5604 used.
5598
5605
5599 To facilitate version control, distribution, and merging of tags,
5606 To facilitate version control, distribution, and merging of tags,
5600 they are stored as a file named ".hgtags" which is managed similarly
5607 they are stored as a file named ".hgtags" which is managed similarly
5601 to other project files and can be hand-edited if necessary. This
5608 to other project files and can be hand-edited if necessary. This
5602 also means that tagging creates a new commit. The file
5609 also means that tagging creates a new commit. The file
5603 ".hg/localtags" is used for local tags (not shared among
5610 ".hg/localtags" is used for local tags (not shared among
5604 repositories).
5611 repositories).
5605
5612
5606 Tag commits are usually made at the head of a branch. If the parent
5613 Tag commits are usually made at the head of a branch. If the parent
5607 of the working directory is not a branch head, :hg:`tag` aborts; use
5614 of the working directory is not a branch head, :hg:`tag` aborts; use
5608 -f/--force to force the tag commit to be based on a non-head
5615 -f/--force to force the tag commit to be based on a non-head
5609 changeset.
5616 changeset.
5610
5617
5611 See :hg:`help dates` for a list of formats valid for -d/--date.
5618 See :hg:`help dates` for a list of formats valid for -d/--date.
5612
5619
5613 Since tag names have priority over branch names during revision
5620 Since tag names have priority over branch names during revision
5614 lookup, using an existing branch name as a tag name is discouraged.
5621 lookup, using an existing branch name as a tag name is discouraged.
5615
5622
5616 Returns 0 on success.
5623 Returns 0 on success.
5617 """
5624 """
5618 wlock = lock = None
5625 wlock = lock = None
5619 try:
5626 try:
5620 wlock = repo.wlock()
5627 wlock = repo.wlock()
5621 lock = repo.lock()
5628 lock = repo.lock()
5622 rev_ = "."
5629 rev_ = "."
5623 names = [t.strip() for t in (name1,) + names]
5630 names = [t.strip() for t in (name1,) + names]
5624 if len(names) != len(set(names)):
5631 if len(names) != len(set(names)):
5625 raise util.Abort(_('tag names must be unique'))
5632 raise util.Abort(_('tag names must be unique'))
5626 for n in names:
5633 for n in names:
5627 scmutil.checknewlabel(repo, n, 'tag')
5634 scmutil.checknewlabel(repo, n, 'tag')
5628 if not n:
5635 if not n:
5629 raise util.Abort(_('tag names cannot consist entirely of '
5636 raise util.Abort(_('tag names cannot consist entirely of '
5630 'whitespace'))
5637 'whitespace'))
5631 if opts.get('rev') and opts.get('remove'):
5638 if opts.get('rev') and opts.get('remove'):
5632 raise util.Abort(_("--rev and --remove are incompatible"))
5639 raise util.Abort(_("--rev and --remove are incompatible"))
5633 if opts.get('rev'):
5640 if opts.get('rev'):
5634 rev_ = opts['rev']
5641 rev_ = opts['rev']
5635 message = opts.get('message')
5642 message = opts.get('message')
5636 if opts.get('remove'):
5643 if opts.get('remove'):
5637 expectedtype = opts.get('local') and 'local' or 'global'
5644 expectedtype = opts.get('local') and 'local' or 'global'
5638 for n in names:
5645 for n in names:
5639 if not repo.tagtype(n):
5646 if not repo.tagtype(n):
5640 raise util.Abort(_("tag '%s' does not exist") % n)
5647 raise util.Abort(_("tag '%s' does not exist") % n)
5641 if repo.tagtype(n) != expectedtype:
5648 if repo.tagtype(n) != expectedtype:
5642 if expectedtype == 'global':
5649 if expectedtype == 'global':
5643 raise util.Abort(_("tag '%s' is not a global tag") % n)
5650 raise util.Abort(_("tag '%s' is not a global tag") % n)
5644 else:
5651 else:
5645 raise util.Abort(_("tag '%s' is not a local tag") % n)
5652 raise util.Abort(_("tag '%s' is not a local tag") % n)
5646 rev_ = nullid
5653 rev_ = nullid
5647 if not message:
5654 if not message:
5648 # we don't translate commit messages
5655 # we don't translate commit messages
5649 message = 'Removed tag %s' % ', '.join(names)
5656 message = 'Removed tag %s' % ', '.join(names)
5650 elif not opts.get('force'):
5657 elif not opts.get('force'):
5651 for n in names:
5658 for n in names:
5652 if n in repo.tags():
5659 if n in repo.tags():
5653 raise util.Abort(_("tag '%s' already exists "
5660 raise util.Abort(_("tag '%s' already exists "
5654 "(use -f to force)") % n)
5661 "(use -f to force)") % n)
5655 if not opts.get('local'):
5662 if not opts.get('local'):
5656 p1, p2 = repo.dirstate.parents()
5663 p1, p2 = repo.dirstate.parents()
5657 if p2 != nullid:
5664 if p2 != nullid:
5658 raise util.Abort(_('uncommitted merge'))
5665 raise util.Abort(_('uncommitted merge'))
5659 bheads = repo.branchheads()
5666 bheads = repo.branchheads()
5660 if not opts.get('force') and bheads and p1 not in bheads:
5667 if not opts.get('force') and bheads and p1 not in bheads:
5661 raise util.Abort(_('not at a branch head (use -f to force)'))
5668 raise util.Abort(_('not at a branch head (use -f to force)'))
5662 r = scmutil.revsingle(repo, rev_).node()
5669 r = scmutil.revsingle(repo, rev_).node()
5663
5670
5664 if not message:
5671 if not message:
5665 # we don't translate commit messages
5672 # we don't translate commit messages
5666 message = ('Added tag %s for changeset %s' %
5673 message = ('Added tag %s for changeset %s' %
5667 (', '.join(names), short(r)))
5674 (', '.join(names), short(r)))
5668
5675
5669 date = opts.get('date')
5676 date = opts.get('date')
5670 if date:
5677 if date:
5671 date = util.parsedate(date)
5678 date = util.parsedate(date)
5672
5679
5673 if opts.get('edit'):
5680 if opts.get('edit'):
5674 message = ui.edit(message, ui.username())
5681 message = ui.edit(message, ui.username())
5675
5682
5676 # don't allow tagging the null rev
5683 # don't allow tagging the null rev
5677 if (not opts.get('remove') and
5684 if (not opts.get('remove') and
5678 scmutil.revsingle(repo, rev_).rev() == nullrev):
5685 scmutil.revsingle(repo, rev_).rev() == nullrev):
5679 raise util.Abort(_("cannot tag null revision"))
5686 raise util.Abort(_("cannot tag null revision"))
5680
5687
5681 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5688 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
5682 finally:
5689 finally:
5683 release(lock, wlock)
5690 release(lock, wlock)
5684
5691
5685 @command('tags', [], '')
5692 @command('tags', [], '')
5686 def tags(ui, repo, **opts):
5693 def tags(ui, repo, **opts):
5687 """list repository tags
5694 """list repository tags
5688
5695
5689 This lists both regular and local tags. When the -v/--verbose
5696 This lists both regular and local tags. When the -v/--verbose
5690 switch is used, a third column "local" is printed for local tags.
5697 switch is used, a third column "local" is printed for local tags.
5691
5698
5692 Returns 0 on success.
5699 Returns 0 on success.
5693 """
5700 """
5694
5701
5695 fm = ui.formatter('tags', opts)
5702 fm = ui.formatter('tags', opts)
5696 hexfunc = ui.debugflag and hex or short
5703 hexfunc = ui.debugflag and hex or short
5697 tagtype = ""
5704 tagtype = ""
5698
5705
5699 for t, n in reversed(repo.tagslist()):
5706 for t, n in reversed(repo.tagslist()):
5700 hn = hexfunc(n)
5707 hn = hexfunc(n)
5701 label = 'tags.normal'
5708 label = 'tags.normal'
5702 tagtype = ''
5709 tagtype = ''
5703 if repo.tagtype(t) == 'local':
5710 if repo.tagtype(t) == 'local':
5704 label = 'tags.local'
5711 label = 'tags.local'
5705 tagtype = 'local'
5712 tagtype = 'local'
5706
5713
5707 fm.startitem()
5714 fm.startitem()
5708 fm.write('tag', '%s', t, label=label)
5715 fm.write('tag', '%s', t, label=label)
5709 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5716 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
5710 fm.condwrite(not ui.quiet, 'rev id', fmt,
5717 fm.condwrite(not ui.quiet, 'rev id', fmt,
5711 repo.changelog.rev(n), hn, label=label)
5718 repo.changelog.rev(n), hn, label=label)
5712 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5719 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
5713 tagtype, label=label)
5720 tagtype, label=label)
5714 fm.plain('\n')
5721 fm.plain('\n')
5715 fm.end()
5722 fm.end()
5716
5723
5717 @command('tip',
5724 @command('tip',
5718 [('p', 'patch', None, _('show patch')),
5725 [('p', 'patch', None, _('show patch')),
5719 ('g', 'git', None, _('use git extended diff format')),
5726 ('g', 'git', None, _('use git extended diff format')),
5720 ] + templateopts,
5727 ] + templateopts,
5721 _('[-p] [-g]'))
5728 _('[-p] [-g]'))
5722 def tip(ui, repo, **opts):
5729 def tip(ui, repo, **opts):
5723 """show the tip revision (DEPRECATED)
5730 """show the tip revision (DEPRECATED)
5724
5731
5725 The tip revision (usually just called the tip) is the changeset
5732 The tip revision (usually just called the tip) is the changeset
5726 most recently added to the repository (and therefore the most
5733 most recently added to the repository (and therefore the most
5727 recently changed head).
5734 recently changed head).
5728
5735
5729 If you have just made a commit, that commit will be the tip. If
5736 If you have just made a commit, that commit will be the tip. If
5730 you have just pulled changes from another repository, the tip of
5737 you have just pulled changes from another repository, the tip of
5731 that repository becomes the current tip. The "tip" tag is special
5738 that repository becomes the current tip. The "tip" tag is special
5732 and cannot be renamed or assigned to a different changeset.
5739 and cannot be renamed or assigned to a different changeset.
5733
5740
5734 This command is deprecated, please use :hg:`heads` instead.
5741 This command is deprecated, please use :hg:`heads` instead.
5735
5742
5736 Returns 0 on success.
5743 Returns 0 on success.
5737 """
5744 """
5738 displayer = cmdutil.show_changeset(ui, repo, opts)
5745 displayer = cmdutil.show_changeset(ui, repo, opts)
5739 displayer.show(repo['tip'])
5746 displayer.show(repo['tip'])
5740 displayer.close()
5747 displayer.close()
5741
5748
5742 @command('unbundle',
5749 @command('unbundle',
5743 [('u', 'update', None,
5750 [('u', 'update', None,
5744 _('update to new branch head if changesets were unbundled'))],
5751 _('update to new branch head if changesets were unbundled'))],
5745 _('[-u] FILE...'))
5752 _('[-u] FILE...'))
5746 def unbundle(ui, repo, fname1, *fnames, **opts):
5753 def unbundle(ui, repo, fname1, *fnames, **opts):
5747 """apply one or more changegroup files
5754 """apply one or more changegroup files
5748
5755
5749 Apply one or more compressed changegroup files generated by the
5756 Apply one or more compressed changegroup files generated by the
5750 bundle command.
5757 bundle command.
5751
5758
5752 Returns 0 on success, 1 if an update has unresolved files.
5759 Returns 0 on success, 1 if an update has unresolved files.
5753 """
5760 """
5754 fnames = (fname1,) + fnames
5761 fnames = (fname1,) + fnames
5755
5762
5756 lock = repo.lock()
5763 lock = repo.lock()
5757 wc = repo['.']
5764 wc = repo['.']
5758 try:
5765 try:
5759 for fname in fnames:
5766 for fname in fnames:
5760 f = hg.openpath(ui, fname)
5767 f = hg.openpath(ui, fname)
5761 gen = changegroup.readbundle(f, fname)
5768 gen = changegroup.readbundle(f, fname)
5762 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5769 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname)
5763 finally:
5770 finally:
5764 lock.release()
5771 lock.release()
5765 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5772 bookmarks.updatecurrentbookmark(repo, wc.node(), wc.branch())
5766 return postincoming(ui, repo, modheads, opts.get('update'), None)
5773 return postincoming(ui, repo, modheads, opts.get('update'), None)
5767
5774
5768 @command('^update|up|checkout|co',
5775 @command('^update|up|checkout|co',
5769 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5776 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
5770 ('c', 'check', None,
5777 ('c', 'check', None,
5771 _('update across branches if no uncommitted changes')),
5778 _('update across branches if no uncommitted changes')),
5772 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5779 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5773 ('r', 'rev', '', _('revision'), _('REV'))],
5780 ('r', 'rev', '', _('revision'), _('REV'))],
5774 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5781 _('[-c] [-C] [-d DATE] [[-r] REV]'))
5775 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5782 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
5776 """update working directory (or switch revisions)
5783 """update working directory (or switch revisions)
5777
5784
5778 Update the repository's working directory to the specified
5785 Update the repository's working directory to the specified
5779 changeset. If no changeset is specified, update to the tip of the
5786 changeset. If no changeset is specified, update to the tip of the
5780 current named branch and move the current bookmark (see :hg:`help
5787 current named branch and move the current bookmark (see :hg:`help
5781 bookmarks`).
5788 bookmarks`).
5782
5789
5783 Update sets the working directory's parent revision to the specified
5790 Update sets the working directory's parent revision to the specified
5784 changeset (see :hg:`help parents`).
5791 changeset (see :hg:`help parents`).
5785
5792
5786 If the changeset is not a descendant or ancestor of the working
5793 If the changeset is not a descendant or ancestor of the working
5787 directory's parent, the update is aborted. With the -c/--check
5794 directory's parent, the update is aborted. With the -c/--check
5788 option, the working directory is checked for uncommitted changes; if
5795 option, the working directory is checked for uncommitted changes; if
5789 none are found, the working directory is updated to the specified
5796 none are found, the working directory is updated to the specified
5790 changeset.
5797 changeset.
5791
5798
5792 .. container:: verbose
5799 .. container:: verbose
5793
5800
5794 The following rules apply when the working directory contains
5801 The following rules apply when the working directory contains
5795 uncommitted changes:
5802 uncommitted changes:
5796
5803
5797 1. If neither -c/--check nor -C/--clean is specified, and if
5804 1. If neither -c/--check nor -C/--clean is specified, and if
5798 the requested changeset is an ancestor or descendant of
5805 the requested changeset is an ancestor or descendant of
5799 the working directory's parent, the uncommitted changes
5806 the working directory's parent, the uncommitted changes
5800 are merged into the requested changeset and the merged
5807 are merged into the requested changeset and the merged
5801 result is left uncommitted. If the requested changeset is
5808 result is left uncommitted. If the requested changeset is
5802 not an ancestor or descendant (that is, it is on another
5809 not an ancestor or descendant (that is, it is on another
5803 branch), the update is aborted and the uncommitted changes
5810 branch), the update is aborted and the uncommitted changes
5804 are preserved.
5811 are preserved.
5805
5812
5806 2. With the -c/--check option, the update is aborted and the
5813 2. With the -c/--check option, the update is aborted and the
5807 uncommitted changes are preserved.
5814 uncommitted changes are preserved.
5808
5815
5809 3. With the -C/--clean option, uncommitted changes are discarded and
5816 3. With the -C/--clean option, uncommitted changes are discarded and
5810 the working directory is updated to the requested changeset.
5817 the working directory is updated to the requested changeset.
5811
5818
5812 To cancel an uncommitted merge (and lose your changes), use
5819 To cancel an uncommitted merge (and lose your changes), use
5813 :hg:`update --clean .`.
5820 :hg:`update --clean .`.
5814
5821
5815 Use null as the changeset to remove the working directory (like
5822 Use null as the changeset to remove the working directory (like
5816 :hg:`clone -U`).
5823 :hg:`clone -U`).
5817
5824
5818 If you want to revert just one file to an older revision, use
5825 If you want to revert just one file to an older revision, use
5819 :hg:`revert [-r REV] NAME`.
5826 :hg:`revert [-r REV] NAME`.
5820
5827
5821 See :hg:`help dates` for a list of formats valid for -d/--date.
5828 See :hg:`help dates` for a list of formats valid for -d/--date.
5822
5829
5823 Returns 0 on success, 1 if there are unresolved files.
5830 Returns 0 on success, 1 if there are unresolved files.
5824 """
5831 """
5825 if rev and node:
5832 if rev and node:
5826 raise util.Abort(_("please specify just one revision"))
5833 raise util.Abort(_("please specify just one revision"))
5827
5834
5828 if rev is None or rev == '':
5835 if rev is None or rev == '':
5829 rev = node
5836 rev = node
5830
5837
5831 cmdutil.clearunfinished(repo)
5838 cmdutil.clearunfinished(repo)
5832
5839
5833 # with no argument, we also move the current bookmark, if any
5840 # with no argument, we also move the current bookmark, if any
5834 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5841 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
5835
5842
5836 # if we defined a bookmark, we have to remember the original bookmark name
5843 # if we defined a bookmark, we have to remember the original bookmark name
5837 brev = rev
5844 brev = rev
5838 rev = scmutil.revsingle(repo, rev, rev).rev()
5845 rev = scmutil.revsingle(repo, rev, rev).rev()
5839
5846
5840 if check and clean:
5847 if check and clean:
5841 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5848 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
5842
5849
5843 if date:
5850 if date:
5844 if rev is not None:
5851 if rev is not None:
5845 raise util.Abort(_("you can't specify a revision and a date"))
5852 raise util.Abort(_("you can't specify a revision and a date"))
5846 rev = cmdutil.finddate(ui, repo, date)
5853 rev = cmdutil.finddate(ui, repo, date)
5847
5854
5848 if check:
5855 if check:
5849 c = repo[None]
5856 c = repo[None]
5850 if c.dirty(merge=False, branch=False, missing=True):
5857 if c.dirty(merge=False, branch=False, missing=True):
5851 raise util.Abort(_("uncommitted changes"))
5858 raise util.Abort(_("uncommitted changes"))
5852 if rev is None:
5859 if rev is None:
5853 rev = repo[repo[None].branch()].rev()
5860 rev = repo[repo[None].branch()].rev()
5854 mergemod._checkunknown(repo, repo[None], repo[rev])
5861 mergemod._checkunknown(repo, repo[None], repo[rev])
5855
5862
5856 if clean:
5863 if clean:
5857 ret = hg.clean(repo, rev)
5864 ret = hg.clean(repo, rev)
5858 else:
5865 else:
5859 ret = hg.update(repo, rev)
5866 ret = hg.update(repo, rev)
5860
5867
5861 if not ret and movemarkfrom:
5868 if not ret and movemarkfrom:
5862 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5869 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5863 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5870 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5864 elif brev in repo._bookmarks:
5871 elif brev in repo._bookmarks:
5865 bookmarks.setcurrent(repo, brev)
5872 bookmarks.setcurrent(repo, brev)
5866 elif brev:
5873 elif brev:
5867 bookmarks.unsetcurrent(repo)
5874 bookmarks.unsetcurrent(repo)
5868
5875
5869 return ret
5876 return ret
5870
5877
5871 @command('verify', [])
5878 @command('verify', [])
5872 def verify(ui, repo):
5879 def verify(ui, repo):
5873 """verify the integrity of the repository
5880 """verify the integrity of the repository
5874
5881
5875 Verify the integrity of the current repository.
5882 Verify the integrity of the current repository.
5876
5883
5877 This will perform an extensive check of the repository's
5884 This will perform an extensive check of the repository's
5878 integrity, validating the hashes and checksums of each entry in
5885 integrity, validating the hashes and checksums of each entry in
5879 the changelog, manifest, and tracked files, as well as the
5886 the changelog, manifest, and tracked files, as well as the
5880 integrity of their crosslinks and indices.
5887 integrity of their crosslinks and indices.
5881
5888
5882 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5889 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
5883 for more information about recovery from corruption of the
5890 for more information about recovery from corruption of the
5884 repository.
5891 repository.
5885
5892
5886 Returns 0 on success, 1 if errors are encountered.
5893 Returns 0 on success, 1 if errors are encountered.
5887 """
5894 """
5888 return hg.verify(repo)
5895 return hg.verify(repo)
5889
5896
5890 @command('version', [])
5897 @command('version', [])
5891 def version_(ui):
5898 def version_(ui):
5892 """output version and copyright information"""
5899 """output version and copyright information"""
5893 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5900 ui.write(_("Mercurial Distributed SCM (version %s)\n")
5894 % util.version())
5901 % util.version())
5895 ui.status(_(
5902 ui.status(_(
5896 "(see http://mercurial.selenic.com for more information)\n"
5903 "(see http://mercurial.selenic.com for more information)\n"
5897 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5904 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
5898 "This is free software; see the source for copying conditions. "
5905 "This is free software; see the source for copying conditions. "
5899 "There is NO\nwarranty; "
5906 "There is NO\nwarranty; "
5900 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5907 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
5901 ))
5908 ))
5902
5909
5903 norepo = ("clone init version help debugcommands debugcomplete"
5910 norepo = ("clone init version help debugcommands debugcomplete"
5904 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5911 " debugdate debuginstall debugfsinfo debugpushkey debugwireargs"
5905 " debugknown debuggetbundle debugbundle")
5912 " debugknown debuggetbundle debugbundle")
5906 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5913 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
5907 " debugdata debugindex debugindexdot debugrevlog")
5914 " debugdata debugindex debugindexdot debugrevlog")
5908 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5915 inferrepo = ("add addremove annotate cat commit diff grep forget log parents"
5909 " remove resolve status debugwalk")
5916 " remove resolve status debugwalk")
@@ -1,410 +1,408 b''
1 $ hg init basic
1 $ hg init basic
2 $ cd basic
2 $ cd basic
3
3
4 should complain
4 should complain
5
5
6 $ hg backout
6 $ hg backout
7 abort: please specify a revision to backout
7 abort: please specify a revision to backout
8 [255]
8 [255]
9 $ hg backout -r 0 0
9 $ hg backout -r 0 0
10 abort: please specify just one revision
10 abort: please specify just one revision
11 [255]
11 [255]
12
12
13 basic operation
13 basic operation
14
14
15 $ echo a > a
15 $ echo a > a
16 $ hg commit -d '0 0' -A -m a
16 $ hg commit -d '0 0' -A -m a
17 adding a
17 adding a
18 $ echo b >> a
18 $ echo b >> a
19 $ hg commit -d '1 0' -m b
19 $ hg commit -d '1 0' -m b
20
20
21 $ hg backout -d '2 0' tip --tool=true
21 $ hg backout -d '2 0' tip --tool=true
22 reverting a
22 reverting a
23 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
23 changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
24 $ cat a
24 $ cat a
25 a
25 a
26 $ hg summary
26 $ hg summary
27 parent: 2:2929462c3dff tip
27 parent: 2:2929462c3dff tip
28 Backed out changeset a820f4f40a57
28 Backed out changeset a820f4f40a57
29 branch: default
29 branch: default
30 commit: (clean)
30 commit: (clean)
31 update: (current)
31 update: (current)
32
32
33 file that was removed is recreated
33 file that was removed is recreated
34
34
35 $ cd ..
35 $ cd ..
36 $ hg init remove
36 $ hg init remove
37 $ cd remove
37 $ cd remove
38
38
39 $ echo content > a
39 $ echo content > a
40 $ hg commit -d '0 0' -A -m a
40 $ hg commit -d '0 0' -A -m a
41 adding a
41 adding a
42
42
43 $ hg rm a
43 $ hg rm a
44 $ hg commit -d '1 0' -m b
44 $ hg commit -d '1 0' -m b
45
45
46 $ hg backout -d '2 0' tip --tool=true
46 $ hg backout -d '2 0' tip --tool=true
47 adding a
47 adding a
48 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
48 changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
49 $ cat a
49 $ cat a
50 content
50 content
51 $ hg summary
51 $ hg summary
52 parent: 2:de31bdc76c0d tip
52 parent: 2:de31bdc76c0d tip
53 Backed out changeset 76862dcce372
53 Backed out changeset 76862dcce372
54 branch: default
54 branch: default
55 commit: (clean)
55 commit: (clean)
56 update: (current)
56 update: (current)
57
57
58 backout of backout is as if nothing happened
58 backout of backout is as if nothing happened
59
59
60 $ hg backout -d '3 0' --merge tip --tool=true
60 $ hg backout -d '3 0' --merge tip --tool=true
61 removing a
61 removing a
62 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
62 changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
63 $ test -f a
63 $ test -f a
64 [1]
64 [1]
65 $ hg summary
65 $ hg summary
66 parent: 3:7f6d0f120113 tip
66 parent: 3:7f6d0f120113 tip
67 Backed out changeset de31bdc76c0d
67 Backed out changeset de31bdc76c0d
68 branch: default
68 branch: default
69 commit: (clean)
69 commit: (clean)
70 update: (current)
70 update: (current)
71
71
72 across branch
72 across branch
73
73
74 $ cd ..
74 $ cd ..
75 $ hg init branch
75 $ hg init branch
76 $ cd branch
76 $ cd branch
77 $ echo a > a
77 $ echo a > a
78 $ hg ci -Am0
78 $ hg ci -Am0
79 adding a
79 adding a
80 $ echo b > b
80 $ echo b > b
81 $ hg ci -Am1
81 $ hg ci -Am1
82 adding b
82 adding b
83 $ hg co -C 0
83 $ hg co -C 0
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
84 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
85 $ hg summary
85 $ hg summary
86 parent: 0:f7b1eb17ad24
86 parent: 0:f7b1eb17ad24
87 0
87 0
88 branch: default
88 branch: default
89 commit: (clean)
89 commit: (clean)
90 update: 1 new changesets (update)
90 update: 1 new changesets (update)
91
91
92 should fail
92 should fail
93
93
94 $ hg backout 1
94 $ hg backout 1
95 abort: cannot backout change on a different branch
95 abort: cannot backout change on a different branch
96 [255]
96 [255]
97 $ echo c > c
97 $ echo c > c
98 $ hg ci -Am2
98 $ hg ci -Am2
99 adding c
99 adding c
100 created new head
100 created new head
101 $ hg summary
101 $ hg summary
102 parent: 2:db815d6d32e6 tip
102 parent: 2:db815d6d32e6 tip
103 2
103 2
104 branch: default
104 branch: default
105 commit: (clean)
105 commit: (clean)
106 update: 1 new changesets, 2 branch heads (merge)
106 update: 1 new changesets, 2 branch heads (merge)
107
107
108 should fail
108 should fail
109
109
110 $ hg backout 1
110 $ hg backout 1
111 abort: cannot backout change on a different branch
111 abort: cannot backout change on a different branch
112 [255]
112 [255]
113 $ hg summary
113 $ hg summary
114 parent: 2:db815d6d32e6 tip
114 parent: 2:db815d6d32e6 tip
115 2
115 2
116 branch: default
116 branch: default
117 commit: (clean)
117 commit: (clean)
118 update: 1 new changesets, 2 branch heads (merge)
118 update: 1 new changesets, 2 branch heads (merge)
119
119
120 backout with merge
120 backout with merge
121
121
122 $ cd ..
122 $ cd ..
123 $ hg init merge
123 $ hg init merge
124 $ cd merge
124 $ cd merge
125
125
126 $ echo line 1 > a
126 $ echo line 1 > a
127 $ echo line 2 >> a
127 $ echo line 2 >> a
128 $ hg commit -d '0 0' -A -m a
128 $ hg commit -d '0 0' -A -m a
129 adding a
129 adding a
130 $ hg summary
130 $ hg summary
131 parent: 0:59395513a13a tip
131 parent: 0:59395513a13a tip
132 a
132 a
133 branch: default
133 branch: default
134 commit: (clean)
134 commit: (clean)
135 update: (current)
135 update: (current)
136
136
137 remove line 1
137 remove line 1
138
138
139 $ echo line 2 > a
139 $ echo line 2 > a
140 $ hg commit -d '1 0' -m b
140 $ hg commit -d '1 0' -m b
141
141
142 $ echo line 3 >> a
142 $ echo line 3 >> a
143 $ hg commit -d '2 0' -m c
143 $ hg commit -d '2 0' -m c
144
144
145 $ hg backout --merge -d '3 0' 1 --tool=true
145 $ hg backout --merge -d '3 0' 1 --tool=true
146 reverting a
146 reverting a
147 created new head
147 created new head
148 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
148 changeset 3:26b8ccb9ad91 backs out changeset 1:5a50a024c182
149 merging with changeset 3:26b8ccb9ad91
149 merging with changeset 3:26b8ccb9ad91
150 merging a
150 merging a
151 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
151 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
152 (branch merge, don't forget to commit)
152 (branch merge, don't forget to commit)
153 $ hg commit -d '4 0' -m d
153 $ hg commit -d '4 0' -m d
154 $ hg summary
154 $ hg summary
155 parent: 4:c7df5e0b9c09 tip
155 parent: 4:c7df5e0b9c09 tip
156 d
156 d
157 branch: default
157 branch: default
158 commit: (clean)
158 commit: (clean)
159 update: (current)
159 update: (current)
160
160
161 check line 1 is back
161 check line 1 is back
162
162
163 $ cat a
163 $ cat a
164 line 1
164 line 1
165 line 2
165 line 2
166 line 3
166 line 3
167
167
168 $ cd ..
168 $ cd ..
169
169
170 backout should not back out subsequent changesets
170 backout should not back out subsequent changesets
171
171
172 $ hg init onecs
172 $ hg init onecs
173 $ cd onecs
173 $ cd onecs
174 $ echo 1 > a
174 $ echo 1 > a
175 $ hg commit -d '0 0' -A -m a
175 $ hg commit -d '0 0' -A -m a
176 adding a
176 adding a
177 $ echo 2 >> a
177 $ echo 2 >> a
178 $ hg commit -d '1 0' -m b
178 $ hg commit -d '1 0' -m b
179 $ echo 1 > b
179 $ echo 1 > b
180 $ hg commit -d '2 0' -A -m c
180 $ hg commit -d '2 0' -A -m c
181 adding b
181 adding b
182 $ hg summary
182 $ hg summary
183 parent: 2:882396649954 tip
183 parent: 2:882396649954 tip
184 c
184 c
185 branch: default
185 branch: default
186 commit: (clean)
186 commit: (clean)
187 update: (current)
187 update: (current)
188
188
189 without --merge
189 without --merge
190 $ hg backout -d '3 0' 1 --tool=true
190 $ hg backout -d '3 0' 1 --tool=true
191 reverting a
192 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 $ hg locate b
192 $ hg locate b
194 b
193 b
195 $ hg update -C tip
194 $ hg update -C tip
196 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
195 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
197 $ hg locate b
196 $ hg locate b
198 b
197 b
199 $ hg summary
198 $ hg summary
200 parent: 2:882396649954 tip
199 parent: 2:882396649954 tip
201 c
200 c
202 branch: default
201 branch: default
203 commit: (clean)
202 commit: (clean)
204 update: (current)
203 update: (current)
205
204
206 with --merge
205 with --merge
207 $ hg backout --merge -d '3 0' 1 --tool=true
206 $ hg backout --merge -d '3 0' 1 --tool=true
208 reverting a
207 reverting a
209 created new head
208 created new head
210 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
209 changeset 3:3202beb76721 backs out changeset 1:22bca4c721e5
211 merging with changeset 3:3202beb76721
210 merging with changeset 3:3202beb76721
212 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
211 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 (branch merge, don't forget to commit)
212 (branch merge, don't forget to commit)
214 $ hg locate b
213 $ hg locate b
215 b
214 b
216 $ hg update -C tip
215 $ hg update -C tip
217 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
216 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
218 $ hg locate b
217 $ hg locate b
219 [1]
218 [1]
220
219
221 $ cd ..
220 $ cd ..
222 $ hg init m
221 $ hg init m
223 $ cd m
222 $ cd m
224 $ echo a > a
223 $ echo a > a
225 $ hg commit -d '0 0' -A -m a
224 $ hg commit -d '0 0' -A -m a
226 adding a
225 adding a
227 $ echo b > b
226 $ echo b > b
228 $ hg commit -d '1 0' -A -m b
227 $ hg commit -d '1 0' -A -m b
229 adding b
228 adding b
230 $ echo c > c
229 $ echo c > c
231 $ hg commit -d '2 0' -A -m b
230 $ hg commit -d '2 0' -A -m b
232 adding c
231 adding c
233 $ hg update 1
232 $ hg update 1
234 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
233 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
235 $ echo d > d
234 $ echo d > d
236 $ hg commit -d '3 0' -A -m c
235 $ hg commit -d '3 0' -A -m c
237 adding d
236 adding d
238 created new head
237 created new head
239 $ hg merge 2
238 $ hg merge 2
240 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
239 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
241 (branch merge, don't forget to commit)
240 (branch merge, don't forget to commit)
242 $ hg commit -d '4 0' -A -m d
241 $ hg commit -d '4 0' -A -m d
243 $ hg summary
242 $ hg summary
244 parent: 4:b2f3bb92043e tip
243 parent: 4:b2f3bb92043e tip
245 d
244 d
246 branch: default
245 branch: default
247 commit: (clean)
246 commit: (clean)
248 update: (current)
247 update: (current)
249
248
250 backout of merge should fail
249 backout of merge should fail
251
250
252 $ hg backout 4
251 $ hg backout 4
253 abort: cannot backout a merge changeset
252 abort: cannot backout a merge changeset
254 [255]
253 [255]
255
254
256 backout of merge with bad parent should fail
255 backout of merge with bad parent should fail
257
256
258 $ hg backout --parent 0 4
257 $ hg backout --parent 0 4
259 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
258 abort: cb9a9f314b8b is not a parent of b2f3bb92043e
260 [255]
259 [255]
261
260
262 backout of non-merge with parent should fail
261 backout of non-merge with parent should fail
263
262
264 $ hg backout --parent 0 3
263 $ hg backout --parent 0 3
265 abort: cannot use --parent on non-merge changeset
264 abort: cannot use --parent on non-merge changeset
266 [255]
265 [255]
267
266
268 backout with valid parent should be ok
267 backout with valid parent should be ok
269
268
270 $ hg backout -d '5 0' --parent 2 4 --tool=true
269 $ hg backout -d '5 0' --parent 2 4 --tool=true
271 removing d
270 removing d
272 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
271 changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
273 $ hg summary
272 $ hg summary
274 parent: 5:10e5328c8435 tip
273 parent: 5:10e5328c8435 tip
275 Backed out changeset b2f3bb92043e
274 Backed out changeset b2f3bb92043e
276 branch: default
275 branch: default
277 commit: (clean)
276 commit: (clean)
278 update: (current)
277 update: (current)
279
278
280 $ hg rollback
279 $ hg rollback
281 repository tip rolled back to revision 4 (undo commit)
280 repository tip rolled back to revision 4 (undo commit)
282 working directory now based on revision 4
281 working directory now based on revision 4
283 $ hg update -C
282 $ hg update -C
284 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
283 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
285 $ hg summary
284 $ hg summary
286 parent: 4:b2f3bb92043e tip
285 parent: 4:b2f3bb92043e tip
287 d
286 d
288 branch: default
287 branch: default
289 commit: (clean)
288 commit: (clean)
290 update: (current)
289 update: (current)
291
290
292 $ hg backout -d '6 0' --parent 3 4 --tool=true
291 $ hg backout -d '6 0' --parent 3 4 --tool=true
293 removing c
292 removing c
294 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
293 changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
295 $ hg summary
294 $ hg summary
296 parent: 5:033590168430 tip
295 parent: 5:033590168430 tip
297 Backed out changeset b2f3bb92043e
296 Backed out changeset b2f3bb92043e
298 branch: default
297 branch: default
299 commit: (clean)
298 commit: (clean)
300 update: (current)
299 update: (current)
301
300
302 $ cd ..
301 $ cd ..
303
302
304 named branches
303 named branches
305
304
306 $ hg init named_branches
305 $ hg init named_branches
307 $ cd named_branches
306 $ cd named_branches
308
307
309 $ echo default > default
308 $ echo default > default
310 $ hg ci -d '0 0' -Am default
309 $ hg ci -d '0 0' -Am default
311 adding default
310 adding default
312 $ hg branch branch1
311 $ hg branch branch1
313 marked working directory as branch branch1
312 marked working directory as branch branch1
314 (branches are permanent and global, did you want a bookmark?)
313 (branches are permanent and global, did you want a bookmark?)
315 $ echo branch1 > file1
314 $ echo branch1 > file1
316 $ hg ci -d '1 0' -Am file1
315 $ hg ci -d '1 0' -Am file1
317 adding file1
316 adding file1
318 $ hg branch branch2
317 $ hg branch branch2
319 marked working directory as branch branch2
318 marked working directory as branch branch2
320 (branches are permanent and global, did you want a bookmark?)
319 (branches are permanent and global, did you want a bookmark?)
321 $ echo branch2 > file2
320 $ echo branch2 > file2
322 $ hg ci -d '2 0' -Am file2
321 $ hg ci -d '2 0' -Am file2
323 adding file2
322 adding file2
324
323
325 without --merge
324 without --merge
326 $ hg backout -r 1 --tool=true
325 $ hg backout -r 1 --tool=true
327 removing file1
326 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
328 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
329 $ hg branch
327 $ hg branch
330 branch2
328 branch2
331 $ hg status -A
329 $ hg status -A
332 R file1
330 R file1
333 C default
331 C default
334 C file2
332 C file2
335 $ hg summary
333 $ hg summary
336 parent: 2:45bbcd363bf0 tip
334 parent: 2:45bbcd363bf0 tip
337 file2
335 file2
338 branch: branch2
336 branch: branch2
339 commit: 1 removed
337 commit: 1 removed
340 update: (current)
338 update: (current)
341
339
342 with --merge
340 with --merge
343 $ hg update -qC
341 $ hg update -qC
344 $ hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true
342 $ hg backout --merge -d '3 0' -r 1 -m 'backout on branch1' --tool=true
345 removing file1
343 removing file1
346 created new head
344 created new head
347 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
345 changeset 3:d4e8f6db59fb backs out changeset 1:bf1602f437f3
348 merging with changeset 3:d4e8f6db59fb
346 merging with changeset 3:d4e8f6db59fb
349 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
347 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
350 (branch merge, don't forget to commit)
348 (branch merge, don't forget to commit)
351 $ hg summary
349 $ hg summary
352 parent: 2:45bbcd363bf0
350 parent: 2:45bbcd363bf0
353 file2
351 file2
354 parent: 3:d4e8f6db59fb tip
352 parent: 3:d4e8f6db59fb tip
355 backout on branch1
353 backout on branch1
356 branch: branch2
354 branch: branch2
357 commit: 1 removed (merge)
355 commit: 1 removed (merge)
358 update: (current)
356 update: (current)
359 $ hg update -q -C 2
357 $ hg update -q -C 2
360
358
361 on branch2 with branch1 not merged, so file1 should still exist:
359 on branch2 with branch1 not merged, so file1 should still exist:
362
360
363 $ hg id
361 $ hg id
364 45bbcd363bf0 (branch2)
362 45bbcd363bf0 (branch2)
365 $ hg st -A
363 $ hg st -A
366 C default
364 C default
367 C file1
365 C file1
368 C file2
366 C file2
369 $ hg summary
367 $ hg summary
370 parent: 2:45bbcd363bf0
368 parent: 2:45bbcd363bf0
371 file2
369 file2
372 branch: branch2
370 branch: branch2
373 commit: (clean)
371 commit: (clean)
374 update: 1 new changesets, 2 branch heads (merge)
372 update: 1 new changesets, 2 branch heads (merge)
375
373
376 on branch2 with branch1 merged, so file1 should be gone:
374 on branch2 with branch1 merged, so file1 should be gone:
377
375
378 $ hg merge
376 $ hg merge
379 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
377 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
380 (branch merge, don't forget to commit)
378 (branch merge, don't forget to commit)
381 $ hg ci -d '4 0' -m 'merge backout of branch1'
379 $ hg ci -d '4 0' -m 'merge backout of branch1'
382 $ hg id
380 $ hg id
383 22149cdde76d (branch2) tip
381 22149cdde76d (branch2) tip
384 $ hg st -A
382 $ hg st -A
385 C default
383 C default
386 C file2
384 C file2
387 $ hg summary
385 $ hg summary
388 parent: 4:22149cdde76d tip
386 parent: 4:22149cdde76d tip
389 merge backout of branch1
387 merge backout of branch1
390 branch: branch2
388 branch: branch2
391 commit: (clean)
389 commit: (clean)
392 update: (current)
390 update: (current)
393
391
394 on branch1, so no file1 and file2:
392 on branch1, so no file1 and file2:
395
393
396 $ hg co -C branch1
394 $ hg co -C branch1
397 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
395 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
398 $ hg id
396 $ hg id
399 bf1602f437f3 (branch1)
397 bf1602f437f3 (branch1)
400 $ hg st -A
398 $ hg st -A
401 C default
399 C default
402 C file1
400 C file1
403 $ hg summary
401 $ hg summary
404 parent: 1:bf1602f437f3
402 parent: 1:bf1602f437f3
405 file1
403 file1
406 branch: branch1
404 branch: branch1
407 commit: (clean)
405 commit: (clean)
408 update: (current)
406 update: (current)
409
407
410 $ cd ..
408 $ cd ..
@@ -1,1300 +1,1295 b''
1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
1 Let commit recurse into subrepos by default to match pre-2.0 behavior:
2
2
3 $ echo "[ui]" >> $HGRCPATH
3 $ echo "[ui]" >> $HGRCPATH
4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
4 $ echo "commitsubrepos = Yes" >> $HGRCPATH
5
5
6 $ hg init t
6 $ hg init t
7 $ cd t
7 $ cd t
8
8
9 first revision, no sub
9 first revision, no sub
10
10
11 $ echo a > a
11 $ echo a > a
12 $ hg ci -Am0
12 $ hg ci -Am0
13 adding a
13 adding a
14
14
15 add first sub
15 add first sub
16
16
17 $ echo s = s > .hgsub
17 $ echo s = s > .hgsub
18 $ hg add .hgsub
18 $ hg add .hgsub
19 $ hg init s
19 $ hg init s
20 $ echo a > s/a
20 $ echo a > s/a
21
21
22 Issue2232: committing a subrepo without .hgsub
22 Issue2232: committing a subrepo without .hgsub
23
23
24 $ hg ci -mbad s
24 $ hg ci -mbad s
25 abort: can't commit subrepos without .hgsub
25 abort: can't commit subrepos without .hgsub
26 [255]
26 [255]
27
27
28 $ hg -R s ci -Ams0
28 $ hg -R s ci -Ams0
29 adding a
29 adding a
30 $ hg sum
30 $ hg sum
31 parent: 0:f7b1eb17ad24 tip
31 parent: 0:f7b1eb17ad24 tip
32 0
32 0
33 branch: default
33 branch: default
34 commit: 1 added, 1 subrepos
34 commit: 1 added, 1 subrepos
35 update: (current)
35 update: (current)
36 $ hg ci -m1
36 $ hg ci -m1
37
37
38 Revert subrepo and test subrepo fileset keyword:
38 Revert subrepo and test subrepo fileset keyword:
39
39
40 $ echo b > s/a
40 $ echo b > s/a
41 $ hg revert "set:subrepo('glob:s*')"
41 $ hg revert "set:subrepo('glob:s*')"
42 reverting subrepo s
42 reverting subrepo s
43 reverting s/a (glob)
43 reverting s/a (glob)
44 $ rm s/a.orig
44 $ rm s/a.orig
45
45
46 Revert subrepo with no backup. The "reverting s/a" line is gone since
46 Revert subrepo with no backup. The "reverting s/a" line is gone since
47 we're really running 'hg update' in the subrepo:
47 we're really running 'hg update' in the subrepo:
48
48
49 $ echo b > s/a
49 $ echo b > s/a
50 $ hg revert --no-backup s
50 $ hg revert --no-backup s
51 reverting subrepo s
51 reverting subrepo s
52
52
53 Issue2022: update -C
53 Issue2022: update -C
54
54
55 $ echo b > s/a
55 $ echo b > s/a
56 $ hg sum
56 $ hg sum
57 parent: 1:7cf8cfea66e4 tip
57 parent: 1:7cf8cfea66e4 tip
58 1
58 1
59 branch: default
59 branch: default
60 commit: 1 subrepos
60 commit: 1 subrepos
61 update: (current)
61 update: (current)
62 $ hg co -C 1
62 $ hg co -C 1
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
63 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
64 $ hg sum
64 $ hg sum
65 parent: 1:7cf8cfea66e4 tip
65 parent: 1:7cf8cfea66e4 tip
66 1
66 1
67 branch: default
67 branch: default
68 commit: (clean)
68 commit: (clean)
69 update: (current)
69 update: (current)
70
70
71 commands that require a clean repo should respect subrepos
71 commands that require a clean repo should respect subrepos
72
72
73 $ echo b >> s/a
73 $ echo b >> s/a
74 $ hg backout tip
74 $ hg backout tip
75 abort: uncommitted changes in subrepo s
75 abort: uncommitted changes in subrepo s
76 [255]
76 [255]
77 $ hg revert -C -R s s/a
77 $ hg revert -C -R s s/a
78
78
79 add sub sub
79 add sub sub
80
80
81 $ echo ss = ss > s/.hgsub
81 $ echo ss = ss > s/.hgsub
82 $ hg init s/ss
82 $ hg init s/ss
83 $ echo a > s/ss/a
83 $ echo a > s/ss/a
84 $ hg -R s add s/.hgsub
84 $ hg -R s add s/.hgsub
85 $ hg -R s/ss add s/ss/a
85 $ hg -R s/ss add s/ss/a
86 $ hg sum
86 $ hg sum
87 parent: 1:7cf8cfea66e4 tip
87 parent: 1:7cf8cfea66e4 tip
88 1
88 1
89 branch: default
89 branch: default
90 commit: 1 subrepos
90 commit: 1 subrepos
91 update: (current)
91 update: (current)
92 $ hg ci -m2
92 $ hg ci -m2
93 committing subrepository s
93 committing subrepository s
94 committing subrepository s/ss (glob)
94 committing subrepository s/ss (glob)
95 $ hg sum
95 $ hg sum
96 parent: 2:df30734270ae tip
96 parent: 2:df30734270ae tip
97 2
97 2
98 branch: default
98 branch: default
99 commit: (clean)
99 commit: (clean)
100 update: (current)
100 update: (current)
101
101
102 bump sub rev (and check it is ignored by ui.commitsubrepos)
102 bump sub rev (and check it is ignored by ui.commitsubrepos)
103
103
104 $ echo b > s/a
104 $ echo b > s/a
105 $ hg -R s ci -ms1
105 $ hg -R s ci -ms1
106 $ hg --config ui.commitsubrepos=no ci -m3
106 $ hg --config ui.commitsubrepos=no ci -m3
107
107
108 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
108 leave sub dirty (and check ui.commitsubrepos=no aborts the commit)
109
109
110 $ echo c > s/a
110 $ echo c > s/a
111 $ hg --config ui.commitsubrepos=no ci -m4
111 $ hg --config ui.commitsubrepos=no ci -m4
112 abort: uncommitted changes in subrepo s
112 abort: uncommitted changes in subrepo s
113 (use --subrepos for recursive commit)
113 (use --subrepos for recursive commit)
114 [255]
114 [255]
115 $ hg id
115 $ hg id
116 f6affe3fbfaa+ tip
116 f6affe3fbfaa+ tip
117 $ hg -R s ci -mc
117 $ hg -R s ci -mc
118 $ hg id
118 $ hg id
119 f6affe3fbfaa+ tip
119 f6affe3fbfaa+ tip
120 $ echo d > s/a
120 $ echo d > s/a
121 $ hg ci -m4
121 $ hg ci -m4
122 committing subrepository s
122 committing subrepository s
123 $ hg tip -R s
123 $ hg tip -R s
124 changeset: 4:02dcf1d70411
124 changeset: 4:02dcf1d70411
125 tag: tip
125 tag: tip
126 user: test
126 user: test
127 date: Thu Jan 01 00:00:00 1970 +0000
127 date: Thu Jan 01 00:00:00 1970 +0000
128 summary: 4
128 summary: 4
129
129
130
130
131 check caching
131 check caching
132
132
133 $ hg co 0
133 $ hg co 0
134 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
134 0 files updated, 0 files merged, 2 files removed, 0 files unresolved
135 $ hg debugsub
135 $ hg debugsub
136
136
137 restore
137 restore
138
138
139 $ hg co
139 $ hg co
140 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
140 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
141 $ hg debugsub
141 $ hg debugsub
142 path s
142 path s
143 source s
143 source s
144 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
144 revision 02dcf1d704118aee3ee306ccfa1910850d5b05ef
145
145
146 new branch for merge tests
146 new branch for merge tests
147
147
148 $ hg co 1
148 $ hg co 1
149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
149 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
150 $ echo t = t >> .hgsub
150 $ echo t = t >> .hgsub
151 $ hg init t
151 $ hg init t
152 $ echo t > t/t
152 $ echo t > t/t
153 $ hg -R t add t
153 $ hg -R t add t
154 adding t/t (glob)
154 adding t/t (glob)
155
155
156 5
156 5
157
157
158 $ hg ci -m5 # add sub
158 $ hg ci -m5 # add sub
159 committing subrepository t
159 committing subrepository t
160 created new head
160 created new head
161 $ echo t2 > t/t
161 $ echo t2 > t/t
162
162
163 6
163 6
164
164
165 $ hg st -R s
165 $ hg st -R s
166 $ hg ci -m6 # change sub
166 $ hg ci -m6 # change sub
167 committing subrepository t
167 committing subrepository t
168 $ hg debugsub
168 $ hg debugsub
169 path s
169 path s
170 source s
170 source s
171 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
171 revision e4ece1bf43360ddc8f6a96432201a37b7cd27ae4
172 path t
172 path t
173 source t
173 source t
174 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
174 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
175 $ echo t3 > t/t
175 $ echo t3 > t/t
176
176
177 7
177 7
178
178
179 $ hg ci -m7 # change sub again for conflict test
179 $ hg ci -m7 # change sub again for conflict test
180 committing subrepository t
180 committing subrepository t
181 $ hg rm .hgsub
181 $ hg rm .hgsub
182
182
183 8
183 8
184
184
185 $ hg ci -m8 # remove sub
185 $ hg ci -m8 # remove sub
186
186
187 merge tests
187 merge tests
188
188
189 $ hg co -C 3
189 $ hg co -C 3
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
191 $ hg merge 5 # test adding
191 $ hg merge 5 # test adding
192 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
193 (branch merge, don't forget to commit)
193 (branch merge, don't forget to commit)
194 $ hg debugsub
194 $ hg debugsub
195 path s
195 path s
196 source s
196 source s
197 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
197 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
198 path t
198 path t
199 source t
199 source t
200 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
200 revision 60ca1237c19474e7a3978b0dc1ca4e6f36d51382
201 $ hg ci -m9
201 $ hg ci -m9
202 created new head
202 created new head
203 $ hg merge 6 --debug # test change
203 $ hg merge 6 --debug # test change
204 searching for copies back to rev 2
204 searching for copies back to rev 2
205 resolving manifests
205 resolving manifests
206 branchmerge: True, force: False, partial: False
206 branchmerge: True, force: False, partial: False
207 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
207 ancestor: 1f14a2e2d3ec, local: f0d2028bf86d+, remote: 1831e14459c4
208 .hgsubstate: versions differ -> m
208 .hgsubstate: versions differ -> m
209 updating: .hgsubstate 1/1 files (100.00%)
209 updating: .hgsubstate 1/1 files (100.00%)
210 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
210 subrepo merge f0d2028bf86d+ 1831e14459c4 1f14a2e2d3ec
211 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
211 subrepo t: other changed, get t:6747d179aa9a688023c4b0cad32e4c92bb7f34ad:hg
212 getting subrepo t
212 getting subrepo t
213 resolving manifests
213 resolving manifests
214 branchmerge: False, force: False, partial: False
214 branchmerge: False, force: False, partial: False
215 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
215 ancestor: 60ca1237c194, local: 60ca1237c194+, remote: 6747d179aa9a
216 t: remote is newer -> g
216 t: remote is newer -> g
217 getting t
217 getting t
218 updating: t 1/1 files (100.00%)
218 updating: t 1/1 files (100.00%)
219 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
219 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
220 (branch merge, don't forget to commit)
220 (branch merge, don't forget to commit)
221 $ hg debugsub
221 $ hg debugsub
222 path s
222 path s
223 source s
223 source s
224 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
224 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
225 path t
225 path t
226 source t
226 source t
227 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
227 revision 6747d179aa9a688023c4b0cad32e4c92bb7f34ad
228 $ echo conflict > t/t
228 $ echo conflict > t/t
229 $ hg ci -m10
229 $ hg ci -m10
230 committing subrepository t
230 committing subrepository t
231 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
231 $ HGMERGE=internal:merge hg merge --debug 7 # test conflict
232 searching for copies back to rev 2
232 searching for copies back to rev 2
233 resolving manifests
233 resolving manifests
234 branchmerge: True, force: False, partial: False
234 branchmerge: True, force: False, partial: False
235 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
235 ancestor: 1831e14459c4, local: e45c8b14af55+, remote: f94576341bcf
236 .hgsubstate: versions differ -> m
236 .hgsubstate: versions differ -> m
237 updating: .hgsubstate 1/1 files (100.00%)
237 updating: .hgsubstate 1/1 files (100.00%)
238 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
238 subrepo merge e45c8b14af55+ f94576341bcf 1831e14459c4
239 subrepo t: both sides changed
239 subrepo t: both sides changed
240 subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
240 subrepository t diverged (local revision: 20a0db6fbf6c, remote revision: 7af322bc1198)
241 (M)erge, keep (l)ocal or keep (r)emote? m
241 (M)erge, keep (l)ocal or keep (r)emote? m
242 merging subrepo t
242 merging subrepo t
243 searching for copies back to rev 2
243 searching for copies back to rev 2
244 resolving manifests
244 resolving manifests
245 branchmerge: True, force: False, partial: False
245 branchmerge: True, force: False, partial: False
246 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
246 ancestor: 6747d179aa9a, local: 20a0db6fbf6c+, remote: 7af322bc1198
247 t: versions differ -> m
247 t: versions differ -> m
248 preserving t for resolve of t
248 preserving t for resolve of t
249 updating: t 1/1 files (100.00%)
249 updating: t 1/1 files (100.00%)
250 picked tool 'internal:merge' for t (binary False symlink False)
250 picked tool 'internal:merge' for t (binary False symlink False)
251 merging t
251 merging t
252 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
252 my t@20a0db6fbf6c+ other t@7af322bc1198 ancestor t@6747d179aa9a
253 warning: conflicts during merge.
253 warning: conflicts during merge.
254 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
254 merging t incomplete! (edit conflicts, then use 'hg resolve --mark')
255 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
255 0 files updated, 0 files merged, 0 files removed, 1 files unresolved
256 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
256 use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
257 subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
257 subrepo t: merge with t:7af322bc1198a32402fe903e0b7ebcfc5c9bf8f4:hg
258 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
258 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
259 (branch merge, don't forget to commit)
259 (branch merge, don't forget to commit)
260
260
261 should conflict
261 should conflict
262
262
263 $ cat t/t
263 $ cat t/t
264 <<<<<<< local
264 <<<<<<< local
265 conflict
265 conflict
266 =======
266 =======
267 t3
267 t3
268 >>>>>>> other
268 >>>>>>> other
269
269
270 clone
270 clone
271
271
272 $ cd ..
272 $ cd ..
273 $ hg clone t tc
273 $ hg clone t tc
274 updating to branch default
274 updating to branch default
275 cloning subrepo s from $TESTTMP/t/s
275 cloning subrepo s from $TESTTMP/t/s
276 cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
276 cloning subrepo s/ss from $TESTTMP/t/s/ss (glob)
277 cloning subrepo t from $TESTTMP/t/t
277 cloning subrepo t from $TESTTMP/t/t
278 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
278 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
279 $ cd tc
279 $ cd tc
280 $ hg debugsub
280 $ hg debugsub
281 path s
281 path s
282 source s
282 source s
283 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
283 revision fc627a69481fcbe5f1135069e8a3881c023e4cf5
284 path t
284 path t
285 source t
285 source t
286 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
286 revision 20a0db6fbf6c3d2836e6519a642ae929bfc67c0e
287
287
288 push
288 push
289
289
290 $ echo bah > t/t
290 $ echo bah > t/t
291 $ hg ci -m11
291 $ hg ci -m11
292 committing subrepository t
292 committing subrepository t
293 $ hg push
293 $ hg push
294 pushing to $TESTTMP/t (glob)
294 pushing to $TESTTMP/t (glob)
295 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
295 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
296 no changes made to subrepo s since last push to $TESTTMP/t/s
296 no changes made to subrepo s since last push to $TESTTMP/t/s
297 pushing subrepo t to $TESTTMP/t/t
297 pushing subrepo t to $TESTTMP/t/t
298 searching for changes
298 searching for changes
299 adding changesets
299 adding changesets
300 adding manifests
300 adding manifests
301 adding file changes
301 adding file changes
302 added 1 changesets with 1 changes to 1 files
302 added 1 changesets with 1 changes to 1 files
303 searching for changes
303 searching for changes
304 adding changesets
304 adding changesets
305 adding manifests
305 adding manifests
306 adding file changes
306 adding file changes
307 added 1 changesets with 1 changes to 1 files
307 added 1 changesets with 1 changes to 1 files
308
308
309 push -f
309 push -f
310
310
311 $ echo bah > s/a
311 $ echo bah > s/a
312 $ hg ci -m12
312 $ hg ci -m12
313 committing subrepository s
313 committing subrepository s
314 $ hg push
314 $ hg push
315 pushing to $TESTTMP/t (glob)
315 pushing to $TESTTMP/t (glob)
316 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
316 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
317 pushing subrepo s to $TESTTMP/t/s
317 pushing subrepo s to $TESTTMP/t/s
318 searching for changes
318 searching for changes
319 abort: push creates new remote head 12a213df6fa9! (in subrepo s)
319 abort: push creates new remote head 12a213df6fa9! (in subrepo s)
320 (merge or see "hg help push" for details about pushing new heads)
320 (merge or see "hg help push" for details about pushing new heads)
321 [255]
321 [255]
322 $ hg push -f
322 $ hg push -f
323 pushing to $TESTTMP/t (glob)
323 pushing to $TESTTMP/t (glob)
324 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
324 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
325 searching for changes
325 searching for changes
326 no changes found
326 no changes found
327 pushing subrepo s to $TESTTMP/t/s
327 pushing subrepo s to $TESTTMP/t/s
328 searching for changes
328 searching for changes
329 adding changesets
329 adding changesets
330 adding manifests
330 adding manifests
331 adding file changes
331 adding file changes
332 added 1 changesets with 1 changes to 1 files (+1 heads)
332 added 1 changesets with 1 changes to 1 files (+1 heads)
333 pushing subrepo t to $TESTTMP/t/t
333 pushing subrepo t to $TESTTMP/t/t
334 searching for changes
334 searching for changes
335 no changes found
335 no changes found
336 searching for changes
336 searching for changes
337 adding changesets
337 adding changesets
338 adding manifests
338 adding manifests
339 adding file changes
339 adding file changes
340 added 1 changesets with 1 changes to 1 files
340 added 1 changesets with 1 changes to 1 files
341
341
342 check that unmodified subrepos are not pushed
342 check that unmodified subrepos are not pushed
343
343
344 $ hg clone . ../tcc
344 $ hg clone . ../tcc
345 updating to branch default
345 updating to branch default
346 cloning subrepo s from $TESTTMP/tc/s
346 cloning subrepo s from $TESTTMP/tc/s
347 cloning subrepo s/ss from $TESTTMP/tc/s/ss (glob)
347 cloning subrepo s/ss from $TESTTMP/tc/s/ss (glob)
348 cloning subrepo t from $TESTTMP/tc/t
348 cloning subrepo t from $TESTTMP/tc/t
349 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
349 3 files updated, 0 files merged, 0 files removed, 0 files unresolved
350
350
351 the subrepos on the new clone have nothing to push to its source
351 the subrepos on the new clone have nothing to push to its source
352
352
353 $ hg push -R ../tcc .
353 $ hg push -R ../tcc .
354 pushing to .
354 pushing to .
355 no changes made to subrepo s/ss since last push to s/ss (glob)
355 no changes made to subrepo s/ss since last push to s/ss (glob)
356 no changes made to subrepo s since last push to s
356 no changes made to subrepo s since last push to s
357 no changes made to subrepo t since last push to t
357 no changes made to subrepo t since last push to t
358 searching for changes
358 searching for changes
359 no changes found
359 no changes found
360 [1]
360 [1]
361
361
362 the subrepos on the source do not have a clean store versus the clone target
362 the subrepos on the source do not have a clean store versus the clone target
363 because they were never explicitly pushed to the source
363 because they were never explicitly pushed to the source
364
364
365 $ hg push ../tcc
365 $ hg push ../tcc
366 pushing to ../tcc
366 pushing to ../tcc
367 pushing subrepo s/ss to ../tcc/s/ss (glob)
367 pushing subrepo s/ss to ../tcc/s/ss (glob)
368 searching for changes
368 searching for changes
369 no changes found
369 no changes found
370 pushing subrepo s to ../tcc/s
370 pushing subrepo s to ../tcc/s
371 searching for changes
371 searching for changes
372 no changes found
372 no changes found
373 pushing subrepo t to ../tcc/t
373 pushing subrepo t to ../tcc/t
374 searching for changes
374 searching for changes
375 no changes found
375 no changes found
376 searching for changes
376 searching for changes
377 no changes found
377 no changes found
378 [1]
378 [1]
379
379
380 after push their stores become clean
380 after push their stores become clean
381
381
382 $ hg push ../tcc
382 $ hg push ../tcc
383 pushing to ../tcc
383 pushing to ../tcc
384 no changes made to subrepo s/ss since last push to ../tcc/s/ss (glob)
384 no changes made to subrepo s/ss since last push to ../tcc/s/ss (glob)
385 no changes made to subrepo s since last push to ../tcc/s
385 no changes made to subrepo s since last push to ../tcc/s
386 no changes made to subrepo t since last push to ../tcc/t
386 no changes made to subrepo t since last push to ../tcc/t
387 searching for changes
387 searching for changes
388 no changes found
388 no changes found
389 [1]
389 [1]
390
390
391 updating a subrepo to a different revision or changing
391 updating a subrepo to a different revision or changing
392 its working directory does not make its store dirty
392 its working directory does not make its store dirty
393
393
394 $ hg -R s update '.^'
394 $ hg -R s update '.^'
395 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
395 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
396 $ hg push
396 $ hg push
397 pushing to $TESTTMP/t (glob)
397 pushing to $TESTTMP/t (glob)
398 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
398 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
399 no changes made to subrepo s since last push to $TESTTMP/t/s
399 no changes made to subrepo s since last push to $TESTTMP/t/s
400 no changes made to subrepo t since last push to $TESTTMP/t/t
400 no changes made to subrepo t since last push to $TESTTMP/t/t
401 searching for changes
401 searching for changes
402 no changes found
402 no changes found
403 [1]
403 [1]
404 $ echo foo >> s/a
404 $ echo foo >> s/a
405 $ hg push
405 $ hg push
406 pushing to $TESTTMP/t (glob)
406 pushing to $TESTTMP/t (glob)
407 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
407 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
408 no changes made to subrepo s since last push to $TESTTMP/t/s
408 no changes made to subrepo s since last push to $TESTTMP/t/s
409 no changes made to subrepo t since last push to $TESTTMP/t/t
409 no changes made to subrepo t since last push to $TESTTMP/t/t
410 searching for changes
410 searching for changes
411 no changes found
411 no changes found
412 [1]
412 [1]
413 $ hg -R s update -C tip
413 $ hg -R s update -C tip
414 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
414 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
415
415
416 committing into a subrepo makes its store (but not its parent's store) dirty
416 committing into a subrepo makes its store (but not its parent's store) dirty
417
417
418 $ echo foo >> s/ss/a
418 $ echo foo >> s/ss/a
419 $ hg -R s/ss commit -m 'test dirty store detection'
419 $ hg -R s/ss commit -m 'test dirty store detection'
420 $ hg push
420 $ hg push
421 pushing to $TESTTMP/t (glob)
421 pushing to $TESTTMP/t (glob)
422 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
422 pushing subrepo s/ss to $TESTTMP/t/s/ss (glob)
423 searching for changes
423 searching for changes
424 adding changesets
424 adding changesets
425 adding manifests
425 adding manifests
426 adding file changes
426 adding file changes
427 added 1 changesets with 1 changes to 1 files
427 added 1 changesets with 1 changes to 1 files
428 no changes made to subrepo s since last push to $TESTTMP/t/s
428 no changes made to subrepo s since last push to $TESTTMP/t/s
429 no changes made to subrepo t since last push to $TESTTMP/t/t
429 no changes made to subrepo t since last push to $TESTTMP/t/t
430 searching for changes
430 searching for changes
431 no changes found
431 no changes found
432 [1]
432 [1]
433
433
434 a subrepo store may be clean versus one repo but not versus another
434 a subrepo store may be clean versus one repo but not versus another
435
435
436 $ hg push
436 $ hg push
437 pushing to $TESTTMP/t (glob)
437 pushing to $TESTTMP/t (glob)
438 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
438 no changes made to subrepo s/ss since last push to $TESTTMP/t/s/ss (glob)
439 no changes made to subrepo s since last push to $TESTTMP/t/s
439 no changes made to subrepo s since last push to $TESTTMP/t/s
440 no changes made to subrepo t since last push to $TESTTMP/t/t
440 no changes made to subrepo t since last push to $TESTTMP/t/t
441 searching for changes
441 searching for changes
442 no changes found
442 no changes found
443 [1]
443 [1]
444 $ hg push ../tcc
444 $ hg push ../tcc
445 pushing to ../tcc
445 pushing to ../tcc
446 pushing subrepo s/ss to ../tcc/s/ss (glob)
446 pushing subrepo s/ss to ../tcc/s/ss (glob)
447 searching for changes
447 searching for changes
448 adding changesets
448 adding changesets
449 adding manifests
449 adding manifests
450 adding file changes
450 adding file changes
451 added 1 changesets with 1 changes to 1 files
451 added 1 changesets with 1 changes to 1 files
452 no changes made to subrepo s since last push to ../tcc/s
452 no changes made to subrepo s since last push to ../tcc/s
453 no changes made to subrepo t since last push to ../tcc/t
453 no changes made to subrepo t since last push to ../tcc/t
454 searching for changes
454 searching for changes
455 no changes found
455 no changes found
456 [1]
456 [1]
457
457
458 update
458 update
459
459
460 $ cd ../t
460 $ cd ../t
461 $ hg up -C # discard our earlier merge
461 $ hg up -C # discard our earlier merge
462 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
462 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
463 $ echo blah > t/t
463 $ echo blah > t/t
464 $ hg ci -m13
464 $ hg ci -m13
465 committing subrepository t
465 committing subrepository t
466
466
467 backout calls revert internally with minimal opts, which should not raise
467 backout calls revert internally with minimal opts, which should not raise
468 KeyError
468 KeyError
469
469
470 $ hg backout ".^"
470 $ hg backout ".^"
471 reverting .hgsubstate
472 reverting subrepo s
473 reverting s/a (glob)
474 reverting subrepo ss
475 reverting subrepo t
476 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
471 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
477
472
478 $ hg up -C # discard changes
473 $ hg up -C # discard changes
479 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
474 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
480
475
481 pull
476 pull
482
477
483 $ cd ../tc
478 $ cd ../tc
484 $ hg pull
479 $ hg pull
485 pulling from $TESTTMP/t (glob)
480 pulling from $TESTTMP/t (glob)
486 searching for changes
481 searching for changes
487 adding changesets
482 adding changesets
488 adding manifests
483 adding manifests
489 adding file changes
484 adding file changes
490 added 1 changesets with 1 changes to 1 files
485 added 1 changesets with 1 changes to 1 files
491 (run 'hg update' to get a working copy)
486 (run 'hg update' to get a working copy)
492
487
493 should pull t
488 should pull t
494
489
495 $ hg up
490 $ hg up
496 pulling subrepo t from $TESTTMP/t/t
491 pulling subrepo t from $TESTTMP/t/t
497 searching for changes
492 searching for changes
498 adding changesets
493 adding changesets
499 adding manifests
494 adding manifests
500 adding file changes
495 adding file changes
501 added 1 changesets with 1 changes to 1 files
496 added 1 changesets with 1 changes to 1 files
502 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
497 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
503 $ cat t/t
498 $ cat t/t
504 blah
499 blah
505
500
506 bogus subrepo path aborts
501 bogus subrepo path aborts
507
502
508 $ echo 'bogus=[boguspath' >> .hgsub
503 $ echo 'bogus=[boguspath' >> .hgsub
509 $ hg ci -m 'bogus subrepo path'
504 $ hg ci -m 'bogus subrepo path'
510 abort: missing ] in subrepo source
505 abort: missing ] in subrepo source
511 [255]
506 [255]
512
507
513 Issue1986: merge aborts when trying to merge a subrepo that
508 Issue1986: merge aborts when trying to merge a subrepo that
514 shouldn't need merging
509 shouldn't need merging
515
510
516 # subrepo layout
511 # subrepo layout
517 #
512 #
518 # o 5 br
513 # o 5 br
519 # /|
514 # /|
520 # o | 4 default
515 # o | 4 default
521 # | |
516 # | |
522 # | o 3 br
517 # | o 3 br
523 # |/|
518 # |/|
524 # o | 2 default
519 # o | 2 default
525 # | |
520 # | |
526 # | o 1 br
521 # | o 1 br
527 # |/
522 # |/
528 # o 0 default
523 # o 0 default
529
524
530 $ cd ..
525 $ cd ..
531 $ rm -rf sub
526 $ rm -rf sub
532 $ hg init main
527 $ hg init main
533 $ cd main
528 $ cd main
534 $ hg init s
529 $ hg init s
535 $ cd s
530 $ cd s
536 $ echo a > a
531 $ echo a > a
537 $ hg ci -Am1
532 $ hg ci -Am1
538 adding a
533 adding a
539 $ hg branch br
534 $ hg branch br
540 marked working directory as branch br
535 marked working directory as branch br
541 (branches are permanent and global, did you want a bookmark?)
536 (branches are permanent and global, did you want a bookmark?)
542 $ echo a >> a
537 $ echo a >> a
543 $ hg ci -m1
538 $ hg ci -m1
544 $ hg up default
539 $ hg up default
545 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
540 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
546 $ echo b > b
541 $ echo b > b
547 $ hg ci -Am1
542 $ hg ci -Am1
548 adding b
543 adding b
549 $ hg up br
544 $ hg up br
550 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
545 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
551 $ hg merge tip
546 $ hg merge tip
552 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
547 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
553 (branch merge, don't forget to commit)
548 (branch merge, don't forget to commit)
554 $ hg ci -m1
549 $ hg ci -m1
555 $ hg up 2
550 $ hg up 2
556 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
551 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
557 $ echo c > c
552 $ echo c > c
558 $ hg ci -Am1
553 $ hg ci -Am1
559 adding c
554 adding c
560 $ hg up 3
555 $ hg up 3
561 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
556 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
562 $ hg merge 4
557 $ hg merge 4
563 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
558 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
564 (branch merge, don't forget to commit)
559 (branch merge, don't forget to commit)
565 $ hg ci -m1
560 $ hg ci -m1
566
561
567 # main repo layout:
562 # main repo layout:
568 #
563 #
569 # * <-- try to merge default into br again
564 # * <-- try to merge default into br again
570 # .`|
565 # .`|
571 # . o 5 br --> substate = 5
566 # . o 5 br --> substate = 5
572 # . |
567 # . |
573 # o | 4 default --> substate = 4
568 # o | 4 default --> substate = 4
574 # | |
569 # | |
575 # | o 3 br --> substate = 2
570 # | o 3 br --> substate = 2
576 # |/|
571 # |/|
577 # o | 2 default --> substate = 2
572 # o | 2 default --> substate = 2
578 # | |
573 # | |
579 # | o 1 br --> substate = 3
574 # | o 1 br --> substate = 3
580 # |/
575 # |/
581 # o 0 default --> substate = 2
576 # o 0 default --> substate = 2
582
577
583 $ cd ..
578 $ cd ..
584 $ echo 's = s' > .hgsub
579 $ echo 's = s' > .hgsub
585 $ hg -R s up 2
580 $ hg -R s up 2
586 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
581 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
587 $ hg ci -Am1
582 $ hg ci -Am1
588 adding .hgsub
583 adding .hgsub
589 $ hg branch br
584 $ hg branch br
590 marked working directory as branch br
585 marked working directory as branch br
591 (branches are permanent and global, did you want a bookmark?)
586 (branches are permanent and global, did you want a bookmark?)
592 $ echo b > b
587 $ echo b > b
593 $ hg -R s up 3
588 $ hg -R s up 3
594 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
589 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
595 $ hg ci -Am1
590 $ hg ci -Am1
596 adding b
591 adding b
597 $ hg up default
592 $ hg up default
598 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
593 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
599 $ echo c > c
594 $ echo c > c
600 $ hg ci -Am1
595 $ hg ci -Am1
601 adding c
596 adding c
602 $ hg up 1
597 $ hg up 1
603 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
598 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
604 $ hg merge 2
599 $ hg merge 2
605 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
600 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
606 (branch merge, don't forget to commit)
601 (branch merge, don't forget to commit)
607 $ hg ci -m1
602 $ hg ci -m1
608 $ hg up 2
603 $ hg up 2
609 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
604 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
610 $ hg -R s up 4
605 $ hg -R s up 4
611 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
606 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
612 $ echo d > d
607 $ echo d > d
613 $ hg ci -Am1
608 $ hg ci -Am1
614 adding d
609 adding d
615 $ hg up 3
610 $ hg up 3
616 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
611 2 files updated, 0 files merged, 1 files removed, 0 files unresolved
617 $ hg -R s up 5
612 $ hg -R s up 5
618 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
613 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
619 $ echo e > e
614 $ echo e > e
620 $ hg ci -Am1
615 $ hg ci -Am1
621 adding e
616 adding e
622
617
623 $ hg up 5
618 $ hg up 5
624 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
619 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
625 $ hg merge 4 # try to merge default into br again
620 $ hg merge 4 # try to merge default into br again
626 subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
621 subrepository s diverged (local revision: f8f13b33206e, remote revision: a3f9062a4f88)
627 (M)erge, keep (l)ocal or keep (r)emote? m
622 (M)erge, keep (l)ocal or keep (r)emote? m
628 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
623 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
629 (branch merge, don't forget to commit)
624 (branch merge, don't forget to commit)
630 $ cd ..
625 $ cd ..
631
626
632 test subrepo delete from .hgsubstate
627 test subrepo delete from .hgsubstate
633
628
634 $ hg init testdelete
629 $ hg init testdelete
635 $ mkdir testdelete/nested testdelete/nested2
630 $ mkdir testdelete/nested testdelete/nested2
636 $ hg init testdelete/nested
631 $ hg init testdelete/nested
637 $ hg init testdelete/nested2
632 $ hg init testdelete/nested2
638 $ echo test > testdelete/nested/foo
633 $ echo test > testdelete/nested/foo
639 $ echo test > testdelete/nested2/foo
634 $ echo test > testdelete/nested2/foo
640 $ hg -R testdelete/nested add
635 $ hg -R testdelete/nested add
641 adding testdelete/nested/foo (glob)
636 adding testdelete/nested/foo (glob)
642 $ hg -R testdelete/nested2 add
637 $ hg -R testdelete/nested2 add
643 adding testdelete/nested2/foo (glob)
638 adding testdelete/nested2/foo (glob)
644 $ hg -R testdelete/nested ci -m test
639 $ hg -R testdelete/nested ci -m test
645 $ hg -R testdelete/nested2 ci -m test
640 $ hg -R testdelete/nested2 ci -m test
646 $ echo nested = nested > testdelete/.hgsub
641 $ echo nested = nested > testdelete/.hgsub
647 $ echo nested2 = nested2 >> testdelete/.hgsub
642 $ echo nested2 = nested2 >> testdelete/.hgsub
648 $ hg -R testdelete add
643 $ hg -R testdelete add
649 adding testdelete/.hgsub (glob)
644 adding testdelete/.hgsub (glob)
650 $ hg -R testdelete ci -m "nested 1 & 2 added"
645 $ hg -R testdelete ci -m "nested 1 & 2 added"
651 $ echo nested = nested > testdelete/.hgsub
646 $ echo nested = nested > testdelete/.hgsub
652 $ hg -R testdelete ci -m "nested 2 deleted"
647 $ hg -R testdelete ci -m "nested 2 deleted"
653 $ cat testdelete/.hgsubstate
648 $ cat testdelete/.hgsubstate
654 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
649 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
655 $ hg -R testdelete remove testdelete/.hgsub
650 $ hg -R testdelete remove testdelete/.hgsub
656 $ hg -R testdelete ci -m ".hgsub deleted"
651 $ hg -R testdelete ci -m ".hgsub deleted"
657 $ cat testdelete/.hgsubstate
652 $ cat testdelete/.hgsubstate
658 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
653 bdf5c9a3103743d900b12ae0db3ffdcfd7b0d878 nested
659
654
660 test repository cloning
655 test repository cloning
661
656
662 $ mkdir mercurial mercurial2
657 $ mkdir mercurial mercurial2
663 $ hg init nested_absolute
658 $ hg init nested_absolute
664 $ echo test > nested_absolute/foo
659 $ echo test > nested_absolute/foo
665 $ hg -R nested_absolute add
660 $ hg -R nested_absolute add
666 adding nested_absolute/foo (glob)
661 adding nested_absolute/foo (glob)
667 $ hg -R nested_absolute ci -mtest
662 $ hg -R nested_absolute ci -mtest
668 $ cd mercurial
663 $ cd mercurial
669 $ hg init nested_relative
664 $ hg init nested_relative
670 $ echo test2 > nested_relative/foo2
665 $ echo test2 > nested_relative/foo2
671 $ hg -R nested_relative add
666 $ hg -R nested_relative add
672 adding nested_relative/foo2 (glob)
667 adding nested_relative/foo2 (glob)
673 $ hg -R nested_relative ci -mtest2
668 $ hg -R nested_relative ci -mtest2
674 $ hg init main
669 $ hg init main
675 $ echo "nested_relative = ../nested_relative" > main/.hgsub
670 $ echo "nested_relative = ../nested_relative" > main/.hgsub
676 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
671 $ echo "nested_absolute = `pwd`/nested_absolute" >> main/.hgsub
677 $ hg -R main add
672 $ hg -R main add
678 adding main/.hgsub (glob)
673 adding main/.hgsub (glob)
679 $ hg -R main ci -m "add subrepos"
674 $ hg -R main ci -m "add subrepos"
680 $ cd ..
675 $ cd ..
681 $ hg clone mercurial/main mercurial2/main
676 $ hg clone mercurial/main mercurial2/main
682 updating to branch default
677 updating to branch default
683 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
678 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
684 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
679 $ cat mercurial2/main/nested_absolute/.hg/hgrc \
685 > mercurial2/main/nested_relative/.hg/hgrc
680 > mercurial2/main/nested_relative/.hg/hgrc
686 [paths]
681 [paths]
687 default = $TESTTMP/mercurial/nested_absolute
682 default = $TESTTMP/mercurial/nested_absolute
688 [paths]
683 [paths]
689 default = $TESTTMP/mercurial/nested_relative
684 default = $TESTTMP/mercurial/nested_relative
690 $ rm -rf mercurial mercurial2
685 $ rm -rf mercurial mercurial2
691
686
692 Issue1977: multirepo push should fail if subrepo push fails
687 Issue1977: multirepo push should fail if subrepo push fails
693
688
694 $ hg init repo
689 $ hg init repo
695 $ hg init repo/s
690 $ hg init repo/s
696 $ echo a > repo/s/a
691 $ echo a > repo/s/a
697 $ hg -R repo/s ci -Am0
692 $ hg -R repo/s ci -Am0
698 adding a
693 adding a
699 $ echo s = s > repo/.hgsub
694 $ echo s = s > repo/.hgsub
700 $ hg -R repo ci -Am1
695 $ hg -R repo ci -Am1
701 adding .hgsub
696 adding .hgsub
702 $ hg clone repo repo2
697 $ hg clone repo repo2
703 updating to branch default
698 updating to branch default
704 cloning subrepo s from $TESTTMP/repo/s
699 cloning subrepo s from $TESTTMP/repo/s
705 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
700 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
706 $ hg -q -R repo2 pull -u
701 $ hg -q -R repo2 pull -u
707 $ echo 1 > repo2/s/a
702 $ echo 1 > repo2/s/a
708 $ hg -R repo2/s ci -m2
703 $ hg -R repo2/s ci -m2
709 $ hg -q -R repo2/s push
704 $ hg -q -R repo2/s push
710 $ hg -R repo2/s up -C 0
705 $ hg -R repo2/s up -C 0
711 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
706 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
712 $ echo 2 > repo2/s/b
707 $ echo 2 > repo2/s/b
713 $ hg -R repo2/s ci -m3 -A
708 $ hg -R repo2/s ci -m3 -A
714 adding b
709 adding b
715 created new head
710 created new head
716 $ hg -R repo2 ci -m3
711 $ hg -R repo2 ci -m3
717 $ hg -q -R repo2 push
712 $ hg -q -R repo2 push
718 abort: push creates new remote head cc505f09a8b2! (in subrepo s)
713 abort: push creates new remote head cc505f09a8b2! (in subrepo s)
719 (merge or see "hg help push" for details about pushing new heads)
714 (merge or see "hg help push" for details about pushing new heads)
720 [255]
715 [255]
721 $ hg -R repo update
716 $ hg -R repo update
722 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
717 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
723
718
724 test if untracked file is not overwritten
719 test if untracked file is not overwritten
725
720
726 $ echo issue3276_ok > repo/s/b
721 $ echo issue3276_ok > repo/s/b
727 $ hg -R repo2 push -f -q
722 $ hg -R repo2 push -f -q
728 $ hg -R repo update
723 $ hg -R repo update
729 b: untracked file differs
724 b: untracked file differs
730 abort: untracked files in working directory differ from files in requested revision (in subrepo s)
725 abort: untracked files in working directory differ from files in requested revision (in subrepo s)
731 [255]
726 [255]
732
727
733 $ cat repo/s/b
728 $ cat repo/s/b
734 issue3276_ok
729 issue3276_ok
735 $ rm repo/s/b
730 $ rm repo/s/b
736 $ hg -R repo revert --all
731 $ hg -R repo revert --all
737 reverting repo/.hgsubstate (glob)
732 reverting repo/.hgsubstate (glob)
738 reverting subrepo s
733 reverting subrepo s
739 $ hg -R repo update
734 $ hg -R repo update
740 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
735 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
741 $ cat repo/s/b
736 $ cat repo/s/b
742 2
737 2
743 $ rm -rf repo2 repo
738 $ rm -rf repo2 repo
744
739
745
740
746 Issue1852 subrepos with relative paths always push/pull relative to default
741 Issue1852 subrepos with relative paths always push/pull relative to default
747
742
748 Prepare a repo with subrepo
743 Prepare a repo with subrepo
749
744
750 $ hg init issue1852a
745 $ hg init issue1852a
751 $ cd issue1852a
746 $ cd issue1852a
752 $ hg init sub/repo
747 $ hg init sub/repo
753 $ echo test > sub/repo/foo
748 $ echo test > sub/repo/foo
754 $ hg -R sub/repo add sub/repo/foo
749 $ hg -R sub/repo add sub/repo/foo
755 $ echo sub/repo = sub/repo > .hgsub
750 $ echo sub/repo = sub/repo > .hgsub
756 $ hg add .hgsub
751 $ hg add .hgsub
757 $ hg ci -mtest
752 $ hg ci -mtest
758 committing subrepository sub/repo (glob)
753 committing subrepository sub/repo (glob)
759 $ echo test >> sub/repo/foo
754 $ echo test >> sub/repo/foo
760 $ hg ci -mtest
755 $ hg ci -mtest
761 committing subrepository sub/repo (glob)
756 committing subrepository sub/repo (glob)
762 $ cd ..
757 $ cd ..
763
758
764 Create repo without default path, pull top repo, and see what happens on update
759 Create repo without default path, pull top repo, and see what happens on update
765
760
766 $ hg init issue1852b
761 $ hg init issue1852b
767 $ hg -R issue1852b pull issue1852a
762 $ hg -R issue1852b pull issue1852a
768 pulling from issue1852a
763 pulling from issue1852a
769 requesting all changes
764 requesting all changes
770 adding changesets
765 adding changesets
771 adding manifests
766 adding manifests
772 adding file changes
767 adding file changes
773 added 2 changesets with 3 changes to 2 files
768 added 2 changesets with 3 changes to 2 files
774 (run 'hg update' to get a working copy)
769 (run 'hg update' to get a working copy)
775 $ hg -R issue1852b update
770 $ hg -R issue1852b update
776 abort: default path for subrepository not found (in subrepo sub/repo) (glob)
771 abort: default path for subrepository not found (in subrepo sub/repo) (glob)
777 [255]
772 [255]
778
773
779 Ensure a full traceback, not just the SubrepoAbort part
774 Ensure a full traceback, not just the SubrepoAbort part
780
775
781 $ hg -R issue1852b update --traceback 2>&1 | grep 'raise util\.Abort'
776 $ hg -R issue1852b update --traceback 2>&1 | grep 'raise util\.Abort'
782 raise util.Abort(_("default path for subrepository not found"))
777 raise util.Abort(_("default path for subrepository not found"))
783
778
784 Pull -u now doesn't help
779 Pull -u now doesn't help
785
780
786 $ hg -R issue1852b pull -u issue1852a
781 $ hg -R issue1852b pull -u issue1852a
787 pulling from issue1852a
782 pulling from issue1852a
788 searching for changes
783 searching for changes
789 no changes found
784 no changes found
790
785
791 Try the same, but with pull -u
786 Try the same, but with pull -u
792
787
793 $ hg init issue1852c
788 $ hg init issue1852c
794 $ hg -R issue1852c pull -r0 -u issue1852a
789 $ hg -R issue1852c pull -r0 -u issue1852a
795 pulling from issue1852a
790 pulling from issue1852a
796 adding changesets
791 adding changesets
797 adding manifests
792 adding manifests
798 adding file changes
793 adding file changes
799 added 1 changesets with 2 changes to 2 files
794 added 1 changesets with 2 changes to 2 files
800 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
795 cloning subrepo sub/repo from issue1852a/sub/repo (glob)
801 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
796 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
802
797
803 Try to push from the other side
798 Try to push from the other side
804
799
805 $ hg -R issue1852a push `pwd`/issue1852c
800 $ hg -R issue1852a push `pwd`/issue1852c
806 pushing to $TESTTMP/issue1852c (glob)
801 pushing to $TESTTMP/issue1852c (glob)
807 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob)
802 pushing subrepo sub/repo to $TESTTMP/issue1852c/sub/repo (glob)
808 searching for changes
803 searching for changes
809 no changes found
804 no changes found
810 searching for changes
805 searching for changes
811 adding changesets
806 adding changesets
812 adding manifests
807 adding manifests
813 adding file changes
808 adding file changes
814 added 1 changesets with 1 changes to 1 files
809 added 1 changesets with 1 changes to 1 files
815
810
816 Incoming and outgoing should not use the default path:
811 Incoming and outgoing should not use the default path:
817
812
818 $ hg clone -q issue1852a issue1852d
813 $ hg clone -q issue1852a issue1852d
819 $ hg -R issue1852d outgoing --subrepos issue1852c
814 $ hg -R issue1852d outgoing --subrepos issue1852c
820 comparing with issue1852c
815 comparing with issue1852c
821 searching for changes
816 searching for changes
822 no changes found
817 no changes found
823 comparing with issue1852c/sub/repo
818 comparing with issue1852c/sub/repo
824 searching for changes
819 searching for changes
825 no changes found
820 no changes found
826 [1]
821 [1]
827 $ hg -R issue1852d incoming --subrepos issue1852c
822 $ hg -R issue1852d incoming --subrepos issue1852c
828 comparing with issue1852c
823 comparing with issue1852c
829 searching for changes
824 searching for changes
830 no changes found
825 no changes found
831 comparing with issue1852c/sub/repo
826 comparing with issue1852c/sub/repo
832 searching for changes
827 searching for changes
833 no changes found
828 no changes found
834 [1]
829 [1]
835
830
836 Check status of files when none of them belong to the first
831 Check status of files when none of them belong to the first
837 subrepository:
832 subrepository:
838
833
839 $ hg init subrepo-status
834 $ hg init subrepo-status
840 $ cd subrepo-status
835 $ cd subrepo-status
841 $ hg init subrepo-1
836 $ hg init subrepo-1
842 $ hg init subrepo-2
837 $ hg init subrepo-2
843 $ cd subrepo-2
838 $ cd subrepo-2
844 $ touch file
839 $ touch file
845 $ hg add file
840 $ hg add file
846 $ cd ..
841 $ cd ..
847 $ echo subrepo-1 = subrepo-1 > .hgsub
842 $ echo subrepo-1 = subrepo-1 > .hgsub
848 $ echo subrepo-2 = subrepo-2 >> .hgsub
843 $ echo subrepo-2 = subrepo-2 >> .hgsub
849 $ hg add .hgsub
844 $ hg add .hgsub
850 $ hg ci -m 'Added subrepos'
845 $ hg ci -m 'Added subrepos'
851 committing subrepository subrepo-2
846 committing subrepository subrepo-2
852 $ hg st subrepo-2/file
847 $ hg st subrepo-2/file
853
848
854 Check that share works with subrepo
849 Check that share works with subrepo
855 $ hg --config extensions.share= share . ../shared
850 $ hg --config extensions.share= share . ../shared
856 updating working directory
851 updating working directory
857 cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
852 cloning subrepo subrepo-2 from $TESTTMP/subrepo-status/subrepo-2
858 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
853 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
859 $ test -f ../shared/subrepo-1/.hg/sharedpath
854 $ test -f ../shared/subrepo-1/.hg/sharedpath
860 [1]
855 [1]
861 $ hg -R ../shared in
856 $ hg -R ../shared in
862 abort: repository default not found!
857 abort: repository default not found!
863 [255]
858 [255]
864 $ hg -R ../shared/subrepo-2 showconfig paths
859 $ hg -R ../shared/subrepo-2 showconfig paths
865 paths.default=$TESTTMP/subrepo-status/subrepo-2
860 paths.default=$TESTTMP/subrepo-status/subrepo-2
866 $ hg -R ../shared/subrepo-1 sum --remote
861 $ hg -R ../shared/subrepo-1 sum --remote
867 parent: -1:000000000000 tip (empty repository)
862 parent: -1:000000000000 tip (empty repository)
868 branch: default
863 branch: default
869 commit: (clean)
864 commit: (clean)
870 update: (current)
865 update: (current)
871 remote: (synced)
866 remote: (synced)
872
867
873 Check hg update --clean
868 Check hg update --clean
874 $ cd $TESTTMP/t
869 $ cd $TESTTMP/t
875 $ rm -r t/t.orig
870 $ rm -r t/t.orig
876 $ hg status -S --all
871 $ hg status -S --all
877 C .hgsub
872 C .hgsub
878 C .hgsubstate
873 C .hgsubstate
879 C a
874 C a
880 C s/.hgsub
875 C s/.hgsub
881 C s/.hgsubstate
876 C s/.hgsubstate
882 C s/a
877 C s/a
883 C s/ss/a
878 C s/ss/a
884 C t/t
879 C t/t
885 $ echo c1 > s/a
880 $ echo c1 > s/a
886 $ cd s
881 $ cd s
887 $ echo c1 > b
882 $ echo c1 > b
888 $ echo c1 > c
883 $ echo c1 > c
889 $ hg add b
884 $ hg add b
890 $ cd ..
885 $ cd ..
891 $ hg status -S
886 $ hg status -S
892 M s/a
887 M s/a
893 A s/b
888 A s/b
894 ? s/c
889 ? s/c
895 $ hg update -C
890 $ hg update -C
896 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
891 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
897 $ hg status -S
892 $ hg status -S
898 ? s/b
893 ? s/b
899 ? s/c
894 ? s/c
900
895
901 Sticky subrepositories, no changes
896 Sticky subrepositories, no changes
902 $ cd $TESTTMP/t
897 $ cd $TESTTMP/t
903 $ hg id
898 $ hg id
904 925c17564ef8 tip
899 925c17564ef8 tip
905 $ hg -R s id
900 $ hg -R s id
906 12a213df6fa9 tip
901 12a213df6fa9 tip
907 $ hg -R t id
902 $ hg -R t id
908 52c0adc0515a tip
903 52c0adc0515a tip
909 $ hg update 11
904 $ hg update 11
910 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
905 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
911 $ hg id
906 $ hg id
912 365661e5936a
907 365661e5936a
913 $ hg -R s id
908 $ hg -R s id
914 fc627a69481f
909 fc627a69481f
915 $ hg -R t id
910 $ hg -R t id
916 e95bcfa18a35
911 e95bcfa18a35
917
912
918 Sticky subrepositorys, file changes
913 Sticky subrepositorys, file changes
919 $ touch s/f1
914 $ touch s/f1
920 $ touch t/f1
915 $ touch t/f1
921 $ hg add -S s/f1
916 $ hg add -S s/f1
922 $ hg add -S t/f1
917 $ hg add -S t/f1
923 $ hg id
918 $ hg id
924 365661e5936a+
919 365661e5936a+
925 $ hg -R s id
920 $ hg -R s id
926 fc627a69481f+
921 fc627a69481f+
927 $ hg -R t id
922 $ hg -R t id
928 e95bcfa18a35+
923 e95bcfa18a35+
929 $ hg update tip
924 $ hg update tip
930 subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
925 subrepository s diverged (local revision: fc627a69481f, remote revision: 12a213df6fa9)
931 (M)erge, keep (l)ocal or keep (r)emote? m
926 (M)erge, keep (l)ocal or keep (r)emote? m
932 subrepository sources for s differ
927 subrepository sources for s differ
933 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
928 use (l)ocal source (fc627a69481f) or (r)emote source (12a213df6fa9)?
934 l
929 l
935 subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
930 subrepository t diverged (local revision: e95bcfa18a35, remote revision: 52c0adc0515a)
936 (M)erge, keep (l)ocal or keep (r)emote? m
931 (M)erge, keep (l)ocal or keep (r)emote? m
937 subrepository sources for t differ
932 subrepository sources for t differ
938 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
933 use (l)ocal source (e95bcfa18a35) or (r)emote source (52c0adc0515a)?
939 l
934 l
940 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
935 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
941 $ hg id
936 $ hg id
942 925c17564ef8+ tip
937 925c17564ef8+ tip
943 $ hg -R s id
938 $ hg -R s id
944 fc627a69481f+
939 fc627a69481f+
945 $ hg -R t id
940 $ hg -R t id
946 e95bcfa18a35+
941 e95bcfa18a35+
947 $ hg update --clean tip
942 $ hg update --clean tip
948 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
943 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
949
944
950 Sticky subrepository, revision updates
945 Sticky subrepository, revision updates
951 $ hg id
946 $ hg id
952 925c17564ef8 tip
947 925c17564ef8 tip
953 $ hg -R s id
948 $ hg -R s id
954 12a213df6fa9 tip
949 12a213df6fa9 tip
955 $ hg -R t id
950 $ hg -R t id
956 52c0adc0515a tip
951 52c0adc0515a tip
957 $ cd s
952 $ cd s
958 $ hg update -r -2
953 $ hg update -r -2
959 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
954 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
960 $ cd ../t
955 $ cd ../t
961 $ hg update -r 2
956 $ hg update -r 2
962 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
957 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
963 $ cd ..
958 $ cd ..
964 $ hg update 10
959 $ hg update 10
965 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
960 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
966 (M)erge, keep (l)ocal or keep (r)emote? m
961 (M)erge, keep (l)ocal or keep (r)emote? m
967 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
962 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 20a0db6fbf6c)
968 (M)erge, keep (l)ocal or keep (r)emote? m
963 (M)erge, keep (l)ocal or keep (r)emote? m
969 subrepository sources for t differ (in checked out version)
964 subrepository sources for t differ (in checked out version)
970 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
965 use (l)ocal source (7af322bc1198) or (r)emote source (20a0db6fbf6c)?
971 l
966 l
972 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
967 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
973 $ hg id
968 $ hg id
974 e45c8b14af55+
969 e45c8b14af55+
975 $ hg -R s id
970 $ hg -R s id
976 02dcf1d70411
971 02dcf1d70411
977 $ hg -R t id
972 $ hg -R t id
978 7af322bc1198
973 7af322bc1198
979
974
980 Sticky subrepository, file changes and revision updates
975 Sticky subrepository, file changes and revision updates
981 $ touch s/f1
976 $ touch s/f1
982 $ touch t/f1
977 $ touch t/f1
983 $ hg add -S s/f1
978 $ hg add -S s/f1
984 $ hg add -S t/f1
979 $ hg add -S t/f1
985 $ hg id
980 $ hg id
986 e45c8b14af55+
981 e45c8b14af55+
987 $ hg -R s id
982 $ hg -R s id
988 02dcf1d70411+
983 02dcf1d70411+
989 $ hg -R t id
984 $ hg -R t id
990 7af322bc1198+
985 7af322bc1198+
991 $ hg update tip
986 $ hg update tip
992 subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
987 subrepository s diverged (local revision: 12a213df6fa9, remote revision: 12a213df6fa9)
993 (M)erge, keep (l)ocal or keep (r)emote? m
988 (M)erge, keep (l)ocal or keep (r)emote? m
994 subrepository sources for s differ
989 subrepository sources for s differ
995 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)?
990 use (l)ocal source (02dcf1d70411) or (r)emote source (12a213df6fa9)?
996 l
991 l
997 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
992 subrepository t diverged (local revision: 52c0adc0515a, remote revision: 52c0adc0515a)
998 (M)erge, keep (l)ocal or keep (r)emote? m
993 (M)erge, keep (l)ocal or keep (r)emote? m
999 subrepository sources for t differ
994 subrepository sources for t differ
1000 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
995 use (l)ocal source (7af322bc1198) or (r)emote source (52c0adc0515a)?
1001 l
996 l
1002 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
997 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1003 $ hg id
998 $ hg id
1004 925c17564ef8+ tip
999 925c17564ef8+ tip
1005 $ hg -R s id
1000 $ hg -R s id
1006 02dcf1d70411+
1001 02dcf1d70411+
1007 $ hg -R t id
1002 $ hg -R t id
1008 7af322bc1198+
1003 7af322bc1198+
1009
1004
1010 Sticky repository, update --clean
1005 Sticky repository, update --clean
1011 $ hg update --clean tip
1006 $ hg update --clean tip
1012 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1007 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1013 $ hg id
1008 $ hg id
1014 925c17564ef8 tip
1009 925c17564ef8 tip
1015 $ hg -R s id
1010 $ hg -R s id
1016 12a213df6fa9 tip
1011 12a213df6fa9 tip
1017 $ hg -R t id
1012 $ hg -R t id
1018 52c0adc0515a tip
1013 52c0adc0515a tip
1019
1014
1020 Test subrepo already at intended revision:
1015 Test subrepo already at intended revision:
1021 $ cd s
1016 $ cd s
1022 $ hg update fc627a69481f
1017 $ hg update fc627a69481f
1023 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1018 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
1024 $ cd ..
1019 $ cd ..
1025 $ hg update 11
1020 $ hg update 11
1026 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1021 subrepository s diverged (local revision: 12a213df6fa9, remote revision: fc627a69481f)
1027 (M)erge, keep (l)ocal or keep (r)emote? m
1022 (M)erge, keep (l)ocal or keep (r)emote? m
1028 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1023 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1029 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1024 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
1030 $ hg id -n
1025 $ hg id -n
1031 11+
1026 11+
1032 $ hg -R s id
1027 $ hg -R s id
1033 fc627a69481f
1028 fc627a69481f
1034 $ hg -R t id
1029 $ hg -R t id
1035 e95bcfa18a35
1030 e95bcfa18a35
1036
1031
1037 Test that removing .hgsubstate doesn't break anything:
1032 Test that removing .hgsubstate doesn't break anything:
1038
1033
1039 $ hg rm -f .hgsubstate
1034 $ hg rm -f .hgsubstate
1040 $ hg ci -mrm
1035 $ hg ci -mrm
1041 nothing changed
1036 nothing changed
1042 [1]
1037 [1]
1043 $ hg log -vr tip
1038 $ hg log -vr tip
1044 changeset: 13:925c17564ef8
1039 changeset: 13:925c17564ef8
1045 tag: tip
1040 tag: tip
1046 user: test
1041 user: test
1047 date: Thu Jan 01 00:00:00 1970 +0000
1042 date: Thu Jan 01 00:00:00 1970 +0000
1048 files: .hgsubstate
1043 files: .hgsubstate
1049 description:
1044 description:
1050 13
1045 13
1051
1046
1052
1047
1053
1048
1054 Test that removing .hgsub removes .hgsubstate:
1049 Test that removing .hgsub removes .hgsubstate:
1055
1050
1056 $ hg rm .hgsub
1051 $ hg rm .hgsub
1057 $ hg ci -mrm2
1052 $ hg ci -mrm2
1058 created new head
1053 created new head
1059 $ hg log -vr tip
1054 $ hg log -vr tip
1060 changeset: 14:2400bccd50af
1055 changeset: 14:2400bccd50af
1061 tag: tip
1056 tag: tip
1062 parent: 11:365661e5936a
1057 parent: 11:365661e5936a
1063 user: test
1058 user: test
1064 date: Thu Jan 01 00:00:00 1970 +0000
1059 date: Thu Jan 01 00:00:00 1970 +0000
1065 files: .hgsub .hgsubstate
1060 files: .hgsub .hgsubstate
1066 description:
1061 description:
1067 rm2
1062 rm2
1068
1063
1069
1064
1070 Test issue3153: diff -S with deleted subrepos
1065 Test issue3153: diff -S with deleted subrepos
1071
1066
1072 $ hg diff --nodates -S -c .
1067 $ hg diff --nodates -S -c .
1073 diff -r 365661e5936a -r 2400bccd50af .hgsub
1068 diff -r 365661e5936a -r 2400bccd50af .hgsub
1074 --- a/.hgsub
1069 --- a/.hgsub
1075 +++ /dev/null
1070 +++ /dev/null
1076 @@ -1,2 +0,0 @@
1071 @@ -1,2 +0,0 @@
1077 -s = s
1072 -s = s
1078 -t = t
1073 -t = t
1079 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
1074 diff -r 365661e5936a -r 2400bccd50af .hgsubstate
1080 --- a/.hgsubstate
1075 --- a/.hgsubstate
1081 +++ /dev/null
1076 +++ /dev/null
1082 @@ -1,2 +0,0 @@
1077 @@ -1,2 +0,0 @@
1083 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1078 -fc627a69481fcbe5f1135069e8a3881c023e4cf5 s
1084 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
1079 -e95bcfa18a358dc4936da981ebf4147b4cad1362 t
1085
1080
1086 Test behavior of add for explicit path in subrepo:
1081 Test behavior of add for explicit path in subrepo:
1087 $ cd ..
1082 $ cd ..
1088 $ hg init explicit
1083 $ hg init explicit
1089 $ cd explicit
1084 $ cd explicit
1090 $ echo s = s > .hgsub
1085 $ echo s = s > .hgsub
1091 $ hg add .hgsub
1086 $ hg add .hgsub
1092 $ hg init s
1087 $ hg init s
1093 $ hg ci -m0
1088 $ hg ci -m0
1094 Adding with an explicit path in a subrepo adds the file
1089 Adding with an explicit path in a subrepo adds the file
1095 $ echo c1 > f1
1090 $ echo c1 > f1
1096 $ echo c2 > s/f2
1091 $ echo c2 > s/f2
1097 $ hg st -S
1092 $ hg st -S
1098 ? f1
1093 ? f1
1099 ? s/f2
1094 ? s/f2
1100 $ hg add s/f2
1095 $ hg add s/f2
1101 $ hg st -S
1096 $ hg st -S
1102 A s/f2
1097 A s/f2
1103 ? f1
1098 ? f1
1104 $ hg ci -R s -m0
1099 $ hg ci -R s -m0
1105 $ hg ci -Am1
1100 $ hg ci -Am1
1106 adding f1
1101 adding f1
1107 Adding with an explicit path in a subrepo with -S has the same behavior
1102 Adding with an explicit path in a subrepo with -S has the same behavior
1108 $ echo c3 > f3
1103 $ echo c3 > f3
1109 $ echo c4 > s/f4
1104 $ echo c4 > s/f4
1110 $ hg st -S
1105 $ hg st -S
1111 ? f3
1106 ? f3
1112 ? s/f4
1107 ? s/f4
1113 $ hg add -S s/f4
1108 $ hg add -S s/f4
1114 $ hg st -S
1109 $ hg st -S
1115 A s/f4
1110 A s/f4
1116 ? f3
1111 ? f3
1117 $ hg ci -R s -m1
1112 $ hg ci -R s -m1
1118 $ hg ci -Ama2
1113 $ hg ci -Ama2
1119 adding f3
1114 adding f3
1120 Adding without a path or pattern silently ignores subrepos
1115 Adding without a path or pattern silently ignores subrepos
1121 $ echo c5 > f5
1116 $ echo c5 > f5
1122 $ echo c6 > s/f6
1117 $ echo c6 > s/f6
1123 $ echo c7 > s/f7
1118 $ echo c7 > s/f7
1124 $ hg st -S
1119 $ hg st -S
1125 ? f5
1120 ? f5
1126 ? s/f6
1121 ? s/f6
1127 ? s/f7
1122 ? s/f7
1128 $ hg add
1123 $ hg add
1129 adding f5
1124 adding f5
1130 $ hg st -S
1125 $ hg st -S
1131 A f5
1126 A f5
1132 ? s/f6
1127 ? s/f6
1133 ? s/f7
1128 ? s/f7
1134 $ hg ci -R s -Am2
1129 $ hg ci -R s -Am2
1135 adding f6
1130 adding f6
1136 adding f7
1131 adding f7
1137 $ hg ci -m3
1132 $ hg ci -m3
1138 Adding without a path or pattern with -S also adds files in subrepos
1133 Adding without a path or pattern with -S also adds files in subrepos
1139 $ echo c8 > f8
1134 $ echo c8 > f8
1140 $ echo c9 > s/f9
1135 $ echo c9 > s/f9
1141 $ echo c10 > s/f10
1136 $ echo c10 > s/f10
1142 $ hg st -S
1137 $ hg st -S
1143 ? f8
1138 ? f8
1144 ? s/f10
1139 ? s/f10
1145 ? s/f9
1140 ? s/f9
1146 $ hg add -S
1141 $ hg add -S
1147 adding f8
1142 adding f8
1148 adding s/f10 (glob)
1143 adding s/f10 (glob)
1149 adding s/f9 (glob)
1144 adding s/f9 (glob)
1150 $ hg st -S
1145 $ hg st -S
1151 A f8
1146 A f8
1152 A s/f10
1147 A s/f10
1153 A s/f9
1148 A s/f9
1154 $ hg ci -R s -m3
1149 $ hg ci -R s -m3
1155 $ hg ci -m4
1150 $ hg ci -m4
1156 Adding with a pattern silently ignores subrepos
1151 Adding with a pattern silently ignores subrepos
1157 $ echo c11 > fm11
1152 $ echo c11 > fm11
1158 $ echo c12 > fn12
1153 $ echo c12 > fn12
1159 $ echo c13 > s/fm13
1154 $ echo c13 > s/fm13
1160 $ echo c14 > s/fn14
1155 $ echo c14 > s/fn14
1161 $ hg st -S
1156 $ hg st -S
1162 ? fm11
1157 ? fm11
1163 ? fn12
1158 ? fn12
1164 ? s/fm13
1159 ? s/fm13
1165 ? s/fn14
1160 ? s/fn14
1166 $ hg add 'glob:**fm*'
1161 $ hg add 'glob:**fm*'
1167 adding fm11
1162 adding fm11
1168 $ hg st -S
1163 $ hg st -S
1169 A fm11
1164 A fm11
1170 ? fn12
1165 ? fn12
1171 ? s/fm13
1166 ? s/fm13
1172 ? s/fn14
1167 ? s/fn14
1173 $ hg ci -R s -Am4
1168 $ hg ci -R s -Am4
1174 adding fm13
1169 adding fm13
1175 adding fn14
1170 adding fn14
1176 $ hg ci -Am5
1171 $ hg ci -Am5
1177 adding fn12
1172 adding fn12
1178 Adding with a pattern with -S also adds matches in subrepos
1173 Adding with a pattern with -S also adds matches in subrepos
1179 $ echo c15 > fm15
1174 $ echo c15 > fm15
1180 $ echo c16 > fn16
1175 $ echo c16 > fn16
1181 $ echo c17 > s/fm17
1176 $ echo c17 > s/fm17
1182 $ echo c18 > s/fn18
1177 $ echo c18 > s/fn18
1183 $ hg st -S
1178 $ hg st -S
1184 ? fm15
1179 ? fm15
1185 ? fn16
1180 ? fn16
1186 ? s/fm17
1181 ? s/fm17
1187 ? s/fn18
1182 ? s/fn18
1188 $ hg add -S 'glob:**fm*'
1183 $ hg add -S 'glob:**fm*'
1189 adding fm15
1184 adding fm15
1190 adding s/fm17 (glob)
1185 adding s/fm17 (glob)
1191 $ hg st -S
1186 $ hg st -S
1192 A fm15
1187 A fm15
1193 A s/fm17
1188 A s/fm17
1194 ? fn16
1189 ? fn16
1195 ? s/fn18
1190 ? s/fn18
1196 $ hg ci -R s -Am5
1191 $ hg ci -R s -Am5
1197 adding fn18
1192 adding fn18
1198 $ hg ci -Am6
1193 $ hg ci -Am6
1199 adding fn16
1194 adding fn16
1200
1195
1201 Test behavior of forget for explicit path in subrepo:
1196 Test behavior of forget for explicit path in subrepo:
1202 Forgetting an explicit path in a subrepo untracks the file
1197 Forgetting an explicit path in a subrepo untracks the file
1203 $ echo c19 > s/f19
1198 $ echo c19 > s/f19
1204 $ hg add s/f19
1199 $ hg add s/f19
1205 $ hg st -S
1200 $ hg st -S
1206 A s/f19
1201 A s/f19
1207 $ hg forget s/f19
1202 $ hg forget s/f19
1208 $ hg st -S
1203 $ hg st -S
1209 ? s/f19
1204 ? s/f19
1210 $ rm s/f19
1205 $ rm s/f19
1211 $ cd ..
1206 $ cd ..
1212
1207
1213 Courtesy phases synchronisation to publishing server does not block the push
1208 Courtesy phases synchronisation to publishing server does not block the push
1214 (issue3781)
1209 (issue3781)
1215
1210
1216 $ cp -r main issue3781
1211 $ cp -r main issue3781
1217 $ cp -r main issue3781-dest
1212 $ cp -r main issue3781-dest
1218 $ cd issue3781-dest/s
1213 $ cd issue3781-dest/s
1219 $ hg phase tip # show we have draft changeset
1214 $ hg phase tip # show we have draft changeset
1220 5: draft
1215 5: draft
1221 $ chmod a-w .hg/store/phaseroots # prevent phase push
1216 $ chmod a-w .hg/store/phaseroots # prevent phase push
1222 $ cd ../../issue3781
1217 $ cd ../../issue3781
1223 $ cat >> .hg/hgrc << EOF
1218 $ cat >> .hg/hgrc << EOF
1224 > [paths]
1219 > [paths]
1225 > default=../issue3781-dest/
1220 > default=../issue3781-dest/
1226 > EOF
1221 > EOF
1227 $ hg push
1222 $ hg push
1228 pushing to $TESTTMP/issue3781-dest (glob)
1223 pushing to $TESTTMP/issue3781-dest (glob)
1229 pushing subrepo s to $TESTTMP/issue3781-dest/s
1224 pushing subrepo s to $TESTTMP/issue3781-dest/s
1230 searching for changes
1225 searching for changes
1231 no changes found
1226 no changes found
1232 searching for changes
1227 searching for changes
1233 no changes found
1228 no changes found
1234 [1]
1229 [1]
1235 $ cd ..
1230 $ cd ..
1236
1231
1237 Test phase choice for newly created commit with "phases.subrepochecks"
1232 Test phase choice for newly created commit with "phases.subrepochecks"
1238 configuration
1233 configuration
1239
1234
1240 $ cd t
1235 $ cd t
1241 $ hg update -q -r 12
1236 $ hg update -q -r 12
1242
1237
1243 $ cat >> s/ss/.hg/hgrc <<EOF
1238 $ cat >> s/ss/.hg/hgrc <<EOF
1244 > [phases]
1239 > [phases]
1245 > new-commit = secret
1240 > new-commit = secret
1246 > EOF
1241 > EOF
1247 $ cat >> s/.hg/hgrc <<EOF
1242 $ cat >> s/.hg/hgrc <<EOF
1248 > [phases]
1243 > [phases]
1249 > new-commit = draft
1244 > new-commit = draft
1250 > EOF
1245 > EOF
1251 $ echo phasecheck1 >> s/ss/a
1246 $ echo phasecheck1 >> s/ss/a
1252 $ hg -R s commit -S --config phases.checksubrepos=abort -m phasecheck1
1247 $ hg -R s commit -S --config phases.checksubrepos=abort -m phasecheck1
1253 committing subrepository ss
1248 committing subrepository ss
1254 transaction abort!
1249 transaction abort!
1255 rollback completed
1250 rollback completed
1256 abort: can't commit in draft phase conflicting secret from subrepository ss
1251 abort: can't commit in draft phase conflicting secret from subrepository ss
1257 [255]
1252 [255]
1258 $ echo phasecheck2 >> s/ss/a
1253 $ echo phasecheck2 >> s/ss/a
1259 $ hg -R s commit -S --config phases.checksubrepos=ignore -m phasecheck2
1254 $ hg -R s commit -S --config phases.checksubrepos=ignore -m phasecheck2
1260 committing subrepository ss
1255 committing subrepository ss
1261 $ hg -R s/ss phase tip
1256 $ hg -R s/ss phase tip
1262 3: secret
1257 3: secret
1263 $ hg -R s phase tip
1258 $ hg -R s phase tip
1264 6: draft
1259 6: draft
1265 $ echo phasecheck3 >> s/ss/a
1260 $ echo phasecheck3 >> s/ss/a
1266 $ hg -R s commit -S -m phasecheck3
1261 $ hg -R s commit -S -m phasecheck3
1267 committing subrepository ss
1262 committing subrepository ss
1268 warning: changes are committed in secret phase from subrepository ss
1263 warning: changes are committed in secret phase from subrepository ss
1269 $ hg -R s/ss phase tip
1264 $ hg -R s/ss phase tip
1270 4: secret
1265 4: secret
1271 $ hg -R s phase tip
1266 $ hg -R s phase tip
1272 7: secret
1267 7: secret
1273
1268
1274 $ cat >> t/.hg/hgrc <<EOF
1269 $ cat >> t/.hg/hgrc <<EOF
1275 > [phases]
1270 > [phases]
1276 > new-commit = draft
1271 > new-commit = draft
1277 > EOF
1272 > EOF
1278 $ cat >> .hg/hgrc <<EOF
1273 $ cat >> .hg/hgrc <<EOF
1279 > [phases]
1274 > [phases]
1280 > new-commit = public
1275 > new-commit = public
1281 > EOF
1276 > EOF
1282 $ echo phasecheck4 >> s/ss/a
1277 $ echo phasecheck4 >> s/ss/a
1283 $ echo phasecheck4 >> t/t
1278 $ echo phasecheck4 >> t/t
1284 $ hg commit -S -m phasecheck4
1279 $ hg commit -S -m phasecheck4
1285 committing subrepository s
1280 committing subrepository s
1286 committing subrepository s/ss
1281 committing subrepository s/ss
1287 warning: changes are committed in secret phase from subrepository ss
1282 warning: changes are committed in secret phase from subrepository ss
1288 committing subrepository t
1283 committing subrepository t
1289 warning: changes are committed in secret phase from subrepository s
1284 warning: changes are committed in secret phase from subrepository s
1290 created new head
1285 created new head
1291 $ hg -R s/ss phase tip
1286 $ hg -R s/ss phase tip
1292 5: secret
1287 5: secret
1293 $ hg -R s phase tip
1288 $ hg -R s phase tip
1294 8: secret
1289 8: secret
1295 $ hg -R t phase tip
1290 $ hg -R t phase tip
1296 6: draft
1291 6: draft
1297 $ hg phase tip
1292 $ hg phase tip
1298 15: secret
1293 15: secret
1299
1294
1300 $ cd ..
1295 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now