##// END OF EJS Templates
bookmarks: split ui.write() so that it can be easily ported to formatter api...
Yuya Nishihara -
r22775:b59c2c8c default
parent child Browse files
Show More
@@ -1,6319 +1,6321 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, shlex
11 import os, re, difflib, time, tempfile, errno, shlex
12 import sys, socket
12 import sys, socket
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb, commandserver
16 import sshserver, hgweb, commandserver
17 import extensions
17 import extensions
18 from hgweb import server as hgweb_server
18 from hgweb import server as hgweb_server
19 import merge as mergemod
19 import merge as mergemod
20 import minirst, revset, fileset
20 import minirst, revset, fileset
21 import dagparser, context, simplemerge, graphmod
21 import dagparser, context, simplemerge, graphmod
22 import random
22 import random
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
24 import phases, obsolete, exchange
24 import phases, obsolete, exchange
25
25
26 table = {}
26 table = {}
27
27
28 command = cmdutil.command(table)
28 command = cmdutil.command(table)
29
29
30 # Space delimited list of commands that don't require local repositories.
30 # Space delimited list of commands that don't require local repositories.
31 # This should be populated by passing norepo=True into the @command decorator.
31 # This should be populated by passing norepo=True into the @command decorator.
32 norepo = ''
32 norepo = ''
33 # Space delimited list of commands that optionally require local repositories.
33 # Space delimited list of commands that optionally require local repositories.
34 # This should be populated by passing optionalrepo=True into the @command
34 # This should be populated by passing optionalrepo=True into the @command
35 # decorator.
35 # decorator.
36 optionalrepo = ''
36 optionalrepo = ''
37 # Space delimited list of commands that will examine arguments looking for
37 # Space delimited list of commands that will examine arguments looking for
38 # a repository. This should be populated by passing inferrepo=True into the
38 # a repository. This should be populated by passing inferrepo=True into the
39 # @command decorator.
39 # @command decorator.
40 inferrepo = ''
40 inferrepo = ''
41
41
42 # common command options
42 # common command options
43
43
44 globalopts = [
44 globalopts = [
45 ('R', 'repository', '',
45 ('R', 'repository', '',
46 _('repository root directory or name of overlay bundle file'),
46 _('repository root directory or name of overlay bundle file'),
47 _('REPO')),
47 _('REPO')),
48 ('', 'cwd', '',
48 ('', 'cwd', '',
49 _('change working directory'), _('DIR')),
49 _('change working directory'), _('DIR')),
50 ('y', 'noninteractive', None,
50 ('y', 'noninteractive', None,
51 _('do not prompt, automatically pick the first choice for all prompts')),
51 _('do not prompt, automatically pick the first choice for all prompts')),
52 ('q', 'quiet', None, _('suppress output')),
52 ('q', 'quiet', None, _('suppress output')),
53 ('v', 'verbose', None, _('enable additional output')),
53 ('v', 'verbose', None, _('enable additional output')),
54 ('', 'config', [],
54 ('', 'config', [],
55 _('set/override config option (use \'section.name=value\')'),
55 _('set/override config option (use \'section.name=value\')'),
56 _('CONFIG')),
56 _('CONFIG')),
57 ('', 'debug', None, _('enable debugging output')),
57 ('', 'debug', None, _('enable debugging output')),
58 ('', 'debugger', None, _('start debugger')),
58 ('', 'debugger', None, _('start debugger')),
59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
60 _('ENCODE')),
60 _('ENCODE')),
61 ('', 'encodingmode', encoding.encodingmode,
61 ('', 'encodingmode', encoding.encodingmode,
62 _('set the charset encoding mode'), _('MODE')),
62 _('set the charset encoding mode'), _('MODE')),
63 ('', 'traceback', None, _('always print a traceback on exception')),
63 ('', 'traceback', None, _('always print a traceback on exception')),
64 ('', 'time', None, _('time how long the command takes')),
64 ('', 'time', None, _('time how long the command takes')),
65 ('', 'profile', None, _('print command execution profile')),
65 ('', 'profile', None, _('print command execution profile')),
66 ('', 'version', None, _('output version information and exit')),
66 ('', 'version', None, _('output version information and exit')),
67 ('h', 'help', None, _('display help and exit')),
67 ('h', 'help', None, _('display help and exit')),
68 ('', 'hidden', False, _('consider hidden changesets')),
68 ('', 'hidden', False, _('consider hidden changesets')),
69 ]
69 ]
70
70
71 dryrunopts = [('n', 'dry-run', None,
71 dryrunopts = [('n', 'dry-run', None,
72 _('do not perform actions, just print output'))]
72 _('do not perform actions, just print output'))]
73
73
74 remoteopts = [
74 remoteopts = [
75 ('e', 'ssh', '',
75 ('e', 'ssh', '',
76 _('specify ssh command to use'), _('CMD')),
76 _('specify ssh command to use'), _('CMD')),
77 ('', 'remotecmd', '',
77 ('', 'remotecmd', '',
78 _('specify hg command to run on the remote side'), _('CMD')),
78 _('specify hg command to run on the remote side'), _('CMD')),
79 ('', 'insecure', None,
79 ('', 'insecure', None,
80 _('do not verify server certificate (ignoring web.cacerts config)')),
80 _('do not verify server certificate (ignoring web.cacerts config)')),
81 ]
81 ]
82
82
83 walkopts = [
83 walkopts = [
84 ('I', 'include', [],
84 ('I', 'include', [],
85 _('include names matching the given patterns'), _('PATTERN')),
85 _('include names matching the given patterns'), _('PATTERN')),
86 ('X', 'exclude', [],
86 ('X', 'exclude', [],
87 _('exclude names matching the given patterns'), _('PATTERN')),
87 _('exclude names matching the given patterns'), _('PATTERN')),
88 ]
88 ]
89
89
90 commitopts = [
90 commitopts = [
91 ('m', 'message', '',
91 ('m', 'message', '',
92 _('use text as commit message'), _('TEXT')),
92 _('use text as commit message'), _('TEXT')),
93 ('l', 'logfile', '',
93 ('l', 'logfile', '',
94 _('read commit message from file'), _('FILE')),
94 _('read commit message from file'), _('FILE')),
95 ]
95 ]
96
96
97 commitopts2 = [
97 commitopts2 = [
98 ('d', 'date', '',
98 ('d', 'date', '',
99 _('record the specified date as commit date'), _('DATE')),
99 _('record the specified date as commit date'), _('DATE')),
100 ('u', 'user', '',
100 ('u', 'user', '',
101 _('record the specified user as committer'), _('USER')),
101 _('record the specified user as committer'), _('USER')),
102 ]
102 ]
103
103
104 # hidden for now
104 # hidden for now
105 formatteropts = [
105 formatteropts = [
106 ('T', 'template', '',
106 ('T', 'template', '',
107 _('display with template (DEPRECATED)'), _('TEMPLATE')),
107 _('display with template (DEPRECATED)'), _('TEMPLATE')),
108 ]
108 ]
109
109
110 templateopts = [
110 templateopts = [
111 ('', 'style', '',
111 ('', 'style', '',
112 _('display using template map file (DEPRECATED)'), _('STYLE')),
112 _('display using template map file (DEPRECATED)'), _('STYLE')),
113 ('T', 'template', '',
113 ('T', 'template', '',
114 _('display with template'), _('TEMPLATE')),
114 _('display with template'), _('TEMPLATE')),
115 ]
115 ]
116
116
117 logopts = [
117 logopts = [
118 ('p', 'patch', None, _('show patch')),
118 ('p', 'patch', None, _('show patch')),
119 ('g', 'git', None, _('use git extended diff format')),
119 ('g', 'git', None, _('use git extended diff format')),
120 ('l', 'limit', '',
120 ('l', 'limit', '',
121 _('limit number of changes displayed'), _('NUM')),
121 _('limit number of changes displayed'), _('NUM')),
122 ('M', 'no-merges', None, _('do not show merges')),
122 ('M', 'no-merges', None, _('do not show merges')),
123 ('', 'stat', None, _('output diffstat-style summary of changes')),
123 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('G', 'graph', None, _("show the revision DAG")),
124 ('G', 'graph', None, _("show the revision DAG")),
125 ] + templateopts
125 ] + templateopts
126
126
127 diffopts = [
127 diffopts = [
128 ('a', 'text', None, _('treat all files as text')),
128 ('a', 'text', None, _('treat all files as text')),
129 ('g', 'git', None, _('use git extended diff format')),
129 ('g', 'git', None, _('use git extended diff format')),
130 ('', 'nodates', None, _('omit dates from diff headers'))
130 ('', 'nodates', None, _('omit dates from diff headers'))
131 ]
131 ]
132
132
133 diffwsopts = [
133 diffwsopts = [
134 ('w', 'ignore-all-space', None,
134 ('w', 'ignore-all-space', None,
135 _('ignore white space when comparing lines')),
135 _('ignore white space when comparing lines')),
136 ('b', 'ignore-space-change', None,
136 ('b', 'ignore-space-change', None,
137 _('ignore changes in the amount of white space')),
137 _('ignore changes in the amount of white space')),
138 ('B', 'ignore-blank-lines', None,
138 ('B', 'ignore-blank-lines', None,
139 _('ignore changes whose lines are all blank')),
139 _('ignore changes whose lines are all blank')),
140 ]
140 ]
141
141
142 diffopts2 = [
142 diffopts2 = [
143 ('p', 'show-function', None, _('show which function each change is in')),
143 ('p', 'show-function', None, _('show which function each change is in')),
144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
145 ] + diffwsopts + [
145 ] + diffwsopts + [
146 ('U', 'unified', '',
146 ('U', 'unified', '',
147 _('number of lines of context to show'), _('NUM')),
147 _('number of lines of context to show'), _('NUM')),
148 ('', 'stat', None, _('output diffstat-style summary of changes')),
148 ('', 'stat', None, _('output diffstat-style summary of changes')),
149 ]
149 ]
150
150
151 mergetoolopts = [
151 mergetoolopts = [
152 ('t', 'tool', '', _('specify merge tool')),
152 ('t', 'tool', '', _('specify merge tool')),
153 ]
153 ]
154
154
155 similarityopts = [
155 similarityopts = [
156 ('s', 'similarity', '',
156 ('s', 'similarity', '',
157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
158 ]
158 ]
159
159
160 subrepoopts = [
160 subrepoopts = [
161 ('S', 'subrepos', None,
161 ('S', 'subrepos', None,
162 _('recurse into subrepositories'))
162 _('recurse into subrepositories'))
163 ]
163 ]
164
164
165 # Commands start here, listed alphabetically
165 # Commands start here, listed alphabetically
166
166
167 @command('^add',
167 @command('^add',
168 walkopts + subrepoopts + dryrunopts,
168 walkopts + subrepoopts + dryrunopts,
169 _('[OPTION]... [FILE]...'),
169 _('[OPTION]... [FILE]...'),
170 inferrepo=True)
170 inferrepo=True)
171 def add(ui, repo, *pats, **opts):
171 def add(ui, repo, *pats, **opts):
172 """add the specified files on the next commit
172 """add the specified files on the next commit
173
173
174 Schedule files to be version controlled and added to the
174 Schedule files to be version controlled and added to the
175 repository.
175 repository.
176
176
177 The files will be added to the repository at the next commit. To
177 The files will be added to the repository at the next commit. To
178 undo an add before that, see :hg:`forget`.
178 undo an add before that, see :hg:`forget`.
179
179
180 If no names are given, add all files to the repository.
180 If no names are given, add all files to the repository.
181
181
182 .. container:: verbose
182 .. container:: verbose
183
183
184 An example showing how new (unknown) files are added
184 An example showing how new (unknown) files are added
185 automatically by :hg:`add`::
185 automatically by :hg:`add`::
186
186
187 $ ls
187 $ ls
188 foo.c
188 foo.c
189 $ hg status
189 $ hg status
190 ? foo.c
190 ? foo.c
191 $ hg add
191 $ hg add
192 adding foo.c
192 adding foo.c
193 $ hg status
193 $ hg status
194 A foo.c
194 A foo.c
195
195
196 Returns 0 if all files are successfully added.
196 Returns 0 if all files are successfully added.
197 """
197 """
198
198
199 m = scmutil.match(repo[None], pats, opts)
199 m = scmutil.match(repo[None], pats, opts)
200 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
200 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
201 opts.get('subrepos'), prefix="", explicitonly=False)
201 opts.get('subrepos'), prefix="", explicitonly=False)
202 return rejected and 1 or 0
202 return rejected and 1 or 0
203
203
204 @command('addremove',
204 @command('addremove',
205 similarityopts + walkopts + dryrunopts,
205 similarityopts + walkopts + dryrunopts,
206 _('[OPTION]... [FILE]...'),
206 _('[OPTION]... [FILE]...'),
207 inferrepo=True)
207 inferrepo=True)
208 def addremove(ui, repo, *pats, **opts):
208 def addremove(ui, repo, *pats, **opts):
209 """add all new files, delete all missing files
209 """add all new files, delete all missing files
210
210
211 Add all new files and remove all missing files from the
211 Add all new files and remove all missing files from the
212 repository.
212 repository.
213
213
214 New files are ignored if they match any of the patterns in
214 New files are ignored if they match any of the patterns in
215 ``.hgignore``. As with add, these changes take effect at the next
215 ``.hgignore``. As with add, these changes take effect at the next
216 commit.
216 commit.
217
217
218 Use the -s/--similarity option to detect renamed files. This
218 Use the -s/--similarity option to detect renamed files. This
219 option takes a percentage between 0 (disabled) and 100 (files must
219 option takes a percentage between 0 (disabled) and 100 (files must
220 be identical) as its parameter. With a parameter greater than 0,
220 be identical) as its parameter. With a parameter greater than 0,
221 this compares every removed file with every added file and records
221 this compares every removed file with every added file and records
222 those similar enough as renames. Detecting renamed files this way
222 those similar enough as renames. Detecting renamed files this way
223 can be expensive. After using this option, :hg:`status -C` can be
223 can be expensive. After using this option, :hg:`status -C` can be
224 used to check which files were identified as moved or renamed. If
224 used to check which files were identified as moved or renamed. If
225 not specified, -s/--similarity defaults to 100 and only renames of
225 not specified, -s/--similarity defaults to 100 and only renames of
226 identical files are detected.
226 identical files are detected.
227
227
228 Returns 0 if all files are successfully added.
228 Returns 0 if all files are successfully added.
229 """
229 """
230 try:
230 try:
231 sim = float(opts.get('similarity') or 100)
231 sim = float(opts.get('similarity') or 100)
232 except ValueError:
232 except ValueError:
233 raise util.Abort(_('similarity must be a number'))
233 raise util.Abort(_('similarity must be a number'))
234 if sim < 0 or sim > 100:
234 if sim < 0 or sim > 100:
235 raise util.Abort(_('similarity must be between 0 and 100'))
235 raise util.Abort(_('similarity must be between 0 and 100'))
236 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
236 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
237
237
238 @command('^annotate|blame',
238 @command('^annotate|blame',
239 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
239 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
240 ('', 'follow', None,
240 ('', 'follow', None,
241 _('follow copies/renames and list the filename (DEPRECATED)')),
241 _('follow copies/renames and list the filename (DEPRECATED)')),
242 ('', 'no-follow', None, _("don't follow copies and renames")),
242 ('', 'no-follow', None, _("don't follow copies and renames")),
243 ('a', 'text', None, _('treat all files as text')),
243 ('a', 'text', None, _('treat all files as text')),
244 ('u', 'user', None, _('list the author (long with -v)')),
244 ('u', 'user', None, _('list the author (long with -v)')),
245 ('f', 'file', None, _('list the filename')),
245 ('f', 'file', None, _('list the filename')),
246 ('d', 'date', None, _('list the date (short with -q)')),
246 ('d', 'date', None, _('list the date (short with -q)')),
247 ('n', 'number', None, _('list the revision number (default)')),
247 ('n', 'number', None, _('list the revision number (default)')),
248 ('c', 'changeset', None, _('list the changeset')),
248 ('c', 'changeset', None, _('list the changeset')),
249 ('l', 'line-number', None, _('show line number at the first appearance'))
249 ('l', 'line-number', None, _('show line number at the first appearance'))
250 ] + diffwsopts + walkopts + formatteropts,
250 ] + diffwsopts + walkopts + formatteropts,
251 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
251 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
252 inferrepo=True)
252 inferrepo=True)
253 def annotate(ui, repo, *pats, **opts):
253 def annotate(ui, repo, *pats, **opts):
254 """show changeset information by line for each file
254 """show changeset information by line for each file
255
255
256 List changes in files, showing the revision id responsible for
256 List changes in files, showing the revision id responsible for
257 each line
257 each line
258
258
259 This command is useful for discovering when a change was made and
259 This command is useful for discovering when a change was made and
260 by whom.
260 by whom.
261
261
262 Without the -a/--text option, annotate will avoid processing files
262 Without the -a/--text option, annotate will avoid processing files
263 it detects as binary. With -a, annotate will annotate the file
263 it detects as binary. With -a, annotate will annotate the file
264 anyway, although the results will probably be neither useful
264 anyway, although the results will probably be neither useful
265 nor desirable.
265 nor desirable.
266
266
267 Returns 0 on success.
267 Returns 0 on success.
268 """
268 """
269 if not pats:
269 if not pats:
270 raise util.Abort(_('at least one filename or pattern is required'))
270 raise util.Abort(_('at least one filename or pattern is required'))
271
271
272 if opts.get('follow'):
272 if opts.get('follow'):
273 # --follow is deprecated and now just an alias for -f/--file
273 # --follow is deprecated and now just an alias for -f/--file
274 # to mimic the behavior of Mercurial before version 1.5
274 # to mimic the behavior of Mercurial before version 1.5
275 opts['file'] = True
275 opts['file'] = True
276
276
277 fm = ui.formatter('annotate', opts)
277 fm = ui.formatter('annotate', opts)
278 datefunc = ui.quiet and util.shortdate or util.datestr
278 datefunc = ui.quiet and util.shortdate or util.datestr
279 hexfn = fm.hexfunc
279 hexfn = fm.hexfunc
280
280
281 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
281 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
282 ('number', ' ', lambda x: x[0].rev(), str),
282 ('number', ' ', lambda x: x[0].rev(), str),
283 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
283 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
284 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
284 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
285 ('file', ' ', lambda x: x[0].path(), str),
285 ('file', ' ', lambda x: x[0].path(), str),
286 ('line_number', ':', lambda x: x[1], str),
286 ('line_number', ':', lambda x: x[1], str),
287 ]
287 ]
288 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
288 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
289
289
290 if (not opts.get('user') and not opts.get('changeset')
290 if (not opts.get('user') and not opts.get('changeset')
291 and not opts.get('date') and not opts.get('file')):
291 and not opts.get('date') and not opts.get('file')):
292 opts['number'] = True
292 opts['number'] = True
293
293
294 linenumber = opts.get('line_number') is not None
294 linenumber = opts.get('line_number') is not None
295 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
295 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
296 raise util.Abort(_('at least one of -n/-c is required for -l'))
296 raise util.Abort(_('at least one of -n/-c is required for -l'))
297
297
298 if fm:
298 if fm:
299 def makefunc(get, fmt):
299 def makefunc(get, fmt):
300 return get
300 return get
301 else:
301 else:
302 def makefunc(get, fmt):
302 def makefunc(get, fmt):
303 return lambda x: fmt(get(x))
303 return lambda x: fmt(get(x))
304 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
304 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
305 if opts.get(op)]
305 if opts.get(op)]
306 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
306 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
307 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
307 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
308 if opts.get(op))
308 if opts.get(op))
309
309
310 def bad(x, y):
310 def bad(x, y):
311 raise util.Abort("%s: %s" % (x, y))
311 raise util.Abort("%s: %s" % (x, y))
312
312
313 ctx = scmutil.revsingle(repo, opts.get('rev'))
313 ctx = scmutil.revsingle(repo, opts.get('rev'))
314 m = scmutil.match(ctx, pats, opts)
314 m = scmutil.match(ctx, pats, opts)
315 m.bad = bad
315 m.bad = bad
316 follow = not opts.get('no_follow')
316 follow = not opts.get('no_follow')
317 diffopts = patch.diffopts(ui, opts, section='annotate')
317 diffopts = patch.diffopts(ui, opts, section='annotate')
318 for abs in ctx.walk(m):
318 for abs in ctx.walk(m):
319 fctx = ctx[abs]
319 fctx = ctx[abs]
320 if not opts.get('text') and util.binary(fctx.data()):
320 if not opts.get('text') and util.binary(fctx.data()):
321 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
321 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
322 continue
322 continue
323
323
324 lines = fctx.annotate(follow=follow, linenumber=linenumber,
324 lines = fctx.annotate(follow=follow, linenumber=linenumber,
325 diffopts=diffopts)
325 diffopts=diffopts)
326 formats = []
326 formats = []
327 pieces = []
327 pieces = []
328
328
329 for f, sep in funcmap:
329 for f, sep in funcmap:
330 l = [f(n) for n, dummy in lines]
330 l = [f(n) for n, dummy in lines]
331 if l:
331 if l:
332 if fm:
332 if fm:
333 formats.append(['%s' for x in l])
333 formats.append(['%s' for x in l])
334 else:
334 else:
335 sizes = [encoding.colwidth(x) for x in l]
335 sizes = [encoding.colwidth(x) for x in l]
336 ml = max(sizes)
336 ml = max(sizes)
337 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
337 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
338 pieces.append(l)
338 pieces.append(l)
339
339
340 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
340 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
341 fm.startitem()
341 fm.startitem()
342 fm.write(fields, "".join(f), *p)
342 fm.write(fields, "".join(f), *p)
343 fm.write('line', ": %s", l[1])
343 fm.write('line', ": %s", l[1])
344
344
345 if lines and not lines[-1][1].endswith('\n'):
345 if lines and not lines[-1][1].endswith('\n'):
346 fm.plain('\n')
346 fm.plain('\n')
347
347
348 fm.end()
348 fm.end()
349
349
350 @command('archive',
350 @command('archive',
351 [('', 'no-decode', None, _('do not pass files through decoders')),
351 [('', 'no-decode', None, _('do not pass files through decoders')),
352 ('p', 'prefix', '', _('directory prefix for files in archive'),
352 ('p', 'prefix', '', _('directory prefix for files in archive'),
353 _('PREFIX')),
353 _('PREFIX')),
354 ('r', 'rev', '', _('revision to distribute'), _('REV')),
354 ('r', 'rev', '', _('revision to distribute'), _('REV')),
355 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
355 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
356 ] + subrepoopts + walkopts,
356 ] + subrepoopts + walkopts,
357 _('[OPTION]... DEST'))
357 _('[OPTION]... DEST'))
358 def archive(ui, repo, dest, **opts):
358 def archive(ui, repo, dest, **opts):
359 '''create an unversioned archive of a repository revision
359 '''create an unversioned archive of a repository revision
360
360
361 By default, the revision used is the parent of the working
361 By default, the revision used is the parent of the working
362 directory; use -r/--rev to specify a different revision.
362 directory; use -r/--rev to specify a different revision.
363
363
364 The archive type is automatically detected based on file
364 The archive type is automatically detected based on file
365 extension (or override using -t/--type).
365 extension (or override using -t/--type).
366
366
367 .. container:: verbose
367 .. container:: verbose
368
368
369 Examples:
369 Examples:
370
370
371 - create a zip file containing the 1.0 release::
371 - create a zip file containing the 1.0 release::
372
372
373 hg archive -r 1.0 project-1.0.zip
373 hg archive -r 1.0 project-1.0.zip
374
374
375 - create a tarball excluding .hg files::
375 - create a tarball excluding .hg files::
376
376
377 hg archive project.tar.gz -X ".hg*"
377 hg archive project.tar.gz -X ".hg*"
378
378
379 Valid types are:
379 Valid types are:
380
380
381 :``files``: a directory full of files (default)
381 :``files``: a directory full of files (default)
382 :``tar``: tar archive, uncompressed
382 :``tar``: tar archive, uncompressed
383 :``tbz2``: tar archive, compressed using bzip2
383 :``tbz2``: tar archive, compressed using bzip2
384 :``tgz``: tar archive, compressed using gzip
384 :``tgz``: tar archive, compressed using gzip
385 :``uzip``: zip archive, uncompressed
385 :``uzip``: zip archive, uncompressed
386 :``zip``: zip archive, compressed using deflate
386 :``zip``: zip archive, compressed using deflate
387
387
388 The exact name of the destination archive or directory is given
388 The exact name of the destination archive or directory is given
389 using a format string; see :hg:`help export` for details.
389 using a format string; see :hg:`help export` for details.
390
390
391 Each member added to an archive file has a directory prefix
391 Each member added to an archive file has a directory prefix
392 prepended. Use -p/--prefix to specify a format string for the
392 prepended. Use -p/--prefix to specify a format string for the
393 prefix. The default is the basename of the archive, with suffixes
393 prefix. The default is the basename of the archive, with suffixes
394 removed.
394 removed.
395
395
396 Returns 0 on success.
396 Returns 0 on success.
397 '''
397 '''
398
398
399 ctx = scmutil.revsingle(repo, opts.get('rev'))
399 ctx = scmutil.revsingle(repo, opts.get('rev'))
400 if not ctx:
400 if not ctx:
401 raise util.Abort(_('no working directory: please specify a revision'))
401 raise util.Abort(_('no working directory: please specify a revision'))
402 node = ctx.node()
402 node = ctx.node()
403 dest = cmdutil.makefilename(repo, dest, node)
403 dest = cmdutil.makefilename(repo, dest, node)
404 if os.path.realpath(dest) == repo.root:
404 if os.path.realpath(dest) == repo.root:
405 raise util.Abort(_('repository root cannot be destination'))
405 raise util.Abort(_('repository root cannot be destination'))
406
406
407 kind = opts.get('type') or archival.guesskind(dest) or 'files'
407 kind = opts.get('type') or archival.guesskind(dest) or 'files'
408 prefix = opts.get('prefix')
408 prefix = opts.get('prefix')
409
409
410 if dest == '-':
410 if dest == '-':
411 if kind == 'files':
411 if kind == 'files':
412 raise util.Abort(_('cannot archive plain files to stdout'))
412 raise util.Abort(_('cannot archive plain files to stdout'))
413 dest = cmdutil.makefileobj(repo, dest)
413 dest = cmdutil.makefileobj(repo, dest)
414 if not prefix:
414 if not prefix:
415 prefix = os.path.basename(repo.root) + '-%h'
415 prefix = os.path.basename(repo.root) + '-%h'
416
416
417 prefix = cmdutil.makefilename(repo, prefix, node)
417 prefix = cmdutil.makefilename(repo, prefix, node)
418 matchfn = scmutil.match(ctx, [], opts)
418 matchfn = scmutil.match(ctx, [], opts)
419 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
419 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
420 matchfn, prefix, subrepos=opts.get('subrepos'))
420 matchfn, prefix, subrepos=opts.get('subrepos'))
421
421
422 @command('backout',
422 @command('backout',
423 [('', 'merge', None, _('merge with old dirstate parent after backout')),
423 [('', 'merge', None, _('merge with old dirstate parent after backout')),
424 ('', 'parent', '',
424 ('', 'parent', '',
425 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
425 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
426 ('r', 'rev', '', _('revision to backout'), _('REV')),
426 ('r', 'rev', '', _('revision to backout'), _('REV')),
427 ('e', 'edit', False, _('invoke editor on commit messages')),
427 ('e', 'edit', False, _('invoke editor on commit messages')),
428 ] + mergetoolopts + walkopts + commitopts + commitopts2,
428 ] + mergetoolopts + walkopts + commitopts + commitopts2,
429 _('[OPTION]... [-r] REV'))
429 _('[OPTION]... [-r] REV'))
430 def backout(ui, repo, node=None, rev=None, **opts):
430 def backout(ui, repo, node=None, rev=None, **opts):
431 '''reverse effect of earlier changeset
431 '''reverse effect of earlier changeset
432
432
433 Prepare a new changeset with the effect of REV undone in the
433 Prepare a new changeset with the effect of REV undone in the
434 current working directory.
434 current working directory.
435
435
436 If REV is the parent of the working directory, then this new changeset
436 If REV is the parent of the working directory, then this new changeset
437 is committed automatically. Otherwise, hg needs to merge the
437 is committed automatically. Otherwise, hg needs to merge the
438 changes and the merged result is left uncommitted.
438 changes and the merged result is left uncommitted.
439
439
440 .. note::
440 .. note::
441
441
442 backout cannot be used to fix either an unwanted or
442 backout cannot be used to fix either an unwanted or
443 incorrect merge.
443 incorrect merge.
444
444
445 .. container:: verbose
445 .. container:: verbose
446
446
447 By default, the pending changeset will have one parent,
447 By default, the pending changeset will have one parent,
448 maintaining a linear history. With --merge, the pending
448 maintaining a linear history. With --merge, the pending
449 changeset will instead have two parents: the old parent of the
449 changeset will instead have two parents: the old parent of the
450 working directory and a new child of REV that simply undoes REV.
450 working directory and a new child of REV that simply undoes REV.
451
451
452 Before version 1.7, the behavior without --merge was equivalent
452 Before version 1.7, the behavior without --merge was equivalent
453 to specifying --merge followed by :hg:`update --clean .` to
453 to specifying --merge followed by :hg:`update --clean .` to
454 cancel the merge and leave the child of REV as a head to be
454 cancel the merge and leave the child of REV as a head to be
455 merged separately.
455 merged separately.
456
456
457 See :hg:`help dates` for a list of formats valid for -d/--date.
457 See :hg:`help dates` for a list of formats valid for -d/--date.
458
458
459 Returns 0 on success, 1 if nothing to backout or there are unresolved
459 Returns 0 on success, 1 if nothing to backout or there are unresolved
460 files.
460 files.
461 '''
461 '''
462 if rev and node:
462 if rev and node:
463 raise util.Abort(_("please specify just one revision"))
463 raise util.Abort(_("please specify just one revision"))
464
464
465 if not rev:
465 if not rev:
466 rev = node
466 rev = node
467
467
468 if not rev:
468 if not rev:
469 raise util.Abort(_("please specify a revision to backout"))
469 raise util.Abort(_("please specify a revision to backout"))
470
470
471 date = opts.get('date')
471 date = opts.get('date')
472 if date:
472 if date:
473 opts['date'] = util.parsedate(date)
473 opts['date'] = util.parsedate(date)
474
474
475 cmdutil.checkunfinished(repo)
475 cmdutil.checkunfinished(repo)
476 cmdutil.bailifchanged(repo)
476 cmdutil.bailifchanged(repo)
477 node = scmutil.revsingle(repo, rev).node()
477 node = scmutil.revsingle(repo, rev).node()
478
478
479 op1, op2 = repo.dirstate.parents()
479 op1, op2 = repo.dirstate.parents()
480 if not repo.changelog.isancestor(node, op1):
480 if not repo.changelog.isancestor(node, op1):
481 raise util.Abort(_('cannot backout change that is not an ancestor'))
481 raise util.Abort(_('cannot backout change that is not an ancestor'))
482
482
483 p1, p2 = repo.changelog.parents(node)
483 p1, p2 = repo.changelog.parents(node)
484 if p1 == nullid:
484 if p1 == nullid:
485 raise util.Abort(_('cannot backout a change with no parents'))
485 raise util.Abort(_('cannot backout a change with no parents'))
486 if p2 != nullid:
486 if p2 != nullid:
487 if not opts.get('parent'):
487 if not opts.get('parent'):
488 raise util.Abort(_('cannot backout a merge changeset'))
488 raise util.Abort(_('cannot backout a merge changeset'))
489 p = repo.lookup(opts['parent'])
489 p = repo.lookup(opts['parent'])
490 if p not in (p1, p2):
490 if p not in (p1, p2):
491 raise util.Abort(_('%s is not a parent of %s') %
491 raise util.Abort(_('%s is not a parent of %s') %
492 (short(p), short(node)))
492 (short(p), short(node)))
493 parent = p
493 parent = p
494 else:
494 else:
495 if opts.get('parent'):
495 if opts.get('parent'):
496 raise util.Abort(_('cannot use --parent on non-merge changeset'))
496 raise util.Abort(_('cannot use --parent on non-merge changeset'))
497 parent = p1
497 parent = p1
498
498
499 # the backout should appear on the same branch
499 # the backout should appear on the same branch
500 wlock = repo.wlock()
500 wlock = repo.wlock()
501 try:
501 try:
502 branch = repo.dirstate.branch()
502 branch = repo.dirstate.branch()
503 bheads = repo.branchheads(branch)
503 bheads = repo.branchheads(branch)
504 rctx = scmutil.revsingle(repo, hex(parent))
504 rctx = scmutil.revsingle(repo, hex(parent))
505 if not opts.get('merge') and op1 != node:
505 if not opts.get('merge') and op1 != node:
506 try:
506 try:
507 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
507 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
508 'backout')
508 'backout')
509 repo.dirstate.beginparentchange()
509 repo.dirstate.beginparentchange()
510 stats = mergemod.update(repo, parent, True, True, False,
510 stats = mergemod.update(repo, parent, True, True, False,
511 node, False)
511 node, False)
512 repo.setparents(op1, op2)
512 repo.setparents(op1, op2)
513 repo.dirstate.endparentchange()
513 repo.dirstate.endparentchange()
514 hg._showstats(repo, stats)
514 hg._showstats(repo, stats)
515 if stats[3]:
515 if stats[3]:
516 repo.ui.status(_("use 'hg resolve' to retry unresolved "
516 repo.ui.status(_("use 'hg resolve' to retry unresolved "
517 "file merges\n"))
517 "file merges\n"))
518 else:
518 else:
519 msg = _("changeset %s backed out, "
519 msg = _("changeset %s backed out, "
520 "don't forget to commit.\n")
520 "don't forget to commit.\n")
521 ui.status(msg % short(node))
521 ui.status(msg % short(node))
522 return stats[3] > 0
522 return stats[3] > 0
523 finally:
523 finally:
524 ui.setconfig('ui', 'forcemerge', '', '')
524 ui.setconfig('ui', 'forcemerge', '', '')
525 else:
525 else:
526 hg.clean(repo, node, show_stats=False)
526 hg.clean(repo, node, show_stats=False)
527 repo.dirstate.setbranch(branch)
527 repo.dirstate.setbranch(branch)
528 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
528 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
529
529
530
530
531 def commitfunc(ui, repo, message, match, opts):
531 def commitfunc(ui, repo, message, match, opts):
532 editform = 'backout'
532 editform = 'backout'
533 e = cmdutil.getcommiteditor(editform=editform, **opts)
533 e = cmdutil.getcommiteditor(editform=editform, **opts)
534 if not message:
534 if not message:
535 # we don't translate commit messages
535 # we don't translate commit messages
536 message = "Backed out changeset %s" % short(node)
536 message = "Backed out changeset %s" % short(node)
537 e = cmdutil.getcommiteditor(edit=True, editform=editform)
537 e = cmdutil.getcommiteditor(edit=True, editform=editform)
538 return repo.commit(message, opts.get('user'), opts.get('date'),
538 return repo.commit(message, opts.get('user'), opts.get('date'),
539 match, editor=e)
539 match, editor=e)
540 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
540 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
541 if not newnode:
541 if not newnode:
542 ui.status(_("nothing changed\n"))
542 ui.status(_("nothing changed\n"))
543 return 1
543 return 1
544 cmdutil.commitstatus(repo, newnode, branch, bheads)
544 cmdutil.commitstatus(repo, newnode, branch, bheads)
545
545
546 def nice(node):
546 def nice(node):
547 return '%d:%s' % (repo.changelog.rev(node), short(node))
547 return '%d:%s' % (repo.changelog.rev(node), short(node))
548 ui.status(_('changeset %s backs out changeset %s\n') %
548 ui.status(_('changeset %s backs out changeset %s\n') %
549 (nice(repo.changelog.tip()), nice(node)))
549 (nice(repo.changelog.tip()), nice(node)))
550 if opts.get('merge') and op1 != node:
550 if opts.get('merge') and op1 != node:
551 hg.clean(repo, op1, show_stats=False)
551 hg.clean(repo, op1, show_stats=False)
552 ui.status(_('merging with changeset %s\n')
552 ui.status(_('merging with changeset %s\n')
553 % nice(repo.changelog.tip()))
553 % nice(repo.changelog.tip()))
554 try:
554 try:
555 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
555 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
556 'backout')
556 'backout')
557 return hg.merge(repo, hex(repo.changelog.tip()))
557 return hg.merge(repo, hex(repo.changelog.tip()))
558 finally:
558 finally:
559 ui.setconfig('ui', 'forcemerge', '', '')
559 ui.setconfig('ui', 'forcemerge', '', '')
560 finally:
560 finally:
561 wlock.release()
561 wlock.release()
562 return 0
562 return 0
563
563
564 @command('bisect',
564 @command('bisect',
565 [('r', 'reset', False, _('reset bisect state')),
565 [('r', 'reset', False, _('reset bisect state')),
566 ('g', 'good', False, _('mark changeset good')),
566 ('g', 'good', False, _('mark changeset good')),
567 ('b', 'bad', False, _('mark changeset bad')),
567 ('b', 'bad', False, _('mark changeset bad')),
568 ('s', 'skip', False, _('skip testing changeset')),
568 ('s', 'skip', False, _('skip testing changeset')),
569 ('e', 'extend', False, _('extend the bisect range')),
569 ('e', 'extend', False, _('extend the bisect range')),
570 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
570 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
571 ('U', 'noupdate', False, _('do not update to target'))],
571 ('U', 'noupdate', False, _('do not update to target'))],
572 _("[-gbsr] [-U] [-c CMD] [REV]"))
572 _("[-gbsr] [-U] [-c CMD] [REV]"))
573 def bisect(ui, repo, rev=None, extra=None, command=None,
573 def bisect(ui, repo, rev=None, extra=None, command=None,
574 reset=None, good=None, bad=None, skip=None, extend=None,
574 reset=None, good=None, bad=None, skip=None, extend=None,
575 noupdate=None):
575 noupdate=None):
576 """subdivision search of changesets
576 """subdivision search of changesets
577
577
578 This command helps to find changesets which introduce problems. To
578 This command helps to find changesets which introduce problems. To
579 use, mark the earliest changeset you know exhibits the problem as
579 use, mark the earliest changeset you know exhibits the problem as
580 bad, then mark the latest changeset which is free from the problem
580 bad, then mark the latest changeset which is free from the problem
581 as good. Bisect will update your working directory to a revision
581 as good. Bisect will update your working directory to a revision
582 for testing (unless the -U/--noupdate option is specified). Once
582 for testing (unless the -U/--noupdate option is specified). Once
583 you have performed tests, mark the working directory as good or
583 you have performed tests, mark the working directory as good or
584 bad, and bisect will either update to another candidate changeset
584 bad, and bisect will either update to another candidate changeset
585 or announce that it has found the bad revision.
585 or announce that it has found the bad revision.
586
586
587 As a shortcut, you can also use the revision argument to mark a
587 As a shortcut, you can also use the revision argument to mark a
588 revision as good or bad without checking it out first.
588 revision as good or bad without checking it out first.
589
589
590 If you supply a command, it will be used for automatic bisection.
590 If you supply a command, it will be used for automatic bisection.
591 The environment variable HG_NODE will contain the ID of the
591 The environment variable HG_NODE will contain the ID of the
592 changeset being tested. The exit status of the command will be
592 changeset being tested. The exit status of the command will be
593 used to mark revisions as good or bad: status 0 means good, 125
593 used to mark revisions as good or bad: status 0 means good, 125
594 means to skip the revision, 127 (command not found) will abort the
594 means to skip the revision, 127 (command not found) will abort the
595 bisection, and any other non-zero exit status means the revision
595 bisection, and any other non-zero exit status means the revision
596 is bad.
596 is bad.
597
597
598 .. container:: verbose
598 .. container:: verbose
599
599
600 Some examples:
600 Some examples:
601
601
602 - start a bisection with known bad revision 34, and good revision 12::
602 - start a bisection with known bad revision 34, and good revision 12::
603
603
604 hg bisect --bad 34
604 hg bisect --bad 34
605 hg bisect --good 12
605 hg bisect --good 12
606
606
607 - advance the current bisection by marking current revision as good or
607 - advance the current bisection by marking current revision as good or
608 bad::
608 bad::
609
609
610 hg bisect --good
610 hg bisect --good
611 hg bisect --bad
611 hg bisect --bad
612
612
613 - mark the current revision, or a known revision, to be skipped (e.g. if
613 - mark the current revision, or a known revision, to be skipped (e.g. if
614 that revision is not usable because of another issue)::
614 that revision is not usable because of another issue)::
615
615
616 hg bisect --skip
616 hg bisect --skip
617 hg bisect --skip 23
617 hg bisect --skip 23
618
618
619 - skip all revisions that do not touch directories ``foo`` or ``bar``::
619 - skip all revisions that do not touch directories ``foo`` or ``bar``::
620
620
621 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
621 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
622
622
623 - forget the current bisection::
623 - forget the current bisection::
624
624
625 hg bisect --reset
625 hg bisect --reset
626
626
627 - use 'make && make tests' to automatically find the first broken
627 - use 'make && make tests' to automatically find the first broken
628 revision::
628 revision::
629
629
630 hg bisect --reset
630 hg bisect --reset
631 hg bisect --bad 34
631 hg bisect --bad 34
632 hg bisect --good 12
632 hg bisect --good 12
633 hg bisect --command "make && make tests"
633 hg bisect --command "make && make tests"
634
634
635 - see all changesets whose states are already known in the current
635 - see all changesets whose states are already known in the current
636 bisection::
636 bisection::
637
637
638 hg log -r "bisect(pruned)"
638 hg log -r "bisect(pruned)"
639
639
640 - see the changeset currently being bisected (especially useful
640 - see the changeset currently being bisected (especially useful
641 if running with -U/--noupdate)::
641 if running with -U/--noupdate)::
642
642
643 hg log -r "bisect(current)"
643 hg log -r "bisect(current)"
644
644
645 - see all changesets that took part in the current bisection::
645 - see all changesets that took part in the current bisection::
646
646
647 hg log -r "bisect(range)"
647 hg log -r "bisect(range)"
648
648
649 - you can even get a nice graph::
649 - you can even get a nice graph::
650
650
651 hg log --graph -r "bisect(range)"
651 hg log --graph -r "bisect(range)"
652
652
653 See :hg:`help revsets` for more about the `bisect()` keyword.
653 See :hg:`help revsets` for more about the `bisect()` keyword.
654
654
655 Returns 0 on success.
655 Returns 0 on success.
656 """
656 """
657 def extendbisectrange(nodes, good):
657 def extendbisectrange(nodes, good):
658 # bisect is incomplete when it ends on a merge node and
658 # bisect is incomplete when it ends on a merge node and
659 # one of the parent was not checked.
659 # one of the parent was not checked.
660 parents = repo[nodes[0]].parents()
660 parents = repo[nodes[0]].parents()
661 if len(parents) > 1:
661 if len(parents) > 1:
662 side = good and state['bad'] or state['good']
662 side = good and state['bad'] or state['good']
663 num = len(set(i.node() for i in parents) & set(side))
663 num = len(set(i.node() for i in parents) & set(side))
664 if num == 1:
664 if num == 1:
665 return parents[0].ancestor(parents[1])
665 return parents[0].ancestor(parents[1])
666 return None
666 return None
667
667
668 def print_result(nodes, good):
668 def print_result(nodes, good):
669 displayer = cmdutil.show_changeset(ui, repo, {})
669 displayer = cmdutil.show_changeset(ui, repo, {})
670 if len(nodes) == 1:
670 if len(nodes) == 1:
671 # narrowed it down to a single revision
671 # narrowed it down to a single revision
672 if good:
672 if good:
673 ui.write(_("The first good revision is:\n"))
673 ui.write(_("The first good revision is:\n"))
674 else:
674 else:
675 ui.write(_("The first bad revision is:\n"))
675 ui.write(_("The first bad revision is:\n"))
676 displayer.show(repo[nodes[0]])
676 displayer.show(repo[nodes[0]])
677 extendnode = extendbisectrange(nodes, good)
677 extendnode = extendbisectrange(nodes, good)
678 if extendnode is not None:
678 if extendnode is not None:
679 ui.write(_('Not all ancestors of this changeset have been'
679 ui.write(_('Not all ancestors of this changeset have been'
680 ' checked.\nUse bisect --extend to continue the '
680 ' checked.\nUse bisect --extend to continue the '
681 'bisection from\nthe common ancestor, %s.\n')
681 'bisection from\nthe common ancestor, %s.\n')
682 % extendnode)
682 % extendnode)
683 else:
683 else:
684 # multiple possible revisions
684 # multiple possible revisions
685 if good:
685 if good:
686 ui.write(_("Due to skipped revisions, the first "
686 ui.write(_("Due to skipped revisions, the first "
687 "good revision could be any of:\n"))
687 "good revision could be any of:\n"))
688 else:
688 else:
689 ui.write(_("Due to skipped revisions, the first "
689 ui.write(_("Due to skipped revisions, the first "
690 "bad revision could be any of:\n"))
690 "bad revision could be any of:\n"))
691 for n in nodes:
691 for n in nodes:
692 displayer.show(repo[n])
692 displayer.show(repo[n])
693 displayer.close()
693 displayer.close()
694
694
695 def check_state(state, interactive=True):
695 def check_state(state, interactive=True):
696 if not state['good'] or not state['bad']:
696 if not state['good'] or not state['bad']:
697 if (good or bad or skip or reset) and interactive:
697 if (good or bad or skip or reset) and interactive:
698 return
698 return
699 if not state['good']:
699 if not state['good']:
700 raise util.Abort(_('cannot bisect (no known good revisions)'))
700 raise util.Abort(_('cannot bisect (no known good revisions)'))
701 else:
701 else:
702 raise util.Abort(_('cannot bisect (no known bad revisions)'))
702 raise util.Abort(_('cannot bisect (no known bad revisions)'))
703 return True
703 return True
704
704
705 # backward compatibility
705 # backward compatibility
706 if rev in "good bad reset init".split():
706 if rev in "good bad reset init".split():
707 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
707 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
708 cmd, rev, extra = rev, extra, None
708 cmd, rev, extra = rev, extra, None
709 if cmd == "good":
709 if cmd == "good":
710 good = True
710 good = True
711 elif cmd == "bad":
711 elif cmd == "bad":
712 bad = True
712 bad = True
713 else:
713 else:
714 reset = True
714 reset = True
715 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
715 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
716 raise util.Abort(_('incompatible arguments'))
716 raise util.Abort(_('incompatible arguments'))
717
717
718 cmdutil.checkunfinished(repo)
718 cmdutil.checkunfinished(repo)
719
719
720 if reset:
720 if reset:
721 p = repo.join("bisect.state")
721 p = repo.join("bisect.state")
722 if os.path.exists(p):
722 if os.path.exists(p):
723 os.unlink(p)
723 os.unlink(p)
724 return
724 return
725
725
726 state = hbisect.load_state(repo)
726 state = hbisect.load_state(repo)
727
727
728 if command:
728 if command:
729 changesets = 1
729 changesets = 1
730 if noupdate:
730 if noupdate:
731 try:
731 try:
732 node = state['current'][0]
732 node = state['current'][0]
733 except LookupError:
733 except LookupError:
734 raise util.Abort(_('current bisect revision is unknown - '
734 raise util.Abort(_('current bisect revision is unknown - '
735 'start a new bisect to fix'))
735 'start a new bisect to fix'))
736 else:
736 else:
737 node, p2 = repo.dirstate.parents()
737 node, p2 = repo.dirstate.parents()
738 if p2 != nullid:
738 if p2 != nullid:
739 raise util.Abort(_('current bisect revision is a merge'))
739 raise util.Abort(_('current bisect revision is a merge'))
740 try:
740 try:
741 while changesets:
741 while changesets:
742 # update state
742 # update state
743 state['current'] = [node]
743 state['current'] = [node]
744 hbisect.save_state(repo, state)
744 hbisect.save_state(repo, state)
745 status = util.system(command,
745 status = util.system(command,
746 environ={'HG_NODE': hex(node)},
746 environ={'HG_NODE': hex(node)},
747 out=ui.fout)
747 out=ui.fout)
748 if status == 125:
748 if status == 125:
749 transition = "skip"
749 transition = "skip"
750 elif status == 0:
750 elif status == 0:
751 transition = "good"
751 transition = "good"
752 # status < 0 means process was killed
752 # status < 0 means process was killed
753 elif status == 127:
753 elif status == 127:
754 raise util.Abort(_("failed to execute %s") % command)
754 raise util.Abort(_("failed to execute %s") % command)
755 elif status < 0:
755 elif status < 0:
756 raise util.Abort(_("%s killed") % command)
756 raise util.Abort(_("%s killed") % command)
757 else:
757 else:
758 transition = "bad"
758 transition = "bad"
759 ctx = scmutil.revsingle(repo, rev, node)
759 ctx = scmutil.revsingle(repo, rev, node)
760 rev = None # clear for future iterations
760 rev = None # clear for future iterations
761 state[transition].append(ctx.node())
761 state[transition].append(ctx.node())
762 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
762 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
763 check_state(state, interactive=False)
763 check_state(state, interactive=False)
764 # bisect
764 # bisect
765 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
765 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
766 # update to next check
766 # update to next check
767 node = nodes[0]
767 node = nodes[0]
768 if not noupdate:
768 if not noupdate:
769 cmdutil.bailifchanged(repo)
769 cmdutil.bailifchanged(repo)
770 hg.clean(repo, node, show_stats=False)
770 hg.clean(repo, node, show_stats=False)
771 finally:
771 finally:
772 state['current'] = [node]
772 state['current'] = [node]
773 hbisect.save_state(repo, state)
773 hbisect.save_state(repo, state)
774 print_result(nodes, bgood)
774 print_result(nodes, bgood)
775 return
775 return
776
776
777 # update state
777 # update state
778
778
779 if rev:
779 if rev:
780 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
780 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
781 else:
781 else:
782 nodes = [repo.lookup('.')]
782 nodes = [repo.lookup('.')]
783
783
784 if good or bad or skip:
784 if good or bad or skip:
785 if good:
785 if good:
786 state['good'] += nodes
786 state['good'] += nodes
787 elif bad:
787 elif bad:
788 state['bad'] += nodes
788 state['bad'] += nodes
789 elif skip:
789 elif skip:
790 state['skip'] += nodes
790 state['skip'] += nodes
791 hbisect.save_state(repo, state)
791 hbisect.save_state(repo, state)
792
792
793 if not check_state(state):
793 if not check_state(state):
794 return
794 return
795
795
796 # actually bisect
796 # actually bisect
797 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
797 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
798 if extend:
798 if extend:
799 if not changesets:
799 if not changesets:
800 extendnode = extendbisectrange(nodes, good)
800 extendnode = extendbisectrange(nodes, good)
801 if extendnode is not None:
801 if extendnode is not None:
802 ui.write(_("Extending search to changeset %d:%s\n")
802 ui.write(_("Extending search to changeset %d:%s\n")
803 % (extendnode.rev(), extendnode))
803 % (extendnode.rev(), extendnode))
804 state['current'] = [extendnode.node()]
804 state['current'] = [extendnode.node()]
805 hbisect.save_state(repo, state)
805 hbisect.save_state(repo, state)
806 if noupdate:
806 if noupdate:
807 return
807 return
808 cmdutil.bailifchanged(repo)
808 cmdutil.bailifchanged(repo)
809 return hg.clean(repo, extendnode.node())
809 return hg.clean(repo, extendnode.node())
810 raise util.Abort(_("nothing to extend"))
810 raise util.Abort(_("nothing to extend"))
811
811
812 if changesets == 0:
812 if changesets == 0:
813 print_result(nodes, good)
813 print_result(nodes, good)
814 else:
814 else:
815 assert len(nodes) == 1 # only a single node can be tested next
815 assert len(nodes) == 1 # only a single node can be tested next
816 node = nodes[0]
816 node = nodes[0]
817 # compute the approximate number of remaining tests
817 # compute the approximate number of remaining tests
818 tests, size = 0, 2
818 tests, size = 0, 2
819 while size <= changesets:
819 while size <= changesets:
820 tests, size = tests + 1, size * 2
820 tests, size = tests + 1, size * 2
821 rev = repo.changelog.rev(node)
821 rev = repo.changelog.rev(node)
822 ui.write(_("Testing changeset %d:%s "
822 ui.write(_("Testing changeset %d:%s "
823 "(%d changesets remaining, ~%d tests)\n")
823 "(%d changesets remaining, ~%d tests)\n")
824 % (rev, short(node), changesets, tests))
824 % (rev, short(node), changesets, tests))
825 state['current'] = [node]
825 state['current'] = [node]
826 hbisect.save_state(repo, state)
826 hbisect.save_state(repo, state)
827 if not noupdate:
827 if not noupdate:
828 cmdutil.bailifchanged(repo)
828 cmdutil.bailifchanged(repo)
829 return hg.clean(repo, node)
829 return hg.clean(repo, node)
830
830
831 @command('bookmarks|bookmark',
831 @command('bookmarks|bookmark',
832 [('f', 'force', False, _('force')),
832 [('f', 'force', False, _('force')),
833 ('r', 'rev', '', _('revision'), _('REV')),
833 ('r', 'rev', '', _('revision'), _('REV')),
834 ('d', 'delete', False, _('delete a given bookmark')),
834 ('d', 'delete', False, _('delete a given bookmark')),
835 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
835 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
836 ('i', 'inactive', False, _('mark a bookmark inactive'))],
836 ('i', 'inactive', False, _('mark a bookmark inactive'))],
837 _('hg bookmarks [OPTIONS]... [NAME]...'))
837 _('hg bookmarks [OPTIONS]... [NAME]...'))
838 def bookmark(ui, repo, *names, **opts):
838 def bookmark(ui, repo, *names, **opts):
839 '''create a new bookmark or list existing bookmarks
839 '''create a new bookmark or list existing bookmarks
840
840
841 Bookmarks are labels on changesets to help track lines of development.
841 Bookmarks are labels on changesets to help track lines of development.
842 Bookmarks are unversioned and can be moved, renamed and deleted.
842 Bookmarks are unversioned and can be moved, renamed and deleted.
843 Deleting or moving a bookmark has no effect on the associated changesets.
843 Deleting or moving a bookmark has no effect on the associated changesets.
844
844
845 Creating or updating to a bookmark causes it to be marked as 'active'.
845 Creating or updating to a bookmark causes it to be marked as 'active'.
846 The active bookmark is indicated with a '*'.
846 The active bookmark is indicated with a '*'.
847 When a commit is made, the active bookmark will advance to the new commit.
847 When a commit is made, the active bookmark will advance to the new commit.
848 A plain :hg:`update` will also advance an active bookmark, if possible.
848 A plain :hg:`update` will also advance an active bookmark, if possible.
849 Updating away from a bookmark will cause it to be deactivated.
849 Updating away from a bookmark will cause it to be deactivated.
850
850
851 Bookmarks can be pushed and pulled between repositories (see
851 Bookmarks can be pushed and pulled between repositories (see
852 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
852 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
853 diverged, a new 'divergent bookmark' of the form 'name@path' will
853 diverged, a new 'divergent bookmark' of the form 'name@path' will
854 be created. Using :hg:'merge' will resolve the divergence.
854 be created. Using :hg:'merge' will resolve the divergence.
855
855
856 A bookmark named '@' has the special property that :hg:`clone` will
856 A bookmark named '@' has the special property that :hg:`clone` will
857 check it out by default if it exists.
857 check it out by default if it exists.
858
858
859 .. container:: verbose
859 .. container:: verbose
860
860
861 Examples:
861 Examples:
862
862
863 - create an active bookmark for a new line of development::
863 - create an active bookmark for a new line of development::
864
864
865 hg book new-feature
865 hg book new-feature
866
866
867 - create an inactive bookmark as a place marker::
867 - create an inactive bookmark as a place marker::
868
868
869 hg book -i reviewed
869 hg book -i reviewed
870
870
871 - create an inactive bookmark on another changeset::
871 - create an inactive bookmark on another changeset::
872
872
873 hg book -r .^ tested
873 hg book -r .^ tested
874
874
875 - move the '@' bookmark from another branch::
875 - move the '@' bookmark from another branch::
876
876
877 hg book -f @
877 hg book -f @
878 '''
878 '''
879 force = opts.get('force')
879 force = opts.get('force')
880 rev = opts.get('rev')
880 rev = opts.get('rev')
881 delete = opts.get('delete')
881 delete = opts.get('delete')
882 rename = opts.get('rename')
882 rename = opts.get('rename')
883 inactive = opts.get('inactive')
883 inactive = opts.get('inactive')
884
884
885 def checkformat(mark):
885 def checkformat(mark):
886 mark = mark.strip()
886 mark = mark.strip()
887 if not mark:
887 if not mark:
888 raise util.Abort(_("bookmark names cannot consist entirely of "
888 raise util.Abort(_("bookmark names cannot consist entirely of "
889 "whitespace"))
889 "whitespace"))
890 scmutil.checknewlabel(repo, mark, 'bookmark')
890 scmutil.checknewlabel(repo, mark, 'bookmark')
891 return mark
891 return mark
892
892
893 def checkconflict(repo, mark, cur, force=False, target=None):
893 def checkconflict(repo, mark, cur, force=False, target=None):
894 if mark in marks and not force:
894 if mark in marks and not force:
895 if target:
895 if target:
896 if marks[mark] == target and target == cur:
896 if marks[mark] == target and target == cur:
897 # re-activating a bookmark
897 # re-activating a bookmark
898 return
898 return
899 anc = repo.changelog.ancestors([repo[target].rev()])
899 anc = repo.changelog.ancestors([repo[target].rev()])
900 bmctx = repo[marks[mark]]
900 bmctx = repo[marks[mark]]
901 divs = [repo[b].node() for b in marks
901 divs = [repo[b].node() for b in marks
902 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
902 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
903
903
904 # allow resolving a single divergent bookmark even if moving
904 # allow resolving a single divergent bookmark even if moving
905 # the bookmark across branches when a revision is specified
905 # the bookmark across branches when a revision is specified
906 # that contains a divergent bookmark
906 # that contains a divergent bookmark
907 if bmctx.rev() not in anc and target in divs:
907 if bmctx.rev() not in anc and target in divs:
908 bookmarks.deletedivergent(repo, [target], mark)
908 bookmarks.deletedivergent(repo, [target], mark)
909 return
909 return
910
910
911 deletefrom = [b for b in divs
911 deletefrom = [b for b in divs
912 if repo[b].rev() in anc or b == target]
912 if repo[b].rev() in anc or b == target]
913 bookmarks.deletedivergent(repo, deletefrom, mark)
913 bookmarks.deletedivergent(repo, deletefrom, mark)
914 if bookmarks.validdest(repo, bmctx, repo[target]):
914 if bookmarks.validdest(repo, bmctx, repo[target]):
915 ui.status(_("moving bookmark '%s' forward from %s\n") %
915 ui.status(_("moving bookmark '%s' forward from %s\n") %
916 (mark, short(bmctx.node())))
916 (mark, short(bmctx.node())))
917 return
917 return
918 raise util.Abort(_("bookmark '%s' already exists "
918 raise util.Abort(_("bookmark '%s' already exists "
919 "(use -f to force)") % mark)
919 "(use -f to force)") % mark)
920 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
920 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
921 and not force):
921 and not force):
922 raise util.Abort(
922 raise util.Abort(
923 _("a bookmark cannot have the name of an existing branch"))
923 _("a bookmark cannot have the name of an existing branch"))
924
924
925 if delete and rename:
925 if delete and rename:
926 raise util.Abort(_("--delete and --rename are incompatible"))
926 raise util.Abort(_("--delete and --rename are incompatible"))
927 if delete and rev:
927 if delete and rev:
928 raise util.Abort(_("--rev is incompatible with --delete"))
928 raise util.Abort(_("--rev is incompatible with --delete"))
929 if rename and rev:
929 if rename and rev:
930 raise util.Abort(_("--rev is incompatible with --rename"))
930 raise util.Abort(_("--rev is incompatible with --rename"))
931 if not names and (delete or rev):
931 if not names and (delete or rev):
932 raise util.Abort(_("bookmark name required"))
932 raise util.Abort(_("bookmark name required"))
933
933
934 if delete or rename or names or inactive:
934 if delete or rename or names or inactive:
935 wlock = repo.wlock()
935 wlock = repo.wlock()
936 try:
936 try:
937 cur = repo.changectx('.').node()
937 cur = repo.changectx('.').node()
938 marks = repo._bookmarks
938 marks = repo._bookmarks
939 if delete:
939 if delete:
940 for mark in names:
940 for mark in names:
941 if mark not in marks:
941 if mark not in marks:
942 raise util.Abort(_("bookmark '%s' does not exist") %
942 raise util.Abort(_("bookmark '%s' does not exist") %
943 mark)
943 mark)
944 if mark == repo._bookmarkcurrent:
944 if mark == repo._bookmarkcurrent:
945 bookmarks.unsetcurrent(repo)
945 bookmarks.unsetcurrent(repo)
946 del marks[mark]
946 del marks[mark]
947 marks.write()
947 marks.write()
948
948
949 elif rename:
949 elif rename:
950 if not names:
950 if not names:
951 raise util.Abort(_("new bookmark name required"))
951 raise util.Abort(_("new bookmark name required"))
952 elif len(names) > 1:
952 elif len(names) > 1:
953 raise util.Abort(_("only one new bookmark name allowed"))
953 raise util.Abort(_("only one new bookmark name allowed"))
954 mark = checkformat(names[0])
954 mark = checkformat(names[0])
955 if rename not in marks:
955 if rename not in marks:
956 raise util.Abort(_("bookmark '%s' does not exist") % rename)
956 raise util.Abort(_("bookmark '%s' does not exist") % rename)
957 checkconflict(repo, mark, cur, force)
957 checkconflict(repo, mark, cur, force)
958 marks[mark] = marks[rename]
958 marks[mark] = marks[rename]
959 if repo._bookmarkcurrent == rename and not inactive:
959 if repo._bookmarkcurrent == rename and not inactive:
960 bookmarks.setcurrent(repo, mark)
960 bookmarks.setcurrent(repo, mark)
961 del marks[rename]
961 del marks[rename]
962 marks.write()
962 marks.write()
963
963
964 elif names:
964 elif names:
965 newact = None
965 newact = None
966 for mark in names:
966 for mark in names:
967 mark = checkformat(mark)
967 mark = checkformat(mark)
968 if newact is None:
968 if newact is None:
969 newact = mark
969 newact = mark
970 if inactive and mark == repo._bookmarkcurrent:
970 if inactive and mark == repo._bookmarkcurrent:
971 bookmarks.unsetcurrent(repo)
971 bookmarks.unsetcurrent(repo)
972 return
972 return
973 tgt = cur
973 tgt = cur
974 if rev:
974 if rev:
975 tgt = scmutil.revsingle(repo, rev).node()
975 tgt = scmutil.revsingle(repo, rev).node()
976 checkconflict(repo, mark, cur, force, tgt)
976 checkconflict(repo, mark, cur, force, tgt)
977 marks[mark] = tgt
977 marks[mark] = tgt
978 if not inactive and cur == marks[newact] and not rev:
978 if not inactive and cur == marks[newact] and not rev:
979 bookmarks.setcurrent(repo, newact)
979 bookmarks.setcurrent(repo, newact)
980 elif cur != tgt and newact == repo._bookmarkcurrent:
980 elif cur != tgt and newact == repo._bookmarkcurrent:
981 bookmarks.unsetcurrent(repo)
981 bookmarks.unsetcurrent(repo)
982 marks.write()
982 marks.write()
983
983
984 elif inactive:
984 elif inactive:
985 if len(marks) == 0:
985 if len(marks) == 0:
986 ui.status(_("no bookmarks set\n"))
986 ui.status(_("no bookmarks set\n"))
987 elif not repo._bookmarkcurrent:
987 elif not repo._bookmarkcurrent:
988 ui.status(_("no active bookmark\n"))
988 ui.status(_("no active bookmark\n"))
989 else:
989 else:
990 bookmarks.unsetcurrent(repo)
990 bookmarks.unsetcurrent(repo)
991 finally:
991 finally:
992 wlock.release()
992 wlock.release()
993 else: # show bookmarks
993 else: # show bookmarks
994 hexfn = ui.debugflag and hex or short
994 hexfn = ui.debugflag and hex or short
995 marks = repo._bookmarks
995 marks = repo._bookmarks
996 if len(marks) == 0:
996 if len(marks) == 0:
997 ui.status(_("no bookmarks set\n"))
997 ui.status(_("no bookmarks set\n"))
998 for bmark, n in sorted(marks.iteritems()):
998 for bmark, n in sorted(marks.iteritems()):
999 current = repo._bookmarkcurrent
999 current = repo._bookmarkcurrent
1000 if bmark == current:
1000 if bmark == current:
1001 prefix, label = '*', 'bookmarks.current'
1001 prefix, label = '*', 'bookmarks.current'
1002 else:
1002 else:
1003 prefix, label = ' ', ''
1003 prefix, label = ' ', ''
1004
1004
1005 if ui.quiet:
1005 if not ui.quiet:
1006 ui.write("%s\n" % bmark, label=label)
1006 ui.write(' %s ' % prefix, label=label)
1007 else:
1007 ui.write(bmark, label=label)
1008 pad = " " * (25 - encoding.colwidth(bmark))
1008 pad = " " * (25 - encoding.colwidth(bmark))
1009 ui.write(" %s %s%s %d:%s\n" % (
1009 if not ui.quiet:
1010 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
1010 ui.write('%s %d:%s' % (
1011 pad, repo.changelog.rev(n), hexfn(n)),
1011 label=label)
1012 label=label)
1013 ui.write('\n')
1012
1014
1013 @command('branch',
1015 @command('branch',
1014 [('f', 'force', None,
1016 [('f', 'force', None,
1015 _('set branch name even if it shadows an existing branch')),
1017 _('set branch name even if it shadows an existing branch')),
1016 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1018 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1017 _('[-fC] [NAME]'))
1019 _('[-fC] [NAME]'))
1018 def branch(ui, repo, label=None, **opts):
1020 def branch(ui, repo, label=None, **opts):
1019 """set or show the current branch name
1021 """set or show the current branch name
1020
1022
1021 .. note::
1023 .. note::
1022
1024
1023 Branch names are permanent and global. Use :hg:`bookmark` to create a
1025 Branch names are permanent and global. Use :hg:`bookmark` to create a
1024 light-weight bookmark instead. See :hg:`help glossary` for more
1026 light-weight bookmark instead. See :hg:`help glossary` for more
1025 information about named branches and bookmarks.
1027 information about named branches and bookmarks.
1026
1028
1027 With no argument, show the current branch name. With one argument,
1029 With no argument, show the current branch name. With one argument,
1028 set the working directory branch name (the branch will not exist
1030 set the working directory branch name (the branch will not exist
1029 in the repository until the next commit). Standard practice
1031 in the repository until the next commit). Standard practice
1030 recommends that primary development take place on the 'default'
1032 recommends that primary development take place on the 'default'
1031 branch.
1033 branch.
1032
1034
1033 Unless -f/--force is specified, branch will not let you set a
1035 Unless -f/--force is specified, branch will not let you set a
1034 branch name that already exists, even if it's inactive.
1036 branch name that already exists, even if it's inactive.
1035
1037
1036 Use -C/--clean to reset the working directory branch to that of
1038 Use -C/--clean to reset the working directory branch to that of
1037 the parent of the working directory, negating a previous branch
1039 the parent of the working directory, negating a previous branch
1038 change.
1040 change.
1039
1041
1040 Use the command :hg:`update` to switch to an existing branch. Use
1042 Use the command :hg:`update` to switch to an existing branch. Use
1041 :hg:`commit --close-branch` to mark this branch as closed.
1043 :hg:`commit --close-branch` to mark this branch as closed.
1042
1044
1043 Returns 0 on success.
1045 Returns 0 on success.
1044 """
1046 """
1045 if label:
1047 if label:
1046 label = label.strip()
1048 label = label.strip()
1047
1049
1048 if not opts.get('clean') and not label:
1050 if not opts.get('clean') and not label:
1049 ui.write("%s\n" % repo.dirstate.branch())
1051 ui.write("%s\n" % repo.dirstate.branch())
1050 return
1052 return
1051
1053
1052 wlock = repo.wlock()
1054 wlock = repo.wlock()
1053 try:
1055 try:
1054 if opts.get('clean'):
1056 if opts.get('clean'):
1055 label = repo[None].p1().branch()
1057 label = repo[None].p1().branch()
1056 repo.dirstate.setbranch(label)
1058 repo.dirstate.setbranch(label)
1057 ui.status(_('reset working directory to branch %s\n') % label)
1059 ui.status(_('reset working directory to branch %s\n') % label)
1058 elif label:
1060 elif label:
1059 if not opts.get('force') and label in repo.branchmap():
1061 if not opts.get('force') and label in repo.branchmap():
1060 if label not in [p.branch() for p in repo.parents()]:
1062 if label not in [p.branch() for p in repo.parents()]:
1061 raise util.Abort(_('a branch of the same name already'
1063 raise util.Abort(_('a branch of the same name already'
1062 ' exists'),
1064 ' exists'),
1063 # i18n: "it" refers to an existing branch
1065 # i18n: "it" refers to an existing branch
1064 hint=_("use 'hg update' to switch to it"))
1066 hint=_("use 'hg update' to switch to it"))
1065 scmutil.checknewlabel(repo, label, 'branch')
1067 scmutil.checknewlabel(repo, label, 'branch')
1066 repo.dirstate.setbranch(label)
1068 repo.dirstate.setbranch(label)
1067 ui.status(_('marked working directory as branch %s\n') % label)
1069 ui.status(_('marked working directory as branch %s\n') % label)
1068 ui.status(_('(branches are permanent and global, '
1070 ui.status(_('(branches are permanent and global, '
1069 'did you want a bookmark?)\n'))
1071 'did you want a bookmark?)\n'))
1070 finally:
1072 finally:
1071 wlock.release()
1073 wlock.release()
1072
1074
1073 @command('branches',
1075 @command('branches',
1074 [('a', 'active', False, _('show only branches that have unmerged heads')),
1076 [('a', 'active', False, _('show only branches that have unmerged heads')),
1075 ('c', 'closed', False, _('show normal and closed branches')),
1077 ('c', 'closed', False, _('show normal and closed branches')),
1076 ] + formatteropts,
1078 ] + formatteropts,
1077 _('[-ac]'))
1079 _('[-ac]'))
1078 def branches(ui, repo, active=False, closed=False, **opts):
1080 def branches(ui, repo, active=False, closed=False, **opts):
1079 """list repository named branches
1081 """list repository named branches
1080
1082
1081 List the repository's named branches, indicating which ones are
1083 List the repository's named branches, indicating which ones are
1082 inactive. If -c/--closed is specified, also list branches which have
1084 inactive. If -c/--closed is specified, also list branches which have
1083 been marked closed (see :hg:`commit --close-branch`).
1085 been marked closed (see :hg:`commit --close-branch`).
1084
1086
1085 If -a/--active is specified, only show active branches. A branch
1087 If -a/--active is specified, only show active branches. A branch
1086 is considered active if it contains repository heads.
1088 is considered active if it contains repository heads.
1087
1089
1088 Use the command :hg:`update` to switch to an existing branch.
1090 Use the command :hg:`update` to switch to an existing branch.
1089
1091
1090 Returns 0.
1092 Returns 0.
1091 """
1093 """
1092
1094
1093 fm = ui.formatter('branches', opts)
1095 fm = ui.formatter('branches', opts)
1094 hexfunc = fm.hexfunc
1096 hexfunc = fm.hexfunc
1095
1097
1096 allheads = set(repo.heads())
1098 allheads = set(repo.heads())
1097 branches = []
1099 branches = []
1098 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1100 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1099 isactive = not isclosed and bool(set(heads) & allheads)
1101 isactive = not isclosed and bool(set(heads) & allheads)
1100 branches.append((tag, repo[tip], isactive, not isclosed))
1102 branches.append((tag, repo[tip], isactive, not isclosed))
1101 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1103 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1102 reverse=True)
1104 reverse=True)
1103
1105
1104 for tag, ctx, isactive, isopen in branches:
1106 for tag, ctx, isactive, isopen in branches:
1105 if active and not isactive:
1107 if active and not isactive:
1106 continue
1108 continue
1107 if isactive:
1109 if isactive:
1108 label = 'branches.active'
1110 label = 'branches.active'
1109 notice = ''
1111 notice = ''
1110 elif not isopen:
1112 elif not isopen:
1111 if not closed:
1113 if not closed:
1112 continue
1114 continue
1113 label = 'branches.closed'
1115 label = 'branches.closed'
1114 notice = _(' (closed)')
1116 notice = _(' (closed)')
1115 else:
1117 else:
1116 label = 'branches.inactive'
1118 label = 'branches.inactive'
1117 notice = _(' (inactive)')
1119 notice = _(' (inactive)')
1118 current = (tag == repo.dirstate.branch())
1120 current = (tag == repo.dirstate.branch())
1119 if current:
1121 if current:
1120 label = 'branches.current'
1122 label = 'branches.current'
1121
1123
1122 fm.startitem()
1124 fm.startitem()
1123 fm.write('branch', '%s', tag, label=label)
1125 fm.write('branch', '%s', tag, label=label)
1124 rev = ctx.rev()
1126 rev = ctx.rev()
1125 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1127 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1126 fmt = ' ' * padsize + ' %d:%s'
1128 fmt = ' ' * padsize + ' %d:%s'
1127 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1129 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1128 label='log.changeset changeset.%s' % ctx.phasestr())
1130 label='log.changeset changeset.%s' % ctx.phasestr())
1129 fm.data(active=isactive, closed=not isopen, current=current)
1131 fm.data(active=isactive, closed=not isopen, current=current)
1130 if not ui.quiet:
1132 if not ui.quiet:
1131 fm.plain(notice)
1133 fm.plain(notice)
1132 fm.plain('\n')
1134 fm.plain('\n')
1133 fm.end()
1135 fm.end()
1134
1136
1135 @command('bundle',
1137 @command('bundle',
1136 [('f', 'force', None, _('run even when the destination is unrelated')),
1138 [('f', 'force', None, _('run even when the destination is unrelated')),
1137 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1139 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1138 _('REV')),
1140 _('REV')),
1139 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1141 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1140 _('BRANCH')),
1142 _('BRANCH')),
1141 ('', 'base', [],
1143 ('', 'base', [],
1142 _('a base changeset assumed to be available at the destination'),
1144 _('a base changeset assumed to be available at the destination'),
1143 _('REV')),
1145 _('REV')),
1144 ('a', 'all', None, _('bundle all changesets in the repository')),
1146 ('a', 'all', None, _('bundle all changesets in the repository')),
1145 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1147 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1146 ] + remoteopts,
1148 ] + remoteopts,
1147 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1149 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1148 def bundle(ui, repo, fname, dest=None, **opts):
1150 def bundle(ui, repo, fname, dest=None, **opts):
1149 """create a changegroup file
1151 """create a changegroup file
1150
1152
1151 Generate a compressed changegroup file collecting changesets not
1153 Generate a compressed changegroup file collecting changesets not
1152 known to be in another repository.
1154 known to be in another repository.
1153
1155
1154 If you omit the destination repository, then hg assumes the
1156 If you omit the destination repository, then hg assumes the
1155 destination will have all the nodes you specify with --base
1157 destination will have all the nodes you specify with --base
1156 parameters. To create a bundle containing all changesets, use
1158 parameters. To create a bundle containing all changesets, use
1157 -a/--all (or --base null).
1159 -a/--all (or --base null).
1158
1160
1159 You can change compression method with the -t/--type option.
1161 You can change compression method with the -t/--type option.
1160 The available compression methods are: none, bzip2, and
1162 The available compression methods are: none, bzip2, and
1161 gzip (by default, bundles are compressed using bzip2).
1163 gzip (by default, bundles are compressed using bzip2).
1162
1164
1163 The bundle file can then be transferred using conventional means
1165 The bundle file can then be transferred using conventional means
1164 and applied to another repository with the unbundle or pull
1166 and applied to another repository with the unbundle or pull
1165 command. This is useful when direct push and pull are not
1167 command. This is useful when direct push and pull are not
1166 available or when exporting an entire repository is undesirable.
1168 available or when exporting an entire repository is undesirable.
1167
1169
1168 Applying bundles preserves all changeset contents including
1170 Applying bundles preserves all changeset contents including
1169 permissions, copy/rename information, and revision history.
1171 permissions, copy/rename information, and revision history.
1170
1172
1171 Returns 0 on success, 1 if no changes found.
1173 Returns 0 on success, 1 if no changes found.
1172 """
1174 """
1173 revs = None
1175 revs = None
1174 if 'rev' in opts:
1176 if 'rev' in opts:
1175 revs = scmutil.revrange(repo, opts['rev'])
1177 revs = scmutil.revrange(repo, opts['rev'])
1176
1178
1177 bundletype = opts.get('type', 'bzip2').lower()
1179 bundletype = opts.get('type', 'bzip2').lower()
1178 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1180 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1179 bundletype = btypes.get(bundletype)
1181 bundletype = btypes.get(bundletype)
1180 if bundletype not in changegroup.bundletypes:
1182 if bundletype not in changegroup.bundletypes:
1181 raise util.Abort(_('unknown bundle type specified with --type'))
1183 raise util.Abort(_('unknown bundle type specified with --type'))
1182
1184
1183 if opts.get('all'):
1185 if opts.get('all'):
1184 base = ['null']
1186 base = ['null']
1185 else:
1187 else:
1186 base = scmutil.revrange(repo, opts.get('base'))
1188 base = scmutil.revrange(repo, opts.get('base'))
1187 # TODO: get desired bundlecaps from command line.
1189 # TODO: get desired bundlecaps from command line.
1188 bundlecaps = None
1190 bundlecaps = None
1189 if base:
1191 if base:
1190 if dest:
1192 if dest:
1191 raise util.Abort(_("--base is incompatible with specifying "
1193 raise util.Abort(_("--base is incompatible with specifying "
1192 "a destination"))
1194 "a destination"))
1193 common = [repo.lookup(rev) for rev in base]
1195 common = [repo.lookup(rev) for rev in base]
1194 heads = revs and map(repo.lookup, revs) or revs
1196 heads = revs and map(repo.lookup, revs) or revs
1195 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1197 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1196 common=common, bundlecaps=bundlecaps)
1198 common=common, bundlecaps=bundlecaps)
1197 outgoing = None
1199 outgoing = None
1198 else:
1200 else:
1199 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1201 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1200 dest, branches = hg.parseurl(dest, opts.get('branch'))
1202 dest, branches = hg.parseurl(dest, opts.get('branch'))
1201 other = hg.peer(repo, opts, dest)
1203 other = hg.peer(repo, opts, dest)
1202 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1204 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1203 heads = revs and map(repo.lookup, revs) or revs
1205 heads = revs and map(repo.lookup, revs) or revs
1204 outgoing = discovery.findcommonoutgoing(repo, other,
1206 outgoing = discovery.findcommonoutgoing(repo, other,
1205 onlyheads=heads,
1207 onlyheads=heads,
1206 force=opts.get('force'),
1208 force=opts.get('force'),
1207 portable=True)
1209 portable=True)
1208 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1210 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1209 bundlecaps)
1211 bundlecaps)
1210 if not cg:
1212 if not cg:
1211 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1213 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1212 return 1
1214 return 1
1213
1215
1214 changegroup.writebundle(cg, fname, bundletype)
1216 changegroup.writebundle(cg, fname, bundletype)
1215
1217
1216 @command('cat',
1218 @command('cat',
1217 [('o', 'output', '',
1219 [('o', 'output', '',
1218 _('print output to file with formatted name'), _('FORMAT')),
1220 _('print output to file with formatted name'), _('FORMAT')),
1219 ('r', 'rev', '', _('print the given revision'), _('REV')),
1221 ('r', 'rev', '', _('print the given revision'), _('REV')),
1220 ('', 'decode', None, _('apply any matching decode filter')),
1222 ('', 'decode', None, _('apply any matching decode filter')),
1221 ] + walkopts,
1223 ] + walkopts,
1222 _('[OPTION]... FILE...'),
1224 _('[OPTION]... FILE...'),
1223 inferrepo=True)
1225 inferrepo=True)
1224 def cat(ui, repo, file1, *pats, **opts):
1226 def cat(ui, repo, file1, *pats, **opts):
1225 """output the current or given revision of files
1227 """output the current or given revision of files
1226
1228
1227 Print the specified files as they were at the given revision. If
1229 Print the specified files as they were at the given revision. If
1228 no revision is given, the parent of the working directory is used.
1230 no revision is given, the parent of the working directory is used.
1229
1231
1230 Output may be to a file, in which case the name of the file is
1232 Output may be to a file, in which case the name of the file is
1231 given using a format string. The formatting rules as follows:
1233 given using a format string. The formatting rules as follows:
1232
1234
1233 :``%%``: literal "%" character
1235 :``%%``: literal "%" character
1234 :``%s``: basename of file being printed
1236 :``%s``: basename of file being printed
1235 :``%d``: dirname of file being printed, or '.' if in repository root
1237 :``%d``: dirname of file being printed, or '.' if in repository root
1236 :``%p``: root-relative path name of file being printed
1238 :``%p``: root-relative path name of file being printed
1237 :``%H``: changeset hash (40 hexadecimal digits)
1239 :``%H``: changeset hash (40 hexadecimal digits)
1238 :``%R``: changeset revision number
1240 :``%R``: changeset revision number
1239 :``%h``: short-form changeset hash (12 hexadecimal digits)
1241 :``%h``: short-form changeset hash (12 hexadecimal digits)
1240 :``%r``: zero-padded changeset revision number
1242 :``%r``: zero-padded changeset revision number
1241 :``%b``: basename of the exporting repository
1243 :``%b``: basename of the exporting repository
1242
1244
1243 Returns 0 on success.
1245 Returns 0 on success.
1244 """
1246 """
1245 ctx = scmutil.revsingle(repo, opts.get('rev'))
1247 ctx = scmutil.revsingle(repo, opts.get('rev'))
1246 m = scmutil.match(ctx, (file1,) + pats, opts)
1248 m = scmutil.match(ctx, (file1,) + pats, opts)
1247
1249
1248 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1250 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1249
1251
1250 @command('^clone',
1252 @command('^clone',
1251 [('U', 'noupdate', None,
1253 [('U', 'noupdate', None,
1252 _('the clone will include an empty working copy (only a repository)')),
1254 _('the clone will include an empty working copy (only a repository)')),
1253 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1255 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1254 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1256 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1255 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1257 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1256 ('', 'pull', None, _('use pull protocol to copy metadata')),
1258 ('', 'pull', None, _('use pull protocol to copy metadata')),
1257 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1259 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1258 ] + remoteopts,
1260 ] + remoteopts,
1259 _('[OPTION]... SOURCE [DEST]'),
1261 _('[OPTION]... SOURCE [DEST]'),
1260 norepo=True)
1262 norepo=True)
1261 def clone(ui, source, dest=None, **opts):
1263 def clone(ui, source, dest=None, **opts):
1262 """make a copy of an existing repository
1264 """make a copy of an existing repository
1263
1265
1264 Create a copy of an existing repository in a new directory.
1266 Create a copy of an existing repository in a new directory.
1265
1267
1266 If no destination directory name is specified, it defaults to the
1268 If no destination directory name is specified, it defaults to the
1267 basename of the source.
1269 basename of the source.
1268
1270
1269 The location of the source is added to the new repository's
1271 The location of the source is added to the new repository's
1270 ``.hg/hgrc`` file, as the default to be used for future pulls.
1272 ``.hg/hgrc`` file, as the default to be used for future pulls.
1271
1273
1272 Only local paths and ``ssh://`` URLs are supported as
1274 Only local paths and ``ssh://`` URLs are supported as
1273 destinations. For ``ssh://`` destinations, no working directory or
1275 destinations. For ``ssh://`` destinations, no working directory or
1274 ``.hg/hgrc`` will be created on the remote side.
1276 ``.hg/hgrc`` will be created on the remote side.
1275
1277
1276 To pull only a subset of changesets, specify one or more revisions
1278 To pull only a subset of changesets, specify one or more revisions
1277 identifiers with -r/--rev or branches with -b/--branch. The
1279 identifiers with -r/--rev or branches with -b/--branch. The
1278 resulting clone will contain only the specified changesets and
1280 resulting clone will contain only the specified changesets and
1279 their ancestors. These options (or 'clone src#rev dest') imply
1281 their ancestors. These options (or 'clone src#rev dest') imply
1280 --pull, even for local source repositories. Note that specifying a
1282 --pull, even for local source repositories. Note that specifying a
1281 tag will include the tagged changeset but not the changeset
1283 tag will include the tagged changeset but not the changeset
1282 containing the tag.
1284 containing the tag.
1283
1285
1284 If the source repository has a bookmark called '@' set, that
1286 If the source repository has a bookmark called '@' set, that
1285 revision will be checked out in the new repository by default.
1287 revision will be checked out in the new repository by default.
1286
1288
1287 To check out a particular version, use -u/--update, or
1289 To check out a particular version, use -u/--update, or
1288 -U/--noupdate to create a clone with no working directory.
1290 -U/--noupdate to create a clone with no working directory.
1289
1291
1290 .. container:: verbose
1292 .. container:: verbose
1291
1293
1292 For efficiency, hardlinks are used for cloning whenever the
1294 For efficiency, hardlinks are used for cloning whenever the
1293 source and destination are on the same filesystem (note this
1295 source and destination are on the same filesystem (note this
1294 applies only to the repository data, not to the working
1296 applies only to the repository data, not to the working
1295 directory). Some filesystems, such as AFS, implement hardlinking
1297 directory). Some filesystems, such as AFS, implement hardlinking
1296 incorrectly, but do not report errors. In these cases, use the
1298 incorrectly, but do not report errors. In these cases, use the
1297 --pull option to avoid hardlinking.
1299 --pull option to avoid hardlinking.
1298
1300
1299 In some cases, you can clone repositories and the working
1301 In some cases, you can clone repositories and the working
1300 directory using full hardlinks with ::
1302 directory using full hardlinks with ::
1301
1303
1302 $ cp -al REPO REPOCLONE
1304 $ cp -al REPO REPOCLONE
1303
1305
1304 This is the fastest way to clone, but it is not always safe. The
1306 This is the fastest way to clone, but it is not always safe. The
1305 operation is not atomic (making sure REPO is not modified during
1307 operation is not atomic (making sure REPO is not modified during
1306 the operation is up to you) and you have to make sure your
1308 the operation is up to you) and you have to make sure your
1307 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1309 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1308 so). Also, this is not compatible with certain extensions that
1310 so). Also, this is not compatible with certain extensions that
1309 place their metadata under the .hg directory, such as mq.
1311 place their metadata under the .hg directory, such as mq.
1310
1312
1311 Mercurial will update the working directory to the first applicable
1313 Mercurial will update the working directory to the first applicable
1312 revision from this list:
1314 revision from this list:
1313
1315
1314 a) null if -U or the source repository has no changesets
1316 a) null if -U or the source repository has no changesets
1315 b) if -u . and the source repository is local, the first parent of
1317 b) if -u . and the source repository is local, the first parent of
1316 the source repository's working directory
1318 the source repository's working directory
1317 c) the changeset specified with -u (if a branch name, this means the
1319 c) the changeset specified with -u (if a branch name, this means the
1318 latest head of that branch)
1320 latest head of that branch)
1319 d) the changeset specified with -r
1321 d) the changeset specified with -r
1320 e) the tipmost head specified with -b
1322 e) the tipmost head specified with -b
1321 f) the tipmost head specified with the url#branch source syntax
1323 f) the tipmost head specified with the url#branch source syntax
1322 g) the revision marked with the '@' bookmark, if present
1324 g) the revision marked with the '@' bookmark, if present
1323 h) the tipmost head of the default branch
1325 h) the tipmost head of the default branch
1324 i) tip
1326 i) tip
1325
1327
1326 Examples:
1328 Examples:
1327
1329
1328 - clone a remote repository to a new directory named hg/::
1330 - clone a remote repository to a new directory named hg/::
1329
1331
1330 hg clone http://selenic.com/hg
1332 hg clone http://selenic.com/hg
1331
1333
1332 - create a lightweight local clone::
1334 - create a lightweight local clone::
1333
1335
1334 hg clone project/ project-feature/
1336 hg clone project/ project-feature/
1335
1337
1336 - clone from an absolute path on an ssh server (note double-slash)::
1338 - clone from an absolute path on an ssh server (note double-slash)::
1337
1339
1338 hg clone ssh://user@server//home/projects/alpha/
1340 hg clone ssh://user@server//home/projects/alpha/
1339
1341
1340 - do a high-speed clone over a LAN while checking out a
1342 - do a high-speed clone over a LAN while checking out a
1341 specified version::
1343 specified version::
1342
1344
1343 hg clone --uncompressed http://server/repo -u 1.5
1345 hg clone --uncompressed http://server/repo -u 1.5
1344
1346
1345 - create a repository without changesets after a particular revision::
1347 - create a repository without changesets after a particular revision::
1346
1348
1347 hg clone -r 04e544 experimental/ good/
1349 hg clone -r 04e544 experimental/ good/
1348
1350
1349 - clone (and track) a particular named branch::
1351 - clone (and track) a particular named branch::
1350
1352
1351 hg clone http://selenic.com/hg#stable
1353 hg clone http://selenic.com/hg#stable
1352
1354
1353 See :hg:`help urls` for details on specifying URLs.
1355 See :hg:`help urls` for details on specifying URLs.
1354
1356
1355 Returns 0 on success.
1357 Returns 0 on success.
1356 """
1358 """
1357 if opts.get('noupdate') and opts.get('updaterev'):
1359 if opts.get('noupdate') and opts.get('updaterev'):
1358 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1360 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1359
1361
1360 r = hg.clone(ui, opts, source, dest,
1362 r = hg.clone(ui, opts, source, dest,
1361 pull=opts.get('pull'),
1363 pull=opts.get('pull'),
1362 stream=opts.get('uncompressed'),
1364 stream=opts.get('uncompressed'),
1363 rev=opts.get('rev'),
1365 rev=opts.get('rev'),
1364 update=opts.get('updaterev') or not opts.get('noupdate'),
1366 update=opts.get('updaterev') or not opts.get('noupdate'),
1365 branch=opts.get('branch'))
1367 branch=opts.get('branch'))
1366
1368
1367 return r is None
1369 return r is None
1368
1370
1369 @command('^commit|ci',
1371 @command('^commit|ci',
1370 [('A', 'addremove', None,
1372 [('A', 'addremove', None,
1371 _('mark new/missing files as added/removed before committing')),
1373 _('mark new/missing files as added/removed before committing')),
1372 ('', 'close-branch', None,
1374 ('', 'close-branch', None,
1373 _('mark a branch as closed, hiding it from the branch list')),
1375 _('mark a branch as closed, hiding it from the branch list')),
1374 ('', 'amend', None, _('amend the parent of the working dir')),
1376 ('', 'amend', None, _('amend the parent of the working dir')),
1375 ('s', 'secret', None, _('use the secret phase for committing')),
1377 ('s', 'secret', None, _('use the secret phase for committing')),
1376 ('e', 'edit', None, _('invoke editor on commit messages')),
1378 ('e', 'edit', None, _('invoke editor on commit messages')),
1377 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1379 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1378 _('[OPTION]... [FILE]...'),
1380 _('[OPTION]... [FILE]...'),
1379 inferrepo=True)
1381 inferrepo=True)
1380 def commit(ui, repo, *pats, **opts):
1382 def commit(ui, repo, *pats, **opts):
1381 """commit the specified files or all outstanding changes
1383 """commit the specified files or all outstanding changes
1382
1384
1383 Commit changes to the given files into the repository. Unlike a
1385 Commit changes to the given files into the repository. Unlike a
1384 centralized SCM, this operation is a local operation. See
1386 centralized SCM, this operation is a local operation. See
1385 :hg:`push` for a way to actively distribute your changes.
1387 :hg:`push` for a way to actively distribute your changes.
1386
1388
1387 If a list of files is omitted, all changes reported by :hg:`status`
1389 If a list of files is omitted, all changes reported by :hg:`status`
1388 will be committed.
1390 will be committed.
1389
1391
1390 If you are committing the result of a merge, do not provide any
1392 If you are committing the result of a merge, do not provide any
1391 filenames or -I/-X filters.
1393 filenames or -I/-X filters.
1392
1394
1393 If no commit message is specified, Mercurial starts your
1395 If no commit message is specified, Mercurial starts your
1394 configured editor where you can enter a message. In case your
1396 configured editor where you can enter a message. In case your
1395 commit fails, you will find a backup of your message in
1397 commit fails, you will find a backup of your message in
1396 ``.hg/last-message.txt``.
1398 ``.hg/last-message.txt``.
1397
1399
1398 The --amend flag can be used to amend the parent of the
1400 The --amend flag can be used to amend the parent of the
1399 working directory with a new commit that contains the changes
1401 working directory with a new commit that contains the changes
1400 in the parent in addition to those currently reported by :hg:`status`,
1402 in the parent in addition to those currently reported by :hg:`status`,
1401 if there are any. The old commit is stored in a backup bundle in
1403 if there are any. The old commit is stored in a backup bundle in
1402 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1404 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1403 on how to restore it).
1405 on how to restore it).
1404
1406
1405 Message, user and date are taken from the amended commit unless
1407 Message, user and date are taken from the amended commit unless
1406 specified. When a message isn't specified on the command line,
1408 specified. When a message isn't specified on the command line,
1407 the editor will open with the message of the amended commit.
1409 the editor will open with the message of the amended commit.
1408
1410
1409 It is not possible to amend public changesets (see :hg:`help phases`)
1411 It is not possible to amend public changesets (see :hg:`help phases`)
1410 or changesets that have children.
1412 or changesets that have children.
1411
1413
1412 See :hg:`help dates` for a list of formats valid for -d/--date.
1414 See :hg:`help dates` for a list of formats valid for -d/--date.
1413
1415
1414 Returns 0 on success, 1 if nothing changed.
1416 Returns 0 on success, 1 if nothing changed.
1415 """
1417 """
1416 if opts.get('subrepos'):
1418 if opts.get('subrepos'):
1417 if opts.get('amend'):
1419 if opts.get('amend'):
1418 raise util.Abort(_('cannot amend with --subrepos'))
1420 raise util.Abort(_('cannot amend with --subrepos'))
1419 # Let --subrepos on the command line override config setting.
1421 # Let --subrepos on the command line override config setting.
1420 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1422 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1421
1423
1422 cmdutil.checkunfinished(repo, commit=True)
1424 cmdutil.checkunfinished(repo, commit=True)
1423
1425
1424 branch = repo[None].branch()
1426 branch = repo[None].branch()
1425 bheads = repo.branchheads(branch)
1427 bheads = repo.branchheads(branch)
1426
1428
1427 extra = {}
1429 extra = {}
1428 if opts.get('close_branch'):
1430 if opts.get('close_branch'):
1429 extra['close'] = 1
1431 extra['close'] = 1
1430
1432
1431 if not bheads:
1433 if not bheads:
1432 raise util.Abort(_('can only close branch heads'))
1434 raise util.Abort(_('can only close branch heads'))
1433 elif opts.get('amend'):
1435 elif opts.get('amend'):
1434 if repo.parents()[0].p1().branch() != branch and \
1436 if repo.parents()[0].p1().branch() != branch and \
1435 repo.parents()[0].p2().branch() != branch:
1437 repo.parents()[0].p2().branch() != branch:
1436 raise util.Abort(_('can only close branch heads'))
1438 raise util.Abort(_('can only close branch heads'))
1437
1439
1438 if opts.get('amend'):
1440 if opts.get('amend'):
1439 if ui.configbool('ui', 'commitsubrepos'):
1441 if ui.configbool('ui', 'commitsubrepos'):
1440 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1442 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1441
1443
1442 old = repo['.']
1444 old = repo['.']
1443 if not old.mutable():
1445 if not old.mutable():
1444 raise util.Abort(_('cannot amend public changesets'))
1446 raise util.Abort(_('cannot amend public changesets'))
1445 if len(repo[None].parents()) > 1:
1447 if len(repo[None].parents()) > 1:
1446 raise util.Abort(_('cannot amend while merging'))
1448 raise util.Abort(_('cannot amend while merging'))
1447 if (not obsolete._enabled) and old.children():
1449 if (not obsolete._enabled) and old.children():
1448 raise util.Abort(_('cannot amend changeset with children'))
1450 raise util.Abort(_('cannot amend changeset with children'))
1449
1451
1450 # commitfunc is used only for temporary amend commit by cmdutil.amend
1452 # commitfunc is used only for temporary amend commit by cmdutil.amend
1451 def commitfunc(ui, repo, message, match, opts):
1453 def commitfunc(ui, repo, message, match, opts):
1452 return repo.commit(message,
1454 return repo.commit(message,
1453 opts.get('user') or old.user(),
1455 opts.get('user') or old.user(),
1454 opts.get('date') or old.date(),
1456 opts.get('date') or old.date(),
1455 match,
1457 match,
1456 extra=extra)
1458 extra=extra)
1457
1459
1458 current = repo._bookmarkcurrent
1460 current = repo._bookmarkcurrent
1459 marks = old.bookmarks()
1461 marks = old.bookmarks()
1460 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1462 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1461 if node == old.node():
1463 if node == old.node():
1462 ui.status(_("nothing changed\n"))
1464 ui.status(_("nothing changed\n"))
1463 return 1
1465 return 1
1464 elif marks:
1466 elif marks:
1465 ui.debug('moving bookmarks %r from %s to %s\n' %
1467 ui.debug('moving bookmarks %r from %s to %s\n' %
1466 (marks, old.hex(), hex(node)))
1468 (marks, old.hex(), hex(node)))
1467 newmarks = repo._bookmarks
1469 newmarks = repo._bookmarks
1468 for bm in marks:
1470 for bm in marks:
1469 newmarks[bm] = node
1471 newmarks[bm] = node
1470 if bm == current:
1472 if bm == current:
1471 bookmarks.setcurrent(repo, bm)
1473 bookmarks.setcurrent(repo, bm)
1472 newmarks.write()
1474 newmarks.write()
1473 else:
1475 else:
1474 def commitfunc(ui, repo, message, match, opts):
1476 def commitfunc(ui, repo, message, match, opts):
1475 backup = ui.backupconfig('phases', 'new-commit')
1477 backup = ui.backupconfig('phases', 'new-commit')
1476 baseui = repo.baseui
1478 baseui = repo.baseui
1477 basebackup = baseui.backupconfig('phases', 'new-commit')
1479 basebackup = baseui.backupconfig('phases', 'new-commit')
1478 try:
1480 try:
1479 if opts.get('secret'):
1481 if opts.get('secret'):
1480 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1482 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1481 # Propagate to subrepos
1483 # Propagate to subrepos
1482 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1484 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1483
1485
1484 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1486 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1485 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1487 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1486 return repo.commit(message, opts.get('user'), opts.get('date'),
1488 return repo.commit(message, opts.get('user'), opts.get('date'),
1487 match,
1489 match,
1488 editor=editor,
1490 editor=editor,
1489 extra=extra)
1491 extra=extra)
1490 finally:
1492 finally:
1491 ui.restoreconfig(backup)
1493 ui.restoreconfig(backup)
1492 repo.baseui.restoreconfig(basebackup)
1494 repo.baseui.restoreconfig(basebackup)
1493
1495
1494
1496
1495 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1497 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1496
1498
1497 if not node:
1499 if not node:
1498 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1500 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1499 if stat[3]:
1501 if stat[3]:
1500 ui.status(_("nothing changed (%d missing files, see "
1502 ui.status(_("nothing changed (%d missing files, see "
1501 "'hg status')\n") % len(stat[3]))
1503 "'hg status')\n") % len(stat[3]))
1502 else:
1504 else:
1503 ui.status(_("nothing changed\n"))
1505 ui.status(_("nothing changed\n"))
1504 return 1
1506 return 1
1505
1507
1506 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1508 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1507
1509
1508 @command('config|showconfig|debugconfig',
1510 @command('config|showconfig|debugconfig',
1509 [('u', 'untrusted', None, _('show untrusted configuration options')),
1511 [('u', 'untrusted', None, _('show untrusted configuration options')),
1510 ('e', 'edit', None, _('edit user config')),
1512 ('e', 'edit', None, _('edit user config')),
1511 ('l', 'local', None, _('edit repository config')),
1513 ('l', 'local', None, _('edit repository config')),
1512 ('g', 'global', None, _('edit global config'))],
1514 ('g', 'global', None, _('edit global config'))],
1513 _('[-u] [NAME]...'),
1515 _('[-u] [NAME]...'),
1514 optionalrepo=True)
1516 optionalrepo=True)
1515 def config(ui, repo, *values, **opts):
1517 def config(ui, repo, *values, **opts):
1516 """show combined config settings from all hgrc files
1518 """show combined config settings from all hgrc files
1517
1519
1518 With no arguments, print names and values of all config items.
1520 With no arguments, print names and values of all config items.
1519
1521
1520 With one argument of the form section.name, print just the value
1522 With one argument of the form section.name, print just the value
1521 of that config item.
1523 of that config item.
1522
1524
1523 With multiple arguments, print names and values of all config
1525 With multiple arguments, print names and values of all config
1524 items with matching section names.
1526 items with matching section names.
1525
1527
1526 With --edit, start an editor on the user-level config file. With
1528 With --edit, start an editor on the user-level config file. With
1527 --global, edit the system-wide config file. With --local, edit the
1529 --global, edit the system-wide config file. With --local, edit the
1528 repository-level config file.
1530 repository-level config file.
1529
1531
1530 With --debug, the source (filename and line number) is printed
1532 With --debug, the source (filename and line number) is printed
1531 for each config item.
1533 for each config item.
1532
1534
1533 See :hg:`help config` for more information about config files.
1535 See :hg:`help config` for more information about config files.
1534
1536
1535 Returns 0 on success, 1 if NAME does not exist.
1537 Returns 0 on success, 1 if NAME does not exist.
1536
1538
1537 """
1539 """
1538
1540
1539 if opts.get('edit') or opts.get('local') or opts.get('global'):
1541 if opts.get('edit') or opts.get('local') or opts.get('global'):
1540 if opts.get('local') and opts.get('global'):
1542 if opts.get('local') and opts.get('global'):
1541 raise util.Abort(_("can't use --local and --global together"))
1543 raise util.Abort(_("can't use --local and --global together"))
1542
1544
1543 if opts.get('local'):
1545 if opts.get('local'):
1544 if not repo:
1546 if not repo:
1545 raise util.Abort(_("can't use --local outside a repository"))
1547 raise util.Abort(_("can't use --local outside a repository"))
1546 paths = [repo.join('hgrc')]
1548 paths = [repo.join('hgrc')]
1547 elif opts.get('global'):
1549 elif opts.get('global'):
1548 paths = scmutil.systemrcpath()
1550 paths = scmutil.systemrcpath()
1549 else:
1551 else:
1550 paths = scmutil.userrcpath()
1552 paths = scmutil.userrcpath()
1551
1553
1552 for f in paths:
1554 for f in paths:
1553 if os.path.exists(f):
1555 if os.path.exists(f):
1554 break
1556 break
1555 else:
1557 else:
1556 from ui import samplehgrcs
1558 from ui import samplehgrcs
1557
1559
1558 if opts.get('global'):
1560 if opts.get('global'):
1559 samplehgrc = samplehgrcs['global']
1561 samplehgrc = samplehgrcs['global']
1560 elif opts.get('local'):
1562 elif opts.get('local'):
1561 samplehgrc = samplehgrcs['local']
1563 samplehgrc = samplehgrcs['local']
1562 else:
1564 else:
1563 samplehgrc = samplehgrcs['user']
1565 samplehgrc = samplehgrcs['user']
1564
1566
1565 f = paths[0]
1567 f = paths[0]
1566 fp = open(f, "w")
1568 fp = open(f, "w")
1567 fp.write(samplehgrc)
1569 fp.write(samplehgrc)
1568 fp.close()
1570 fp.close()
1569
1571
1570 editor = ui.geteditor()
1572 editor = ui.geteditor()
1571 util.system("%s \"%s\"" % (editor, f),
1573 util.system("%s \"%s\"" % (editor, f),
1572 onerr=util.Abort, errprefix=_("edit failed"),
1574 onerr=util.Abort, errprefix=_("edit failed"),
1573 out=ui.fout)
1575 out=ui.fout)
1574 return
1576 return
1575
1577
1576 for f in scmutil.rcpath():
1578 for f in scmutil.rcpath():
1577 ui.debug('read config from: %s\n' % f)
1579 ui.debug('read config from: %s\n' % f)
1578 untrusted = bool(opts.get('untrusted'))
1580 untrusted = bool(opts.get('untrusted'))
1579 if values:
1581 if values:
1580 sections = [v for v in values if '.' not in v]
1582 sections = [v for v in values if '.' not in v]
1581 items = [v for v in values if '.' in v]
1583 items = [v for v in values if '.' in v]
1582 if len(items) > 1 or items and sections:
1584 if len(items) > 1 or items and sections:
1583 raise util.Abort(_('only one config item permitted'))
1585 raise util.Abort(_('only one config item permitted'))
1584 matched = False
1586 matched = False
1585 for section, name, value in ui.walkconfig(untrusted=untrusted):
1587 for section, name, value in ui.walkconfig(untrusted=untrusted):
1586 value = str(value).replace('\n', '\\n')
1588 value = str(value).replace('\n', '\\n')
1587 sectname = section + '.' + name
1589 sectname = section + '.' + name
1588 if values:
1590 if values:
1589 for v in values:
1591 for v in values:
1590 if v == section:
1592 if v == section:
1591 ui.debug('%s: ' %
1593 ui.debug('%s: ' %
1592 ui.configsource(section, name, untrusted))
1594 ui.configsource(section, name, untrusted))
1593 ui.write('%s=%s\n' % (sectname, value))
1595 ui.write('%s=%s\n' % (sectname, value))
1594 matched = True
1596 matched = True
1595 elif v == sectname:
1597 elif v == sectname:
1596 ui.debug('%s: ' %
1598 ui.debug('%s: ' %
1597 ui.configsource(section, name, untrusted))
1599 ui.configsource(section, name, untrusted))
1598 ui.write(value, '\n')
1600 ui.write(value, '\n')
1599 matched = True
1601 matched = True
1600 else:
1602 else:
1601 ui.debug('%s: ' %
1603 ui.debug('%s: ' %
1602 ui.configsource(section, name, untrusted))
1604 ui.configsource(section, name, untrusted))
1603 ui.write('%s=%s\n' % (sectname, value))
1605 ui.write('%s=%s\n' % (sectname, value))
1604 matched = True
1606 matched = True
1605 if matched:
1607 if matched:
1606 return 0
1608 return 0
1607 return 1
1609 return 1
1608
1610
1609 @command('copy|cp',
1611 @command('copy|cp',
1610 [('A', 'after', None, _('record a copy that has already occurred')),
1612 [('A', 'after', None, _('record a copy that has already occurred')),
1611 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1613 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1612 ] + walkopts + dryrunopts,
1614 ] + walkopts + dryrunopts,
1613 _('[OPTION]... [SOURCE]... DEST'))
1615 _('[OPTION]... [SOURCE]... DEST'))
1614 def copy(ui, repo, *pats, **opts):
1616 def copy(ui, repo, *pats, **opts):
1615 """mark files as copied for the next commit
1617 """mark files as copied for the next commit
1616
1618
1617 Mark dest as having copies of source files. If dest is a
1619 Mark dest as having copies of source files. If dest is a
1618 directory, copies are put in that directory. If dest is a file,
1620 directory, copies are put in that directory. If dest is a file,
1619 the source must be a single file.
1621 the source must be a single file.
1620
1622
1621 By default, this command copies the contents of files as they
1623 By default, this command copies the contents of files as they
1622 exist in the working directory. If invoked with -A/--after, the
1624 exist in the working directory. If invoked with -A/--after, the
1623 operation is recorded, but no copying is performed.
1625 operation is recorded, but no copying is performed.
1624
1626
1625 This command takes effect with the next commit. To undo a copy
1627 This command takes effect with the next commit. To undo a copy
1626 before that, see :hg:`revert`.
1628 before that, see :hg:`revert`.
1627
1629
1628 Returns 0 on success, 1 if errors are encountered.
1630 Returns 0 on success, 1 if errors are encountered.
1629 """
1631 """
1630 wlock = repo.wlock(False)
1632 wlock = repo.wlock(False)
1631 try:
1633 try:
1632 return cmdutil.copy(ui, repo, pats, opts)
1634 return cmdutil.copy(ui, repo, pats, opts)
1633 finally:
1635 finally:
1634 wlock.release()
1636 wlock.release()
1635
1637
1636 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1638 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1637 def debugancestor(ui, repo, *args):
1639 def debugancestor(ui, repo, *args):
1638 """find the ancestor revision of two revisions in a given index"""
1640 """find the ancestor revision of two revisions in a given index"""
1639 if len(args) == 3:
1641 if len(args) == 3:
1640 index, rev1, rev2 = args
1642 index, rev1, rev2 = args
1641 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1643 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1642 lookup = r.lookup
1644 lookup = r.lookup
1643 elif len(args) == 2:
1645 elif len(args) == 2:
1644 if not repo:
1646 if not repo:
1645 raise util.Abort(_("there is no Mercurial repository here "
1647 raise util.Abort(_("there is no Mercurial repository here "
1646 "(.hg not found)"))
1648 "(.hg not found)"))
1647 rev1, rev2 = args
1649 rev1, rev2 = args
1648 r = repo.changelog
1650 r = repo.changelog
1649 lookup = repo.lookup
1651 lookup = repo.lookup
1650 else:
1652 else:
1651 raise util.Abort(_('either two or three arguments required'))
1653 raise util.Abort(_('either two or three arguments required'))
1652 a = r.ancestor(lookup(rev1), lookup(rev2))
1654 a = r.ancestor(lookup(rev1), lookup(rev2))
1653 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1655 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1654
1656
1655 @command('debugbuilddag',
1657 @command('debugbuilddag',
1656 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1658 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1657 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1659 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1658 ('n', 'new-file', None, _('add new file at each rev'))],
1660 ('n', 'new-file', None, _('add new file at each rev'))],
1659 _('[OPTION]... [TEXT]'))
1661 _('[OPTION]... [TEXT]'))
1660 def debugbuilddag(ui, repo, text=None,
1662 def debugbuilddag(ui, repo, text=None,
1661 mergeable_file=False,
1663 mergeable_file=False,
1662 overwritten_file=False,
1664 overwritten_file=False,
1663 new_file=False):
1665 new_file=False):
1664 """builds a repo with a given DAG from scratch in the current empty repo
1666 """builds a repo with a given DAG from scratch in the current empty repo
1665
1667
1666 The description of the DAG is read from stdin if not given on the
1668 The description of the DAG is read from stdin if not given on the
1667 command line.
1669 command line.
1668
1670
1669 Elements:
1671 Elements:
1670
1672
1671 - "+n" is a linear run of n nodes based on the current default parent
1673 - "+n" is a linear run of n nodes based on the current default parent
1672 - "." is a single node based on the current default parent
1674 - "." is a single node based on the current default parent
1673 - "$" resets the default parent to null (implied at the start);
1675 - "$" resets the default parent to null (implied at the start);
1674 otherwise the default parent is always the last node created
1676 otherwise the default parent is always the last node created
1675 - "<p" sets the default parent to the backref p
1677 - "<p" sets the default parent to the backref p
1676 - "*p" is a fork at parent p, which is a backref
1678 - "*p" is a fork at parent p, which is a backref
1677 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1679 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1678 - "/p2" is a merge of the preceding node and p2
1680 - "/p2" is a merge of the preceding node and p2
1679 - ":tag" defines a local tag for the preceding node
1681 - ":tag" defines a local tag for the preceding node
1680 - "@branch" sets the named branch for subsequent nodes
1682 - "@branch" sets the named branch for subsequent nodes
1681 - "#...\\n" is a comment up to the end of the line
1683 - "#...\\n" is a comment up to the end of the line
1682
1684
1683 Whitespace between the above elements is ignored.
1685 Whitespace between the above elements is ignored.
1684
1686
1685 A backref is either
1687 A backref is either
1686
1688
1687 - a number n, which references the node curr-n, where curr is the current
1689 - a number n, which references the node curr-n, where curr is the current
1688 node, or
1690 node, or
1689 - the name of a local tag you placed earlier using ":tag", or
1691 - the name of a local tag you placed earlier using ":tag", or
1690 - empty to denote the default parent.
1692 - empty to denote the default parent.
1691
1693
1692 All string valued-elements are either strictly alphanumeric, or must
1694 All string valued-elements are either strictly alphanumeric, or must
1693 be enclosed in double quotes ("..."), with "\\" as escape character.
1695 be enclosed in double quotes ("..."), with "\\" as escape character.
1694 """
1696 """
1695
1697
1696 if text is None:
1698 if text is None:
1697 ui.status(_("reading DAG from stdin\n"))
1699 ui.status(_("reading DAG from stdin\n"))
1698 text = ui.fin.read()
1700 text = ui.fin.read()
1699
1701
1700 cl = repo.changelog
1702 cl = repo.changelog
1701 if len(cl) > 0:
1703 if len(cl) > 0:
1702 raise util.Abort(_('repository is not empty'))
1704 raise util.Abort(_('repository is not empty'))
1703
1705
1704 # determine number of revs in DAG
1706 # determine number of revs in DAG
1705 total = 0
1707 total = 0
1706 for type, data in dagparser.parsedag(text):
1708 for type, data in dagparser.parsedag(text):
1707 if type == 'n':
1709 if type == 'n':
1708 total += 1
1710 total += 1
1709
1711
1710 if mergeable_file:
1712 if mergeable_file:
1711 linesperrev = 2
1713 linesperrev = 2
1712 # make a file with k lines per rev
1714 # make a file with k lines per rev
1713 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1715 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1714 initialmergedlines.append("")
1716 initialmergedlines.append("")
1715
1717
1716 tags = []
1718 tags = []
1717
1719
1718 lock = tr = None
1720 lock = tr = None
1719 try:
1721 try:
1720 lock = repo.lock()
1722 lock = repo.lock()
1721 tr = repo.transaction("builddag")
1723 tr = repo.transaction("builddag")
1722
1724
1723 at = -1
1725 at = -1
1724 atbranch = 'default'
1726 atbranch = 'default'
1725 nodeids = []
1727 nodeids = []
1726 id = 0
1728 id = 0
1727 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1729 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1728 for type, data in dagparser.parsedag(text):
1730 for type, data in dagparser.parsedag(text):
1729 if type == 'n':
1731 if type == 'n':
1730 ui.note(('node %s\n' % str(data)))
1732 ui.note(('node %s\n' % str(data)))
1731 id, ps = data
1733 id, ps = data
1732
1734
1733 files = []
1735 files = []
1734 fctxs = {}
1736 fctxs = {}
1735
1737
1736 p2 = None
1738 p2 = None
1737 if mergeable_file:
1739 if mergeable_file:
1738 fn = "mf"
1740 fn = "mf"
1739 p1 = repo[ps[0]]
1741 p1 = repo[ps[0]]
1740 if len(ps) > 1:
1742 if len(ps) > 1:
1741 p2 = repo[ps[1]]
1743 p2 = repo[ps[1]]
1742 pa = p1.ancestor(p2)
1744 pa = p1.ancestor(p2)
1743 base, local, other = [x[fn].data() for x in (pa, p1,
1745 base, local, other = [x[fn].data() for x in (pa, p1,
1744 p2)]
1746 p2)]
1745 m3 = simplemerge.Merge3Text(base, local, other)
1747 m3 = simplemerge.Merge3Text(base, local, other)
1746 ml = [l.strip() for l in m3.merge_lines()]
1748 ml = [l.strip() for l in m3.merge_lines()]
1747 ml.append("")
1749 ml.append("")
1748 elif at > 0:
1750 elif at > 0:
1749 ml = p1[fn].data().split("\n")
1751 ml = p1[fn].data().split("\n")
1750 else:
1752 else:
1751 ml = initialmergedlines
1753 ml = initialmergedlines
1752 ml[id * linesperrev] += " r%i" % id
1754 ml[id * linesperrev] += " r%i" % id
1753 mergedtext = "\n".join(ml)
1755 mergedtext = "\n".join(ml)
1754 files.append(fn)
1756 files.append(fn)
1755 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1757 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1756
1758
1757 if overwritten_file:
1759 if overwritten_file:
1758 fn = "of"
1760 fn = "of"
1759 files.append(fn)
1761 files.append(fn)
1760 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1762 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1761
1763
1762 if new_file:
1764 if new_file:
1763 fn = "nf%i" % id
1765 fn = "nf%i" % id
1764 files.append(fn)
1766 files.append(fn)
1765 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1767 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1766 if len(ps) > 1:
1768 if len(ps) > 1:
1767 if not p2:
1769 if not p2:
1768 p2 = repo[ps[1]]
1770 p2 = repo[ps[1]]
1769 for fn in p2:
1771 for fn in p2:
1770 if fn.startswith("nf"):
1772 if fn.startswith("nf"):
1771 files.append(fn)
1773 files.append(fn)
1772 fctxs[fn] = p2[fn]
1774 fctxs[fn] = p2[fn]
1773
1775
1774 def fctxfn(repo, cx, path):
1776 def fctxfn(repo, cx, path):
1775 return fctxs.get(path)
1777 return fctxs.get(path)
1776
1778
1777 if len(ps) == 0 or ps[0] < 0:
1779 if len(ps) == 0 or ps[0] < 0:
1778 pars = [None, None]
1780 pars = [None, None]
1779 elif len(ps) == 1:
1781 elif len(ps) == 1:
1780 pars = [nodeids[ps[0]], None]
1782 pars = [nodeids[ps[0]], None]
1781 else:
1783 else:
1782 pars = [nodeids[p] for p in ps]
1784 pars = [nodeids[p] for p in ps]
1783 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1785 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1784 date=(id, 0),
1786 date=(id, 0),
1785 user="debugbuilddag",
1787 user="debugbuilddag",
1786 extra={'branch': atbranch})
1788 extra={'branch': atbranch})
1787 nodeid = repo.commitctx(cx)
1789 nodeid = repo.commitctx(cx)
1788 nodeids.append(nodeid)
1790 nodeids.append(nodeid)
1789 at = id
1791 at = id
1790 elif type == 'l':
1792 elif type == 'l':
1791 id, name = data
1793 id, name = data
1792 ui.note(('tag %s\n' % name))
1794 ui.note(('tag %s\n' % name))
1793 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1795 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1794 elif type == 'a':
1796 elif type == 'a':
1795 ui.note(('branch %s\n' % data))
1797 ui.note(('branch %s\n' % data))
1796 atbranch = data
1798 atbranch = data
1797 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1799 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1798 tr.close()
1800 tr.close()
1799
1801
1800 if tags:
1802 if tags:
1801 repo.opener.write("localtags", "".join(tags))
1803 repo.opener.write("localtags", "".join(tags))
1802 finally:
1804 finally:
1803 ui.progress(_('building'), None)
1805 ui.progress(_('building'), None)
1804 release(tr, lock)
1806 release(tr, lock)
1805
1807
1806 @command('debugbundle',
1808 @command('debugbundle',
1807 [('a', 'all', None, _('show all details'))],
1809 [('a', 'all', None, _('show all details'))],
1808 _('FILE'),
1810 _('FILE'),
1809 norepo=True)
1811 norepo=True)
1810 def debugbundle(ui, bundlepath, all=None, **opts):
1812 def debugbundle(ui, bundlepath, all=None, **opts):
1811 """lists the contents of a bundle"""
1813 """lists the contents of a bundle"""
1812 f = hg.openpath(ui, bundlepath)
1814 f = hg.openpath(ui, bundlepath)
1813 try:
1815 try:
1814 gen = exchange.readbundle(ui, f, bundlepath)
1816 gen = exchange.readbundle(ui, f, bundlepath)
1815 if all:
1817 if all:
1816 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1818 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1817
1819
1818 def showchunks(named):
1820 def showchunks(named):
1819 ui.write("\n%s\n" % named)
1821 ui.write("\n%s\n" % named)
1820 chain = None
1822 chain = None
1821 while True:
1823 while True:
1822 chunkdata = gen.deltachunk(chain)
1824 chunkdata = gen.deltachunk(chain)
1823 if not chunkdata:
1825 if not chunkdata:
1824 break
1826 break
1825 node = chunkdata['node']
1827 node = chunkdata['node']
1826 p1 = chunkdata['p1']
1828 p1 = chunkdata['p1']
1827 p2 = chunkdata['p2']
1829 p2 = chunkdata['p2']
1828 cs = chunkdata['cs']
1830 cs = chunkdata['cs']
1829 deltabase = chunkdata['deltabase']
1831 deltabase = chunkdata['deltabase']
1830 delta = chunkdata['delta']
1832 delta = chunkdata['delta']
1831 ui.write("%s %s %s %s %s %s\n" %
1833 ui.write("%s %s %s %s %s %s\n" %
1832 (hex(node), hex(p1), hex(p2),
1834 (hex(node), hex(p1), hex(p2),
1833 hex(cs), hex(deltabase), len(delta)))
1835 hex(cs), hex(deltabase), len(delta)))
1834 chain = node
1836 chain = node
1835
1837
1836 chunkdata = gen.changelogheader()
1838 chunkdata = gen.changelogheader()
1837 showchunks("changelog")
1839 showchunks("changelog")
1838 chunkdata = gen.manifestheader()
1840 chunkdata = gen.manifestheader()
1839 showchunks("manifest")
1841 showchunks("manifest")
1840 while True:
1842 while True:
1841 chunkdata = gen.filelogheader()
1843 chunkdata = gen.filelogheader()
1842 if not chunkdata:
1844 if not chunkdata:
1843 break
1845 break
1844 fname = chunkdata['filename']
1846 fname = chunkdata['filename']
1845 showchunks(fname)
1847 showchunks(fname)
1846 else:
1848 else:
1847 chunkdata = gen.changelogheader()
1849 chunkdata = gen.changelogheader()
1848 chain = None
1850 chain = None
1849 while True:
1851 while True:
1850 chunkdata = gen.deltachunk(chain)
1852 chunkdata = gen.deltachunk(chain)
1851 if not chunkdata:
1853 if not chunkdata:
1852 break
1854 break
1853 node = chunkdata['node']
1855 node = chunkdata['node']
1854 ui.write("%s\n" % hex(node))
1856 ui.write("%s\n" % hex(node))
1855 chain = node
1857 chain = node
1856 finally:
1858 finally:
1857 f.close()
1859 f.close()
1858
1860
1859 @command('debugcheckstate', [], '')
1861 @command('debugcheckstate', [], '')
1860 def debugcheckstate(ui, repo):
1862 def debugcheckstate(ui, repo):
1861 """validate the correctness of the current dirstate"""
1863 """validate the correctness of the current dirstate"""
1862 parent1, parent2 = repo.dirstate.parents()
1864 parent1, parent2 = repo.dirstate.parents()
1863 m1 = repo[parent1].manifest()
1865 m1 = repo[parent1].manifest()
1864 m2 = repo[parent2].manifest()
1866 m2 = repo[parent2].manifest()
1865 errors = 0
1867 errors = 0
1866 for f in repo.dirstate:
1868 for f in repo.dirstate:
1867 state = repo.dirstate[f]
1869 state = repo.dirstate[f]
1868 if state in "nr" and f not in m1:
1870 if state in "nr" and f not in m1:
1869 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1871 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1870 errors += 1
1872 errors += 1
1871 if state in "a" and f in m1:
1873 if state in "a" and f in m1:
1872 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1874 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1873 errors += 1
1875 errors += 1
1874 if state in "m" and f not in m1 and f not in m2:
1876 if state in "m" and f not in m1 and f not in m2:
1875 ui.warn(_("%s in state %s, but not in either manifest\n") %
1877 ui.warn(_("%s in state %s, but not in either manifest\n") %
1876 (f, state))
1878 (f, state))
1877 errors += 1
1879 errors += 1
1878 for f in m1:
1880 for f in m1:
1879 state = repo.dirstate[f]
1881 state = repo.dirstate[f]
1880 if state not in "nrm":
1882 if state not in "nrm":
1881 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1883 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1882 errors += 1
1884 errors += 1
1883 if errors:
1885 if errors:
1884 error = _(".hg/dirstate inconsistent with current parent's manifest")
1886 error = _(".hg/dirstate inconsistent with current parent's manifest")
1885 raise util.Abort(error)
1887 raise util.Abort(error)
1886
1888
1887 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1889 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1888 def debugcommands(ui, cmd='', *args):
1890 def debugcommands(ui, cmd='', *args):
1889 """list all available commands and options"""
1891 """list all available commands and options"""
1890 for cmd, vals in sorted(table.iteritems()):
1892 for cmd, vals in sorted(table.iteritems()):
1891 cmd = cmd.split('|')[0].strip('^')
1893 cmd = cmd.split('|')[0].strip('^')
1892 opts = ', '.join([i[1] for i in vals[1]])
1894 opts = ', '.join([i[1] for i in vals[1]])
1893 ui.write('%s: %s\n' % (cmd, opts))
1895 ui.write('%s: %s\n' % (cmd, opts))
1894
1896
1895 @command('debugcomplete',
1897 @command('debugcomplete',
1896 [('o', 'options', None, _('show the command options'))],
1898 [('o', 'options', None, _('show the command options'))],
1897 _('[-o] CMD'),
1899 _('[-o] CMD'),
1898 norepo=True)
1900 norepo=True)
1899 def debugcomplete(ui, cmd='', **opts):
1901 def debugcomplete(ui, cmd='', **opts):
1900 """returns the completion list associated with the given command"""
1902 """returns the completion list associated with the given command"""
1901
1903
1902 if opts.get('options'):
1904 if opts.get('options'):
1903 options = []
1905 options = []
1904 otables = [globalopts]
1906 otables = [globalopts]
1905 if cmd:
1907 if cmd:
1906 aliases, entry = cmdutil.findcmd(cmd, table, False)
1908 aliases, entry = cmdutil.findcmd(cmd, table, False)
1907 otables.append(entry[1])
1909 otables.append(entry[1])
1908 for t in otables:
1910 for t in otables:
1909 for o in t:
1911 for o in t:
1910 if "(DEPRECATED)" in o[3]:
1912 if "(DEPRECATED)" in o[3]:
1911 continue
1913 continue
1912 if o[0]:
1914 if o[0]:
1913 options.append('-%s' % o[0])
1915 options.append('-%s' % o[0])
1914 options.append('--%s' % o[1])
1916 options.append('--%s' % o[1])
1915 ui.write("%s\n" % "\n".join(options))
1917 ui.write("%s\n" % "\n".join(options))
1916 return
1918 return
1917
1919
1918 cmdlist = cmdutil.findpossible(cmd, table)
1920 cmdlist = cmdutil.findpossible(cmd, table)
1919 if ui.verbose:
1921 if ui.verbose:
1920 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1922 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1921 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1923 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1922
1924
1923 @command('debugdag',
1925 @command('debugdag',
1924 [('t', 'tags', None, _('use tags as labels')),
1926 [('t', 'tags', None, _('use tags as labels')),
1925 ('b', 'branches', None, _('annotate with branch names')),
1927 ('b', 'branches', None, _('annotate with branch names')),
1926 ('', 'dots', None, _('use dots for runs')),
1928 ('', 'dots', None, _('use dots for runs')),
1927 ('s', 'spaces', None, _('separate elements by spaces'))],
1929 ('s', 'spaces', None, _('separate elements by spaces'))],
1928 _('[OPTION]... [FILE [REV]...]'),
1930 _('[OPTION]... [FILE [REV]...]'),
1929 optionalrepo=True)
1931 optionalrepo=True)
1930 def debugdag(ui, repo, file_=None, *revs, **opts):
1932 def debugdag(ui, repo, file_=None, *revs, **opts):
1931 """format the changelog or an index DAG as a concise textual description
1933 """format the changelog or an index DAG as a concise textual description
1932
1934
1933 If you pass a revlog index, the revlog's DAG is emitted. If you list
1935 If you pass a revlog index, the revlog's DAG is emitted. If you list
1934 revision numbers, they get labeled in the output as rN.
1936 revision numbers, they get labeled in the output as rN.
1935
1937
1936 Otherwise, the changelog DAG of the current repo is emitted.
1938 Otherwise, the changelog DAG of the current repo is emitted.
1937 """
1939 """
1938 spaces = opts.get('spaces')
1940 spaces = opts.get('spaces')
1939 dots = opts.get('dots')
1941 dots = opts.get('dots')
1940 if file_:
1942 if file_:
1941 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1943 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1942 revs = set((int(r) for r in revs))
1944 revs = set((int(r) for r in revs))
1943 def events():
1945 def events():
1944 for r in rlog:
1946 for r in rlog:
1945 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1947 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1946 if p != -1))
1948 if p != -1))
1947 if r in revs:
1949 if r in revs:
1948 yield 'l', (r, "r%i" % r)
1950 yield 'l', (r, "r%i" % r)
1949 elif repo:
1951 elif repo:
1950 cl = repo.changelog
1952 cl = repo.changelog
1951 tags = opts.get('tags')
1953 tags = opts.get('tags')
1952 branches = opts.get('branches')
1954 branches = opts.get('branches')
1953 if tags:
1955 if tags:
1954 labels = {}
1956 labels = {}
1955 for l, n in repo.tags().items():
1957 for l, n in repo.tags().items():
1956 labels.setdefault(cl.rev(n), []).append(l)
1958 labels.setdefault(cl.rev(n), []).append(l)
1957 def events():
1959 def events():
1958 b = "default"
1960 b = "default"
1959 for r in cl:
1961 for r in cl:
1960 if branches:
1962 if branches:
1961 newb = cl.read(cl.node(r))[5]['branch']
1963 newb = cl.read(cl.node(r))[5]['branch']
1962 if newb != b:
1964 if newb != b:
1963 yield 'a', newb
1965 yield 'a', newb
1964 b = newb
1966 b = newb
1965 yield 'n', (r, list(p for p in cl.parentrevs(r)
1967 yield 'n', (r, list(p for p in cl.parentrevs(r)
1966 if p != -1))
1968 if p != -1))
1967 if tags:
1969 if tags:
1968 ls = labels.get(r)
1970 ls = labels.get(r)
1969 if ls:
1971 if ls:
1970 for l in ls:
1972 for l in ls:
1971 yield 'l', (r, l)
1973 yield 'l', (r, l)
1972 else:
1974 else:
1973 raise util.Abort(_('need repo for changelog dag'))
1975 raise util.Abort(_('need repo for changelog dag'))
1974
1976
1975 for line in dagparser.dagtextlines(events(),
1977 for line in dagparser.dagtextlines(events(),
1976 addspaces=spaces,
1978 addspaces=spaces,
1977 wraplabels=True,
1979 wraplabels=True,
1978 wrapannotations=True,
1980 wrapannotations=True,
1979 wrapnonlinear=dots,
1981 wrapnonlinear=dots,
1980 usedots=dots,
1982 usedots=dots,
1981 maxlinewidth=70):
1983 maxlinewidth=70):
1982 ui.write(line)
1984 ui.write(line)
1983 ui.write("\n")
1985 ui.write("\n")
1984
1986
1985 @command('debugdata',
1987 @command('debugdata',
1986 [('c', 'changelog', False, _('open changelog')),
1988 [('c', 'changelog', False, _('open changelog')),
1987 ('m', 'manifest', False, _('open manifest'))],
1989 ('m', 'manifest', False, _('open manifest'))],
1988 _('-c|-m|FILE REV'))
1990 _('-c|-m|FILE REV'))
1989 def debugdata(ui, repo, file_, rev=None, **opts):
1991 def debugdata(ui, repo, file_, rev=None, **opts):
1990 """dump the contents of a data file revision"""
1992 """dump the contents of a data file revision"""
1991 if opts.get('changelog') or opts.get('manifest'):
1993 if opts.get('changelog') or opts.get('manifest'):
1992 file_, rev = None, file_
1994 file_, rev = None, file_
1993 elif rev is None:
1995 elif rev is None:
1994 raise error.CommandError('debugdata', _('invalid arguments'))
1996 raise error.CommandError('debugdata', _('invalid arguments'))
1995 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1997 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1996 try:
1998 try:
1997 ui.write(r.revision(r.lookup(rev)))
1999 ui.write(r.revision(r.lookup(rev)))
1998 except KeyError:
2000 except KeyError:
1999 raise util.Abort(_('invalid revision identifier %s') % rev)
2001 raise util.Abort(_('invalid revision identifier %s') % rev)
2000
2002
2001 @command('debugdate',
2003 @command('debugdate',
2002 [('e', 'extended', None, _('try extended date formats'))],
2004 [('e', 'extended', None, _('try extended date formats'))],
2003 _('[-e] DATE [RANGE]'),
2005 _('[-e] DATE [RANGE]'),
2004 norepo=True, optionalrepo=True)
2006 norepo=True, optionalrepo=True)
2005 def debugdate(ui, date, range=None, **opts):
2007 def debugdate(ui, date, range=None, **opts):
2006 """parse and display a date"""
2008 """parse and display a date"""
2007 if opts["extended"]:
2009 if opts["extended"]:
2008 d = util.parsedate(date, util.extendeddateformats)
2010 d = util.parsedate(date, util.extendeddateformats)
2009 else:
2011 else:
2010 d = util.parsedate(date)
2012 d = util.parsedate(date)
2011 ui.write(("internal: %s %s\n") % d)
2013 ui.write(("internal: %s %s\n") % d)
2012 ui.write(("standard: %s\n") % util.datestr(d))
2014 ui.write(("standard: %s\n") % util.datestr(d))
2013 if range:
2015 if range:
2014 m = util.matchdate(range)
2016 m = util.matchdate(range)
2015 ui.write(("match: %s\n") % m(d[0]))
2017 ui.write(("match: %s\n") % m(d[0]))
2016
2018
2017 @command('debugdiscovery',
2019 @command('debugdiscovery',
2018 [('', 'old', None, _('use old-style discovery')),
2020 [('', 'old', None, _('use old-style discovery')),
2019 ('', 'nonheads', None,
2021 ('', 'nonheads', None,
2020 _('use old-style discovery with non-heads included')),
2022 _('use old-style discovery with non-heads included')),
2021 ] + remoteopts,
2023 ] + remoteopts,
2022 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2024 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2023 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2025 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2024 """runs the changeset discovery protocol in isolation"""
2026 """runs the changeset discovery protocol in isolation"""
2025 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2027 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2026 opts.get('branch'))
2028 opts.get('branch'))
2027 remote = hg.peer(repo, opts, remoteurl)
2029 remote = hg.peer(repo, opts, remoteurl)
2028 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2030 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2029
2031
2030 # make sure tests are repeatable
2032 # make sure tests are repeatable
2031 random.seed(12323)
2033 random.seed(12323)
2032
2034
2033 def doit(localheads, remoteheads, remote=remote):
2035 def doit(localheads, remoteheads, remote=remote):
2034 if opts.get('old'):
2036 if opts.get('old'):
2035 if localheads:
2037 if localheads:
2036 raise util.Abort('cannot use localheads with old style '
2038 raise util.Abort('cannot use localheads with old style '
2037 'discovery')
2039 'discovery')
2038 if not util.safehasattr(remote, 'branches'):
2040 if not util.safehasattr(remote, 'branches'):
2039 # enable in-client legacy support
2041 # enable in-client legacy support
2040 remote = localrepo.locallegacypeer(remote.local())
2042 remote = localrepo.locallegacypeer(remote.local())
2041 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2043 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2042 force=True)
2044 force=True)
2043 common = set(common)
2045 common = set(common)
2044 if not opts.get('nonheads'):
2046 if not opts.get('nonheads'):
2045 ui.write(("unpruned common: %s\n") %
2047 ui.write(("unpruned common: %s\n") %
2046 " ".join(sorted(short(n) for n in common)))
2048 " ".join(sorted(short(n) for n in common)))
2047 dag = dagutil.revlogdag(repo.changelog)
2049 dag = dagutil.revlogdag(repo.changelog)
2048 all = dag.ancestorset(dag.internalizeall(common))
2050 all = dag.ancestorset(dag.internalizeall(common))
2049 common = dag.externalizeall(dag.headsetofconnecteds(all))
2051 common = dag.externalizeall(dag.headsetofconnecteds(all))
2050 else:
2052 else:
2051 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2053 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2052 common = set(common)
2054 common = set(common)
2053 rheads = set(hds)
2055 rheads = set(hds)
2054 lheads = set(repo.heads())
2056 lheads = set(repo.heads())
2055 ui.write(("common heads: %s\n") %
2057 ui.write(("common heads: %s\n") %
2056 " ".join(sorted(short(n) for n in common)))
2058 " ".join(sorted(short(n) for n in common)))
2057 if lheads <= common:
2059 if lheads <= common:
2058 ui.write(("local is subset\n"))
2060 ui.write(("local is subset\n"))
2059 elif rheads <= common:
2061 elif rheads <= common:
2060 ui.write(("remote is subset\n"))
2062 ui.write(("remote is subset\n"))
2061
2063
2062 serverlogs = opts.get('serverlog')
2064 serverlogs = opts.get('serverlog')
2063 if serverlogs:
2065 if serverlogs:
2064 for filename in serverlogs:
2066 for filename in serverlogs:
2065 logfile = open(filename, 'r')
2067 logfile = open(filename, 'r')
2066 try:
2068 try:
2067 line = logfile.readline()
2069 line = logfile.readline()
2068 while line:
2070 while line:
2069 parts = line.strip().split(';')
2071 parts = line.strip().split(';')
2070 op = parts[1]
2072 op = parts[1]
2071 if op == 'cg':
2073 if op == 'cg':
2072 pass
2074 pass
2073 elif op == 'cgss':
2075 elif op == 'cgss':
2074 doit(parts[2].split(' '), parts[3].split(' '))
2076 doit(parts[2].split(' '), parts[3].split(' '))
2075 elif op == 'unb':
2077 elif op == 'unb':
2076 doit(parts[3].split(' '), parts[2].split(' '))
2078 doit(parts[3].split(' '), parts[2].split(' '))
2077 line = logfile.readline()
2079 line = logfile.readline()
2078 finally:
2080 finally:
2079 logfile.close()
2081 logfile.close()
2080
2082
2081 else:
2083 else:
2082 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2084 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2083 opts.get('remote_head'))
2085 opts.get('remote_head'))
2084 localrevs = opts.get('local_head')
2086 localrevs = opts.get('local_head')
2085 doit(localrevs, remoterevs)
2087 doit(localrevs, remoterevs)
2086
2088
2087 @command('debugfileset',
2089 @command('debugfileset',
2088 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2090 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2089 _('[-r REV] FILESPEC'))
2091 _('[-r REV] FILESPEC'))
2090 def debugfileset(ui, repo, expr, **opts):
2092 def debugfileset(ui, repo, expr, **opts):
2091 '''parse and apply a fileset specification'''
2093 '''parse and apply a fileset specification'''
2092 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2094 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2093 if ui.verbose:
2095 if ui.verbose:
2094 tree = fileset.parse(expr)[0]
2096 tree = fileset.parse(expr)[0]
2095 ui.note(tree, "\n")
2097 ui.note(tree, "\n")
2096
2098
2097 for f in ctx.getfileset(expr):
2099 for f in ctx.getfileset(expr):
2098 ui.write("%s\n" % f)
2100 ui.write("%s\n" % f)
2099
2101
2100 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2102 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2101 def debugfsinfo(ui, path="."):
2103 def debugfsinfo(ui, path="."):
2102 """show information detected about current filesystem"""
2104 """show information detected about current filesystem"""
2103 util.writefile('.debugfsinfo', '')
2105 util.writefile('.debugfsinfo', '')
2104 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2106 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2105 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2107 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2106 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2108 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2107 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2109 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2108 and 'yes' or 'no'))
2110 and 'yes' or 'no'))
2109 os.unlink('.debugfsinfo')
2111 os.unlink('.debugfsinfo')
2110
2112
2111 @command('debuggetbundle',
2113 @command('debuggetbundle',
2112 [('H', 'head', [], _('id of head node'), _('ID')),
2114 [('H', 'head', [], _('id of head node'), _('ID')),
2113 ('C', 'common', [], _('id of common node'), _('ID')),
2115 ('C', 'common', [], _('id of common node'), _('ID')),
2114 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2116 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2115 _('REPO FILE [-H|-C ID]...'),
2117 _('REPO FILE [-H|-C ID]...'),
2116 norepo=True)
2118 norepo=True)
2117 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2119 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2118 """retrieves a bundle from a repo
2120 """retrieves a bundle from a repo
2119
2121
2120 Every ID must be a full-length hex node id string. Saves the bundle to the
2122 Every ID must be a full-length hex node id string. Saves the bundle to the
2121 given file.
2123 given file.
2122 """
2124 """
2123 repo = hg.peer(ui, opts, repopath)
2125 repo = hg.peer(ui, opts, repopath)
2124 if not repo.capable('getbundle'):
2126 if not repo.capable('getbundle'):
2125 raise util.Abort("getbundle() not supported by target repository")
2127 raise util.Abort("getbundle() not supported by target repository")
2126 args = {}
2128 args = {}
2127 if common:
2129 if common:
2128 args['common'] = [bin(s) for s in common]
2130 args['common'] = [bin(s) for s in common]
2129 if head:
2131 if head:
2130 args['heads'] = [bin(s) for s in head]
2132 args['heads'] = [bin(s) for s in head]
2131 # TODO: get desired bundlecaps from command line.
2133 # TODO: get desired bundlecaps from command line.
2132 args['bundlecaps'] = None
2134 args['bundlecaps'] = None
2133 bundle = repo.getbundle('debug', **args)
2135 bundle = repo.getbundle('debug', **args)
2134
2136
2135 bundletype = opts.get('type', 'bzip2').lower()
2137 bundletype = opts.get('type', 'bzip2').lower()
2136 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2138 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2137 bundletype = btypes.get(bundletype)
2139 bundletype = btypes.get(bundletype)
2138 if bundletype not in changegroup.bundletypes:
2140 if bundletype not in changegroup.bundletypes:
2139 raise util.Abort(_('unknown bundle type specified with --type'))
2141 raise util.Abort(_('unknown bundle type specified with --type'))
2140 changegroup.writebundle(bundle, bundlepath, bundletype)
2142 changegroup.writebundle(bundle, bundlepath, bundletype)
2141
2143
2142 @command('debugignore', [], '')
2144 @command('debugignore', [], '')
2143 def debugignore(ui, repo, *values, **opts):
2145 def debugignore(ui, repo, *values, **opts):
2144 """display the combined ignore pattern"""
2146 """display the combined ignore pattern"""
2145 ignore = repo.dirstate._ignore
2147 ignore = repo.dirstate._ignore
2146 includepat = getattr(ignore, 'includepat', None)
2148 includepat = getattr(ignore, 'includepat', None)
2147 if includepat is not None:
2149 if includepat is not None:
2148 ui.write("%s\n" % includepat)
2150 ui.write("%s\n" % includepat)
2149 else:
2151 else:
2150 raise util.Abort(_("no ignore patterns found"))
2152 raise util.Abort(_("no ignore patterns found"))
2151
2153
2152 @command('debugindex',
2154 @command('debugindex',
2153 [('c', 'changelog', False, _('open changelog')),
2155 [('c', 'changelog', False, _('open changelog')),
2154 ('m', 'manifest', False, _('open manifest')),
2156 ('m', 'manifest', False, _('open manifest')),
2155 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2157 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2156 _('[-f FORMAT] -c|-m|FILE'),
2158 _('[-f FORMAT] -c|-m|FILE'),
2157 optionalrepo=True)
2159 optionalrepo=True)
2158 def debugindex(ui, repo, file_=None, **opts):
2160 def debugindex(ui, repo, file_=None, **opts):
2159 """dump the contents of an index file"""
2161 """dump the contents of an index file"""
2160 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2162 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2161 format = opts.get('format', 0)
2163 format = opts.get('format', 0)
2162 if format not in (0, 1):
2164 if format not in (0, 1):
2163 raise util.Abort(_("unknown format %d") % format)
2165 raise util.Abort(_("unknown format %d") % format)
2164
2166
2165 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2167 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2166 if generaldelta:
2168 if generaldelta:
2167 basehdr = ' delta'
2169 basehdr = ' delta'
2168 else:
2170 else:
2169 basehdr = ' base'
2171 basehdr = ' base'
2170
2172
2171 if format == 0:
2173 if format == 0:
2172 ui.write(" rev offset length " + basehdr + " linkrev"
2174 ui.write(" rev offset length " + basehdr + " linkrev"
2173 " nodeid p1 p2\n")
2175 " nodeid p1 p2\n")
2174 elif format == 1:
2176 elif format == 1:
2175 ui.write(" rev flag offset length"
2177 ui.write(" rev flag offset length"
2176 " size " + basehdr + " link p1 p2"
2178 " size " + basehdr + " link p1 p2"
2177 " nodeid\n")
2179 " nodeid\n")
2178
2180
2179 for i in r:
2181 for i in r:
2180 node = r.node(i)
2182 node = r.node(i)
2181 if generaldelta:
2183 if generaldelta:
2182 base = r.deltaparent(i)
2184 base = r.deltaparent(i)
2183 else:
2185 else:
2184 base = r.chainbase(i)
2186 base = r.chainbase(i)
2185 if format == 0:
2187 if format == 0:
2186 try:
2188 try:
2187 pp = r.parents(node)
2189 pp = r.parents(node)
2188 except Exception:
2190 except Exception:
2189 pp = [nullid, nullid]
2191 pp = [nullid, nullid]
2190 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2192 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2191 i, r.start(i), r.length(i), base, r.linkrev(i),
2193 i, r.start(i), r.length(i), base, r.linkrev(i),
2192 short(node), short(pp[0]), short(pp[1])))
2194 short(node), short(pp[0]), short(pp[1])))
2193 elif format == 1:
2195 elif format == 1:
2194 pr = r.parentrevs(i)
2196 pr = r.parentrevs(i)
2195 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2197 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2196 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2198 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2197 base, r.linkrev(i), pr[0], pr[1], short(node)))
2199 base, r.linkrev(i), pr[0], pr[1], short(node)))
2198
2200
2199 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2201 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2200 def debugindexdot(ui, repo, file_):
2202 def debugindexdot(ui, repo, file_):
2201 """dump an index DAG as a graphviz dot file"""
2203 """dump an index DAG as a graphviz dot file"""
2202 r = None
2204 r = None
2203 if repo:
2205 if repo:
2204 filelog = repo.file(file_)
2206 filelog = repo.file(file_)
2205 if len(filelog):
2207 if len(filelog):
2206 r = filelog
2208 r = filelog
2207 if not r:
2209 if not r:
2208 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2210 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2209 ui.write(("digraph G {\n"))
2211 ui.write(("digraph G {\n"))
2210 for i in r:
2212 for i in r:
2211 node = r.node(i)
2213 node = r.node(i)
2212 pp = r.parents(node)
2214 pp = r.parents(node)
2213 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2215 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2214 if pp[1] != nullid:
2216 if pp[1] != nullid:
2215 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2217 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2216 ui.write("}\n")
2218 ui.write("}\n")
2217
2219
2218 @command('debuginstall', [], '', norepo=True)
2220 @command('debuginstall', [], '', norepo=True)
2219 def debuginstall(ui):
2221 def debuginstall(ui):
2220 '''test Mercurial installation
2222 '''test Mercurial installation
2221
2223
2222 Returns 0 on success.
2224 Returns 0 on success.
2223 '''
2225 '''
2224
2226
2225 def writetemp(contents):
2227 def writetemp(contents):
2226 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2228 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2227 f = os.fdopen(fd, "wb")
2229 f = os.fdopen(fd, "wb")
2228 f.write(contents)
2230 f.write(contents)
2229 f.close()
2231 f.close()
2230 return name
2232 return name
2231
2233
2232 problems = 0
2234 problems = 0
2233
2235
2234 # encoding
2236 # encoding
2235 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2237 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2236 try:
2238 try:
2237 encoding.fromlocal("test")
2239 encoding.fromlocal("test")
2238 except util.Abort, inst:
2240 except util.Abort, inst:
2239 ui.write(" %s\n" % inst)
2241 ui.write(" %s\n" % inst)
2240 ui.write(_(" (check that your locale is properly set)\n"))
2242 ui.write(_(" (check that your locale is properly set)\n"))
2241 problems += 1
2243 problems += 1
2242
2244
2243 # Python
2245 # Python
2244 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2246 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2245 ui.status(_("checking Python version (%s)\n")
2247 ui.status(_("checking Python version (%s)\n")
2246 % ("%s.%s.%s" % sys.version_info[:3]))
2248 % ("%s.%s.%s" % sys.version_info[:3]))
2247 ui.status(_("checking Python lib (%s)...\n")
2249 ui.status(_("checking Python lib (%s)...\n")
2248 % os.path.dirname(os.__file__))
2250 % os.path.dirname(os.__file__))
2249
2251
2250 # compiled modules
2252 # compiled modules
2251 ui.status(_("checking installed modules (%s)...\n")
2253 ui.status(_("checking installed modules (%s)...\n")
2252 % os.path.dirname(__file__))
2254 % os.path.dirname(__file__))
2253 try:
2255 try:
2254 import bdiff, mpatch, base85, osutil
2256 import bdiff, mpatch, base85, osutil
2255 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2257 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2256 except Exception, inst:
2258 except Exception, inst:
2257 ui.write(" %s\n" % inst)
2259 ui.write(" %s\n" % inst)
2258 ui.write(_(" One or more extensions could not be found"))
2260 ui.write(_(" One or more extensions could not be found"))
2259 ui.write(_(" (check that you compiled the extensions)\n"))
2261 ui.write(_(" (check that you compiled the extensions)\n"))
2260 problems += 1
2262 problems += 1
2261
2263
2262 # templates
2264 # templates
2263 import templater
2265 import templater
2264 p = templater.templatepaths()
2266 p = templater.templatepaths()
2265 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2267 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2266 if p:
2268 if p:
2267 m = templater.templatepath("map-cmdline.default")
2269 m = templater.templatepath("map-cmdline.default")
2268 if m:
2270 if m:
2269 # template found, check if it is working
2271 # template found, check if it is working
2270 try:
2272 try:
2271 templater.templater(m)
2273 templater.templater(m)
2272 except Exception, inst:
2274 except Exception, inst:
2273 ui.write(" %s\n" % inst)
2275 ui.write(" %s\n" % inst)
2274 p = None
2276 p = None
2275 else:
2277 else:
2276 ui.write(_(" template 'default' not found\n"))
2278 ui.write(_(" template 'default' not found\n"))
2277 p = None
2279 p = None
2278 else:
2280 else:
2279 ui.write(_(" no template directories found\n"))
2281 ui.write(_(" no template directories found\n"))
2280 if not p:
2282 if not p:
2281 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2283 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2282 problems += 1
2284 problems += 1
2283
2285
2284 # editor
2286 # editor
2285 ui.status(_("checking commit editor...\n"))
2287 ui.status(_("checking commit editor...\n"))
2286 editor = ui.geteditor()
2288 editor = ui.geteditor()
2287 cmdpath = util.findexe(shlex.split(editor)[0])
2289 cmdpath = util.findexe(shlex.split(editor)[0])
2288 if not cmdpath:
2290 if not cmdpath:
2289 if editor == 'vi':
2291 if editor == 'vi':
2290 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2292 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2291 ui.write(_(" (specify a commit editor in your configuration"
2293 ui.write(_(" (specify a commit editor in your configuration"
2292 " file)\n"))
2294 " file)\n"))
2293 else:
2295 else:
2294 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2296 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2295 ui.write(_(" (specify a commit editor in your configuration"
2297 ui.write(_(" (specify a commit editor in your configuration"
2296 " file)\n"))
2298 " file)\n"))
2297 problems += 1
2299 problems += 1
2298
2300
2299 # check username
2301 # check username
2300 ui.status(_("checking username...\n"))
2302 ui.status(_("checking username...\n"))
2301 try:
2303 try:
2302 ui.username()
2304 ui.username()
2303 except util.Abort, e:
2305 except util.Abort, e:
2304 ui.write(" %s\n" % e)
2306 ui.write(" %s\n" % e)
2305 ui.write(_(" (specify a username in your configuration file)\n"))
2307 ui.write(_(" (specify a username in your configuration file)\n"))
2306 problems += 1
2308 problems += 1
2307
2309
2308 if not problems:
2310 if not problems:
2309 ui.status(_("no problems detected\n"))
2311 ui.status(_("no problems detected\n"))
2310 else:
2312 else:
2311 ui.write(_("%s problems detected,"
2313 ui.write(_("%s problems detected,"
2312 " please check your install!\n") % problems)
2314 " please check your install!\n") % problems)
2313
2315
2314 return problems
2316 return problems
2315
2317
2316 @command('debugknown', [], _('REPO ID...'), norepo=True)
2318 @command('debugknown', [], _('REPO ID...'), norepo=True)
2317 def debugknown(ui, repopath, *ids, **opts):
2319 def debugknown(ui, repopath, *ids, **opts):
2318 """test whether node ids are known to a repo
2320 """test whether node ids are known to a repo
2319
2321
2320 Every ID must be a full-length hex node id string. Returns a list of 0s
2322 Every ID must be a full-length hex node id string. Returns a list of 0s
2321 and 1s indicating unknown/known.
2323 and 1s indicating unknown/known.
2322 """
2324 """
2323 repo = hg.peer(ui, opts, repopath)
2325 repo = hg.peer(ui, opts, repopath)
2324 if not repo.capable('known'):
2326 if not repo.capable('known'):
2325 raise util.Abort("known() not supported by target repository")
2327 raise util.Abort("known() not supported by target repository")
2326 flags = repo.known([bin(s) for s in ids])
2328 flags = repo.known([bin(s) for s in ids])
2327 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2329 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2328
2330
2329 @command('debuglabelcomplete', [], _('LABEL...'))
2331 @command('debuglabelcomplete', [], _('LABEL...'))
2330 def debuglabelcomplete(ui, repo, *args):
2332 def debuglabelcomplete(ui, repo, *args):
2331 '''complete "labels" - tags, open branch names, bookmark names'''
2333 '''complete "labels" - tags, open branch names, bookmark names'''
2332
2334
2333 labels = set()
2335 labels = set()
2334 labels.update(t[0] for t in repo.tagslist())
2336 labels.update(t[0] for t in repo.tagslist())
2335 labels.update(repo._bookmarks.keys())
2337 labels.update(repo._bookmarks.keys())
2336 labels.update(tag for (tag, heads, tip, closed)
2338 labels.update(tag for (tag, heads, tip, closed)
2337 in repo.branchmap().iterbranches() if not closed)
2339 in repo.branchmap().iterbranches() if not closed)
2338 completions = set()
2340 completions = set()
2339 if not args:
2341 if not args:
2340 args = ['']
2342 args = ['']
2341 for a in args:
2343 for a in args:
2342 completions.update(l for l in labels if l.startswith(a))
2344 completions.update(l for l in labels if l.startswith(a))
2343 ui.write('\n'.join(sorted(completions)))
2345 ui.write('\n'.join(sorted(completions)))
2344 ui.write('\n')
2346 ui.write('\n')
2345
2347
2346 @command('debuglocks',
2348 @command('debuglocks',
2347 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2349 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2348 ('W', 'force-wlock', None,
2350 ('W', 'force-wlock', None,
2349 _('free the working state lock (DANGEROUS)'))],
2351 _('free the working state lock (DANGEROUS)'))],
2350 _(''))
2352 _(''))
2351 def debuglocks(ui, repo, **opts):
2353 def debuglocks(ui, repo, **opts):
2352 """show or modify state of locks
2354 """show or modify state of locks
2353
2355
2354 By default, this command will show which locks are held. This
2356 By default, this command will show which locks are held. This
2355 includes the user and process holding the lock, the amount of time
2357 includes the user and process holding the lock, the amount of time
2356 the lock has been held, and the machine name where the process is
2358 the lock has been held, and the machine name where the process is
2357 running if it's not local.
2359 running if it's not local.
2358
2360
2359 Locks protect the integrity of Mercurial's data, so should be
2361 Locks protect the integrity of Mercurial's data, so should be
2360 treated with care. System crashes or other interruptions may cause
2362 treated with care. System crashes or other interruptions may cause
2361 locks to not be properly released, though Mercurial will usually
2363 locks to not be properly released, though Mercurial will usually
2362 detect and remove such stale locks automatically.
2364 detect and remove such stale locks automatically.
2363
2365
2364 However, detecting stale locks may not always be possible (for
2366 However, detecting stale locks may not always be possible (for
2365 instance, on a shared filesystem). Removing locks may also be
2367 instance, on a shared filesystem). Removing locks may also be
2366 blocked by filesystem permissions.
2368 blocked by filesystem permissions.
2367
2369
2368 Returns 0 if no locks are held.
2370 Returns 0 if no locks are held.
2369
2371
2370 """
2372 """
2371
2373
2372 if opts.get('force_lock'):
2374 if opts.get('force_lock'):
2373 repo.svfs.unlink('lock')
2375 repo.svfs.unlink('lock')
2374 if opts.get('force_wlock'):
2376 if opts.get('force_wlock'):
2375 repo.vfs.unlink('wlock')
2377 repo.vfs.unlink('wlock')
2376 if opts.get('force_lock') or opts.get('force_lock'):
2378 if opts.get('force_lock') or opts.get('force_lock'):
2377 return 0
2379 return 0
2378
2380
2379 now = time.time()
2381 now = time.time()
2380 held = 0
2382 held = 0
2381
2383
2382 def report(vfs, name, method):
2384 def report(vfs, name, method):
2383 # this causes stale locks to get reaped for more accurate reporting
2385 # this causes stale locks to get reaped for more accurate reporting
2384 try:
2386 try:
2385 l = method(False)
2387 l = method(False)
2386 except error.LockHeld:
2388 except error.LockHeld:
2387 l = None
2389 l = None
2388
2390
2389 if l:
2391 if l:
2390 l.release()
2392 l.release()
2391 else:
2393 else:
2392 try:
2394 try:
2393 stat = repo.svfs.lstat(name)
2395 stat = repo.svfs.lstat(name)
2394 age = now - stat.st_mtime
2396 age = now - stat.st_mtime
2395 user = util.username(stat.st_uid)
2397 user = util.username(stat.st_uid)
2396 locker = vfs.readlock(name)
2398 locker = vfs.readlock(name)
2397 if ":" in locker:
2399 if ":" in locker:
2398 host, pid = locker.split(':')
2400 host, pid = locker.split(':')
2399 if host == socket.gethostname():
2401 if host == socket.gethostname():
2400 locker = 'user %s, process %s' % (user, pid)
2402 locker = 'user %s, process %s' % (user, pid)
2401 else:
2403 else:
2402 locker = 'user %s, process %s, host %s' \
2404 locker = 'user %s, process %s, host %s' \
2403 % (user, pid, host)
2405 % (user, pid, host)
2404 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2406 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2405 return 1
2407 return 1
2406 except OSError, e:
2408 except OSError, e:
2407 if e.errno != errno.ENOENT:
2409 if e.errno != errno.ENOENT:
2408 raise
2410 raise
2409
2411
2410 ui.write("%-6s free\n" % (name + ":"))
2412 ui.write("%-6s free\n" % (name + ":"))
2411 return 0
2413 return 0
2412
2414
2413 held += report(repo.svfs, "lock", repo.lock)
2415 held += report(repo.svfs, "lock", repo.lock)
2414 held += report(repo.vfs, "wlock", repo.wlock)
2416 held += report(repo.vfs, "wlock", repo.wlock)
2415
2417
2416 return held
2418 return held
2417
2419
2418 @command('debugobsolete',
2420 @command('debugobsolete',
2419 [('', 'flags', 0, _('markers flag')),
2421 [('', 'flags', 0, _('markers flag')),
2420 ('', 'record-parents', False,
2422 ('', 'record-parents', False,
2421 _('record parent information for the precursor')),
2423 _('record parent information for the precursor')),
2422 ('r', 'rev', [], _('display markers relevant to REV')),
2424 ('r', 'rev', [], _('display markers relevant to REV')),
2423 ] + commitopts2,
2425 ] + commitopts2,
2424 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2426 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2425 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2427 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2426 """create arbitrary obsolete marker
2428 """create arbitrary obsolete marker
2427
2429
2428 With no arguments, displays the list of obsolescence markers."""
2430 With no arguments, displays the list of obsolescence markers."""
2429
2431
2430 def parsenodeid(s):
2432 def parsenodeid(s):
2431 try:
2433 try:
2432 # We do not use revsingle/revrange functions here to accept
2434 # We do not use revsingle/revrange functions here to accept
2433 # arbitrary node identifiers, possibly not present in the
2435 # arbitrary node identifiers, possibly not present in the
2434 # local repository.
2436 # local repository.
2435 n = bin(s)
2437 n = bin(s)
2436 if len(n) != len(nullid):
2438 if len(n) != len(nullid):
2437 raise TypeError()
2439 raise TypeError()
2438 return n
2440 return n
2439 except TypeError:
2441 except TypeError:
2440 raise util.Abort('changeset references must be full hexadecimal '
2442 raise util.Abort('changeset references must be full hexadecimal '
2441 'node identifiers')
2443 'node identifiers')
2442
2444
2443 if precursor is not None:
2445 if precursor is not None:
2444 if opts['rev']:
2446 if opts['rev']:
2445 raise util.Abort('cannot select revision when creating marker')
2447 raise util.Abort('cannot select revision when creating marker')
2446 metadata = {}
2448 metadata = {}
2447 metadata['user'] = opts['user'] or ui.username()
2449 metadata['user'] = opts['user'] or ui.username()
2448 succs = tuple(parsenodeid(succ) for succ in successors)
2450 succs = tuple(parsenodeid(succ) for succ in successors)
2449 l = repo.lock()
2451 l = repo.lock()
2450 try:
2452 try:
2451 tr = repo.transaction('debugobsolete')
2453 tr = repo.transaction('debugobsolete')
2452 try:
2454 try:
2453 try:
2455 try:
2454 date = opts.get('date')
2456 date = opts.get('date')
2455 if date:
2457 if date:
2456 date = util.parsedate(date)
2458 date = util.parsedate(date)
2457 else:
2459 else:
2458 date = None
2460 date = None
2459 prec = parsenodeid(precursor)
2461 prec = parsenodeid(precursor)
2460 parents = None
2462 parents = None
2461 if opts['record_parents']:
2463 if opts['record_parents']:
2462 if prec not in repo.unfiltered():
2464 if prec not in repo.unfiltered():
2463 raise util.Abort('cannot used --record-parents on '
2465 raise util.Abort('cannot used --record-parents on '
2464 'unknown changesets')
2466 'unknown changesets')
2465 parents = repo.unfiltered()[prec].parents()
2467 parents = repo.unfiltered()[prec].parents()
2466 parents = tuple(p.node() for p in parents)
2468 parents = tuple(p.node() for p in parents)
2467 repo.obsstore.create(tr, prec, succs, opts['flags'],
2469 repo.obsstore.create(tr, prec, succs, opts['flags'],
2468 parents=parents, date=date,
2470 parents=parents, date=date,
2469 metadata=metadata)
2471 metadata=metadata)
2470 tr.close()
2472 tr.close()
2471 except ValueError, exc:
2473 except ValueError, exc:
2472 raise util.Abort(_('bad obsmarker input: %s') % exc)
2474 raise util.Abort(_('bad obsmarker input: %s') % exc)
2473 finally:
2475 finally:
2474 tr.release()
2476 tr.release()
2475 finally:
2477 finally:
2476 l.release()
2478 l.release()
2477 else:
2479 else:
2478 if opts['rev']:
2480 if opts['rev']:
2479 revs = scmutil.revrange(repo, opts['rev'])
2481 revs = scmutil.revrange(repo, opts['rev'])
2480 nodes = [repo[r].node() for r in revs]
2482 nodes = [repo[r].node() for r in revs]
2481 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2483 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2482 markers.sort(key=lambda x: x._data)
2484 markers.sort(key=lambda x: x._data)
2483 else:
2485 else:
2484 markers = obsolete.getmarkers(repo)
2486 markers = obsolete.getmarkers(repo)
2485
2487
2486 for m in markers:
2488 for m in markers:
2487 cmdutil.showmarker(ui, m)
2489 cmdutil.showmarker(ui, m)
2488
2490
2489 @command('debugpathcomplete',
2491 @command('debugpathcomplete',
2490 [('f', 'full', None, _('complete an entire path')),
2492 [('f', 'full', None, _('complete an entire path')),
2491 ('n', 'normal', None, _('show only normal files')),
2493 ('n', 'normal', None, _('show only normal files')),
2492 ('a', 'added', None, _('show only added files')),
2494 ('a', 'added', None, _('show only added files')),
2493 ('r', 'removed', None, _('show only removed files'))],
2495 ('r', 'removed', None, _('show only removed files'))],
2494 _('FILESPEC...'))
2496 _('FILESPEC...'))
2495 def debugpathcomplete(ui, repo, *specs, **opts):
2497 def debugpathcomplete(ui, repo, *specs, **opts):
2496 '''complete part or all of a tracked path
2498 '''complete part or all of a tracked path
2497
2499
2498 This command supports shells that offer path name completion. It
2500 This command supports shells that offer path name completion. It
2499 currently completes only files already known to the dirstate.
2501 currently completes only files already known to the dirstate.
2500
2502
2501 Completion extends only to the next path segment unless
2503 Completion extends only to the next path segment unless
2502 --full is specified, in which case entire paths are used.'''
2504 --full is specified, in which case entire paths are used.'''
2503
2505
2504 def complete(path, acceptable):
2506 def complete(path, acceptable):
2505 dirstate = repo.dirstate
2507 dirstate = repo.dirstate
2506 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2508 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2507 rootdir = repo.root + os.sep
2509 rootdir = repo.root + os.sep
2508 if spec != repo.root and not spec.startswith(rootdir):
2510 if spec != repo.root and not spec.startswith(rootdir):
2509 return [], []
2511 return [], []
2510 if os.path.isdir(spec):
2512 if os.path.isdir(spec):
2511 spec += '/'
2513 spec += '/'
2512 spec = spec[len(rootdir):]
2514 spec = spec[len(rootdir):]
2513 fixpaths = os.sep != '/'
2515 fixpaths = os.sep != '/'
2514 if fixpaths:
2516 if fixpaths:
2515 spec = spec.replace(os.sep, '/')
2517 spec = spec.replace(os.sep, '/')
2516 speclen = len(spec)
2518 speclen = len(spec)
2517 fullpaths = opts['full']
2519 fullpaths = opts['full']
2518 files, dirs = set(), set()
2520 files, dirs = set(), set()
2519 adddir, addfile = dirs.add, files.add
2521 adddir, addfile = dirs.add, files.add
2520 for f, st in dirstate.iteritems():
2522 for f, st in dirstate.iteritems():
2521 if f.startswith(spec) and st[0] in acceptable:
2523 if f.startswith(spec) and st[0] in acceptable:
2522 if fixpaths:
2524 if fixpaths:
2523 f = f.replace('/', os.sep)
2525 f = f.replace('/', os.sep)
2524 if fullpaths:
2526 if fullpaths:
2525 addfile(f)
2527 addfile(f)
2526 continue
2528 continue
2527 s = f.find(os.sep, speclen)
2529 s = f.find(os.sep, speclen)
2528 if s >= 0:
2530 if s >= 0:
2529 adddir(f[:s])
2531 adddir(f[:s])
2530 else:
2532 else:
2531 addfile(f)
2533 addfile(f)
2532 return files, dirs
2534 return files, dirs
2533
2535
2534 acceptable = ''
2536 acceptable = ''
2535 if opts['normal']:
2537 if opts['normal']:
2536 acceptable += 'nm'
2538 acceptable += 'nm'
2537 if opts['added']:
2539 if opts['added']:
2538 acceptable += 'a'
2540 acceptable += 'a'
2539 if opts['removed']:
2541 if opts['removed']:
2540 acceptable += 'r'
2542 acceptable += 'r'
2541 cwd = repo.getcwd()
2543 cwd = repo.getcwd()
2542 if not specs:
2544 if not specs:
2543 specs = ['.']
2545 specs = ['.']
2544
2546
2545 files, dirs = set(), set()
2547 files, dirs = set(), set()
2546 for spec in specs:
2548 for spec in specs:
2547 f, d = complete(spec, acceptable or 'nmar')
2549 f, d = complete(spec, acceptable or 'nmar')
2548 files.update(f)
2550 files.update(f)
2549 dirs.update(d)
2551 dirs.update(d)
2550 files.update(dirs)
2552 files.update(dirs)
2551 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2553 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2552 ui.write('\n')
2554 ui.write('\n')
2553
2555
2554 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2556 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2555 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2557 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2556 '''access the pushkey key/value protocol
2558 '''access the pushkey key/value protocol
2557
2559
2558 With two args, list the keys in the given namespace.
2560 With two args, list the keys in the given namespace.
2559
2561
2560 With five args, set a key to new if it currently is set to old.
2562 With five args, set a key to new if it currently is set to old.
2561 Reports success or failure.
2563 Reports success or failure.
2562 '''
2564 '''
2563
2565
2564 target = hg.peer(ui, {}, repopath)
2566 target = hg.peer(ui, {}, repopath)
2565 if keyinfo:
2567 if keyinfo:
2566 key, old, new = keyinfo
2568 key, old, new = keyinfo
2567 r = target.pushkey(namespace, key, old, new)
2569 r = target.pushkey(namespace, key, old, new)
2568 ui.status(str(r) + '\n')
2570 ui.status(str(r) + '\n')
2569 return not r
2571 return not r
2570 else:
2572 else:
2571 for k, v in sorted(target.listkeys(namespace).iteritems()):
2573 for k, v in sorted(target.listkeys(namespace).iteritems()):
2572 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2574 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2573 v.encode('string-escape')))
2575 v.encode('string-escape')))
2574
2576
2575 @command('debugpvec', [], _('A B'))
2577 @command('debugpvec', [], _('A B'))
2576 def debugpvec(ui, repo, a, b=None):
2578 def debugpvec(ui, repo, a, b=None):
2577 ca = scmutil.revsingle(repo, a)
2579 ca = scmutil.revsingle(repo, a)
2578 cb = scmutil.revsingle(repo, b)
2580 cb = scmutil.revsingle(repo, b)
2579 pa = pvec.ctxpvec(ca)
2581 pa = pvec.ctxpvec(ca)
2580 pb = pvec.ctxpvec(cb)
2582 pb = pvec.ctxpvec(cb)
2581 if pa == pb:
2583 if pa == pb:
2582 rel = "="
2584 rel = "="
2583 elif pa > pb:
2585 elif pa > pb:
2584 rel = ">"
2586 rel = ">"
2585 elif pa < pb:
2587 elif pa < pb:
2586 rel = "<"
2588 rel = "<"
2587 elif pa | pb:
2589 elif pa | pb:
2588 rel = "|"
2590 rel = "|"
2589 ui.write(_("a: %s\n") % pa)
2591 ui.write(_("a: %s\n") % pa)
2590 ui.write(_("b: %s\n") % pb)
2592 ui.write(_("b: %s\n") % pb)
2591 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2593 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2592 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2594 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2593 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2595 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2594 pa.distance(pb), rel))
2596 pa.distance(pb), rel))
2595
2597
2596 @command('debugrebuilddirstate|debugrebuildstate',
2598 @command('debugrebuilddirstate|debugrebuildstate',
2597 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2599 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2598 _('[-r REV]'))
2600 _('[-r REV]'))
2599 def debugrebuilddirstate(ui, repo, rev):
2601 def debugrebuilddirstate(ui, repo, rev):
2600 """rebuild the dirstate as it would look like for the given revision
2602 """rebuild the dirstate as it would look like for the given revision
2601
2603
2602 If no revision is specified the first current parent will be used.
2604 If no revision is specified the first current parent will be used.
2603
2605
2604 The dirstate will be set to the files of the given revision.
2606 The dirstate will be set to the files of the given revision.
2605 The actual working directory content or existing dirstate
2607 The actual working directory content or existing dirstate
2606 information such as adds or removes is not considered.
2608 information such as adds or removes is not considered.
2607
2609
2608 One use of this command is to make the next :hg:`status` invocation
2610 One use of this command is to make the next :hg:`status` invocation
2609 check the actual file content.
2611 check the actual file content.
2610 """
2612 """
2611 ctx = scmutil.revsingle(repo, rev)
2613 ctx = scmutil.revsingle(repo, rev)
2612 wlock = repo.wlock()
2614 wlock = repo.wlock()
2613 try:
2615 try:
2614 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2616 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2615 finally:
2617 finally:
2616 wlock.release()
2618 wlock.release()
2617
2619
2618 @command('debugrename',
2620 @command('debugrename',
2619 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2621 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2620 _('[-r REV] FILE'))
2622 _('[-r REV] FILE'))
2621 def debugrename(ui, repo, file1, *pats, **opts):
2623 def debugrename(ui, repo, file1, *pats, **opts):
2622 """dump rename information"""
2624 """dump rename information"""
2623
2625
2624 ctx = scmutil.revsingle(repo, opts.get('rev'))
2626 ctx = scmutil.revsingle(repo, opts.get('rev'))
2625 m = scmutil.match(ctx, (file1,) + pats, opts)
2627 m = scmutil.match(ctx, (file1,) + pats, opts)
2626 for abs in ctx.walk(m):
2628 for abs in ctx.walk(m):
2627 fctx = ctx[abs]
2629 fctx = ctx[abs]
2628 o = fctx.filelog().renamed(fctx.filenode())
2630 o = fctx.filelog().renamed(fctx.filenode())
2629 rel = m.rel(abs)
2631 rel = m.rel(abs)
2630 if o:
2632 if o:
2631 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2633 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2632 else:
2634 else:
2633 ui.write(_("%s not renamed\n") % rel)
2635 ui.write(_("%s not renamed\n") % rel)
2634
2636
2635 @command('debugrevlog',
2637 @command('debugrevlog',
2636 [('c', 'changelog', False, _('open changelog')),
2638 [('c', 'changelog', False, _('open changelog')),
2637 ('m', 'manifest', False, _('open manifest')),
2639 ('m', 'manifest', False, _('open manifest')),
2638 ('d', 'dump', False, _('dump index data'))],
2640 ('d', 'dump', False, _('dump index data'))],
2639 _('-c|-m|FILE'),
2641 _('-c|-m|FILE'),
2640 optionalrepo=True)
2642 optionalrepo=True)
2641 def debugrevlog(ui, repo, file_=None, **opts):
2643 def debugrevlog(ui, repo, file_=None, **opts):
2642 """show data and statistics about a revlog"""
2644 """show data and statistics about a revlog"""
2643 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2645 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2644
2646
2645 if opts.get("dump"):
2647 if opts.get("dump"):
2646 numrevs = len(r)
2648 numrevs = len(r)
2647 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2649 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2648 " rawsize totalsize compression heads chainlen\n")
2650 " rawsize totalsize compression heads chainlen\n")
2649 ts = 0
2651 ts = 0
2650 heads = set()
2652 heads = set()
2651 rindex = r.index
2653 rindex = r.index
2652
2654
2653 def chainbaseandlen(rev):
2655 def chainbaseandlen(rev):
2654 clen = 0
2656 clen = 0
2655 base = rindex[rev][3]
2657 base = rindex[rev][3]
2656 while base != rev:
2658 while base != rev:
2657 clen += 1
2659 clen += 1
2658 rev = base
2660 rev = base
2659 base = rindex[rev][3]
2661 base = rindex[rev][3]
2660 return base, clen
2662 return base, clen
2661
2663
2662 for rev in xrange(numrevs):
2664 for rev in xrange(numrevs):
2663 dbase = r.deltaparent(rev)
2665 dbase = r.deltaparent(rev)
2664 if dbase == -1:
2666 if dbase == -1:
2665 dbase = rev
2667 dbase = rev
2666 cbase, clen = chainbaseandlen(rev)
2668 cbase, clen = chainbaseandlen(rev)
2667 p1, p2 = r.parentrevs(rev)
2669 p1, p2 = r.parentrevs(rev)
2668 rs = r.rawsize(rev)
2670 rs = r.rawsize(rev)
2669 ts = ts + rs
2671 ts = ts + rs
2670 heads -= set(r.parentrevs(rev))
2672 heads -= set(r.parentrevs(rev))
2671 heads.add(rev)
2673 heads.add(rev)
2672 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2674 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2673 "%11d %5d %8d\n" %
2675 "%11d %5d %8d\n" %
2674 (rev, p1, p2, r.start(rev), r.end(rev),
2676 (rev, p1, p2, r.start(rev), r.end(rev),
2675 r.start(dbase), r.start(cbase),
2677 r.start(dbase), r.start(cbase),
2676 r.start(p1), r.start(p2),
2678 r.start(p1), r.start(p2),
2677 rs, ts, ts / r.end(rev), len(heads), clen))
2679 rs, ts, ts / r.end(rev), len(heads), clen))
2678 return 0
2680 return 0
2679
2681
2680 v = r.version
2682 v = r.version
2681 format = v & 0xFFFF
2683 format = v & 0xFFFF
2682 flags = []
2684 flags = []
2683 gdelta = False
2685 gdelta = False
2684 if v & revlog.REVLOGNGINLINEDATA:
2686 if v & revlog.REVLOGNGINLINEDATA:
2685 flags.append('inline')
2687 flags.append('inline')
2686 if v & revlog.REVLOGGENERALDELTA:
2688 if v & revlog.REVLOGGENERALDELTA:
2687 gdelta = True
2689 gdelta = True
2688 flags.append('generaldelta')
2690 flags.append('generaldelta')
2689 if not flags:
2691 if not flags:
2690 flags = ['(none)']
2692 flags = ['(none)']
2691
2693
2692 nummerges = 0
2694 nummerges = 0
2693 numfull = 0
2695 numfull = 0
2694 numprev = 0
2696 numprev = 0
2695 nump1 = 0
2697 nump1 = 0
2696 nump2 = 0
2698 nump2 = 0
2697 numother = 0
2699 numother = 0
2698 nump1prev = 0
2700 nump1prev = 0
2699 nump2prev = 0
2701 nump2prev = 0
2700 chainlengths = []
2702 chainlengths = []
2701
2703
2702 datasize = [None, 0, 0L]
2704 datasize = [None, 0, 0L]
2703 fullsize = [None, 0, 0L]
2705 fullsize = [None, 0, 0L]
2704 deltasize = [None, 0, 0L]
2706 deltasize = [None, 0, 0L]
2705
2707
2706 def addsize(size, l):
2708 def addsize(size, l):
2707 if l[0] is None or size < l[0]:
2709 if l[0] is None or size < l[0]:
2708 l[0] = size
2710 l[0] = size
2709 if size > l[1]:
2711 if size > l[1]:
2710 l[1] = size
2712 l[1] = size
2711 l[2] += size
2713 l[2] += size
2712
2714
2713 numrevs = len(r)
2715 numrevs = len(r)
2714 for rev in xrange(numrevs):
2716 for rev in xrange(numrevs):
2715 p1, p2 = r.parentrevs(rev)
2717 p1, p2 = r.parentrevs(rev)
2716 delta = r.deltaparent(rev)
2718 delta = r.deltaparent(rev)
2717 if format > 0:
2719 if format > 0:
2718 addsize(r.rawsize(rev), datasize)
2720 addsize(r.rawsize(rev), datasize)
2719 if p2 != nullrev:
2721 if p2 != nullrev:
2720 nummerges += 1
2722 nummerges += 1
2721 size = r.length(rev)
2723 size = r.length(rev)
2722 if delta == nullrev:
2724 if delta == nullrev:
2723 chainlengths.append(0)
2725 chainlengths.append(0)
2724 numfull += 1
2726 numfull += 1
2725 addsize(size, fullsize)
2727 addsize(size, fullsize)
2726 else:
2728 else:
2727 chainlengths.append(chainlengths[delta] + 1)
2729 chainlengths.append(chainlengths[delta] + 1)
2728 addsize(size, deltasize)
2730 addsize(size, deltasize)
2729 if delta == rev - 1:
2731 if delta == rev - 1:
2730 numprev += 1
2732 numprev += 1
2731 if delta == p1:
2733 if delta == p1:
2732 nump1prev += 1
2734 nump1prev += 1
2733 elif delta == p2:
2735 elif delta == p2:
2734 nump2prev += 1
2736 nump2prev += 1
2735 elif delta == p1:
2737 elif delta == p1:
2736 nump1 += 1
2738 nump1 += 1
2737 elif delta == p2:
2739 elif delta == p2:
2738 nump2 += 1
2740 nump2 += 1
2739 elif delta != nullrev:
2741 elif delta != nullrev:
2740 numother += 1
2742 numother += 1
2741
2743
2742 # Adjust size min value for empty cases
2744 # Adjust size min value for empty cases
2743 for size in (datasize, fullsize, deltasize):
2745 for size in (datasize, fullsize, deltasize):
2744 if size[0] is None:
2746 if size[0] is None:
2745 size[0] = 0
2747 size[0] = 0
2746
2748
2747 numdeltas = numrevs - numfull
2749 numdeltas = numrevs - numfull
2748 numoprev = numprev - nump1prev - nump2prev
2750 numoprev = numprev - nump1prev - nump2prev
2749 totalrawsize = datasize[2]
2751 totalrawsize = datasize[2]
2750 datasize[2] /= numrevs
2752 datasize[2] /= numrevs
2751 fulltotal = fullsize[2]
2753 fulltotal = fullsize[2]
2752 fullsize[2] /= numfull
2754 fullsize[2] /= numfull
2753 deltatotal = deltasize[2]
2755 deltatotal = deltasize[2]
2754 if numrevs - numfull > 0:
2756 if numrevs - numfull > 0:
2755 deltasize[2] /= numrevs - numfull
2757 deltasize[2] /= numrevs - numfull
2756 totalsize = fulltotal + deltatotal
2758 totalsize = fulltotal + deltatotal
2757 avgchainlen = sum(chainlengths) / numrevs
2759 avgchainlen = sum(chainlengths) / numrevs
2758 compratio = totalrawsize / totalsize
2760 compratio = totalrawsize / totalsize
2759
2761
2760 basedfmtstr = '%%%dd\n'
2762 basedfmtstr = '%%%dd\n'
2761 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2763 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2762
2764
2763 def dfmtstr(max):
2765 def dfmtstr(max):
2764 return basedfmtstr % len(str(max))
2766 return basedfmtstr % len(str(max))
2765 def pcfmtstr(max, padding=0):
2767 def pcfmtstr(max, padding=0):
2766 return basepcfmtstr % (len(str(max)), ' ' * padding)
2768 return basepcfmtstr % (len(str(max)), ' ' * padding)
2767
2769
2768 def pcfmt(value, total):
2770 def pcfmt(value, total):
2769 return (value, 100 * float(value) / total)
2771 return (value, 100 * float(value) / total)
2770
2772
2771 ui.write(('format : %d\n') % format)
2773 ui.write(('format : %d\n') % format)
2772 ui.write(('flags : %s\n') % ', '.join(flags))
2774 ui.write(('flags : %s\n') % ', '.join(flags))
2773
2775
2774 ui.write('\n')
2776 ui.write('\n')
2775 fmt = pcfmtstr(totalsize)
2777 fmt = pcfmtstr(totalsize)
2776 fmt2 = dfmtstr(totalsize)
2778 fmt2 = dfmtstr(totalsize)
2777 ui.write(('revisions : ') + fmt2 % numrevs)
2779 ui.write(('revisions : ') + fmt2 % numrevs)
2778 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2780 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2779 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2781 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2780 ui.write(('revisions : ') + fmt2 % numrevs)
2782 ui.write(('revisions : ') + fmt2 % numrevs)
2781 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2783 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2782 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2784 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2783 ui.write(('revision size : ') + fmt2 % totalsize)
2785 ui.write(('revision size : ') + fmt2 % totalsize)
2784 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2786 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2785 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2787 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2786
2788
2787 ui.write('\n')
2789 ui.write('\n')
2788 fmt = dfmtstr(max(avgchainlen, compratio))
2790 fmt = dfmtstr(max(avgchainlen, compratio))
2789 ui.write(('avg chain length : ') + fmt % avgchainlen)
2791 ui.write(('avg chain length : ') + fmt % avgchainlen)
2790 ui.write(('compression ratio : ') + fmt % compratio)
2792 ui.write(('compression ratio : ') + fmt % compratio)
2791
2793
2792 if format > 0:
2794 if format > 0:
2793 ui.write('\n')
2795 ui.write('\n')
2794 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2796 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2795 % tuple(datasize))
2797 % tuple(datasize))
2796 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2798 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2797 % tuple(fullsize))
2799 % tuple(fullsize))
2798 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2800 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2799 % tuple(deltasize))
2801 % tuple(deltasize))
2800
2802
2801 if numdeltas > 0:
2803 if numdeltas > 0:
2802 ui.write('\n')
2804 ui.write('\n')
2803 fmt = pcfmtstr(numdeltas)
2805 fmt = pcfmtstr(numdeltas)
2804 fmt2 = pcfmtstr(numdeltas, 4)
2806 fmt2 = pcfmtstr(numdeltas, 4)
2805 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2807 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2806 if numprev > 0:
2808 if numprev > 0:
2807 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2809 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2808 numprev))
2810 numprev))
2809 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2811 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2810 numprev))
2812 numprev))
2811 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2813 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2812 numprev))
2814 numprev))
2813 if gdelta:
2815 if gdelta:
2814 ui.write(('deltas against p1 : ')
2816 ui.write(('deltas against p1 : ')
2815 + fmt % pcfmt(nump1, numdeltas))
2817 + fmt % pcfmt(nump1, numdeltas))
2816 ui.write(('deltas against p2 : ')
2818 ui.write(('deltas against p2 : ')
2817 + fmt % pcfmt(nump2, numdeltas))
2819 + fmt % pcfmt(nump2, numdeltas))
2818 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2820 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2819 numdeltas))
2821 numdeltas))
2820
2822
2821 @command('debugrevspec',
2823 @command('debugrevspec',
2822 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2824 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2823 ('REVSPEC'))
2825 ('REVSPEC'))
2824 def debugrevspec(ui, repo, expr, **opts):
2826 def debugrevspec(ui, repo, expr, **opts):
2825 """parse and apply a revision specification
2827 """parse and apply a revision specification
2826
2828
2827 Use --verbose to print the parsed tree before and after aliases
2829 Use --verbose to print the parsed tree before and after aliases
2828 expansion.
2830 expansion.
2829 """
2831 """
2830 if ui.verbose:
2832 if ui.verbose:
2831 tree = revset.parse(expr)[0]
2833 tree = revset.parse(expr)[0]
2832 ui.note(revset.prettyformat(tree), "\n")
2834 ui.note(revset.prettyformat(tree), "\n")
2833 newtree = revset.findaliases(ui, tree)
2835 newtree = revset.findaliases(ui, tree)
2834 if newtree != tree:
2836 if newtree != tree:
2835 ui.note(revset.prettyformat(newtree), "\n")
2837 ui.note(revset.prettyformat(newtree), "\n")
2836 if opts["optimize"]:
2838 if opts["optimize"]:
2837 weight, optimizedtree = revset.optimize(newtree, True)
2839 weight, optimizedtree = revset.optimize(newtree, True)
2838 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2840 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2839 func = revset.match(ui, expr)
2841 func = revset.match(ui, expr)
2840 for c in func(repo, revset.spanset(repo)):
2842 for c in func(repo, revset.spanset(repo)):
2841 ui.write("%s\n" % c)
2843 ui.write("%s\n" % c)
2842
2844
2843 @command('debugsetparents', [], _('REV1 [REV2]'))
2845 @command('debugsetparents', [], _('REV1 [REV2]'))
2844 def debugsetparents(ui, repo, rev1, rev2=None):
2846 def debugsetparents(ui, repo, rev1, rev2=None):
2845 """manually set the parents of the current working directory
2847 """manually set the parents of the current working directory
2846
2848
2847 This is useful for writing repository conversion tools, but should
2849 This is useful for writing repository conversion tools, but should
2848 be used with care.
2850 be used with care.
2849
2851
2850 Returns 0 on success.
2852 Returns 0 on success.
2851 """
2853 """
2852
2854
2853 r1 = scmutil.revsingle(repo, rev1).node()
2855 r1 = scmutil.revsingle(repo, rev1).node()
2854 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2856 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2855
2857
2856 wlock = repo.wlock()
2858 wlock = repo.wlock()
2857 try:
2859 try:
2858 repo.dirstate.beginparentchange()
2860 repo.dirstate.beginparentchange()
2859 repo.setparents(r1, r2)
2861 repo.setparents(r1, r2)
2860 repo.dirstate.endparentchange()
2862 repo.dirstate.endparentchange()
2861 finally:
2863 finally:
2862 wlock.release()
2864 wlock.release()
2863
2865
2864 @command('debugdirstate|debugstate',
2866 @command('debugdirstate|debugstate',
2865 [('', 'nodates', None, _('do not display the saved mtime')),
2867 [('', 'nodates', None, _('do not display the saved mtime')),
2866 ('', 'datesort', None, _('sort by saved mtime'))],
2868 ('', 'datesort', None, _('sort by saved mtime'))],
2867 _('[OPTION]...'))
2869 _('[OPTION]...'))
2868 def debugstate(ui, repo, nodates=None, datesort=None):
2870 def debugstate(ui, repo, nodates=None, datesort=None):
2869 """show the contents of the current dirstate"""
2871 """show the contents of the current dirstate"""
2870 timestr = ""
2872 timestr = ""
2871 showdate = not nodates
2873 showdate = not nodates
2872 if datesort:
2874 if datesort:
2873 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2875 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2874 else:
2876 else:
2875 keyfunc = None # sort by filename
2877 keyfunc = None # sort by filename
2876 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2878 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2877 if showdate:
2879 if showdate:
2878 if ent[3] == -1:
2880 if ent[3] == -1:
2879 # Pad or slice to locale representation
2881 # Pad or slice to locale representation
2880 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2882 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2881 time.localtime(0)))
2883 time.localtime(0)))
2882 timestr = 'unset'
2884 timestr = 'unset'
2883 timestr = (timestr[:locale_len] +
2885 timestr = (timestr[:locale_len] +
2884 ' ' * (locale_len - len(timestr)))
2886 ' ' * (locale_len - len(timestr)))
2885 else:
2887 else:
2886 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2888 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2887 time.localtime(ent[3]))
2889 time.localtime(ent[3]))
2888 if ent[1] & 020000:
2890 if ent[1] & 020000:
2889 mode = 'lnk'
2891 mode = 'lnk'
2890 else:
2892 else:
2891 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2893 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2892 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2894 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2893 for f in repo.dirstate.copies():
2895 for f in repo.dirstate.copies():
2894 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2896 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2895
2897
2896 @command('debugsub',
2898 @command('debugsub',
2897 [('r', 'rev', '',
2899 [('r', 'rev', '',
2898 _('revision to check'), _('REV'))],
2900 _('revision to check'), _('REV'))],
2899 _('[-r REV] [REV]'))
2901 _('[-r REV] [REV]'))
2900 def debugsub(ui, repo, rev=None):
2902 def debugsub(ui, repo, rev=None):
2901 ctx = scmutil.revsingle(repo, rev, None)
2903 ctx = scmutil.revsingle(repo, rev, None)
2902 for k, v in sorted(ctx.substate.items()):
2904 for k, v in sorted(ctx.substate.items()):
2903 ui.write(('path %s\n') % k)
2905 ui.write(('path %s\n') % k)
2904 ui.write((' source %s\n') % v[0])
2906 ui.write((' source %s\n') % v[0])
2905 ui.write((' revision %s\n') % v[1])
2907 ui.write((' revision %s\n') % v[1])
2906
2908
2907 @command('debugsuccessorssets',
2909 @command('debugsuccessorssets',
2908 [],
2910 [],
2909 _('[REV]'))
2911 _('[REV]'))
2910 def debugsuccessorssets(ui, repo, *revs):
2912 def debugsuccessorssets(ui, repo, *revs):
2911 """show set of successors for revision
2913 """show set of successors for revision
2912
2914
2913 A successors set of changeset A is a consistent group of revisions that
2915 A successors set of changeset A is a consistent group of revisions that
2914 succeed A. It contains non-obsolete changesets only.
2916 succeed A. It contains non-obsolete changesets only.
2915
2917
2916 In most cases a changeset A has a single successors set containing a single
2918 In most cases a changeset A has a single successors set containing a single
2917 successor (changeset A replaced by A').
2919 successor (changeset A replaced by A').
2918
2920
2919 A changeset that is made obsolete with no successors are called "pruned".
2921 A changeset that is made obsolete with no successors are called "pruned".
2920 Such changesets have no successors sets at all.
2922 Such changesets have no successors sets at all.
2921
2923
2922 A changeset that has been "split" will have a successors set containing
2924 A changeset that has been "split" will have a successors set containing
2923 more than one successor.
2925 more than one successor.
2924
2926
2925 A changeset that has been rewritten in multiple different ways is called
2927 A changeset that has been rewritten in multiple different ways is called
2926 "divergent". Such changesets have multiple successor sets (each of which
2928 "divergent". Such changesets have multiple successor sets (each of which
2927 may also be split, i.e. have multiple successors).
2929 may also be split, i.e. have multiple successors).
2928
2930
2929 Results are displayed as follows::
2931 Results are displayed as follows::
2930
2932
2931 <rev1>
2933 <rev1>
2932 <successors-1A>
2934 <successors-1A>
2933 <rev2>
2935 <rev2>
2934 <successors-2A>
2936 <successors-2A>
2935 <successors-2B1> <successors-2B2> <successors-2B3>
2937 <successors-2B1> <successors-2B2> <successors-2B3>
2936
2938
2937 Here rev2 has two possible (i.e. divergent) successors sets. The first
2939 Here rev2 has two possible (i.e. divergent) successors sets. The first
2938 holds one element, whereas the second holds three (i.e. the changeset has
2940 holds one element, whereas the second holds three (i.e. the changeset has
2939 been split).
2941 been split).
2940 """
2942 """
2941 # passed to successorssets caching computation from one call to another
2943 # passed to successorssets caching computation from one call to another
2942 cache = {}
2944 cache = {}
2943 ctx2str = str
2945 ctx2str = str
2944 node2str = short
2946 node2str = short
2945 if ui.debug():
2947 if ui.debug():
2946 def ctx2str(ctx):
2948 def ctx2str(ctx):
2947 return ctx.hex()
2949 return ctx.hex()
2948 node2str = hex
2950 node2str = hex
2949 for rev in scmutil.revrange(repo, revs):
2951 for rev in scmutil.revrange(repo, revs):
2950 ctx = repo[rev]
2952 ctx = repo[rev]
2951 ui.write('%s\n'% ctx2str(ctx))
2953 ui.write('%s\n'% ctx2str(ctx))
2952 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2954 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2953 if succsset:
2955 if succsset:
2954 ui.write(' ')
2956 ui.write(' ')
2955 ui.write(node2str(succsset[0]))
2957 ui.write(node2str(succsset[0]))
2956 for node in succsset[1:]:
2958 for node in succsset[1:]:
2957 ui.write(' ')
2959 ui.write(' ')
2958 ui.write(node2str(node))
2960 ui.write(node2str(node))
2959 ui.write('\n')
2961 ui.write('\n')
2960
2962
2961 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2963 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2962 def debugwalk(ui, repo, *pats, **opts):
2964 def debugwalk(ui, repo, *pats, **opts):
2963 """show how files match on given patterns"""
2965 """show how files match on given patterns"""
2964 m = scmutil.match(repo[None], pats, opts)
2966 m = scmutil.match(repo[None], pats, opts)
2965 items = list(repo.walk(m))
2967 items = list(repo.walk(m))
2966 if not items:
2968 if not items:
2967 return
2969 return
2968 f = lambda fn: fn
2970 f = lambda fn: fn
2969 if ui.configbool('ui', 'slash') and os.sep != '/':
2971 if ui.configbool('ui', 'slash') and os.sep != '/':
2970 f = lambda fn: util.normpath(fn)
2972 f = lambda fn: util.normpath(fn)
2971 fmt = 'f %%-%ds %%-%ds %%s' % (
2973 fmt = 'f %%-%ds %%-%ds %%s' % (
2972 max([len(abs) for abs in items]),
2974 max([len(abs) for abs in items]),
2973 max([len(m.rel(abs)) for abs in items]))
2975 max([len(m.rel(abs)) for abs in items]))
2974 for abs in items:
2976 for abs in items:
2975 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2977 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2976 ui.write("%s\n" % line.rstrip())
2978 ui.write("%s\n" % line.rstrip())
2977
2979
2978 @command('debugwireargs',
2980 @command('debugwireargs',
2979 [('', 'three', '', 'three'),
2981 [('', 'three', '', 'three'),
2980 ('', 'four', '', 'four'),
2982 ('', 'four', '', 'four'),
2981 ('', 'five', '', 'five'),
2983 ('', 'five', '', 'five'),
2982 ] + remoteopts,
2984 ] + remoteopts,
2983 _('REPO [OPTIONS]... [ONE [TWO]]'),
2985 _('REPO [OPTIONS]... [ONE [TWO]]'),
2984 norepo=True)
2986 norepo=True)
2985 def debugwireargs(ui, repopath, *vals, **opts):
2987 def debugwireargs(ui, repopath, *vals, **opts):
2986 repo = hg.peer(ui, opts, repopath)
2988 repo = hg.peer(ui, opts, repopath)
2987 for opt in remoteopts:
2989 for opt in remoteopts:
2988 del opts[opt[1]]
2990 del opts[opt[1]]
2989 args = {}
2991 args = {}
2990 for k, v in opts.iteritems():
2992 for k, v in opts.iteritems():
2991 if v:
2993 if v:
2992 args[k] = v
2994 args[k] = v
2993 # run twice to check that we don't mess up the stream for the next command
2995 # run twice to check that we don't mess up the stream for the next command
2994 res1 = repo.debugwireargs(*vals, **args)
2996 res1 = repo.debugwireargs(*vals, **args)
2995 res2 = repo.debugwireargs(*vals, **args)
2997 res2 = repo.debugwireargs(*vals, **args)
2996 ui.write("%s\n" % res1)
2998 ui.write("%s\n" % res1)
2997 if res1 != res2:
2999 if res1 != res2:
2998 ui.warn("%s\n" % res2)
3000 ui.warn("%s\n" % res2)
2999
3001
3000 @command('^diff',
3002 @command('^diff',
3001 [('r', 'rev', [], _('revision'), _('REV')),
3003 [('r', 'rev', [], _('revision'), _('REV')),
3002 ('c', 'change', '', _('change made by revision'), _('REV'))
3004 ('c', 'change', '', _('change made by revision'), _('REV'))
3003 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3005 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3004 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3006 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3005 inferrepo=True)
3007 inferrepo=True)
3006 def diff(ui, repo, *pats, **opts):
3008 def diff(ui, repo, *pats, **opts):
3007 """diff repository (or selected files)
3009 """diff repository (or selected files)
3008
3010
3009 Show differences between revisions for the specified files.
3011 Show differences between revisions for the specified files.
3010
3012
3011 Differences between files are shown using the unified diff format.
3013 Differences between files are shown using the unified diff format.
3012
3014
3013 .. note::
3015 .. note::
3014
3016
3015 diff may generate unexpected results for merges, as it will
3017 diff may generate unexpected results for merges, as it will
3016 default to comparing against the working directory's first
3018 default to comparing against the working directory's first
3017 parent changeset if no revisions are specified.
3019 parent changeset if no revisions are specified.
3018
3020
3019 When two revision arguments are given, then changes are shown
3021 When two revision arguments are given, then changes are shown
3020 between those revisions. If only one revision is specified then
3022 between those revisions. If only one revision is specified then
3021 that revision is compared to the working directory, and, when no
3023 that revision is compared to the working directory, and, when no
3022 revisions are specified, the working directory files are compared
3024 revisions are specified, the working directory files are compared
3023 to its parent.
3025 to its parent.
3024
3026
3025 Alternatively you can specify -c/--change with a revision to see
3027 Alternatively you can specify -c/--change with a revision to see
3026 the changes in that changeset relative to its first parent.
3028 the changes in that changeset relative to its first parent.
3027
3029
3028 Without the -a/--text option, diff will avoid generating diffs of
3030 Without the -a/--text option, diff will avoid generating diffs of
3029 files it detects as binary. With -a, diff will generate a diff
3031 files it detects as binary. With -a, diff will generate a diff
3030 anyway, probably with undesirable results.
3032 anyway, probably with undesirable results.
3031
3033
3032 Use the -g/--git option to generate diffs in the git extended diff
3034 Use the -g/--git option to generate diffs in the git extended diff
3033 format. For more information, read :hg:`help diffs`.
3035 format. For more information, read :hg:`help diffs`.
3034
3036
3035 .. container:: verbose
3037 .. container:: verbose
3036
3038
3037 Examples:
3039 Examples:
3038
3040
3039 - compare a file in the current working directory to its parent::
3041 - compare a file in the current working directory to its parent::
3040
3042
3041 hg diff foo.c
3043 hg diff foo.c
3042
3044
3043 - compare two historical versions of a directory, with rename info::
3045 - compare two historical versions of a directory, with rename info::
3044
3046
3045 hg diff --git -r 1.0:1.2 lib/
3047 hg diff --git -r 1.0:1.2 lib/
3046
3048
3047 - get change stats relative to the last change on some date::
3049 - get change stats relative to the last change on some date::
3048
3050
3049 hg diff --stat -r "date('may 2')"
3051 hg diff --stat -r "date('may 2')"
3050
3052
3051 - diff all newly-added files that contain a keyword::
3053 - diff all newly-added files that contain a keyword::
3052
3054
3053 hg diff "set:added() and grep(GNU)"
3055 hg diff "set:added() and grep(GNU)"
3054
3056
3055 - compare a revision and its parents::
3057 - compare a revision and its parents::
3056
3058
3057 hg diff -c 9353 # compare against first parent
3059 hg diff -c 9353 # compare against first parent
3058 hg diff -r 9353^:9353 # same using revset syntax
3060 hg diff -r 9353^:9353 # same using revset syntax
3059 hg diff -r 9353^2:9353 # compare against the second parent
3061 hg diff -r 9353^2:9353 # compare against the second parent
3060
3062
3061 Returns 0 on success.
3063 Returns 0 on success.
3062 """
3064 """
3063
3065
3064 revs = opts.get('rev')
3066 revs = opts.get('rev')
3065 change = opts.get('change')
3067 change = opts.get('change')
3066 stat = opts.get('stat')
3068 stat = opts.get('stat')
3067 reverse = opts.get('reverse')
3069 reverse = opts.get('reverse')
3068
3070
3069 if revs and change:
3071 if revs and change:
3070 msg = _('cannot specify --rev and --change at the same time')
3072 msg = _('cannot specify --rev and --change at the same time')
3071 raise util.Abort(msg)
3073 raise util.Abort(msg)
3072 elif change:
3074 elif change:
3073 node2 = scmutil.revsingle(repo, change, None).node()
3075 node2 = scmutil.revsingle(repo, change, None).node()
3074 node1 = repo[node2].p1().node()
3076 node1 = repo[node2].p1().node()
3075 else:
3077 else:
3076 node1, node2 = scmutil.revpair(repo, revs)
3078 node1, node2 = scmutil.revpair(repo, revs)
3077
3079
3078 if reverse:
3080 if reverse:
3079 node1, node2 = node2, node1
3081 node1, node2 = node2, node1
3080
3082
3081 diffopts = patch.diffopts(ui, opts)
3083 diffopts = patch.diffopts(ui, opts)
3082 m = scmutil.match(repo[node2], pats, opts)
3084 m = scmutil.match(repo[node2], pats, opts)
3083 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3085 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3084 listsubrepos=opts.get('subrepos'))
3086 listsubrepos=opts.get('subrepos'))
3085
3087
3086 @command('^export',
3088 @command('^export',
3087 [('o', 'output', '',
3089 [('o', 'output', '',
3088 _('print output to file with formatted name'), _('FORMAT')),
3090 _('print output to file with formatted name'), _('FORMAT')),
3089 ('', 'switch-parent', None, _('diff against the second parent')),
3091 ('', 'switch-parent', None, _('diff against the second parent')),
3090 ('r', 'rev', [], _('revisions to export'), _('REV')),
3092 ('r', 'rev', [], _('revisions to export'), _('REV')),
3091 ] + diffopts,
3093 ] + diffopts,
3092 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3094 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3093 def export(ui, repo, *changesets, **opts):
3095 def export(ui, repo, *changesets, **opts):
3094 """dump the header and diffs for one or more changesets
3096 """dump the header and diffs for one or more changesets
3095
3097
3096 Print the changeset header and diffs for one or more revisions.
3098 Print the changeset header and diffs for one or more revisions.
3097 If no revision is given, the parent of the working directory is used.
3099 If no revision is given, the parent of the working directory is used.
3098
3100
3099 The information shown in the changeset header is: author, date,
3101 The information shown in the changeset header is: author, date,
3100 branch name (if non-default), changeset hash, parent(s) and commit
3102 branch name (if non-default), changeset hash, parent(s) and commit
3101 comment.
3103 comment.
3102
3104
3103 .. note::
3105 .. note::
3104
3106
3105 export may generate unexpected diff output for merge
3107 export may generate unexpected diff output for merge
3106 changesets, as it will compare the merge changeset against its
3108 changesets, as it will compare the merge changeset against its
3107 first parent only.
3109 first parent only.
3108
3110
3109 Output may be to a file, in which case the name of the file is
3111 Output may be to a file, in which case the name of the file is
3110 given using a format string. The formatting rules are as follows:
3112 given using a format string. The formatting rules are as follows:
3111
3113
3112 :``%%``: literal "%" character
3114 :``%%``: literal "%" character
3113 :``%H``: changeset hash (40 hexadecimal digits)
3115 :``%H``: changeset hash (40 hexadecimal digits)
3114 :``%N``: number of patches being generated
3116 :``%N``: number of patches being generated
3115 :``%R``: changeset revision number
3117 :``%R``: changeset revision number
3116 :``%b``: basename of the exporting repository
3118 :``%b``: basename of the exporting repository
3117 :``%h``: short-form changeset hash (12 hexadecimal digits)
3119 :``%h``: short-form changeset hash (12 hexadecimal digits)
3118 :``%m``: first line of the commit message (only alphanumeric characters)
3120 :``%m``: first line of the commit message (only alphanumeric characters)
3119 :``%n``: zero-padded sequence number, starting at 1
3121 :``%n``: zero-padded sequence number, starting at 1
3120 :``%r``: zero-padded changeset revision number
3122 :``%r``: zero-padded changeset revision number
3121
3123
3122 Without the -a/--text option, export will avoid generating diffs
3124 Without the -a/--text option, export will avoid generating diffs
3123 of files it detects as binary. With -a, export will generate a
3125 of files it detects as binary. With -a, export will generate a
3124 diff anyway, probably with undesirable results.
3126 diff anyway, probably with undesirable results.
3125
3127
3126 Use the -g/--git option to generate diffs in the git extended diff
3128 Use the -g/--git option to generate diffs in the git extended diff
3127 format. See :hg:`help diffs` for more information.
3129 format. See :hg:`help diffs` for more information.
3128
3130
3129 With the --switch-parent option, the diff will be against the
3131 With the --switch-parent option, the diff will be against the
3130 second parent. It can be useful to review a merge.
3132 second parent. It can be useful to review a merge.
3131
3133
3132 .. container:: verbose
3134 .. container:: verbose
3133
3135
3134 Examples:
3136 Examples:
3135
3137
3136 - use export and import to transplant a bugfix to the current
3138 - use export and import to transplant a bugfix to the current
3137 branch::
3139 branch::
3138
3140
3139 hg export -r 9353 | hg import -
3141 hg export -r 9353 | hg import -
3140
3142
3141 - export all the changesets between two revisions to a file with
3143 - export all the changesets between two revisions to a file with
3142 rename information::
3144 rename information::
3143
3145
3144 hg export --git -r 123:150 > changes.txt
3146 hg export --git -r 123:150 > changes.txt
3145
3147
3146 - split outgoing changes into a series of patches with
3148 - split outgoing changes into a series of patches with
3147 descriptive names::
3149 descriptive names::
3148
3150
3149 hg export -r "outgoing()" -o "%n-%m.patch"
3151 hg export -r "outgoing()" -o "%n-%m.patch"
3150
3152
3151 Returns 0 on success.
3153 Returns 0 on success.
3152 """
3154 """
3153 changesets += tuple(opts.get('rev', []))
3155 changesets += tuple(opts.get('rev', []))
3154 if not changesets:
3156 if not changesets:
3155 changesets = ['.']
3157 changesets = ['.']
3156 revs = scmutil.revrange(repo, changesets)
3158 revs = scmutil.revrange(repo, changesets)
3157 if not revs:
3159 if not revs:
3158 raise util.Abort(_("export requires at least one changeset"))
3160 raise util.Abort(_("export requires at least one changeset"))
3159 if len(revs) > 1:
3161 if len(revs) > 1:
3160 ui.note(_('exporting patches:\n'))
3162 ui.note(_('exporting patches:\n'))
3161 else:
3163 else:
3162 ui.note(_('exporting patch:\n'))
3164 ui.note(_('exporting patch:\n'))
3163 cmdutil.export(repo, revs, template=opts.get('output'),
3165 cmdutil.export(repo, revs, template=opts.get('output'),
3164 switch_parent=opts.get('switch_parent'),
3166 switch_parent=opts.get('switch_parent'),
3165 opts=patch.diffopts(ui, opts))
3167 opts=patch.diffopts(ui, opts))
3166
3168
3167 @command('files',
3169 @command('files',
3168 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3170 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3169 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3171 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3170 ] + walkopts + formatteropts,
3172 ] + walkopts + formatteropts,
3171 _('[OPTION]... [PATTERN]...'))
3173 _('[OPTION]... [PATTERN]...'))
3172 def files(ui, repo, *pats, **opts):
3174 def files(ui, repo, *pats, **opts):
3173 """list tracked files
3175 """list tracked files
3174
3176
3175 Print files under Mercurial control in the working directory or
3177 Print files under Mercurial control in the working directory or
3176 specified revision whose names match the given patterns (excluding
3178 specified revision whose names match the given patterns (excluding
3177 removed files).
3179 removed files).
3178
3180
3179 If no patterns are given to match, this command prints the names
3181 If no patterns are given to match, this command prints the names
3180 of all files under Mercurial control in the working copy.
3182 of all files under Mercurial control in the working copy.
3181
3183
3182 .. container:: verbose
3184 .. container:: verbose
3183
3185
3184 Examples:
3186 Examples:
3185
3187
3186 - list all files under the current directory::
3188 - list all files under the current directory::
3187
3189
3188 hg files .
3190 hg files .
3189
3191
3190 - shows sizes and flags for current revision::
3192 - shows sizes and flags for current revision::
3191
3193
3192 hg files -vr .
3194 hg files -vr .
3193
3195
3194 - list all files named README::
3196 - list all files named README::
3195
3197
3196 hg files -I "**/README"
3198 hg files -I "**/README"
3197
3199
3198 - list all binary files::
3200 - list all binary files::
3199
3201
3200 hg files "set:binary()"
3202 hg files "set:binary()"
3201
3203
3202 - find files containing a regular expression:
3204 - find files containing a regular expression:
3203
3205
3204 hg files "set:grep('bob')"
3206 hg files "set:grep('bob')"
3205
3207
3206 - search tracked file contents with xargs and grep::
3208 - search tracked file contents with xargs and grep::
3207
3209
3208 hg files -0 | xargs -0 grep foo
3210 hg files -0 | xargs -0 grep foo
3209
3211
3210 See :hg:'help pattern' and :hg:'help revsets' for more information
3212 See :hg:'help pattern' and :hg:'help revsets' for more information
3211 on specifying file patterns.
3213 on specifying file patterns.
3212
3214
3213 Returns 0 if a match is found, 1 otherwise.
3215 Returns 0 if a match is found, 1 otherwise.
3214
3216
3215 """
3217 """
3216 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3218 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3217 rev = ctx.rev()
3219 rev = ctx.rev()
3218 ret = 1
3220 ret = 1
3219
3221
3220 end = '\n'
3222 end = '\n'
3221 if opts.get('print0'):
3223 if opts.get('print0'):
3222 end = '\0'
3224 end = '\0'
3223 fm = ui.formatter('files', opts)
3225 fm = ui.formatter('files', opts)
3224 fmt = '%s' + end
3226 fmt = '%s' + end
3225
3227
3226 m = scmutil.match(ctx, pats, opts)
3228 m = scmutil.match(ctx, pats, opts)
3227 ds = repo.dirstate
3229 ds = repo.dirstate
3228 for f in ctx.matches(m):
3230 for f in ctx.matches(m):
3229 if rev is None and ds[f] == 'r':
3231 if rev is None and ds[f] == 'r':
3230 continue
3232 continue
3231 fm.startitem()
3233 fm.startitem()
3232 if ui.verbose:
3234 if ui.verbose:
3233 fc = ctx[f]
3235 fc = ctx[f]
3234 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3236 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3235 fm.data(abspath=f)
3237 fm.data(abspath=f)
3236 fm.write('path', fmt, m.rel(f))
3238 fm.write('path', fmt, m.rel(f))
3237 ret = 0
3239 ret = 0
3238
3240
3239 fm.end()
3241 fm.end()
3240
3242
3241 return ret
3243 return ret
3242
3244
3243 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3245 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3244 def forget(ui, repo, *pats, **opts):
3246 def forget(ui, repo, *pats, **opts):
3245 """forget the specified files on the next commit
3247 """forget the specified files on the next commit
3246
3248
3247 Mark the specified files so they will no longer be tracked
3249 Mark the specified files so they will no longer be tracked
3248 after the next commit.
3250 after the next commit.
3249
3251
3250 This only removes files from the current branch, not from the
3252 This only removes files from the current branch, not from the
3251 entire project history, and it does not delete them from the
3253 entire project history, and it does not delete them from the
3252 working directory.
3254 working directory.
3253
3255
3254 To undo a forget before the next commit, see :hg:`add`.
3256 To undo a forget before the next commit, see :hg:`add`.
3255
3257
3256 .. container:: verbose
3258 .. container:: verbose
3257
3259
3258 Examples:
3260 Examples:
3259
3261
3260 - forget newly-added binary files::
3262 - forget newly-added binary files::
3261
3263
3262 hg forget "set:added() and binary()"
3264 hg forget "set:added() and binary()"
3263
3265
3264 - forget files that would be excluded by .hgignore::
3266 - forget files that would be excluded by .hgignore::
3265
3267
3266 hg forget "set:hgignore()"
3268 hg forget "set:hgignore()"
3267
3269
3268 Returns 0 on success.
3270 Returns 0 on success.
3269 """
3271 """
3270
3272
3271 if not pats:
3273 if not pats:
3272 raise util.Abort(_('no files specified'))
3274 raise util.Abort(_('no files specified'))
3273
3275
3274 m = scmutil.match(repo[None], pats, opts)
3276 m = scmutil.match(repo[None], pats, opts)
3275 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3277 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3276 return rejected and 1 or 0
3278 return rejected and 1 or 0
3277
3279
3278 @command(
3280 @command(
3279 'graft',
3281 'graft',
3280 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3282 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3281 ('c', 'continue', False, _('resume interrupted graft')),
3283 ('c', 'continue', False, _('resume interrupted graft')),
3282 ('e', 'edit', False, _('invoke editor on commit messages')),
3284 ('e', 'edit', False, _('invoke editor on commit messages')),
3283 ('', 'log', None, _('append graft info to log message')),
3285 ('', 'log', None, _('append graft info to log message')),
3284 ('f', 'force', False, _('force graft')),
3286 ('f', 'force', False, _('force graft')),
3285 ('D', 'currentdate', False,
3287 ('D', 'currentdate', False,
3286 _('record the current date as commit date')),
3288 _('record the current date as commit date')),
3287 ('U', 'currentuser', False,
3289 ('U', 'currentuser', False,
3288 _('record the current user as committer'), _('DATE'))]
3290 _('record the current user as committer'), _('DATE'))]
3289 + commitopts2 + mergetoolopts + dryrunopts,
3291 + commitopts2 + mergetoolopts + dryrunopts,
3290 _('[OPTION]... [-r] REV...'))
3292 _('[OPTION]... [-r] REV...'))
3291 def graft(ui, repo, *revs, **opts):
3293 def graft(ui, repo, *revs, **opts):
3292 '''copy changes from other branches onto the current branch
3294 '''copy changes from other branches onto the current branch
3293
3295
3294 This command uses Mercurial's merge logic to copy individual
3296 This command uses Mercurial's merge logic to copy individual
3295 changes from other branches without merging branches in the
3297 changes from other branches without merging branches in the
3296 history graph. This is sometimes known as 'backporting' or
3298 history graph. This is sometimes known as 'backporting' or
3297 'cherry-picking'. By default, graft will copy user, date, and
3299 'cherry-picking'. By default, graft will copy user, date, and
3298 description from the source changesets.
3300 description from the source changesets.
3299
3301
3300 Changesets that are ancestors of the current revision, that have
3302 Changesets that are ancestors of the current revision, that have
3301 already been grafted, or that are merges will be skipped.
3303 already been grafted, or that are merges will be skipped.
3302
3304
3303 If --log is specified, log messages will have a comment appended
3305 If --log is specified, log messages will have a comment appended
3304 of the form::
3306 of the form::
3305
3307
3306 (grafted from CHANGESETHASH)
3308 (grafted from CHANGESETHASH)
3307
3309
3308 If --force is specified, revisions will be grafted even if they
3310 If --force is specified, revisions will be grafted even if they
3309 are already ancestors of or have been grafted to the destination.
3311 are already ancestors of or have been grafted to the destination.
3310 This is useful when the revisions have since been backed out.
3312 This is useful when the revisions have since been backed out.
3311
3313
3312 If a graft merge results in conflicts, the graft process is
3314 If a graft merge results in conflicts, the graft process is
3313 interrupted so that the current merge can be manually resolved.
3315 interrupted so that the current merge can be manually resolved.
3314 Once all conflicts are addressed, the graft process can be
3316 Once all conflicts are addressed, the graft process can be
3315 continued with the -c/--continue option.
3317 continued with the -c/--continue option.
3316
3318
3317 .. note::
3319 .. note::
3318
3320
3319 The -c/--continue option does not reapply earlier options, except
3321 The -c/--continue option does not reapply earlier options, except
3320 for --force.
3322 for --force.
3321
3323
3322 .. container:: verbose
3324 .. container:: verbose
3323
3325
3324 Examples:
3326 Examples:
3325
3327
3326 - copy a single change to the stable branch and edit its description::
3328 - copy a single change to the stable branch and edit its description::
3327
3329
3328 hg update stable
3330 hg update stable
3329 hg graft --edit 9393
3331 hg graft --edit 9393
3330
3332
3331 - graft a range of changesets with one exception, updating dates::
3333 - graft a range of changesets with one exception, updating dates::
3332
3334
3333 hg graft -D "2085::2093 and not 2091"
3335 hg graft -D "2085::2093 and not 2091"
3334
3336
3335 - continue a graft after resolving conflicts::
3337 - continue a graft after resolving conflicts::
3336
3338
3337 hg graft -c
3339 hg graft -c
3338
3340
3339 - show the source of a grafted changeset::
3341 - show the source of a grafted changeset::
3340
3342
3341 hg log --debug -r .
3343 hg log --debug -r .
3342
3344
3343 See :hg:`help revisions` and :hg:`help revsets` for more about
3345 See :hg:`help revisions` and :hg:`help revsets` for more about
3344 specifying revisions.
3346 specifying revisions.
3345
3347
3346 Returns 0 on successful completion.
3348 Returns 0 on successful completion.
3347 '''
3349 '''
3348
3350
3349 revs = list(revs)
3351 revs = list(revs)
3350 revs.extend(opts['rev'])
3352 revs.extend(opts['rev'])
3351
3353
3352 if not opts.get('user') and opts.get('currentuser'):
3354 if not opts.get('user') and opts.get('currentuser'):
3353 opts['user'] = ui.username()
3355 opts['user'] = ui.username()
3354 if not opts.get('date') and opts.get('currentdate'):
3356 if not opts.get('date') and opts.get('currentdate'):
3355 opts['date'] = "%d %d" % util.makedate()
3357 opts['date'] = "%d %d" % util.makedate()
3356
3358
3357 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3359 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3358
3360
3359 cont = False
3361 cont = False
3360 if opts['continue']:
3362 if opts['continue']:
3361 cont = True
3363 cont = True
3362 if revs:
3364 if revs:
3363 raise util.Abort(_("can't specify --continue and revisions"))
3365 raise util.Abort(_("can't specify --continue and revisions"))
3364 # read in unfinished revisions
3366 # read in unfinished revisions
3365 try:
3367 try:
3366 nodes = repo.opener.read('graftstate').splitlines()
3368 nodes = repo.opener.read('graftstate').splitlines()
3367 revs = [repo[node].rev() for node in nodes]
3369 revs = [repo[node].rev() for node in nodes]
3368 except IOError, inst:
3370 except IOError, inst:
3369 if inst.errno != errno.ENOENT:
3371 if inst.errno != errno.ENOENT:
3370 raise
3372 raise
3371 raise util.Abort(_("no graft state found, can't continue"))
3373 raise util.Abort(_("no graft state found, can't continue"))
3372 else:
3374 else:
3373 cmdutil.checkunfinished(repo)
3375 cmdutil.checkunfinished(repo)
3374 cmdutil.bailifchanged(repo)
3376 cmdutil.bailifchanged(repo)
3375 if not revs:
3377 if not revs:
3376 raise util.Abort(_('no revisions specified'))
3378 raise util.Abort(_('no revisions specified'))
3377 revs = scmutil.revrange(repo, revs)
3379 revs = scmutil.revrange(repo, revs)
3378
3380
3379 # check for merges
3381 # check for merges
3380 for rev in repo.revs('%ld and merge()', revs):
3382 for rev in repo.revs('%ld and merge()', revs):
3381 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3383 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3382 revs.remove(rev)
3384 revs.remove(rev)
3383 if not revs:
3385 if not revs:
3384 return -1
3386 return -1
3385
3387
3386 # Don't check in the --continue case, in effect retaining --force across
3388 # Don't check in the --continue case, in effect retaining --force across
3387 # --continues. That's because without --force, any revisions we decided to
3389 # --continues. That's because without --force, any revisions we decided to
3388 # skip would have been filtered out here, so they wouldn't have made their
3390 # skip would have been filtered out here, so they wouldn't have made their
3389 # way to the graftstate. With --force, any revisions we would have otherwise
3391 # way to the graftstate. With --force, any revisions we would have otherwise
3390 # skipped would not have been filtered out, and if they hadn't been applied
3392 # skipped would not have been filtered out, and if they hadn't been applied
3391 # already, they'd have been in the graftstate.
3393 # already, they'd have been in the graftstate.
3392 if not (cont or opts.get('force')):
3394 if not (cont or opts.get('force')):
3393 # check for ancestors of dest branch
3395 # check for ancestors of dest branch
3394 crev = repo['.'].rev()
3396 crev = repo['.'].rev()
3395 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3397 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3396 # Cannot use x.remove(y) on smart set, this has to be a list.
3398 # Cannot use x.remove(y) on smart set, this has to be a list.
3397 # XXX make this lazy in the future
3399 # XXX make this lazy in the future
3398 revs = list(revs)
3400 revs = list(revs)
3399 # don't mutate while iterating, create a copy
3401 # don't mutate while iterating, create a copy
3400 for rev in list(revs):
3402 for rev in list(revs):
3401 if rev in ancestors:
3403 if rev in ancestors:
3402 ui.warn(_('skipping ancestor revision %s\n') % rev)
3404 ui.warn(_('skipping ancestor revision %s\n') % rev)
3403 # XXX remove on list is slow
3405 # XXX remove on list is slow
3404 revs.remove(rev)
3406 revs.remove(rev)
3405 if not revs:
3407 if not revs:
3406 return -1
3408 return -1
3407
3409
3408 # analyze revs for earlier grafts
3410 # analyze revs for earlier grafts
3409 ids = {}
3411 ids = {}
3410 for ctx in repo.set("%ld", revs):
3412 for ctx in repo.set("%ld", revs):
3411 ids[ctx.hex()] = ctx.rev()
3413 ids[ctx.hex()] = ctx.rev()
3412 n = ctx.extra().get('source')
3414 n = ctx.extra().get('source')
3413 if n:
3415 if n:
3414 ids[n] = ctx.rev()
3416 ids[n] = ctx.rev()
3415
3417
3416 # check ancestors for earlier grafts
3418 # check ancestors for earlier grafts
3417 ui.debug('scanning for duplicate grafts\n')
3419 ui.debug('scanning for duplicate grafts\n')
3418
3420
3419 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3421 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3420 ctx = repo[rev]
3422 ctx = repo[rev]
3421 n = ctx.extra().get('source')
3423 n = ctx.extra().get('source')
3422 if n in ids:
3424 if n in ids:
3423 try:
3425 try:
3424 r = repo[n].rev()
3426 r = repo[n].rev()
3425 except error.RepoLookupError:
3427 except error.RepoLookupError:
3426 r = None
3428 r = None
3427 if r in revs:
3429 if r in revs:
3428 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3430 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3429 % (r, rev))
3431 % (r, rev))
3430 revs.remove(r)
3432 revs.remove(r)
3431 elif ids[n] in revs:
3433 elif ids[n] in revs:
3432 if r is None:
3434 if r is None:
3433 ui.warn(_('skipping already grafted revision %s '
3435 ui.warn(_('skipping already grafted revision %s '
3434 '(%s also has unknown origin %s)\n')
3436 '(%s also has unknown origin %s)\n')
3435 % (ids[n], rev, n))
3437 % (ids[n], rev, n))
3436 else:
3438 else:
3437 ui.warn(_('skipping already grafted revision %s '
3439 ui.warn(_('skipping already grafted revision %s '
3438 '(%s also has origin %d)\n')
3440 '(%s also has origin %d)\n')
3439 % (ids[n], rev, r))
3441 % (ids[n], rev, r))
3440 revs.remove(ids[n])
3442 revs.remove(ids[n])
3441 elif ctx.hex() in ids:
3443 elif ctx.hex() in ids:
3442 r = ids[ctx.hex()]
3444 r = ids[ctx.hex()]
3443 ui.warn(_('skipping already grafted revision %s '
3445 ui.warn(_('skipping already grafted revision %s '
3444 '(was grafted from %d)\n') % (r, rev))
3446 '(was grafted from %d)\n') % (r, rev))
3445 revs.remove(r)
3447 revs.remove(r)
3446 if not revs:
3448 if not revs:
3447 return -1
3449 return -1
3448
3450
3449 wlock = repo.wlock()
3451 wlock = repo.wlock()
3450 try:
3452 try:
3451 current = repo['.']
3453 current = repo['.']
3452 for pos, ctx in enumerate(repo.set("%ld", revs)):
3454 for pos, ctx in enumerate(repo.set("%ld", revs)):
3453
3455
3454 ui.status(_('grafting revision %s\n') % ctx.rev())
3456 ui.status(_('grafting revision %s\n') % ctx.rev())
3455 if opts.get('dry_run'):
3457 if opts.get('dry_run'):
3456 continue
3458 continue
3457
3459
3458 source = ctx.extra().get('source')
3460 source = ctx.extra().get('source')
3459 if not source:
3461 if not source:
3460 source = ctx.hex()
3462 source = ctx.hex()
3461 extra = {'source': source}
3463 extra = {'source': source}
3462 user = ctx.user()
3464 user = ctx.user()
3463 if opts.get('user'):
3465 if opts.get('user'):
3464 user = opts['user']
3466 user = opts['user']
3465 date = ctx.date()
3467 date = ctx.date()
3466 if opts.get('date'):
3468 if opts.get('date'):
3467 date = opts['date']
3469 date = opts['date']
3468 message = ctx.description()
3470 message = ctx.description()
3469 if opts.get('log'):
3471 if opts.get('log'):
3470 message += '\n(grafted from %s)' % ctx.hex()
3472 message += '\n(grafted from %s)' % ctx.hex()
3471
3473
3472 # we don't merge the first commit when continuing
3474 # we don't merge the first commit when continuing
3473 if not cont:
3475 if not cont:
3474 # perform the graft merge with p1(rev) as 'ancestor'
3476 # perform the graft merge with p1(rev) as 'ancestor'
3475 try:
3477 try:
3476 # ui.forcemerge is an internal variable, do not document
3478 # ui.forcemerge is an internal variable, do not document
3477 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3479 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3478 'graft')
3480 'graft')
3479 stats = mergemod.update(repo, ctx.node(), True, True, False,
3481 stats = mergemod.update(repo, ctx.node(), True, True, False,
3480 ctx.p1().node(),
3482 ctx.p1().node(),
3481 labels=['local', 'graft'])
3483 labels=['local', 'graft'])
3482 finally:
3484 finally:
3483 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3485 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3484 # report any conflicts
3486 # report any conflicts
3485 if stats and stats[3] > 0:
3487 if stats and stats[3] > 0:
3486 # write out state for --continue
3488 # write out state for --continue
3487 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3489 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3488 repo.opener.write('graftstate', ''.join(nodelines))
3490 repo.opener.write('graftstate', ''.join(nodelines))
3489 raise util.Abort(
3491 raise util.Abort(
3490 _("unresolved conflicts, can't continue"),
3492 _("unresolved conflicts, can't continue"),
3491 hint=_('use hg resolve and hg graft --continue'))
3493 hint=_('use hg resolve and hg graft --continue'))
3492 else:
3494 else:
3493 cont = False
3495 cont = False
3494
3496
3495 # drop the second merge parent
3497 # drop the second merge parent
3496 repo.dirstate.beginparentchange()
3498 repo.dirstate.beginparentchange()
3497 repo.setparents(current.node(), nullid)
3499 repo.setparents(current.node(), nullid)
3498 repo.dirstate.write()
3500 repo.dirstate.write()
3499 # fix up dirstate for copies and renames
3501 # fix up dirstate for copies and renames
3500 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3502 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3501 repo.dirstate.endparentchange()
3503 repo.dirstate.endparentchange()
3502
3504
3503 # commit
3505 # commit
3504 node = repo.commit(text=message, user=user,
3506 node = repo.commit(text=message, user=user,
3505 date=date, extra=extra, editor=editor)
3507 date=date, extra=extra, editor=editor)
3506 if node is None:
3508 if node is None:
3507 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3509 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3508 else:
3510 else:
3509 current = repo[node]
3511 current = repo[node]
3510 finally:
3512 finally:
3511 wlock.release()
3513 wlock.release()
3512
3514
3513 # remove state when we complete successfully
3515 # remove state when we complete successfully
3514 if not opts.get('dry_run'):
3516 if not opts.get('dry_run'):
3515 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3517 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3516
3518
3517 return 0
3519 return 0
3518
3520
3519 @command('grep',
3521 @command('grep',
3520 [('0', 'print0', None, _('end fields with NUL')),
3522 [('0', 'print0', None, _('end fields with NUL')),
3521 ('', 'all', None, _('print all revisions that match')),
3523 ('', 'all', None, _('print all revisions that match')),
3522 ('a', 'text', None, _('treat all files as text')),
3524 ('a', 'text', None, _('treat all files as text')),
3523 ('f', 'follow', None,
3525 ('f', 'follow', None,
3524 _('follow changeset history,'
3526 _('follow changeset history,'
3525 ' or file history across copies and renames')),
3527 ' or file history across copies and renames')),
3526 ('i', 'ignore-case', None, _('ignore case when matching')),
3528 ('i', 'ignore-case', None, _('ignore case when matching')),
3527 ('l', 'files-with-matches', None,
3529 ('l', 'files-with-matches', None,
3528 _('print only filenames and revisions that match')),
3530 _('print only filenames and revisions that match')),
3529 ('n', 'line-number', None, _('print matching line numbers')),
3531 ('n', 'line-number', None, _('print matching line numbers')),
3530 ('r', 'rev', [],
3532 ('r', 'rev', [],
3531 _('only search files changed within revision range'), _('REV')),
3533 _('only search files changed within revision range'), _('REV')),
3532 ('u', 'user', None, _('list the author (long with -v)')),
3534 ('u', 'user', None, _('list the author (long with -v)')),
3533 ('d', 'date', None, _('list the date (short with -q)')),
3535 ('d', 'date', None, _('list the date (short with -q)')),
3534 ] + walkopts,
3536 ] + walkopts,
3535 _('[OPTION]... PATTERN [FILE]...'),
3537 _('[OPTION]... PATTERN [FILE]...'),
3536 inferrepo=True)
3538 inferrepo=True)
3537 def grep(ui, repo, pattern, *pats, **opts):
3539 def grep(ui, repo, pattern, *pats, **opts):
3538 """search for a pattern in specified files and revisions
3540 """search for a pattern in specified files and revisions
3539
3541
3540 Search revisions of files for a regular expression.
3542 Search revisions of files for a regular expression.
3541
3543
3542 This command behaves differently than Unix grep. It only accepts
3544 This command behaves differently than Unix grep. It only accepts
3543 Python/Perl regexps. It searches repository history, not the
3545 Python/Perl regexps. It searches repository history, not the
3544 working directory. It always prints the revision number in which a
3546 working directory. It always prints the revision number in which a
3545 match appears.
3547 match appears.
3546
3548
3547 By default, grep only prints output for the first revision of a
3549 By default, grep only prints output for the first revision of a
3548 file in which it finds a match. To get it to print every revision
3550 file in which it finds a match. To get it to print every revision
3549 that contains a change in match status ("-" for a match that
3551 that contains a change in match status ("-" for a match that
3550 becomes a non-match, or "+" for a non-match that becomes a match),
3552 becomes a non-match, or "+" for a non-match that becomes a match),
3551 use the --all flag.
3553 use the --all flag.
3552
3554
3553 Returns 0 if a match is found, 1 otherwise.
3555 Returns 0 if a match is found, 1 otherwise.
3554 """
3556 """
3555 reflags = re.M
3557 reflags = re.M
3556 if opts.get('ignore_case'):
3558 if opts.get('ignore_case'):
3557 reflags |= re.I
3559 reflags |= re.I
3558 try:
3560 try:
3559 regexp = util.re.compile(pattern, reflags)
3561 regexp = util.re.compile(pattern, reflags)
3560 except re.error, inst:
3562 except re.error, inst:
3561 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3563 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3562 return 1
3564 return 1
3563 sep, eol = ':', '\n'
3565 sep, eol = ':', '\n'
3564 if opts.get('print0'):
3566 if opts.get('print0'):
3565 sep = eol = '\0'
3567 sep = eol = '\0'
3566
3568
3567 getfile = util.lrucachefunc(repo.file)
3569 getfile = util.lrucachefunc(repo.file)
3568
3570
3569 def matchlines(body):
3571 def matchlines(body):
3570 begin = 0
3572 begin = 0
3571 linenum = 0
3573 linenum = 0
3572 while begin < len(body):
3574 while begin < len(body):
3573 match = regexp.search(body, begin)
3575 match = regexp.search(body, begin)
3574 if not match:
3576 if not match:
3575 break
3577 break
3576 mstart, mend = match.span()
3578 mstart, mend = match.span()
3577 linenum += body.count('\n', begin, mstart) + 1
3579 linenum += body.count('\n', begin, mstart) + 1
3578 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3580 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3579 begin = body.find('\n', mend) + 1 or len(body) + 1
3581 begin = body.find('\n', mend) + 1 or len(body) + 1
3580 lend = begin - 1
3582 lend = begin - 1
3581 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3583 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3582
3584
3583 class linestate(object):
3585 class linestate(object):
3584 def __init__(self, line, linenum, colstart, colend):
3586 def __init__(self, line, linenum, colstart, colend):
3585 self.line = line
3587 self.line = line
3586 self.linenum = linenum
3588 self.linenum = linenum
3587 self.colstart = colstart
3589 self.colstart = colstart
3588 self.colend = colend
3590 self.colend = colend
3589
3591
3590 def __hash__(self):
3592 def __hash__(self):
3591 return hash((self.linenum, self.line))
3593 return hash((self.linenum, self.line))
3592
3594
3593 def __eq__(self, other):
3595 def __eq__(self, other):
3594 return self.line == other.line
3596 return self.line == other.line
3595
3597
3596 def __iter__(self):
3598 def __iter__(self):
3597 yield (self.line[:self.colstart], '')
3599 yield (self.line[:self.colstart], '')
3598 yield (self.line[self.colstart:self.colend], 'grep.match')
3600 yield (self.line[self.colstart:self.colend], 'grep.match')
3599 rest = self.line[self.colend:]
3601 rest = self.line[self.colend:]
3600 while rest != '':
3602 while rest != '':
3601 match = regexp.search(rest)
3603 match = regexp.search(rest)
3602 if not match:
3604 if not match:
3603 yield (rest, '')
3605 yield (rest, '')
3604 break
3606 break
3605 mstart, mend = match.span()
3607 mstart, mend = match.span()
3606 yield (rest[:mstart], '')
3608 yield (rest[:mstart], '')
3607 yield (rest[mstart:mend], 'grep.match')
3609 yield (rest[mstart:mend], 'grep.match')
3608 rest = rest[mend:]
3610 rest = rest[mend:]
3609
3611
3610 matches = {}
3612 matches = {}
3611 copies = {}
3613 copies = {}
3612 def grepbody(fn, rev, body):
3614 def grepbody(fn, rev, body):
3613 matches[rev].setdefault(fn, [])
3615 matches[rev].setdefault(fn, [])
3614 m = matches[rev][fn]
3616 m = matches[rev][fn]
3615 for lnum, cstart, cend, line in matchlines(body):
3617 for lnum, cstart, cend, line in matchlines(body):
3616 s = linestate(line, lnum, cstart, cend)
3618 s = linestate(line, lnum, cstart, cend)
3617 m.append(s)
3619 m.append(s)
3618
3620
3619 def difflinestates(a, b):
3621 def difflinestates(a, b):
3620 sm = difflib.SequenceMatcher(None, a, b)
3622 sm = difflib.SequenceMatcher(None, a, b)
3621 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3623 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3622 if tag == 'insert':
3624 if tag == 'insert':
3623 for i in xrange(blo, bhi):
3625 for i in xrange(blo, bhi):
3624 yield ('+', b[i])
3626 yield ('+', b[i])
3625 elif tag == 'delete':
3627 elif tag == 'delete':
3626 for i in xrange(alo, ahi):
3628 for i in xrange(alo, ahi):
3627 yield ('-', a[i])
3629 yield ('-', a[i])
3628 elif tag == 'replace':
3630 elif tag == 'replace':
3629 for i in xrange(alo, ahi):
3631 for i in xrange(alo, ahi):
3630 yield ('-', a[i])
3632 yield ('-', a[i])
3631 for i in xrange(blo, bhi):
3633 for i in xrange(blo, bhi):
3632 yield ('+', b[i])
3634 yield ('+', b[i])
3633
3635
3634 def display(fn, ctx, pstates, states):
3636 def display(fn, ctx, pstates, states):
3635 rev = ctx.rev()
3637 rev = ctx.rev()
3636 datefunc = ui.quiet and util.shortdate or util.datestr
3638 datefunc = ui.quiet and util.shortdate or util.datestr
3637 found = False
3639 found = False
3638 @util.cachefunc
3640 @util.cachefunc
3639 def binary():
3641 def binary():
3640 flog = getfile(fn)
3642 flog = getfile(fn)
3641 return util.binary(flog.read(ctx.filenode(fn)))
3643 return util.binary(flog.read(ctx.filenode(fn)))
3642
3644
3643 if opts.get('all'):
3645 if opts.get('all'):
3644 iter = difflinestates(pstates, states)
3646 iter = difflinestates(pstates, states)
3645 else:
3647 else:
3646 iter = [('', l) for l in states]
3648 iter = [('', l) for l in states]
3647 for change, l in iter:
3649 for change, l in iter:
3648 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3650 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3649
3651
3650 if opts.get('line_number'):
3652 if opts.get('line_number'):
3651 cols.append((str(l.linenum), 'grep.linenumber'))
3653 cols.append((str(l.linenum), 'grep.linenumber'))
3652 if opts.get('all'):
3654 if opts.get('all'):
3653 cols.append((change, 'grep.change'))
3655 cols.append((change, 'grep.change'))
3654 if opts.get('user'):
3656 if opts.get('user'):
3655 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3657 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3656 if opts.get('date'):
3658 if opts.get('date'):
3657 cols.append((datefunc(ctx.date()), 'grep.date'))
3659 cols.append((datefunc(ctx.date()), 'grep.date'))
3658 for col, label in cols[:-1]:
3660 for col, label in cols[:-1]:
3659 ui.write(col, label=label)
3661 ui.write(col, label=label)
3660 ui.write(sep, label='grep.sep')
3662 ui.write(sep, label='grep.sep')
3661 ui.write(cols[-1][0], label=cols[-1][1])
3663 ui.write(cols[-1][0], label=cols[-1][1])
3662 if not opts.get('files_with_matches'):
3664 if not opts.get('files_with_matches'):
3663 ui.write(sep, label='grep.sep')
3665 ui.write(sep, label='grep.sep')
3664 if not opts.get('text') and binary():
3666 if not opts.get('text') and binary():
3665 ui.write(" Binary file matches")
3667 ui.write(" Binary file matches")
3666 else:
3668 else:
3667 for s, label in l:
3669 for s, label in l:
3668 ui.write(s, label=label)
3670 ui.write(s, label=label)
3669 ui.write(eol)
3671 ui.write(eol)
3670 found = True
3672 found = True
3671 if opts.get('files_with_matches'):
3673 if opts.get('files_with_matches'):
3672 break
3674 break
3673 return found
3675 return found
3674
3676
3675 skip = {}
3677 skip = {}
3676 revfiles = {}
3678 revfiles = {}
3677 matchfn = scmutil.match(repo[None], pats, opts)
3679 matchfn = scmutil.match(repo[None], pats, opts)
3678 found = False
3680 found = False
3679 follow = opts.get('follow')
3681 follow = opts.get('follow')
3680
3682
3681 def prep(ctx, fns):
3683 def prep(ctx, fns):
3682 rev = ctx.rev()
3684 rev = ctx.rev()
3683 pctx = ctx.p1()
3685 pctx = ctx.p1()
3684 parent = pctx.rev()
3686 parent = pctx.rev()
3685 matches.setdefault(rev, {})
3687 matches.setdefault(rev, {})
3686 matches.setdefault(parent, {})
3688 matches.setdefault(parent, {})
3687 files = revfiles.setdefault(rev, [])
3689 files = revfiles.setdefault(rev, [])
3688 for fn in fns:
3690 for fn in fns:
3689 flog = getfile(fn)
3691 flog = getfile(fn)
3690 try:
3692 try:
3691 fnode = ctx.filenode(fn)
3693 fnode = ctx.filenode(fn)
3692 except error.LookupError:
3694 except error.LookupError:
3693 continue
3695 continue
3694
3696
3695 copied = flog.renamed(fnode)
3697 copied = flog.renamed(fnode)
3696 copy = follow and copied and copied[0]
3698 copy = follow and copied and copied[0]
3697 if copy:
3699 if copy:
3698 copies.setdefault(rev, {})[fn] = copy
3700 copies.setdefault(rev, {})[fn] = copy
3699 if fn in skip:
3701 if fn in skip:
3700 if copy:
3702 if copy:
3701 skip[copy] = True
3703 skip[copy] = True
3702 continue
3704 continue
3703 files.append(fn)
3705 files.append(fn)
3704
3706
3705 if fn not in matches[rev]:
3707 if fn not in matches[rev]:
3706 grepbody(fn, rev, flog.read(fnode))
3708 grepbody(fn, rev, flog.read(fnode))
3707
3709
3708 pfn = copy or fn
3710 pfn = copy or fn
3709 if pfn not in matches[parent]:
3711 if pfn not in matches[parent]:
3710 try:
3712 try:
3711 fnode = pctx.filenode(pfn)
3713 fnode = pctx.filenode(pfn)
3712 grepbody(pfn, parent, flog.read(fnode))
3714 grepbody(pfn, parent, flog.read(fnode))
3713 except error.LookupError:
3715 except error.LookupError:
3714 pass
3716 pass
3715
3717
3716 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3718 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3717 rev = ctx.rev()
3719 rev = ctx.rev()
3718 parent = ctx.p1().rev()
3720 parent = ctx.p1().rev()
3719 for fn in sorted(revfiles.get(rev, [])):
3721 for fn in sorted(revfiles.get(rev, [])):
3720 states = matches[rev][fn]
3722 states = matches[rev][fn]
3721 copy = copies.get(rev, {}).get(fn)
3723 copy = copies.get(rev, {}).get(fn)
3722 if fn in skip:
3724 if fn in skip:
3723 if copy:
3725 if copy:
3724 skip[copy] = True
3726 skip[copy] = True
3725 continue
3727 continue
3726 pstates = matches.get(parent, {}).get(copy or fn, [])
3728 pstates = matches.get(parent, {}).get(copy or fn, [])
3727 if pstates or states:
3729 if pstates or states:
3728 r = display(fn, ctx, pstates, states)
3730 r = display(fn, ctx, pstates, states)
3729 found = found or r
3731 found = found or r
3730 if r and not opts.get('all'):
3732 if r and not opts.get('all'):
3731 skip[fn] = True
3733 skip[fn] = True
3732 if copy:
3734 if copy:
3733 skip[copy] = True
3735 skip[copy] = True
3734 del matches[rev]
3736 del matches[rev]
3735 del revfiles[rev]
3737 del revfiles[rev]
3736
3738
3737 return not found
3739 return not found
3738
3740
3739 @command('heads',
3741 @command('heads',
3740 [('r', 'rev', '',
3742 [('r', 'rev', '',
3741 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3743 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3742 ('t', 'topo', False, _('show topological heads only')),
3744 ('t', 'topo', False, _('show topological heads only')),
3743 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3745 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3744 ('c', 'closed', False, _('show normal and closed branch heads')),
3746 ('c', 'closed', False, _('show normal and closed branch heads')),
3745 ] + templateopts,
3747 ] + templateopts,
3746 _('[-ct] [-r STARTREV] [REV]...'))
3748 _('[-ct] [-r STARTREV] [REV]...'))
3747 def heads(ui, repo, *branchrevs, **opts):
3749 def heads(ui, repo, *branchrevs, **opts):
3748 """show branch heads
3750 """show branch heads
3749
3751
3750 With no arguments, show all open branch heads in the repository.
3752 With no arguments, show all open branch heads in the repository.
3751 Branch heads are changesets that have no descendants on the
3753 Branch heads are changesets that have no descendants on the
3752 same branch. They are where development generally takes place and
3754 same branch. They are where development generally takes place and
3753 are the usual targets for update and merge operations.
3755 are the usual targets for update and merge operations.
3754
3756
3755 If one or more REVs are given, only open branch heads on the
3757 If one or more REVs are given, only open branch heads on the
3756 branches associated with the specified changesets are shown. This
3758 branches associated with the specified changesets are shown. This
3757 means that you can use :hg:`heads .` to see the heads on the
3759 means that you can use :hg:`heads .` to see the heads on the
3758 currently checked-out branch.
3760 currently checked-out branch.
3759
3761
3760 If -c/--closed is specified, also show branch heads marked closed
3762 If -c/--closed is specified, also show branch heads marked closed
3761 (see :hg:`commit --close-branch`).
3763 (see :hg:`commit --close-branch`).
3762
3764
3763 If STARTREV is specified, only those heads that are descendants of
3765 If STARTREV is specified, only those heads that are descendants of
3764 STARTREV will be displayed.
3766 STARTREV will be displayed.
3765
3767
3766 If -t/--topo is specified, named branch mechanics will be ignored and only
3768 If -t/--topo is specified, named branch mechanics will be ignored and only
3767 topological heads (changesets with no children) will be shown.
3769 topological heads (changesets with no children) will be shown.
3768
3770
3769 Returns 0 if matching heads are found, 1 if not.
3771 Returns 0 if matching heads are found, 1 if not.
3770 """
3772 """
3771
3773
3772 start = None
3774 start = None
3773 if 'rev' in opts:
3775 if 'rev' in opts:
3774 start = scmutil.revsingle(repo, opts['rev'], None).node()
3776 start = scmutil.revsingle(repo, opts['rev'], None).node()
3775
3777
3776 if opts.get('topo'):
3778 if opts.get('topo'):
3777 heads = [repo[h] for h in repo.heads(start)]
3779 heads = [repo[h] for h in repo.heads(start)]
3778 else:
3780 else:
3779 heads = []
3781 heads = []
3780 for branch in repo.branchmap():
3782 for branch in repo.branchmap():
3781 heads += repo.branchheads(branch, start, opts.get('closed'))
3783 heads += repo.branchheads(branch, start, opts.get('closed'))
3782 heads = [repo[h] for h in heads]
3784 heads = [repo[h] for h in heads]
3783
3785
3784 if branchrevs:
3786 if branchrevs:
3785 branches = set(repo[br].branch() for br in branchrevs)
3787 branches = set(repo[br].branch() for br in branchrevs)
3786 heads = [h for h in heads if h.branch() in branches]
3788 heads = [h for h in heads if h.branch() in branches]
3787
3789
3788 if opts.get('active') and branchrevs:
3790 if opts.get('active') and branchrevs:
3789 dagheads = repo.heads(start)
3791 dagheads = repo.heads(start)
3790 heads = [h for h in heads if h.node() in dagheads]
3792 heads = [h for h in heads if h.node() in dagheads]
3791
3793
3792 if branchrevs:
3794 if branchrevs:
3793 haveheads = set(h.branch() for h in heads)
3795 haveheads = set(h.branch() for h in heads)
3794 if branches - haveheads:
3796 if branches - haveheads:
3795 headless = ', '.join(b for b in branches - haveheads)
3797 headless = ', '.join(b for b in branches - haveheads)
3796 msg = _('no open branch heads found on branches %s')
3798 msg = _('no open branch heads found on branches %s')
3797 if opts.get('rev'):
3799 if opts.get('rev'):
3798 msg += _(' (started at %s)') % opts['rev']
3800 msg += _(' (started at %s)') % opts['rev']
3799 ui.warn((msg + '\n') % headless)
3801 ui.warn((msg + '\n') % headless)
3800
3802
3801 if not heads:
3803 if not heads:
3802 return 1
3804 return 1
3803
3805
3804 heads = sorted(heads, key=lambda x: -x.rev())
3806 heads = sorted(heads, key=lambda x: -x.rev())
3805 displayer = cmdutil.show_changeset(ui, repo, opts)
3807 displayer = cmdutil.show_changeset(ui, repo, opts)
3806 for ctx in heads:
3808 for ctx in heads:
3807 displayer.show(ctx)
3809 displayer.show(ctx)
3808 displayer.close()
3810 displayer.close()
3809
3811
3810 @command('help',
3812 @command('help',
3811 [('e', 'extension', None, _('show only help for extensions')),
3813 [('e', 'extension', None, _('show only help for extensions')),
3812 ('c', 'command', None, _('show only help for commands')),
3814 ('c', 'command', None, _('show only help for commands')),
3813 ('k', 'keyword', '', _('show topics matching keyword')),
3815 ('k', 'keyword', '', _('show topics matching keyword')),
3814 ],
3816 ],
3815 _('[-ec] [TOPIC]'),
3817 _('[-ec] [TOPIC]'),
3816 norepo=True)
3818 norepo=True)
3817 def help_(ui, name=None, **opts):
3819 def help_(ui, name=None, **opts):
3818 """show help for a given topic or a help overview
3820 """show help for a given topic or a help overview
3819
3821
3820 With no arguments, print a list of commands with short help messages.
3822 With no arguments, print a list of commands with short help messages.
3821
3823
3822 Given a topic, extension, or command name, print help for that
3824 Given a topic, extension, or command name, print help for that
3823 topic.
3825 topic.
3824
3826
3825 Returns 0 if successful.
3827 Returns 0 if successful.
3826 """
3828 """
3827
3829
3828 textwidth = min(ui.termwidth(), 80) - 2
3830 textwidth = min(ui.termwidth(), 80) - 2
3829
3831
3830 keep = []
3832 keep = []
3831 if ui.verbose:
3833 if ui.verbose:
3832 keep.append('verbose')
3834 keep.append('verbose')
3833 if sys.platform.startswith('win'):
3835 if sys.platform.startswith('win'):
3834 keep.append('windows')
3836 keep.append('windows')
3835 elif sys.platform == 'OpenVMS':
3837 elif sys.platform == 'OpenVMS':
3836 keep.append('vms')
3838 keep.append('vms')
3837 elif sys.platform == 'plan9':
3839 elif sys.platform == 'plan9':
3838 keep.append('plan9')
3840 keep.append('plan9')
3839 else:
3841 else:
3840 keep.append('unix')
3842 keep.append('unix')
3841 keep.append(sys.platform.lower())
3843 keep.append(sys.platform.lower())
3842
3844
3843 section = None
3845 section = None
3844 if name and '.' in name:
3846 if name and '.' in name:
3845 name, section = name.split('.')
3847 name, section = name.split('.')
3846
3848
3847 text = help.help_(ui, name, **opts)
3849 text = help.help_(ui, name, **opts)
3848
3850
3849 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3851 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3850 section=section)
3852 section=section)
3851 if section and not formatted:
3853 if section and not formatted:
3852 raise util.Abort(_("help section not found"))
3854 raise util.Abort(_("help section not found"))
3853
3855
3854 if 'verbose' in pruned:
3856 if 'verbose' in pruned:
3855 keep.append('omitted')
3857 keep.append('omitted')
3856 else:
3858 else:
3857 keep.append('notomitted')
3859 keep.append('notomitted')
3858 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3860 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3859 section=section)
3861 section=section)
3860 ui.write(formatted)
3862 ui.write(formatted)
3861
3863
3862
3864
3863 @command('identify|id',
3865 @command('identify|id',
3864 [('r', 'rev', '',
3866 [('r', 'rev', '',
3865 _('identify the specified revision'), _('REV')),
3867 _('identify the specified revision'), _('REV')),
3866 ('n', 'num', None, _('show local revision number')),
3868 ('n', 'num', None, _('show local revision number')),
3867 ('i', 'id', None, _('show global revision id')),
3869 ('i', 'id', None, _('show global revision id')),
3868 ('b', 'branch', None, _('show branch')),
3870 ('b', 'branch', None, _('show branch')),
3869 ('t', 'tags', None, _('show tags')),
3871 ('t', 'tags', None, _('show tags')),
3870 ('B', 'bookmarks', None, _('show bookmarks')),
3872 ('B', 'bookmarks', None, _('show bookmarks')),
3871 ] + remoteopts,
3873 ] + remoteopts,
3872 _('[-nibtB] [-r REV] [SOURCE]'),
3874 _('[-nibtB] [-r REV] [SOURCE]'),
3873 optionalrepo=True)
3875 optionalrepo=True)
3874 def identify(ui, repo, source=None, rev=None,
3876 def identify(ui, repo, source=None, rev=None,
3875 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3877 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3876 """identify the working copy or specified revision
3878 """identify the working copy or specified revision
3877
3879
3878 Print a summary identifying the repository state at REV using one or
3880 Print a summary identifying the repository state at REV using one or
3879 two parent hash identifiers, followed by a "+" if the working
3881 two parent hash identifiers, followed by a "+" if the working
3880 directory has uncommitted changes, the branch name (if not default),
3882 directory has uncommitted changes, the branch name (if not default),
3881 a list of tags, and a list of bookmarks.
3883 a list of tags, and a list of bookmarks.
3882
3884
3883 When REV is not given, print a summary of the current state of the
3885 When REV is not given, print a summary of the current state of the
3884 repository.
3886 repository.
3885
3887
3886 Specifying a path to a repository root or Mercurial bundle will
3888 Specifying a path to a repository root or Mercurial bundle will
3887 cause lookup to operate on that repository/bundle.
3889 cause lookup to operate on that repository/bundle.
3888
3890
3889 .. container:: verbose
3891 .. container:: verbose
3890
3892
3891 Examples:
3893 Examples:
3892
3894
3893 - generate a build identifier for the working directory::
3895 - generate a build identifier for the working directory::
3894
3896
3895 hg id --id > build-id.dat
3897 hg id --id > build-id.dat
3896
3898
3897 - find the revision corresponding to a tag::
3899 - find the revision corresponding to a tag::
3898
3900
3899 hg id -n -r 1.3
3901 hg id -n -r 1.3
3900
3902
3901 - check the most recent revision of a remote repository::
3903 - check the most recent revision of a remote repository::
3902
3904
3903 hg id -r tip http://selenic.com/hg/
3905 hg id -r tip http://selenic.com/hg/
3904
3906
3905 Returns 0 if successful.
3907 Returns 0 if successful.
3906 """
3908 """
3907
3909
3908 if not repo and not source:
3910 if not repo and not source:
3909 raise util.Abort(_("there is no Mercurial repository here "
3911 raise util.Abort(_("there is no Mercurial repository here "
3910 "(.hg not found)"))
3912 "(.hg not found)"))
3911
3913
3912 hexfunc = ui.debugflag and hex or short
3914 hexfunc = ui.debugflag and hex or short
3913 default = not (num or id or branch or tags or bookmarks)
3915 default = not (num or id or branch or tags or bookmarks)
3914 output = []
3916 output = []
3915 revs = []
3917 revs = []
3916
3918
3917 if source:
3919 if source:
3918 source, branches = hg.parseurl(ui.expandpath(source))
3920 source, branches = hg.parseurl(ui.expandpath(source))
3919 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3921 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3920 repo = peer.local()
3922 repo = peer.local()
3921 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3923 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3922
3924
3923 if not repo:
3925 if not repo:
3924 if num or branch or tags:
3926 if num or branch or tags:
3925 raise util.Abort(
3927 raise util.Abort(
3926 _("can't query remote revision number, branch, or tags"))
3928 _("can't query remote revision number, branch, or tags"))
3927 if not rev and revs:
3929 if not rev and revs:
3928 rev = revs[0]
3930 rev = revs[0]
3929 if not rev:
3931 if not rev:
3930 rev = "tip"
3932 rev = "tip"
3931
3933
3932 remoterev = peer.lookup(rev)
3934 remoterev = peer.lookup(rev)
3933 if default or id:
3935 if default or id:
3934 output = [hexfunc(remoterev)]
3936 output = [hexfunc(remoterev)]
3935
3937
3936 def getbms():
3938 def getbms():
3937 bms = []
3939 bms = []
3938
3940
3939 if 'bookmarks' in peer.listkeys('namespaces'):
3941 if 'bookmarks' in peer.listkeys('namespaces'):
3940 hexremoterev = hex(remoterev)
3942 hexremoterev = hex(remoterev)
3941 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3943 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3942 if bmr == hexremoterev]
3944 if bmr == hexremoterev]
3943
3945
3944 return sorted(bms)
3946 return sorted(bms)
3945
3947
3946 if bookmarks:
3948 if bookmarks:
3947 output.extend(getbms())
3949 output.extend(getbms())
3948 elif default and not ui.quiet:
3950 elif default and not ui.quiet:
3949 # multiple bookmarks for a single parent separated by '/'
3951 # multiple bookmarks for a single parent separated by '/'
3950 bm = '/'.join(getbms())
3952 bm = '/'.join(getbms())
3951 if bm:
3953 if bm:
3952 output.append(bm)
3954 output.append(bm)
3953 else:
3955 else:
3954 if not rev:
3956 if not rev:
3955 ctx = repo[None]
3957 ctx = repo[None]
3956 parents = ctx.parents()
3958 parents = ctx.parents()
3957 changed = ""
3959 changed = ""
3958 if default or id or num:
3960 if default or id or num:
3959 if (util.any(repo.status())
3961 if (util.any(repo.status())
3960 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3962 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3961 changed = '+'
3963 changed = '+'
3962 if default or id:
3964 if default or id:
3963 output = ["%s%s" %
3965 output = ["%s%s" %
3964 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3966 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3965 if num:
3967 if num:
3966 output.append("%s%s" %
3968 output.append("%s%s" %
3967 ('+'.join([str(p.rev()) for p in parents]), changed))
3969 ('+'.join([str(p.rev()) for p in parents]), changed))
3968 else:
3970 else:
3969 ctx = scmutil.revsingle(repo, rev)
3971 ctx = scmutil.revsingle(repo, rev)
3970 if default or id:
3972 if default or id:
3971 output = [hexfunc(ctx.node())]
3973 output = [hexfunc(ctx.node())]
3972 if num:
3974 if num:
3973 output.append(str(ctx.rev()))
3975 output.append(str(ctx.rev()))
3974
3976
3975 if default and not ui.quiet:
3977 if default and not ui.quiet:
3976 b = ctx.branch()
3978 b = ctx.branch()
3977 if b != 'default':
3979 if b != 'default':
3978 output.append("(%s)" % b)
3980 output.append("(%s)" % b)
3979
3981
3980 # multiple tags for a single parent separated by '/'
3982 # multiple tags for a single parent separated by '/'
3981 t = '/'.join(ctx.tags())
3983 t = '/'.join(ctx.tags())
3982 if t:
3984 if t:
3983 output.append(t)
3985 output.append(t)
3984
3986
3985 # multiple bookmarks for a single parent separated by '/'
3987 # multiple bookmarks for a single parent separated by '/'
3986 bm = '/'.join(ctx.bookmarks())
3988 bm = '/'.join(ctx.bookmarks())
3987 if bm:
3989 if bm:
3988 output.append(bm)
3990 output.append(bm)
3989 else:
3991 else:
3990 if branch:
3992 if branch:
3991 output.append(ctx.branch())
3993 output.append(ctx.branch())
3992
3994
3993 if tags:
3995 if tags:
3994 output.extend(ctx.tags())
3996 output.extend(ctx.tags())
3995
3997
3996 if bookmarks:
3998 if bookmarks:
3997 output.extend(ctx.bookmarks())
3999 output.extend(ctx.bookmarks())
3998
4000
3999 ui.write("%s\n" % ' '.join(output))
4001 ui.write("%s\n" % ' '.join(output))
4000
4002
4001 @command('import|patch',
4003 @command('import|patch',
4002 [('p', 'strip', 1,
4004 [('p', 'strip', 1,
4003 _('directory strip option for patch. This has the same '
4005 _('directory strip option for patch. This has the same '
4004 'meaning as the corresponding patch option'), _('NUM')),
4006 'meaning as the corresponding patch option'), _('NUM')),
4005 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4007 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4006 ('e', 'edit', False, _('invoke editor on commit messages')),
4008 ('e', 'edit', False, _('invoke editor on commit messages')),
4007 ('f', 'force', None,
4009 ('f', 'force', None,
4008 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4010 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4009 ('', 'no-commit', None,
4011 ('', 'no-commit', None,
4010 _("don't commit, just update the working directory")),
4012 _("don't commit, just update the working directory")),
4011 ('', 'bypass', None,
4013 ('', 'bypass', None,
4012 _("apply patch without touching the working directory")),
4014 _("apply patch without touching the working directory")),
4013 ('', 'partial', None,
4015 ('', 'partial', None,
4014 _('commit even if some hunks fail')),
4016 _('commit even if some hunks fail')),
4015 ('', 'exact', None,
4017 ('', 'exact', None,
4016 _('apply patch to the nodes from which it was generated')),
4018 _('apply patch to the nodes from which it was generated')),
4017 ('', 'import-branch', None,
4019 ('', 'import-branch', None,
4018 _('use any branch information in patch (implied by --exact)'))] +
4020 _('use any branch information in patch (implied by --exact)'))] +
4019 commitopts + commitopts2 + similarityopts,
4021 commitopts + commitopts2 + similarityopts,
4020 _('[OPTION]... PATCH...'))
4022 _('[OPTION]... PATCH...'))
4021 def import_(ui, repo, patch1=None, *patches, **opts):
4023 def import_(ui, repo, patch1=None, *patches, **opts):
4022 """import an ordered set of patches
4024 """import an ordered set of patches
4023
4025
4024 Import a list of patches and commit them individually (unless
4026 Import a list of patches and commit them individually (unless
4025 --no-commit is specified).
4027 --no-commit is specified).
4026
4028
4027 Because import first applies changes to the working directory,
4029 Because import first applies changes to the working directory,
4028 import will abort if there are outstanding changes.
4030 import will abort if there are outstanding changes.
4029
4031
4030 You can import a patch straight from a mail message. Even patches
4032 You can import a patch straight from a mail message. Even patches
4031 as attachments work (to use the body part, it must have type
4033 as attachments work (to use the body part, it must have type
4032 text/plain or text/x-patch). From and Subject headers of email
4034 text/plain or text/x-patch). From and Subject headers of email
4033 message are used as default committer and commit message. All
4035 message are used as default committer and commit message. All
4034 text/plain body parts before first diff are added to commit
4036 text/plain body parts before first diff are added to commit
4035 message.
4037 message.
4036
4038
4037 If the imported patch was generated by :hg:`export`, user and
4039 If the imported patch was generated by :hg:`export`, user and
4038 description from patch override values from message headers and
4040 description from patch override values from message headers and
4039 body. Values given on command line with -m/--message and -u/--user
4041 body. Values given on command line with -m/--message and -u/--user
4040 override these.
4042 override these.
4041
4043
4042 If --exact is specified, import will set the working directory to
4044 If --exact is specified, import will set the working directory to
4043 the parent of each patch before applying it, and will abort if the
4045 the parent of each patch before applying it, and will abort if the
4044 resulting changeset has a different ID than the one recorded in
4046 resulting changeset has a different ID than the one recorded in
4045 the patch. This may happen due to character set problems or other
4047 the patch. This may happen due to character set problems or other
4046 deficiencies in the text patch format.
4048 deficiencies in the text patch format.
4047
4049
4048 Use --bypass to apply and commit patches directly to the
4050 Use --bypass to apply and commit patches directly to the
4049 repository, not touching the working directory. Without --exact,
4051 repository, not touching the working directory. Without --exact,
4050 patches will be applied on top of the working directory parent
4052 patches will be applied on top of the working directory parent
4051 revision.
4053 revision.
4052
4054
4053 With -s/--similarity, hg will attempt to discover renames and
4055 With -s/--similarity, hg will attempt to discover renames and
4054 copies in the patch in the same way as :hg:`addremove`.
4056 copies in the patch in the same way as :hg:`addremove`.
4055
4057
4056 Use --partial to ensure a changeset will be created from the patch
4058 Use --partial to ensure a changeset will be created from the patch
4057 even if some hunks fail to apply. Hunks that fail to apply will be
4059 even if some hunks fail to apply. Hunks that fail to apply will be
4058 written to a <target-file>.rej file. Conflicts can then be resolved
4060 written to a <target-file>.rej file. Conflicts can then be resolved
4059 by hand before :hg:`commit --amend` is run to update the created
4061 by hand before :hg:`commit --amend` is run to update the created
4060 changeset. This flag exists to let people import patches that
4062 changeset. This flag exists to let people import patches that
4061 partially apply without losing the associated metadata (author,
4063 partially apply without losing the associated metadata (author,
4062 date, description, ...). Note that when none of the hunk applies
4064 date, description, ...). Note that when none of the hunk applies
4063 cleanly, :hg:`import --partial` will create an empty changeset,
4065 cleanly, :hg:`import --partial` will create an empty changeset,
4064 importing only the patch metadata.
4066 importing only the patch metadata.
4065
4067
4066 To read a patch from standard input, use "-" as the patch name. If
4068 To read a patch from standard input, use "-" as the patch name. If
4067 a URL is specified, the patch will be downloaded from it.
4069 a URL is specified, the patch will be downloaded from it.
4068 See :hg:`help dates` for a list of formats valid for -d/--date.
4070 See :hg:`help dates` for a list of formats valid for -d/--date.
4069
4071
4070 .. container:: verbose
4072 .. container:: verbose
4071
4073
4072 Examples:
4074 Examples:
4073
4075
4074 - import a traditional patch from a website and detect renames::
4076 - import a traditional patch from a website and detect renames::
4075
4077
4076 hg import -s 80 http://example.com/bugfix.patch
4078 hg import -s 80 http://example.com/bugfix.patch
4077
4079
4078 - import a changeset from an hgweb server::
4080 - import a changeset from an hgweb server::
4079
4081
4080 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4082 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4081
4083
4082 - import all the patches in an Unix-style mbox::
4084 - import all the patches in an Unix-style mbox::
4083
4085
4084 hg import incoming-patches.mbox
4086 hg import incoming-patches.mbox
4085
4087
4086 - attempt to exactly restore an exported changeset (not always
4088 - attempt to exactly restore an exported changeset (not always
4087 possible)::
4089 possible)::
4088
4090
4089 hg import --exact proposed-fix.patch
4091 hg import --exact proposed-fix.patch
4090
4092
4091 Returns 0 on success, 1 on partial success (see --partial).
4093 Returns 0 on success, 1 on partial success (see --partial).
4092 """
4094 """
4093
4095
4094 if not patch1:
4096 if not patch1:
4095 raise util.Abort(_('need at least one patch to import'))
4097 raise util.Abort(_('need at least one patch to import'))
4096
4098
4097 patches = (patch1,) + patches
4099 patches = (patch1,) + patches
4098
4100
4099 date = opts.get('date')
4101 date = opts.get('date')
4100 if date:
4102 if date:
4101 opts['date'] = util.parsedate(date)
4103 opts['date'] = util.parsedate(date)
4102
4104
4103 update = not opts.get('bypass')
4105 update = not opts.get('bypass')
4104 if not update and opts.get('no_commit'):
4106 if not update and opts.get('no_commit'):
4105 raise util.Abort(_('cannot use --no-commit with --bypass'))
4107 raise util.Abort(_('cannot use --no-commit with --bypass'))
4106 try:
4108 try:
4107 sim = float(opts.get('similarity') or 0)
4109 sim = float(opts.get('similarity') or 0)
4108 except ValueError:
4110 except ValueError:
4109 raise util.Abort(_('similarity must be a number'))
4111 raise util.Abort(_('similarity must be a number'))
4110 if sim < 0 or sim > 100:
4112 if sim < 0 or sim > 100:
4111 raise util.Abort(_('similarity must be between 0 and 100'))
4113 raise util.Abort(_('similarity must be between 0 and 100'))
4112 if sim and not update:
4114 if sim and not update:
4113 raise util.Abort(_('cannot use --similarity with --bypass'))
4115 raise util.Abort(_('cannot use --similarity with --bypass'))
4114 if opts.get('exact') and opts.get('edit'):
4116 if opts.get('exact') and opts.get('edit'):
4115 raise util.Abort(_('cannot use --exact with --edit'))
4117 raise util.Abort(_('cannot use --exact with --edit'))
4116
4118
4117 if update:
4119 if update:
4118 cmdutil.checkunfinished(repo)
4120 cmdutil.checkunfinished(repo)
4119 if (opts.get('exact') or not opts.get('force')) and update:
4121 if (opts.get('exact') or not opts.get('force')) and update:
4120 cmdutil.bailifchanged(repo)
4122 cmdutil.bailifchanged(repo)
4121
4123
4122 base = opts["base"]
4124 base = opts["base"]
4123 wlock = lock = tr = None
4125 wlock = lock = tr = None
4124 msgs = []
4126 msgs = []
4125 ret = 0
4127 ret = 0
4126
4128
4127
4129
4128 try:
4130 try:
4129 try:
4131 try:
4130 wlock = repo.wlock()
4132 wlock = repo.wlock()
4131 repo.dirstate.beginparentchange()
4133 repo.dirstate.beginparentchange()
4132 if not opts.get('no_commit'):
4134 if not opts.get('no_commit'):
4133 lock = repo.lock()
4135 lock = repo.lock()
4134 tr = repo.transaction('import')
4136 tr = repo.transaction('import')
4135 parents = repo.parents()
4137 parents = repo.parents()
4136 for patchurl in patches:
4138 for patchurl in patches:
4137 if patchurl == '-':
4139 if patchurl == '-':
4138 ui.status(_('applying patch from stdin\n'))
4140 ui.status(_('applying patch from stdin\n'))
4139 patchfile = ui.fin
4141 patchfile = ui.fin
4140 patchurl = 'stdin' # for error message
4142 patchurl = 'stdin' # for error message
4141 else:
4143 else:
4142 patchurl = os.path.join(base, patchurl)
4144 patchurl = os.path.join(base, patchurl)
4143 ui.status(_('applying %s\n') % patchurl)
4145 ui.status(_('applying %s\n') % patchurl)
4144 patchfile = hg.openpath(ui, patchurl)
4146 patchfile = hg.openpath(ui, patchurl)
4145
4147
4146 haspatch = False
4148 haspatch = False
4147 for hunk in patch.split(patchfile):
4149 for hunk in patch.split(patchfile):
4148 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4150 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4149 parents, opts,
4151 parents, opts,
4150 msgs, hg.clean)
4152 msgs, hg.clean)
4151 if msg:
4153 if msg:
4152 haspatch = True
4154 haspatch = True
4153 ui.note(msg + '\n')
4155 ui.note(msg + '\n')
4154 if update or opts.get('exact'):
4156 if update or opts.get('exact'):
4155 parents = repo.parents()
4157 parents = repo.parents()
4156 else:
4158 else:
4157 parents = [repo[node]]
4159 parents = [repo[node]]
4158 if rej:
4160 if rej:
4159 ui.write_err(_("patch applied partially\n"))
4161 ui.write_err(_("patch applied partially\n"))
4160 ui.write_err(_("(fix the .rej files and run "
4162 ui.write_err(_("(fix the .rej files and run "
4161 "`hg commit --amend`)\n"))
4163 "`hg commit --amend`)\n"))
4162 ret = 1
4164 ret = 1
4163 break
4165 break
4164
4166
4165 if not haspatch:
4167 if not haspatch:
4166 raise util.Abort(_('%s: no diffs found') % patchurl)
4168 raise util.Abort(_('%s: no diffs found') % patchurl)
4167
4169
4168 if tr:
4170 if tr:
4169 tr.close()
4171 tr.close()
4170 if msgs:
4172 if msgs:
4171 repo.savecommitmessage('\n* * *\n'.join(msgs))
4173 repo.savecommitmessage('\n* * *\n'.join(msgs))
4172 repo.dirstate.endparentchange()
4174 repo.dirstate.endparentchange()
4173 return ret
4175 return ret
4174 except: # re-raises
4176 except: # re-raises
4175 # wlock.release() indirectly calls dirstate.write(): since
4177 # wlock.release() indirectly calls dirstate.write(): since
4176 # we're crashing, we do not want to change the working dir
4178 # we're crashing, we do not want to change the working dir
4177 # parent after all, so make sure it writes nothing
4179 # parent after all, so make sure it writes nothing
4178 repo.dirstate.invalidate()
4180 repo.dirstate.invalidate()
4179 raise
4181 raise
4180 finally:
4182 finally:
4181 if tr:
4183 if tr:
4182 tr.release()
4184 tr.release()
4183 release(lock, wlock)
4185 release(lock, wlock)
4184
4186
4185 @command('incoming|in',
4187 @command('incoming|in',
4186 [('f', 'force', None,
4188 [('f', 'force', None,
4187 _('run even if remote repository is unrelated')),
4189 _('run even if remote repository is unrelated')),
4188 ('n', 'newest-first', None, _('show newest record first')),
4190 ('n', 'newest-first', None, _('show newest record first')),
4189 ('', 'bundle', '',
4191 ('', 'bundle', '',
4190 _('file to store the bundles into'), _('FILE')),
4192 _('file to store the bundles into'), _('FILE')),
4191 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4193 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4192 ('B', 'bookmarks', False, _("compare bookmarks")),
4194 ('B', 'bookmarks', False, _("compare bookmarks")),
4193 ('b', 'branch', [],
4195 ('b', 'branch', [],
4194 _('a specific branch you would like to pull'), _('BRANCH')),
4196 _('a specific branch you would like to pull'), _('BRANCH')),
4195 ] + logopts + remoteopts + subrepoopts,
4197 ] + logopts + remoteopts + subrepoopts,
4196 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4198 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4197 def incoming(ui, repo, source="default", **opts):
4199 def incoming(ui, repo, source="default", **opts):
4198 """show new changesets found in source
4200 """show new changesets found in source
4199
4201
4200 Show new changesets found in the specified path/URL or the default
4202 Show new changesets found in the specified path/URL or the default
4201 pull location. These are the changesets that would have been pulled
4203 pull location. These are the changesets that would have been pulled
4202 if a pull at the time you issued this command.
4204 if a pull at the time you issued this command.
4203
4205
4204 For remote repository, using --bundle avoids downloading the
4206 For remote repository, using --bundle avoids downloading the
4205 changesets twice if the incoming is followed by a pull.
4207 changesets twice if the incoming is followed by a pull.
4206
4208
4207 See pull for valid source format details.
4209 See pull for valid source format details.
4208
4210
4209 .. container:: verbose
4211 .. container:: verbose
4210
4212
4211 Examples:
4213 Examples:
4212
4214
4213 - show incoming changes with patches and full description::
4215 - show incoming changes with patches and full description::
4214
4216
4215 hg incoming -vp
4217 hg incoming -vp
4216
4218
4217 - show incoming changes excluding merges, store a bundle::
4219 - show incoming changes excluding merges, store a bundle::
4218
4220
4219 hg in -vpM --bundle incoming.hg
4221 hg in -vpM --bundle incoming.hg
4220 hg pull incoming.hg
4222 hg pull incoming.hg
4221
4223
4222 - briefly list changes inside a bundle::
4224 - briefly list changes inside a bundle::
4223
4225
4224 hg in changes.hg -T "{desc|firstline}\\n"
4226 hg in changes.hg -T "{desc|firstline}\\n"
4225
4227
4226 Returns 0 if there are incoming changes, 1 otherwise.
4228 Returns 0 if there are incoming changes, 1 otherwise.
4227 """
4229 """
4228 if opts.get('graph'):
4230 if opts.get('graph'):
4229 cmdutil.checkunsupportedgraphflags([], opts)
4231 cmdutil.checkunsupportedgraphflags([], opts)
4230 def display(other, chlist, displayer):
4232 def display(other, chlist, displayer):
4231 revdag = cmdutil.graphrevs(other, chlist, opts)
4233 revdag = cmdutil.graphrevs(other, chlist, opts)
4232 showparents = [ctx.node() for ctx in repo[None].parents()]
4234 showparents = [ctx.node() for ctx in repo[None].parents()]
4233 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4235 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4234 graphmod.asciiedges)
4236 graphmod.asciiedges)
4235
4237
4236 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4238 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4237 return 0
4239 return 0
4238
4240
4239 if opts.get('bundle') and opts.get('subrepos'):
4241 if opts.get('bundle') and opts.get('subrepos'):
4240 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4242 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4241
4243
4242 if opts.get('bookmarks'):
4244 if opts.get('bookmarks'):
4243 source, branches = hg.parseurl(ui.expandpath(source),
4245 source, branches = hg.parseurl(ui.expandpath(source),
4244 opts.get('branch'))
4246 opts.get('branch'))
4245 other = hg.peer(repo, opts, source)
4247 other = hg.peer(repo, opts, source)
4246 if 'bookmarks' not in other.listkeys('namespaces'):
4248 if 'bookmarks' not in other.listkeys('namespaces'):
4247 ui.warn(_("remote doesn't support bookmarks\n"))
4249 ui.warn(_("remote doesn't support bookmarks\n"))
4248 return 0
4250 return 0
4249 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4251 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4250 return bookmarks.diff(ui, repo, other)
4252 return bookmarks.diff(ui, repo, other)
4251
4253
4252 repo._subtoppath = ui.expandpath(source)
4254 repo._subtoppath = ui.expandpath(source)
4253 try:
4255 try:
4254 return hg.incoming(ui, repo, source, opts)
4256 return hg.incoming(ui, repo, source, opts)
4255 finally:
4257 finally:
4256 del repo._subtoppath
4258 del repo._subtoppath
4257
4259
4258
4260
4259 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4261 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4260 norepo=True)
4262 norepo=True)
4261 def init(ui, dest=".", **opts):
4263 def init(ui, dest=".", **opts):
4262 """create a new repository in the given directory
4264 """create a new repository in the given directory
4263
4265
4264 Initialize a new repository in the given directory. If the given
4266 Initialize a new repository in the given directory. If the given
4265 directory does not exist, it will be created.
4267 directory does not exist, it will be created.
4266
4268
4267 If no directory is given, the current directory is used.
4269 If no directory is given, the current directory is used.
4268
4270
4269 It is possible to specify an ``ssh://`` URL as the destination.
4271 It is possible to specify an ``ssh://`` URL as the destination.
4270 See :hg:`help urls` for more information.
4272 See :hg:`help urls` for more information.
4271
4273
4272 Returns 0 on success.
4274 Returns 0 on success.
4273 """
4275 """
4274 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4276 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4275
4277
4276 @command('locate',
4278 @command('locate',
4277 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4279 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4278 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4280 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4279 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4281 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4280 ] + walkopts,
4282 ] + walkopts,
4281 _('[OPTION]... [PATTERN]...'))
4283 _('[OPTION]... [PATTERN]...'))
4282 def locate(ui, repo, *pats, **opts):
4284 def locate(ui, repo, *pats, **opts):
4283 """locate files matching specific patterns (DEPRECATED)
4285 """locate files matching specific patterns (DEPRECATED)
4284
4286
4285 Print files under Mercurial control in the working directory whose
4287 Print files under Mercurial control in the working directory whose
4286 names match the given patterns.
4288 names match the given patterns.
4287
4289
4288 By default, this command searches all directories in the working
4290 By default, this command searches all directories in the working
4289 directory. To search just the current directory and its
4291 directory. To search just the current directory and its
4290 subdirectories, use "--include .".
4292 subdirectories, use "--include .".
4291
4293
4292 If no patterns are given to match, this command prints the names
4294 If no patterns are given to match, this command prints the names
4293 of all files under Mercurial control in the working directory.
4295 of all files under Mercurial control in the working directory.
4294
4296
4295 If you want to feed the output of this command into the "xargs"
4297 If you want to feed the output of this command into the "xargs"
4296 command, use the -0 option to both this command and "xargs". This
4298 command, use the -0 option to both this command and "xargs". This
4297 will avoid the problem of "xargs" treating single filenames that
4299 will avoid the problem of "xargs" treating single filenames that
4298 contain whitespace as multiple filenames.
4300 contain whitespace as multiple filenames.
4299
4301
4300 See :hg:`help files` for a more versatile command.
4302 See :hg:`help files` for a more versatile command.
4301
4303
4302 Returns 0 if a match is found, 1 otherwise.
4304 Returns 0 if a match is found, 1 otherwise.
4303 """
4305 """
4304 end = opts.get('print0') and '\0' or '\n'
4306 end = opts.get('print0') and '\0' or '\n'
4305 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4307 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4306
4308
4307 ret = 1
4309 ret = 1
4308 ctx = repo[rev]
4310 ctx = repo[rev]
4309 m = scmutil.match(ctx, pats, opts, default='relglob')
4311 m = scmutil.match(ctx, pats, opts, default='relglob')
4310 m.bad = lambda x, y: False
4312 m.bad = lambda x, y: False
4311
4313
4312 for abs in ctx.matches(m):
4314 for abs in ctx.matches(m):
4313 if opts.get('fullpath'):
4315 if opts.get('fullpath'):
4314 ui.write(repo.wjoin(abs), end)
4316 ui.write(repo.wjoin(abs), end)
4315 else:
4317 else:
4316 ui.write(((pats and m.rel(abs)) or abs), end)
4318 ui.write(((pats and m.rel(abs)) or abs), end)
4317 ret = 0
4319 ret = 0
4318
4320
4319 return ret
4321 return ret
4320
4322
4321 @command('^log|history',
4323 @command('^log|history',
4322 [('f', 'follow', None,
4324 [('f', 'follow', None,
4323 _('follow changeset history, or file history across copies and renames')),
4325 _('follow changeset history, or file history across copies and renames')),
4324 ('', 'follow-first', None,
4326 ('', 'follow-first', None,
4325 _('only follow the first parent of merge changesets (DEPRECATED)')),
4327 _('only follow the first parent of merge changesets (DEPRECATED)')),
4326 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4328 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4327 ('C', 'copies', None, _('show copied files')),
4329 ('C', 'copies', None, _('show copied files')),
4328 ('k', 'keyword', [],
4330 ('k', 'keyword', [],
4329 _('do case-insensitive search for a given text'), _('TEXT')),
4331 _('do case-insensitive search for a given text'), _('TEXT')),
4330 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4332 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4331 ('', 'removed', None, _('include revisions where files were removed')),
4333 ('', 'removed', None, _('include revisions where files were removed')),
4332 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4334 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4333 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4335 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4334 ('', 'only-branch', [],
4336 ('', 'only-branch', [],
4335 _('show only changesets within the given named branch (DEPRECATED)'),
4337 _('show only changesets within the given named branch (DEPRECATED)'),
4336 _('BRANCH')),
4338 _('BRANCH')),
4337 ('b', 'branch', [],
4339 ('b', 'branch', [],
4338 _('show changesets within the given named branch'), _('BRANCH')),
4340 _('show changesets within the given named branch'), _('BRANCH')),
4339 ('P', 'prune', [],
4341 ('P', 'prune', [],
4340 _('do not display revision or any of its ancestors'), _('REV')),
4342 _('do not display revision or any of its ancestors'), _('REV')),
4341 ] + logopts + walkopts,
4343 ] + logopts + walkopts,
4342 _('[OPTION]... [FILE]'),
4344 _('[OPTION]... [FILE]'),
4343 inferrepo=True)
4345 inferrepo=True)
4344 def log(ui, repo, *pats, **opts):
4346 def log(ui, repo, *pats, **opts):
4345 """show revision history of entire repository or files
4347 """show revision history of entire repository or files
4346
4348
4347 Print the revision history of the specified files or the entire
4349 Print the revision history of the specified files or the entire
4348 project.
4350 project.
4349
4351
4350 If no revision range is specified, the default is ``tip:0`` unless
4352 If no revision range is specified, the default is ``tip:0`` unless
4351 --follow is set, in which case the working directory parent is
4353 --follow is set, in which case the working directory parent is
4352 used as the starting revision.
4354 used as the starting revision.
4353
4355
4354 File history is shown without following rename or copy history of
4356 File history is shown without following rename or copy history of
4355 files. Use -f/--follow with a filename to follow history across
4357 files. Use -f/--follow with a filename to follow history across
4356 renames and copies. --follow without a filename will only show
4358 renames and copies. --follow without a filename will only show
4357 ancestors or descendants of the starting revision.
4359 ancestors or descendants of the starting revision.
4358
4360
4359 By default this command prints revision number and changeset id,
4361 By default this command prints revision number and changeset id,
4360 tags, non-trivial parents, user, date and time, and a summary for
4362 tags, non-trivial parents, user, date and time, and a summary for
4361 each commit. When the -v/--verbose switch is used, the list of
4363 each commit. When the -v/--verbose switch is used, the list of
4362 changed files and full commit message are shown.
4364 changed files and full commit message are shown.
4363
4365
4364 With --graph the revisions are shown as an ASCII art DAG with the most
4366 With --graph the revisions are shown as an ASCII art DAG with the most
4365 recent changeset at the top.
4367 recent changeset at the top.
4366 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4368 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4367 and '+' represents a fork where the changeset from the lines below is a
4369 and '+' represents a fork where the changeset from the lines below is a
4368 parent of the 'o' merge on the same line.
4370 parent of the 'o' merge on the same line.
4369
4371
4370 .. note::
4372 .. note::
4371
4373
4372 log -p/--patch may generate unexpected diff output for merge
4374 log -p/--patch may generate unexpected diff output for merge
4373 changesets, as it will only compare the merge changeset against
4375 changesets, as it will only compare the merge changeset against
4374 its first parent. Also, only files different from BOTH parents
4376 its first parent. Also, only files different from BOTH parents
4375 will appear in files:.
4377 will appear in files:.
4376
4378
4377 .. note::
4379 .. note::
4378
4380
4379 for performance reasons, log FILE may omit duplicate changes
4381 for performance reasons, log FILE may omit duplicate changes
4380 made on branches and will not show removals or mode changes. To
4382 made on branches and will not show removals or mode changes. To
4381 see all such changes, use the --removed switch.
4383 see all such changes, use the --removed switch.
4382
4384
4383 .. container:: verbose
4385 .. container:: verbose
4384
4386
4385 Some examples:
4387 Some examples:
4386
4388
4387 - changesets with full descriptions and file lists::
4389 - changesets with full descriptions and file lists::
4388
4390
4389 hg log -v
4391 hg log -v
4390
4392
4391 - changesets ancestral to the working directory::
4393 - changesets ancestral to the working directory::
4392
4394
4393 hg log -f
4395 hg log -f
4394
4396
4395 - last 10 commits on the current branch::
4397 - last 10 commits on the current branch::
4396
4398
4397 hg log -l 10 -b .
4399 hg log -l 10 -b .
4398
4400
4399 - changesets showing all modifications of a file, including removals::
4401 - changesets showing all modifications of a file, including removals::
4400
4402
4401 hg log --removed file.c
4403 hg log --removed file.c
4402
4404
4403 - all changesets that touch a directory, with diffs, excluding merges::
4405 - all changesets that touch a directory, with diffs, excluding merges::
4404
4406
4405 hg log -Mp lib/
4407 hg log -Mp lib/
4406
4408
4407 - all revision numbers that match a keyword::
4409 - all revision numbers that match a keyword::
4408
4410
4409 hg log -k bug --template "{rev}\\n"
4411 hg log -k bug --template "{rev}\\n"
4410
4412
4411 - list available log templates::
4413 - list available log templates::
4412
4414
4413 hg log -T list
4415 hg log -T list
4414
4416
4415 - check if a given changeset is included in a tagged release::
4417 - check if a given changeset is included in a tagged release::
4416
4418
4417 hg log -r "a21ccf and ancestor(1.9)"
4419 hg log -r "a21ccf and ancestor(1.9)"
4418
4420
4419 - find all changesets by some user in a date range::
4421 - find all changesets by some user in a date range::
4420
4422
4421 hg log -k alice -d "may 2008 to jul 2008"
4423 hg log -k alice -d "may 2008 to jul 2008"
4422
4424
4423 - summary of all changesets after the last tag::
4425 - summary of all changesets after the last tag::
4424
4426
4425 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4427 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4426
4428
4427 See :hg:`help dates` for a list of formats valid for -d/--date.
4429 See :hg:`help dates` for a list of formats valid for -d/--date.
4428
4430
4429 See :hg:`help revisions` and :hg:`help revsets` for more about
4431 See :hg:`help revisions` and :hg:`help revsets` for more about
4430 specifying revisions.
4432 specifying revisions.
4431
4433
4432 See :hg:`help templates` for more about pre-packaged styles and
4434 See :hg:`help templates` for more about pre-packaged styles and
4433 specifying custom templates.
4435 specifying custom templates.
4434
4436
4435 Returns 0 on success.
4437 Returns 0 on success.
4436
4438
4437 """
4439 """
4438 if opts.get('graph'):
4440 if opts.get('graph'):
4439 return cmdutil.graphlog(ui, repo, *pats, **opts)
4441 return cmdutil.graphlog(ui, repo, *pats, **opts)
4440
4442
4441 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4443 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4442 limit = cmdutil.loglimit(opts)
4444 limit = cmdutil.loglimit(opts)
4443 count = 0
4445 count = 0
4444
4446
4445 getrenamed = None
4447 getrenamed = None
4446 if opts.get('copies'):
4448 if opts.get('copies'):
4447 endrev = None
4449 endrev = None
4448 if opts.get('rev'):
4450 if opts.get('rev'):
4449 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4451 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4450 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4452 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4451
4453
4452 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4454 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4453 for rev in revs:
4455 for rev in revs:
4454 if count == limit:
4456 if count == limit:
4455 break
4457 break
4456 ctx = repo[rev]
4458 ctx = repo[rev]
4457 copies = None
4459 copies = None
4458 if getrenamed is not None and rev:
4460 if getrenamed is not None and rev:
4459 copies = []
4461 copies = []
4460 for fn in ctx.files():
4462 for fn in ctx.files():
4461 rename = getrenamed(fn, rev)
4463 rename = getrenamed(fn, rev)
4462 if rename:
4464 if rename:
4463 copies.append((fn, rename[0]))
4465 copies.append((fn, rename[0]))
4464 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4466 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4465 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4467 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4466 if displayer.flush(rev):
4468 if displayer.flush(rev):
4467 count += 1
4469 count += 1
4468
4470
4469 displayer.close()
4471 displayer.close()
4470
4472
4471 @command('manifest',
4473 @command('manifest',
4472 [('r', 'rev', '', _('revision to display'), _('REV')),
4474 [('r', 'rev', '', _('revision to display'), _('REV')),
4473 ('', 'all', False, _("list files from all revisions"))]
4475 ('', 'all', False, _("list files from all revisions"))]
4474 + formatteropts,
4476 + formatteropts,
4475 _('[-r REV]'))
4477 _('[-r REV]'))
4476 def manifest(ui, repo, node=None, rev=None, **opts):
4478 def manifest(ui, repo, node=None, rev=None, **opts):
4477 """output the current or given revision of the project manifest
4479 """output the current or given revision of the project manifest
4478
4480
4479 Print a list of version controlled files for the given revision.
4481 Print a list of version controlled files for the given revision.
4480 If no revision is given, the first parent of the working directory
4482 If no revision is given, the first parent of the working directory
4481 is used, or the null revision if no revision is checked out.
4483 is used, or the null revision if no revision is checked out.
4482
4484
4483 With -v, print file permissions, symlink and executable bits.
4485 With -v, print file permissions, symlink and executable bits.
4484 With --debug, print file revision hashes.
4486 With --debug, print file revision hashes.
4485
4487
4486 If option --all is specified, the list of all files from all revisions
4488 If option --all is specified, the list of all files from all revisions
4487 is printed. This includes deleted and renamed files.
4489 is printed. This includes deleted and renamed files.
4488
4490
4489 Returns 0 on success.
4491 Returns 0 on success.
4490 """
4492 """
4491
4493
4492 fm = ui.formatter('manifest', opts)
4494 fm = ui.formatter('manifest', opts)
4493
4495
4494 if opts.get('all'):
4496 if opts.get('all'):
4495 if rev or node:
4497 if rev or node:
4496 raise util.Abort(_("can't specify a revision with --all"))
4498 raise util.Abort(_("can't specify a revision with --all"))
4497
4499
4498 res = []
4500 res = []
4499 prefix = "data/"
4501 prefix = "data/"
4500 suffix = ".i"
4502 suffix = ".i"
4501 plen = len(prefix)
4503 plen = len(prefix)
4502 slen = len(suffix)
4504 slen = len(suffix)
4503 lock = repo.lock()
4505 lock = repo.lock()
4504 try:
4506 try:
4505 for fn, b, size in repo.store.datafiles():
4507 for fn, b, size in repo.store.datafiles():
4506 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4508 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4507 res.append(fn[plen:-slen])
4509 res.append(fn[plen:-slen])
4508 finally:
4510 finally:
4509 lock.release()
4511 lock.release()
4510 for f in res:
4512 for f in res:
4511 fm.startitem()
4513 fm.startitem()
4512 fm.write("path", '%s\n', f)
4514 fm.write("path", '%s\n', f)
4513 fm.end()
4515 fm.end()
4514 return
4516 return
4515
4517
4516 if rev and node:
4518 if rev and node:
4517 raise util.Abort(_("please specify just one revision"))
4519 raise util.Abort(_("please specify just one revision"))
4518
4520
4519 if not node:
4521 if not node:
4520 node = rev
4522 node = rev
4521
4523
4522 char = {'l': '@', 'x': '*', '': ''}
4524 char = {'l': '@', 'x': '*', '': ''}
4523 mode = {'l': '644', 'x': '755', '': '644'}
4525 mode = {'l': '644', 'x': '755', '': '644'}
4524 ctx = scmutil.revsingle(repo, node)
4526 ctx = scmutil.revsingle(repo, node)
4525 mf = ctx.manifest()
4527 mf = ctx.manifest()
4526 for f in ctx:
4528 for f in ctx:
4527 fm.startitem()
4529 fm.startitem()
4528 fl = ctx[f].flags()
4530 fl = ctx[f].flags()
4529 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4531 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4530 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4532 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4531 fm.write('path', '%s\n', f)
4533 fm.write('path', '%s\n', f)
4532 fm.end()
4534 fm.end()
4533
4535
4534 @command('^merge',
4536 @command('^merge',
4535 [('f', 'force', None,
4537 [('f', 'force', None,
4536 _('force a merge including outstanding changes (DEPRECATED)')),
4538 _('force a merge including outstanding changes (DEPRECATED)')),
4537 ('r', 'rev', '', _('revision to merge'), _('REV')),
4539 ('r', 'rev', '', _('revision to merge'), _('REV')),
4538 ('P', 'preview', None,
4540 ('P', 'preview', None,
4539 _('review revisions to merge (no merge is performed)'))
4541 _('review revisions to merge (no merge is performed)'))
4540 ] + mergetoolopts,
4542 ] + mergetoolopts,
4541 _('[-P] [-f] [[-r] REV]'))
4543 _('[-P] [-f] [[-r] REV]'))
4542 def merge(ui, repo, node=None, **opts):
4544 def merge(ui, repo, node=None, **opts):
4543 """merge working directory with another revision
4545 """merge working directory with another revision
4544
4546
4545 The current working directory is updated with all changes made in
4547 The current working directory is updated with all changes made in
4546 the requested revision since the last common predecessor revision.
4548 the requested revision since the last common predecessor revision.
4547
4549
4548 Files that changed between either parent are marked as changed for
4550 Files that changed between either parent are marked as changed for
4549 the next commit and a commit must be performed before any further
4551 the next commit and a commit must be performed before any further
4550 updates to the repository are allowed. The next commit will have
4552 updates to the repository are allowed. The next commit will have
4551 two parents.
4553 two parents.
4552
4554
4553 ``--tool`` can be used to specify the merge tool used for file
4555 ``--tool`` can be used to specify the merge tool used for file
4554 merges. It overrides the HGMERGE environment variable and your
4556 merges. It overrides the HGMERGE environment variable and your
4555 configuration files. See :hg:`help merge-tools` for options.
4557 configuration files. See :hg:`help merge-tools` for options.
4556
4558
4557 If no revision is specified, the working directory's parent is a
4559 If no revision is specified, the working directory's parent is a
4558 head revision, and the current branch contains exactly one other
4560 head revision, and the current branch contains exactly one other
4559 head, the other head is merged with by default. Otherwise, an
4561 head, the other head is merged with by default. Otherwise, an
4560 explicit revision with which to merge with must be provided.
4562 explicit revision with which to merge with must be provided.
4561
4563
4562 :hg:`resolve` must be used to resolve unresolved files.
4564 :hg:`resolve` must be used to resolve unresolved files.
4563
4565
4564 To undo an uncommitted merge, use :hg:`update --clean .` which
4566 To undo an uncommitted merge, use :hg:`update --clean .` which
4565 will check out a clean copy of the original merge parent, losing
4567 will check out a clean copy of the original merge parent, losing
4566 all changes.
4568 all changes.
4567
4569
4568 Returns 0 on success, 1 if there are unresolved files.
4570 Returns 0 on success, 1 if there are unresolved files.
4569 """
4571 """
4570
4572
4571 if opts.get('rev') and node:
4573 if opts.get('rev') and node:
4572 raise util.Abort(_("please specify just one revision"))
4574 raise util.Abort(_("please specify just one revision"))
4573 if not node:
4575 if not node:
4574 node = opts.get('rev')
4576 node = opts.get('rev')
4575
4577
4576 if node:
4578 if node:
4577 node = scmutil.revsingle(repo, node).node()
4579 node = scmutil.revsingle(repo, node).node()
4578
4580
4579 if not node and repo._bookmarkcurrent:
4581 if not node and repo._bookmarkcurrent:
4580 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4582 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4581 curhead = repo[repo._bookmarkcurrent].node()
4583 curhead = repo[repo._bookmarkcurrent].node()
4582 if len(bmheads) == 2:
4584 if len(bmheads) == 2:
4583 if curhead == bmheads[0]:
4585 if curhead == bmheads[0]:
4584 node = bmheads[1]
4586 node = bmheads[1]
4585 else:
4587 else:
4586 node = bmheads[0]
4588 node = bmheads[0]
4587 elif len(bmheads) > 2:
4589 elif len(bmheads) > 2:
4588 raise util.Abort(_("multiple matching bookmarks to merge - "
4590 raise util.Abort(_("multiple matching bookmarks to merge - "
4589 "please merge with an explicit rev or bookmark"),
4591 "please merge with an explicit rev or bookmark"),
4590 hint=_("run 'hg heads' to see all heads"))
4592 hint=_("run 'hg heads' to see all heads"))
4591 elif len(bmheads) <= 1:
4593 elif len(bmheads) <= 1:
4592 raise util.Abort(_("no matching bookmark to merge - "
4594 raise util.Abort(_("no matching bookmark to merge - "
4593 "please merge with an explicit rev or bookmark"),
4595 "please merge with an explicit rev or bookmark"),
4594 hint=_("run 'hg heads' to see all heads"))
4596 hint=_("run 'hg heads' to see all heads"))
4595
4597
4596 if not node and not repo._bookmarkcurrent:
4598 if not node and not repo._bookmarkcurrent:
4597 branch = repo[None].branch()
4599 branch = repo[None].branch()
4598 bheads = repo.branchheads(branch)
4600 bheads = repo.branchheads(branch)
4599 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4601 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4600
4602
4601 if len(nbhs) > 2:
4603 if len(nbhs) > 2:
4602 raise util.Abort(_("branch '%s' has %d heads - "
4604 raise util.Abort(_("branch '%s' has %d heads - "
4603 "please merge with an explicit rev")
4605 "please merge with an explicit rev")
4604 % (branch, len(bheads)),
4606 % (branch, len(bheads)),
4605 hint=_("run 'hg heads .' to see heads"))
4607 hint=_("run 'hg heads .' to see heads"))
4606
4608
4607 parent = repo.dirstate.p1()
4609 parent = repo.dirstate.p1()
4608 if len(nbhs) <= 1:
4610 if len(nbhs) <= 1:
4609 if len(bheads) > 1:
4611 if len(bheads) > 1:
4610 raise util.Abort(_("heads are bookmarked - "
4612 raise util.Abort(_("heads are bookmarked - "
4611 "please merge with an explicit rev"),
4613 "please merge with an explicit rev"),
4612 hint=_("run 'hg heads' to see all heads"))
4614 hint=_("run 'hg heads' to see all heads"))
4613 if len(repo.heads()) > 1:
4615 if len(repo.heads()) > 1:
4614 raise util.Abort(_("branch '%s' has one head - "
4616 raise util.Abort(_("branch '%s' has one head - "
4615 "please merge with an explicit rev")
4617 "please merge with an explicit rev")
4616 % branch,
4618 % branch,
4617 hint=_("run 'hg heads' to see all heads"))
4619 hint=_("run 'hg heads' to see all heads"))
4618 msg, hint = _('nothing to merge'), None
4620 msg, hint = _('nothing to merge'), None
4619 if parent != repo.lookup(branch):
4621 if parent != repo.lookup(branch):
4620 hint = _("use 'hg update' instead")
4622 hint = _("use 'hg update' instead")
4621 raise util.Abort(msg, hint=hint)
4623 raise util.Abort(msg, hint=hint)
4622
4624
4623 if parent not in bheads:
4625 if parent not in bheads:
4624 raise util.Abort(_('working directory not at a head revision'),
4626 raise util.Abort(_('working directory not at a head revision'),
4625 hint=_("use 'hg update' or merge with an "
4627 hint=_("use 'hg update' or merge with an "
4626 "explicit revision"))
4628 "explicit revision"))
4627 if parent == nbhs[0]:
4629 if parent == nbhs[0]:
4628 node = nbhs[-1]
4630 node = nbhs[-1]
4629 else:
4631 else:
4630 node = nbhs[0]
4632 node = nbhs[0]
4631
4633
4632 if opts.get('preview'):
4634 if opts.get('preview'):
4633 # find nodes that are ancestors of p2 but not of p1
4635 # find nodes that are ancestors of p2 but not of p1
4634 p1 = repo.lookup('.')
4636 p1 = repo.lookup('.')
4635 p2 = repo.lookup(node)
4637 p2 = repo.lookup(node)
4636 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4638 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4637
4639
4638 displayer = cmdutil.show_changeset(ui, repo, opts)
4640 displayer = cmdutil.show_changeset(ui, repo, opts)
4639 for node in nodes:
4641 for node in nodes:
4640 displayer.show(repo[node])
4642 displayer.show(repo[node])
4641 displayer.close()
4643 displayer.close()
4642 return 0
4644 return 0
4643
4645
4644 try:
4646 try:
4645 # ui.forcemerge is an internal variable, do not document
4647 # ui.forcemerge is an internal variable, do not document
4646 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4648 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4647 return hg.merge(repo, node, force=opts.get('force'))
4649 return hg.merge(repo, node, force=opts.get('force'))
4648 finally:
4650 finally:
4649 ui.setconfig('ui', 'forcemerge', '', 'merge')
4651 ui.setconfig('ui', 'forcemerge', '', 'merge')
4650
4652
4651 @command('outgoing|out',
4653 @command('outgoing|out',
4652 [('f', 'force', None, _('run even when the destination is unrelated')),
4654 [('f', 'force', None, _('run even when the destination is unrelated')),
4653 ('r', 'rev', [],
4655 ('r', 'rev', [],
4654 _('a changeset intended to be included in the destination'), _('REV')),
4656 _('a changeset intended to be included in the destination'), _('REV')),
4655 ('n', 'newest-first', None, _('show newest record first')),
4657 ('n', 'newest-first', None, _('show newest record first')),
4656 ('B', 'bookmarks', False, _('compare bookmarks')),
4658 ('B', 'bookmarks', False, _('compare bookmarks')),
4657 ('b', 'branch', [], _('a specific branch you would like to push'),
4659 ('b', 'branch', [], _('a specific branch you would like to push'),
4658 _('BRANCH')),
4660 _('BRANCH')),
4659 ] + logopts + remoteopts + subrepoopts,
4661 ] + logopts + remoteopts + subrepoopts,
4660 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4662 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4661 def outgoing(ui, repo, dest=None, **opts):
4663 def outgoing(ui, repo, dest=None, **opts):
4662 """show changesets not found in the destination
4664 """show changesets not found in the destination
4663
4665
4664 Show changesets not found in the specified destination repository
4666 Show changesets not found in the specified destination repository
4665 or the default push location. These are the changesets that would
4667 or the default push location. These are the changesets that would
4666 be pushed if a push was requested.
4668 be pushed if a push was requested.
4667
4669
4668 See pull for details of valid destination formats.
4670 See pull for details of valid destination formats.
4669
4671
4670 Returns 0 if there are outgoing changes, 1 otherwise.
4672 Returns 0 if there are outgoing changes, 1 otherwise.
4671 """
4673 """
4672 if opts.get('graph'):
4674 if opts.get('graph'):
4673 cmdutil.checkunsupportedgraphflags([], opts)
4675 cmdutil.checkunsupportedgraphflags([], opts)
4674 o, other = hg._outgoing(ui, repo, dest, opts)
4676 o, other = hg._outgoing(ui, repo, dest, opts)
4675 if not o:
4677 if not o:
4676 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4678 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4677 return
4679 return
4678
4680
4679 revdag = cmdutil.graphrevs(repo, o, opts)
4681 revdag = cmdutil.graphrevs(repo, o, opts)
4680 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4682 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4681 showparents = [ctx.node() for ctx in repo[None].parents()]
4683 showparents = [ctx.node() for ctx in repo[None].parents()]
4682 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4684 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4683 graphmod.asciiedges)
4685 graphmod.asciiedges)
4684 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4686 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4685 return 0
4687 return 0
4686
4688
4687 if opts.get('bookmarks'):
4689 if opts.get('bookmarks'):
4688 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4690 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4689 dest, branches = hg.parseurl(dest, opts.get('branch'))
4691 dest, branches = hg.parseurl(dest, opts.get('branch'))
4690 other = hg.peer(repo, opts, dest)
4692 other = hg.peer(repo, opts, dest)
4691 if 'bookmarks' not in other.listkeys('namespaces'):
4693 if 'bookmarks' not in other.listkeys('namespaces'):
4692 ui.warn(_("remote doesn't support bookmarks\n"))
4694 ui.warn(_("remote doesn't support bookmarks\n"))
4693 return 0
4695 return 0
4694 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4696 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4695 return bookmarks.diff(ui, other, repo)
4697 return bookmarks.diff(ui, other, repo)
4696
4698
4697 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4699 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4698 try:
4700 try:
4699 return hg.outgoing(ui, repo, dest, opts)
4701 return hg.outgoing(ui, repo, dest, opts)
4700 finally:
4702 finally:
4701 del repo._subtoppath
4703 del repo._subtoppath
4702
4704
4703 @command('parents',
4705 @command('parents',
4704 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4706 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4705 ] + templateopts,
4707 ] + templateopts,
4706 _('[-r REV] [FILE]'),
4708 _('[-r REV] [FILE]'),
4707 inferrepo=True)
4709 inferrepo=True)
4708 def parents(ui, repo, file_=None, **opts):
4710 def parents(ui, repo, file_=None, **opts):
4709 """show the parents of the working directory or revision (DEPRECATED)
4711 """show the parents of the working directory or revision (DEPRECATED)
4710
4712
4711 Print the working directory's parent revisions. If a revision is
4713 Print the working directory's parent revisions. If a revision is
4712 given via -r/--rev, the parent of that revision will be printed.
4714 given via -r/--rev, the parent of that revision will be printed.
4713 If a file argument is given, the revision in which the file was
4715 If a file argument is given, the revision in which the file was
4714 last changed (before the working directory revision or the
4716 last changed (before the working directory revision or the
4715 argument to --rev if given) is printed.
4717 argument to --rev if given) is printed.
4716
4718
4717 See :hg:`summary` and :hg:`help revsets` for related information.
4719 See :hg:`summary` and :hg:`help revsets` for related information.
4718
4720
4719 Returns 0 on success.
4721 Returns 0 on success.
4720 """
4722 """
4721
4723
4722 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4724 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4723
4725
4724 if file_:
4726 if file_:
4725 m = scmutil.match(ctx, (file_,), opts)
4727 m = scmutil.match(ctx, (file_,), opts)
4726 if m.anypats() or len(m.files()) != 1:
4728 if m.anypats() or len(m.files()) != 1:
4727 raise util.Abort(_('can only specify an explicit filename'))
4729 raise util.Abort(_('can only specify an explicit filename'))
4728 file_ = m.files()[0]
4730 file_ = m.files()[0]
4729 filenodes = []
4731 filenodes = []
4730 for cp in ctx.parents():
4732 for cp in ctx.parents():
4731 if not cp:
4733 if not cp:
4732 continue
4734 continue
4733 try:
4735 try:
4734 filenodes.append(cp.filenode(file_))
4736 filenodes.append(cp.filenode(file_))
4735 except error.LookupError:
4737 except error.LookupError:
4736 pass
4738 pass
4737 if not filenodes:
4739 if not filenodes:
4738 raise util.Abort(_("'%s' not found in manifest!") % file_)
4740 raise util.Abort(_("'%s' not found in manifest!") % file_)
4739 p = []
4741 p = []
4740 for fn in filenodes:
4742 for fn in filenodes:
4741 fctx = repo.filectx(file_, fileid=fn)
4743 fctx = repo.filectx(file_, fileid=fn)
4742 p.append(fctx.node())
4744 p.append(fctx.node())
4743 else:
4745 else:
4744 p = [cp.node() for cp in ctx.parents()]
4746 p = [cp.node() for cp in ctx.parents()]
4745
4747
4746 displayer = cmdutil.show_changeset(ui, repo, opts)
4748 displayer = cmdutil.show_changeset(ui, repo, opts)
4747 for n in p:
4749 for n in p:
4748 if n != nullid:
4750 if n != nullid:
4749 displayer.show(repo[n])
4751 displayer.show(repo[n])
4750 displayer.close()
4752 displayer.close()
4751
4753
4752 @command('paths', [], _('[NAME]'), optionalrepo=True)
4754 @command('paths', [], _('[NAME]'), optionalrepo=True)
4753 def paths(ui, repo, search=None):
4755 def paths(ui, repo, search=None):
4754 """show aliases for remote repositories
4756 """show aliases for remote repositories
4755
4757
4756 Show definition of symbolic path name NAME. If no name is given,
4758 Show definition of symbolic path name NAME. If no name is given,
4757 show definition of all available names.
4759 show definition of all available names.
4758
4760
4759 Option -q/--quiet suppresses all output when searching for NAME
4761 Option -q/--quiet suppresses all output when searching for NAME
4760 and shows only the path names when listing all definitions.
4762 and shows only the path names when listing all definitions.
4761
4763
4762 Path names are defined in the [paths] section of your
4764 Path names are defined in the [paths] section of your
4763 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4765 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4764 repository, ``.hg/hgrc`` is used, too.
4766 repository, ``.hg/hgrc`` is used, too.
4765
4767
4766 The path names ``default`` and ``default-push`` have a special
4768 The path names ``default`` and ``default-push`` have a special
4767 meaning. When performing a push or pull operation, they are used
4769 meaning. When performing a push or pull operation, they are used
4768 as fallbacks if no location is specified on the command-line.
4770 as fallbacks if no location is specified on the command-line.
4769 When ``default-push`` is set, it will be used for push and
4771 When ``default-push`` is set, it will be used for push and
4770 ``default`` will be used for pull; otherwise ``default`` is used
4772 ``default`` will be used for pull; otherwise ``default`` is used
4771 as the fallback for both. When cloning a repository, the clone
4773 as the fallback for both. When cloning a repository, the clone
4772 source is written as ``default`` in ``.hg/hgrc``. Note that
4774 source is written as ``default`` in ``.hg/hgrc``. Note that
4773 ``default`` and ``default-push`` apply to all inbound (e.g.
4775 ``default`` and ``default-push`` apply to all inbound (e.g.
4774 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4776 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4775 :hg:`bundle`) operations.
4777 :hg:`bundle`) operations.
4776
4778
4777 See :hg:`help urls` for more information.
4779 See :hg:`help urls` for more information.
4778
4780
4779 Returns 0 on success.
4781 Returns 0 on success.
4780 """
4782 """
4781 if search:
4783 if search:
4782 for name, path in ui.configitems("paths"):
4784 for name, path in ui.configitems("paths"):
4783 if name == search:
4785 if name == search:
4784 ui.status("%s\n" % util.hidepassword(path))
4786 ui.status("%s\n" % util.hidepassword(path))
4785 return
4787 return
4786 if not ui.quiet:
4788 if not ui.quiet:
4787 ui.warn(_("not found!\n"))
4789 ui.warn(_("not found!\n"))
4788 return 1
4790 return 1
4789 else:
4791 else:
4790 for name, path in ui.configitems("paths"):
4792 for name, path in ui.configitems("paths"):
4791 if ui.quiet:
4793 if ui.quiet:
4792 ui.write("%s\n" % name)
4794 ui.write("%s\n" % name)
4793 else:
4795 else:
4794 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4796 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4795
4797
4796 @command('phase',
4798 @command('phase',
4797 [('p', 'public', False, _('set changeset phase to public')),
4799 [('p', 'public', False, _('set changeset phase to public')),
4798 ('d', 'draft', False, _('set changeset phase to draft')),
4800 ('d', 'draft', False, _('set changeset phase to draft')),
4799 ('s', 'secret', False, _('set changeset phase to secret')),
4801 ('s', 'secret', False, _('set changeset phase to secret')),
4800 ('f', 'force', False, _('allow to move boundary backward')),
4802 ('f', 'force', False, _('allow to move boundary backward')),
4801 ('r', 'rev', [], _('target revision'), _('REV')),
4803 ('r', 'rev', [], _('target revision'), _('REV')),
4802 ],
4804 ],
4803 _('[-p|-d|-s] [-f] [-r] REV...'))
4805 _('[-p|-d|-s] [-f] [-r] REV...'))
4804 def phase(ui, repo, *revs, **opts):
4806 def phase(ui, repo, *revs, **opts):
4805 """set or show the current phase name
4807 """set or show the current phase name
4806
4808
4807 With no argument, show the phase name of specified revisions.
4809 With no argument, show the phase name of specified revisions.
4808
4810
4809 With one of -p/--public, -d/--draft or -s/--secret, change the
4811 With one of -p/--public, -d/--draft or -s/--secret, change the
4810 phase value of the specified revisions.
4812 phase value of the specified revisions.
4811
4813
4812 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4814 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4813 lower phase to an higher phase. Phases are ordered as follows::
4815 lower phase to an higher phase. Phases are ordered as follows::
4814
4816
4815 public < draft < secret
4817 public < draft < secret
4816
4818
4817 Returns 0 on success, 1 if no phases were changed or some could not
4819 Returns 0 on success, 1 if no phases were changed or some could not
4818 be changed.
4820 be changed.
4819 """
4821 """
4820 # search for a unique phase argument
4822 # search for a unique phase argument
4821 targetphase = None
4823 targetphase = None
4822 for idx, name in enumerate(phases.phasenames):
4824 for idx, name in enumerate(phases.phasenames):
4823 if opts[name]:
4825 if opts[name]:
4824 if targetphase is not None:
4826 if targetphase is not None:
4825 raise util.Abort(_('only one phase can be specified'))
4827 raise util.Abort(_('only one phase can be specified'))
4826 targetphase = idx
4828 targetphase = idx
4827
4829
4828 # look for specified revision
4830 # look for specified revision
4829 revs = list(revs)
4831 revs = list(revs)
4830 revs.extend(opts['rev'])
4832 revs.extend(opts['rev'])
4831 if not revs:
4833 if not revs:
4832 raise util.Abort(_('no revisions specified'))
4834 raise util.Abort(_('no revisions specified'))
4833
4835
4834 revs = scmutil.revrange(repo, revs)
4836 revs = scmutil.revrange(repo, revs)
4835
4837
4836 lock = None
4838 lock = None
4837 ret = 0
4839 ret = 0
4838 if targetphase is None:
4840 if targetphase is None:
4839 # display
4841 # display
4840 for r in revs:
4842 for r in revs:
4841 ctx = repo[r]
4843 ctx = repo[r]
4842 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4844 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4843 else:
4845 else:
4844 tr = None
4846 tr = None
4845 lock = repo.lock()
4847 lock = repo.lock()
4846 try:
4848 try:
4847 tr = repo.transaction("phase")
4849 tr = repo.transaction("phase")
4848 # set phase
4850 # set phase
4849 if not revs:
4851 if not revs:
4850 raise util.Abort(_('empty revision set'))
4852 raise util.Abort(_('empty revision set'))
4851 nodes = [repo[r].node() for r in revs]
4853 nodes = [repo[r].node() for r in revs]
4852 olddata = repo._phasecache.getphaserevs(repo)[:]
4854 olddata = repo._phasecache.getphaserevs(repo)[:]
4853 phases.advanceboundary(repo, tr, targetphase, nodes)
4855 phases.advanceboundary(repo, tr, targetphase, nodes)
4854 if opts['force']:
4856 if opts['force']:
4855 phases.retractboundary(repo, tr, targetphase, nodes)
4857 phases.retractboundary(repo, tr, targetphase, nodes)
4856 tr.close()
4858 tr.close()
4857 finally:
4859 finally:
4858 if tr is not None:
4860 if tr is not None:
4859 tr.release()
4861 tr.release()
4860 lock.release()
4862 lock.release()
4861 # moving revision from public to draft may hide them
4863 # moving revision from public to draft may hide them
4862 # We have to check result on an unfiltered repository
4864 # We have to check result on an unfiltered repository
4863 unfi = repo.unfiltered()
4865 unfi = repo.unfiltered()
4864 newdata = repo._phasecache.getphaserevs(unfi)
4866 newdata = repo._phasecache.getphaserevs(unfi)
4865 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4867 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4866 cl = unfi.changelog
4868 cl = unfi.changelog
4867 rejected = [n for n in nodes
4869 rejected = [n for n in nodes
4868 if newdata[cl.rev(n)] < targetphase]
4870 if newdata[cl.rev(n)] < targetphase]
4869 if rejected:
4871 if rejected:
4870 ui.warn(_('cannot move %i changesets to a higher '
4872 ui.warn(_('cannot move %i changesets to a higher '
4871 'phase, use --force\n') % len(rejected))
4873 'phase, use --force\n') % len(rejected))
4872 ret = 1
4874 ret = 1
4873 if changes:
4875 if changes:
4874 msg = _('phase changed for %i changesets\n') % changes
4876 msg = _('phase changed for %i changesets\n') % changes
4875 if ret:
4877 if ret:
4876 ui.status(msg)
4878 ui.status(msg)
4877 else:
4879 else:
4878 ui.note(msg)
4880 ui.note(msg)
4879 else:
4881 else:
4880 ui.warn(_('no phases changed\n'))
4882 ui.warn(_('no phases changed\n'))
4881 ret = 1
4883 ret = 1
4882 return ret
4884 return ret
4883
4885
4884 def postincoming(ui, repo, modheads, optupdate, checkout):
4886 def postincoming(ui, repo, modheads, optupdate, checkout):
4885 if modheads == 0:
4887 if modheads == 0:
4886 return
4888 return
4887 if optupdate:
4889 if optupdate:
4888 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4890 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4889 try:
4891 try:
4890 ret = hg.update(repo, checkout)
4892 ret = hg.update(repo, checkout)
4891 except util.Abort, inst:
4893 except util.Abort, inst:
4892 ui.warn(_("not updating: %s\n") % str(inst))
4894 ui.warn(_("not updating: %s\n") % str(inst))
4893 if inst.hint:
4895 if inst.hint:
4894 ui.warn(_("(%s)\n") % inst.hint)
4896 ui.warn(_("(%s)\n") % inst.hint)
4895 return 0
4897 return 0
4896 if not ret and not checkout:
4898 if not ret and not checkout:
4897 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4899 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4898 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4900 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4899 return ret
4901 return ret
4900 if modheads > 1:
4902 if modheads > 1:
4901 currentbranchheads = len(repo.branchheads())
4903 currentbranchheads = len(repo.branchheads())
4902 if currentbranchheads == modheads:
4904 if currentbranchheads == modheads:
4903 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4905 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4904 elif currentbranchheads > 1:
4906 elif currentbranchheads > 1:
4905 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4907 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4906 "merge)\n"))
4908 "merge)\n"))
4907 else:
4909 else:
4908 ui.status(_("(run 'hg heads' to see heads)\n"))
4910 ui.status(_("(run 'hg heads' to see heads)\n"))
4909 else:
4911 else:
4910 ui.status(_("(run 'hg update' to get a working copy)\n"))
4912 ui.status(_("(run 'hg update' to get a working copy)\n"))
4911
4913
4912 @command('^pull',
4914 @command('^pull',
4913 [('u', 'update', None,
4915 [('u', 'update', None,
4914 _('update to new branch head if changesets were pulled')),
4916 _('update to new branch head if changesets were pulled')),
4915 ('f', 'force', None, _('run even when remote repository is unrelated')),
4917 ('f', 'force', None, _('run even when remote repository is unrelated')),
4916 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4918 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4917 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4919 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4918 ('b', 'branch', [], _('a specific branch you would like to pull'),
4920 ('b', 'branch', [], _('a specific branch you would like to pull'),
4919 _('BRANCH')),
4921 _('BRANCH')),
4920 ] + remoteopts,
4922 ] + remoteopts,
4921 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4923 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4922 def pull(ui, repo, source="default", **opts):
4924 def pull(ui, repo, source="default", **opts):
4923 """pull changes from the specified source
4925 """pull changes from the specified source
4924
4926
4925 Pull changes from a remote repository to a local one.
4927 Pull changes from a remote repository to a local one.
4926
4928
4927 This finds all changes from the repository at the specified path
4929 This finds all changes from the repository at the specified path
4928 or URL and adds them to a local repository (the current one unless
4930 or URL and adds them to a local repository (the current one unless
4929 -R is specified). By default, this does not update the copy of the
4931 -R is specified). By default, this does not update the copy of the
4930 project in the working directory.
4932 project in the working directory.
4931
4933
4932 Use :hg:`incoming` if you want to see what would have been added
4934 Use :hg:`incoming` if you want to see what would have been added
4933 by a pull at the time you issued this command. If you then decide
4935 by a pull at the time you issued this command. If you then decide
4934 to add those changes to the repository, you should use :hg:`pull
4936 to add those changes to the repository, you should use :hg:`pull
4935 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4937 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4936
4938
4937 If SOURCE is omitted, the 'default' path will be used.
4939 If SOURCE is omitted, the 'default' path will be used.
4938 See :hg:`help urls` for more information.
4940 See :hg:`help urls` for more information.
4939
4941
4940 Returns 0 on success, 1 if an update had unresolved files.
4942 Returns 0 on success, 1 if an update had unresolved files.
4941 """
4943 """
4942 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4944 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4943 other = hg.peer(repo, opts, source)
4945 other = hg.peer(repo, opts, source)
4944 try:
4946 try:
4945 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4947 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4946 revs, checkout = hg.addbranchrevs(repo, other, branches,
4948 revs, checkout = hg.addbranchrevs(repo, other, branches,
4947 opts.get('rev'))
4949 opts.get('rev'))
4948
4950
4949 remotebookmarks = other.listkeys('bookmarks')
4951 remotebookmarks = other.listkeys('bookmarks')
4950
4952
4951 if opts.get('bookmark'):
4953 if opts.get('bookmark'):
4952 if not revs:
4954 if not revs:
4953 revs = []
4955 revs = []
4954 for b in opts['bookmark']:
4956 for b in opts['bookmark']:
4955 if b not in remotebookmarks:
4957 if b not in remotebookmarks:
4956 raise util.Abort(_('remote bookmark %s not found!') % b)
4958 raise util.Abort(_('remote bookmark %s not found!') % b)
4957 revs.append(remotebookmarks[b])
4959 revs.append(remotebookmarks[b])
4958
4960
4959 if revs:
4961 if revs:
4960 try:
4962 try:
4961 revs = [other.lookup(rev) for rev in revs]
4963 revs = [other.lookup(rev) for rev in revs]
4962 except error.CapabilityError:
4964 except error.CapabilityError:
4963 err = _("other repository doesn't support revision lookup, "
4965 err = _("other repository doesn't support revision lookup, "
4964 "so a rev cannot be specified.")
4966 "so a rev cannot be specified.")
4965 raise util.Abort(err)
4967 raise util.Abort(err)
4966
4968
4967 modheads = exchange.pull(repo, other, heads=revs,
4969 modheads = exchange.pull(repo, other, heads=revs,
4968 force=opts.get('force'),
4970 force=opts.get('force'),
4969 bookmarks=opts.get('bookmark', ())).cgresult
4971 bookmarks=opts.get('bookmark', ())).cgresult
4970 if checkout:
4972 if checkout:
4971 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4973 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4972 repo._subtoppath = source
4974 repo._subtoppath = source
4973 try:
4975 try:
4974 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4976 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4975
4977
4976 finally:
4978 finally:
4977 del repo._subtoppath
4979 del repo._subtoppath
4978
4980
4979 finally:
4981 finally:
4980 other.close()
4982 other.close()
4981 return ret
4983 return ret
4982
4984
4983 @command('^push',
4985 @command('^push',
4984 [('f', 'force', None, _('force push')),
4986 [('f', 'force', None, _('force push')),
4985 ('r', 'rev', [],
4987 ('r', 'rev', [],
4986 _('a changeset intended to be included in the destination'),
4988 _('a changeset intended to be included in the destination'),
4987 _('REV')),
4989 _('REV')),
4988 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4990 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4989 ('b', 'branch', [],
4991 ('b', 'branch', [],
4990 _('a specific branch you would like to push'), _('BRANCH')),
4992 _('a specific branch you would like to push'), _('BRANCH')),
4991 ('', 'new-branch', False, _('allow pushing a new branch')),
4993 ('', 'new-branch', False, _('allow pushing a new branch')),
4992 ] + remoteopts,
4994 ] + remoteopts,
4993 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4995 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4994 def push(ui, repo, dest=None, **opts):
4996 def push(ui, repo, dest=None, **opts):
4995 """push changes to the specified destination
4997 """push changes to the specified destination
4996
4998
4997 Push changesets from the local repository to the specified
4999 Push changesets from the local repository to the specified
4998 destination.
5000 destination.
4999
5001
5000 This operation is symmetrical to pull: it is identical to a pull
5002 This operation is symmetrical to pull: it is identical to a pull
5001 in the destination repository from the current one.
5003 in the destination repository from the current one.
5002
5004
5003 By default, push will not allow creation of new heads at the
5005 By default, push will not allow creation of new heads at the
5004 destination, since multiple heads would make it unclear which head
5006 destination, since multiple heads would make it unclear which head
5005 to use. In this situation, it is recommended to pull and merge
5007 to use. In this situation, it is recommended to pull and merge
5006 before pushing.
5008 before pushing.
5007
5009
5008 Use --new-branch if you want to allow push to create a new named
5010 Use --new-branch if you want to allow push to create a new named
5009 branch that is not present at the destination. This allows you to
5011 branch that is not present at the destination. This allows you to
5010 only create a new branch without forcing other changes.
5012 only create a new branch without forcing other changes.
5011
5013
5012 .. note::
5014 .. note::
5013
5015
5014 Extra care should be taken with the -f/--force option,
5016 Extra care should be taken with the -f/--force option,
5015 which will push all new heads on all branches, an action which will
5017 which will push all new heads on all branches, an action which will
5016 almost always cause confusion for collaborators.
5018 almost always cause confusion for collaborators.
5017
5019
5018 If -r/--rev is used, the specified revision and all its ancestors
5020 If -r/--rev is used, the specified revision and all its ancestors
5019 will be pushed to the remote repository.
5021 will be pushed to the remote repository.
5020
5022
5021 If -B/--bookmark is used, the specified bookmarked revision, its
5023 If -B/--bookmark is used, the specified bookmarked revision, its
5022 ancestors, and the bookmark will be pushed to the remote
5024 ancestors, and the bookmark will be pushed to the remote
5023 repository.
5025 repository.
5024
5026
5025 Please see :hg:`help urls` for important details about ``ssh://``
5027 Please see :hg:`help urls` for important details about ``ssh://``
5026 URLs. If DESTINATION is omitted, a default path will be used.
5028 URLs. If DESTINATION is omitted, a default path will be used.
5027
5029
5028 Returns 0 if push was successful, 1 if nothing to push.
5030 Returns 0 if push was successful, 1 if nothing to push.
5029 """
5031 """
5030
5032
5031 if opts.get('bookmark'):
5033 if opts.get('bookmark'):
5032 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5034 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5033 for b in opts['bookmark']:
5035 for b in opts['bookmark']:
5034 # translate -B options to -r so changesets get pushed
5036 # translate -B options to -r so changesets get pushed
5035 if b in repo._bookmarks:
5037 if b in repo._bookmarks:
5036 opts.setdefault('rev', []).append(b)
5038 opts.setdefault('rev', []).append(b)
5037 else:
5039 else:
5038 # if we try to push a deleted bookmark, translate it to null
5040 # if we try to push a deleted bookmark, translate it to null
5039 # this lets simultaneous -r, -b options continue working
5041 # this lets simultaneous -r, -b options continue working
5040 opts.setdefault('rev', []).append("null")
5042 opts.setdefault('rev', []).append("null")
5041
5043
5042 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5044 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5043 dest, branches = hg.parseurl(dest, opts.get('branch'))
5045 dest, branches = hg.parseurl(dest, opts.get('branch'))
5044 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5046 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5045 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5047 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5046 try:
5048 try:
5047 other = hg.peer(repo, opts, dest)
5049 other = hg.peer(repo, opts, dest)
5048 except error.RepoError:
5050 except error.RepoError:
5049 if dest == "default-push":
5051 if dest == "default-push":
5050 raise util.Abort(_("default repository not configured!"),
5052 raise util.Abort(_("default repository not configured!"),
5051 hint=_('see the "path" section in "hg help config"'))
5053 hint=_('see the "path" section in "hg help config"'))
5052 else:
5054 else:
5053 raise
5055 raise
5054
5056
5055 if revs:
5057 if revs:
5056 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5058 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5057
5059
5058 repo._subtoppath = dest
5060 repo._subtoppath = dest
5059 try:
5061 try:
5060 # push subrepos depth-first for coherent ordering
5062 # push subrepos depth-first for coherent ordering
5061 c = repo['']
5063 c = repo['']
5062 subs = c.substate # only repos that are committed
5064 subs = c.substate # only repos that are committed
5063 for s in sorted(subs):
5065 for s in sorted(subs):
5064 result = c.sub(s).push(opts)
5066 result = c.sub(s).push(opts)
5065 if result == 0:
5067 if result == 0:
5066 return not result
5068 return not result
5067 finally:
5069 finally:
5068 del repo._subtoppath
5070 del repo._subtoppath
5069 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5071 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5070 newbranch=opts.get('new_branch'),
5072 newbranch=opts.get('new_branch'),
5071 bookmarks=opts.get('bookmark', ()))
5073 bookmarks=opts.get('bookmark', ()))
5072
5074
5073 result = not pushop.cgresult
5075 result = not pushop.cgresult
5074
5076
5075 if pushop.bkresult is not None:
5077 if pushop.bkresult is not None:
5076 if pushop.bkresult == 2:
5078 if pushop.bkresult == 2:
5077 result = 2
5079 result = 2
5078 elif not result and pushop.bkresult:
5080 elif not result and pushop.bkresult:
5079 result = 2
5081 result = 2
5080
5082
5081 return result
5083 return result
5082
5084
5083 @command('recover', [])
5085 @command('recover', [])
5084 def recover(ui, repo):
5086 def recover(ui, repo):
5085 """roll back an interrupted transaction
5087 """roll back an interrupted transaction
5086
5088
5087 Recover from an interrupted commit or pull.
5089 Recover from an interrupted commit or pull.
5088
5090
5089 This command tries to fix the repository status after an
5091 This command tries to fix the repository status after an
5090 interrupted operation. It should only be necessary when Mercurial
5092 interrupted operation. It should only be necessary when Mercurial
5091 suggests it.
5093 suggests it.
5092
5094
5093 Returns 0 if successful, 1 if nothing to recover or verify fails.
5095 Returns 0 if successful, 1 if nothing to recover or verify fails.
5094 """
5096 """
5095 if repo.recover():
5097 if repo.recover():
5096 return hg.verify(repo)
5098 return hg.verify(repo)
5097 return 1
5099 return 1
5098
5100
5099 @command('^remove|rm',
5101 @command('^remove|rm',
5100 [('A', 'after', None, _('record delete for missing files')),
5102 [('A', 'after', None, _('record delete for missing files')),
5101 ('f', 'force', None,
5103 ('f', 'force', None,
5102 _('remove (and delete) file even if added or modified')),
5104 _('remove (and delete) file even if added or modified')),
5103 ] + walkopts,
5105 ] + walkopts,
5104 _('[OPTION]... FILE...'),
5106 _('[OPTION]... FILE...'),
5105 inferrepo=True)
5107 inferrepo=True)
5106 def remove(ui, repo, *pats, **opts):
5108 def remove(ui, repo, *pats, **opts):
5107 """remove the specified files on the next commit
5109 """remove the specified files on the next commit
5108
5110
5109 Schedule the indicated files for removal from the current branch.
5111 Schedule the indicated files for removal from the current branch.
5110
5112
5111 This command schedules the files to be removed at the next commit.
5113 This command schedules the files to be removed at the next commit.
5112 To undo a remove before that, see :hg:`revert`. To undo added
5114 To undo a remove before that, see :hg:`revert`. To undo added
5113 files, see :hg:`forget`.
5115 files, see :hg:`forget`.
5114
5116
5115 .. container:: verbose
5117 .. container:: verbose
5116
5118
5117 -A/--after can be used to remove only files that have already
5119 -A/--after can be used to remove only files that have already
5118 been deleted, -f/--force can be used to force deletion, and -Af
5120 been deleted, -f/--force can be used to force deletion, and -Af
5119 can be used to remove files from the next revision without
5121 can be used to remove files from the next revision without
5120 deleting them from the working directory.
5122 deleting them from the working directory.
5121
5123
5122 The following table details the behavior of remove for different
5124 The following table details the behavior of remove for different
5123 file states (columns) and option combinations (rows). The file
5125 file states (columns) and option combinations (rows). The file
5124 states are Added [A], Clean [C], Modified [M] and Missing [!]
5126 states are Added [A], Clean [C], Modified [M] and Missing [!]
5125 (as reported by :hg:`status`). The actions are Warn, Remove
5127 (as reported by :hg:`status`). The actions are Warn, Remove
5126 (from branch) and Delete (from disk):
5128 (from branch) and Delete (from disk):
5127
5129
5128 ========= == == == ==
5130 ========= == == == ==
5129 opt/state A C M !
5131 opt/state A C M !
5130 ========= == == == ==
5132 ========= == == == ==
5131 none W RD W R
5133 none W RD W R
5132 -f R RD RD R
5134 -f R RD RD R
5133 -A W W W R
5135 -A W W W R
5134 -Af R R R R
5136 -Af R R R R
5135 ========= == == == ==
5137 ========= == == == ==
5136
5138
5137 Note that remove never deletes files in Added [A] state from the
5139 Note that remove never deletes files in Added [A] state from the
5138 working directory, not even if option --force is specified.
5140 working directory, not even if option --force is specified.
5139
5141
5140 Returns 0 on success, 1 if any warnings encountered.
5142 Returns 0 on success, 1 if any warnings encountered.
5141 """
5143 """
5142
5144
5143 ret = 0
5145 ret = 0
5144 after, force = opts.get('after'), opts.get('force')
5146 after, force = opts.get('after'), opts.get('force')
5145 if not pats and not after:
5147 if not pats and not after:
5146 raise util.Abort(_('no files specified'))
5148 raise util.Abort(_('no files specified'))
5147
5149
5148 m = scmutil.match(repo[None], pats, opts)
5150 m = scmutil.match(repo[None], pats, opts)
5149 s = repo.status(match=m, clean=True)
5151 s = repo.status(match=m, clean=True)
5150 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5152 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5151
5153
5152 # warn about failure to delete explicit files/dirs
5154 # warn about failure to delete explicit files/dirs
5153 wctx = repo[None]
5155 wctx = repo[None]
5154 for f in m.files():
5156 for f in m.files():
5155 if f in repo.dirstate or f in wctx.dirs():
5157 if f in repo.dirstate or f in wctx.dirs():
5156 continue
5158 continue
5157 if os.path.exists(m.rel(f)):
5159 if os.path.exists(m.rel(f)):
5158 if os.path.isdir(m.rel(f)):
5160 if os.path.isdir(m.rel(f)):
5159 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5161 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5160 else:
5162 else:
5161 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5163 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5162 # missing files will generate a warning elsewhere
5164 # missing files will generate a warning elsewhere
5163 ret = 1
5165 ret = 1
5164
5166
5165 if force:
5167 if force:
5166 list = modified + deleted + clean + added
5168 list = modified + deleted + clean + added
5167 elif after:
5169 elif after:
5168 list = deleted
5170 list = deleted
5169 for f in modified + added + clean:
5171 for f in modified + added + clean:
5170 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5172 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5171 ret = 1
5173 ret = 1
5172 else:
5174 else:
5173 list = deleted + clean
5175 list = deleted + clean
5174 for f in modified:
5176 for f in modified:
5175 ui.warn(_('not removing %s: file is modified (use -f'
5177 ui.warn(_('not removing %s: file is modified (use -f'
5176 ' to force removal)\n') % m.rel(f))
5178 ' to force removal)\n') % m.rel(f))
5177 ret = 1
5179 ret = 1
5178 for f in added:
5180 for f in added:
5179 ui.warn(_('not removing %s: file has been marked for add'
5181 ui.warn(_('not removing %s: file has been marked for add'
5180 ' (use forget to undo)\n') % m.rel(f))
5182 ' (use forget to undo)\n') % m.rel(f))
5181 ret = 1
5183 ret = 1
5182
5184
5183 for f in sorted(list):
5185 for f in sorted(list):
5184 if ui.verbose or not m.exact(f):
5186 if ui.verbose or not m.exact(f):
5185 ui.status(_('removing %s\n') % m.rel(f))
5187 ui.status(_('removing %s\n') % m.rel(f))
5186
5188
5187 wlock = repo.wlock()
5189 wlock = repo.wlock()
5188 try:
5190 try:
5189 if not after:
5191 if not after:
5190 for f in list:
5192 for f in list:
5191 if f in added:
5193 if f in added:
5192 continue # we never unlink added files on remove
5194 continue # we never unlink added files on remove
5193 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5195 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5194 repo[None].forget(list)
5196 repo[None].forget(list)
5195 finally:
5197 finally:
5196 wlock.release()
5198 wlock.release()
5197
5199
5198 return ret
5200 return ret
5199
5201
5200 @command('rename|move|mv',
5202 @command('rename|move|mv',
5201 [('A', 'after', None, _('record a rename that has already occurred')),
5203 [('A', 'after', None, _('record a rename that has already occurred')),
5202 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5204 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5203 ] + walkopts + dryrunopts,
5205 ] + walkopts + dryrunopts,
5204 _('[OPTION]... SOURCE... DEST'))
5206 _('[OPTION]... SOURCE... DEST'))
5205 def rename(ui, repo, *pats, **opts):
5207 def rename(ui, repo, *pats, **opts):
5206 """rename files; equivalent of copy + remove
5208 """rename files; equivalent of copy + remove
5207
5209
5208 Mark dest as copies of sources; mark sources for deletion. If dest
5210 Mark dest as copies of sources; mark sources for deletion. If dest
5209 is a directory, copies are put in that directory. If dest is a
5211 is a directory, copies are put in that directory. If dest is a
5210 file, there can only be one source.
5212 file, there can only be one source.
5211
5213
5212 By default, this command copies the contents of files as they
5214 By default, this command copies the contents of files as they
5213 exist in the working directory. If invoked with -A/--after, the
5215 exist in the working directory. If invoked with -A/--after, the
5214 operation is recorded, but no copying is performed.
5216 operation is recorded, but no copying is performed.
5215
5217
5216 This command takes effect at the next commit. To undo a rename
5218 This command takes effect at the next commit. To undo a rename
5217 before that, see :hg:`revert`.
5219 before that, see :hg:`revert`.
5218
5220
5219 Returns 0 on success, 1 if errors are encountered.
5221 Returns 0 on success, 1 if errors are encountered.
5220 """
5222 """
5221 wlock = repo.wlock(False)
5223 wlock = repo.wlock(False)
5222 try:
5224 try:
5223 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5225 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5224 finally:
5226 finally:
5225 wlock.release()
5227 wlock.release()
5226
5228
5227 @command('resolve',
5229 @command('resolve',
5228 [('a', 'all', None, _('select all unresolved files')),
5230 [('a', 'all', None, _('select all unresolved files')),
5229 ('l', 'list', None, _('list state of files needing merge')),
5231 ('l', 'list', None, _('list state of files needing merge')),
5230 ('m', 'mark', None, _('mark files as resolved')),
5232 ('m', 'mark', None, _('mark files as resolved')),
5231 ('u', 'unmark', None, _('mark files as unresolved')),
5233 ('u', 'unmark', None, _('mark files as unresolved')),
5232 ('n', 'no-status', None, _('hide status prefix'))]
5234 ('n', 'no-status', None, _('hide status prefix'))]
5233 + mergetoolopts + walkopts,
5235 + mergetoolopts + walkopts,
5234 _('[OPTION]... [FILE]...'),
5236 _('[OPTION]... [FILE]...'),
5235 inferrepo=True)
5237 inferrepo=True)
5236 def resolve(ui, repo, *pats, **opts):
5238 def resolve(ui, repo, *pats, **opts):
5237 """redo merges or set/view the merge status of files
5239 """redo merges or set/view the merge status of files
5238
5240
5239 Merges with unresolved conflicts are often the result of
5241 Merges with unresolved conflicts are often the result of
5240 non-interactive merging using the ``internal:merge`` configuration
5242 non-interactive merging using the ``internal:merge`` configuration
5241 setting, or a command-line merge tool like ``diff3``. The resolve
5243 setting, or a command-line merge tool like ``diff3``. The resolve
5242 command is used to manage the files involved in a merge, after
5244 command is used to manage the files involved in a merge, after
5243 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5245 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5244 working directory must have two parents). See :hg:`help
5246 working directory must have two parents). See :hg:`help
5245 merge-tools` for information on configuring merge tools.
5247 merge-tools` for information on configuring merge tools.
5246
5248
5247 The resolve command can be used in the following ways:
5249 The resolve command can be used in the following ways:
5248
5250
5249 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5251 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5250 files, discarding any previous merge attempts. Re-merging is not
5252 files, discarding any previous merge attempts. Re-merging is not
5251 performed for files already marked as resolved. Use ``--all/-a``
5253 performed for files already marked as resolved. Use ``--all/-a``
5252 to select all unresolved files. ``--tool`` can be used to specify
5254 to select all unresolved files. ``--tool`` can be used to specify
5253 the merge tool used for the given files. It overrides the HGMERGE
5255 the merge tool used for the given files. It overrides the HGMERGE
5254 environment variable and your configuration files. Previous file
5256 environment variable and your configuration files. Previous file
5255 contents are saved with a ``.orig`` suffix.
5257 contents are saved with a ``.orig`` suffix.
5256
5258
5257 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5259 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5258 (e.g. after having manually fixed-up the files). The default is
5260 (e.g. after having manually fixed-up the files). The default is
5259 to mark all unresolved files.
5261 to mark all unresolved files.
5260
5262
5261 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5263 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5262 default is to mark all resolved files.
5264 default is to mark all resolved files.
5263
5265
5264 - :hg:`resolve -l`: list files which had or still have conflicts.
5266 - :hg:`resolve -l`: list files which had or still have conflicts.
5265 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5267 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5266
5268
5267 Note that Mercurial will not let you commit files with unresolved
5269 Note that Mercurial will not let you commit files with unresolved
5268 merge conflicts. You must use :hg:`resolve -m ...` before you can
5270 merge conflicts. You must use :hg:`resolve -m ...` before you can
5269 commit after a conflicting merge.
5271 commit after a conflicting merge.
5270
5272
5271 Returns 0 on success, 1 if any files fail a resolve attempt.
5273 Returns 0 on success, 1 if any files fail a resolve attempt.
5272 """
5274 """
5273
5275
5274 all, mark, unmark, show, nostatus = \
5276 all, mark, unmark, show, nostatus = \
5275 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5277 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5276
5278
5277 if (show and (mark or unmark)) or (mark and unmark):
5279 if (show and (mark or unmark)) or (mark and unmark):
5278 raise util.Abort(_("too many options specified"))
5280 raise util.Abort(_("too many options specified"))
5279 if pats and all:
5281 if pats and all:
5280 raise util.Abort(_("can't specify --all and patterns"))
5282 raise util.Abort(_("can't specify --all and patterns"))
5281 if not (all or pats or show or mark or unmark):
5283 if not (all or pats or show or mark or unmark):
5282 raise util.Abort(_('no files or directories specified'),
5284 raise util.Abort(_('no files or directories specified'),
5283 hint=('use --all to remerge all files'))
5285 hint=('use --all to remerge all files'))
5284
5286
5285 wlock = repo.wlock()
5287 wlock = repo.wlock()
5286 try:
5288 try:
5287 ms = mergemod.mergestate(repo)
5289 ms = mergemod.mergestate(repo)
5288
5290
5289 if not ms.active() and not show:
5291 if not ms.active() and not show:
5290 raise util.Abort(
5292 raise util.Abort(
5291 _('resolve command not applicable when not merging'))
5293 _('resolve command not applicable when not merging'))
5292
5294
5293 m = scmutil.match(repo[None], pats, opts)
5295 m = scmutil.match(repo[None], pats, opts)
5294 ret = 0
5296 ret = 0
5295 didwork = False
5297 didwork = False
5296
5298
5297 for f in ms:
5299 for f in ms:
5298 if not m(f):
5300 if not m(f):
5299 continue
5301 continue
5300
5302
5301 didwork = True
5303 didwork = True
5302
5304
5303 if show:
5305 if show:
5304 if nostatus:
5306 if nostatus:
5305 ui.write("%s\n" % f)
5307 ui.write("%s\n" % f)
5306 else:
5308 else:
5307 ui.write("%s %s\n" % (ms[f].upper(), f),
5309 ui.write("%s %s\n" % (ms[f].upper(), f),
5308 label='resolve.' +
5310 label='resolve.' +
5309 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5311 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5310 elif mark:
5312 elif mark:
5311 ms.mark(f, "r")
5313 ms.mark(f, "r")
5312 elif unmark:
5314 elif unmark:
5313 ms.mark(f, "u")
5315 ms.mark(f, "u")
5314 else:
5316 else:
5315 wctx = repo[None]
5317 wctx = repo[None]
5316
5318
5317 # backup pre-resolve (merge uses .orig for its own purposes)
5319 # backup pre-resolve (merge uses .orig for its own purposes)
5318 a = repo.wjoin(f)
5320 a = repo.wjoin(f)
5319 util.copyfile(a, a + ".resolve")
5321 util.copyfile(a, a + ".resolve")
5320
5322
5321 try:
5323 try:
5322 # resolve file
5324 # resolve file
5323 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5325 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5324 'resolve')
5326 'resolve')
5325 if ms.resolve(f, wctx):
5327 if ms.resolve(f, wctx):
5326 ret = 1
5328 ret = 1
5327 finally:
5329 finally:
5328 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5330 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5329 ms.commit()
5331 ms.commit()
5330
5332
5331 # replace filemerge's .orig file with our resolve file
5333 # replace filemerge's .orig file with our resolve file
5332 util.rename(a + ".resolve", a + ".orig")
5334 util.rename(a + ".resolve", a + ".orig")
5333
5335
5334 ms.commit()
5336 ms.commit()
5335
5337
5336 if not didwork and pats:
5338 if not didwork and pats:
5337 ui.warn(_("arguments do not match paths that need resolving\n"))
5339 ui.warn(_("arguments do not match paths that need resolving\n"))
5338
5340
5339 finally:
5341 finally:
5340 wlock.release()
5342 wlock.release()
5341
5343
5342 # Nudge users into finishing an unfinished operation. We don't print
5344 # Nudge users into finishing an unfinished operation. We don't print
5343 # this with the list/show operation because we want list/show to remain
5345 # this with the list/show operation because we want list/show to remain
5344 # machine readable.
5346 # machine readable.
5345 if not list(ms.unresolved()) and not show:
5347 if not list(ms.unresolved()) and not show:
5346 ui.status(_('(no more unresolved files)\n'))
5348 ui.status(_('(no more unresolved files)\n'))
5347
5349
5348 return ret
5350 return ret
5349
5351
5350 @command('revert',
5352 @command('revert',
5351 [('a', 'all', None, _('revert all changes when no arguments given')),
5353 [('a', 'all', None, _('revert all changes when no arguments given')),
5352 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5354 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5353 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5355 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5354 ('C', 'no-backup', None, _('do not save backup copies of files')),
5356 ('C', 'no-backup', None, _('do not save backup copies of files')),
5355 ] + walkopts + dryrunopts,
5357 ] + walkopts + dryrunopts,
5356 _('[OPTION]... [-r REV] [NAME]...'))
5358 _('[OPTION]... [-r REV] [NAME]...'))
5357 def revert(ui, repo, *pats, **opts):
5359 def revert(ui, repo, *pats, **opts):
5358 """restore files to their checkout state
5360 """restore files to their checkout state
5359
5361
5360 .. note::
5362 .. note::
5361
5363
5362 To check out earlier revisions, you should use :hg:`update REV`.
5364 To check out earlier revisions, you should use :hg:`update REV`.
5363 To cancel an uncommitted merge (and lose your changes),
5365 To cancel an uncommitted merge (and lose your changes),
5364 use :hg:`update --clean .`.
5366 use :hg:`update --clean .`.
5365
5367
5366 With no revision specified, revert the specified files or directories
5368 With no revision specified, revert the specified files or directories
5367 to the contents they had in the parent of the working directory.
5369 to the contents they had in the parent of the working directory.
5368 This restores the contents of files to an unmodified
5370 This restores the contents of files to an unmodified
5369 state and unschedules adds, removes, copies, and renames. If the
5371 state and unschedules adds, removes, copies, and renames. If the
5370 working directory has two parents, you must explicitly specify a
5372 working directory has two parents, you must explicitly specify a
5371 revision.
5373 revision.
5372
5374
5373 Using the -r/--rev or -d/--date options, revert the given files or
5375 Using the -r/--rev or -d/--date options, revert the given files or
5374 directories to their states as of a specific revision. Because
5376 directories to their states as of a specific revision. Because
5375 revert does not change the working directory parents, this will
5377 revert does not change the working directory parents, this will
5376 cause these files to appear modified. This can be helpful to "back
5378 cause these files to appear modified. This can be helpful to "back
5377 out" some or all of an earlier change. See :hg:`backout` for a
5379 out" some or all of an earlier change. See :hg:`backout` for a
5378 related method.
5380 related method.
5379
5381
5380 Modified files are saved with a .orig suffix before reverting.
5382 Modified files are saved with a .orig suffix before reverting.
5381 To disable these backups, use --no-backup.
5383 To disable these backups, use --no-backup.
5382
5384
5383 See :hg:`help dates` for a list of formats valid for -d/--date.
5385 See :hg:`help dates` for a list of formats valid for -d/--date.
5384
5386
5385 Returns 0 on success.
5387 Returns 0 on success.
5386 """
5388 """
5387
5389
5388 if opts.get("date"):
5390 if opts.get("date"):
5389 if opts.get("rev"):
5391 if opts.get("rev"):
5390 raise util.Abort(_("you can't specify a revision and a date"))
5392 raise util.Abort(_("you can't specify a revision and a date"))
5391 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5393 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5392
5394
5393 parent, p2 = repo.dirstate.parents()
5395 parent, p2 = repo.dirstate.parents()
5394 if not opts.get('rev') and p2 != nullid:
5396 if not opts.get('rev') and p2 != nullid:
5395 # revert after merge is a trap for new users (issue2915)
5397 # revert after merge is a trap for new users (issue2915)
5396 raise util.Abort(_('uncommitted merge with no revision specified'),
5398 raise util.Abort(_('uncommitted merge with no revision specified'),
5397 hint=_('use "hg update" or see "hg help revert"'))
5399 hint=_('use "hg update" or see "hg help revert"'))
5398
5400
5399 ctx = scmutil.revsingle(repo, opts.get('rev'))
5401 ctx = scmutil.revsingle(repo, opts.get('rev'))
5400
5402
5401 if not pats and not opts.get('all'):
5403 if not pats and not opts.get('all'):
5402 msg = _("no files or directories specified")
5404 msg = _("no files or directories specified")
5403 if p2 != nullid:
5405 if p2 != nullid:
5404 hint = _("uncommitted merge, use --all to discard all changes,"
5406 hint = _("uncommitted merge, use --all to discard all changes,"
5405 " or 'hg update -C .' to abort the merge")
5407 " or 'hg update -C .' to abort the merge")
5406 raise util.Abort(msg, hint=hint)
5408 raise util.Abort(msg, hint=hint)
5407 dirty = util.any(repo.status())
5409 dirty = util.any(repo.status())
5408 node = ctx.node()
5410 node = ctx.node()
5409 if node != parent:
5411 if node != parent:
5410 if dirty:
5412 if dirty:
5411 hint = _("uncommitted changes, use --all to discard all"
5413 hint = _("uncommitted changes, use --all to discard all"
5412 " changes, or 'hg update %s' to update") % ctx.rev()
5414 " changes, or 'hg update %s' to update") % ctx.rev()
5413 else:
5415 else:
5414 hint = _("use --all to revert all files,"
5416 hint = _("use --all to revert all files,"
5415 " or 'hg update %s' to update") % ctx.rev()
5417 " or 'hg update %s' to update") % ctx.rev()
5416 elif dirty:
5418 elif dirty:
5417 hint = _("uncommitted changes, use --all to discard all changes")
5419 hint = _("uncommitted changes, use --all to discard all changes")
5418 else:
5420 else:
5419 hint = _("use --all to revert all files")
5421 hint = _("use --all to revert all files")
5420 raise util.Abort(msg, hint=hint)
5422 raise util.Abort(msg, hint=hint)
5421
5423
5422 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5424 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5423
5425
5424 @command('rollback', dryrunopts +
5426 @command('rollback', dryrunopts +
5425 [('f', 'force', False, _('ignore safety measures'))])
5427 [('f', 'force', False, _('ignore safety measures'))])
5426 def rollback(ui, repo, **opts):
5428 def rollback(ui, repo, **opts):
5427 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5429 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5428
5430
5429 Please use :hg:`commit --amend` instead of rollback to correct
5431 Please use :hg:`commit --amend` instead of rollback to correct
5430 mistakes in the last commit.
5432 mistakes in the last commit.
5431
5433
5432 This command should be used with care. There is only one level of
5434 This command should be used with care. There is only one level of
5433 rollback, and there is no way to undo a rollback. It will also
5435 rollback, and there is no way to undo a rollback. It will also
5434 restore the dirstate at the time of the last transaction, losing
5436 restore the dirstate at the time of the last transaction, losing
5435 any dirstate changes since that time. This command does not alter
5437 any dirstate changes since that time. This command does not alter
5436 the working directory.
5438 the working directory.
5437
5439
5438 Transactions are used to encapsulate the effects of all commands
5440 Transactions are used to encapsulate the effects of all commands
5439 that create new changesets or propagate existing changesets into a
5441 that create new changesets or propagate existing changesets into a
5440 repository.
5442 repository.
5441
5443
5442 .. container:: verbose
5444 .. container:: verbose
5443
5445
5444 For example, the following commands are transactional, and their
5446 For example, the following commands are transactional, and their
5445 effects can be rolled back:
5447 effects can be rolled back:
5446
5448
5447 - commit
5449 - commit
5448 - import
5450 - import
5449 - pull
5451 - pull
5450 - push (with this repository as the destination)
5452 - push (with this repository as the destination)
5451 - unbundle
5453 - unbundle
5452
5454
5453 To avoid permanent data loss, rollback will refuse to rollback a
5455 To avoid permanent data loss, rollback will refuse to rollback a
5454 commit transaction if it isn't checked out. Use --force to
5456 commit transaction if it isn't checked out. Use --force to
5455 override this protection.
5457 override this protection.
5456
5458
5457 This command is not intended for use on public repositories. Once
5459 This command is not intended for use on public repositories. Once
5458 changes are visible for pull by other users, rolling a transaction
5460 changes are visible for pull by other users, rolling a transaction
5459 back locally is ineffective (someone else may already have pulled
5461 back locally is ineffective (someone else may already have pulled
5460 the changes). Furthermore, a race is possible with readers of the
5462 the changes). Furthermore, a race is possible with readers of the
5461 repository; for example an in-progress pull from the repository
5463 repository; for example an in-progress pull from the repository
5462 may fail if a rollback is performed.
5464 may fail if a rollback is performed.
5463
5465
5464 Returns 0 on success, 1 if no rollback data is available.
5466 Returns 0 on success, 1 if no rollback data is available.
5465 """
5467 """
5466 return repo.rollback(dryrun=opts.get('dry_run'),
5468 return repo.rollback(dryrun=opts.get('dry_run'),
5467 force=opts.get('force'))
5469 force=opts.get('force'))
5468
5470
5469 @command('root', [])
5471 @command('root', [])
5470 def root(ui, repo):
5472 def root(ui, repo):
5471 """print the root (top) of the current working directory
5473 """print the root (top) of the current working directory
5472
5474
5473 Print the root directory of the current repository.
5475 Print the root directory of the current repository.
5474
5476
5475 Returns 0 on success.
5477 Returns 0 on success.
5476 """
5478 """
5477 ui.write(repo.root + "\n")
5479 ui.write(repo.root + "\n")
5478
5480
5479 @command('^serve',
5481 @command('^serve',
5480 [('A', 'accesslog', '', _('name of access log file to write to'),
5482 [('A', 'accesslog', '', _('name of access log file to write to'),
5481 _('FILE')),
5483 _('FILE')),
5482 ('d', 'daemon', None, _('run server in background')),
5484 ('d', 'daemon', None, _('run server in background')),
5483 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5485 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5484 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5486 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5485 # use string type, then we can check if something was passed
5487 # use string type, then we can check if something was passed
5486 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5488 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5487 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5489 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5488 _('ADDR')),
5490 _('ADDR')),
5489 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5491 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5490 _('PREFIX')),
5492 _('PREFIX')),
5491 ('n', 'name', '',
5493 ('n', 'name', '',
5492 _('name to show in web pages (default: working directory)'), _('NAME')),
5494 _('name to show in web pages (default: working directory)'), _('NAME')),
5493 ('', 'web-conf', '',
5495 ('', 'web-conf', '',
5494 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5496 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5495 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5497 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5496 _('FILE')),
5498 _('FILE')),
5497 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5499 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5498 ('', 'stdio', None, _('for remote clients')),
5500 ('', 'stdio', None, _('for remote clients')),
5499 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5501 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5500 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5502 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5501 ('', 'style', '', _('template style to use'), _('STYLE')),
5503 ('', 'style', '', _('template style to use'), _('STYLE')),
5502 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5504 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5503 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5505 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5504 _('[OPTION]...'),
5506 _('[OPTION]...'),
5505 optionalrepo=True)
5507 optionalrepo=True)
5506 def serve(ui, repo, **opts):
5508 def serve(ui, repo, **opts):
5507 """start stand-alone webserver
5509 """start stand-alone webserver
5508
5510
5509 Start a local HTTP repository browser and pull server. You can use
5511 Start a local HTTP repository browser and pull server. You can use
5510 this for ad-hoc sharing and browsing of repositories. It is
5512 this for ad-hoc sharing and browsing of repositories. It is
5511 recommended to use a real web server to serve a repository for
5513 recommended to use a real web server to serve a repository for
5512 longer periods of time.
5514 longer periods of time.
5513
5515
5514 Please note that the server does not implement access control.
5516 Please note that the server does not implement access control.
5515 This means that, by default, anybody can read from the server and
5517 This means that, by default, anybody can read from the server and
5516 nobody can write to it by default. Set the ``web.allow_push``
5518 nobody can write to it by default. Set the ``web.allow_push``
5517 option to ``*`` to allow everybody to push to the server. You
5519 option to ``*`` to allow everybody to push to the server. You
5518 should use a real web server if you need to authenticate users.
5520 should use a real web server if you need to authenticate users.
5519
5521
5520 By default, the server logs accesses to stdout and errors to
5522 By default, the server logs accesses to stdout and errors to
5521 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5523 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5522 files.
5524 files.
5523
5525
5524 To have the server choose a free port number to listen on, specify
5526 To have the server choose a free port number to listen on, specify
5525 a port number of 0; in this case, the server will print the port
5527 a port number of 0; in this case, the server will print the port
5526 number it uses.
5528 number it uses.
5527
5529
5528 Returns 0 on success.
5530 Returns 0 on success.
5529 """
5531 """
5530
5532
5531 if opts["stdio"] and opts["cmdserver"]:
5533 if opts["stdio"] and opts["cmdserver"]:
5532 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5534 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5533
5535
5534 if opts["stdio"]:
5536 if opts["stdio"]:
5535 if repo is None:
5537 if repo is None:
5536 raise error.RepoError(_("there is no Mercurial repository here"
5538 raise error.RepoError(_("there is no Mercurial repository here"
5537 " (.hg not found)"))
5539 " (.hg not found)"))
5538 s = sshserver.sshserver(ui, repo)
5540 s = sshserver.sshserver(ui, repo)
5539 s.serve_forever()
5541 s.serve_forever()
5540
5542
5541 if opts["cmdserver"]:
5543 if opts["cmdserver"]:
5542 s = commandserver.server(ui, repo, opts["cmdserver"])
5544 s = commandserver.server(ui, repo, opts["cmdserver"])
5543 return s.serve()
5545 return s.serve()
5544
5546
5545 # this way we can check if something was given in the command-line
5547 # this way we can check if something was given in the command-line
5546 if opts.get('port'):
5548 if opts.get('port'):
5547 opts['port'] = util.getport(opts.get('port'))
5549 opts['port'] = util.getport(opts.get('port'))
5548
5550
5549 baseui = repo and repo.baseui or ui
5551 baseui = repo and repo.baseui or ui
5550 optlist = ("name templates style address port prefix ipv6"
5552 optlist = ("name templates style address port prefix ipv6"
5551 " accesslog errorlog certificate encoding")
5553 " accesslog errorlog certificate encoding")
5552 for o in optlist.split():
5554 for o in optlist.split():
5553 val = opts.get(o, '')
5555 val = opts.get(o, '')
5554 if val in (None, ''): # should check against default options instead
5556 if val in (None, ''): # should check against default options instead
5555 continue
5557 continue
5556 baseui.setconfig("web", o, val, 'serve')
5558 baseui.setconfig("web", o, val, 'serve')
5557 if repo and repo.ui != baseui:
5559 if repo and repo.ui != baseui:
5558 repo.ui.setconfig("web", o, val, 'serve')
5560 repo.ui.setconfig("web", o, val, 'serve')
5559
5561
5560 o = opts.get('web_conf') or opts.get('webdir_conf')
5562 o = opts.get('web_conf') or opts.get('webdir_conf')
5561 if not o:
5563 if not o:
5562 if not repo:
5564 if not repo:
5563 raise error.RepoError(_("there is no Mercurial repository"
5565 raise error.RepoError(_("there is no Mercurial repository"
5564 " here (.hg not found)"))
5566 " here (.hg not found)"))
5565 o = repo
5567 o = repo
5566
5568
5567 app = hgweb.hgweb(o, baseui=baseui)
5569 app = hgweb.hgweb(o, baseui=baseui)
5568 service = httpservice(ui, app, opts)
5570 service = httpservice(ui, app, opts)
5569 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5571 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5570
5572
5571 class httpservice(object):
5573 class httpservice(object):
5572 def __init__(self, ui, app, opts):
5574 def __init__(self, ui, app, opts):
5573 self.ui = ui
5575 self.ui = ui
5574 self.app = app
5576 self.app = app
5575 self.opts = opts
5577 self.opts = opts
5576
5578
5577 def init(self):
5579 def init(self):
5578 util.setsignalhandler()
5580 util.setsignalhandler()
5579 self.httpd = hgweb_server.create_server(self.ui, self.app)
5581 self.httpd = hgweb_server.create_server(self.ui, self.app)
5580
5582
5581 if self.opts['port'] and not self.ui.verbose:
5583 if self.opts['port'] and not self.ui.verbose:
5582 return
5584 return
5583
5585
5584 if self.httpd.prefix:
5586 if self.httpd.prefix:
5585 prefix = self.httpd.prefix.strip('/') + '/'
5587 prefix = self.httpd.prefix.strip('/') + '/'
5586 else:
5588 else:
5587 prefix = ''
5589 prefix = ''
5588
5590
5589 port = ':%d' % self.httpd.port
5591 port = ':%d' % self.httpd.port
5590 if port == ':80':
5592 if port == ':80':
5591 port = ''
5593 port = ''
5592
5594
5593 bindaddr = self.httpd.addr
5595 bindaddr = self.httpd.addr
5594 if bindaddr == '0.0.0.0':
5596 if bindaddr == '0.0.0.0':
5595 bindaddr = '*'
5597 bindaddr = '*'
5596 elif ':' in bindaddr: # IPv6
5598 elif ':' in bindaddr: # IPv6
5597 bindaddr = '[%s]' % bindaddr
5599 bindaddr = '[%s]' % bindaddr
5598
5600
5599 fqaddr = self.httpd.fqaddr
5601 fqaddr = self.httpd.fqaddr
5600 if ':' in fqaddr:
5602 if ':' in fqaddr:
5601 fqaddr = '[%s]' % fqaddr
5603 fqaddr = '[%s]' % fqaddr
5602 if self.opts['port']:
5604 if self.opts['port']:
5603 write = self.ui.status
5605 write = self.ui.status
5604 else:
5606 else:
5605 write = self.ui.write
5607 write = self.ui.write
5606 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5608 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5607 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5609 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5608 self.ui.flush() # avoid buffering of status message
5610 self.ui.flush() # avoid buffering of status message
5609
5611
5610 def run(self):
5612 def run(self):
5611 self.httpd.serve_forever()
5613 self.httpd.serve_forever()
5612
5614
5613
5615
5614 @command('^status|st',
5616 @command('^status|st',
5615 [('A', 'all', None, _('show status of all files')),
5617 [('A', 'all', None, _('show status of all files')),
5616 ('m', 'modified', None, _('show only modified files')),
5618 ('m', 'modified', None, _('show only modified files')),
5617 ('a', 'added', None, _('show only added files')),
5619 ('a', 'added', None, _('show only added files')),
5618 ('r', 'removed', None, _('show only removed files')),
5620 ('r', 'removed', None, _('show only removed files')),
5619 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5621 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5620 ('c', 'clean', None, _('show only files without changes')),
5622 ('c', 'clean', None, _('show only files without changes')),
5621 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5623 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5622 ('i', 'ignored', None, _('show only ignored files')),
5624 ('i', 'ignored', None, _('show only ignored files')),
5623 ('n', 'no-status', None, _('hide status prefix')),
5625 ('n', 'no-status', None, _('hide status prefix')),
5624 ('C', 'copies', None, _('show source of copied files')),
5626 ('C', 'copies', None, _('show source of copied files')),
5625 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5627 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5626 ('', 'rev', [], _('show difference from revision'), _('REV')),
5628 ('', 'rev', [], _('show difference from revision'), _('REV')),
5627 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5629 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5628 ] + walkopts + subrepoopts + formatteropts,
5630 ] + walkopts + subrepoopts + formatteropts,
5629 _('[OPTION]... [FILE]...'),
5631 _('[OPTION]... [FILE]...'),
5630 inferrepo=True)
5632 inferrepo=True)
5631 def status(ui, repo, *pats, **opts):
5633 def status(ui, repo, *pats, **opts):
5632 """show changed files in the working directory
5634 """show changed files in the working directory
5633
5635
5634 Show status of files in the repository. If names are given, only
5636 Show status of files in the repository. If names are given, only
5635 files that match are shown. Files that are clean or ignored or
5637 files that match are shown. Files that are clean or ignored or
5636 the source of a copy/move operation, are not listed unless
5638 the source of a copy/move operation, are not listed unless
5637 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5639 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5638 Unless options described with "show only ..." are given, the
5640 Unless options described with "show only ..." are given, the
5639 options -mardu are used.
5641 options -mardu are used.
5640
5642
5641 Option -q/--quiet hides untracked (unknown and ignored) files
5643 Option -q/--quiet hides untracked (unknown and ignored) files
5642 unless explicitly requested with -u/--unknown or -i/--ignored.
5644 unless explicitly requested with -u/--unknown or -i/--ignored.
5643
5645
5644 .. note::
5646 .. note::
5645
5647
5646 status may appear to disagree with diff if permissions have
5648 status may appear to disagree with diff if permissions have
5647 changed or a merge has occurred. The standard diff format does
5649 changed or a merge has occurred. The standard diff format does
5648 not report permission changes and diff only reports changes
5650 not report permission changes and diff only reports changes
5649 relative to one merge parent.
5651 relative to one merge parent.
5650
5652
5651 If one revision is given, it is used as the base revision.
5653 If one revision is given, it is used as the base revision.
5652 If two revisions are given, the differences between them are
5654 If two revisions are given, the differences between them are
5653 shown. The --change option can also be used as a shortcut to list
5655 shown. The --change option can also be used as a shortcut to list
5654 the changed files of a revision from its first parent.
5656 the changed files of a revision from its first parent.
5655
5657
5656 The codes used to show the status of files are::
5658 The codes used to show the status of files are::
5657
5659
5658 M = modified
5660 M = modified
5659 A = added
5661 A = added
5660 R = removed
5662 R = removed
5661 C = clean
5663 C = clean
5662 ! = missing (deleted by non-hg command, but still tracked)
5664 ! = missing (deleted by non-hg command, but still tracked)
5663 ? = not tracked
5665 ? = not tracked
5664 I = ignored
5666 I = ignored
5665 = origin of the previous file (with --copies)
5667 = origin of the previous file (with --copies)
5666
5668
5667 .. container:: verbose
5669 .. container:: verbose
5668
5670
5669 Examples:
5671 Examples:
5670
5672
5671 - show changes in the working directory relative to a
5673 - show changes in the working directory relative to a
5672 changeset::
5674 changeset::
5673
5675
5674 hg status --rev 9353
5676 hg status --rev 9353
5675
5677
5676 - show all changes including copies in an existing changeset::
5678 - show all changes including copies in an existing changeset::
5677
5679
5678 hg status --copies --change 9353
5680 hg status --copies --change 9353
5679
5681
5680 - get a NUL separated list of added files, suitable for xargs::
5682 - get a NUL separated list of added files, suitable for xargs::
5681
5683
5682 hg status -an0
5684 hg status -an0
5683
5685
5684 Returns 0 on success.
5686 Returns 0 on success.
5685 """
5687 """
5686
5688
5687 revs = opts.get('rev')
5689 revs = opts.get('rev')
5688 change = opts.get('change')
5690 change = opts.get('change')
5689
5691
5690 if revs and change:
5692 if revs and change:
5691 msg = _('cannot specify --rev and --change at the same time')
5693 msg = _('cannot specify --rev and --change at the same time')
5692 raise util.Abort(msg)
5694 raise util.Abort(msg)
5693 elif change:
5695 elif change:
5694 node2 = scmutil.revsingle(repo, change, None).node()
5696 node2 = scmutil.revsingle(repo, change, None).node()
5695 node1 = repo[node2].p1().node()
5697 node1 = repo[node2].p1().node()
5696 else:
5698 else:
5697 node1, node2 = scmutil.revpair(repo, revs)
5699 node1, node2 = scmutil.revpair(repo, revs)
5698
5700
5699 cwd = (pats and repo.getcwd()) or ''
5701 cwd = (pats and repo.getcwd()) or ''
5700 end = opts.get('print0') and '\0' or '\n'
5702 end = opts.get('print0') and '\0' or '\n'
5701 copy = {}
5703 copy = {}
5702 states = 'modified added removed deleted unknown ignored clean'.split()
5704 states = 'modified added removed deleted unknown ignored clean'.split()
5703 show = [k for k in states if opts.get(k)]
5705 show = [k for k in states if opts.get(k)]
5704 if opts.get('all'):
5706 if opts.get('all'):
5705 show += ui.quiet and (states[:4] + ['clean']) or states
5707 show += ui.quiet and (states[:4] + ['clean']) or states
5706 if not show:
5708 if not show:
5707 show = ui.quiet and states[:4] or states[:5]
5709 show = ui.quiet and states[:4] or states[:5]
5708
5710
5709 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5711 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5710 'ignored' in show, 'clean' in show, 'unknown' in show,
5712 'ignored' in show, 'clean' in show, 'unknown' in show,
5711 opts.get('subrepos'))
5713 opts.get('subrepos'))
5712 changestates = zip(states, 'MAR!?IC', stat)
5714 changestates = zip(states, 'MAR!?IC', stat)
5713
5715
5714 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5716 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5715 copy = copies.pathcopies(repo[node1], repo[node2])
5717 copy = copies.pathcopies(repo[node1], repo[node2])
5716
5718
5717 fm = ui.formatter('status', opts)
5719 fm = ui.formatter('status', opts)
5718 fmt = '%s' + end
5720 fmt = '%s' + end
5719 showchar = not opts.get('no_status')
5721 showchar = not opts.get('no_status')
5720
5722
5721 for state, char, files in changestates:
5723 for state, char, files in changestates:
5722 if state in show:
5724 if state in show:
5723 label = 'status.' + state
5725 label = 'status.' + state
5724 for f in files:
5726 for f in files:
5725 fm.startitem()
5727 fm.startitem()
5726 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5728 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5727 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5729 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5728 if f in copy:
5730 if f in copy:
5729 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5731 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5730 label='status.copied')
5732 label='status.copied')
5731 fm.end()
5733 fm.end()
5732
5734
5733 @command('^summary|sum',
5735 @command('^summary|sum',
5734 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5736 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5735 def summary(ui, repo, **opts):
5737 def summary(ui, repo, **opts):
5736 """summarize working directory state
5738 """summarize working directory state
5737
5739
5738 This generates a brief summary of the working directory state,
5740 This generates a brief summary of the working directory state,
5739 including parents, branch, commit status, and available updates.
5741 including parents, branch, commit status, and available updates.
5740
5742
5741 With the --remote option, this will check the default paths for
5743 With the --remote option, this will check the default paths for
5742 incoming and outgoing changes. This can be time-consuming.
5744 incoming and outgoing changes. This can be time-consuming.
5743
5745
5744 Returns 0 on success.
5746 Returns 0 on success.
5745 """
5747 """
5746
5748
5747 ctx = repo[None]
5749 ctx = repo[None]
5748 parents = ctx.parents()
5750 parents = ctx.parents()
5749 pnode = parents[0].node()
5751 pnode = parents[0].node()
5750 marks = []
5752 marks = []
5751
5753
5752 for p in parents:
5754 for p in parents:
5753 # label with log.changeset (instead of log.parent) since this
5755 # label with log.changeset (instead of log.parent) since this
5754 # shows a working directory parent *changeset*:
5756 # shows a working directory parent *changeset*:
5755 # i18n: column positioning for "hg summary"
5757 # i18n: column positioning for "hg summary"
5756 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5758 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5757 label='log.changeset changeset.%s' % p.phasestr())
5759 label='log.changeset changeset.%s' % p.phasestr())
5758 ui.write(' '.join(p.tags()), label='log.tag')
5760 ui.write(' '.join(p.tags()), label='log.tag')
5759 if p.bookmarks():
5761 if p.bookmarks():
5760 marks.extend(p.bookmarks())
5762 marks.extend(p.bookmarks())
5761 if p.rev() == -1:
5763 if p.rev() == -1:
5762 if not len(repo):
5764 if not len(repo):
5763 ui.write(_(' (empty repository)'))
5765 ui.write(_(' (empty repository)'))
5764 else:
5766 else:
5765 ui.write(_(' (no revision checked out)'))
5767 ui.write(_(' (no revision checked out)'))
5766 ui.write('\n')
5768 ui.write('\n')
5767 if p.description():
5769 if p.description():
5768 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5770 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5769 label='log.summary')
5771 label='log.summary')
5770
5772
5771 branch = ctx.branch()
5773 branch = ctx.branch()
5772 bheads = repo.branchheads(branch)
5774 bheads = repo.branchheads(branch)
5773 # i18n: column positioning for "hg summary"
5775 # i18n: column positioning for "hg summary"
5774 m = _('branch: %s\n') % branch
5776 m = _('branch: %s\n') % branch
5775 if branch != 'default':
5777 if branch != 'default':
5776 ui.write(m, label='log.branch')
5778 ui.write(m, label='log.branch')
5777 else:
5779 else:
5778 ui.status(m, label='log.branch')
5780 ui.status(m, label='log.branch')
5779
5781
5780 if marks:
5782 if marks:
5781 current = repo._bookmarkcurrent
5783 current = repo._bookmarkcurrent
5782 # i18n: column positioning for "hg summary"
5784 # i18n: column positioning for "hg summary"
5783 ui.write(_('bookmarks:'), label='log.bookmark')
5785 ui.write(_('bookmarks:'), label='log.bookmark')
5784 if current is not None:
5786 if current is not None:
5785 if current in marks:
5787 if current in marks:
5786 ui.write(' *' + current, label='bookmarks.current')
5788 ui.write(' *' + current, label='bookmarks.current')
5787 marks.remove(current)
5789 marks.remove(current)
5788 else:
5790 else:
5789 ui.write(' [%s]' % current, label='bookmarks.current')
5791 ui.write(' [%s]' % current, label='bookmarks.current')
5790 for m in marks:
5792 for m in marks:
5791 ui.write(' ' + m, label='log.bookmark')
5793 ui.write(' ' + m, label='log.bookmark')
5792 ui.write('\n', label='log.bookmark')
5794 ui.write('\n', label='log.bookmark')
5793
5795
5794 st = list(repo.status(unknown=True))[:5]
5796 st = list(repo.status(unknown=True))[:5]
5795
5797
5796 c = repo.dirstate.copies()
5798 c = repo.dirstate.copies()
5797 copied, renamed = [], []
5799 copied, renamed = [], []
5798 for d, s in c.iteritems():
5800 for d, s in c.iteritems():
5799 if s in st[2]:
5801 if s in st[2]:
5800 st[2].remove(s)
5802 st[2].remove(s)
5801 renamed.append(d)
5803 renamed.append(d)
5802 else:
5804 else:
5803 copied.append(d)
5805 copied.append(d)
5804 if d in st[1]:
5806 if d in st[1]:
5805 st[1].remove(d)
5807 st[1].remove(d)
5806 st.insert(3, renamed)
5808 st.insert(3, renamed)
5807 st.insert(4, copied)
5809 st.insert(4, copied)
5808
5810
5809 ms = mergemod.mergestate(repo)
5811 ms = mergemod.mergestate(repo)
5810 st.append([f for f in ms if ms[f] == 'u'])
5812 st.append([f for f in ms if ms[f] == 'u'])
5811
5813
5812 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5814 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5813 st.append(subs)
5815 st.append(subs)
5814
5816
5815 labels = [ui.label(_('%d modified'), 'status.modified'),
5817 labels = [ui.label(_('%d modified'), 'status.modified'),
5816 ui.label(_('%d added'), 'status.added'),
5818 ui.label(_('%d added'), 'status.added'),
5817 ui.label(_('%d removed'), 'status.removed'),
5819 ui.label(_('%d removed'), 'status.removed'),
5818 ui.label(_('%d renamed'), 'status.copied'),
5820 ui.label(_('%d renamed'), 'status.copied'),
5819 ui.label(_('%d copied'), 'status.copied'),
5821 ui.label(_('%d copied'), 'status.copied'),
5820 ui.label(_('%d deleted'), 'status.deleted'),
5822 ui.label(_('%d deleted'), 'status.deleted'),
5821 ui.label(_('%d unknown'), 'status.unknown'),
5823 ui.label(_('%d unknown'), 'status.unknown'),
5822 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5824 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5823 ui.label(_('%d subrepos'), 'status.modified')]
5825 ui.label(_('%d subrepos'), 'status.modified')]
5824 t = []
5826 t = []
5825 for s, l in zip(st, labels):
5827 for s, l in zip(st, labels):
5826 if s:
5828 if s:
5827 t.append(l % len(s))
5829 t.append(l % len(s))
5828
5830
5829 t = ', '.join(t)
5831 t = ', '.join(t)
5830 cleanworkdir = False
5832 cleanworkdir = False
5831
5833
5832 if repo.vfs.exists('updatestate'):
5834 if repo.vfs.exists('updatestate'):
5833 t += _(' (interrupted update)')
5835 t += _(' (interrupted update)')
5834 elif len(parents) > 1:
5836 elif len(parents) > 1:
5835 t += _(' (merge)')
5837 t += _(' (merge)')
5836 elif branch != parents[0].branch():
5838 elif branch != parents[0].branch():
5837 t += _(' (new branch)')
5839 t += _(' (new branch)')
5838 elif (parents[0].closesbranch() and
5840 elif (parents[0].closesbranch() and
5839 pnode in repo.branchheads(branch, closed=True)):
5841 pnode in repo.branchheads(branch, closed=True)):
5840 t += _(' (head closed)')
5842 t += _(' (head closed)')
5841 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[8]):
5843 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[8]):
5842 t += _(' (clean)')
5844 t += _(' (clean)')
5843 cleanworkdir = True
5845 cleanworkdir = True
5844 elif pnode not in bheads:
5846 elif pnode not in bheads:
5845 t += _(' (new branch head)')
5847 t += _(' (new branch head)')
5846
5848
5847 if cleanworkdir:
5849 if cleanworkdir:
5848 # i18n: column positioning for "hg summary"
5850 # i18n: column positioning for "hg summary"
5849 ui.status(_('commit: %s\n') % t.strip())
5851 ui.status(_('commit: %s\n') % t.strip())
5850 else:
5852 else:
5851 # i18n: column positioning for "hg summary"
5853 # i18n: column positioning for "hg summary"
5852 ui.write(_('commit: %s\n') % t.strip())
5854 ui.write(_('commit: %s\n') % t.strip())
5853
5855
5854 # all ancestors of branch heads - all ancestors of parent = new csets
5856 # all ancestors of branch heads - all ancestors of parent = new csets
5855 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5857 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5856 bheads))
5858 bheads))
5857
5859
5858 if new == 0:
5860 if new == 0:
5859 # i18n: column positioning for "hg summary"
5861 # i18n: column positioning for "hg summary"
5860 ui.status(_('update: (current)\n'))
5862 ui.status(_('update: (current)\n'))
5861 elif pnode not in bheads:
5863 elif pnode not in bheads:
5862 # i18n: column positioning for "hg summary"
5864 # i18n: column positioning for "hg summary"
5863 ui.write(_('update: %d new changesets (update)\n') % new)
5865 ui.write(_('update: %d new changesets (update)\n') % new)
5864 else:
5866 else:
5865 # i18n: column positioning for "hg summary"
5867 # i18n: column positioning for "hg summary"
5866 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5868 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5867 (new, len(bheads)))
5869 (new, len(bheads)))
5868
5870
5869 cmdutil.summaryhooks(ui, repo)
5871 cmdutil.summaryhooks(ui, repo)
5870
5872
5871 if opts.get('remote'):
5873 if opts.get('remote'):
5872 needsincoming, needsoutgoing = True, True
5874 needsincoming, needsoutgoing = True, True
5873 else:
5875 else:
5874 needsincoming, needsoutgoing = False, False
5876 needsincoming, needsoutgoing = False, False
5875 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5877 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5876 if i:
5878 if i:
5877 needsincoming = True
5879 needsincoming = True
5878 if o:
5880 if o:
5879 needsoutgoing = True
5881 needsoutgoing = True
5880 if not needsincoming and not needsoutgoing:
5882 if not needsincoming and not needsoutgoing:
5881 return
5883 return
5882
5884
5883 def getincoming():
5885 def getincoming():
5884 source, branches = hg.parseurl(ui.expandpath('default'))
5886 source, branches = hg.parseurl(ui.expandpath('default'))
5885 sbranch = branches[0]
5887 sbranch = branches[0]
5886 try:
5888 try:
5887 other = hg.peer(repo, {}, source)
5889 other = hg.peer(repo, {}, source)
5888 except error.RepoError:
5890 except error.RepoError:
5889 if opts.get('remote'):
5891 if opts.get('remote'):
5890 raise
5892 raise
5891 return source, sbranch, None, None, None
5893 return source, sbranch, None, None, None
5892 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5894 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5893 if revs:
5895 if revs:
5894 revs = [other.lookup(rev) for rev in revs]
5896 revs = [other.lookup(rev) for rev in revs]
5895 ui.debug('comparing with %s\n' % util.hidepassword(source))
5897 ui.debug('comparing with %s\n' % util.hidepassword(source))
5896 repo.ui.pushbuffer()
5898 repo.ui.pushbuffer()
5897 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5899 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5898 repo.ui.popbuffer()
5900 repo.ui.popbuffer()
5899 return source, sbranch, other, commoninc, commoninc[1]
5901 return source, sbranch, other, commoninc, commoninc[1]
5900
5902
5901 if needsincoming:
5903 if needsincoming:
5902 source, sbranch, sother, commoninc, incoming = getincoming()
5904 source, sbranch, sother, commoninc, incoming = getincoming()
5903 else:
5905 else:
5904 source = sbranch = sother = commoninc = incoming = None
5906 source = sbranch = sother = commoninc = incoming = None
5905
5907
5906 def getoutgoing():
5908 def getoutgoing():
5907 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5909 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5908 dbranch = branches[0]
5910 dbranch = branches[0]
5909 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5911 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5910 if source != dest:
5912 if source != dest:
5911 try:
5913 try:
5912 dother = hg.peer(repo, {}, dest)
5914 dother = hg.peer(repo, {}, dest)
5913 except error.RepoError:
5915 except error.RepoError:
5914 if opts.get('remote'):
5916 if opts.get('remote'):
5915 raise
5917 raise
5916 return dest, dbranch, None, None
5918 return dest, dbranch, None, None
5917 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5919 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5918 elif sother is None:
5920 elif sother is None:
5919 # there is no explicit destination peer, but source one is invalid
5921 # there is no explicit destination peer, but source one is invalid
5920 return dest, dbranch, None, None
5922 return dest, dbranch, None, None
5921 else:
5923 else:
5922 dother = sother
5924 dother = sother
5923 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5925 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5924 common = None
5926 common = None
5925 else:
5927 else:
5926 common = commoninc
5928 common = commoninc
5927 if revs:
5929 if revs:
5928 revs = [repo.lookup(rev) for rev in revs]
5930 revs = [repo.lookup(rev) for rev in revs]
5929 repo.ui.pushbuffer()
5931 repo.ui.pushbuffer()
5930 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5932 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5931 commoninc=common)
5933 commoninc=common)
5932 repo.ui.popbuffer()
5934 repo.ui.popbuffer()
5933 return dest, dbranch, dother, outgoing
5935 return dest, dbranch, dother, outgoing
5934
5936
5935 if needsoutgoing:
5937 if needsoutgoing:
5936 dest, dbranch, dother, outgoing = getoutgoing()
5938 dest, dbranch, dother, outgoing = getoutgoing()
5937 else:
5939 else:
5938 dest = dbranch = dother = outgoing = None
5940 dest = dbranch = dother = outgoing = None
5939
5941
5940 if opts.get('remote'):
5942 if opts.get('remote'):
5941 t = []
5943 t = []
5942 if incoming:
5944 if incoming:
5943 t.append(_('1 or more incoming'))
5945 t.append(_('1 or more incoming'))
5944 o = outgoing.missing
5946 o = outgoing.missing
5945 if o:
5947 if o:
5946 t.append(_('%d outgoing') % len(o))
5948 t.append(_('%d outgoing') % len(o))
5947 other = dother or sother
5949 other = dother or sother
5948 if 'bookmarks' in other.listkeys('namespaces'):
5950 if 'bookmarks' in other.listkeys('namespaces'):
5949 lmarks = repo.listkeys('bookmarks')
5951 lmarks = repo.listkeys('bookmarks')
5950 rmarks = other.listkeys('bookmarks')
5952 rmarks = other.listkeys('bookmarks')
5951 diff = set(rmarks) - set(lmarks)
5953 diff = set(rmarks) - set(lmarks)
5952 if len(diff) > 0:
5954 if len(diff) > 0:
5953 t.append(_('%d incoming bookmarks') % len(diff))
5955 t.append(_('%d incoming bookmarks') % len(diff))
5954 diff = set(lmarks) - set(rmarks)
5956 diff = set(lmarks) - set(rmarks)
5955 if len(diff) > 0:
5957 if len(diff) > 0:
5956 t.append(_('%d outgoing bookmarks') % len(diff))
5958 t.append(_('%d outgoing bookmarks') % len(diff))
5957
5959
5958 if t:
5960 if t:
5959 # i18n: column positioning for "hg summary"
5961 # i18n: column positioning for "hg summary"
5960 ui.write(_('remote: %s\n') % (', '.join(t)))
5962 ui.write(_('remote: %s\n') % (', '.join(t)))
5961 else:
5963 else:
5962 # i18n: column positioning for "hg summary"
5964 # i18n: column positioning for "hg summary"
5963 ui.status(_('remote: (synced)\n'))
5965 ui.status(_('remote: (synced)\n'))
5964
5966
5965 cmdutil.summaryremotehooks(ui, repo, opts,
5967 cmdutil.summaryremotehooks(ui, repo, opts,
5966 ((source, sbranch, sother, commoninc),
5968 ((source, sbranch, sother, commoninc),
5967 (dest, dbranch, dother, outgoing)))
5969 (dest, dbranch, dother, outgoing)))
5968
5970
5969 @command('tag',
5971 @command('tag',
5970 [('f', 'force', None, _('force tag')),
5972 [('f', 'force', None, _('force tag')),
5971 ('l', 'local', None, _('make the tag local')),
5973 ('l', 'local', None, _('make the tag local')),
5972 ('r', 'rev', '', _('revision to tag'), _('REV')),
5974 ('r', 'rev', '', _('revision to tag'), _('REV')),
5973 ('', 'remove', None, _('remove a tag')),
5975 ('', 'remove', None, _('remove a tag')),
5974 # -l/--local is already there, commitopts cannot be used
5976 # -l/--local is already there, commitopts cannot be used
5975 ('e', 'edit', None, _('invoke editor on commit messages')),
5977 ('e', 'edit', None, _('invoke editor on commit messages')),
5976 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5978 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5977 ] + commitopts2,
5979 ] + commitopts2,
5978 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5980 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5979 def tag(ui, repo, name1, *names, **opts):
5981 def tag(ui, repo, name1, *names, **opts):
5980 """add one or more tags for the current or given revision
5982 """add one or more tags for the current or given revision
5981
5983
5982 Name a particular revision using <name>.
5984 Name a particular revision using <name>.
5983
5985
5984 Tags are used to name particular revisions of the repository and are
5986 Tags are used to name particular revisions of the repository and are
5985 very useful to compare different revisions, to go back to significant
5987 very useful to compare different revisions, to go back to significant
5986 earlier versions or to mark branch points as releases, etc. Changing
5988 earlier versions or to mark branch points as releases, etc. Changing
5987 an existing tag is normally disallowed; use -f/--force to override.
5989 an existing tag is normally disallowed; use -f/--force to override.
5988
5990
5989 If no revision is given, the parent of the working directory is
5991 If no revision is given, the parent of the working directory is
5990 used.
5992 used.
5991
5993
5992 To facilitate version control, distribution, and merging of tags,
5994 To facilitate version control, distribution, and merging of tags,
5993 they are stored as a file named ".hgtags" which is managed similarly
5995 they are stored as a file named ".hgtags" which is managed similarly
5994 to other project files and can be hand-edited if necessary. This
5996 to other project files and can be hand-edited if necessary. This
5995 also means that tagging creates a new commit. The file
5997 also means that tagging creates a new commit. The file
5996 ".hg/localtags" is used for local tags (not shared among
5998 ".hg/localtags" is used for local tags (not shared among
5997 repositories).
5999 repositories).
5998
6000
5999 Tag commits are usually made at the head of a branch. If the parent
6001 Tag commits are usually made at the head of a branch. If the parent
6000 of the working directory is not a branch head, :hg:`tag` aborts; use
6002 of the working directory is not a branch head, :hg:`tag` aborts; use
6001 -f/--force to force the tag commit to be based on a non-head
6003 -f/--force to force the tag commit to be based on a non-head
6002 changeset.
6004 changeset.
6003
6005
6004 See :hg:`help dates` for a list of formats valid for -d/--date.
6006 See :hg:`help dates` for a list of formats valid for -d/--date.
6005
6007
6006 Since tag names have priority over branch names during revision
6008 Since tag names have priority over branch names during revision
6007 lookup, using an existing branch name as a tag name is discouraged.
6009 lookup, using an existing branch name as a tag name is discouraged.
6008
6010
6009 Returns 0 on success.
6011 Returns 0 on success.
6010 """
6012 """
6011 wlock = lock = None
6013 wlock = lock = None
6012 try:
6014 try:
6013 wlock = repo.wlock()
6015 wlock = repo.wlock()
6014 lock = repo.lock()
6016 lock = repo.lock()
6015 rev_ = "."
6017 rev_ = "."
6016 names = [t.strip() for t in (name1,) + names]
6018 names = [t.strip() for t in (name1,) + names]
6017 if len(names) != len(set(names)):
6019 if len(names) != len(set(names)):
6018 raise util.Abort(_('tag names must be unique'))
6020 raise util.Abort(_('tag names must be unique'))
6019 for n in names:
6021 for n in names:
6020 scmutil.checknewlabel(repo, n, 'tag')
6022 scmutil.checknewlabel(repo, n, 'tag')
6021 if not n:
6023 if not n:
6022 raise util.Abort(_('tag names cannot consist entirely of '
6024 raise util.Abort(_('tag names cannot consist entirely of '
6023 'whitespace'))
6025 'whitespace'))
6024 if opts.get('rev') and opts.get('remove'):
6026 if opts.get('rev') and opts.get('remove'):
6025 raise util.Abort(_("--rev and --remove are incompatible"))
6027 raise util.Abort(_("--rev and --remove are incompatible"))
6026 if opts.get('rev'):
6028 if opts.get('rev'):
6027 rev_ = opts['rev']
6029 rev_ = opts['rev']
6028 message = opts.get('message')
6030 message = opts.get('message')
6029 if opts.get('remove'):
6031 if opts.get('remove'):
6030 expectedtype = opts.get('local') and 'local' or 'global'
6032 expectedtype = opts.get('local') and 'local' or 'global'
6031 for n in names:
6033 for n in names:
6032 if not repo.tagtype(n):
6034 if not repo.tagtype(n):
6033 raise util.Abort(_("tag '%s' does not exist") % n)
6035 raise util.Abort(_("tag '%s' does not exist") % n)
6034 if repo.tagtype(n) != expectedtype:
6036 if repo.tagtype(n) != expectedtype:
6035 if expectedtype == 'global':
6037 if expectedtype == 'global':
6036 raise util.Abort(_("tag '%s' is not a global tag") % n)
6038 raise util.Abort(_("tag '%s' is not a global tag") % n)
6037 else:
6039 else:
6038 raise util.Abort(_("tag '%s' is not a local tag") % n)
6040 raise util.Abort(_("tag '%s' is not a local tag") % n)
6039 rev_ = nullid
6041 rev_ = nullid
6040 if not message:
6042 if not message:
6041 # we don't translate commit messages
6043 # we don't translate commit messages
6042 message = 'Removed tag %s' % ', '.join(names)
6044 message = 'Removed tag %s' % ', '.join(names)
6043 elif not opts.get('force'):
6045 elif not opts.get('force'):
6044 for n in names:
6046 for n in names:
6045 if n in repo.tags():
6047 if n in repo.tags():
6046 raise util.Abort(_("tag '%s' already exists "
6048 raise util.Abort(_("tag '%s' already exists "
6047 "(use -f to force)") % n)
6049 "(use -f to force)") % n)
6048 if not opts.get('local'):
6050 if not opts.get('local'):
6049 p1, p2 = repo.dirstate.parents()
6051 p1, p2 = repo.dirstate.parents()
6050 if p2 != nullid:
6052 if p2 != nullid:
6051 raise util.Abort(_('uncommitted merge'))
6053 raise util.Abort(_('uncommitted merge'))
6052 bheads = repo.branchheads()
6054 bheads = repo.branchheads()
6053 if not opts.get('force') and bheads and p1 not in bheads:
6055 if not opts.get('force') and bheads and p1 not in bheads:
6054 raise util.Abort(_('not at a branch head (use -f to force)'))
6056 raise util.Abort(_('not at a branch head (use -f to force)'))
6055 r = scmutil.revsingle(repo, rev_).node()
6057 r = scmutil.revsingle(repo, rev_).node()
6056
6058
6057 if not message:
6059 if not message:
6058 # we don't translate commit messages
6060 # we don't translate commit messages
6059 message = ('Added tag %s for changeset %s' %
6061 message = ('Added tag %s for changeset %s' %
6060 (', '.join(names), short(r)))
6062 (', '.join(names), short(r)))
6061
6063
6062 date = opts.get('date')
6064 date = opts.get('date')
6063 if date:
6065 if date:
6064 date = util.parsedate(date)
6066 date = util.parsedate(date)
6065
6067
6066 if opts.get('remove'):
6068 if opts.get('remove'):
6067 editform = 'tag.remove'
6069 editform = 'tag.remove'
6068 else:
6070 else:
6069 editform = 'tag.add'
6071 editform = 'tag.add'
6070 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6072 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6071
6073
6072 # don't allow tagging the null rev
6074 # don't allow tagging the null rev
6073 if (not opts.get('remove') and
6075 if (not opts.get('remove') and
6074 scmutil.revsingle(repo, rev_).rev() == nullrev):
6076 scmutil.revsingle(repo, rev_).rev() == nullrev):
6075 raise util.Abort(_("cannot tag null revision"))
6077 raise util.Abort(_("cannot tag null revision"))
6076
6078
6077 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6079 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6078 editor=editor)
6080 editor=editor)
6079 finally:
6081 finally:
6080 release(lock, wlock)
6082 release(lock, wlock)
6081
6083
6082 @command('tags', formatteropts, '')
6084 @command('tags', formatteropts, '')
6083 def tags(ui, repo, **opts):
6085 def tags(ui, repo, **opts):
6084 """list repository tags
6086 """list repository tags
6085
6087
6086 This lists both regular and local tags. When the -v/--verbose
6088 This lists both regular and local tags. When the -v/--verbose
6087 switch is used, a third column "local" is printed for local tags.
6089 switch is used, a third column "local" is printed for local tags.
6088
6090
6089 Returns 0 on success.
6091 Returns 0 on success.
6090 """
6092 """
6091
6093
6092 fm = ui.formatter('tags', opts)
6094 fm = ui.formatter('tags', opts)
6093 hexfunc = fm.hexfunc
6095 hexfunc = fm.hexfunc
6094 tagtype = ""
6096 tagtype = ""
6095
6097
6096 for t, n in reversed(repo.tagslist()):
6098 for t, n in reversed(repo.tagslist()):
6097 hn = hexfunc(n)
6099 hn = hexfunc(n)
6098 label = 'tags.normal'
6100 label = 'tags.normal'
6099 tagtype = ''
6101 tagtype = ''
6100 if repo.tagtype(t) == 'local':
6102 if repo.tagtype(t) == 'local':
6101 label = 'tags.local'
6103 label = 'tags.local'
6102 tagtype = 'local'
6104 tagtype = 'local'
6103
6105
6104 fm.startitem()
6106 fm.startitem()
6105 fm.write('tag', '%s', t, label=label)
6107 fm.write('tag', '%s', t, label=label)
6106 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6108 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6107 fm.condwrite(not ui.quiet, 'rev node', fmt,
6109 fm.condwrite(not ui.quiet, 'rev node', fmt,
6108 repo.changelog.rev(n), hn, label=label)
6110 repo.changelog.rev(n), hn, label=label)
6109 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6111 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6110 tagtype, label=label)
6112 tagtype, label=label)
6111 fm.plain('\n')
6113 fm.plain('\n')
6112 fm.end()
6114 fm.end()
6113
6115
6114 @command('tip',
6116 @command('tip',
6115 [('p', 'patch', None, _('show patch')),
6117 [('p', 'patch', None, _('show patch')),
6116 ('g', 'git', None, _('use git extended diff format')),
6118 ('g', 'git', None, _('use git extended diff format')),
6117 ] + templateopts,
6119 ] + templateopts,
6118 _('[-p] [-g]'))
6120 _('[-p] [-g]'))
6119 def tip(ui, repo, **opts):
6121 def tip(ui, repo, **opts):
6120 """show the tip revision (DEPRECATED)
6122 """show the tip revision (DEPRECATED)
6121
6123
6122 The tip revision (usually just called the tip) is the changeset
6124 The tip revision (usually just called the tip) is the changeset
6123 most recently added to the repository (and therefore the most
6125 most recently added to the repository (and therefore the most
6124 recently changed head).
6126 recently changed head).
6125
6127
6126 If you have just made a commit, that commit will be the tip. If
6128 If you have just made a commit, that commit will be the tip. If
6127 you have just pulled changes from another repository, the tip of
6129 you have just pulled changes from another repository, the tip of
6128 that repository becomes the current tip. The "tip" tag is special
6130 that repository becomes the current tip. The "tip" tag is special
6129 and cannot be renamed or assigned to a different changeset.
6131 and cannot be renamed or assigned to a different changeset.
6130
6132
6131 This command is deprecated, please use :hg:`heads` instead.
6133 This command is deprecated, please use :hg:`heads` instead.
6132
6134
6133 Returns 0 on success.
6135 Returns 0 on success.
6134 """
6136 """
6135 displayer = cmdutil.show_changeset(ui, repo, opts)
6137 displayer = cmdutil.show_changeset(ui, repo, opts)
6136 displayer.show(repo['tip'])
6138 displayer.show(repo['tip'])
6137 displayer.close()
6139 displayer.close()
6138
6140
6139 @command('unbundle',
6141 @command('unbundle',
6140 [('u', 'update', None,
6142 [('u', 'update', None,
6141 _('update to new branch head if changesets were unbundled'))],
6143 _('update to new branch head if changesets were unbundled'))],
6142 _('[-u] FILE...'))
6144 _('[-u] FILE...'))
6143 def unbundle(ui, repo, fname1, *fnames, **opts):
6145 def unbundle(ui, repo, fname1, *fnames, **opts):
6144 """apply one or more changegroup files
6146 """apply one or more changegroup files
6145
6147
6146 Apply one or more compressed changegroup files generated by the
6148 Apply one or more compressed changegroup files generated by the
6147 bundle command.
6149 bundle command.
6148
6150
6149 Returns 0 on success, 1 if an update has unresolved files.
6151 Returns 0 on success, 1 if an update has unresolved files.
6150 """
6152 """
6151 fnames = (fname1,) + fnames
6153 fnames = (fname1,) + fnames
6152
6154
6153 lock = repo.lock()
6155 lock = repo.lock()
6154 try:
6156 try:
6155 for fname in fnames:
6157 for fname in fnames:
6156 f = hg.openpath(ui, fname)
6158 f = hg.openpath(ui, fname)
6157 gen = exchange.readbundle(ui, f, fname)
6159 gen = exchange.readbundle(ui, f, fname)
6158 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6160 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6159 'bundle:' + fname)
6161 'bundle:' + fname)
6160 finally:
6162 finally:
6161 lock.release()
6163 lock.release()
6162
6164
6163 return postincoming(ui, repo, modheads, opts.get('update'), None)
6165 return postincoming(ui, repo, modheads, opts.get('update'), None)
6164
6166
6165 @command('^update|up|checkout|co',
6167 @command('^update|up|checkout|co',
6166 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6168 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6167 ('c', 'check', None,
6169 ('c', 'check', None,
6168 _('update across branches if no uncommitted changes')),
6170 _('update across branches if no uncommitted changes')),
6169 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6171 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6170 ('r', 'rev', '', _('revision'), _('REV'))
6172 ('r', 'rev', '', _('revision'), _('REV'))
6171 ] + mergetoolopts,
6173 ] + mergetoolopts,
6172 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6174 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6173 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6175 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6174 tool=None):
6176 tool=None):
6175 """update working directory (or switch revisions)
6177 """update working directory (or switch revisions)
6176
6178
6177 Update the repository's working directory to the specified
6179 Update the repository's working directory to the specified
6178 changeset. If no changeset is specified, update to the tip of the
6180 changeset. If no changeset is specified, update to the tip of the
6179 current named branch and move the current bookmark (see :hg:`help
6181 current named branch and move the current bookmark (see :hg:`help
6180 bookmarks`).
6182 bookmarks`).
6181
6183
6182 Update sets the working directory's parent revision to the specified
6184 Update sets the working directory's parent revision to the specified
6183 changeset (see :hg:`help parents`).
6185 changeset (see :hg:`help parents`).
6184
6186
6185 If the changeset is not a descendant or ancestor of the working
6187 If the changeset is not a descendant or ancestor of the working
6186 directory's parent, the update is aborted. With the -c/--check
6188 directory's parent, the update is aborted. With the -c/--check
6187 option, the working directory is checked for uncommitted changes; if
6189 option, the working directory is checked for uncommitted changes; if
6188 none are found, the working directory is updated to the specified
6190 none are found, the working directory is updated to the specified
6189 changeset.
6191 changeset.
6190
6192
6191 .. container:: verbose
6193 .. container:: verbose
6192
6194
6193 The following rules apply when the working directory contains
6195 The following rules apply when the working directory contains
6194 uncommitted changes:
6196 uncommitted changes:
6195
6197
6196 1. If neither -c/--check nor -C/--clean is specified, and if
6198 1. If neither -c/--check nor -C/--clean is specified, and if
6197 the requested changeset is an ancestor or descendant of
6199 the requested changeset is an ancestor or descendant of
6198 the working directory's parent, the uncommitted changes
6200 the working directory's parent, the uncommitted changes
6199 are merged into the requested changeset and the merged
6201 are merged into the requested changeset and the merged
6200 result is left uncommitted. If the requested changeset is
6202 result is left uncommitted. If the requested changeset is
6201 not an ancestor or descendant (that is, it is on another
6203 not an ancestor or descendant (that is, it is on another
6202 branch), the update is aborted and the uncommitted changes
6204 branch), the update is aborted and the uncommitted changes
6203 are preserved.
6205 are preserved.
6204
6206
6205 2. With the -c/--check option, the update is aborted and the
6207 2. With the -c/--check option, the update is aborted and the
6206 uncommitted changes are preserved.
6208 uncommitted changes are preserved.
6207
6209
6208 3. With the -C/--clean option, uncommitted changes are discarded and
6210 3. With the -C/--clean option, uncommitted changes are discarded and
6209 the working directory is updated to the requested changeset.
6211 the working directory is updated to the requested changeset.
6210
6212
6211 To cancel an uncommitted merge (and lose your changes), use
6213 To cancel an uncommitted merge (and lose your changes), use
6212 :hg:`update --clean .`.
6214 :hg:`update --clean .`.
6213
6215
6214 Use null as the changeset to remove the working directory (like
6216 Use null as the changeset to remove the working directory (like
6215 :hg:`clone -U`).
6217 :hg:`clone -U`).
6216
6218
6217 If you want to revert just one file to an older revision, use
6219 If you want to revert just one file to an older revision, use
6218 :hg:`revert [-r REV] NAME`.
6220 :hg:`revert [-r REV] NAME`.
6219
6221
6220 See :hg:`help dates` for a list of formats valid for -d/--date.
6222 See :hg:`help dates` for a list of formats valid for -d/--date.
6221
6223
6222 Returns 0 on success, 1 if there are unresolved files.
6224 Returns 0 on success, 1 if there are unresolved files.
6223 """
6225 """
6224 if rev and node:
6226 if rev and node:
6225 raise util.Abort(_("please specify just one revision"))
6227 raise util.Abort(_("please specify just one revision"))
6226
6228
6227 if rev is None or rev == '':
6229 if rev is None or rev == '':
6228 rev = node
6230 rev = node
6229
6231
6230 cmdutil.clearunfinished(repo)
6232 cmdutil.clearunfinished(repo)
6231
6233
6232 # with no argument, we also move the current bookmark, if any
6234 # with no argument, we also move the current bookmark, if any
6233 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6235 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6234
6236
6235 # if we defined a bookmark, we have to remember the original bookmark name
6237 # if we defined a bookmark, we have to remember the original bookmark name
6236 brev = rev
6238 brev = rev
6237 rev = scmutil.revsingle(repo, rev, rev).rev()
6239 rev = scmutil.revsingle(repo, rev, rev).rev()
6238
6240
6239 if check and clean:
6241 if check and clean:
6240 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6242 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6241
6243
6242 if date:
6244 if date:
6243 if rev is not None:
6245 if rev is not None:
6244 raise util.Abort(_("you can't specify a revision and a date"))
6246 raise util.Abort(_("you can't specify a revision and a date"))
6245 rev = cmdutil.finddate(ui, repo, date)
6247 rev = cmdutil.finddate(ui, repo, date)
6246
6248
6247 if check:
6249 if check:
6248 c = repo[None]
6250 c = repo[None]
6249 if c.dirty(merge=False, branch=False, missing=True):
6251 if c.dirty(merge=False, branch=False, missing=True):
6250 raise util.Abort(_("uncommitted changes"))
6252 raise util.Abort(_("uncommitted changes"))
6251 if rev is None:
6253 if rev is None:
6252 rev = repo[repo[None].branch()].rev()
6254 rev = repo[repo[None].branch()].rev()
6253 mergemod._checkunknown(repo, repo[None], repo[rev])
6255 mergemod._checkunknown(repo, repo[None], repo[rev])
6254
6256
6255 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6257 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6256
6258
6257 if clean:
6259 if clean:
6258 ret = hg.clean(repo, rev)
6260 ret = hg.clean(repo, rev)
6259 else:
6261 else:
6260 ret = hg.update(repo, rev)
6262 ret = hg.update(repo, rev)
6261
6263
6262 if not ret and movemarkfrom:
6264 if not ret and movemarkfrom:
6263 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6265 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6264 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6266 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6265 elif brev in repo._bookmarks:
6267 elif brev in repo._bookmarks:
6266 bookmarks.setcurrent(repo, brev)
6268 bookmarks.setcurrent(repo, brev)
6267 ui.status(_("(activating bookmark %s)\n") % brev)
6269 ui.status(_("(activating bookmark %s)\n") % brev)
6268 elif brev:
6270 elif brev:
6269 if repo._bookmarkcurrent:
6271 if repo._bookmarkcurrent:
6270 ui.status(_("(leaving bookmark %s)\n") %
6272 ui.status(_("(leaving bookmark %s)\n") %
6271 repo._bookmarkcurrent)
6273 repo._bookmarkcurrent)
6272 bookmarks.unsetcurrent(repo)
6274 bookmarks.unsetcurrent(repo)
6273
6275
6274 return ret
6276 return ret
6275
6277
6276 @command('verify', [])
6278 @command('verify', [])
6277 def verify(ui, repo):
6279 def verify(ui, repo):
6278 """verify the integrity of the repository
6280 """verify the integrity of the repository
6279
6281
6280 Verify the integrity of the current repository.
6282 Verify the integrity of the current repository.
6281
6283
6282 This will perform an extensive check of the repository's
6284 This will perform an extensive check of the repository's
6283 integrity, validating the hashes and checksums of each entry in
6285 integrity, validating the hashes and checksums of each entry in
6284 the changelog, manifest, and tracked files, as well as the
6286 the changelog, manifest, and tracked files, as well as the
6285 integrity of their crosslinks and indices.
6287 integrity of their crosslinks and indices.
6286
6288
6287 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6289 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6288 for more information about recovery from corruption of the
6290 for more information about recovery from corruption of the
6289 repository.
6291 repository.
6290
6292
6291 Returns 0 on success, 1 if errors are encountered.
6293 Returns 0 on success, 1 if errors are encountered.
6292 """
6294 """
6293 return hg.verify(repo)
6295 return hg.verify(repo)
6294
6296
6295 @command('version', [], norepo=True)
6297 @command('version', [], norepo=True)
6296 def version_(ui):
6298 def version_(ui):
6297 """output version and copyright information"""
6299 """output version and copyright information"""
6298 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6300 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6299 % util.version())
6301 % util.version())
6300 ui.status(_(
6302 ui.status(_(
6301 "(see http://mercurial.selenic.com for more information)\n"
6303 "(see http://mercurial.selenic.com for more information)\n"
6302 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6304 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6303 "This is free software; see the source for copying conditions. "
6305 "This is free software; see the source for copying conditions. "
6304 "There is NO\nwarranty; "
6306 "There is NO\nwarranty; "
6305 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6307 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6306 ))
6308 ))
6307
6309
6308 ui.note(_("\nEnabled extensions:\n\n"))
6310 ui.note(_("\nEnabled extensions:\n\n"))
6309 if ui.verbose:
6311 if ui.verbose:
6310 # format names and versions into columns
6312 # format names and versions into columns
6311 names = []
6313 names = []
6312 vers = []
6314 vers = []
6313 for name, module in extensions.extensions():
6315 for name, module in extensions.extensions():
6314 names.append(name)
6316 names.append(name)
6315 vers.append(extensions.moduleversion(module))
6317 vers.append(extensions.moduleversion(module))
6316 if names:
6318 if names:
6317 maxnamelen = max(len(n) for n in names)
6319 maxnamelen = max(len(n) for n in names)
6318 for i, name in enumerate(names):
6320 for i, name in enumerate(names):
6319 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6321 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,195 +1,195 b''
1 $ hg init
1 $ hg init
2
2
3 no bookmarks
3 no bookmarks
4
4
5 $ hg bookmarks
5 $ hg bookmarks
6 no bookmarks set
6 no bookmarks set
7
7
8 set bookmark X
8 set bookmark X
9
9
10 $ hg bookmark X
10 $ hg bookmark X
11
11
12 list bookmarks
12 list bookmarks
13
13
14 $ hg bookmark
14 $ hg bookmark
15 * X -1:000000000000
15 * X -1:000000000000
16
16
17 list bookmarks with color
17 list bookmarks with color
18
18
19 $ hg --config extensions.color= --config color.mode=ansi \
19 $ hg --config extensions.color= --config color.mode=ansi \
20 > bookmark --color=always
20 > bookmark --color=always
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
21 \x1b[0;32m * \x1b[0m\x1b[0;32mX\x1b[0m\x1b[0;32m -1:000000000000\x1b[0m (esc)
22
22
23 update to bookmark X
23 update to bookmark X
24
24
25 $ hg update X
25 $ hg update X
26 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
26 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
27 (activating bookmark X)
27 (activating bookmark X)
28
28
29 list bookmarks
29 list bookmarks
30
30
31 $ hg bookmarks
31 $ hg bookmarks
32 * X -1:000000000000
32 * X -1:000000000000
33
33
34 rename
34 rename
35
35
36 $ hg bookmark -m X Z
36 $ hg bookmark -m X Z
37
37
38 list bookmarks
38 list bookmarks
39
39
40 $ cat .hg/bookmarks.current
40 $ cat .hg/bookmarks.current
41 Z (no-eol)
41 Z (no-eol)
42 $ cat .hg/bookmarks
42 $ cat .hg/bookmarks
43 0000000000000000000000000000000000000000 Z
43 0000000000000000000000000000000000000000 Z
44 $ hg bookmarks
44 $ hg bookmarks
45 * Z -1:000000000000
45 * Z -1:000000000000
46
46
47 new bookmarks X and Y, first one made active
47 new bookmarks X and Y, first one made active
48
48
49 $ hg bookmark Y X
49 $ hg bookmark Y X
50
50
51 list bookmarks
51 list bookmarks
52
52
53 $ hg bookmark
53 $ hg bookmark
54 X -1:000000000000
54 X -1:000000000000
55 * Y -1:000000000000
55 * Y -1:000000000000
56 Z -1:000000000000
56 Z -1:000000000000
57
57
58 $ hg bookmark -d X
58 $ hg bookmark -d X
59
59
60 commit
60 commit
61
61
62 $ echo 'b' > b
62 $ echo 'b' > b
63 $ hg add b
63 $ hg add b
64 $ hg commit -m'test'
64 $ hg commit -m'test'
65
65
66 list bookmarks
66 list bookmarks
67
67
68 $ hg bookmark
68 $ hg bookmark
69 * Y 0:719295282060
69 * Y 0:719295282060
70 Z -1:000000000000
70 Z -1:000000000000
71
71
72 Verify that switching to Z updates the current bookmark:
72 Verify that switching to Z updates the current bookmark:
73 $ hg update Z
73 $ hg update Z
74 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
74 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
75 (activating bookmark Z)
75 (activating bookmark Z)
76 $ hg bookmark
76 $ hg bookmark
77 Y 0:719295282060
77 Y 0:719295282060
78 * Z -1:000000000000
78 * Z -1:000000000000
79
79
80 Switch back to Y for the remaining tests in this file:
80 Switch back to Y for the remaining tests in this file:
81 $ hg update Y
81 $ hg update Y
82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
82 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
83 (activating bookmark Y)
83 (activating bookmark Y)
84
84
85 delete bookmarks
85 delete bookmarks
86
86
87 $ hg bookmark -d Y
87 $ hg bookmark -d Y
88 $ hg bookmark -d Z
88 $ hg bookmark -d Z
89
89
90 list bookmarks
90 list bookmarks
91
91
92 $ hg bookmark
92 $ hg bookmark
93 no bookmarks set
93 no bookmarks set
94
94
95 update to tip
95 update to tip
96
96
97 $ hg update tip
97 $ hg update tip
98 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
98 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
99
99
100 set bookmark Y using -r . but make sure that the active
100 set bookmark Y using -r . but make sure that the active
101 bookmark is not activated
101 bookmark is not activated
102
102
103 $ hg bookmark -r . Y
103 $ hg bookmark -r . Y
104
104
105 list bookmarks, Y should not be active
105 list bookmarks, Y should not be active
106
106
107 $ hg bookmark
107 $ hg bookmark
108 Y 0:719295282060
108 Y 0:719295282060
109
109
110 now, activate Y
110 now, activate Y
111
111
112 $ hg up -q Y
112 $ hg up -q Y
113
113
114 set bookmark Z using -i
114 set bookmark Z using -i
115
115
116 $ hg bookmark -r . -i Z
116 $ hg bookmark -r . -i Z
117 $ hg bookmarks
117 $ hg bookmarks
118 * Y 0:719295282060
118 * Y 0:719295282060
119 Z 0:719295282060
119 Z 0:719295282060
120
120
121 deactivate current bookmark using -i
121 deactivate current bookmark using -i
122
122
123 $ hg bookmark -i Y
123 $ hg bookmark -i Y
124 $ hg bookmarks
124 $ hg bookmarks
125 Y 0:719295282060
125 Y 0:719295282060
126 Z 0:719295282060
126 Z 0:719295282060
127
127
128 $ hg up -q Y
128 $ hg up -q Y
129 $ hg bookmark -i
129 $ hg bookmark -i
130 $ hg bookmarks
130 $ hg bookmarks
131 Y 0:719295282060
131 Y 0:719295282060
132 Z 0:719295282060
132 Z 0:719295282060
133 $ hg bookmark -i
133 $ hg bookmark -i
134 no active bookmark
134 no active bookmark
135 $ hg up -q Y
135 $ hg up -q Y
136 $ hg bookmarks
136 $ hg bookmarks
137 * Y 0:719295282060
137 * Y 0:719295282060
138 Z 0:719295282060
138 Z 0:719295282060
139
139
140 deactivate current bookmark while renaming
140 deactivate current bookmark while renaming
141
141
142 $ hg bookmark -i -m Y X
142 $ hg bookmark -i -m Y X
143 $ hg bookmarks
143 $ hg bookmarks
144 X 0:719295282060
144 X 0:719295282060
145 Z 0:719295282060
145 Z 0:719295282060
146
146
147 bare update moves the active bookmark forward and clear the divergent bookmarks
147 bare update moves the active bookmark forward and clear the divergent bookmarks
148
148
149 $ echo a > a
149 $ echo a > a
150 $ hg ci -Am1
150 $ hg ci -Am1
151 adding a
151 adding a
152 $ echo b >> a
152 $ echo b >> a
153 $ hg ci -Am2
153 $ hg ci -Am2
154 $ hg bookmark X@1 -r 1
154 $ hg bookmark X@1 -r 1
155 $ hg bookmark X@2 -r 2
155 $ hg bookmark X@2 -r 2
156 $ hg update X
156 $ hg update X
157 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
157 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
158 (activating bookmark X)
158 (activating bookmark X)
159 $ hg bookmarks
159 $ hg bookmarks
160 * X 0:719295282060
160 * X 0:719295282060
161 X@1 1:cc586d725fbe
161 X@1 1:cc586d725fbe
162 X@2 2:49e1c4e84c58
162 X@2 2:49e1c4e84c58
163 Z 0:719295282060
163 Z 0:719295282060
164 $ hg update
164 $ hg update
165 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
165 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
166 updating bookmark X
166 updating bookmark X
167 $ hg bookmarks
167 $ hg bookmarks
168 * X 2:49e1c4e84c58
168 * X 2:49e1c4e84c58
169 Z 0:719295282060
169 Z 0:719295282060
170
170
171 test deleting .hg/bookmarks.current when explicitly updating
171 test deleting .hg/bookmarks.current when explicitly updating
172 to a revision
172 to a revision
173
173
174 $ echo a >> b
174 $ echo a >> b
175 $ hg ci -m.
175 $ hg ci -m.
176 $ hg up -q X
176 $ hg up -q X
177 $ test -f .hg/bookmarks.current
177 $ test -f .hg/bookmarks.current
178
178
179 try to update to it again to make sure we don't
179 try to update to it again to make sure we don't
180 set and then unset it
180 set and then unset it
181
181
182 $ hg up -q X
182 $ hg up -q X
183 $ test -f .hg/bookmarks.current
183 $ test -f .hg/bookmarks.current
184
184
185 $ hg up -q 1
185 $ hg up -q 1
186 $ test -f .hg/bookmarks.current
186 $ test -f .hg/bookmarks.current
187 [1]
187 [1]
188
188
189 when a bookmark is active, hg up -r . is
189 when a bookmark is active, hg up -r . is
190 analogous to hg book -i <active bookmark>
190 analogous to hg book -i <active bookmark>
191
191
192 $ hg up -q X
192 $ hg up -q X
193 $ hg up -q .
193 $ hg up -q .
194 $ test -f .hg/bookmarks.current
194 $ test -f .hg/bookmarks.current
195 [1]
195 [1]
@@ -1,663 +1,663 b''
1 $ hg init
1 $ hg init
2
2
3 no bookmarks
3 no bookmarks
4
4
5 $ hg bookmarks
5 $ hg bookmarks
6 no bookmarks set
6 no bookmarks set
7
7
8 bookmark rev -1
8 bookmark rev -1
9
9
10 $ hg bookmark X
10 $ hg bookmark X
11
11
12 list bookmarks
12 list bookmarks
13
13
14 $ hg bookmarks
14 $ hg bookmarks
15 * X -1:000000000000
15 * X -1:000000000000
16
16
17 list bookmarks with color
17 list bookmarks with color
18
18
19 $ hg --config extensions.color= --config color.mode=ansi \
19 $ hg --config extensions.color= --config color.mode=ansi \
20 > bookmarks --color=always
20 > bookmarks --color=always
21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
21 \x1b[0;32m * \x1b[0m\x1b[0;32mX\x1b[0m\x1b[0;32m -1:000000000000\x1b[0m (esc)
22
22
23 $ echo a > a
23 $ echo a > a
24 $ hg add a
24 $ hg add a
25 $ hg commit -m 0
25 $ hg commit -m 0
26
26
27 bookmark X moved to rev 0
27 bookmark X moved to rev 0
28
28
29 $ hg bookmarks
29 $ hg bookmarks
30 * X 0:f7b1eb17ad24
30 * X 0:f7b1eb17ad24
31
31
32 look up bookmark
32 look up bookmark
33
33
34 $ hg log -r X
34 $ hg log -r X
35 changeset: 0:f7b1eb17ad24
35 changeset: 0:f7b1eb17ad24
36 bookmark: X
36 bookmark: X
37 tag: tip
37 tag: tip
38 user: test
38 user: test
39 date: Thu Jan 01 00:00:00 1970 +0000
39 date: Thu Jan 01 00:00:00 1970 +0000
40 summary: 0
40 summary: 0
41
41
42
42
43 second bookmark for rev 0, command should work even with ui.strict on
43 second bookmark for rev 0, command should work even with ui.strict on
44
44
45 $ hg --config ui.strict=1 bookmark X2
45 $ hg --config ui.strict=1 bookmark X2
46
46
47 bookmark rev -1 again
47 bookmark rev -1 again
48
48
49 $ hg bookmark -r null Y
49 $ hg bookmark -r null Y
50
50
51 list bookmarks
51 list bookmarks
52
52
53 $ hg bookmarks
53 $ hg bookmarks
54 X 0:f7b1eb17ad24
54 X 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
55 * X2 0:f7b1eb17ad24
56 Y -1:000000000000
56 Y -1:000000000000
57
57
58 $ echo b > b
58 $ echo b > b
59 $ hg add b
59 $ hg add b
60 $ hg commit -m 1
60 $ hg commit -m 1
61
61
62 bookmarks revset
62 bookmarks revset
63
63
64 $ hg log -r 'bookmark()'
64 $ hg log -r 'bookmark()'
65 changeset: 0:f7b1eb17ad24
65 changeset: 0:f7b1eb17ad24
66 bookmark: X
66 bookmark: X
67 user: test
67 user: test
68 date: Thu Jan 01 00:00:00 1970 +0000
68 date: Thu Jan 01 00:00:00 1970 +0000
69 summary: 0
69 summary: 0
70
70
71 changeset: 1:925d80f479bb
71 changeset: 1:925d80f479bb
72 bookmark: X2
72 bookmark: X2
73 tag: tip
73 tag: tip
74 user: test
74 user: test
75 date: Thu Jan 01 00:00:00 1970 +0000
75 date: Thu Jan 01 00:00:00 1970 +0000
76 summary: 1
76 summary: 1
77
77
78 $ hg log -r 'bookmark(Y)'
78 $ hg log -r 'bookmark(Y)'
79 $ hg log -r 'bookmark(X2)'
79 $ hg log -r 'bookmark(X2)'
80 changeset: 1:925d80f479bb
80 changeset: 1:925d80f479bb
81 bookmark: X2
81 bookmark: X2
82 tag: tip
82 tag: tip
83 user: test
83 user: test
84 date: Thu Jan 01 00:00:00 1970 +0000
84 date: Thu Jan 01 00:00:00 1970 +0000
85 summary: 1
85 summary: 1
86
86
87 $ hg log -r 'bookmark("re:X")'
87 $ hg log -r 'bookmark("re:X")'
88 changeset: 0:f7b1eb17ad24
88 changeset: 0:f7b1eb17ad24
89 bookmark: X
89 bookmark: X
90 user: test
90 user: test
91 date: Thu Jan 01 00:00:00 1970 +0000
91 date: Thu Jan 01 00:00:00 1970 +0000
92 summary: 0
92 summary: 0
93
93
94 changeset: 1:925d80f479bb
94 changeset: 1:925d80f479bb
95 bookmark: X2
95 bookmark: X2
96 tag: tip
96 tag: tip
97 user: test
97 user: test
98 date: Thu Jan 01 00:00:00 1970 +0000
98 date: Thu Jan 01 00:00:00 1970 +0000
99 summary: 1
99 summary: 1
100
100
101 $ hg log -r 'bookmark("literal:X")'
101 $ hg log -r 'bookmark("literal:X")'
102 changeset: 0:f7b1eb17ad24
102 changeset: 0:f7b1eb17ad24
103 bookmark: X
103 bookmark: X
104 user: test
104 user: test
105 date: Thu Jan 01 00:00:00 1970 +0000
105 date: Thu Jan 01 00:00:00 1970 +0000
106 summary: 0
106 summary: 0
107
107
108
108
109 $ hg log -r 'bookmark(unknown)'
109 $ hg log -r 'bookmark(unknown)'
110 abort: bookmark 'unknown' does not exist
110 abort: bookmark 'unknown' does not exist
111 [255]
111 [255]
112
112
113 $ hg help revsets | grep 'bookmark('
113 $ hg help revsets | grep 'bookmark('
114 "bookmark([name])"
114 "bookmark([name])"
115
115
116 bookmarks X and X2 moved to rev 1, Y at rev -1
116 bookmarks X and X2 moved to rev 1, Y at rev -1
117
117
118 $ hg bookmarks
118 $ hg bookmarks
119 X 0:f7b1eb17ad24
119 X 0:f7b1eb17ad24
120 * X2 1:925d80f479bb
120 * X2 1:925d80f479bb
121 Y -1:000000000000
121 Y -1:000000000000
122
122
123 bookmark rev 0 again
123 bookmark rev 0 again
124
124
125 $ hg bookmark -r 0 Z
125 $ hg bookmark -r 0 Z
126
126
127 $ hg update X
127 $ hg update X
128 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
128 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
129 (activating bookmark X)
129 (activating bookmark X)
130 $ echo c > c
130 $ echo c > c
131 $ hg add c
131 $ hg add c
132 $ hg commit -m 2
132 $ hg commit -m 2
133 created new head
133 created new head
134
134
135 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
135 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
136
136
137 $ hg bookmarks
137 $ hg bookmarks
138 * X 2:db815d6d32e6
138 * X 2:db815d6d32e6
139 X2 1:925d80f479bb
139 X2 1:925d80f479bb
140 Y -1:000000000000
140 Y -1:000000000000
141 Z 0:f7b1eb17ad24
141 Z 0:f7b1eb17ad24
142
142
143 rename nonexistent bookmark
143 rename nonexistent bookmark
144
144
145 $ hg bookmark -m A B
145 $ hg bookmark -m A B
146 abort: bookmark 'A' does not exist
146 abort: bookmark 'A' does not exist
147 [255]
147 [255]
148
148
149 rename to existent bookmark
149 rename to existent bookmark
150
150
151 $ hg bookmark -m X Y
151 $ hg bookmark -m X Y
152 abort: bookmark 'Y' already exists (use -f to force)
152 abort: bookmark 'Y' already exists (use -f to force)
153 [255]
153 [255]
154
154
155 force rename to existent bookmark
155 force rename to existent bookmark
156
156
157 $ hg bookmark -f -m X Y
157 $ hg bookmark -f -m X Y
158
158
159 list bookmarks
159 list bookmarks
160
160
161 $ hg bookmark
161 $ hg bookmark
162 X2 1:925d80f479bb
162 X2 1:925d80f479bb
163 * Y 2:db815d6d32e6
163 * Y 2:db815d6d32e6
164 Z 0:f7b1eb17ad24
164 Z 0:f7b1eb17ad24
165
165
166 bookmarks from a revset
166 bookmarks from a revset
167 $ hg bookmark -r '.^1' REVSET
167 $ hg bookmark -r '.^1' REVSET
168 $ hg bookmark -r ':tip' TIP
168 $ hg bookmark -r ':tip' TIP
169 $ hg up -q TIP
169 $ hg up -q TIP
170 $ hg bookmarks
170 $ hg bookmarks
171 REVSET 0:f7b1eb17ad24
171 REVSET 0:f7b1eb17ad24
172 * TIP 2:db815d6d32e6
172 * TIP 2:db815d6d32e6
173 X2 1:925d80f479bb
173 X2 1:925d80f479bb
174 Y 2:db815d6d32e6
174 Y 2:db815d6d32e6
175 Z 0:f7b1eb17ad24
175 Z 0:f7b1eb17ad24
176
176
177 $ hg bookmark -d REVSET
177 $ hg bookmark -d REVSET
178 $ hg bookmark -d TIP
178 $ hg bookmark -d TIP
179
179
180 rename without new name or multiple names
180 rename without new name or multiple names
181
181
182 $ hg bookmark -m Y
182 $ hg bookmark -m Y
183 abort: new bookmark name required
183 abort: new bookmark name required
184 [255]
184 [255]
185 $ hg bookmark -m Y Y2 Y3
185 $ hg bookmark -m Y Y2 Y3
186 abort: only one new bookmark name allowed
186 abort: only one new bookmark name allowed
187 [255]
187 [255]
188
188
189 delete without name
189 delete without name
190
190
191 $ hg bookmark -d
191 $ hg bookmark -d
192 abort: bookmark name required
192 abort: bookmark name required
193 [255]
193 [255]
194
194
195 delete nonexistent bookmark
195 delete nonexistent bookmark
196
196
197 $ hg bookmark -d A
197 $ hg bookmark -d A
198 abort: bookmark 'A' does not exist
198 abort: bookmark 'A' does not exist
199 [255]
199 [255]
200
200
201 bookmark name with spaces should be stripped
201 bookmark name with spaces should be stripped
202
202
203 $ hg bookmark ' x y '
203 $ hg bookmark ' x y '
204
204
205 list bookmarks
205 list bookmarks
206
206
207 $ hg bookmarks
207 $ hg bookmarks
208 X2 1:925d80f479bb
208 X2 1:925d80f479bb
209 Y 2:db815d6d32e6
209 Y 2:db815d6d32e6
210 Z 0:f7b1eb17ad24
210 Z 0:f7b1eb17ad24
211 * x y 2:db815d6d32e6
211 * x y 2:db815d6d32e6
212
212
213 look up stripped bookmark name
213 look up stripped bookmark name
214
214
215 $ hg log -r '"x y"'
215 $ hg log -r '"x y"'
216 changeset: 2:db815d6d32e6
216 changeset: 2:db815d6d32e6
217 bookmark: Y
217 bookmark: Y
218 bookmark: x y
218 bookmark: x y
219 tag: tip
219 tag: tip
220 parent: 0:f7b1eb17ad24
220 parent: 0:f7b1eb17ad24
221 user: test
221 user: test
222 date: Thu Jan 01 00:00:00 1970 +0000
222 date: Thu Jan 01 00:00:00 1970 +0000
223 summary: 2
223 summary: 2
224
224
225
225
226 reject bookmark name with newline
226 reject bookmark name with newline
227
227
228 $ hg bookmark '
228 $ hg bookmark '
229 > '
229 > '
230 abort: bookmark names cannot consist entirely of whitespace
230 abort: bookmark names cannot consist entirely of whitespace
231 [255]
231 [255]
232
232
233 $ hg bookmark -m Z '
233 $ hg bookmark -m Z '
234 > '
234 > '
235 abort: bookmark names cannot consist entirely of whitespace
235 abort: bookmark names cannot consist entirely of whitespace
236 [255]
236 [255]
237
237
238 bookmark with reserved name
238 bookmark with reserved name
239
239
240 $ hg bookmark tip
240 $ hg bookmark tip
241 abort: the name 'tip' is reserved
241 abort: the name 'tip' is reserved
242 [255]
242 [255]
243
243
244 $ hg bookmark .
244 $ hg bookmark .
245 abort: the name '.' is reserved
245 abort: the name '.' is reserved
246 [255]
246 [255]
247
247
248 $ hg bookmark null
248 $ hg bookmark null
249 abort: the name 'null' is reserved
249 abort: the name 'null' is reserved
250 [255]
250 [255]
251
251
252
252
253 bookmark with existing name
253 bookmark with existing name
254
254
255 $ hg bookmark X2
255 $ hg bookmark X2
256 abort: bookmark 'X2' already exists (use -f to force)
256 abort: bookmark 'X2' already exists (use -f to force)
257 [255]
257 [255]
258
258
259 $ hg bookmark -m Y Z
259 $ hg bookmark -m Y Z
260 abort: bookmark 'Z' already exists (use -f to force)
260 abort: bookmark 'Z' already exists (use -f to force)
261 [255]
261 [255]
262
262
263 bookmark with name of branch
263 bookmark with name of branch
264
264
265 $ hg bookmark default
265 $ hg bookmark default
266 abort: a bookmark cannot have the name of an existing branch
266 abort: a bookmark cannot have the name of an existing branch
267 [255]
267 [255]
268
268
269 $ hg bookmark -m Y default
269 $ hg bookmark -m Y default
270 abort: a bookmark cannot have the name of an existing branch
270 abort: a bookmark cannot have the name of an existing branch
271 [255]
271 [255]
272
272
273 bookmark with integer name
273 bookmark with integer name
274
274
275 $ hg bookmark 10
275 $ hg bookmark 10
276 abort: cannot use an integer as a name
276 abort: cannot use an integer as a name
277 [255]
277 [255]
278
278
279 incompatible options
279 incompatible options
280
280
281 $ hg bookmark -m Y -d Z
281 $ hg bookmark -m Y -d Z
282 abort: --delete and --rename are incompatible
282 abort: --delete and --rename are incompatible
283 [255]
283 [255]
284
284
285 $ hg bookmark -r 1 -d Z
285 $ hg bookmark -r 1 -d Z
286 abort: --rev is incompatible with --delete
286 abort: --rev is incompatible with --delete
287 [255]
287 [255]
288
288
289 $ hg bookmark -r 1 -m Z Y
289 $ hg bookmark -r 1 -m Z Y
290 abort: --rev is incompatible with --rename
290 abort: --rev is incompatible with --rename
291 [255]
291 [255]
292
292
293 force bookmark with existing name
293 force bookmark with existing name
294
294
295 $ hg bookmark -f X2
295 $ hg bookmark -f X2
296
296
297 force bookmark back to where it was, should deactivate it
297 force bookmark back to where it was, should deactivate it
298
298
299 $ hg bookmark -fr1 X2
299 $ hg bookmark -fr1 X2
300 $ hg bookmarks
300 $ hg bookmarks
301 X2 1:925d80f479bb
301 X2 1:925d80f479bb
302 Y 2:db815d6d32e6
302 Y 2:db815d6d32e6
303 Z 0:f7b1eb17ad24
303 Z 0:f7b1eb17ad24
304 x y 2:db815d6d32e6
304 x y 2:db815d6d32e6
305
305
306 forward bookmark to descendant without --force
306 forward bookmark to descendant without --force
307
307
308 $ hg bookmark Z
308 $ hg bookmark Z
309 moving bookmark 'Z' forward from f7b1eb17ad24
309 moving bookmark 'Z' forward from f7b1eb17ad24
310
310
311 list bookmarks
311 list bookmarks
312
312
313 $ hg bookmark
313 $ hg bookmark
314 X2 1:925d80f479bb
314 X2 1:925d80f479bb
315 Y 2:db815d6d32e6
315 Y 2:db815d6d32e6
316 * Z 2:db815d6d32e6
316 * Z 2:db815d6d32e6
317 x y 2:db815d6d32e6
317 x y 2:db815d6d32e6
318
318
319 revision but no bookmark name
319 revision but no bookmark name
320
320
321 $ hg bookmark -r .
321 $ hg bookmark -r .
322 abort: bookmark name required
322 abort: bookmark name required
323 [255]
323 [255]
324
324
325 bookmark name with whitespace only
325 bookmark name with whitespace only
326
326
327 $ hg bookmark ' '
327 $ hg bookmark ' '
328 abort: bookmark names cannot consist entirely of whitespace
328 abort: bookmark names cannot consist entirely of whitespace
329 [255]
329 [255]
330
330
331 $ hg bookmark -m Y ' '
331 $ hg bookmark -m Y ' '
332 abort: bookmark names cannot consist entirely of whitespace
332 abort: bookmark names cannot consist entirely of whitespace
333 [255]
333 [255]
334
334
335 invalid bookmark
335 invalid bookmark
336
336
337 $ hg bookmark 'foo:bar'
337 $ hg bookmark 'foo:bar'
338 abort: ':' cannot be used in a name
338 abort: ':' cannot be used in a name
339 [255]
339 [255]
340
340
341 $ hg bookmark 'foo
341 $ hg bookmark 'foo
342 > bar'
342 > bar'
343 abort: '\n' cannot be used in a name
343 abort: '\n' cannot be used in a name
344 [255]
344 [255]
345
345
346 the bookmark extension should be ignored now that it is part of core
346 the bookmark extension should be ignored now that it is part of core
347
347
348 $ echo "[extensions]" >> $HGRCPATH
348 $ echo "[extensions]" >> $HGRCPATH
349 $ echo "bookmarks=" >> $HGRCPATH
349 $ echo "bookmarks=" >> $HGRCPATH
350 $ hg bookmarks
350 $ hg bookmarks
351 X2 1:925d80f479bb
351 X2 1:925d80f479bb
352 Y 2:db815d6d32e6
352 Y 2:db815d6d32e6
353 * Z 2:db815d6d32e6
353 * Z 2:db815d6d32e6
354 x y 2:db815d6d32e6
354 x y 2:db815d6d32e6
355
355
356 test summary
356 test summary
357
357
358 $ hg summary
358 $ hg summary
359 parent: 2:db815d6d32e6 tip
359 parent: 2:db815d6d32e6 tip
360 2
360 2
361 branch: default
361 branch: default
362 bookmarks: *Z Y x y
362 bookmarks: *Z Y x y
363 commit: (clean)
363 commit: (clean)
364 update: 1 new changesets, 2 branch heads (merge)
364 update: 1 new changesets, 2 branch heads (merge)
365
365
366 test id
366 test id
367
367
368 $ hg id
368 $ hg id
369 db815d6d32e6 tip Y/Z/x y
369 db815d6d32e6 tip Y/Z/x y
370
370
371 test rollback
371 test rollback
372
372
373 $ echo foo > f1
373 $ echo foo > f1
374 $ hg ci -Amr
374 $ hg ci -Amr
375 adding f1
375 adding f1
376 $ hg bookmark -f Y -r 1
376 $ hg bookmark -f Y -r 1
377 $ hg bookmark -f Z -r 1
377 $ hg bookmark -f Z -r 1
378 $ hg rollback
378 $ hg rollback
379 repository tip rolled back to revision 2 (undo commit)
379 repository tip rolled back to revision 2 (undo commit)
380 working directory now based on revision 2
380 working directory now based on revision 2
381 $ hg bookmarks
381 $ hg bookmarks
382 X2 1:925d80f479bb
382 X2 1:925d80f479bb
383 Y 2:db815d6d32e6
383 Y 2:db815d6d32e6
384 Z 2:db815d6d32e6
384 Z 2:db815d6d32e6
385 x y 2:db815d6d32e6
385 x y 2:db815d6d32e6
386
386
387 activate bookmark on working dir parent without --force
387 activate bookmark on working dir parent without --force
388
388
389 $ hg bookmark --inactive Z
389 $ hg bookmark --inactive Z
390 $ hg bookmark Z
390 $ hg bookmark Z
391
391
392 test clone
392 test clone
393
393
394 $ hg bookmark -r 2 -i @
394 $ hg bookmark -r 2 -i @
395 $ hg bookmark -r 2 -i a@
395 $ hg bookmark -r 2 -i a@
396 $ hg bookmarks
396 $ hg bookmarks
397 @ 2:db815d6d32e6
397 @ 2:db815d6d32e6
398 X2 1:925d80f479bb
398 X2 1:925d80f479bb
399 Y 2:db815d6d32e6
399 Y 2:db815d6d32e6
400 * Z 2:db815d6d32e6
400 * Z 2:db815d6d32e6
401 a@ 2:db815d6d32e6
401 a@ 2:db815d6d32e6
402 x y 2:db815d6d32e6
402 x y 2:db815d6d32e6
403 $ hg clone . cloned-bookmarks
403 $ hg clone . cloned-bookmarks
404 updating to bookmark @
404 updating to bookmark @
405 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
405 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
406 $ hg -R cloned-bookmarks bookmarks
406 $ hg -R cloned-bookmarks bookmarks
407 * @ 2:db815d6d32e6
407 * @ 2:db815d6d32e6
408 X2 1:925d80f479bb
408 X2 1:925d80f479bb
409 Y 2:db815d6d32e6
409 Y 2:db815d6d32e6
410 Z 2:db815d6d32e6
410 Z 2:db815d6d32e6
411 a@ 2:db815d6d32e6
411 a@ 2:db815d6d32e6
412 x y 2:db815d6d32e6
412 x y 2:db815d6d32e6
413
413
414 test clone with pull protocol
414 test clone with pull protocol
415
415
416 $ hg clone --pull . cloned-bookmarks-pull
416 $ hg clone --pull . cloned-bookmarks-pull
417 requesting all changes
417 requesting all changes
418 adding changesets
418 adding changesets
419 adding manifests
419 adding manifests
420 adding file changes
420 adding file changes
421 added 3 changesets with 3 changes to 3 files (+1 heads)
421 added 3 changesets with 3 changes to 3 files (+1 heads)
422 updating to bookmark @
422 updating to bookmark @
423 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
423 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
424 $ hg -R cloned-bookmarks-pull bookmarks
424 $ hg -R cloned-bookmarks-pull bookmarks
425 * @ 2:db815d6d32e6
425 * @ 2:db815d6d32e6
426 X2 1:925d80f479bb
426 X2 1:925d80f479bb
427 Y 2:db815d6d32e6
427 Y 2:db815d6d32e6
428 Z 2:db815d6d32e6
428 Z 2:db815d6d32e6
429 a@ 2:db815d6d32e6
429 a@ 2:db815d6d32e6
430 x y 2:db815d6d32e6
430 x y 2:db815d6d32e6
431
431
432 delete multiple bookmarks at once
432 delete multiple bookmarks at once
433
433
434 $ hg bookmark -d @ a@
434 $ hg bookmark -d @ a@
435
435
436 test clone with a bookmark named "default" (issue3677)
436 test clone with a bookmark named "default" (issue3677)
437
437
438 $ hg bookmark -r 1 -f -i default
438 $ hg bookmark -r 1 -f -i default
439 $ hg clone . cloned-bookmark-default
439 $ hg clone . cloned-bookmark-default
440 updating to branch default
440 updating to branch default
441 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
441 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
442 $ hg -R cloned-bookmark-default bookmarks
442 $ hg -R cloned-bookmark-default bookmarks
443 X2 1:925d80f479bb
443 X2 1:925d80f479bb
444 Y 2:db815d6d32e6
444 Y 2:db815d6d32e6
445 Z 2:db815d6d32e6
445 Z 2:db815d6d32e6
446 default 1:925d80f479bb
446 default 1:925d80f479bb
447 x y 2:db815d6d32e6
447 x y 2:db815d6d32e6
448 $ hg -R cloned-bookmark-default parents -q
448 $ hg -R cloned-bookmark-default parents -q
449 2:db815d6d32e6
449 2:db815d6d32e6
450 $ hg bookmark -d default
450 $ hg bookmark -d default
451
451
452 test clone with a specific revision
452 test clone with a specific revision
453
453
454 $ hg clone -r 925d80 . cloned-bookmarks-rev
454 $ hg clone -r 925d80 . cloned-bookmarks-rev
455 adding changesets
455 adding changesets
456 adding manifests
456 adding manifests
457 adding file changes
457 adding file changes
458 added 2 changesets with 2 changes to 2 files
458 added 2 changesets with 2 changes to 2 files
459 updating to branch default
459 updating to branch default
460 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
460 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 $ hg -R cloned-bookmarks-rev bookmarks
461 $ hg -R cloned-bookmarks-rev bookmarks
462 X2 1:925d80f479bb
462 X2 1:925d80f479bb
463
463
464 test clone with update to a bookmark
464 test clone with update to a bookmark
465
465
466 $ hg clone -u Z . cloned-bookmarks-update
466 $ hg clone -u Z . cloned-bookmarks-update
467 updating to branch default
467 updating to branch default
468 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
468 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
469 $ hg -R cloned-bookmarks-update bookmarks
469 $ hg -R cloned-bookmarks-update bookmarks
470 X2 1:925d80f479bb
470 X2 1:925d80f479bb
471 Y 2:db815d6d32e6
471 Y 2:db815d6d32e6
472 * Z 2:db815d6d32e6
472 * Z 2:db815d6d32e6
473 x y 2:db815d6d32e6
473 x y 2:db815d6d32e6
474
474
475 create bundle with two heads
475 create bundle with two heads
476
476
477 $ hg clone . tobundle
477 $ hg clone . tobundle
478 updating to branch default
478 updating to branch default
479 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
479 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
480 $ echo x > tobundle/x
480 $ echo x > tobundle/x
481 $ hg -R tobundle add tobundle/x
481 $ hg -R tobundle add tobundle/x
482 $ hg -R tobundle commit -m'x'
482 $ hg -R tobundle commit -m'x'
483 $ hg -R tobundle update -r -2
483 $ hg -R tobundle update -r -2
484 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
484 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
485 $ echo y > tobundle/y
485 $ echo y > tobundle/y
486 $ hg -R tobundle branch test
486 $ hg -R tobundle branch test
487 marked working directory as branch test
487 marked working directory as branch test
488 (branches are permanent and global, did you want a bookmark?)
488 (branches are permanent and global, did you want a bookmark?)
489 $ hg -R tobundle add tobundle/y
489 $ hg -R tobundle add tobundle/y
490 $ hg -R tobundle commit -m'y'
490 $ hg -R tobundle commit -m'y'
491 $ hg -R tobundle bundle tobundle.hg
491 $ hg -R tobundle bundle tobundle.hg
492 searching for changes
492 searching for changes
493 2 changesets found
493 2 changesets found
494 $ hg unbundle tobundle.hg
494 $ hg unbundle tobundle.hg
495 adding changesets
495 adding changesets
496 adding manifests
496 adding manifests
497 adding file changes
497 adding file changes
498 added 2 changesets with 2 changes to 2 files (+1 heads)
498 added 2 changesets with 2 changes to 2 files (+1 heads)
499 (run 'hg heads' to see heads, 'hg merge' to merge)
499 (run 'hg heads' to see heads, 'hg merge' to merge)
500
500
501 update to current bookmark if it's not the parent
501 update to current bookmark if it's not the parent
502
502
503 $ hg summary
503 $ hg summary
504 parent: 2:db815d6d32e6
504 parent: 2:db815d6d32e6
505 2
505 2
506 branch: default
506 branch: default
507 bookmarks: *Z Y x y
507 bookmarks: *Z Y x y
508 commit: 1 added, 1 unknown (new branch head)
508 commit: 1 added, 1 unknown (new branch head)
509 update: 2 new changesets (update)
509 update: 2 new changesets (update)
510 $ hg update
510 $ hg update
511 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
511 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
512 updating bookmark Z
512 updating bookmark Z
513 $ hg bookmarks
513 $ hg bookmarks
514 X2 1:925d80f479bb
514 X2 1:925d80f479bb
515 Y 2:db815d6d32e6
515 Y 2:db815d6d32e6
516 * Z 3:125c9a1d6df6
516 * Z 3:125c9a1d6df6
517 x y 2:db815d6d32e6
517 x y 2:db815d6d32e6
518
518
519 pull --update works the same as pull && update
519 pull --update works the same as pull && update
520
520
521 $ hg bookmark -r3 Y
521 $ hg bookmark -r3 Y
522 moving bookmark 'Y' forward from db815d6d32e6
522 moving bookmark 'Y' forward from db815d6d32e6
523 $ hg -R cloned-bookmarks-update update Y
523 $ hg -R cloned-bookmarks-update update Y
524 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
524 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
525 (activating bookmark Y)
525 (activating bookmark Y)
526 $ hg -R cloned-bookmarks-update pull --update .
526 $ hg -R cloned-bookmarks-update pull --update .
527 pulling from .
527 pulling from .
528 searching for changes
528 searching for changes
529 adding changesets
529 adding changesets
530 adding manifests
530 adding manifests
531 adding file changes
531 adding file changes
532 added 2 changesets with 2 changes to 2 files (+1 heads)
532 added 2 changesets with 2 changes to 2 files (+1 heads)
533 updating bookmark Y
533 updating bookmark Y
534 updating bookmark Z
534 updating bookmark Z
535 updating to active bookmark Y
535 updating to active bookmark Y
536 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
536 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
537
537
538 test wrongly formated bookmark
538 test wrongly formated bookmark
539
539
540 $ echo '' >> .hg/bookmarks
540 $ echo '' >> .hg/bookmarks
541 $ hg bookmarks
541 $ hg bookmarks
542 X2 1:925d80f479bb
542 X2 1:925d80f479bb
543 Y 3:125c9a1d6df6
543 Y 3:125c9a1d6df6
544 * Z 3:125c9a1d6df6
544 * Z 3:125c9a1d6df6
545 x y 2:db815d6d32e6
545 x y 2:db815d6d32e6
546 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
546 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
547 $ hg bookmarks
547 $ hg bookmarks
548 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
548 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
549 X2 1:925d80f479bb
549 X2 1:925d80f479bb
550 Y 3:125c9a1d6df6
550 Y 3:125c9a1d6df6
551 * Z 3:125c9a1d6df6
551 * Z 3:125c9a1d6df6
552 x y 2:db815d6d32e6
552 x y 2:db815d6d32e6
553
553
554 test missing revisions
554 test missing revisions
555
555
556 $ echo "925d80f479bc z" > .hg/bookmarks
556 $ echo "925d80f479bc z" > .hg/bookmarks
557 $ hg book
557 $ hg book
558 no bookmarks set
558 no bookmarks set
559
559
560 test stripping a non-checked-out but bookmarked revision
560 test stripping a non-checked-out but bookmarked revision
561
561
562 $ hg log --graph
562 $ hg log --graph
563 o changeset: 4:9ba5f110a0b3
563 o changeset: 4:9ba5f110a0b3
564 | branch: test
564 | branch: test
565 | tag: tip
565 | tag: tip
566 | parent: 2:db815d6d32e6
566 | parent: 2:db815d6d32e6
567 | user: test
567 | user: test
568 | date: Thu Jan 01 00:00:00 1970 +0000
568 | date: Thu Jan 01 00:00:00 1970 +0000
569 | summary: y
569 | summary: y
570 |
570 |
571 | @ changeset: 3:125c9a1d6df6
571 | @ changeset: 3:125c9a1d6df6
572 |/ user: test
572 |/ user: test
573 | date: Thu Jan 01 00:00:00 1970 +0000
573 | date: Thu Jan 01 00:00:00 1970 +0000
574 | summary: x
574 | summary: x
575 |
575 |
576 o changeset: 2:db815d6d32e6
576 o changeset: 2:db815d6d32e6
577 | parent: 0:f7b1eb17ad24
577 | parent: 0:f7b1eb17ad24
578 | user: test
578 | user: test
579 | date: Thu Jan 01 00:00:00 1970 +0000
579 | date: Thu Jan 01 00:00:00 1970 +0000
580 | summary: 2
580 | summary: 2
581 |
581 |
582 | o changeset: 1:925d80f479bb
582 | o changeset: 1:925d80f479bb
583 |/ user: test
583 |/ user: test
584 | date: Thu Jan 01 00:00:00 1970 +0000
584 | date: Thu Jan 01 00:00:00 1970 +0000
585 | summary: 1
585 | summary: 1
586 |
586 |
587 o changeset: 0:f7b1eb17ad24
587 o changeset: 0:f7b1eb17ad24
588 user: test
588 user: test
589 date: Thu Jan 01 00:00:00 1970 +0000
589 date: Thu Jan 01 00:00:00 1970 +0000
590 summary: 0
590 summary: 0
591
591
592 $ hg book should-end-on-two
592 $ hg book should-end-on-two
593 $ hg co --clean 4
593 $ hg co --clean 4
594 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
594 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
595 (leaving bookmark should-end-on-two)
595 (leaving bookmark should-end-on-two)
596 $ hg book four
596 $ hg book four
597 $ hg --config extensions.mq= strip 3
597 $ hg --config extensions.mq= strip 3
598 saved backup bundle to * (glob)
598 saved backup bundle to * (glob)
599 should-end-on-two should end up pointing to revision 2, as that's the
599 should-end-on-two should end up pointing to revision 2, as that's the
600 tipmost surviving ancestor of the stripped revision.
600 tipmost surviving ancestor of the stripped revision.
601 $ hg log --graph
601 $ hg log --graph
602 @ changeset: 3:9ba5f110a0b3
602 @ changeset: 3:9ba5f110a0b3
603 | branch: test
603 | branch: test
604 | bookmark: four
604 | bookmark: four
605 | tag: tip
605 | tag: tip
606 | user: test
606 | user: test
607 | date: Thu Jan 01 00:00:00 1970 +0000
607 | date: Thu Jan 01 00:00:00 1970 +0000
608 | summary: y
608 | summary: y
609 |
609 |
610 o changeset: 2:db815d6d32e6
610 o changeset: 2:db815d6d32e6
611 | bookmark: should-end-on-two
611 | bookmark: should-end-on-two
612 | parent: 0:f7b1eb17ad24
612 | parent: 0:f7b1eb17ad24
613 | user: test
613 | user: test
614 | date: Thu Jan 01 00:00:00 1970 +0000
614 | date: Thu Jan 01 00:00:00 1970 +0000
615 | summary: 2
615 | summary: 2
616 |
616 |
617 | o changeset: 1:925d80f479bb
617 | o changeset: 1:925d80f479bb
618 |/ user: test
618 |/ user: test
619 | date: Thu Jan 01 00:00:00 1970 +0000
619 | date: Thu Jan 01 00:00:00 1970 +0000
620 | summary: 1
620 | summary: 1
621 |
621 |
622 o changeset: 0:f7b1eb17ad24
622 o changeset: 0:f7b1eb17ad24
623 user: test
623 user: test
624 date: Thu Jan 01 00:00:00 1970 +0000
624 date: Thu Jan 01 00:00:00 1970 +0000
625 summary: 0
625 summary: 0
626
626
627
627
628 test clearing divergent bookmarks of linear ancestors
628 test clearing divergent bookmarks of linear ancestors
629
629
630 $ hg bookmark Z -r 0
630 $ hg bookmark Z -r 0
631 $ hg bookmark Z@1 -r 1
631 $ hg bookmark Z@1 -r 1
632 $ hg bookmark Z@2 -r 2
632 $ hg bookmark Z@2 -r 2
633 $ hg bookmark Z@3 -r 3
633 $ hg bookmark Z@3 -r 3
634 $ hg book
634 $ hg book
635 Z 0:f7b1eb17ad24
635 Z 0:f7b1eb17ad24
636 Z@1 1:925d80f479bb
636 Z@1 1:925d80f479bb
637 Z@2 2:db815d6d32e6
637 Z@2 2:db815d6d32e6
638 Z@3 3:9ba5f110a0b3
638 Z@3 3:9ba5f110a0b3
639 * four 3:9ba5f110a0b3
639 * four 3:9ba5f110a0b3
640 should-end-on-two 2:db815d6d32e6
640 should-end-on-two 2:db815d6d32e6
641 $ hg bookmark Z
641 $ hg bookmark Z
642 moving bookmark 'Z' forward from f7b1eb17ad24
642 moving bookmark 'Z' forward from f7b1eb17ad24
643 $ hg book
643 $ hg book
644 * Z 3:9ba5f110a0b3
644 * Z 3:9ba5f110a0b3
645 Z@1 1:925d80f479bb
645 Z@1 1:925d80f479bb
646 four 3:9ba5f110a0b3
646 four 3:9ba5f110a0b3
647 should-end-on-two 2:db815d6d32e6
647 should-end-on-two 2:db815d6d32e6
648
648
649 test clearing only a single divergent bookmark across branches
649 test clearing only a single divergent bookmark across branches
650
650
651 $ hg book foo -r 1
651 $ hg book foo -r 1
652 $ hg book foo@1 -r 0
652 $ hg book foo@1 -r 0
653 $ hg book foo@2 -r 2
653 $ hg book foo@2 -r 2
654 $ hg book foo@3 -r 3
654 $ hg book foo@3 -r 3
655 $ hg book foo -r foo@3
655 $ hg book foo -r foo@3
656 $ hg book
656 $ hg book
657 * Z 3:9ba5f110a0b3
657 * Z 3:9ba5f110a0b3
658 Z@1 1:925d80f479bb
658 Z@1 1:925d80f479bb
659 foo 3:9ba5f110a0b3
659 foo 3:9ba5f110a0b3
660 foo@1 0:f7b1eb17ad24
660 foo@1 0:f7b1eb17ad24
661 foo@2 2:db815d6d32e6
661 foo@2 2:db815d6d32e6
662 four 3:9ba5f110a0b3
662 four 3:9ba5f110a0b3
663 should-end-on-two 2:db815d6d32e6
663 should-end-on-two 2:db815d6d32e6
General Comments 0
You need to be logged in to leave comments. Login now