##// END OF EJS Templates
graft: drop cset description from empty commit message...
Matt Mackall -
r23508:2164226a default
parent child Browse files
Show More
@@ -1,6262 +1,6263
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, copies
21 import dagparser, context, simplemerge, graphmod, copies
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 import ui as uimod
25 import ui as uimod
26
26
27 table = {}
27 table = {}
28
28
29 command = cmdutil.command(table)
29 command = cmdutil.command(table)
30
30
31 # Space delimited list of commands that don't require local repositories.
31 # Space delimited list of commands that don't require local repositories.
32 # This should be populated by passing norepo=True into the @command decorator.
32 # This should be populated by passing norepo=True into the @command decorator.
33 norepo = ''
33 norepo = ''
34 # Space delimited list of commands that optionally require local repositories.
34 # Space delimited list of commands that optionally require local repositories.
35 # This should be populated by passing optionalrepo=True into the @command
35 # This should be populated by passing optionalrepo=True into the @command
36 # decorator.
36 # decorator.
37 optionalrepo = ''
37 optionalrepo = ''
38 # Space delimited list of commands that will examine arguments looking for
38 # Space delimited list of commands that will examine arguments looking for
39 # a repository. This should be populated by passing inferrepo=True into the
39 # a repository. This should be populated by passing inferrepo=True into the
40 # @command decorator.
40 # @command decorator.
41 inferrepo = ''
41 inferrepo = ''
42
42
43 # common command options
43 # common command options
44
44
45 globalopts = [
45 globalopts = [
46 ('R', 'repository', '',
46 ('R', 'repository', '',
47 _('repository root directory or name of overlay bundle file'),
47 _('repository root directory or name of overlay bundle file'),
48 _('REPO')),
48 _('REPO')),
49 ('', 'cwd', '',
49 ('', 'cwd', '',
50 _('change working directory'), _('DIR')),
50 _('change working directory'), _('DIR')),
51 ('y', 'noninteractive', None,
51 ('y', 'noninteractive', None,
52 _('do not prompt, automatically pick the first choice for all prompts')),
52 _('do not prompt, automatically pick the first choice for all prompts')),
53 ('q', 'quiet', None, _('suppress output')),
53 ('q', 'quiet', None, _('suppress output')),
54 ('v', 'verbose', None, _('enable additional output')),
54 ('v', 'verbose', None, _('enable additional output')),
55 ('', 'config', [],
55 ('', 'config', [],
56 _('set/override config option (use \'section.name=value\')'),
56 _('set/override config option (use \'section.name=value\')'),
57 _('CONFIG')),
57 _('CONFIG')),
58 ('', 'debug', None, _('enable debugging output')),
58 ('', 'debug', None, _('enable debugging output')),
59 ('', 'debugger', None, _('start debugger')),
59 ('', 'debugger', None, _('start debugger')),
60 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
60 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
61 _('ENCODE')),
61 _('ENCODE')),
62 ('', 'encodingmode', encoding.encodingmode,
62 ('', 'encodingmode', encoding.encodingmode,
63 _('set the charset encoding mode'), _('MODE')),
63 _('set the charset encoding mode'), _('MODE')),
64 ('', 'traceback', None, _('always print a traceback on exception')),
64 ('', 'traceback', None, _('always print a traceback on exception')),
65 ('', 'time', None, _('time how long the command takes')),
65 ('', 'time', None, _('time how long the command takes')),
66 ('', 'profile', None, _('print command execution profile')),
66 ('', 'profile', None, _('print command execution profile')),
67 ('', 'version', None, _('output version information and exit')),
67 ('', 'version', None, _('output version information and exit')),
68 ('h', 'help', None, _('display help and exit')),
68 ('h', 'help', None, _('display help and exit')),
69 ('', 'hidden', False, _('consider hidden changesets')),
69 ('', 'hidden', False, _('consider hidden changesets')),
70 ]
70 ]
71
71
72 dryrunopts = [('n', 'dry-run', None,
72 dryrunopts = [('n', 'dry-run', None,
73 _('do not perform actions, just print output'))]
73 _('do not perform actions, just print output'))]
74
74
75 remoteopts = [
75 remoteopts = [
76 ('e', 'ssh', '',
76 ('e', 'ssh', '',
77 _('specify ssh command to use'), _('CMD')),
77 _('specify ssh command to use'), _('CMD')),
78 ('', 'remotecmd', '',
78 ('', 'remotecmd', '',
79 _('specify hg command to run on the remote side'), _('CMD')),
79 _('specify hg command to run on the remote side'), _('CMD')),
80 ('', 'insecure', None,
80 ('', 'insecure', None,
81 _('do not verify server certificate (ignoring web.cacerts config)')),
81 _('do not verify server certificate (ignoring web.cacerts config)')),
82 ]
82 ]
83
83
84 walkopts = [
84 walkopts = [
85 ('I', 'include', [],
85 ('I', 'include', [],
86 _('include names matching the given patterns'), _('PATTERN')),
86 _('include names matching the given patterns'), _('PATTERN')),
87 ('X', 'exclude', [],
87 ('X', 'exclude', [],
88 _('exclude names matching the given patterns'), _('PATTERN')),
88 _('exclude names matching the given patterns'), _('PATTERN')),
89 ]
89 ]
90
90
91 commitopts = [
91 commitopts = [
92 ('m', 'message', '',
92 ('m', 'message', '',
93 _('use text as commit message'), _('TEXT')),
93 _('use text as commit message'), _('TEXT')),
94 ('l', 'logfile', '',
94 ('l', 'logfile', '',
95 _('read commit message from file'), _('FILE')),
95 _('read commit message from file'), _('FILE')),
96 ]
96 ]
97
97
98 commitopts2 = [
98 commitopts2 = [
99 ('d', 'date', '',
99 ('d', 'date', '',
100 _('record the specified date as commit date'), _('DATE')),
100 _('record the specified date as commit date'), _('DATE')),
101 ('u', 'user', '',
101 ('u', 'user', '',
102 _('record the specified user as committer'), _('USER')),
102 _('record the specified user as committer'), _('USER')),
103 ]
103 ]
104
104
105 # hidden for now
105 # hidden for now
106 formatteropts = [
106 formatteropts = [
107 ('T', 'template', '',
107 ('T', 'template', '',
108 _('display with template (DEPRECATED)'), _('TEMPLATE')),
108 _('display with template (DEPRECATED)'), _('TEMPLATE')),
109 ]
109 ]
110
110
111 templateopts = [
111 templateopts = [
112 ('', 'style', '',
112 ('', 'style', '',
113 _('display using template map file (DEPRECATED)'), _('STYLE')),
113 _('display using template map file (DEPRECATED)'), _('STYLE')),
114 ('T', 'template', '',
114 ('T', 'template', '',
115 _('display with template'), _('TEMPLATE')),
115 _('display with template'), _('TEMPLATE')),
116 ]
116 ]
117
117
118 logopts = [
118 logopts = [
119 ('p', 'patch', None, _('show patch')),
119 ('p', 'patch', None, _('show patch')),
120 ('g', 'git', None, _('use git extended diff format')),
120 ('g', 'git', None, _('use git extended diff format')),
121 ('l', 'limit', '',
121 ('l', 'limit', '',
122 _('limit number of changes displayed'), _('NUM')),
122 _('limit number of changes displayed'), _('NUM')),
123 ('M', 'no-merges', None, _('do not show merges')),
123 ('M', 'no-merges', None, _('do not show merges')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ('G', 'graph', None, _("show the revision DAG")),
125 ('G', 'graph', None, _("show the revision DAG")),
126 ] + templateopts
126 ] + templateopts
127
127
128 diffopts = [
128 diffopts = [
129 ('a', 'text', None, _('treat all files as text')),
129 ('a', 'text', None, _('treat all files as text')),
130 ('g', 'git', None, _('use git extended diff format')),
130 ('g', 'git', None, _('use git extended diff format')),
131 ('', 'nodates', None, _('omit dates from diff headers'))
131 ('', 'nodates', None, _('omit dates from diff headers'))
132 ]
132 ]
133
133
134 diffwsopts = [
134 diffwsopts = [
135 ('w', 'ignore-all-space', None,
135 ('w', 'ignore-all-space', None,
136 _('ignore white space when comparing lines')),
136 _('ignore white space when comparing lines')),
137 ('b', 'ignore-space-change', None,
137 ('b', 'ignore-space-change', None,
138 _('ignore changes in the amount of white space')),
138 _('ignore changes in the amount of white space')),
139 ('B', 'ignore-blank-lines', None,
139 ('B', 'ignore-blank-lines', None,
140 _('ignore changes whose lines are all blank')),
140 _('ignore changes whose lines are all blank')),
141 ]
141 ]
142
142
143 diffopts2 = [
143 diffopts2 = [
144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
145 ('p', 'show-function', None, _('show which function each change is in')),
145 ('p', 'show-function', None, _('show which function each change is in')),
146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
147 ] + diffwsopts + [
147 ] + diffwsopts + [
148 ('U', 'unified', '',
148 ('U', 'unified', '',
149 _('number of lines of context to show'), _('NUM')),
149 _('number of lines of context to show'), _('NUM')),
150 ('', 'stat', None, _('output diffstat-style summary of changes')),
150 ('', 'stat', None, _('output diffstat-style summary of changes')),
151 ]
151 ]
152
152
153 mergetoolopts = [
153 mergetoolopts = [
154 ('t', 'tool', '', _('specify merge tool')),
154 ('t', 'tool', '', _('specify merge tool')),
155 ]
155 ]
156
156
157 similarityopts = [
157 similarityopts = [
158 ('s', 'similarity', '',
158 ('s', 'similarity', '',
159 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
159 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
160 ]
160 ]
161
161
162 subrepoopts = [
162 subrepoopts = [
163 ('S', 'subrepos', None,
163 ('S', 'subrepos', None,
164 _('recurse into subrepositories'))
164 _('recurse into subrepositories'))
165 ]
165 ]
166
166
167 # Commands start here, listed alphabetically
167 # Commands start here, listed alphabetically
168
168
169 @command('^add',
169 @command('^add',
170 walkopts + subrepoopts + dryrunopts,
170 walkopts + subrepoopts + dryrunopts,
171 _('[OPTION]... [FILE]...'),
171 _('[OPTION]... [FILE]...'),
172 inferrepo=True)
172 inferrepo=True)
173 def add(ui, repo, *pats, **opts):
173 def add(ui, repo, *pats, **opts):
174 """add the specified files on the next commit
174 """add the specified files on the next commit
175
175
176 Schedule files to be version controlled and added to the
176 Schedule files to be version controlled and added to the
177 repository.
177 repository.
178
178
179 The files will be added to the repository at the next commit. To
179 The files will be added to the repository at the next commit. To
180 undo an add before that, see :hg:`forget`.
180 undo an add before that, see :hg:`forget`.
181
181
182 If no names are given, add all files to the repository.
182 If no names are given, add all files to the repository.
183
183
184 .. container:: verbose
184 .. container:: verbose
185
185
186 An example showing how new (unknown) files are added
186 An example showing how new (unknown) files are added
187 automatically by :hg:`add`::
187 automatically by :hg:`add`::
188
188
189 $ ls
189 $ ls
190 foo.c
190 foo.c
191 $ hg status
191 $ hg status
192 ? foo.c
192 ? foo.c
193 $ hg add
193 $ hg add
194 adding foo.c
194 adding foo.c
195 $ hg status
195 $ hg status
196 A foo.c
196 A foo.c
197
197
198 Returns 0 if all files are successfully added.
198 Returns 0 if all files are successfully added.
199 """
199 """
200
200
201 m = scmutil.match(repo[None], pats, opts)
201 m = scmutil.match(repo[None], pats, opts)
202 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
202 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
203 opts.get('subrepos'), prefix="", explicitonly=False)
203 opts.get('subrepos'), prefix="", explicitonly=False)
204 return rejected and 1 or 0
204 return rejected and 1 or 0
205
205
206 @command('addremove',
206 @command('addremove',
207 similarityopts + walkopts + dryrunopts,
207 similarityopts + walkopts + dryrunopts,
208 _('[OPTION]... [FILE]...'),
208 _('[OPTION]... [FILE]...'),
209 inferrepo=True)
209 inferrepo=True)
210 def addremove(ui, repo, *pats, **opts):
210 def addremove(ui, repo, *pats, **opts):
211 """add all new files, delete all missing files
211 """add all new files, delete all missing files
212
212
213 Add all new files and remove all missing files from the
213 Add all new files and remove all missing files from the
214 repository.
214 repository.
215
215
216 New files are ignored if they match any of the patterns in
216 New files are ignored if they match any of the patterns in
217 ``.hgignore``. As with add, these changes take effect at the next
217 ``.hgignore``. As with add, these changes take effect at the next
218 commit.
218 commit.
219
219
220 Use the -s/--similarity option to detect renamed files. This
220 Use the -s/--similarity option to detect renamed files. This
221 option takes a percentage between 0 (disabled) and 100 (files must
221 option takes a percentage between 0 (disabled) and 100 (files must
222 be identical) as its parameter. With a parameter greater than 0,
222 be identical) as its parameter. With a parameter greater than 0,
223 this compares every removed file with every added file and records
223 this compares every removed file with every added file and records
224 those similar enough as renames. Detecting renamed files this way
224 those similar enough as renames. Detecting renamed files this way
225 can be expensive. After using this option, :hg:`status -C` can be
225 can be expensive. After using this option, :hg:`status -C` can be
226 used to check which files were identified as moved or renamed. If
226 used to check which files were identified as moved or renamed. If
227 not specified, -s/--similarity defaults to 100 and only renames of
227 not specified, -s/--similarity defaults to 100 and only renames of
228 identical files are detected.
228 identical files are detected.
229
229
230 Returns 0 if all files are successfully added.
230 Returns 0 if all files are successfully added.
231 """
231 """
232 try:
232 try:
233 sim = float(opts.get('similarity') or 100)
233 sim = float(opts.get('similarity') or 100)
234 except ValueError:
234 except ValueError:
235 raise util.Abort(_('similarity must be a number'))
235 raise util.Abort(_('similarity must be a number'))
236 if sim < 0 or sim > 100:
236 if sim < 0 or sim > 100:
237 raise util.Abort(_('similarity must be between 0 and 100'))
237 raise util.Abort(_('similarity must be between 0 and 100'))
238 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
238 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
239
239
240 @command('^annotate|blame',
240 @command('^annotate|blame',
241 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
241 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
242 ('', 'follow', None,
242 ('', 'follow', None,
243 _('follow copies/renames and list the filename (DEPRECATED)')),
243 _('follow copies/renames and list the filename (DEPRECATED)')),
244 ('', 'no-follow', None, _("don't follow copies and renames")),
244 ('', 'no-follow', None, _("don't follow copies and renames")),
245 ('a', 'text', None, _('treat all files as text')),
245 ('a', 'text', None, _('treat all files as text')),
246 ('u', 'user', None, _('list the author (long with -v)')),
246 ('u', 'user', None, _('list the author (long with -v)')),
247 ('f', 'file', None, _('list the filename')),
247 ('f', 'file', None, _('list the filename')),
248 ('d', 'date', None, _('list the date (short with -q)')),
248 ('d', 'date', None, _('list the date (short with -q)')),
249 ('n', 'number', None, _('list the revision number (default)')),
249 ('n', 'number', None, _('list the revision number (default)')),
250 ('c', 'changeset', None, _('list the changeset')),
250 ('c', 'changeset', None, _('list the changeset')),
251 ('l', 'line-number', None, _('show line number at the first appearance'))
251 ('l', 'line-number', None, _('show line number at the first appearance'))
252 ] + diffwsopts + walkopts + formatteropts,
252 ] + diffwsopts + walkopts + formatteropts,
253 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
253 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
254 inferrepo=True)
254 inferrepo=True)
255 def annotate(ui, repo, *pats, **opts):
255 def annotate(ui, repo, *pats, **opts):
256 """show changeset information by line for each file
256 """show changeset information by line for each file
257
257
258 List changes in files, showing the revision id responsible for
258 List changes in files, showing the revision id responsible for
259 each line
259 each line
260
260
261 This command is useful for discovering when a change was made and
261 This command is useful for discovering when a change was made and
262 by whom.
262 by whom.
263
263
264 Without the -a/--text option, annotate will avoid processing files
264 Without the -a/--text option, annotate will avoid processing files
265 it detects as binary. With -a, annotate will annotate the file
265 it detects as binary. With -a, annotate will annotate the file
266 anyway, although the results will probably be neither useful
266 anyway, although the results will probably be neither useful
267 nor desirable.
267 nor desirable.
268
268
269 Returns 0 on success.
269 Returns 0 on success.
270 """
270 """
271 if not pats:
271 if not pats:
272 raise util.Abort(_('at least one filename or pattern is required'))
272 raise util.Abort(_('at least one filename or pattern is required'))
273
273
274 if opts.get('follow'):
274 if opts.get('follow'):
275 # --follow is deprecated and now just an alias for -f/--file
275 # --follow is deprecated and now just an alias for -f/--file
276 # to mimic the behavior of Mercurial before version 1.5
276 # to mimic the behavior of Mercurial before version 1.5
277 opts['file'] = True
277 opts['file'] = True
278
278
279 fm = ui.formatter('annotate', opts)
279 fm = ui.formatter('annotate', opts)
280 datefunc = ui.quiet and util.shortdate or util.datestr
280 datefunc = ui.quiet and util.shortdate or util.datestr
281 hexfn = fm.hexfunc
281 hexfn = fm.hexfunc
282
282
283 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
283 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
284 ('number', ' ', lambda x: x[0].rev(), str),
284 ('number', ' ', lambda x: x[0].rev(), str),
285 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
285 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
286 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
286 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
287 ('file', ' ', lambda x: x[0].path(), str),
287 ('file', ' ', lambda x: x[0].path(), str),
288 ('line_number', ':', lambda x: x[1], str),
288 ('line_number', ':', lambda x: x[1], str),
289 ]
289 ]
290 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
290 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
291
291
292 if (not opts.get('user') and not opts.get('changeset')
292 if (not opts.get('user') and not opts.get('changeset')
293 and not opts.get('date') and not opts.get('file')):
293 and not opts.get('date') and not opts.get('file')):
294 opts['number'] = True
294 opts['number'] = True
295
295
296 linenumber = opts.get('line_number') is not None
296 linenumber = opts.get('line_number') is not None
297 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
297 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
298 raise util.Abort(_('at least one of -n/-c is required for -l'))
298 raise util.Abort(_('at least one of -n/-c is required for -l'))
299
299
300 if fm:
300 if fm:
301 def makefunc(get, fmt):
301 def makefunc(get, fmt):
302 return get
302 return get
303 else:
303 else:
304 def makefunc(get, fmt):
304 def makefunc(get, fmt):
305 return lambda x: fmt(get(x))
305 return lambda x: fmt(get(x))
306 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
306 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
307 if opts.get(op)]
307 if opts.get(op)]
308 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
308 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
309 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
309 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
310 if opts.get(op))
310 if opts.get(op))
311
311
312 def bad(x, y):
312 def bad(x, y):
313 raise util.Abort("%s: %s" % (x, y))
313 raise util.Abort("%s: %s" % (x, y))
314
314
315 ctx = scmutil.revsingle(repo, opts.get('rev'))
315 ctx = scmutil.revsingle(repo, opts.get('rev'))
316 m = scmutil.match(ctx, pats, opts)
316 m = scmutil.match(ctx, pats, opts)
317 m.bad = bad
317 m.bad = bad
318 follow = not opts.get('no_follow')
318 follow = not opts.get('no_follow')
319 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
319 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
320 whitespace=True)
320 whitespace=True)
321 for abs in ctx.walk(m):
321 for abs in ctx.walk(m):
322 fctx = ctx[abs]
322 fctx = ctx[abs]
323 if not opts.get('text') and util.binary(fctx.data()):
323 if not opts.get('text') and util.binary(fctx.data()):
324 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
324 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
325 continue
325 continue
326
326
327 lines = fctx.annotate(follow=follow, linenumber=linenumber,
327 lines = fctx.annotate(follow=follow, linenumber=linenumber,
328 diffopts=diffopts)
328 diffopts=diffopts)
329 formats = []
329 formats = []
330 pieces = []
330 pieces = []
331
331
332 for f, sep in funcmap:
332 for f, sep in funcmap:
333 l = [f(n) for n, dummy in lines]
333 l = [f(n) for n, dummy in lines]
334 if l:
334 if l:
335 if fm:
335 if fm:
336 formats.append(['%s' for x in l])
336 formats.append(['%s' for x in l])
337 else:
337 else:
338 sizes = [encoding.colwidth(x) for x in l]
338 sizes = [encoding.colwidth(x) for x in l]
339 ml = max(sizes)
339 ml = max(sizes)
340 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
340 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
341 pieces.append(l)
341 pieces.append(l)
342
342
343 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
343 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
344 fm.startitem()
344 fm.startitem()
345 fm.write(fields, "".join(f), *p)
345 fm.write(fields, "".join(f), *p)
346 fm.write('line', ": %s", l[1])
346 fm.write('line', ": %s", l[1])
347
347
348 if lines and not lines[-1][1].endswith('\n'):
348 if lines and not lines[-1][1].endswith('\n'):
349 fm.plain('\n')
349 fm.plain('\n')
350
350
351 fm.end()
351 fm.end()
352
352
353 @command('archive',
353 @command('archive',
354 [('', 'no-decode', None, _('do not pass files through decoders')),
354 [('', 'no-decode', None, _('do not pass files through decoders')),
355 ('p', 'prefix', '', _('directory prefix for files in archive'),
355 ('p', 'prefix', '', _('directory prefix for files in archive'),
356 _('PREFIX')),
356 _('PREFIX')),
357 ('r', 'rev', '', _('revision to distribute'), _('REV')),
357 ('r', 'rev', '', _('revision to distribute'), _('REV')),
358 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
358 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
359 ] + subrepoopts + walkopts,
359 ] + subrepoopts + walkopts,
360 _('[OPTION]... DEST'))
360 _('[OPTION]... DEST'))
361 def archive(ui, repo, dest, **opts):
361 def archive(ui, repo, dest, **opts):
362 '''create an unversioned archive of a repository revision
362 '''create an unversioned archive of a repository revision
363
363
364 By default, the revision used is the parent of the working
364 By default, the revision used is the parent of the working
365 directory; use -r/--rev to specify a different revision.
365 directory; use -r/--rev to specify a different revision.
366
366
367 The archive type is automatically detected based on file
367 The archive type is automatically detected based on file
368 extension (or override using -t/--type).
368 extension (or override using -t/--type).
369
369
370 .. container:: verbose
370 .. container:: verbose
371
371
372 Examples:
372 Examples:
373
373
374 - create a zip file containing the 1.0 release::
374 - create a zip file containing the 1.0 release::
375
375
376 hg archive -r 1.0 project-1.0.zip
376 hg archive -r 1.0 project-1.0.zip
377
377
378 - create a tarball excluding .hg files::
378 - create a tarball excluding .hg files::
379
379
380 hg archive project.tar.gz -X ".hg*"
380 hg archive project.tar.gz -X ".hg*"
381
381
382 Valid types are:
382 Valid types are:
383
383
384 :``files``: a directory full of files (default)
384 :``files``: a directory full of files (default)
385 :``tar``: tar archive, uncompressed
385 :``tar``: tar archive, uncompressed
386 :``tbz2``: tar archive, compressed using bzip2
386 :``tbz2``: tar archive, compressed using bzip2
387 :``tgz``: tar archive, compressed using gzip
387 :``tgz``: tar archive, compressed using gzip
388 :``uzip``: zip archive, uncompressed
388 :``uzip``: zip archive, uncompressed
389 :``zip``: zip archive, compressed using deflate
389 :``zip``: zip archive, compressed using deflate
390
390
391 The exact name of the destination archive or directory is given
391 The exact name of the destination archive or directory is given
392 using a format string; see :hg:`help export` for details.
392 using a format string; see :hg:`help export` for details.
393
393
394 Each member added to an archive file has a directory prefix
394 Each member added to an archive file has a directory prefix
395 prepended. Use -p/--prefix to specify a format string for the
395 prepended. Use -p/--prefix to specify a format string for the
396 prefix. The default is the basename of the archive, with suffixes
396 prefix. The default is the basename of the archive, with suffixes
397 removed.
397 removed.
398
398
399 Returns 0 on success.
399 Returns 0 on success.
400 '''
400 '''
401
401
402 ctx = scmutil.revsingle(repo, opts.get('rev'))
402 ctx = scmutil.revsingle(repo, opts.get('rev'))
403 if not ctx:
403 if not ctx:
404 raise util.Abort(_('no working directory: please specify a revision'))
404 raise util.Abort(_('no working directory: please specify a revision'))
405 node = ctx.node()
405 node = ctx.node()
406 dest = cmdutil.makefilename(repo, dest, node)
406 dest = cmdutil.makefilename(repo, dest, node)
407 if os.path.realpath(dest) == repo.root:
407 if os.path.realpath(dest) == repo.root:
408 raise util.Abort(_('repository root cannot be destination'))
408 raise util.Abort(_('repository root cannot be destination'))
409
409
410 kind = opts.get('type') or archival.guesskind(dest) or 'files'
410 kind = opts.get('type') or archival.guesskind(dest) or 'files'
411 prefix = opts.get('prefix')
411 prefix = opts.get('prefix')
412
412
413 if dest == '-':
413 if dest == '-':
414 if kind == 'files':
414 if kind == 'files':
415 raise util.Abort(_('cannot archive plain files to stdout'))
415 raise util.Abort(_('cannot archive plain files to stdout'))
416 dest = cmdutil.makefileobj(repo, dest)
416 dest = cmdutil.makefileobj(repo, dest)
417 if not prefix:
417 if not prefix:
418 prefix = os.path.basename(repo.root) + '-%h'
418 prefix = os.path.basename(repo.root) + '-%h'
419
419
420 prefix = cmdutil.makefilename(repo, prefix, node)
420 prefix = cmdutil.makefilename(repo, prefix, node)
421 matchfn = scmutil.match(ctx, [], opts)
421 matchfn = scmutil.match(ctx, [], opts)
422 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
422 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
423 matchfn, prefix, subrepos=opts.get('subrepos'))
423 matchfn, prefix, subrepos=opts.get('subrepos'))
424
424
425 @command('backout',
425 @command('backout',
426 [('', 'merge', None, _('merge with old dirstate parent after backout')),
426 [('', 'merge', None, _('merge with old dirstate parent after backout')),
427 ('', 'parent', '',
427 ('', 'parent', '',
428 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
428 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
429 ('r', 'rev', '', _('revision to backout'), _('REV')),
429 ('r', 'rev', '', _('revision to backout'), _('REV')),
430 ('e', 'edit', False, _('invoke editor on commit messages')),
430 ('e', 'edit', False, _('invoke editor on commit messages')),
431 ] + mergetoolopts + walkopts + commitopts + commitopts2,
431 ] + mergetoolopts + walkopts + commitopts + commitopts2,
432 _('[OPTION]... [-r] REV'))
432 _('[OPTION]... [-r] REV'))
433 def backout(ui, repo, node=None, rev=None, **opts):
433 def backout(ui, repo, node=None, rev=None, **opts):
434 '''reverse effect of earlier changeset
434 '''reverse effect of earlier changeset
435
435
436 Prepare a new changeset with the effect of REV undone in the
436 Prepare a new changeset with the effect of REV undone in the
437 current working directory.
437 current working directory.
438
438
439 If REV is the parent of the working directory, then this new changeset
439 If REV is the parent of the working directory, then this new changeset
440 is committed automatically. Otherwise, hg needs to merge the
440 is committed automatically. Otherwise, hg needs to merge the
441 changes and the merged result is left uncommitted.
441 changes and the merged result is left uncommitted.
442
442
443 .. note::
443 .. note::
444
444
445 backout cannot be used to fix either an unwanted or
445 backout cannot be used to fix either an unwanted or
446 incorrect merge.
446 incorrect merge.
447
447
448 .. container:: verbose
448 .. container:: verbose
449
449
450 By default, the pending changeset will have one parent,
450 By default, the pending changeset will have one parent,
451 maintaining a linear history. With --merge, the pending
451 maintaining a linear history. With --merge, the pending
452 changeset will instead have two parents: the old parent of the
452 changeset will instead have two parents: the old parent of the
453 working directory and a new child of REV that simply undoes REV.
453 working directory and a new child of REV that simply undoes REV.
454
454
455 Before version 1.7, the behavior without --merge was equivalent
455 Before version 1.7, the behavior without --merge was equivalent
456 to specifying --merge followed by :hg:`update --clean .` to
456 to specifying --merge followed by :hg:`update --clean .` to
457 cancel the merge and leave the child of REV as a head to be
457 cancel the merge and leave the child of REV as a head to be
458 merged separately.
458 merged separately.
459
459
460 See :hg:`help dates` for a list of formats valid for -d/--date.
460 See :hg:`help dates` for a list of formats valid for -d/--date.
461
461
462 Returns 0 on success, 1 if nothing to backout or there are unresolved
462 Returns 0 on success, 1 if nothing to backout or there are unresolved
463 files.
463 files.
464 '''
464 '''
465 if rev and node:
465 if rev and node:
466 raise util.Abort(_("please specify just one revision"))
466 raise util.Abort(_("please specify just one revision"))
467
467
468 if not rev:
468 if not rev:
469 rev = node
469 rev = node
470
470
471 if not rev:
471 if not rev:
472 raise util.Abort(_("please specify a revision to backout"))
472 raise util.Abort(_("please specify a revision to backout"))
473
473
474 date = opts.get('date')
474 date = opts.get('date')
475 if date:
475 if date:
476 opts['date'] = util.parsedate(date)
476 opts['date'] = util.parsedate(date)
477
477
478 cmdutil.checkunfinished(repo)
478 cmdutil.checkunfinished(repo)
479 cmdutil.bailifchanged(repo)
479 cmdutil.bailifchanged(repo)
480 node = scmutil.revsingle(repo, rev).node()
480 node = scmutil.revsingle(repo, rev).node()
481
481
482 op1, op2 = repo.dirstate.parents()
482 op1, op2 = repo.dirstate.parents()
483 if not repo.changelog.isancestor(node, op1):
483 if not repo.changelog.isancestor(node, op1):
484 raise util.Abort(_('cannot backout change that is not an ancestor'))
484 raise util.Abort(_('cannot backout change that is not an ancestor'))
485
485
486 p1, p2 = repo.changelog.parents(node)
486 p1, p2 = repo.changelog.parents(node)
487 if p1 == nullid:
487 if p1 == nullid:
488 raise util.Abort(_('cannot backout a change with no parents'))
488 raise util.Abort(_('cannot backout a change with no parents'))
489 if p2 != nullid:
489 if p2 != nullid:
490 if not opts.get('parent'):
490 if not opts.get('parent'):
491 raise util.Abort(_('cannot backout a merge changeset'))
491 raise util.Abort(_('cannot backout a merge changeset'))
492 p = repo.lookup(opts['parent'])
492 p = repo.lookup(opts['parent'])
493 if p not in (p1, p2):
493 if p not in (p1, p2):
494 raise util.Abort(_('%s is not a parent of %s') %
494 raise util.Abort(_('%s is not a parent of %s') %
495 (short(p), short(node)))
495 (short(p), short(node)))
496 parent = p
496 parent = p
497 else:
497 else:
498 if opts.get('parent'):
498 if opts.get('parent'):
499 raise util.Abort(_('cannot use --parent on non-merge changeset'))
499 raise util.Abort(_('cannot use --parent on non-merge changeset'))
500 parent = p1
500 parent = p1
501
501
502 # the backout should appear on the same branch
502 # the backout should appear on the same branch
503 wlock = repo.wlock()
503 wlock = repo.wlock()
504 try:
504 try:
505 branch = repo.dirstate.branch()
505 branch = repo.dirstate.branch()
506 bheads = repo.branchheads(branch)
506 bheads = repo.branchheads(branch)
507 rctx = scmutil.revsingle(repo, hex(parent))
507 rctx = scmutil.revsingle(repo, hex(parent))
508 if not opts.get('merge') and op1 != node:
508 if not opts.get('merge') and op1 != node:
509 try:
509 try:
510 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
510 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
511 'backout')
511 'backout')
512 repo.dirstate.beginparentchange()
512 repo.dirstate.beginparentchange()
513 stats = mergemod.update(repo, parent, True, True, False,
513 stats = mergemod.update(repo, parent, True, True, False,
514 node, False)
514 node, False)
515 repo.setparents(op1, op2)
515 repo.setparents(op1, op2)
516 repo.dirstate.endparentchange()
516 repo.dirstate.endparentchange()
517 hg._showstats(repo, stats)
517 hg._showstats(repo, stats)
518 if stats[3]:
518 if stats[3]:
519 repo.ui.status(_("use 'hg resolve' to retry unresolved "
519 repo.ui.status(_("use 'hg resolve' to retry unresolved "
520 "file merges\n"))
520 "file merges\n"))
521 else:
521 else:
522 msg = _("changeset %s backed out, "
522 msg = _("changeset %s backed out, "
523 "don't forget to commit.\n")
523 "don't forget to commit.\n")
524 ui.status(msg % short(node))
524 ui.status(msg % short(node))
525 return stats[3] > 0
525 return stats[3] > 0
526 finally:
526 finally:
527 ui.setconfig('ui', 'forcemerge', '', '')
527 ui.setconfig('ui', 'forcemerge', '', '')
528 else:
528 else:
529 hg.clean(repo, node, show_stats=False)
529 hg.clean(repo, node, show_stats=False)
530 repo.dirstate.setbranch(branch)
530 repo.dirstate.setbranch(branch)
531 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
531 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
532
532
533
533
534 def commitfunc(ui, repo, message, match, opts):
534 def commitfunc(ui, repo, message, match, opts):
535 editform = 'backout'
535 editform = 'backout'
536 e = cmdutil.getcommiteditor(editform=editform, **opts)
536 e = cmdutil.getcommiteditor(editform=editform, **opts)
537 if not message:
537 if not message:
538 # we don't translate commit messages
538 # we don't translate commit messages
539 message = "Backed out changeset %s" % short(node)
539 message = "Backed out changeset %s" % short(node)
540 e = cmdutil.getcommiteditor(edit=True, editform=editform)
540 e = cmdutil.getcommiteditor(edit=True, editform=editform)
541 return repo.commit(message, opts.get('user'), opts.get('date'),
541 return repo.commit(message, opts.get('user'), opts.get('date'),
542 match, editor=e)
542 match, editor=e)
543 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
543 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
544 if not newnode:
544 if not newnode:
545 ui.status(_("nothing changed\n"))
545 ui.status(_("nothing changed\n"))
546 return 1
546 return 1
547 cmdutil.commitstatus(repo, newnode, branch, bheads)
547 cmdutil.commitstatus(repo, newnode, branch, bheads)
548
548
549 def nice(node):
549 def nice(node):
550 return '%d:%s' % (repo.changelog.rev(node), short(node))
550 return '%d:%s' % (repo.changelog.rev(node), short(node))
551 ui.status(_('changeset %s backs out changeset %s\n') %
551 ui.status(_('changeset %s backs out changeset %s\n') %
552 (nice(repo.changelog.tip()), nice(node)))
552 (nice(repo.changelog.tip()), nice(node)))
553 if opts.get('merge') and op1 != node:
553 if opts.get('merge') and op1 != node:
554 hg.clean(repo, op1, show_stats=False)
554 hg.clean(repo, op1, show_stats=False)
555 ui.status(_('merging with changeset %s\n')
555 ui.status(_('merging with changeset %s\n')
556 % nice(repo.changelog.tip()))
556 % nice(repo.changelog.tip()))
557 try:
557 try:
558 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
558 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
559 'backout')
559 'backout')
560 return hg.merge(repo, hex(repo.changelog.tip()))
560 return hg.merge(repo, hex(repo.changelog.tip()))
561 finally:
561 finally:
562 ui.setconfig('ui', 'forcemerge', '', '')
562 ui.setconfig('ui', 'forcemerge', '', '')
563 finally:
563 finally:
564 wlock.release()
564 wlock.release()
565 return 0
565 return 0
566
566
567 @command('bisect',
567 @command('bisect',
568 [('r', 'reset', False, _('reset bisect state')),
568 [('r', 'reset', False, _('reset bisect state')),
569 ('g', 'good', False, _('mark changeset good')),
569 ('g', 'good', False, _('mark changeset good')),
570 ('b', 'bad', False, _('mark changeset bad')),
570 ('b', 'bad', False, _('mark changeset bad')),
571 ('s', 'skip', False, _('skip testing changeset')),
571 ('s', 'skip', False, _('skip testing changeset')),
572 ('e', 'extend', False, _('extend the bisect range')),
572 ('e', 'extend', False, _('extend the bisect range')),
573 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
573 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
574 ('U', 'noupdate', False, _('do not update to target'))],
574 ('U', 'noupdate', False, _('do not update to target'))],
575 _("[-gbsr] [-U] [-c CMD] [REV]"))
575 _("[-gbsr] [-U] [-c CMD] [REV]"))
576 def bisect(ui, repo, rev=None, extra=None, command=None,
576 def bisect(ui, repo, rev=None, extra=None, command=None,
577 reset=None, good=None, bad=None, skip=None, extend=None,
577 reset=None, good=None, bad=None, skip=None, extend=None,
578 noupdate=None):
578 noupdate=None):
579 """subdivision search of changesets
579 """subdivision search of changesets
580
580
581 This command helps to find changesets which introduce problems. To
581 This command helps to find changesets which introduce problems. To
582 use, mark the earliest changeset you know exhibits the problem as
582 use, mark the earliest changeset you know exhibits the problem as
583 bad, then mark the latest changeset which is free from the problem
583 bad, then mark the latest changeset which is free from the problem
584 as good. Bisect will update your working directory to a revision
584 as good. Bisect will update your working directory to a revision
585 for testing (unless the -U/--noupdate option is specified). Once
585 for testing (unless the -U/--noupdate option is specified). Once
586 you have performed tests, mark the working directory as good or
586 you have performed tests, mark the working directory as good or
587 bad, and bisect will either update to another candidate changeset
587 bad, and bisect will either update to another candidate changeset
588 or announce that it has found the bad revision.
588 or announce that it has found the bad revision.
589
589
590 As a shortcut, you can also use the revision argument to mark a
590 As a shortcut, you can also use the revision argument to mark a
591 revision as good or bad without checking it out first.
591 revision as good or bad without checking it out first.
592
592
593 If you supply a command, it will be used for automatic bisection.
593 If you supply a command, it will be used for automatic bisection.
594 The environment variable HG_NODE will contain the ID of the
594 The environment variable HG_NODE will contain the ID of the
595 changeset being tested. The exit status of the command will be
595 changeset being tested. The exit status of the command will be
596 used to mark revisions as good or bad: status 0 means good, 125
596 used to mark revisions as good or bad: status 0 means good, 125
597 means to skip the revision, 127 (command not found) will abort the
597 means to skip the revision, 127 (command not found) will abort the
598 bisection, and any other non-zero exit status means the revision
598 bisection, and any other non-zero exit status means the revision
599 is bad.
599 is bad.
600
600
601 .. container:: verbose
601 .. container:: verbose
602
602
603 Some examples:
603 Some examples:
604
604
605 - start a bisection with known bad revision 34, and good revision 12::
605 - start a bisection with known bad revision 34, and good revision 12::
606
606
607 hg bisect --bad 34
607 hg bisect --bad 34
608 hg bisect --good 12
608 hg bisect --good 12
609
609
610 - advance the current bisection by marking current revision as good or
610 - advance the current bisection by marking current revision as good or
611 bad::
611 bad::
612
612
613 hg bisect --good
613 hg bisect --good
614 hg bisect --bad
614 hg bisect --bad
615
615
616 - mark the current revision, or a known revision, to be skipped (e.g. if
616 - mark the current revision, or a known revision, to be skipped (e.g. if
617 that revision is not usable because of another issue)::
617 that revision is not usable because of another issue)::
618
618
619 hg bisect --skip
619 hg bisect --skip
620 hg bisect --skip 23
620 hg bisect --skip 23
621
621
622 - skip all revisions that do not touch directories ``foo`` or ``bar``::
622 - skip all revisions that do not touch directories ``foo`` or ``bar``::
623
623
624 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
624 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
625
625
626 - forget the current bisection::
626 - forget the current bisection::
627
627
628 hg bisect --reset
628 hg bisect --reset
629
629
630 - use 'make && make tests' to automatically find the first broken
630 - use 'make && make tests' to automatically find the first broken
631 revision::
631 revision::
632
632
633 hg bisect --reset
633 hg bisect --reset
634 hg bisect --bad 34
634 hg bisect --bad 34
635 hg bisect --good 12
635 hg bisect --good 12
636 hg bisect --command "make && make tests"
636 hg bisect --command "make && make tests"
637
637
638 - see all changesets whose states are already known in the current
638 - see all changesets whose states are already known in the current
639 bisection::
639 bisection::
640
640
641 hg log -r "bisect(pruned)"
641 hg log -r "bisect(pruned)"
642
642
643 - see the changeset currently being bisected (especially useful
643 - see the changeset currently being bisected (especially useful
644 if running with -U/--noupdate)::
644 if running with -U/--noupdate)::
645
645
646 hg log -r "bisect(current)"
646 hg log -r "bisect(current)"
647
647
648 - see all changesets that took part in the current bisection::
648 - see all changesets that took part in the current bisection::
649
649
650 hg log -r "bisect(range)"
650 hg log -r "bisect(range)"
651
651
652 - you can even get a nice graph::
652 - you can even get a nice graph::
653
653
654 hg log --graph -r "bisect(range)"
654 hg log --graph -r "bisect(range)"
655
655
656 See :hg:`help revsets` for more about the `bisect()` keyword.
656 See :hg:`help revsets` for more about the `bisect()` keyword.
657
657
658 Returns 0 on success.
658 Returns 0 on success.
659 """
659 """
660 def extendbisectrange(nodes, good):
660 def extendbisectrange(nodes, good):
661 # bisect is incomplete when it ends on a merge node and
661 # bisect is incomplete when it ends on a merge node and
662 # one of the parent was not checked.
662 # one of the parent was not checked.
663 parents = repo[nodes[0]].parents()
663 parents = repo[nodes[0]].parents()
664 if len(parents) > 1:
664 if len(parents) > 1:
665 side = good and state['bad'] or state['good']
665 side = good and state['bad'] or state['good']
666 num = len(set(i.node() for i in parents) & set(side))
666 num = len(set(i.node() for i in parents) & set(side))
667 if num == 1:
667 if num == 1:
668 return parents[0].ancestor(parents[1])
668 return parents[0].ancestor(parents[1])
669 return None
669 return None
670
670
671 def print_result(nodes, good):
671 def print_result(nodes, good):
672 displayer = cmdutil.show_changeset(ui, repo, {})
672 displayer = cmdutil.show_changeset(ui, repo, {})
673 if len(nodes) == 1:
673 if len(nodes) == 1:
674 # narrowed it down to a single revision
674 # narrowed it down to a single revision
675 if good:
675 if good:
676 ui.write(_("The first good revision is:\n"))
676 ui.write(_("The first good revision is:\n"))
677 else:
677 else:
678 ui.write(_("The first bad revision is:\n"))
678 ui.write(_("The first bad revision is:\n"))
679 displayer.show(repo[nodes[0]])
679 displayer.show(repo[nodes[0]])
680 extendnode = extendbisectrange(nodes, good)
680 extendnode = extendbisectrange(nodes, good)
681 if extendnode is not None:
681 if extendnode is not None:
682 ui.write(_('Not all ancestors of this changeset have been'
682 ui.write(_('Not all ancestors of this changeset have been'
683 ' checked.\nUse bisect --extend to continue the '
683 ' checked.\nUse bisect --extend to continue the '
684 'bisection from\nthe common ancestor, %s.\n')
684 'bisection from\nthe common ancestor, %s.\n')
685 % extendnode)
685 % extendnode)
686 else:
686 else:
687 # multiple possible revisions
687 # multiple possible revisions
688 if good:
688 if good:
689 ui.write(_("Due to skipped revisions, the first "
689 ui.write(_("Due to skipped revisions, the first "
690 "good revision could be any of:\n"))
690 "good revision could be any of:\n"))
691 else:
691 else:
692 ui.write(_("Due to skipped revisions, the first "
692 ui.write(_("Due to skipped revisions, the first "
693 "bad revision could be any of:\n"))
693 "bad revision could be any of:\n"))
694 for n in nodes:
694 for n in nodes:
695 displayer.show(repo[n])
695 displayer.show(repo[n])
696 displayer.close()
696 displayer.close()
697
697
698 def check_state(state, interactive=True):
698 def check_state(state, interactive=True):
699 if not state['good'] or not state['bad']:
699 if not state['good'] or not state['bad']:
700 if (good or bad or skip or reset) and interactive:
700 if (good or bad or skip or reset) and interactive:
701 return
701 return
702 if not state['good']:
702 if not state['good']:
703 raise util.Abort(_('cannot bisect (no known good revisions)'))
703 raise util.Abort(_('cannot bisect (no known good revisions)'))
704 else:
704 else:
705 raise util.Abort(_('cannot bisect (no known bad revisions)'))
705 raise util.Abort(_('cannot bisect (no known bad revisions)'))
706 return True
706 return True
707
707
708 # backward compatibility
708 # backward compatibility
709 if rev in "good bad reset init".split():
709 if rev in "good bad reset init".split():
710 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
710 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
711 cmd, rev, extra = rev, extra, None
711 cmd, rev, extra = rev, extra, None
712 if cmd == "good":
712 if cmd == "good":
713 good = True
713 good = True
714 elif cmd == "bad":
714 elif cmd == "bad":
715 bad = True
715 bad = True
716 else:
716 else:
717 reset = True
717 reset = True
718 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
718 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
719 raise util.Abort(_('incompatible arguments'))
719 raise util.Abort(_('incompatible arguments'))
720
720
721 cmdutil.checkunfinished(repo)
721 cmdutil.checkunfinished(repo)
722
722
723 if reset:
723 if reset:
724 p = repo.join("bisect.state")
724 p = repo.join("bisect.state")
725 if os.path.exists(p):
725 if os.path.exists(p):
726 os.unlink(p)
726 os.unlink(p)
727 return
727 return
728
728
729 state = hbisect.load_state(repo)
729 state = hbisect.load_state(repo)
730
730
731 if command:
731 if command:
732 changesets = 1
732 changesets = 1
733 if noupdate:
733 if noupdate:
734 try:
734 try:
735 node = state['current'][0]
735 node = state['current'][0]
736 except LookupError:
736 except LookupError:
737 raise util.Abort(_('current bisect revision is unknown - '
737 raise util.Abort(_('current bisect revision is unknown - '
738 'start a new bisect to fix'))
738 'start a new bisect to fix'))
739 else:
739 else:
740 node, p2 = repo.dirstate.parents()
740 node, p2 = repo.dirstate.parents()
741 if p2 != nullid:
741 if p2 != nullid:
742 raise util.Abort(_('current bisect revision is a merge'))
742 raise util.Abort(_('current bisect revision is a merge'))
743 try:
743 try:
744 while changesets:
744 while changesets:
745 # update state
745 # update state
746 state['current'] = [node]
746 state['current'] = [node]
747 hbisect.save_state(repo, state)
747 hbisect.save_state(repo, state)
748 status = ui.system(command, environ={'HG_NODE': hex(node)})
748 status = ui.system(command, environ={'HG_NODE': hex(node)})
749 if status == 125:
749 if status == 125:
750 transition = "skip"
750 transition = "skip"
751 elif status == 0:
751 elif status == 0:
752 transition = "good"
752 transition = "good"
753 # status < 0 means process was killed
753 # status < 0 means process was killed
754 elif status == 127:
754 elif status == 127:
755 raise util.Abort(_("failed to execute %s") % command)
755 raise util.Abort(_("failed to execute %s") % command)
756 elif status < 0:
756 elif status < 0:
757 raise util.Abort(_("%s killed") % command)
757 raise util.Abort(_("%s killed") % command)
758 else:
758 else:
759 transition = "bad"
759 transition = "bad"
760 ctx = scmutil.revsingle(repo, rev, node)
760 ctx = scmutil.revsingle(repo, rev, node)
761 rev = None # clear for future iterations
761 rev = None # clear for future iterations
762 state[transition].append(ctx.node())
762 state[transition].append(ctx.node())
763 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
763 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
764 check_state(state, interactive=False)
764 check_state(state, interactive=False)
765 # bisect
765 # bisect
766 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
766 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
767 # update to next check
767 # update to next check
768 node = nodes[0]
768 node = nodes[0]
769 if not noupdate:
769 if not noupdate:
770 cmdutil.bailifchanged(repo)
770 cmdutil.bailifchanged(repo)
771 hg.clean(repo, node, show_stats=False)
771 hg.clean(repo, node, show_stats=False)
772 finally:
772 finally:
773 state['current'] = [node]
773 state['current'] = [node]
774 hbisect.save_state(repo, state)
774 hbisect.save_state(repo, state)
775 print_result(nodes, bgood)
775 print_result(nodes, bgood)
776 return
776 return
777
777
778 # update state
778 # update state
779
779
780 if rev:
780 if rev:
781 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
781 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
782 else:
782 else:
783 nodes = [repo.lookup('.')]
783 nodes = [repo.lookup('.')]
784
784
785 if good or bad or skip:
785 if good or bad or skip:
786 if good:
786 if good:
787 state['good'] += nodes
787 state['good'] += nodes
788 elif bad:
788 elif bad:
789 state['bad'] += nodes
789 state['bad'] += nodes
790 elif skip:
790 elif skip:
791 state['skip'] += nodes
791 state['skip'] += nodes
792 hbisect.save_state(repo, state)
792 hbisect.save_state(repo, state)
793
793
794 if not check_state(state):
794 if not check_state(state):
795 return
795 return
796
796
797 # actually bisect
797 # actually bisect
798 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
798 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
799 if extend:
799 if extend:
800 if not changesets:
800 if not changesets:
801 extendnode = extendbisectrange(nodes, good)
801 extendnode = extendbisectrange(nodes, good)
802 if extendnode is not None:
802 if extendnode is not None:
803 ui.write(_("Extending search to changeset %d:%s\n")
803 ui.write(_("Extending search to changeset %d:%s\n")
804 % (extendnode.rev(), extendnode))
804 % (extendnode.rev(), extendnode))
805 state['current'] = [extendnode.node()]
805 state['current'] = [extendnode.node()]
806 hbisect.save_state(repo, state)
806 hbisect.save_state(repo, state)
807 if noupdate:
807 if noupdate:
808 return
808 return
809 cmdutil.bailifchanged(repo)
809 cmdutil.bailifchanged(repo)
810 return hg.clean(repo, extendnode.node())
810 return hg.clean(repo, extendnode.node())
811 raise util.Abort(_("nothing to extend"))
811 raise util.Abort(_("nothing to extend"))
812
812
813 if changesets == 0:
813 if changesets == 0:
814 print_result(nodes, good)
814 print_result(nodes, good)
815 else:
815 else:
816 assert len(nodes) == 1 # only a single node can be tested next
816 assert len(nodes) == 1 # only a single node can be tested next
817 node = nodes[0]
817 node = nodes[0]
818 # compute the approximate number of remaining tests
818 # compute the approximate number of remaining tests
819 tests, size = 0, 2
819 tests, size = 0, 2
820 while size <= changesets:
820 while size <= changesets:
821 tests, size = tests + 1, size * 2
821 tests, size = tests + 1, size * 2
822 rev = repo.changelog.rev(node)
822 rev = repo.changelog.rev(node)
823 ui.write(_("Testing changeset %d:%s "
823 ui.write(_("Testing changeset %d:%s "
824 "(%d changesets remaining, ~%d tests)\n")
824 "(%d changesets remaining, ~%d tests)\n")
825 % (rev, short(node), changesets, tests))
825 % (rev, short(node), changesets, tests))
826 state['current'] = [node]
826 state['current'] = [node]
827 hbisect.save_state(repo, state)
827 hbisect.save_state(repo, state)
828 if not noupdate:
828 if not noupdate:
829 cmdutil.bailifchanged(repo)
829 cmdutil.bailifchanged(repo)
830 return hg.clean(repo, node)
830 return hg.clean(repo, node)
831
831
832 @command('bookmarks|bookmark',
832 @command('bookmarks|bookmark',
833 [('f', 'force', False, _('force')),
833 [('f', 'force', False, _('force')),
834 ('r', 'rev', '', _('revision'), _('REV')),
834 ('r', 'rev', '', _('revision'), _('REV')),
835 ('d', 'delete', False, _('delete a given bookmark')),
835 ('d', 'delete', False, _('delete a given bookmark')),
836 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
836 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
837 ('i', 'inactive', False, _('mark a bookmark inactive')),
837 ('i', 'inactive', False, _('mark a bookmark inactive')),
838 ] + formatteropts,
838 ] + formatteropts,
839 _('hg bookmarks [OPTIONS]... [NAME]...'))
839 _('hg bookmarks [OPTIONS]... [NAME]...'))
840 def bookmark(ui, repo, *names, **opts):
840 def bookmark(ui, repo, *names, **opts):
841 '''create a new bookmark or list existing bookmarks
841 '''create a new bookmark or list existing bookmarks
842
842
843 Bookmarks are labels on changesets to help track lines of development.
843 Bookmarks are labels on changesets to help track lines of development.
844 Bookmarks are unversioned and can be moved, renamed and deleted.
844 Bookmarks are unversioned and can be moved, renamed and deleted.
845 Deleting or moving a bookmark has no effect on the associated changesets.
845 Deleting or moving a bookmark has no effect on the associated changesets.
846
846
847 Creating or updating to a bookmark causes it to be marked as 'active'.
847 Creating or updating to a bookmark causes it to be marked as 'active'.
848 The active bookmark is indicated with a '*'.
848 The active bookmark is indicated with a '*'.
849 When a commit is made, the active bookmark will advance to the new commit.
849 When a commit is made, the active bookmark will advance to the new commit.
850 A plain :hg:`update` will also advance an active bookmark, if possible.
850 A plain :hg:`update` will also advance an active bookmark, if possible.
851 Updating away from a bookmark will cause it to be deactivated.
851 Updating away from a bookmark will cause it to be deactivated.
852
852
853 Bookmarks can be pushed and pulled between repositories (see
853 Bookmarks can be pushed and pulled between repositories (see
854 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
854 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
855 diverged, a new 'divergent bookmark' of the form 'name@path' will
855 diverged, a new 'divergent bookmark' of the form 'name@path' will
856 be created. Using :hg:`merge` will resolve the divergence.
856 be created. Using :hg:`merge` will resolve the divergence.
857
857
858 A bookmark named '@' has the special property that :hg:`clone` will
858 A bookmark named '@' has the special property that :hg:`clone` will
859 check it out by default if it exists.
859 check it out by default if it exists.
860
860
861 .. container:: verbose
861 .. container:: verbose
862
862
863 Examples:
863 Examples:
864
864
865 - create an active bookmark for a new line of development::
865 - create an active bookmark for a new line of development::
866
866
867 hg book new-feature
867 hg book new-feature
868
868
869 - create an inactive bookmark as a place marker::
869 - create an inactive bookmark as a place marker::
870
870
871 hg book -i reviewed
871 hg book -i reviewed
872
872
873 - create an inactive bookmark on another changeset::
873 - create an inactive bookmark on another changeset::
874
874
875 hg book -r .^ tested
875 hg book -r .^ tested
876
876
877 - move the '@' bookmark from another branch::
877 - move the '@' bookmark from another branch::
878
878
879 hg book -f @
879 hg book -f @
880 '''
880 '''
881 force = opts.get('force')
881 force = opts.get('force')
882 rev = opts.get('rev')
882 rev = opts.get('rev')
883 delete = opts.get('delete')
883 delete = opts.get('delete')
884 rename = opts.get('rename')
884 rename = opts.get('rename')
885 inactive = opts.get('inactive')
885 inactive = opts.get('inactive')
886
886
887 def checkformat(mark):
887 def checkformat(mark):
888 mark = mark.strip()
888 mark = mark.strip()
889 if not mark:
889 if not mark:
890 raise util.Abort(_("bookmark names cannot consist entirely of "
890 raise util.Abort(_("bookmark names cannot consist entirely of "
891 "whitespace"))
891 "whitespace"))
892 scmutil.checknewlabel(repo, mark, 'bookmark')
892 scmutil.checknewlabel(repo, mark, 'bookmark')
893 return mark
893 return mark
894
894
895 def checkconflict(repo, mark, cur, force=False, target=None):
895 def checkconflict(repo, mark, cur, force=False, target=None):
896 if mark in marks and not force:
896 if mark in marks and not force:
897 if target:
897 if target:
898 if marks[mark] == target and target == cur:
898 if marks[mark] == target and target == cur:
899 # re-activating a bookmark
899 # re-activating a bookmark
900 return
900 return
901 anc = repo.changelog.ancestors([repo[target].rev()])
901 anc = repo.changelog.ancestors([repo[target].rev()])
902 bmctx = repo[marks[mark]]
902 bmctx = repo[marks[mark]]
903 divs = [repo[b].node() for b in marks
903 divs = [repo[b].node() for b in marks
904 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
904 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
905
905
906 # allow resolving a single divergent bookmark even if moving
906 # allow resolving a single divergent bookmark even if moving
907 # the bookmark across branches when a revision is specified
907 # the bookmark across branches when a revision is specified
908 # that contains a divergent bookmark
908 # that contains a divergent bookmark
909 if bmctx.rev() not in anc and target in divs:
909 if bmctx.rev() not in anc and target in divs:
910 bookmarks.deletedivergent(repo, [target], mark)
910 bookmarks.deletedivergent(repo, [target], mark)
911 return
911 return
912
912
913 deletefrom = [b for b in divs
913 deletefrom = [b for b in divs
914 if repo[b].rev() in anc or b == target]
914 if repo[b].rev() in anc or b == target]
915 bookmarks.deletedivergent(repo, deletefrom, mark)
915 bookmarks.deletedivergent(repo, deletefrom, mark)
916 if bookmarks.validdest(repo, bmctx, repo[target]):
916 if bookmarks.validdest(repo, bmctx, repo[target]):
917 ui.status(_("moving bookmark '%s' forward from %s\n") %
917 ui.status(_("moving bookmark '%s' forward from %s\n") %
918 (mark, short(bmctx.node())))
918 (mark, short(bmctx.node())))
919 return
919 return
920 raise util.Abort(_("bookmark '%s' already exists "
920 raise util.Abort(_("bookmark '%s' already exists "
921 "(use -f to force)") % mark)
921 "(use -f to force)") % mark)
922 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
922 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
923 and not force):
923 and not force):
924 raise util.Abort(
924 raise util.Abort(
925 _("a bookmark cannot have the name of an existing branch"))
925 _("a bookmark cannot have the name of an existing branch"))
926
926
927 if delete and rename:
927 if delete and rename:
928 raise util.Abort(_("--delete and --rename are incompatible"))
928 raise util.Abort(_("--delete and --rename are incompatible"))
929 if delete and rev:
929 if delete and rev:
930 raise util.Abort(_("--rev is incompatible with --delete"))
930 raise util.Abort(_("--rev is incompatible with --delete"))
931 if rename and rev:
931 if rename and rev:
932 raise util.Abort(_("--rev is incompatible with --rename"))
932 raise util.Abort(_("--rev is incompatible with --rename"))
933 if not names and (delete or rev):
933 if not names and (delete or rev):
934 raise util.Abort(_("bookmark name required"))
934 raise util.Abort(_("bookmark name required"))
935
935
936 if delete or rename or names or inactive:
936 if delete or rename or names or inactive:
937 wlock = repo.wlock()
937 wlock = repo.wlock()
938 try:
938 try:
939 cur = repo.changectx('.').node()
939 cur = repo.changectx('.').node()
940 marks = repo._bookmarks
940 marks = repo._bookmarks
941 if delete:
941 if delete:
942 for mark in names:
942 for mark in names:
943 if mark not in marks:
943 if mark not in marks:
944 raise util.Abort(_("bookmark '%s' does not exist") %
944 raise util.Abort(_("bookmark '%s' does not exist") %
945 mark)
945 mark)
946 if mark == repo._bookmarkcurrent:
946 if mark == repo._bookmarkcurrent:
947 bookmarks.unsetcurrent(repo)
947 bookmarks.unsetcurrent(repo)
948 del marks[mark]
948 del marks[mark]
949 marks.write()
949 marks.write()
950
950
951 elif rename:
951 elif rename:
952 if not names:
952 if not names:
953 raise util.Abort(_("new bookmark name required"))
953 raise util.Abort(_("new bookmark name required"))
954 elif len(names) > 1:
954 elif len(names) > 1:
955 raise util.Abort(_("only one new bookmark name allowed"))
955 raise util.Abort(_("only one new bookmark name allowed"))
956 mark = checkformat(names[0])
956 mark = checkformat(names[0])
957 if rename not in marks:
957 if rename not in marks:
958 raise util.Abort(_("bookmark '%s' does not exist") % rename)
958 raise util.Abort(_("bookmark '%s' does not exist") % rename)
959 checkconflict(repo, mark, cur, force)
959 checkconflict(repo, mark, cur, force)
960 marks[mark] = marks[rename]
960 marks[mark] = marks[rename]
961 if repo._bookmarkcurrent == rename and not inactive:
961 if repo._bookmarkcurrent == rename and not inactive:
962 bookmarks.setcurrent(repo, mark)
962 bookmarks.setcurrent(repo, mark)
963 del marks[rename]
963 del marks[rename]
964 marks.write()
964 marks.write()
965
965
966 elif names:
966 elif names:
967 newact = None
967 newact = None
968 for mark in names:
968 for mark in names:
969 mark = checkformat(mark)
969 mark = checkformat(mark)
970 if newact is None:
970 if newact is None:
971 newact = mark
971 newact = mark
972 if inactive and mark == repo._bookmarkcurrent:
972 if inactive and mark == repo._bookmarkcurrent:
973 bookmarks.unsetcurrent(repo)
973 bookmarks.unsetcurrent(repo)
974 return
974 return
975 tgt = cur
975 tgt = cur
976 if rev:
976 if rev:
977 tgt = scmutil.revsingle(repo, rev).node()
977 tgt = scmutil.revsingle(repo, rev).node()
978 checkconflict(repo, mark, cur, force, tgt)
978 checkconflict(repo, mark, cur, force, tgt)
979 marks[mark] = tgt
979 marks[mark] = tgt
980 if not inactive and cur == marks[newact] and not rev:
980 if not inactive and cur == marks[newact] and not rev:
981 bookmarks.setcurrent(repo, newact)
981 bookmarks.setcurrent(repo, newact)
982 elif cur != tgt and newact == repo._bookmarkcurrent:
982 elif cur != tgt and newact == repo._bookmarkcurrent:
983 bookmarks.unsetcurrent(repo)
983 bookmarks.unsetcurrent(repo)
984 marks.write()
984 marks.write()
985
985
986 elif inactive:
986 elif inactive:
987 if len(marks) == 0:
987 if len(marks) == 0:
988 ui.status(_("no bookmarks set\n"))
988 ui.status(_("no bookmarks set\n"))
989 elif not repo._bookmarkcurrent:
989 elif not repo._bookmarkcurrent:
990 ui.status(_("no active bookmark\n"))
990 ui.status(_("no active bookmark\n"))
991 else:
991 else:
992 bookmarks.unsetcurrent(repo)
992 bookmarks.unsetcurrent(repo)
993 finally:
993 finally:
994 wlock.release()
994 wlock.release()
995 else: # show bookmarks
995 else: # show bookmarks
996 fm = ui.formatter('bookmarks', opts)
996 fm = ui.formatter('bookmarks', opts)
997 hexfn = fm.hexfunc
997 hexfn = fm.hexfunc
998 marks = repo._bookmarks
998 marks = repo._bookmarks
999 if len(marks) == 0 and not fm:
999 if len(marks) == 0 and not fm:
1000 ui.status(_("no bookmarks set\n"))
1000 ui.status(_("no bookmarks set\n"))
1001 for bmark, n in sorted(marks.iteritems()):
1001 for bmark, n in sorted(marks.iteritems()):
1002 current = repo._bookmarkcurrent
1002 current = repo._bookmarkcurrent
1003 if bmark == current:
1003 if bmark == current:
1004 prefix, label = '*', 'bookmarks.current'
1004 prefix, label = '*', 'bookmarks.current'
1005 else:
1005 else:
1006 prefix, label = ' ', ''
1006 prefix, label = ' ', ''
1007
1007
1008 fm.startitem()
1008 fm.startitem()
1009 if not ui.quiet:
1009 if not ui.quiet:
1010 fm.plain(' %s ' % prefix, label=label)
1010 fm.plain(' %s ' % prefix, label=label)
1011 fm.write('bookmark', '%s', bmark, label=label)
1011 fm.write('bookmark', '%s', bmark, label=label)
1012 pad = " " * (25 - encoding.colwidth(bmark))
1012 pad = " " * (25 - encoding.colwidth(bmark))
1013 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1013 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1014 repo.changelog.rev(n), hexfn(n), label=label)
1014 repo.changelog.rev(n), hexfn(n), label=label)
1015 fm.data(active=(bmark == current))
1015 fm.data(active=(bmark == current))
1016 fm.plain('\n')
1016 fm.plain('\n')
1017 fm.end()
1017 fm.end()
1018
1018
1019 @command('branch',
1019 @command('branch',
1020 [('f', 'force', None,
1020 [('f', 'force', None,
1021 _('set branch name even if it shadows an existing branch')),
1021 _('set branch name even if it shadows an existing branch')),
1022 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1022 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1023 _('[-fC] [NAME]'))
1023 _('[-fC] [NAME]'))
1024 def branch(ui, repo, label=None, **opts):
1024 def branch(ui, repo, label=None, **opts):
1025 """set or show the current branch name
1025 """set or show the current branch name
1026
1026
1027 .. note::
1027 .. note::
1028
1028
1029 Branch names are permanent and global. Use :hg:`bookmark` to create a
1029 Branch names are permanent and global. Use :hg:`bookmark` to create a
1030 light-weight bookmark instead. See :hg:`help glossary` for more
1030 light-weight bookmark instead. See :hg:`help glossary` for more
1031 information about named branches and bookmarks.
1031 information about named branches and bookmarks.
1032
1032
1033 With no argument, show the current branch name. With one argument,
1033 With no argument, show the current branch name. With one argument,
1034 set the working directory branch name (the branch will not exist
1034 set the working directory branch name (the branch will not exist
1035 in the repository until the next commit). Standard practice
1035 in the repository until the next commit). Standard practice
1036 recommends that primary development take place on the 'default'
1036 recommends that primary development take place on the 'default'
1037 branch.
1037 branch.
1038
1038
1039 Unless -f/--force is specified, branch will not let you set a
1039 Unless -f/--force is specified, branch will not let you set a
1040 branch name that already exists, even if it's inactive.
1040 branch name that already exists, even if it's inactive.
1041
1041
1042 Use -C/--clean to reset the working directory branch to that of
1042 Use -C/--clean to reset the working directory branch to that of
1043 the parent of the working directory, negating a previous branch
1043 the parent of the working directory, negating a previous branch
1044 change.
1044 change.
1045
1045
1046 Use the command :hg:`update` to switch to an existing branch. Use
1046 Use the command :hg:`update` to switch to an existing branch. Use
1047 :hg:`commit --close-branch` to mark this branch as closed.
1047 :hg:`commit --close-branch` to mark this branch as closed.
1048
1048
1049 Returns 0 on success.
1049 Returns 0 on success.
1050 """
1050 """
1051 if label:
1051 if label:
1052 label = label.strip()
1052 label = label.strip()
1053
1053
1054 if not opts.get('clean') and not label:
1054 if not opts.get('clean') and not label:
1055 ui.write("%s\n" % repo.dirstate.branch())
1055 ui.write("%s\n" % repo.dirstate.branch())
1056 return
1056 return
1057
1057
1058 wlock = repo.wlock()
1058 wlock = repo.wlock()
1059 try:
1059 try:
1060 if opts.get('clean'):
1060 if opts.get('clean'):
1061 label = repo[None].p1().branch()
1061 label = repo[None].p1().branch()
1062 repo.dirstate.setbranch(label)
1062 repo.dirstate.setbranch(label)
1063 ui.status(_('reset working directory to branch %s\n') % label)
1063 ui.status(_('reset working directory to branch %s\n') % label)
1064 elif label:
1064 elif label:
1065 if not opts.get('force') and label in repo.branchmap():
1065 if not opts.get('force') and label in repo.branchmap():
1066 if label not in [p.branch() for p in repo.parents()]:
1066 if label not in [p.branch() for p in repo.parents()]:
1067 raise util.Abort(_('a branch of the same name already'
1067 raise util.Abort(_('a branch of the same name already'
1068 ' exists'),
1068 ' exists'),
1069 # i18n: "it" refers to an existing branch
1069 # i18n: "it" refers to an existing branch
1070 hint=_("use 'hg update' to switch to it"))
1070 hint=_("use 'hg update' to switch to it"))
1071 scmutil.checknewlabel(repo, label, 'branch')
1071 scmutil.checknewlabel(repo, label, 'branch')
1072 repo.dirstate.setbranch(label)
1072 repo.dirstate.setbranch(label)
1073 ui.status(_('marked working directory as branch %s\n') % label)
1073 ui.status(_('marked working directory as branch %s\n') % label)
1074 ui.status(_('(branches are permanent and global, '
1074 ui.status(_('(branches are permanent and global, '
1075 'did you want a bookmark?)\n'))
1075 'did you want a bookmark?)\n'))
1076 finally:
1076 finally:
1077 wlock.release()
1077 wlock.release()
1078
1078
1079 @command('branches',
1079 @command('branches',
1080 [('a', 'active', False, _('show only branches that have unmerged heads')),
1080 [('a', 'active', False, _('show only branches that have unmerged heads')),
1081 ('c', 'closed', False, _('show normal and closed branches')),
1081 ('c', 'closed', False, _('show normal and closed branches')),
1082 ] + formatteropts,
1082 ] + formatteropts,
1083 _('[-ac]'))
1083 _('[-ac]'))
1084 def branches(ui, repo, active=False, closed=False, **opts):
1084 def branches(ui, repo, active=False, closed=False, **opts):
1085 """list repository named branches
1085 """list repository named branches
1086
1086
1087 List the repository's named branches, indicating which ones are
1087 List the repository's named branches, indicating which ones are
1088 inactive. If -c/--closed is specified, also list branches which have
1088 inactive. If -c/--closed is specified, also list branches which have
1089 been marked closed (see :hg:`commit --close-branch`).
1089 been marked closed (see :hg:`commit --close-branch`).
1090
1090
1091 If -a/--active is specified, only show active branches. A branch
1091 If -a/--active is specified, only show active branches. A branch
1092 is considered active if it contains repository heads.
1092 is considered active if it contains repository heads.
1093
1093
1094 Use the command :hg:`update` to switch to an existing branch.
1094 Use the command :hg:`update` to switch to an existing branch.
1095
1095
1096 Returns 0.
1096 Returns 0.
1097 """
1097 """
1098
1098
1099 fm = ui.formatter('branches', opts)
1099 fm = ui.formatter('branches', opts)
1100 hexfunc = fm.hexfunc
1100 hexfunc = fm.hexfunc
1101
1101
1102 allheads = set(repo.heads())
1102 allheads = set(repo.heads())
1103 branches = []
1103 branches = []
1104 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1104 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1105 isactive = not isclosed and bool(set(heads) & allheads)
1105 isactive = not isclosed and bool(set(heads) & allheads)
1106 branches.append((tag, repo[tip], isactive, not isclosed))
1106 branches.append((tag, repo[tip], isactive, not isclosed))
1107 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1107 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1108 reverse=True)
1108 reverse=True)
1109
1109
1110 for tag, ctx, isactive, isopen in branches:
1110 for tag, ctx, isactive, isopen in branches:
1111 if active and not isactive:
1111 if active and not isactive:
1112 continue
1112 continue
1113 if isactive:
1113 if isactive:
1114 label = 'branches.active'
1114 label = 'branches.active'
1115 notice = ''
1115 notice = ''
1116 elif not isopen:
1116 elif not isopen:
1117 if not closed:
1117 if not closed:
1118 continue
1118 continue
1119 label = 'branches.closed'
1119 label = 'branches.closed'
1120 notice = _(' (closed)')
1120 notice = _(' (closed)')
1121 else:
1121 else:
1122 label = 'branches.inactive'
1122 label = 'branches.inactive'
1123 notice = _(' (inactive)')
1123 notice = _(' (inactive)')
1124 current = (tag == repo.dirstate.branch())
1124 current = (tag == repo.dirstate.branch())
1125 if current:
1125 if current:
1126 label = 'branches.current'
1126 label = 'branches.current'
1127
1127
1128 fm.startitem()
1128 fm.startitem()
1129 fm.write('branch', '%s', tag, label=label)
1129 fm.write('branch', '%s', tag, label=label)
1130 rev = ctx.rev()
1130 rev = ctx.rev()
1131 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1131 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1132 fmt = ' ' * padsize + ' %d:%s'
1132 fmt = ' ' * padsize + ' %d:%s'
1133 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1133 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1134 label='log.changeset changeset.%s' % ctx.phasestr())
1134 label='log.changeset changeset.%s' % ctx.phasestr())
1135 fm.data(active=isactive, closed=not isopen, current=current)
1135 fm.data(active=isactive, closed=not isopen, current=current)
1136 if not ui.quiet:
1136 if not ui.quiet:
1137 fm.plain(notice)
1137 fm.plain(notice)
1138 fm.plain('\n')
1138 fm.plain('\n')
1139 fm.end()
1139 fm.end()
1140
1140
1141 @command('bundle',
1141 @command('bundle',
1142 [('f', 'force', None, _('run even when the destination is unrelated')),
1142 [('f', 'force', None, _('run even when the destination is unrelated')),
1143 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1143 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1144 _('REV')),
1144 _('REV')),
1145 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1145 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1146 _('BRANCH')),
1146 _('BRANCH')),
1147 ('', 'base', [],
1147 ('', 'base', [],
1148 _('a base changeset assumed to be available at the destination'),
1148 _('a base changeset assumed to be available at the destination'),
1149 _('REV')),
1149 _('REV')),
1150 ('a', 'all', None, _('bundle all changesets in the repository')),
1150 ('a', 'all', None, _('bundle all changesets in the repository')),
1151 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1151 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1152 ] + remoteopts,
1152 ] + remoteopts,
1153 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1153 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1154 def bundle(ui, repo, fname, dest=None, **opts):
1154 def bundle(ui, repo, fname, dest=None, **opts):
1155 """create a changegroup file
1155 """create a changegroup file
1156
1156
1157 Generate a compressed changegroup file collecting changesets not
1157 Generate a compressed changegroup file collecting changesets not
1158 known to be in another repository.
1158 known to be in another repository.
1159
1159
1160 If you omit the destination repository, then hg assumes the
1160 If you omit the destination repository, then hg assumes the
1161 destination will have all the nodes you specify with --base
1161 destination will have all the nodes you specify with --base
1162 parameters. To create a bundle containing all changesets, use
1162 parameters. To create a bundle containing all changesets, use
1163 -a/--all (or --base null).
1163 -a/--all (or --base null).
1164
1164
1165 You can change compression method with the -t/--type option.
1165 You can change compression method with the -t/--type option.
1166 The available compression methods are: none, bzip2, and
1166 The available compression methods are: none, bzip2, and
1167 gzip (by default, bundles are compressed using bzip2).
1167 gzip (by default, bundles are compressed using bzip2).
1168
1168
1169 The bundle file can then be transferred using conventional means
1169 The bundle file can then be transferred using conventional means
1170 and applied to another repository with the unbundle or pull
1170 and applied to another repository with the unbundle or pull
1171 command. This is useful when direct push and pull are not
1171 command. This is useful when direct push and pull are not
1172 available or when exporting an entire repository is undesirable.
1172 available or when exporting an entire repository is undesirable.
1173
1173
1174 Applying bundles preserves all changeset contents including
1174 Applying bundles preserves all changeset contents including
1175 permissions, copy/rename information, and revision history.
1175 permissions, copy/rename information, and revision history.
1176
1176
1177 Returns 0 on success, 1 if no changes found.
1177 Returns 0 on success, 1 if no changes found.
1178 """
1178 """
1179 revs = None
1179 revs = None
1180 if 'rev' in opts:
1180 if 'rev' in opts:
1181 revs = scmutil.revrange(repo, opts['rev'])
1181 revs = scmutil.revrange(repo, opts['rev'])
1182
1182
1183 bundletype = opts.get('type', 'bzip2').lower()
1183 bundletype = opts.get('type', 'bzip2').lower()
1184 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1184 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1185 bundletype = btypes.get(bundletype)
1185 bundletype = btypes.get(bundletype)
1186 if bundletype not in changegroup.bundletypes:
1186 if bundletype not in changegroup.bundletypes:
1187 raise util.Abort(_('unknown bundle type specified with --type'))
1187 raise util.Abort(_('unknown bundle type specified with --type'))
1188
1188
1189 if opts.get('all'):
1189 if opts.get('all'):
1190 base = ['null']
1190 base = ['null']
1191 else:
1191 else:
1192 base = scmutil.revrange(repo, opts.get('base'))
1192 base = scmutil.revrange(repo, opts.get('base'))
1193 # TODO: get desired bundlecaps from command line.
1193 # TODO: get desired bundlecaps from command line.
1194 bundlecaps = None
1194 bundlecaps = None
1195 if base:
1195 if base:
1196 if dest:
1196 if dest:
1197 raise util.Abort(_("--base is incompatible with specifying "
1197 raise util.Abort(_("--base is incompatible with specifying "
1198 "a destination"))
1198 "a destination"))
1199 common = [repo.lookup(rev) for rev in base]
1199 common = [repo.lookup(rev) for rev in base]
1200 heads = revs and map(repo.lookup, revs) or revs
1200 heads = revs and map(repo.lookup, revs) or revs
1201 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1201 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1202 common=common, bundlecaps=bundlecaps)
1202 common=common, bundlecaps=bundlecaps)
1203 outgoing = None
1203 outgoing = None
1204 else:
1204 else:
1205 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1205 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1206 dest, branches = hg.parseurl(dest, opts.get('branch'))
1206 dest, branches = hg.parseurl(dest, opts.get('branch'))
1207 other = hg.peer(repo, opts, dest)
1207 other = hg.peer(repo, opts, dest)
1208 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1208 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1209 heads = revs and map(repo.lookup, revs) or revs
1209 heads = revs and map(repo.lookup, revs) or revs
1210 outgoing = discovery.findcommonoutgoing(repo, other,
1210 outgoing = discovery.findcommonoutgoing(repo, other,
1211 onlyheads=heads,
1211 onlyheads=heads,
1212 force=opts.get('force'),
1212 force=opts.get('force'),
1213 portable=True)
1213 portable=True)
1214 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1214 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1215 bundlecaps)
1215 bundlecaps)
1216 if not cg:
1216 if not cg:
1217 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1217 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1218 return 1
1218 return 1
1219
1219
1220 changegroup.writebundle(cg, fname, bundletype)
1220 changegroup.writebundle(cg, fname, bundletype)
1221
1221
1222 @command('cat',
1222 @command('cat',
1223 [('o', 'output', '',
1223 [('o', 'output', '',
1224 _('print output to file with formatted name'), _('FORMAT')),
1224 _('print output to file with formatted name'), _('FORMAT')),
1225 ('r', 'rev', '', _('print the given revision'), _('REV')),
1225 ('r', 'rev', '', _('print the given revision'), _('REV')),
1226 ('', 'decode', None, _('apply any matching decode filter')),
1226 ('', 'decode', None, _('apply any matching decode filter')),
1227 ] + walkopts,
1227 ] + walkopts,
1228 _('[OPTION]... FILE...'),
1228 _('[OPTION]... FILE...'),
1229 inferrepo=True)
1229 inferrepo=True)
1230 def cat(ui, repo, file1, *pats, **opts):
1230 def cat(ui, repo, file1, *pats, **opts):
1231 """output the current or given revision of files
1231 """output the current or given revision of files
1232
1232
1233 Print the specified files as they were at the given revision. If
1233 Print the specified files as they were at the given revision. If
1234 no revision is given, the parent of the working directory is used.
1234 no revision is given, the parent of the working directory is used.
1235
1235
1236 Output may be to a file, in which case the name of the file is
1236 Output may be to a file, in which case the name of the file is
1237 given using a format string. The formatting rules as follows:
1237 given using a format string. The formatting rules as follows:
1238
1238
1239 :``%%``: literal "%" character
1239 :``%%``: literal "%" character
1240 :``%s``: basename of file being printed
1240 :``%s``: basename of file being printed
1241 :``%d``: dirname of file being printed, or '.' if in repository root
1241 :``%d``: dirname of file being printed, or '.' if in repository root
1242 :``%p``: root-relative path name of file being printed
1242 :``%p``: root-relative path name of file being printed
1243 :``%H``: changeset hash (40 hexadecimal digits)
1243 :``%H``: changeset hash (40 hexadecimal digits)
1244 :``%R``: changeset revision number
1244 :``%R``: changeset revision number
1245 :``%h``: short-form changeset hash (12 hexadecimal digits)
1245 :``%h``: short-form changeset hash (12 hexadecimal digits)
1246 :``%r``: zero-padded changeset revision number
1246 :``%r``: zero-padded changeset revision number
1247 :``%b``: basename of the exporting repository
1247 :``%b``: basename of the exporting repository
1248
1248
1249 Returns 0 on success.
1249 Returns 0 on success.
1250 """
1250 """
1251 ctx = scmutil.revsingle(repo, opts.get('rev'))
1251 ctx = scmutil.revsingle(repo, opts.get('rev'))
1252 m = scmutil.match(ctx, (file1,) + pats, opts)
1252 m = scmutil.match(ctx, (file1,) + pats, opts)
1253
1253
1254 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1254 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1255
1255
1256 @command('^clone',
1256 @command('^clone',
1257 [('U', 'noupdate', None,
1257 [('U', 'noupdate', None,
1258 _('the clone will include an empty working copy (only a repository)')),
1258 _('the clone will include an empty working copy (only a repository)')),
1259 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1259 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1260 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1260 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1261 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1261 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1262 ('', 'pull', None, _('use pull protocol to copy metadata')),
1262 ('', 'pull', None, _('use pull protocol to copy metadata')),
1263 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1263 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1264 ] + remoteopts,
1264 ] + remoteopts,
1265 _('[OPTION]... SOURCE [DEST]'),
1265 _('[OPTION]... SOURCE [DEST]'),
1266 norepo=True)
1266 norepo=True)
1267 def clone(ui, source, dest=None, **opts):
1267 def clone(ui, source, dest=None, **opts):
1268 """make a copy of an existing repository
1268 """make a copy of an existing repository
1269
1269
1270 Create a copy of an existing repository in a new directory.
1270 Create a copy of an existing repository in a new directory.
1271
1271
1272 If no destination directory name is specified, it defaults to the
1272 If no destination directory name is specified, it defaults to the
1273 basename of the source.
1273 basename of the source.
1274
1274
1275 The location of the source is added to the new repository's
1275 The location of the source is added to the new repository's
1276 ``.hg/hgrc`` file, as the default to be used for future pulls.
1276 ``.hg/hgrc`` file, as the default to be used for future pulls.
1277
1277
1278 Only local paths and ``ssh://`` URLs are supported as
1278 Only local paths and ``ssh://`` URLs are supported as
1279 destinations. For ``ssh://`` destinations, no working directory or
1279 destinations. For ``ssh://`` destinations, no working directory or
1280 ``.hg/hgrc`` will be created on the remote side.
1280 ``.hg/hgrc`` will be created on the remote side.
1281
1281
1282 To pull only a subset of changesets, specify one or more revisions
1282 To pull only a subset of changesets, specify one or more revisions
1283 identifiers with -r/--rev or branches with -b/--branch. The
1283 identifiers with -r/--rev or branches with -b/--branch. The
1284 resulting clone will contain only the specified changesets and
1284 resulting clone will contain only the specified changesets and
1285 their ancestors. These options (or 'clone src#rev dest') imply
1285 their ancestors. These options (or 'clone src#rev dest') imply
1286 --pull, even for local source repositories. Note that specifying a
1286 --pull, even for local source repositories. Note that specifying a
1287 tag will include the tagged changeset but not the changeset
1287 tag will include the tagged changeset but not the changeset
1288 containing the tag.
1288 containing the tag.
1289
1289
1290 If the source repository has a bookmark called '@' set, that
1290 If the source repository has a bookmark called '@' set, that
1291 revision will be checked out in the new repository by default.
1291 revision will be checked out in the new repository by default.
1292
1292
1293 To check out a particular version, use -u/--update, or
1293 To check out a particular version, use -u/--update, or
1294 -U/--noupdate to create a clone with no working directory.
1294 -U/--noupdate to create a clone with no working directory.
1295
1295
1296 .. container:: verbose
1296 .. container:: verbose
1297
1297
1298 For efficiency, hardlinks are used for cloning whenever the
1298 For efficiency, hardlinks are used for cloning whenever the
1299 source and destination are on the same filesystem (note this
1299 source and destination are on the same filesystem (note this
1300 applies only to the repository data, not to the working
1300 applies only to the repository data, not to the working
1301 directory). Some filesystems, such as AFS, implement hardlinking
1301 directory). Some filesystems, such as AFS, implement hardlinking
1302 incorrectly, but do not report errors. In these cases, use the
1302 incorrectly, but do not report errors. In these cases, use the
1303 --pull option to avoid hardlinking.
1303 --pull option to avoid hardlinking.
1304
1304
1305 In some cases, you can clone repositories and the working
1305 In some cases, you can clone repositories and the working
1306 directory using full hardlinks with ::
1306 directory using full hardlinks with ::
1307
1307
1308 $ cp -al REPO REPOCLONE
1308 $ cp -al REPO REPOCLONE
1309
1309
1310 This is the fastest way to clone, but it is not always safe. The
1310 This is the fastest way to clone, but it is not always safe. The
1311 operation is not atomic (making sure REPO is not modified during
1311 operation is not atomic (making sure REPO is not modified during
1312 the operation is up to you) and you have to make sure your
1312 the operation is up to you) and you have to make sure your
1313 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1313 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1314 so). Also, this is not compatible with certain extensions that
1314 so). Also, this is not compatible with certain extensions that
1315 place their metadata under the .hg directory, such as mq.
1315 place their metadata under the .hg directory, such as mq.
1316
1316
1317 Mercurial will update the working directory to the first applicable
1317 Mercurial will update the working directory to the first applicable
1318 revision from this list:
1318 revision from this list:
1319
1319
1320 a) null if -U or the source repository has no changesets
1320 a) null if -U or the source repository has no changesets
1321 b) if -u . and the source repository is local, the first parent of
1321 b) if -u . and the source repository is local, the first parent of
1322 the source repository's working directory
1322 the source repository's working directory
1323 c) the changeset specified with -u (if a branch name, this means the
1323 c) the changeset specified with -u (if a branch name, this means the
1324 latest head of that branch)
1324 latest head of that branch)
1325 d) the changeset specified with -r
1325 d) the changeset specified with -r
1326 e) the tipmost head specified with -b
1326 e) the tipmost head specified with -b
1327 f) the tipmost head specified with the url#branch source syntax
1327 f) the tipmost head specified with the url#branch source syntax
1328 g) the revision marked with the '@' bookmark, if present
1328 g) the revision marked with the '@' bookmark, if present
1329 h) the tipmost head of the default branch
1329 h) the tipmost head of the default branch
1330 i) tip
1330 i) tip
1331
1331
1332 Examples:
1332 Examples:
1333
1333
1334 - clone a remote repository to a new directory named hg/::
1334 - clone a remote repository to a new directory named hg/::
1335
1335
1336 hg clone http://selenic.com/hg
1336 hg clone http://selenic.com/hg
1337
1337
1338 - create a lightweight local clone::
1338 - create a lightweight local clone::
1339
1339
1340 hg clone project/ project-feature/
1340 hg clone project/ project-feature/
1341
1341
1342 - clone from an absolute path on an ssh server (note double-slash)::
1342 - clone from an absolute path on an ssh server (note double-slash)::
1343
1343
1344 hg clone ssh://user@server//home/projects/alpha/
1344 hg clone ssh://user@server//home/projects/alpha/
1345
1345
1346 - do a high-speed clone over a LAN while checking out a
1346 - do a high-speed clone over a LAN while checking out a
1347 specified version::
1347 specified version::
1348
1348
1349 hg clone --uncompressed http://server/repo -u 1.5
1349 hg clone --uncompressed http://server/repo -u 1.5
1350
1350
1351 - create a repository without changesets after a particular revision::
1351 - create a repository without changesets after a particular revision::
1352
1352
1353 hg clone -r 04e544 experimental/ good/
1353 hg clone -r 04e544 experimental/ good/
1354
1354
1355 - clone (and track) a particular named branch::
1355 - clone (and track) a particular named branch::
1356
1356
1357 hg clone http://selenic.com/hg#stable
1357 hg clone http://selenic.com/hg#stable
1358
1358
1359 See :hg:`help urls` for details on specifying URLs.
1359 See :hg:`help urls` for details on specifying URLs.
1360
1360
1361 Returns 0 on success.
1361 Returns 0 on success.
1362 """
1362 """
1363 if opts.get('noupdate') and opts.get('updaterev'):
1363 if opts.get('noupdate') and opts.get('updaterev'):
1364 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1364 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1365
1365
1366 r = hg.clone(ui, opts, source, dest,
1366 r = hg.clone(ui, opts, source, dest,
1367 pull=opts.get('pull'),
1367 pull=opts.get('pull'),
1368 stream=opts.get('uncompressed'),
1368 stream=opts.get('uncompressed'),
1369 rev=opts.get('rev'),
1369 rev=opts.get('rev'),
1370 update=opts.get('updaterev') or not opts.get('noupdate'),
1370 update=opts.get('updaterev') or not opts.get('noupdate'),
1371 branch=opts.get('branch'))
1371 branch=opts.get('branch'))
1372
1372
1373 return r is None
1373 return r is None
1374
1374
1375 @command('^commit|ci',
1375 @command('^commit|ci',
1376 [('A', 'addremove', None,
1376 [('A', 'addremove', None,
1377 _('mark new/missing files as added/removed before committing')),
1377 _('mark new/missing files as added/removed before committing')),
1378 ('', 'close-branch', None,
1378 ('', 'close-branch', None,
1379 _('mark a branch as closed, hiding it from the branch list')),
1379 _('mark a branch as closed, hiding it from the branch list')),
1380 ('', 'amend', None, _('amend the parent of the working dir')),
1380 ('', 'amend', None, _('amend the parent of the working dir')),
1381 ('s', 'secret', None, _('use the secret phase for committing')),
1381 ('s', 'secret', None, _('use the secret phase for committing')),
1382 ('e', 'edit', None, _('invoke editor on commit messages')),
1382 ('e', 'edit', None, _('invoke editor on commit messages')),
1383 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1383 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1384 _('[OPTION]... [FILE]...'),
1384 _('[OPTION]... [FILE]...'),
1385 inferrepo=True)
1385 inferrepo=True)
1386 def commit(ui, repo, *pats, **opts):
1386 def commit(ui, repo, *pats, **opts):
1387 """commit the specified files or all outstanding changes
1387 """commit the specified files or all outstanding changes
1388
1388
1389 Commit changes to the given files into the repository. Unlike a
1389 Commit changes to the given files into the repository. Unlike a
1390 centralized SCM, this operation is a local operation. See
1390 centralized SCM, this operation is a local operation. See
1391 :hg:`push` for a way to actively distribute your changes.
1391 :hg:`push` for a way to actively distribute your changes.
1392
1392
1393 If a list of files is omitted, all changes reported by :hg:`status`
1393 If a list of files is omitted, all changes reported by :hg:`status`
1394 will be committed.
1394 will be committed.
1395
1395
1396 If you are committing the result of a merge, do not provide any
1396 If you are committing the result of a merge, do not provide any
1397 filenames or -I/-X filters.
1397 filenames or -I/-X filters.
1398
1398
1399 If no commit message is specified, Mercurial starts your
1399 If no commit message is specified, Mercurial starts your
1400 configured editor where you can enter a message. In case your
1400 configured editor where you can enter a message. In case your
1401 commit fails, you will find a backup of your message in
1401 commit fails, you will find a backup of your message in
1402 ``.hg/last-message.txt``.
1402 ``.hg/last-message.txt``.
1403
1403
1404 The --amend flag can be used to amend the parent of the
1404 The --amend flag can be used to amend the parent of the
1405 working directory with a new commit that contains the changes
1405 working directory with a new commit that contains the changes
1406 in the parent in addition to those currently reported by :hg:`status`,
1406 in the parent in addition to those currently reported by :hg:`status`,
1407 if there are any. The old commit is stored in a backup bundle in
1407 if there are any. The old commit is stored in a backup bundle in
1408 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1408 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1409 on how to restore it).
1409 on how to restore it).
1410
1410
1411 Message, user and date are taken from the amended commit unless
1411 Message, user and date are taken from the amended commit unless
1412 specified. When a message isn't specified on the command line,
1412 specified. When a message isn't specified on the command line,
1413 the editor will open with the message of the amended commit.
1413 the editor will open with the message of the amended commit.
1414
1414
1415 It is not possible to amend public changesets (see :hg:`help phases`)
1415 It is not possible to amend public changesets (see :hg:`help phases`)
1416 or changesets that have children.
1416 or changesets that have children.
1417
1417
1418 See :hg:`help dates` for a list of formats valid for -d/--date.
1418 See :hg:`help dates` for a list of formats valid for -d/--date.
1419
1419
1420 Returns 0 on success, 1 if nothing changed.
1420 Returns 0 on success, 1 if nothing changed.
1421 """
1421 """
1422 if opts.get('subrepos'):
1422 if opts.get('subrepos'):
1423 if opts.get('amend'):
1423 if opts.get('amend'):
1424 raise util.Abort(_('cannot amend with --subrepos'))
1424 raise util.Abort(_('cannot amend with --subrepos'))
1425 # Let --subrepos on the command line override config setting.
1425 # Let --subrepos on the command line override config setting.
1426 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1426 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1427
1427
1428 cmdutil.checkunfinished(repo, commit=True)
1428 cmdutil.checkunfinished(repo, commit=True)
1429
1429
1430 branch = repo[None].branch()
1430 branch = repo[None].branch()
1431 bheads = repo.branchheads(branch)
1431 bheads = repo.branchheads(branch)
1432
1432
1433 extra = {}
1433 extra = {}
1434 if opts.get('close_branch'):
1434 if opts.get('close_branch'):
1435 extra['close'] = 1
1435 extra['close'] = 1
1436
1436
1437 if not bheads:
1437 if not bheads:
1438 raise util.Abort(_('can only close branch heads'))
1438 raise util.Abort(_('can only close branch heads'))
1439 elif opts.get('amend'):
1439 elif opts.get('amend'):
1440 if repo.parents()[0].p1().branch() != branch and \
1440 if repo.parents()[0].p1().branch() != branch and \
1441 repo.parents()[0].p2().branch() != branch:
1441 repo.parents()[0].p2().branch() != branch:
1442 raise util.Abort(_('can only close branch heads'))
1442 raise util.Abort(_('can only close branch heads'))
1443
1443
1444 if opts.get('amend'):
1444 if opts.get('amend'):
1445 if ui.configbool('ui', 'commitsubrepos'):
1445 if ui.configbool('ui', 'commitsubrepos'):
1446 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1446 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1447
1447
1448 old = repo['.']
1448 old = repo['.']
1449 if not old.mutable():
1449 if not old.mutable():
1450 raise util.Abort(_('cannot amend public changesets'))
1450 raise util.Abort(_('cannot amend public changesets'))
1451 if len(repo[None].parents()) > 1:
1451 if len(repo[None].parents()) > 1:
1452 raise util.Abort(_('cannot amend while merging'))
1452 raise util.Abort(_('cannot amend while merging'))
1453 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1453 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1454 if not allowunstable and old.children():
1454 if not allowunstable and old.children():
1455 raise util.Abort(_('cannot amend changeset with children'))
1455 raise util.Abort(_('cannot amend changeset with children'))
1456
1456
1457 # commitfunc is used only for temporary amend commit by cmdutil.amend
1457 # commitfunc is used only for temporary amend commit by cmdutil.amend
1458 def commitfunc(ui, repo, message, match, opts):
1458 def commitfunc(ui, repo, message, match, opts):
1459 return repo.commit(message,
1459 return repo.commit(message,
1460 opts.get('user') or old.user(),
1460 opts.get('user') or old.user(),
1461 opts.get('date') or old.date(),
1461 opts.get('date') or old.date(),
1462 match,
1462 match,
1463 extra=extra)
1463 extra=extra)
1464
1464
1465 current = repo._bookmarkcurrent
1465 current = repo._bookmarkcurrent
1466 marks = old.bookmarks()
1466 marks = old.bookmarks()
1467 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1467 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1468 if node == old.node():
1468 if node == old.node():
1469 ui.status(_("nothing changed\n"))
1469 ui.status(_("nothing changed\n"))
1470 return 1
1470 return 1
1471 elif marks:
1471 elif marks:
1472 ui.debug('moving bookmarks %r from %s to %s\n' %
1472 ui.debug('moving bookmarks %r from %s to %s\n' %
1473 (marks, old.hex(), hex(node)))
1473 (marks, old.hex(), hex(node)))
1474 newmarks = repo._bookmarks
1474 newmarks = repo._bookmarks
1475 for bm in marks:
1475 for bm in marks:
1476 newmarks[bm] = node
1476 newmarks[bm] = node
1477 if bm == current:
1477 if bm == current:
1478 bookmarks.setcurrent(repo, bm)
1478 bookmarks.setcurrent(repo, bm)
1479 newmarks.write()
1479 newmarks.write()
1480 else:
1480 else:
1481 def commitfunc(ui, repo, message, match, opts):
1481 def commitfunc(ui, repo, message, match, opts):
1482 backup = ui.backupconfig('phases', 'new-commit')
1482 backup = ui.backupconfig('phases', 'new-commit')
1483 baseui = repo.baseui
1483 baseui = repo.baseui
1484 basebackup = baseui.backupconfig('phases', 'new-commit')
1484 basebackup = baseui.backupconfig('phases', 'new-commit')
1485 try:
1485 try:
1486 if opts.get('secret'):
1486 if opts.get('secret'):
1487 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1487 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1488 # Propagate to subrepos
1488 # Propagate to subrepos
1489 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1489 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1490
1490
1491 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1491 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1492 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1492 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1493 return repo.commit(message, opts.get('user'), opts.get('date'),
1493 return repo.commit(message, opts.get('user'), opts.get('date'),
1494 match,
1494 match,
1495 editor=editor,
1495 editor=editor,
1496 extra=extra)
1496 extra=extra)
1497 finally:
1497 finally:
1498 ui.restoreconfig(backup)
1498 ui.restoreconfig(backup)
1499 repo.baseui.restoreconfig(basebackup)
1499 repo.baseui.restoreconfig(basebackup)
1500
1500
1501
1501
1502 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1502 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1503
1503
1504 if not node:
1504 if not node:
1505 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1505 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1506 if stat[3]:
1506 if stat[3]:
1507 ui.status(_("nothing changed (%d missing files, see "
1507 ui.status(_("nothing changed (%d missing files, see "
1508 "'hg status')\n") % len(stat[3]))
1508 "'hg status')\n") % len(stat[3]))
1509 else:
1509 else:
1510 ui.status(_("nothing changed\n"))
1510 ui.status(_("nothing changed\n"))
1511 return 1
1511 return 1
1512
1512
1513 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1513 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1514
1514
1515 @command('config|showconfig|debugconfig',
1515 @command('config|showconfig|debugconfig',
1516 [('u', 'untrusted', None, _('show untrusted configuration options')),
1516 [('u', 'untrusted', None, _('show untrusted configuration options')),
1517 ('e', 'edit', None, _('edit user config')),
1517 ('e', 'edit', None, _('edit user config')),
1518 ('l', 'local', None, _('edit repository config')),
1518 ('l', 'local', None, _('edit repository config')),
1519 ('g', 'global', None, _('edit global config'))],
1519 ('g', 'global', None, _('edit global config'))],
1520 _('[-u] [NAME]...'),
1520 _('[-u] [NAME]...'),
1521 optionalrepo=True)
1521 optionalrepo=True)
1522 def config(ui, repo, *values, **opts):
1522 def config(ui, repo, *values, **opts):
1523 """show combined config settings from all hgrc files
1523 """show combined config settings from all hgrc files
1524
1524
1525 With no arguments, print names and values of all config items.
1525 With no arguments, print names and values of all config items.
1526
1526
1527 With one argument of the form section.name, print just the value
1527 With one argument of the form section.name, print just the value
1528 of that config item.
1528 of that config item.
1529
1529
1530 With multiple arguments, print names and values of all config
1530 With multiple arguments, print names and values of all config
1531 items with matching section names.
1531 items with matching section names.
1532
1532
1533 With --edit, start an editor on the user-level config file. With
1533 With --edit, start an editor on the user-level config file. With
1534 --global, edit the system-wide config file. With --local, edit the
1534 --global, edit the system-wide config file. With --local, edit the
1535 repository-level config file.
1535 repository-level config file.
1536
1536
1537 With --debug, the source (filename and line number) is printed
1537 With --debug, the source (filename and line number) is printed
1538 for each config item.
1538 for each config item.
1539
1539
1540 See :hg:`help config` for more information about config files.
1540 See :hg:`help config` for more information about config files.
1541
1541
1542 Returns 0 on success, 1 if NAME does not exist.
1542 Returns 0 on success, 1 if NAME does not exist.
1543
1543
1544 """
1544 """
1545
1545
1546 if opts.get('edit') or opts.get('local') or opts.get('global'):
1546 if opts.get('edit') or opts.get('local') or opts.get('global'):
1547 if opts.get('local') and opts.get('global'):
1547 if opts.get('local') and opts.get('global'):
1548 raise util.Abort(_("can't use --local and --global together"))
1548 raise util.Abort(_("can't use --local and --global together"))
1549
1549
1550 if opts.get('local'):
1550 if opts.get('local'):
1551 if not repo:
1551 if not repo:
1552 raise util.Abort(_("can't use --local outside a repository"))
1552 raise util.Abort(_("can't use --local outside a repository"))
1553 paths = [repo.join('hgrc')]
1553 paths = [repo.join('hgrc')]
1554 elif opts.get('global'):
1554 elif opts.get('global'):
1555 paths = scmutil.systemrcpath()
1555 paths = scmutil.systemrcpath()
1556 else:
1556 else:
1557 paths = scmutil.userrcpath()
1557 paths = scmutil.userrcpath()
1558
1558
1559 for f in paths:
1559 for f in paths:
1560 if os.path.exists(f):
1560 if os.path.exists(f):
1561 break
1561 break
1562 else:
1562 else:
1563 if opts.get('global'):
1563 if opts.get('global'):
1564 samplehgrc = uimod.samplehgrcs['global']
1564 samplehgrc = uimod.samplehgrcs['global']
1565 elif opts.get('local'):
1565 elif opts.get('local'):
1566 samplehgrc = uimod.samplehgrcs['local']
1566 samplehgrc = uimod.samplehgrcs['local']
1567 else:
1567 else:
1568 samplehgrc = uimod.samplehgrcs['user']
1568 samplehgrc = uimod.samplehgrcs['user']
1569
1569
1570 f = paths[0]
1570 f = paths[0]
1571 fp = open(f, "w")
1571 fp = open(f, "w")
1572 fp.write(samplehgrc)
1572 fp.write(samplehgrc)
1573 fp.close()
1573 fp.close()
1574
1574
1575 editor = ui.geteditor()
1575 editor = ui.geteditor()
1576 ui.system("%s \"%s\"" % (editor, f),
1576 ui.system("%s \"%s\"" % (editor, f),
1577 onerr=util.Abort, errprefix=_("edit failed"))
1577 onerr=util.Abort, errprefix=_("edit failed"))
1578 return
1578 return
1579
1579
1580 for f in scmutil.rcpath():
1580 for f in scmutil.rcpath():
1581 ui.debug('read config from: %s\n' % f)
1581 ui.debug('read config from: %s\n' % f)
1582 untrusted = bool(opts.get('untrusted'))
1582 untrusted = bool(opts.get('untrusted'))
1583 if values:
1583 if values:
1584 sections = [v for v in values if '.' not in v]
1584 sections = [v for v in values if '.' not in v]
1585 items = [v for v in values if '.' in v]
1585 items = [v for v in values if '.' in v]
1586 if len(items) > 1 or items and sections:
1586 if len(items) > 1 or items and sections:
1587 raise util.Abort(_('only one config item permitted'))
1587 raise util.Abort(_('only one config item permitted'))
1588 matched = False
1588 matched = False
1589 for section, name, value in ui.walkconfig(untrusted=untrusted):
1589 for section, name, value in ui.walkconfig(untrusted=untrusted):
1590 value = str(value).replace('\n', '\\n')
1590 value = str(value).replace('\n', '\\n')
1591 sectname = section + '.' + name
1591 sectname = section + '.' + name
1592 if values:
1592 if values:
1593 for v in values:
1593 for v in values:
1594 if v == section:
1594 if v == section:
1595 ui.debug('%s: ' %
1595 ui.debug('%s: ' %
1596 ui.configsource(section, name, untrusted))
1596 ui.configsource(section, name, untrusted))
1597 ui.write('%s=%s\n' % (sectname, value))
1597 ui.write('%s=%s\n' % (sectname, value))
1598 matched = True
1598 matched = True
1599 elif v == sectname:
1599 elif v == sectname:
1600 ui.debug('%s: ' %
1600 ui.debug('%s: ' %
1601 ui.configsource(section, name, untrusted))
1601 ui.configsource(section, name, untrusted))
1602 ui.write(value, '\n')
1602 ui.write(value, '\n')
1603 matched = True
1603 matched = True
1604 else:
1604 else:
1605 ui.debug('%s: ' %
1605 ui.debug('%s: ' %
1606 ui.configsource(section, name, untrusted))
1606 ui.configsource(section, name, untrusted))
1607 ui.write('%s=%s\n' % (sectname, value))
1607 ui.write('%s=%s\n' % (sectname, value))
1608 matched = True
1608 matched = True
1609 if matched:
1609 if matched:
1610 return 0
1610 return 0
1611 return 1
1611 return 1
1612
1612
1613 @command('copy|cp',
1613 @command('copy|cp',
1614 [('A', 'after', None, _('record a copy that has already occurred')),
1614 [('A', 'after', None, _('record a copy that has already occurred')),
1615 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1615 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1616 ] + walkopts + dryrunopts,
1616 ] + walkopts + dryrunopts,
1617 _('[OPTION]... [SOURCE]... DEST'))
1617 _('[OPTION]... [SOURCE]... DEST'))
1618 def copy(ui, repo, *pats, **opts):
1618 def copy(ui, repo, *pats, **opts):
1619 """mark files as copied for the next commit
1619 """mark files as copied for the next commit
1620
1620
1621 Mark dest as having copies of source files. If dest is a
1621 Mark dest as having copies of source files. If dest is a
1622 directory, copies are put in that directory. If dest is a file,
1622 directory, copies are put in that directory. If dest is a file,
1623 the source must be a single file.
1623 the source must be a single file.
1624
1624
1625 By default, this command copies the contents of files as they
1625 By default, this command copies the contents of files as they
1626 exist in the working directory. If invoked with -A/--after, the
1626 exist in the working directory. If invoked with -A/--after, the
1627 operation is recorded, but no copying is performed.
1627 operation is recorded, but no copying is performed.
1628
1628
1629 This command takes effect with the next commit. To undo a copy
1629 This command takes effect with the next commit. To undo a copy
1630 before that, see :hg:`revert`.
1630 before that, see :hg:`revert`.
1631
1631
1632 Returns 0 on success, 1 if errors are encountered.
1632 Returns 0 on success, 1 if errors are encountered.
1633 """
1633 """
1634 wlock = repo.wlock(False)
1634 wlock = repo.wlock(False)
1635 try:
1635 try:
1636 return cmdutil.copy(ui, repo, pats, opts)
1636 return cmdutil.copy(ui, repo, pats, opts)
1637 finally:
1637 finally:
1638 wlock.release()
1638 wlock.release()
1639
1639
1640 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1640 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1641 def debugancestor(ui, repo, *args):
1641 def debugancestor(ui, repo, *args):
1642 """find the ancestor revision of two revisions in a given index"""
1642 """find the ancestor revision of two revisions in a given index"""
1643 if len(args) == 3:
1643 if len(args) == 3:
1644 index, rev1, rev2 = args
1644 index, rev1, rev2 = args
1645 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1645 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1646 lookup = r.lookup
1646 lookup = r.lookup
1647 elif len(args) == 2:
1647 elif len(args) == 2:
1648 if not repo:
1648 if not repo:
1649 raise util.Abort(_("there is no Mercurial repository here "
1649 raise util.Abort(_("there is no Mercurial repository here "
1650 "(.hg not found)"))
1650 "(.hg not found)"))
1651 rev1, rev2 = args
1651 rev1, rev2 = args
1652 r = repo.changelog
1652 r = repo.changelog
1653 lookup = repo.lookup
1653 lookup = repo.lookup
1654 else:
1654 else:
1655 raise util.Abort(_('either two or three arguments required'))
1655 raise util.Abort(_('either two or three arguments required'))
1656 a = r.ancestor(lookup(rev1), lookup(rev2))
1656 a = r.ancestor(lookup(rev1), lookup(rev2))
1657 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1657 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1658
1658
1659 @command('debugbuilddag',
1659 @command('debugbuilddag',
1660 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1660 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1661 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1661 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1662 ('n', 'new-file', None, _('add new file at each rev'))],
1662 ('n', 'new-file', None, _('add new file at each rev'))],
1663 _('[OPTION]... [TEXT]'))
1663 _('[OPTION]... [TEXT]'))
1664 def debugbuilddag(ui, repo, text=None,
1664 def debugbuilddag(ui, repo, text=None,
1665 mergeable_file=False,
1665 mergeable_file=False,
1666 overwritten_file=False,
1666 overwritten_file=False,
1667 new_file=False):
1667 new_file=False):
1668 """builds a repo with a given DAG from scratch in the current empty repo
1668 """builds a repo with a given DAG from scratch in the current empty repo
1669
1669
1670 The description of the DAG is read from stdin if not given on the
1670 The description of the DAG is read from stdin if not given on the
1671 command line.
1671 command line.
1672
1672
1673 Elements:
1673 Elements:
1674
1674
1675 - "+n" is a linear run of n nodes based on the current default parent
1675 - "+n" is a linear run of n nodes based on the current default parent
1676 - "." is a single node based on the current default parent
1676 - "." is a single node based on the current default parent
1677 - "$" resets the default parent to null (implied at the start);
1677 - "$" resets the default parent to null (implied at the start);
1678 otherwise the default parent is always the last node created
1678 otherwise the default parent is always the last node created
1679 - "<p" sets the default parent to the backref p
1679 - "<p" sets the default parent to the backref p
1680 - "*p" is a fork at parent p, which is a backref
1680 - "*p" is a fork at parent p, which is a backref
1681 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1681 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1682 - "/p2" is a merge of the preceding node and p2
1682 - "/p2" is a merge of the preceding node and p2
1683 - ":tag" defines a local tag for the preceding node
1683 - ":tag" defines a local tag for the preceding node
1684 - "@branch" sets the named branch for subsequent nodes
1684 - "@branch" sets the named branch for subsequent nodes
1685 - "#...\\n" is a comment up to the end of the line
1685 - "#...\\n" is a comment up to the end of the line
1686
1686
1687 Whitespace between the above elements is ignored.
1687 Whitespace between the above elements is ignored.
1688
1688
1689 A backref is either
1689 A backref is either
1690
1690
1691 - a number n, which references the node curr-n, where curr is the current
1691 - a number n, which references the node curr-n, where curr is the current
1692 node, or
1692 node, or
1693 - the name of a local tag you placed earlier using ":tag", or
1693 - the name of a local tag you placed earlier using ":tag", or
1694 - empty to denote the default parent.
1694 - empty to denote the default parent.
1695
1695
1696 All string valued-elements are either strictly alphanumeric, or must
1696 All string valued-elements are either strictly alphanumeric, or must
1697 be enclosed in double quotes ("..."), with "\\" as escape character.
1697 be enclosed in double quotes ("..."), with "\\" as escape character.
1698 """
1698 """
1699
1699
1700 if text is None:
1700 if text is None:
1701 ui.status(_("reading DAG from stdin\n"))
1701 ui.status(_("reading DAG from stdin\n"))
1702 text = ui.fin.read()
1702 text = ui.fin.read()
1703
1703
1704 cl = repo.changelog
1704 cl = repo.changelog
1705 if len(cl) > 0:
1705 if len(cl) > 0:
1706 raise util.Abort(_('repository is not empty'))
1706 raise util.Abort(_('repository is not empty'))
1707
1707
1708 # determine number of revs in DAG
1708 # determine number of revs in DAG
1709 total = 0
1709 total = 0
1710 for type, data in dagparser.parsedag(text):
1710 for type, data in dagparser.parsedag(text):
1711 if type == 'n':
1711 if type == 'n':
1712 total += 1
1712 total += 1
1713
1713
1714 if mergeable_file:
1714 if mergeable_file:
1715 linesperrev = 2
1715 linesperrev = 2
1716 # make a file with k lines per rev
1716 # make a file with k lines per rev
1717 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1717 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1718 initialmergedlines.append("")
1718 initialmergedlines.append("")
1719
1719
1720 tags = []
1720 tags = []
1721
1721
1722 lock = tr = None
1722 lock = tr = None
1723 try:
1723 try:
1724 lock = repo.lock()
1724 lock = repo.lock()
1725 tr = repo.transaction("builddag")
1725 tr = repo.transaction("builddag")
1726
1726
1727 at = -1
1727 at = -1
1728 atbranch = 'default'
1728 atbranch = 'default'
1729 nodeids = []
1729 nodeids = []
1730 id = 0
1730 id = 0
1731 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1731 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1732 for type, data in dagparser.parsedag(text):
1732 for type, data in dagparser.parsedag(text):
1733 if type == 'n':
1733 if type == 'n':
1734 ui.note(('node %s\n' % str(data)))
1734 ui.note(('node %s\n' % str(data)))
1735 id, ps = data
1735 id, ps = data
1736
1736
1737 files = []
1737 files = []
1738 fctxs = {}
1738 fctxs = {}
1739
1739
1740 p2 = None
1740 p2 = None
1741 if mergeable_file:
1741 if mergeable_file:
1742 fn = "mf"
1742 fn = "mf"
1743 p1 = repo[ps[0]]
1743 p1 = repo[ps[0]]
1744 if len(ps) > 1:
1744 if len(ps) > 1:
1745 p2 = repo[ps[1]]
1745 p2 = repo[ps[1]]
1746 pa = p1.ancestor(p2)
1746 pa = p1.ancestor(p2)
1747 base, local, other = [x[fn].data() for x in (pa, p1,
1747 base, local, other = [x[fn].data() for x in (pa, p1,
1748 p2)]
1748 p2)]
1749 m3 = simplemerge.Merge3Text(base, local, other)
1749 m3 = simplemerge.Merge3Text(base, local, other)
1750 ml = [l.strip() for l in m3.merge_lines()]
1750 ml = [l.strip() for l in m3.merge_lines()]
1751 ml.append("")
1751 ml.append("")
1752 elif at > 0:
1752 elif at > 0:
1753 ml = p1[fn].data().split("\n")
1753 ml = p1[fn].data().split("\n")
1754 else:
1754 else:
1755 ml = initialmergedlines
1755 ml = initialmergedlines
1756 ml[id * linesperrev] += " r%i" % id
1756 ml[id * linesperrev] += " r%i" % id
1757 mergedtext = "\n".join(ml)
1757 mergedtext = "\n".join(ml)
1758 files.append(fn)
1758 files.append(fn)
1759 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1759 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1760
1760
1761 if overwritten_file:
1761 if overwritten_file:
1762 fn = "of"
1762 fn = "of"
1763 files.append(fn)
1763 files.append(fn)
1764 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1764 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1765
1765
1766 if new_file:
1766 if new_file:
1767 fn = "nf%i" % id
1767 fn = "nf%i" % id
1768 files.append(fn)
1768 files.append(fn)
1769 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1769 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1770 if len(ps) > 1:
1770 if len(ps) > 1:
1771 if not p2:
1771 if not p2:
1772 p2 = repo[ps[1]]
1772 p2 = repo[ps[1]]
1773 for fn in p2:
1773 for fn in p2:
1774 if fn.startswith("nf"):
1774 if fn.startswith("nf"):
1775 files.append(fn)
1775 files.append(fn)
1776 fctxs[fn] = p2[fn]
1776 fctxs[fn] = p2[fn]
1777
1777
1778 def fctxfn(repo, cx, path):
1778 def fctxfn(repo, cx, path):
1779 return fctxs.get(path)
1779 return fctxs.get(path)
1780
1780
1781 if len(ps) == 0 or ps[0] < 0:
1781 if len(ps) == 0 or ps[0] < 0:
1782 pars = [None, None]
1782 pars = [None, None]
1783 elif len(ps) == 1:
1783 elif len(ps) == 1:
1784 pars = [nodeids[ps[0]], None]
1784 pars = [nodeids[ps[0]], None]
1785 else:
1785 else:
1786 pars = [nodeids[p] for p in ps]
1786 pars = [nodeids[p] for p in ps]
1787 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1787 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1788 date=(id, 0),
1788 date=(id, 0),
1789 user="debugbuilddag",
1789 user="debugbuilddag",
1790 extra={'branch': atbranch})
1790 extra={'branch': atbranch})
1791 nodeid = repo.commitctx(cx)
1791 nodeid = repo.commitctx(cx)
1792 nodeids.append(nodeid)
1792 nodeids.append(nodeid)
1793 at = id
1793 at = id
1794 elif type == 'l':
1794 elif type == 'l':
1795 id, name = data
1795 id, name = data
1796 ui.note(('tag %s\n' % name))
1796 ui.note(('tag %s\n' % name))
1797 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1797 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1798 elif type == 'a':
1798 elif type == 'a':
1799 ui.note(('branch %s\n' % data))
1799 ui.note(('branch %s\n' % data))
1800 atbranch = data
1800 atbranch = data
1801 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1801 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1802 tr.close()
1802 tr.close()
1803
1803
1804 if tags:
1804 if tags:
1805 repo.opener.write("localtags", "".join(tags))
1805 repo.opener.write("localtags", "".join(tags))
1806 finally:
1806 finally:
1807 ui.progress(_('building'), None)
1807 ui.progress(_('building'), None)
1808 release(tr, lock)
1808 release(tr, lock)
1809
1809
1810 @command('debugbundle',
1810 @command('debugbundle',
1811 [('a', 'all', None, _('show all details'))],
1811 [('a', 'all', None, _('show all details'))],
1812 _('FILE'),
1812 _('FILE'),
1813 norepo=True)
1813 norepo=True)
1814 def debugbundle(ui, bundlepath, all=None, **opts):
1814 def debugbundle(ui, bundlepath, all=None, **opts):
1815 """lists the contents of a bundle"""
1815 """lists the contents of a bundle"""
1816 f = hg.openpath(ui, bundlepath)
1816 f = hg.openpath(ui, bundlepath)
1817 try:
1817 try:
1818 gen = exchange.readbundle(ui, f, bundlepath)
1818 gen = exchange.readbundle(ui, f, bundlepath)
1819 if all:
1819 if all:
1820 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1820 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1821
1821
1822 def showchunks(named):
1822 def showchunks(named):
1823 ui.write("\n%s\n" % named)
1823 ui.write("\n%s\n" % named)
1824 chain = None
1824 chain = None
1825 while True:
1825 while True:
1826 chunkdata = gen.deltachunk(chain)
1826 chunkdata = gen.deltachunk(chain)
1827 if not chunkdata:
1827 if not chunkdata:
1828 break
1828 break
1829 node = chunkdata['node']
1829 node = chunkdata['node']
1830 p1 = chunkdata['p1']
1830 p1 = chunkdata['p1']
1831 p2 = chunkdata['p2']
1831 p2 = chunkdata['p2']
1832 cs = chunkdata['cs']
1832 cs = chunkdata['cs']
1833 deltabase = chunkdata['deltabase']
1833 deltabase = chunkdata['deltabase']
1834 delta = chunkdata['delta']
1834 delta = chunkdata['delta']
1835 ui.write("%s %s %s %s %s %s\n" %
1835 ui.write("%s %s %s %s %s %s\n" %
1836 (hex(node), hex(p1), hex(p2),
1836 (hex(node), hex(p1), hex(p2),
1837 hex(cs), hex(deltabase), len(delta)))
1837 hex(cs), hex(deltabase), len(delta)))
1838 chain = node
1838 chain = node
1839
1839
1840 chunkdata = gen.changelogheader()
1840 chunkdata = gen.changelogheader()
1841 showchunks("changelog")
1841 showchunks("changelog")
1842 chunkdata = gen.manifestheader()
1842 chunkdata = gen.manifestheader()
1843 showchunks("manifest")
1843 showchunks("manifest")
1844 while True:
1844 while True:
1845 chunkdata = gen.filelogheader()
1845 chunkdata = gen.filelogheader()
1846 if not chunkdata:
1846 if not chunkdata:
1847 break
1847 break
1848 fname = chunkdata['filename']
1848 fname = chunkdata['filename']
1849 showchunks(fname)
1849 showchunks(fname)
1850 else:
1850 else:
1851 chunkdata = gen.changelogheader()
1851 chunkdata = gen.changelogheader()
1852 chain = None
1852 chain = None
1853 while True:
1853 while True:
1854 chunkdata = gen.deltachunk(chain)
1854 chunkdata = gen.deltachunk(chain)
1855 if not chunkdata:
1855 if not chunkdata:
1856 break
1856 break
1857 node = chunkdata['node']
1857 node = chunkdata['node']
1858 ui.write("%s\n" % hex(node))
1858 ui.write("%s\n" % hex(node))
1859 chain = node
1859 chain = node
1860 finally:
1860 finally:
1861 f.close()
1861 f.close()
1862
1862
1863 @command('debugcheckstate', [], '')
1863 @command('debugcheckstate', [], '')
1864 def debugcheckstate(ui, repo):
1864 def debugcheckstate(ui, repo):
1865 """validate the correctness of the current dirstate"""
1865 """validate the correctness of the current dirstate"""
1866 parent1, parent2 = repo.dirstate.parents()
1866 parent1, parent2 = repo.dirstate.parents()
1867 m1 = repo[parent1].manifest()
1867 m1 = repo[parent1].manifest()
1868 m2 = repo[parent2].manifest()
1868 m2 = repo[parent2].manifest()
1869 errors = 0
1869 errors = 0
1870 for f in repo.dirstate:
1870 for f in repo.dirstate:
1871 state = repo.dirstate[f]
1871 state = repo.dirstate[f]
1872 if state in "nr" and f not in m1:
1872 if state in "nr" and f not in m1:
1873 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1873 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1874 errors += 1
1874 errors += 1
1875 if state in "a" and f in m1:
1875 if state in "a" and f in m1:
1876 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1876 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1877 errors += 1
1877 errors += 1
1878 if state in "m" and f not in m1 and f not in m2:
1878 if state in "m" and f not in m1 and f not in m2:
1879 ui.warn(_("%s in state %s, but not in either manifest\n") %
1879 ui.warn(_("%s in state %s, but not in either manifest\n") %
1880 (f, state))
1880 (f, state))
1881 errors += 1
1881 errors += 1
1882 for f in m1:
1882 for f in m1:
1883 state = repo.dirstate[f]
1883 state = repo.dirstate[f]
1884 if state not in "nrm":
1884 if state not in "nrm":
1885 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1885 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1886 errors += 1
1886 errors += 1
1887 if errors:
1887 if errors:
1888 error = _(".hg/dirstate inconsistent with current parent's manifest")
1888 error = _(".hg/dirstate inconsistent with current parent's manifest")
1889 raise util.Abort(error)
1889 raise util.Abort(error)
1890
1890
1891 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1891 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1892 def debugcommands(ui, cmd='', *args):
1892 def debugcommands(ui, cmd='', *args):
1893 """list all available commands and options"""
1893 """list all available commands and options"""
1894 for cmd, vals in sorted(table.iteritems()):
1894 for cmd, vals in sorted(table.iteritems()):
1895 cmd = cmd.split('|')[0].strip('^')
1895 cmd = cmd.split('|')[0].strip('^')
1896 opts = ', '.join([i[1] for i in vals[1]])
1896 opts = ', '.join([i[1] for i in vals[1]])
1897 ui.write('%s: %s\n' % (cmd, opts))
1897 ui.write('%s: %s\n' % (cmd, opts))
1898
1898
1899 @command('debugcomplete',
1899 @command('debugcomplete',
1900 [('o', 'options', None, _('show the command options'))],
1900 [('o', 'options', None, _('show the command options'))],
1901 _('[-o] CMD'),
1901 _('[-o] CMD'),
1902 norepo=True)
1902 norepo=True)
1903 def debugcomplete(ui, cmd='', **opts):
1903 def debugcomplete(ui, cmd='', **opts):
1904 """returns the completion list associated with the given command"""
1904 """returns the completion list associated with the given command"""
1905
1905
1906 if opts.get('options'):
1906 if opts.get('options'):
1907 options = []
1907 options = []
1908 otables = [globalopts]
1908 otables = [globalopts]
1909 if cmd:
1909 if cmd:
1910 aliases, entry = cmdutil.findcmd(cmd, table, False)
1910 aliases, entry = cmdutil.findcmd(cmd, table, False)
1911 otables.append(entry[1])
1911 otables.append(entry[1])
1912 for t in otables:
1912 for t in otables:
1913 for o in t:
1913 for o in t:
1914 if "(DEPRECATED)" in o[3]:
1914 if "(DEPRECATED)" in o[3]:
1915 continue
1915 continue
1916 if o[0]:
1916 if o[0]:
1917 options.append('-%s' % o[0])
1917 options.append('-%s' % o[0])
1918 options.append('--%s' % o[1])
1918 options.append('--%s' % o[1])
1919 ui.write("%s\n" % "\n".join(options))
1919 ui.write("%s\n" % "\n".join(options))
1920 return
1920 return
1921
1921
1922 cmdlist = cmdutil.findpossible(cmd, table)
1922 cmdlist = cmdutil.findpossible(cmd, table)
1923 if ui.verbose:
1923 if ui.verbose:
1924 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1924 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1925 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1925 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1926
1926
1927 @command('debugdag',
1927 @command('debugdag',
1928 [('t', 'tags', None, _('use tags as labels')),
1928 [('t', 'tags', None, _('use tags as labels')),
1929 ('b', 'branches', None, _('annotate with branch names')),
1929 ('b', 'branches', None, _('annotate with branch names')),
1930 ('', 'dots', None, _('use dots for runs')),
1930 ('', 'dots', None, _('use dots for runs')),
1931 ('s', 'spaces', None, _('separate elements by spaces'))],
1931 ('s', 'spaces', None, _('separate elements by spaces'))],
1932 _('[OPTION]... [FILE [REV]...]'),
1932 _('[OPTION]... [FILE [REV]...]'),
1933 optionalrepo=True)
1933 optionalrepo=True)
1934 def debugdag(ui, repo, file_=None, *revs, **opts):
1934 def debugdag(ui, repo, file_=None, *revs, **opts):
1935 """format the changelog or an index DAG as a concise textual description
1935 """format the changelog or an index DAG as a concise textual description
1936
1936
1937 If you pass a revlog index, the revlog's DAG is emitted. If you list
1937 If you pass a revlog index, the revlog's DAG is emitted. If you list
1938 revision numbers, they get labeled in the output as rN.
1938 revision numbers, they get labeled in the output as rN.
1939
1939
1940 Otherwise, the changelog DAG of the current repo is emitted.
1940 Otherwise, the changelog DAG of the current repo is emitted.
1941 """
1941 """
1942 spaces = opts.get('spaces')
1942 spaces = opts.get('spaces')
1943 dots = opts.get('dots')
1943 dots = opts.get('dots')
1944 if file_:
1944 if file_:
1945 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1945 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1946 revs = set((int(r) for r in revs))
1946 revs = set((int(r) for r in revs))
1947 def events():
1947 def events():
1948 for r in rlog:
1948 for r in rlog:
1949 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1949 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1950 if p != -1))
1950 if p != -1))
1951 if r in revs:
1951 if r in revs:
1952 yield 'l', (r, "r%i" % r)
1952 yield 'l', (r, "r%i" % r)
1953 elif repo:
1953 elif repo:
1954 cl = repo.changelog
1954 cl = repo.changelog
1955 tags = opts.get('tags')
1955 tags = opts.get('tags')
1956 branches = opts.get('branches')
1956 branches = opts.get('branches')
1957 if tags:
1957 if tags:
1958 labels = {}
1958 labels = {}
1959 for l, n in repo.tags().items():
1959 for l, n in repo.tags().items():
1960 labels.setdefault(cl.rev(n), []).append(l)
1960 labels.setdefault(cl.rev(n), []).append(l)
1961 def events():
1961 def events():
1962 b = "default"
1962 b = "default"
1963 for r in cl:
1963 for r in cl:
1964 if branches:
1964 if branches:
1965 newb = cl.read(cl.node(r))[5]['branch']
1965 newb = cl.read(cl.node(r))[5]['branch']
1966 if newb != b:
1966 if newb != b:
1967 yield 'a', newb
1967 yield 'a', newb
1968 b = newb
1968 b = newb
1969 yield 'n', (r, list(p for p in cl.parentrevs(r)
1969 yield 'n', (r, list(p for p in cl.parentrevs(r)
1970 if p != -1))
1970 if p != -1))
1971 if tags:
1971 if tags:
1972 ls = labels.get(r)
1972 ls = labels.get(r)
1973 if ls:
1973 if ls:
1974 for l in ls:
1974 for l in ls:
1975 yield 'l', (r, l)
1975 yield 'l', (r, l)
1976 else:
1976 else:
1977 raise util.Abort(_('need repo for changelog dag'))
1977 raise util.Abort(_('need repo for changelog dag'))
1978
1978
1979 for line in dagparser.dagtextlines(events(),
1979 for line in dagparser.dagtextlines(events(),
1980 addspaces=spaces,
1980 addspaces=spaces,
1981 wraplabels=True,
1981 wraplabels=True,
1982 wrapannotations=True,
1982 wrapannotations=True,
1983 wrapnonlinear=dots,
1983 wrapnonlinear=dots,
1984 usedots=dots,
1984 usedots=dots,
1985 maxlinewidth=70):
1985 maxlinewidth=70):
1986 ui.write(line)
1986 ui.write(line)
1987 ui.write("\n")
1987 ui.write("\n")
1988
1988
1989 @command('debugdata',
1989 @command('debugdata',
1990 [('c', 'changelog', False, _('open changelog')),
1990 [('c', 'changelog', False, _('open changelog')),
1991 ('m', 'manifest', False, _('open manifest'))],
1991 ('m', 'manifest', False, _('open manifest'))],
1992 _('-c|-m|FILE REV'))
1992 _('-c|-m|FILE REV'))
1993 def debugdata(ui, repo, file_, rev=None, **opts):
1993 def debugdata(ui, repo, file_, rev=None, **opts):
1994 """dump the contents of a data file revision"""
1994 """dump the contents of a data file revision"""
1995 if opts.get('changelog') or opts.get('manifest'):
1995 if opts.get('changelog') or opts.get('manifest'):
1996 file_, rev = None, file_
1996 file_, rev = None, file_
1997 elif rev is None:
1997 elif rev is None:
1998 raise error.CommandError('debugdata', _('invalid arguments'))
1998 raise error.CommandError('debugdata', _('invalid arguments'))
1999 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1999 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2000 try:
2000 try:
2001 ui.write(r.revision(r.lookup(rev)))
2001 ui.write(r.revision(r.lookup(rev)))
2002 except KeyError:
2002 except KeyError:
2003 raise util.Abort(_('invalid revision identifier %s') % rev)
2003 raise util.Abort(_('invalid revision identifier %s') % rev)
2004
2004
2005 @command('debugdate',
2005 @command('debugdate',
2006 [('e', 'extended', None, _('try extended date formats'))],
2006 [('e', 'extended', None, _('try extended date formats'))],
2007 _('[-e] DATE [RANGE]'),
2007 _('[-e] DATE [RANGE]'),
2008 norepo=True, optionalrepo=True)
2008 norepo=True, optionalrepo=True)
2009 def debugdate(ui, date, range=None, **opts):
2009 def debugdate(ui, date, range=None, **opts):
2010 """parse and display a date"""
2010 """parse and display a date"""
2011 if opts["extended"]:
2011 if opts["extended"]:
2012 d = util.parsedate(date, util.extendeddateformats)
2012 d = util.parsedate(date, util.extendeddateformats)
2013 else:
2013 else:
2014 d = util.parsedate(date)
2014 d = util.parsedate(date)
2015 ui.write(("internal: %s %s\n") % d)
2015 ui.write(("internal: %s %s\n") % d)
2016 ui.write(("standard: %s\n") % util.datestr(d))
2016 ui.write(("standard: %s\n") % util.datestr(d))
2017 if range:
2017 if range:
2018 m = util.matchdate(range)
2018 m = util.matchdate(range)
2019 ui.write(("match: %s\n") % m(d[0]))
2019 ui.write(("match: %s\n") % m(d[0]))
2020
2020
2021 @command('debugdiscovery',
2021 @command('debugdiscovery',
2022 [('', 'old', None, _('use old-style discovery')),
2022 [('', 'old', None, _('use old-style discovery')),
2023 ('', 'nonheads', None,
2023 ('', 'nonheads', None,
2024 _('use old-style discovery with non-heads included')),
2024 _('use old-style discovery with non-heads included')),
2025 ] + remoteopts,
2025 ] + remoteopts,
2026 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2026 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2027 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2027 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2028 """runs the changeset discovery protocol in isolation"""
2028 """runs the changeset discovery protocol in isolation"""
2029 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2029 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2030 opts.get('branch'))
2030 opts.get('branch'))
2031 remote = hg.peer(repo, opts, remoteurl)
2031 remote = hg.peer(repo, opts, remoteurl)
2032 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2032 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2033
2033
2034 # make sure tests are repeatable
2034 # make sure tests are repeatable
2035 random.seed(12323)
2035 random.seed(12323)
2036
2036
2037 def doit(localheads, remoteheads, remote=remote):
2037 def doit(localheads, remoteheads, remote=remote):
2038 if opts.get('old'):
2038 if opts.get('old'):
2039 if localheads:
2039 if localheads:
2040 raise util.Abort('cannot use localheads with old style '
2040 raise util.Abort('cannot use localheads with old style '
2041 'discovery')
2041 'discovery')
2042 if not util.safehasattr(remote, 'branches'):
2042 if not util.safehasattr(remote, 'branches'):
2043 # enable in-client legacy support
2043 # enable in-client legacy support
2044 remote = localrepo.locallegacypeer(remote.local())
2044 remote = localrepo.locallegacypeer(remote.local())
2045 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2045 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2046 force=True)
2046 force=True)
2047 common = set(common)
2047 common = set(common)
2048 if not opts.get('nonheads'):
2048 if not opts.get('nonheads'):
2049 ui.write(("unpruned common: %s\n") %
2049 ui.write(("unpruned common: %s\n") %
2050 " ".join(sorted(short(n) for n in common)))
2050 " ".join(sorted(short(n) for n in common)))
2051 dag = dagutil.revlogdag(repo.changelog)
2051 dag = dagutil.revlogdag(repo.changelog)
2052 all = dag.ancestorset(dag.internalizeall(common))
2052 all = dag.ancestorset(dag.internalizeall(common))
2053 common = dag.externalizeall(dag.headsetofconnecteds(all))
2053 common = dag.externalizeall(dag.headsetofconnecteds(all))
2054 else:
2054 else:
2055 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2055 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2056 common = set(common)
2056 common = set(common)
2057 rheads = set(hds)
2057 rheads = set(hds)
2058 lheads = set(repo.heads())
2058 lheads = set(repo.heads())
2059 ui.write(("common heads: %s\n") %
2059 ui.write(("common heads: %s\n") %
2060 " ".join(sorted(short(n) for n in common)))
2060 " ".join(sorted(short(n) for n in common)))
2061 if lheads <= common:
2061 if lheads <= common:
2062 ui.write(("local is subset\n"))
2062 ui.write(("local is subset\n"))
2063 elif rheads <= common:
2063 elif rheads <= common:
2064 ui.write(("remote is subset\n"))
2064 ui.write(("remote is subset\n"))
2065
2065
2066 serverlogs = opts.get('serverlog')
2066 serverlogs = opts.get('serverlog')
2067 if serverlogs:
2067 if serverlogs:
2068 for filename in serverlogs:
2068 for filename in serverlogs:
2069 logfile = open(filename, 'r')
2069 logfile = open(filename, 'r')
2070 try:
2070 try:
2071 line = logfile.readline()
2071 line = logfile.readline()
2072 while line:
2072 while line:
2073 parts = line.strip().split(';')
2073 parts = line.strip().split(';')
2074 op = parts[1]
2074 op = parts[1]
2075 if op == 'cg':
2075 if op == 'cg':
2076 pass
2076 pass
2077 elif op == 'cgss':
2077 elif op == 'cgss':
2078 doit(parts[2].split(' '), parts[3].split(' '))
2078 doit(parts[2].split(' '), parts[3].split(' '))
2079 elif op == 'unb':
2079 elif op == 'unb':
2080 doit(parts[3].split(' '), parts[2].split(' '))
2080 doit(parts[3].split(' '), parts[2].split(' '))
2081 line = logfile.readline()
2081 line = logfile.readline()
2082 finally:
2082 finally:
2083 logfile.close()
2083 logfile.close()
2084
2084
2085 else:
2085 else:
2086 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2086 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2087 opts.get('remote_head'))
2087 opts.get('remote_head'))
2088 localrevs = opts.get('local_head')
2088 localrevs = opts.get('local_head')
2089 doit(localrevs, remoterevs)
2089 doit(localrevs, remoterevs)
2090
2090
2091 @command('debugfileset',
2091 @command('debugfileset',
2092 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2092 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2093 _('[-r REV] FILESPEC'))
2093 _('[-r REV] FILESPEC'))
2094 def debugfileset(ui, repo, expr, **opts):
2094 def debugfileset(ui, repo, expr, **opts):
2095 '''parse and apply a fileset specification'''
2095 '''parse and apply a fileset specification'''
2096 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2096 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2097 if ui.verbose:
2097 if ui.verbose:
2098 tree = fileset.parse(expr)[0]
2098 tree = fileset.parse(expr)[0]
2099 ui.note(tree, "\n")
2099 ui.note(tree, "\n")
2100
2100
2101 for f in ctx.getfileset(expr):
2101 for f in ctx.getfileset(expr):
2102 ui.write("%s\n" % f)
2102 ui.write("%s\n" % f)
2103
2103
2104 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2104 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2105 def debugfsinfo(ui, path="."):
2105 def debugfsinfo(ui, path="."):
2106 """show information detected about current filesystem"""
2106 """show information detected about current filesystem"""
2107 util.writefile('.debugfsinfo', '')
2107 util.writefile('.debugfsinfo', '')
2108 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2108 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2109 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2109 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2110 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2110 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2111 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2111 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2112 and 'yes' or 'no'))
2112 and 'yes' or 'no'))
2113 os.unlink('.debugfsinfo')
2113 os.unlink('.debugfsinfo')
2114
2114
2115 @command('debuggetbundle',
2115 @command('debuggetbundle',
2116 [('H', 'head', [], _('id of head node'), _('ID')),
2116 [('H', 'head', [], _('id of head node'), _('ID')),
2117 ('C', 'common', [], _('id of common node'), _('ID')),
2117 ('C', 'common', [], _('id of common node'), _('ID')),
2118 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2118 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2119 _('REPO FILE [-H|-C ID]...'),
2119 _('REPO FILE [-H|-C ID]...'),
2120 norepo=True)
2120 norepo=True)
2121 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2121 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2122 """retrieves a bundle from a repo
2122 """retrieves a bundle from a repo
2123
2123
2124 Every ID must be a full-length hex node id string. Saves the bundle to the
2124 Every ID must be a full-length hex node id string. Saves the bundle to the
2125 given file.
2125 given file.
2126 """
2126 """
2127 repo = hg.peer(ui, opts, repopath)
2127 repo = hg.peer(ui, opts, repopath)
2128 if not repo.capable('getbundle'):
2128 if not repo.capable('getbundle'):
2129 raise util.Abort("getbundle() not supported by target repository")
2129 raise util.Abort("getbundle() not supported by target repository")
2130 args = {}
2130 args = {}
2131 if common:
2131 if common:
2132 args['common'] = [bin(s) for s in common]
2132 args['common'] = [bin(s) for s in common]
2133 if head:
2133 if head:
2134 args['heads'] = [bin(s) for s in head]
2134 args['heads'] = [bin(s) for s in head]
2135 # TODO: get desired bundlecaps from command line.
2135 # TODO: get desired bundlecaps from command line.
2136 args['bundlecaps'] = None
2136 args['bundlecaps'] = None
2137 bundle = repo.getbundle('debug', **args)
2137 bundle = repo.getbundle('debug', **args)
2138
2138
2139 bundletype = opts.get('type', 'bzip2').lower()
2139 bundletype = opts.get('type', 'bzip2').lower()
2140 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2140 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2141 bundletype = btypes.get(bundletype)
2141 bundletype = btypes.get(bundletype)
2142 if bundletype not in changegroup.bundletypes:
2142 if bundletype not in changegroup.bundletypes:
2143 raise util.Abort(_('unknown bundle type specified with --type'))
2143 raise util.Abort(_('unknown bundle type specified with --type'))
2144 changegroup.writebundle(bundle, bundlepath, bundletype)
2144 changegroup.writebundle(bundle, bundlepath, bundletype)
2145
2145
2146 @command('debugignore', [], '')
2146 @command('debugignore', [], '')
2147 def debugignore(ui, repo, *values, **opts):
2147 def debugignore(ui, repo, *values, **opts):
2148 """display the combined ignore pattern"""
2148 """display the combined ignore pattern"""
2149 ignore = repo.dirstate._ignore
2149 ignore = repo.dirstate._ignore
2150 includepat = getattr(ignore, 'includepat', None)
2150 includepat = getattr(ignore, 'includepat', None)
2151 if includepat is not None:
2151 if includepat is not None:
2152 ui.write("%s\n" % includepat)
2152 ui.write("%s\n" % includepat)
2153 else:
2153 else:
2154 raise util.Abort(_("no ignore patterns found"))
2154 raise util.Abort(_("no ignore patterns found"))
2155
2155
2156 @command('debugindex',
2156 @command('debugindex',
2157 [('c', 'changelog', False, _('open changelog')),
2157 [('c', 'changelog', False, _('open changelog')),
2158 ('m', 'manifest', False, _('open manifest')),
2158 ('m', 'manifest', False, _('open manifest')),
2159 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2159 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2160 _('[-f FORMAT] -c|-m|FILE'),
2160 _('[-f FORMAT] -c|-m|FILE'),
2161 optionalrepo=True)
2161 optionalrepo=True)
2162 def debugindex(ui, repo, file_=None, **opts):
2162 def debugindex(ui, repo, file_=None, **opts):
2163 """dump the contents of an index file"""
2163 """dump the contents of an index file"""
2164 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2164 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2165 format = opts.get('format', 0)
2165 format = opts.get('format', 0)
2166 if format not in (0, 1):
2166 if format not in (0, 1):
2167 raise util.Abort(_("unknown format %d") % format)
2167 raise util.Abort(_("unknown format %d") % format)
2168
2168
2169 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2169 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2170 if generaldelta:
2170 if generaldelta:
2171 basehdr = ' delta'
2171 basehdr = ' delta'
2172 else:
2172 else:
2173 basehdr = ' base'
2173 basehdr = ' base'
2174
2174
2175 if format == 0:
2175 if format == 0:
2176 ui.write(" rev offset length " + basehdr + " linkrev"
2176 ui.write(" rev offset length " + basehdr + " linkrev"
2177 " nodeid p1 p2\n")
2177 " nodeid p1 p2\n")
2178 elif format == 1:
2178 elif format == 1:
2179 ui.write(" rev flag offset length"
2179 ui.write(" rev flag offset length"
2180 " size " + basehdr + " link p1 p2"
2180 " size " + basehdr + " link p1 p2"
2181 " nodeid\n")
2181 " nodeid\n")
2182
2182
2183 for i in r:
2183 for i in r:
2184 node = r.node(i)
2184 node = r.node(i)
2185 if generaldelta:
2185 if generaldelta:
2186 base = r.deltaparent(i)
2186 base = r.deltaparent(i)
2187 else:
2187 else:
2188 base = r.chainbase(i)
2188 base = r.chainbase(i)
2189 if format == 0:
2189 if format == 0:
2190 try:
2190 try:
2191 pp = r.parents(node)
2191 pp = r.parents(node)
2192 except Exception:
2192 except Exception:
2193 pp = [nullid, nullid]
2193 pp = [nullid, nullid]
2194 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2194 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2195 i, r.start(i), r.length(i), base, r.linkrev(i),
2195 i, r.start(i), r.length(i), base, r.linkrev(i),
2196 short(node), short(pp[0]), short(pp[1])))
2196 short(node), short(pp[0]), short(pp[1])))
2197 elif format == 1:
2197 elif format == 1:
2198 pr = r.parentrevs(i)
2198 pr = r.parentrevs(i)
2199 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2199 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2200 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2200 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2201 base, r.linkrev(i), pr[0], pr[1], short(node)))
2201 base, r.linkrev(i), pr[0], pr[1], short(node)))
2202
2202
2203 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2203 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2204 def debugindexdot(ui, repo, file_):
2204 def debugindexdot(ui, repo, file_):
2205 """dump an index DAG as a graphviz dot file"""
2205 """dump an index DAG as a graphviz dot file"""
2206 r = None
2206 r = None
2207 if repo:
2207 if repo:
2208 filelog = repo.file(file_)
2208 filelog = repo.file(file_)
2209 if len(filelog):
2209 if len(filelog):
2210 r = filelog
2210 r = filelog
2211 if not r:
2211 if not r:
2212 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2212 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2213 ui.write(("digraph G {\n"))
2213 ui.write(("digraph G {\n"))
2214 for i in r:
2214 for i in r:
2215 node = r.node(i)
2215 node = r.node(i)
2216 pp = r.parents(node)
2216 pp = r.parents(node)
2217 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2217 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2218 if pp[1] != nullid:
2218 if pp[1] != nullid:
2219 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2219 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2220 ui.write("}\n")
2220 ui.write("}\n")
2221
2221
2222 @command('debuginstall', [], '', norepo=True)
2222 @command('debuginstall', [], '', norepo=True)
2223 def debuginstall(ui):
2223 def debuginstall(ui):
2224 '''test Mercurial installation
2224 '''test Mercurial installation
2225
2225
2226 Returns 0 on success.
2226 Returns 0 on success.
2227 '''
2227 '''
2228
2228
2229 def writetemp(contents):
2229 def writetemp(contents):
2230 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2230 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2231 f = os.fdopen(fd, "wb")
2231 f = os.fdopen(fd, "wb")
2232 f.write(contents)
2232 f.write(contents)
2233 f.close()
2233 f.close()
2234 return name
2234 return name
2235
2235
2236 problems = 0
2236 problems = 0
2237
2237
2238 # encoding
2238 # encoding
2239 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2239 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2240 try:
2240 try:
2241 encoding.fromlocal("test")
2241 encoding.fromlocal("test")
2242 except util.Abort, inst:
2242 except util.Abort, inst:
2243 ui.write(" %s\n" % inst)
2243 ui.write(" %s\n" % inst)
2244 ui.write(_(" (check that your locale is properly set)\n"))
2244 ui.write(_(" (check that your locale is properly set)\n"))
2245 problems += 1
2245 problems += 1
2246
2246
2247 # Python
2247 # Python
2248 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2248 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2249 ui.status(_("checking Python version (%s)\n")
2249 ui.status(_("checking Python version (%s)\n")
2250 % ("%s.%s.%s" % sys.version_info[:3]))
2250 % ("%s.%s.%s" % sys.version_info[:3]))
2251 ui.status(_("checking Python lib (%s)...\n")
2251 ui.status(_("checking Python lib (%s)...\n")
2252 % os.path.dirname(os.__file__))
2252 % os.path.dirname(os.__file__))
2253
2253
2254 # compiled modules
2254 # compiled modules
2255 ui.status(_("checking installed modules (%s)...\n")
2255 ui.status(_("checking installed modules (%s)...\n")
2256 % os.path.dirname(__file__))
2256 % os.path.dirname(__file__))
2257 try:
2257 try:
2258 import bdiff, mpatch, base85, osutil
2258 import bdiff, mpatch, base85, osutil
2259 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2259 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2260 except Exception, inst:
2260 except Exception, inst:
2261 ui.write(" %s\n" % inst)
2261 ui.write(" %s\n" % inst)
2262 ui.write(_(" One or more extensions could not be found"))
2262 ui.write(_(" One or more extensions could not be found"))
2263 ui.write(_(" (check that you compiled the extensions)\n"))
2263 ui.write(_(" (check that you compiled the extensions)\n"))
2264 problems += 1
2264 problems += 1
2265
2265
2266 # templates
2266 # templates
2267 import templater
2267 import templater
2268 p = templater.templatepaths()
2268 p = templater.templatepaths()
2269 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2269 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2270 if p:
2270 if p:
2271 m = templater.templatepath("map-cmdline.default")
2271 m = templater.templatepath("map-cmdline.default")
2272 if m:
2272 if m:
2273 # template found, check if it is working
2273 # template found, check if it is working
2274 try:
2274 try:
2275 templater.templater(m)
2275 templater.templater(m)
2276 except Exception, inst:
2276 except Exception, inst:
2277 ui.write(" %s\n" % inst)
2277 ui.write(" %s\n" % inst)
2278 p = None
2278 p = None
2279 else:
2279 else:
2280 ui.write(_(" template 'default' not found\n"))
2280 ui.write(_(" template 'default' not found\n"))
2281 p = None
2281 p = None
2282 else:
2282 else:
2283 ui.write(_(" no template directories found\n"))
2283 ui.write(_(" no template directories found\n"))
2284 if not p:
2284 if not p:
2285 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2285 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2286 problems += 1
2286 problems += 1
2287
2287
2288 # editor
2288 # editor
2289 ui.status(_("checking commit editor...\n"))
2289 ui.status(_("checking commit editor...\n"))
2290 editor = ui.geteditor()
2290 editor = ui.geteditor()
2291 cmdpath = util.findexe(shlex.split(editor)[0])
2291 cmdpath = util.findexe(shlex.split(editor)[0])
2292 if not cmdpath:
2292 if not cmdpath:
2293 if editor == 'vi':
2293 if editor == 'vi':
2294 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2294 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2295 ui.write(_(" (specify a commit editor in your configuration"
2295 ui.write(_(" (specify a commit editor in your configuration"
2296 " file)\n"))
2296 " file)\n"))
2297 else:
2297 else:
2298 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2298 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2299 ui.write(_(" (specify a commit editor in your configuration"
2299 ui.write(_(" (specify a commit editor in your configuration"
2300 " file)\n"))
2300 " file)\n"))
2301 problems += 1
2301 problems += 1
2302
2302
2303 # check username
2303 # check username
2304 ui.status(_("checking username...\n"))
2304 ui.status(_("checking username...\n"))
2305 try:
2305 try:
2306 ui.username()
2306 ui.username()
2307 except util.Abort, e:
2307 except util.Abort, e:
2308 ui.write(" %s\n" % e)
2308 ui.write(" %s\n" % e)
2309 ui.write(_(" (specify a username in your configuration file)\n"))
2309 ui.write(_(" (specify a username in your configuration file)\n"))
2310 problems += 1
2310 problems += 1
2311
2311
2312 if not problems:
2312 if not problems:
2313 ui.status(_("no problems detected\n"))
2313 ui.status(_("no problems detected\n"))
2314 else:
2314 else:
2315 ui.write(_("%s problems detected,"
2315 ui.write(_("%s problems detected,"
2316 " please check your install!\n") % problems)
2316 " please check your install!\n") % problems)
2317
2317
2318 return problems
2318 return problems
2319
2319
2320 @command('debugknown', [], _('REPO ID...'), norepo=True)
2320 @command('debugknown', [], _('REPO ID...'), norepo=True)
2321 def debugknown(ui, repopath, *ids, **opts):
2321 def debugknown(ui, repopath, *ids, **opts):
2322 """test whether node ids are known to a repo
2322 """test whether node ids are known to a repo
2323
2323
2324 Every ID must be a full-length hex node id string. Returns a list of 0s
2324 Every ID must be a full-length hex node id string. Returns a list of 0s
2325 and 1s indicating unknown/known.
2325 and 1s indicating unknown/known.
2326 """
2326 """
2327 repo = hg.peer(ui, opts, repopath)
2327 repo = hg.peer(ui, opts, repopath)
2328 if not repo.capable('known'):
2328 if not repo.capable('known'):
2329 raise util.Abort("known() not supported by target repository")
2329 raise util.Abort("known() not supported by target repository")
2330 flags = repo.known([bin(s) for s in ids])
2330 flags = repo.known([bin(s) for s in ids])
2331 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2331 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2332
2332
2333 @command('debuglabelcomplete', [], _('LABEL...'))
2333 @command('debuglabelcomplete', [], _('LABEL...'))
2334 def debuglabelcomplete(ui, repo, *args):
2334 def debuglabelcomplete(ui, repo, *args):
2335 '''complete "labels" - tags, open branch names, bookmark names'''
2335 '''complete "labels" - tags, open branch names, bookmark names'''
2336
2336
2337 labels = set()
2337 labels = set()
2338 labels.update(t[0] for t in repo.tagslist())
2338 labels.update(t[0] for t in repo.tagslist())
2339 labels.update(repo._bookmarks.keys())
2339 labels.update(repo._bookmarks.keys())
2340 labels.update(tag for (tag, heads, tip, closed)
2340 labels.update(tag for (tag, heads, tip, closed)
2341 in repo.branchmap().iterbranches() if not closed)
2341 in repo.branchmap().iterbranches() if not closed)
2342 completions = set()
2342 completions = set()
2343 if not args:
2343 if not args:
2344 args = ['']
2344 args = ['']
2345 for a in args:
2345 for a in args:
2346 completions.update(l for l in labels if l.startswith(a))
2346 completions.update(l for l in labels if l.startswith(a))
2347 ui.write('\n'.join(sorted(completions)))
2347 ui.write('\n'.join(sorted(completions)))
2348 ui.write('\n')
2348 ui.write('\n')
2349
2349
2350 @command('debuglocks',
2350 @command('debuglocks',
2351 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2351 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2352 ('W', 'force-wlock', None,
2352 ('W', 'force-wlock', None,
2353 _('free the working state lock (DANGEROUS)'))],
2353 _('free the working state lock (DANGEROUS)'))],
2354 _('[OPTION]...'))
2354 _('[OPTION]...'))
2355 def debuglocks(ui, repo, **opts):
2355 def debuglocks(ui, repo, **opts):
2356 """show or modify state of locks
2356 """show or modify state of locks
2357
2357
2358 By default, this command will show which locks are held. This
2358 By default, this command will show which locks are held. This
2359 includes the user and process holding the lock, the amount of time
2359 includes the user and process holding the lock, the amount of time
2360 the lock has been held, and the machine name where the process is
2360 the lock has been held, and the machine name where the process is
2361 running if it's not local.
2361 running if it's not local.
2362
2362
2363 Locks protect the integrity of Mercurial's data, so should be
2363 Locks protect the integrity of Mercurial's data, so should be
2364 treated with care. System crashes or other interruptions may cause
2364 treated with care. System crashes or other interruptions may cause
2365 locks to not be properly released, though Mercurial will usually
2365 locks to not be properly released, though Mercurial will usually
2366 detect and remove such stale locks automatically.
2366 detect and remove such stale locks automatically.
2367
2367
2368 However, detecting stale locks may not always be possible (for
2368 However, detecting stale locks may not always be possible (for
2369 instance, on a shared filesystem). Removing locks may also be
2369 instance, on a shared filesystem). Removing locks may also be
2370 blocked by filesystem permissions.
2370 blocked by filesystem permissions.
2371
2371
2372 Returns 0 if no locks are held.
2372 Returns 0 if no locks are held.
2373
2373
2374 """
2374 """
2375
2375
2376 if opts.get('force_lock'):
2376 if opts.get('force_lock'):
2377 repo.svfs.unlink('lock')
2377 repo.svfs.unlink('lock')
2378 if opts.get('force_wlock'):
2378 if opts.get('force_wlock'):
2379 repo.vfs.unlink('wlock')
2379 repo.vfs.unlink('wlock')
2380 if opts.get('force_lock') or opts.get('force_lock'):
2380 if opts.get('force_lock') or opts.get('force_lock'):
2381 return 0
2381 return 0
2382
2382
2383 now = time.time()
2383 now = time.time()
2384 held = 0
2384 held = 0
2385
2385
2386 def report(vfs, name, method):
2386 def report(vfs, name, method):
2387 # this causes stale locks to get reaped for more accurate reporting
2387 # this causes stale locks to get reaped for more accurate reporting
2388 try:
2388 try:
2389 l = method(False)
2389 l = method(False)
2390 except error.LockHeld:
2390 except error.LockHeld:
2391 l = None
2391 l = None
2392
2392
2393 if l:
2393 if l:
2394 l.release()
2394 l.release()
2395 else:
2395 else:
2396 try:
2396 try:
2397 stat = repo.svfs.lstat(name)
2397 stat = repo.svfs.lstat(name)
2398 age = now - stat.st_mtime
2398 age = now - stat.st_mtime
2399 user = util.username(stat.st_uid)
2399 user = util.username(stat.st_uid)
2400 locker = vfs.readlock(name)
2400 locker = vfs.readlock(name)
2401 if ":" in locker:
2401 if ":" in locker:
2402 host, pid = locker.split(':')
2402 host, pid = locker.split(':')
2403 if host == socket.gethostname():
2403 if host == socket.gethostname():
2404 locker = 'user %s, process %s' % (user, pid)
2404 locker = 'user %s, process %s' % (user, pid)
2405 else:
2405 else:
2406 locker = 'user %s, process %s, host %s' \
2406 locker = 'user %s, process %s, host %s' \
2407 % (user, pid, host)
2407 % (user, pid, host)
2408 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2408 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2409 return 1
2409 return 1
2410 except OSError, e:
2410 except OSError, e:
2411 if e.errno != errno.ENOENT:
2411 if e.errno != errno.ENOENT:
2412 raise
2412 raise
2413
2413
2414 ui.write("%-6s free\n" % (name + ":"))
2414 ui.write("%-6s free\n" % (name + ":"))
2415 return 0
2415 return 0
2416
2416
2417 held += report(repo.svfs, "lock", repo.lock)
2417 held += report(repo.svfs, "lock", repo.lock)
2418 held += report(repo.vfs, "wlock", repo.wlock)
2418 held += report(repo.vfs, "wlock", repo.wlock)
2419
2419
2420 return held
2420 return held
2421
2421
2422 @command('debugobsolete',
2422 @command('debugobsolete',
2423 [('', 'flags', 0, _('markers flag')),
2423 [('', 'flags', 0, _('markers flag')),
2424 ('', 'record-parents', False,
2424 ('', 'record-parents', False,
2425 _('record parent information for the precursor')),
2425 _('record parent information for the precursor')),
2426 ('r', 'rev', [], _('display markers relevant to REV')),
2426 ('r', 'rev', [], _('display markers relevant to REV')),
2427 ] + commitopts2,
2427 ] + commitopts2,
2428 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2428 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2429 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2429 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2430 """create arbitrary obsolete marker
2430 """create arbitrary obsolete marker
2431
2431
2432 With no arguments, displays the list of obsolescence markers."""
2432 With no arguments, displays the list of obsolescence markers."""
2433
2433
2434 def parsenodeid(s):
2434 def parsenodeid(s):
2435 try:
2435 try:
2436 # We do not use revsingle/revrange functions here to accept
2436 # We do not use revsingle/revrange functions here to accept
2437 # arbitrary node identifiers, possibly not present in the
2437 # arbitrary node identifiers, possibly not present in the
2438 # local repository.
2438 # local repository.
2439 n = bin(s)
2439 n = bin(s)
2440 if len(n) != len(nullid):
2440 if len(n) != len(nullid):
2441 raise TypeError()
2441 raise TypeError()
2442 return n
2442 return n
2443 except TypeError:
2443 except TypeError:
2444 raise util.Abort('changeset references must be full hexadecimal '
2444 raise util.Abort('changeset references must be full hexadecimal '
2445 'node identifiers')
2445 'node identifiers')
2446
2446
2447 if precursor is not None:
2447 if precursor is not None:
2448 if opts['rev']:
2448 if opts['rev']:
2449 raise util.Abort('cannot select revision when creating marker')
2449 raise util.Abort('cannot select revision when creating marker')
2450 metadata = {}
2450 metadata = {}
2451 metadata['user'] = opts['user'] or ui.username()
2451 metadata['user'] = opts['user'] or ui.username()
2452 succs = tuple(parsenodeid(succ) for succ in successors)
2452 succs = tuple(parsenodeid(succ) for succ in successors)
2453 l = repo.lock()
2453 l = repo.lock()
2454 try:
2454 try:
2455 tr = repo.transaction('debugobsolete')
2455 tr = repo.transaction('debugobsolete')
2456 try:
2456 try:
2457 try:
2457 try:
2458 date = opts.get('date')
2458 date = opts.get('date')
2459 if date:
2459 if date:
2460 date = util.parsedate(date)
2460 date = util.parsedate(date)
2461 else:
2461 else:
2462 date = None
2462 date = None
2463 prec = parsenodeid(precursor)
2463 prec = parsenodeid(precursor)
2464 parents = None
2464 parents = None
2465 if opts['record_parents']:
2465 if opts['record_parents']:
2466 if prec not in repo.unfiltered():
2466 if prec not in repo.unfiltered():
2467 raise util.Abort('cannot used --record-parents on '
2467 raise util.Abort('cannot used --record-parents on '
2468 'unknown changesets')
2468 'unknown changesets')
2469 parents = repo.unfiltered()[prec].parents()
2469 parents = repo.unfiltered()[prec].parents()
2470 parents = tuple(p.node() for p in parents)
2470 parents = tuple(p.node() for p in parents)
2471 repo.obsstore.create(tr, prec, succs, opts['flags'],
2471 repo.obsstore.create(tr, prec, succs, opts['flags'],
2472 parents=parents, date=date,
2472 parents=parents, date=date,
2473 metadata=metadata)
2473 metadata=metadata)
2474 tr.close()
2474 tr.close()
2475 except ValueError, exc:
2475 except ValueError, exc:
2476 raise util.Abort(_('bad obsmarker input: %s') % exc)
2476 raise util.Abort(_('bad obsmarker input: %s') % exc)
2477 finally:
2477 finally:
2478 tr.release()
2478 tr.release()
2479 finally:
2479 finally:
2480 l.release()
2480 l.release()
2481 else:
2481 else:
2482 if opts['rev']:
2482 if opts['rev']:
2483 revs = scmutil.revrange(repo, opts['rev'])
2483 revs = scmutil.revrange(repo, opts['rev'])
2484 nodes = [repo[r].node() for r in revs]
2484 nodes = [repo[r].node() for r in revs]
2485 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2485 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2486 markers.sort(key=lambda x: x._data)
2486 markers.sort(key=lambda x: x._data)
2487 else:
2487 else:
2488 markers = obsolete.getmarkers(repo)
2488 markers = obsolete.getmarkers(repo)
2489
2489
2490 for m in markers:
2490 for m in markers:
2491 cmdutil.showmarker(ui, m)
2491 cmdutil.showmarker(ui, m)
2492
2492
2493 @command('debugpathcomplete',
2493 @command('debugpathcomplete',
2494 [('f', 'full', None, _('complete an entire path')),
2494 [('f', 'full', None, _('complete an entire path')),
2495 ('n', 'normal', None, _('show only normal files')),
2495 ('n', 'normal', None, _('show only normal files')),
2496 ('a', 'added', None, _('show only added files')),
2496 ('a', 'added', None, _('show only added files')),
2497 ('r', 'removed', None, _('show only removed files'))],
2497 ('r', 'removed', None, _('show only removed files'))],
2498 _('FILESPEC...'))
2498 _('FILESPEC...'))
2499 def debugpathcomplete(ui, repo, *specs, **opts):
2499 def debugpathcomplete(ui, repo, *specs, **opts):
2500 '''complete part or all of a tracked path
2500 '''complete part or all of a tracked path
2501
2501
2502 This command supports shells that offer path name completion. It
2502 This command supports shells that offer path name completion. It
2503 currently completes only files already known to the dirstate.
2503 currently completes only files already known to the dirstate.
2504
2504
2505 Completion extends only to the next path segment unless
2505 Completion extends only to the next path segment unless
2506 --full is specified, in which case entire paths are used.'''
2506 --full is specified, in which case entire paths are used.'''
2507
2507
2508 def complete(path, acceptable):
2508 def complete(path, acceptable):
2509 dirstate = repo.dirstate
2509 dirstate = repo.dirstate
2510 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2510 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2511 rootdir = repo.root + os.sep
2511 rootdir = repo.root + os.sep
2512 if spec != repo.root and not spec.startswith(rootdir):
2512 if spec != repo.root and not spec.startswith(rootdir):
2513 return [], []
2513 return [], []
2514 if os.path.isdir(spec):
2514 if os.path.isdir(spec):
2515 spec += '/'
2515 spec += '/'
2516 spec = spec[len(rootdir):]
2516 spec = spec[len(rootdir):]
2517 fixpaths = os.sep != '/'
2517 fixpaths = os.sep != '/'
2518 if fixpaths:
2518 if fixpaths:
2519 spec = spec.replace(os.sep, '/')
2519 spec = spec.replace(os.sep, '/')
2520 speclen = len(spec)
2520 speclen = len(spec)
2521 fullpaths = opts['full']
2521 fullpaths = opts['full']
2522 files, dirs = set(), set()
2522 files, dirs = set(), set()
2523 adddir, addfile = dirs.add, files.add
2523 adddir, addfile = dirs.add, files.add
2524 for f, st in dirstate.iteritems():
2524 for f, st in dirstate.iteritems():
2525 if f.startswith(spec) and st[0] in acceptable:
2525 if f.startswith(spec) and st[0] in acceptable:
2526 if fixpaths:
2526 if fixpaths:
2527 f = f.replace('/', os.sep)
2527 f = f.replace('/', os.sep)
2528 if fullpaths:
2528 if fullpaths:
2529 addfile(f)
2529 addfile(f)
2530 continue
2530 continue
2531 s = f.find(os.sep, speclen)
2531 s = f.find(os.sep, speclen)
2532 if s >= 0:
2532 if s >= 0:
2533 adddir(f[:s])
2533 adddir(f[:s])
2534 else:
2534 else:
2535 addfile(f)
2535 addfile(f)
2536 return files, dirs
2536 return files, dirs
2537
2537
2538 acceptable = ''
2538 acceptable = ''
2539 if opts['normal']:
2539 if opts['normal']:
2540 acceptable += 'nm'
2540 acceptable += 'nm'
2541 if opts['added']:
2541 if opts['added']:
2542 acceptable += 'a'
2542 acceptable += 'a'
2543 if opts['removed']:
2543 if opts['removed']:
2544 acceptable += 'r'
2544 acceptable += 'r'
2545 cwd = repo.getcwd()
2545 cwd = repo.getcwd()
2546 if not specs:
2546 if not specs:
2547 specs = ['.']
2547 specs = ['.']
2548
2548
2549 files, dirs = set(), set()
2549 files, dirs = set(), set()
2550 for spec in specs:
2550 for spec in specs:
2551 f, d = complete(spec, acceptable or 'nmar')
2551 f, d = complete(spec, acceptable or 'nmar')
2552 files.update(f)
2552 files.update(f)
2553 dirs.update(d)
2553 dirs.update(d)
2554 files.update(dirs)
2554 files.update(dirs)
2555 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2555 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2556 ui.write('\n')
2556 ui.write('\n')
2557
2557
2558 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2558 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2559 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2559 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2560 '''access the pushkey key/value protocol
2560 '''access the pushkey key/value protocol
2561
2561
2562 With two args, list the keys in the given namespace.
2562 With two args, list the keys in the given namespace.
2563
2563
2564 With five args, set a key to new if it currently is set to old.
2564 With five args, set a key to new if it currently is set to old.
2565 Reports success or failure.
2565 Reports success or failure.
2566 '''
2566 '''
2567
2567
2568 target = hg.peer(ui, {}, repopath)
2568 target = hg.peer(ui, {}, repopath)
2569 if keyinfo:
2569 if keyinfo:
2570 key, old, new = keyinfo
2570 key, old, new = keyinfo
2571 r = target.pushkey(namespace, key, old, new)
2571 r = target.pushkey(namespace, key, old, new)
2572 ui.status(str(r) + '\n')
2572 ui.status(str(r) + '\n')
2573 return not r
2573 return not r
2574 else:
2574 else:
2575 for k, v in sorted(target.listkeys(namespace).iteritems()):
2575 for k, v in sorted(target.listkeys(namespace).iteritems()):
2576 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2576 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2577 v.encode('string-escape')))
2577 v.encode('string-escape')))
2578
2578
2579 @command('debugpvec', [], _('A B'))
2579 @command('debugpvec', [], _('A B'))
2580 def debugpvec(ui, repo, a, b=None):
2580 def debugpvec(ui, repo, a, b=None):
2581 ca = scmutil.revsingle(repo, a)
2581 ca = scmutil.revsingle(repo, a)
2582 cb = scmutil.revsingle(repo, b)
2582 cb = scmutil.revsingle(repo, b)
2583 pa = pvec.ctxpvec(ca)
2583 pa = pvec.ctxpvec(ca)
2584 pb = pvec.ctxpvec(cb)
2584 pb = pvec.ctxpvec(cb)
2585 if pa == pb:
2585 if pa == pb:
2586 rel = "="
2586 rel = "="
2587 elif pa > pb:
2587 elif pa > pb:
2588 rel = ">"
2588 rel = ">"
2589 elif pa < pb:
2589 elif pa < pb:
2590 rel = "<"
2590 rel = "<"
2591 elif pa | pb:
2591 elif pa | pb:
2592 rel = "|"
2592 rel = "|"
2593 ui.write(_("a: %s\n") % pa)
2593 ui.write(_("a: %s\n") % pa)
2594 ui.write(_("b: %s\n") % pb)
2594 ui.write(_("b: %s\n") % pb)
2595 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2595 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2596 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2596 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2597 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2597 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2598 pa.distance(pb), rel))
2598 pa.distance(pb), rel))
2599
2599
2600 @command('debugrebuilddirstate|debugrebuildstate',
2600 @command('debugrebuilddirstate|debugrebuildstate',
2601 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2601 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2602 _('[-r REV]'))
2602 _('[-r REV]'))
2603 def debugrebuilddirstate(ui, repo, rev):
2603 def debugrebuilddirstate(ui, repo, rev):
2604 """rebuild the dirstate as it would look like for the given revision
2604 """rebuild the dirstate as it would look like for the given revision
2605
2605
2606 If no revision is specified the first current parent will be used.
2606 If no revision is specified the first current parent will be used.
2607
2607
2608 The dirstate will be set to the files of the given revision.
2608 The dirstate will be set to the files of the given revision.
2609 The actual working directory content or existing dirstate
2609 The actual working directory content or existing dirstate
2610 information such as adds or removes is not considered.
2610 information such as adds or removes is not considered.
2611
2611
2612 One use of this command is to make the next :hg:`status` invocation
2612 One use of this command is to make the next :hg:`status` invocation
2613 check the actual file content.
2613 check the actual file content.
2614 """
2614 """
2615 ctx = scmutil.revsingle(repo, rev)
2615 ctx = scmutil.revsingle(repo, rev)
2616 wlock = repo.wlock()
2616 wlock = repo.wlock()
2617 try:
2617 try:
2618 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2618 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2619 finally:
2619 finally:
2620 wlock.release()
2620 wlock.release()
2621
2621
2622 @command('debugrename',
2622 @command('debugrename',
2623 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2623 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2624 _('[-r REV] FILE'))
2624 _('[-r REV] FILE'))
2625 def debugrename(ui, repo, file1, *pats, **opts):
2625 def debugrename(ui, repo, file1, *pats, **opts):
2626 """dump rename information"""
2626 """dump rename information"""
2627
2627
2628 ctx = scmutil.revsingle(repo, opts.get('rev'))
2628 ctx = scmutil.revsingle(repo, opts.get('rev'))
2629 m = scmutil.match(ctx, (file1,) + pats, opts)
2629 m = scmutil.match(ctx, (file1,) + pats, opts)
2630 for abs in ctx.walk(m):
2630 for abs in ctx.walk(m):
2631 fctx = ctx[abs]
2631 fctx = ctx[abs]
2632 o = fctx.filelog().renamed(fctx.filenode())
2632 o = fctx.filelog().renamed(fctx.filenode())
2633 rel = m.rel(abs)
2633 rel = m.rel(abs)
2634 if o:
2634 if o:
2635 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2635 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2636 else:
2636 else:
2637 ui.write(_("%s not renamed\n") % rel)
2637 ui.write(_("%s not renamed\n") % rel)
2638
2638
2639 @command('debugrevlog',
2639 @command('debugrevlog',
2640 [('c', 'changelog', False, _('open changelog')),
2640 [('c', 'changelog', False, _('open changelog')),
2641 ('m', 'manifest', False, _('open manifest')),
2641 ('m', 'manifest', False, _('open manifest')),
2642 ('d', 'dump', False, _('dump index data'))],
2642 ('d', 'dump', False, _('dump index data'))],
2643 _('-c|-m|FILE'),
2643 _('-c|-m|FILE'),
2644 optionalrepo=True)
2644 optionalrepo=True)
2645 def debugrevlog(ui, repo, file_=None, **opts):
2645 def debugrevlog(ui, repo, file_=None, **opts):
2646 """show data and statistics about a revlog"""
2646 """show data and statistics about a revlog"""
2647 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2647 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2648
2648
2649 if opts.get("dump"):
2649 if opts.get("dump"):
2650 numrevs = len(r)
2650 numrevs = len(r)
2651 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2651 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2652 " rawsize totalsize compression heads chainlen\n")
2652 " rawsize totalsize compression heads chainlen\n")
2653 ts = 0
2653 ts = 0
2654 heads = set()
2654 heads = set()
2655
2655
2656 for rev in xrange(numrevs):
2656 for rev in xrange(numrevs):
2657 dbase = r.deltaparent(rev)
2657 dbase = r.deltaparent(rev)
2658 if dbase == -1:
2658 if dbase == -1:
2659 dbase = rev
2659 dbase = rev
2660 cbase = r.chainbase(rev)
2660 cbase = r.chainbase(rev)
2661 clen = r.chainlen(rev)
2661 clen = r.chainlen(rev)
2662 p1, p2 = r.parentrevs(rev)
2662 p1, p2 = r.parentrevs(rev)
2663 rs = r.rawsize(rev)
2663 rs = r.rawsize(rev)
2664 ts = ts + rs
2664 ts = ts + rs
2665 heads -= set(r.parentrevs(rev))
2665 heads -= set(r.parentrevs(rev))
2666 heads.add(rev)
2666 heads.add(rev)
2667 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2667 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2668 "%11d %5d %8d\n" %
2668 "%11d %5d %8d\n" %
2669 (rev, p1, p2, r.start(rev), r.end(rev),
2669 (rev, p1, p2, r.start(rev), r.end(rev),
2670 r.start(dbase), r.start(cbase),
2670 r.start(dbase), r.start(cbase),
2671 r.start(p1), r.start(p2),
2671 r.start(p1), r.start(p2),
2672 rs, ts, ts / r.end(rev), len(heads), clen))
2672 rs, ts, ts / r.end(rev), len(heads), clen))
2673 return 0
2673 return 0
2674
2674
2675 v = r.version
2675 v = r.version
2676 format = v & 0xFFFF
2676 format = v & 0xFFFF
2677 flags = []
2677 flags = []
2678 gdelta = False
2678 gdelta = False
2679 if v & revlog.REVLOGNGINLINEDATA:
2679 if v & revlog.REVLOGNGINLINEDATA:
2680 flags.append('inline')
2680 flags.append('inline')
2681 if v & revlog.REVLOGGENERALDELTA:
2681 if v & revlog.REVLOGGENERALDELTA:
2682 gdelta = True
2682 gdelta = True
2683 flags.append('generaldelta')
2683 flags.append('generaldelta')
2684 if not flags:
2684 if not flags:
2685 flags = ['(none)']
2685 flags = ['(none)']
2686
2686
2687 nummerges = 0
2687 nummerges = 0
2688 numfull = 0
2688 numfull = 0
2689 numprev = 0
2689 numprev = 0
2690 nump1 = 0
2690 nump1 = 0
2691 nump2 = 0
2691 nump2 = 0
2692 numother = 0
2692 numother = 0
2693 nump1prev = 0
2693 nump1prev = 0
2694 nump2prev = 0
2694 nump2prev = 0
2695 chainlengths = []
2695 chainlengths = []
2696
2696
2697 datasize = [None, 0, 0L]
2697 datasize = [None, 0, 0L]
2698 fullsize = [None, 0, 0L]
2698 fullsize = [None, 0, 0L]
2699 deltasize = [None, 0, 0L]
2699 deltasize = [None, 0, 0L]
2700
2700
2701 def addsize(size, l):
2701 def addsize(size, l):
2702 if l[0] is None or size < l[0]:
2702 if l[0] is None or size < l[0]:
2703 l[0] = size
2703 l[0] = size
2704 if size > l[1]:
2704 if size > l[1]:
2705 l[1] = size
2705 l[1] = size
2706 l[2] += size
2706 l[2] += size
2707
2707
2708 numrevs = len(r)
2708 numrevs = len(r)
2709 for rev in xrange(numrevs):
2709 for rev in xrange(numrevs):
2710 p1, p2 = r.parentrevs(rev)
2710 p1, p2 = r.parentrevs(rev)
2711 delta = r.deltaparent(rev)
2711 delta = r.deltaparent(rev)
2712 if format > 0:
2712 if format > 0:
2713 addsize(r.rawsize(rev), datasize)
2713 addsize(r.rawsize(rev), datasize)
2714 if p2 != nullrev:
2714 if p2 != nullrev:
2715 nummerges += 1
2715 nummerges += 1
2716 size = r.length(rev)
2716 size = r.length(rev)
2717 if delta == nullrev:
2717 if delta == nullrev:
2718 chainlengths.append(0)
2718 chainlengths.append(0)
2719 numfull += 1
2719 numfull += 1
2720 addsize(size, fullsize)
2720 addsize(size, fullsize)
2721 else:
2721 else:
2722 chainlengths.append(chainlengths[delta] + 1)
2722 chainlengths.append(chainlengths[delta] + 1)
2723 addsize(size, deltasize)
2723 addsize(size, deltasize)
2724 if delta == rev - 1:
2724 if delta == rev - 1:
2725 numprev += 1
2725 numprev += 1
2726 if delta == p1:
2726 if delta == p1:
2727 nump1prev += 1
2727 nump1prev += 1
2728 elif delta == p2:
2728 elif delta == p2:
2729 nump2prev += 1
2729 nump2prev += 1
2730 elif delta == p1:
2730 elif delta == p1:
2731 nump1 += 1
2731 nump1 += 1
2732 elif delta == p2:
2732 elif delta == p2:
2733 nump2 += 1
2733 nump2 += 1
2734 elif delta != nullrev:
2734 elif delta != nullrev:
2735 numother += 1
2735 numother += 1
2736
2736
2737 # Adjust size min value for empty cases
2737 # Adjust size min value for empty cases
2738 for size in (datasize, fullsize, deltasize):
2738 for size in (datasize, fullsize, deltasize):
2739 if size[0] is None:
2739 if size[0] is None:
2740 size[0] = 0
2740 size[0] = 0
2741
2741
2742 numdeltas = numrevs - numfull
2742 numdeltas = numrevs - numfull
2743 numoprev = numprev - nump1prev - nump2prev
2743 numoprev = numprev - nump1prev - nump2prev
2744 totalrawsize = datasize[2]
2744 totalrawsize = datasize[2]
2745 datasize[2] /= numrevs
2745 datasize[2] /= numrevs
2746 fulltotal = fullsize[2]
2746 fulltotal = fullsize[2]
2747 fullsize[2] /= numfull
2747 fullsize[2] /= numfull
2748 deltatotal = deltasize[2]
2748 deltatotal = deltasize[2]
2749 if numrevs - numfull > 0:
2749 if numrevs - numfull > 0:
2750 deltasize[2] /= numrevs - numfull
2750 deltasize[2] /= numrevs - numfull
2751 totalsize = fulltotal + deltatotal
2751 totalsize = fulltotal + deltatotal
2752 avgchainlen = sum(chainlengths) / numrevs
2752 avgchainlen = sum(chainlengths) / numrevs
2753 compratio = totalrawsize / totalsize
2753 compratio = totalrawsize / totalsize
2754
2754
2755 basedfmtstr = '%%%dd\n'
2755 basedfmtstr = '%%%dd\n'
2756 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2756 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2757
2757
2758 def dfmtstr(max):
2758 def dfmtstr(max):
2759 return basedfmtstr % len(str(max))
2759 return basedfmtstr % len(str(max))
2760 def pcfmtstr(max, padding=0):
2760 def pcfmtstr(max, padding=0):
2761 return basepcfmtstr % (len(str(max)), ' ' * padding)
2761 return basepcfmtstr % (len(str(max)), ' ' * padding)
2762
2762
2763 def pcfmt(value, total):
2763 def pcfmt(value, total):
2764 return (value, 100 * float(value) / total)
2764 return (value, 100 * float(value) / total)
2765
2765
2766 ui.write(('format : %d\n') % format)
2766 ui.write(('format : %d\n') % format)
2767 ui.write(('flags : %s\n') % ', '.join(flags))
2767 ui.write(('flags : %s\n') % ', '.join(flags))
2768
2768
2769 ui.write('\n')
2769 ui.write('\n')
2770 fmt = pcfmtstr(totalsize)
2770 fmt = pcfmtstr(totalsize)
2771 fmt2 = dfmtstr(totalsize)
2771 fmt2 = dfmtstr(totalsize)
2772 ui.write(('revisions : ') + fmt2 % numrevs)
2772 ui.write(('revisions : ') + fmt2 % numrevs)
2773 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2773 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2774 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2774 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2775 ui.write(('revisions : ') + fmt2 % numrevs)
2775 ui.write(('revisions : ') + fmt2 % numrevs)
2776 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2776 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2777 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2777 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2778 ui.write(('revision size : ') + fmt2 % totalsize)
2778 ui.write(('revision size : ') + fmt2 % totalsize)
2779 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2779 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2780 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2780 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2781
2781
2782 ui.write('\n')
2782 ui.write('\n')
2783 fmt = dfmtstr(max(avgchainlen, compratio))
2783 fmt = dfmtstr(max(avgchainlen, compratio))
2784 ui.write(('avg chain length : ') + fmt % avgchainlen)
2784 ui.write(('avg chain length : ') + fmt % avgchainlen)
2785 ui.write(('compression ratio : ') + fmt % compratio)
2785 ui.write(('compression ratio : ') + fmt % compratio)
2786
2786
2787 if format > 0:
2787 if format > 0:
2788 ui.write('\n')
2788 ui.write('\n')
2789 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2789 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2790 % tuple(datasize))
2790 % tuple(datasize))
2791 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2791 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2792 % tuple(fullsize))
2792 % tuple(fullsize))
2793 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2793 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2794 % tuple(deltasize))
2794 % tuple(deltasize))
2795
2795
2796 if numdeltas > 0:
2796 if numdeltas > 0:
2797 ui.write('\n')
2797 ui.write('\n')
2798 fmt = pcfmtstr(numdeltas)
2798 fmt = pcfmtstr(numdeltas)
2799 fmt2 = pcfmtstr(numdeltas, 4)
2799 fmt2 = pcfmtstr(numdeltas, 4)
2800 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2800 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2801 if numprev > 0:
2801 if numprev > 0:
2802 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2802 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2803 numprev))
2803 numprev))
2804 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2804 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2805 numprev))
2805 numprev))
2806 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2806 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2807 numprev))
2807 numprev))
2808 if gdelta:
2808 if gdelta:
2809 ui.write(('deltas against p1 : ')
2809 ui.write(('deltas against p1 : ')
2810 + fmt % pcfmt(nump1, numdeltas))
2810 + fmt % pcfmt(nump1, numdeltas))
2811 ui.write(('deltas against p2 : ')
2811 ui.write(('deltas against p2 : ')
2812 + fmt % pcfmt(nump2, numdeltas))
2812 + fmt % pcfmt(nump2, numdeltas))
2813 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2813 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2814 numdeltas))
2814 numdeltas))
2815
2815
2816 @command('debugrevspec',
2816 @command('debugrevspec',
2817 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2817 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2818 ('REVSPEC'))
2818 ('REVSPEC'))
2819 def debugrevspec(ui, repo, expr, **opts):
2819 def debugrevspec(ui, repo, expr, **opts):
2820 """parse and apply a revision specification
2820 """parse and apply a revision specification
2821
2821
2822 Use --verbose to print the parsed tree before and after aliases
2822 Use --verbose to print the parsed tree before and after aliases
2823 expansion.
2823 expansion.
2824 """
2824 """
2825 if ui.verbose:
2825 if ui.verbose:
2826 tree = revset.parse(expr)[0]
2826 tree = revset.parse(expr)[0]
2827 ui.note(revset.prettyformat(tree), "\n")
2827 ui.note(revset.prettyformat(tree), "\n")
2828 newtree = revset.findaliases(ui, tree)
2828 newtree = revset.findaliases(ui, tree)
2829 if newtree != tree:
2829 if newtree != tree:
2830 ui.note(revset.prettyformat(newtree), "\n")
2830 ui.note(revset.prettyformat(newtree), "\n")
2831 if opts["optimize"]:
2831 if opts["optimize"]:
2832 weight, optimizedtree = revset.optimize(newtree, True)
2832 weight, optimizedtree = revset.optimize(newtree, True)
2833 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2833 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2834 func = revset.match(ui, expr)
2834 func = revset.match(ui, expr)
2835 for c in func(repo, revset.spanset(repo)):
2835 for c in func(repo, revset.spanset(repo)):
2836 ui.write("%s\n" % c)
2836 ui.write("%s\n" % c)
2837
2837
2838 @command('debugsetparents', [], _('REV1 [REV2]'))
2838 @command('debugsetparents', [], _('REV1 [REV2]'))
2839 def debugsetparents(ui, repo, rev1, rev2=None):
2839 def debugsetparents(ui, repo, rev1, rev2=None):
2840 """manually set the parents of the current working directory
2840 """manually set the parents of the current working directory
2841
2841
2842 This is useful for writing repository conversion tools, but should
2842 This is useful for writing repository conversion tools, but should
2843 be used with care.
2843 be used with care.
2844
2844
2845 Returns 0 on success.
2845 Returns 0 on success.
2846 """
2846 """
2847
2847
2848 r1 = scmutil.revsingle(repo, rev1).node()
2848 r1 = scmutil.revsingle(repo, rev1).node()
2849 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2849 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2850
2850
2851 wlock = repo.wlock()
2851 wlock = repo.wlock()
2852 try:
2852 try:
2853 repo.dirstate.beginparentchange()
2853 repo.dirstate.beginparentchange()
2854 repo.setparents(r1, r2)
2854 repo.setparents(r1, r2)
2855 repo.dirstate.endparentchange()
2855 repo.dirstate.endparentchange()
2856 finally:
2856 finally:
2857 wlock.release()
2857 wlock.release()
2858
2858
2859 @command('debugdirstate|debugstate',
2859 @command('debugdirstate|debugstate',
2860 [('', 'nodates', None, _('do not display the saved mtime')),
2860 [('', 'nodates', None, _('do not display the saved mtime')),
2861 ('', 'datesort', None, _('sort by saved mtime'))],
2861 ('', 'datesort', None, _('sort by saved mtime'))],
2862 _('[OPTION]...'))
2862 _('[OPTION]...'))
2863 def debugstate(ui, repo, nodates=None, datesort=None):
2863 def debugstate(ui, repo, nodates=None, datesort=None):
2864 """show the contents of the current dirstate"""
2864 """show the contents of the current dirstate"""
2865 timestr = ""
2865 timestr = ""
2866 showdate = not nodates
2866 showdate = not nodates
2867 if datesort:
2867 if datesort:
2868 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2868 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2869 else:
2869 else:
2870 keyfunc = None # sort by filename
2870 keyfunc = None # sort by filename
2871 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2871 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2872 if showdate:
2872 if showdate:
2873 if ent[3] == -1:
2873 if ent[3] == -1:
2874 # Pad or slice to locale representation
2874 # Pad or slice to locale representation
2875 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2875 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2876 time.localtime(0)))
2876 time.localtime(0)))
2877 timestr = 'unset'
2877 timestr = 'unset'
2878 timestr = (timestr[:locale_len] +
2878 timestr = (timestr[:locale_len] +
2879 ' ' * (locale_len - len(timestr)))
2879 ' ' * (locale_len - len(timestr)))
2880 else:
2880 else:
2881 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2881 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2882 time.localtime(ent[3]))
2882 time.localtime(ent[3]))
2883 if ent[1] & 020000:
2883 if ent[1] & 020000:
2884 mode = 'lnk'
2884 mode = 'lnk'
2885 else:
2885 else:
2886 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2886 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2887 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2887 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2888 for f in repo.dirstate.copies():
2888 for f in repo.dirstate.copies():
2889 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2889 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2890
2890
2891 @command('debugsub',
2891 @command('debugsub',
2892 [('r', 'rev', '',
2892 [('r', 'rev', '',
2893 _('revision to check'), _('REV'))],
2893 _('revision to check'), _('REV'))],
2894 _('[-r REV] [REV]'))
2894 _('[-r REV] [REV]'))
2895 def debugsub(ui, repo, rev=None):
2895 def debugsub(ui, repo, rev=None):
2896 ctx = scmutil.revsingle(repo, rev, None)
2896 ctx = scmutil.revsingle(repo, rev, None)
2897 for k, v in sorted(ctx.substate.items()):
2897 for k, v in sorted(ctx.substate.items()):
2898 ui.write(('path %s\n') % k)
2898 ui.write(('path %s\n') % k)
2899 ui.write((' source %s\n') % v[0])
2899 ui.write((' source %s\n') % v[0])
2900 ui.write((' revision %s\n') % v[1])
2900 ui.write((' revision %s\n') % v[1])
2901
2901
2902 @command('debugsuccessorssets',
2902 @command('debugsuccessorssets',
2903 [],
2903 [],
2904 _('[REV]'))
2904 _('[REV]'))
2905 def debugsuccessorssets(ui, repo, *revs):
2905 def debugsuccessorssets(ui, repo, *revs):
2906 """show set of successors for revision
2906 """show set of successors for revision
2907
2907
2908 A successors set of changeset A is a consistent group of revisions that
2908 A successors set of changeset A is a consistent group of revisions that
2909 succeed A. It contains non-obsolete changesets only.
2909 succeed A. It contains non-obsolete changesets only.
2910
2910
2911 In most cases a changeset A has a single successors set containing a single
2911 In most cases a changeset A has a single successors set containing a single
2912 successor (changeset A replaced by A').
2912 successor (changeset A replaced by A').
2913
2913
2914 A changeset that is made obsolete with no successors are called "pruned".
2914 A changeset that is made obsolete with no successors are called "pruned".
2915 Such changesets have no successors sets at all.
2915 Such changesets have no successors sets at all.
2916
2916
2917 A changeset that has been "split" will have a successors set containing
2917 A changeset that has been "split" will have a successors set containing
2918 more than one successor.
2918 more than one successor.
2919
2919
2920 A changeset that has been rewritten in multiple different ways is called
2920 A changeset that has been rewritten in multiple different ways is called
2921 "divergent". Such changesets have multiple successor sets (each of which
2921 "divergent". Such changesets have multiple successor sets (each of which
2922 may also be split, i.e. have multiple successors).
2922 may also be split, i.e. have multiple successors).
2923
2923
2924 Results are displayed as follows::
2924 Results are displayed as follows::
2925
2925
2926 <rev1>
2926 <rev1>
2927 <successors-1A>
2927 <successors-1A>
2928 <rev2>
2928 <rev2>
2929 <successors-2A>
2929 <successors-2A>
2930 <successors-2B1> <successors-2B2> <successors-2B3>
2930 <successors-2B1> <successors-2B2> <successors-2B3>
2931
2931
2932 Here rev2 has two possible (i.e. divergent) successors sets. The first
2932 Here rev2 has two possible (i.e. divergent) successors sets. The first
2933 holds one element, whereas the second holds three (i.e. the changeset has
2933 holds one element, whereas the second holds three (i.e. the changeset has
2934 been split).
2934 been split).
2935 """
2935 """
2936 # passed to successorssets caching computation from one call to another
2936 # passed to successorssets caching computation from one call to another
2937 cache = {}
2937 cache = {}
2938 ctx2str = str
2938 ctx2str = str
2939 node2str = short
2939 node2str = short
2940 if ui.debug():
2940 if ui.debug():
2941 def ctx2str(ctx):
2941 def ctx2str(ctx):
2942 return ctx.hex()
2942 return ctx.hex()
2943 node2str = hex
2943 node2str = hex
2944 for rev in scmutil.revrange(repo, revs):
2944 for rev in scmutil.revrange(repo, revs):
2945 ctx = repo[rev]
2945 ctx = repo[rev]
2946 ui.write('%s\n'% ctx2str(ctx))
2946 ui.write('%s\n'% ctx2str(ctx))
2947 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2947 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2948 if succsset:
2948 if succsset:
2949 ui.write(' ')
2949 ui.write(' ')
2950 ui.write(node2str(succsset[0]))
2950 ui.write(node2str(succsset[0]))
2951 for node in succsset[1:]:
2951 for node in succsset[1:]:
2952 ui.write(' ')
2952 ui.write(' ')
2953 ui.write(node2str(node))
2953 ui.write(node2str(node))
2954 ui.write('\n')
2954 ui.write('\n')
2955
2955
2956 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2956 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2957 def debugwalk(ui, repo, *pats, **opts):
2957 def debugwalk(ui, repo, *pats, **opts):
2958 """show how files match on given patterns"""
2958 """show how files match on given patterns"""
2959 m = scmutil.match(repo[None], pats, opts)
2959 m = scmutil.match(repo[None], pats, opts)
2960 items = list(repo.walk(m))
2960 items = list(repo.walk(m))
2961 if not items:
2961 if not items:
2962 return
2962 return
2963 f = lambda fn: fn
2963 f = lambda fn: fn
2964 if ui.configbool('ui', 'slash') and os.sep != '/':
2964 if ui.configbool('ui', 'slash') and os.sep != '/':
2965 f = lambda fn: util.normpath(fn)
2965 f = lambda fn: util.normpath(fn)
2966 fmt = 'f %%-%ds %%-%ds %%s' % (
2966 fmt = 'f %%-%ds %%-%ds %%s' % (
2967 max([len(abs) for abs in items]),
2967 max([len(abs) for abs in items]),
2968 max([len(m.rel(abs)) for abs in items]))
2968 max([len(m.rel(abs)) for abs in items]))
2969 for abs in items:
2969 for abs in items:
2970 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2970 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2971 ui.write("%s\n" % line.rstrip())
2971 ui.write("%s\n" % line.rstrip())
2972
2972
2973 @command('debugwireargs',
2973 @command('debugwireargs',
2974 [('', 'three', '', 'three'),
2974 [('', 'three', '', 'three'),
2975 ('', 'four', '', 'four'),
2975 ('', 'four', '', 'four'),
2976 ('', 'five', '', 'five'),
2976 ('', 'five', '', 'five'),
2977 ] + remoteopts,
2977 ] + remoteopts,
2978 _('REPO [OPTIONS]... [ONE [TWO]]'),
2978 _('REPO [OPTIONS]... [ONE [TWO]]'),
2979 norepo=True)
2979 norepo=True)
2980 def debugwireargs(ui, repopath, *vals, **opts):
2980 def debugwireargs(ui, repopath, *vals, **opts):
2981 repo = hg.peer(ui, opts, repopath)
2981 repo = hg.peer(ui, opts, repopath)
2982 for opt in remoteopts:
2982 for opt in remoteopts:
2983 del opts[opt[1]]
2983 del opts[opt[1]]
2984 args = {}
2984 args = {}
2985 for k, v in opts.iteritems():
2985 for k, v in opts.iteritems():
2986 if v:
2986 if v:
2987 args[k] = v
2987 args[k] = v
2988 # run twice to check that we don't mess up the stream for the next command
2988 # run twice to check that we don't mess up the stream for the next command
2989 res1 = repo.debugwireargs(*vals, **args)
2989 res1 = repo.debugwireargs(*vals, **args)
2990 res2 = repo.debugwireargs(*vals, **args)
2990 res2 = repo.debugwireargs(*vals, **args)
2991 ui.write("%s\n" % res1)
2991 ui.write("%s\n" % res1)
2992 if res1 != res2:
2992 if res1 != res2:
2993 ui.warn("%s\n" % res2)
2993 ui.warn("%s\n" % res2)
2994
2994
2995 @command('^diff',
2995 @command('^diff',
2996 [('r', 'rev', [], _('revision'), _('REV')),
2996 [('r', 'rev', [], _('revision'), _('REV')),
2997 ('c', 'change', '', _('change made by revision'), _('REV'))
2997 ('c', 'change', '', _('change made by revision'), _('REV'))
2998 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2998 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2999 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2999 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3000 inferrepo=True)
3000 inferrepo=True)
3001 def diff(ui, repo, *pats, **opts):
3001 def diff(ui, repo, *pats, **opts):
3002 """diff repository (or selected files)
3002 """diff repository (or selected files)
3003
3003
3004 Show differences between revisions for the specified files.
3004 Show differences between revisions for the specified files.
3005
3005
3006 Differences between files are shown using the unified diff format.
3006 Differences between files are shown using the unified diff format.
3007
3007
3008 .. note::
3008 .. note::
3009
3009
3010 diff may generate unexpected results for merges, as it will
3010 diff may generate unexpected results for merges, as it will
3011 default to comparing against the working directory's first
3011 default to comparing against the working directory's first
3012 parent changeset if no revisions are specified.
3012 parent changeset if no revisions are specified.
3013
3013
3014 When two revision arguments are given, then changes are shown
3014 When two revision arguments are given, then changes are shown
3015 between those revisions. If only one revision is specified then
3015 between those revisions. If only one revision is specified then
3016 that revision is compared to the working directory, and, when no
3016 that revision is compared to the working directory, and, when no
3017 revisions are specified, the working directory files are compared
3017 revisions are specified, the working directory files are compared
3018 to its parent.
3018 to its parent.
3019
3019
3020 Alternatively you can specify -c/--change with a revision to see
3020 Alternatively you can specify -c/--change with a revision to see
3021 the changes in that changeset relative to its first parent.
3021 the changes in that changeset relative to its first parent.
3022
3022
3023 Without the -a/--text option, diff will avoid generating diffs of
3023 Without the -a/--text option, diff will avoid generating diffs of
3024 files it detects as binary. With -a, diff will generate a diff
3024 files it detects as binary. With -a, diff will generate a diff
3025 anyway, probably with undesirable results.
3025 anyway, probably with undesirable results.
3026
3026
3027 Use the -g/--git option to generate diffs in the git extended diff
3027 Use the -g/--git option to generate diffs in the git extended diff
3028 format. For more information, read :hg:`help diffs`.
3028 format. For more information, read :hg:`help diffs`.
3029
3029
3030 .. container:: verbose
3030 .. container:: verbose
3031
3031
3032 Examples:
3032 Examples:
3033
3033
3034 - compare a file in the current working directory to its parent::
3034 - compare a file in the current working directory to its parent::
3035
3035
3036 hg diff foo.c
3036 hg diff foo.c
3037
3037
3038 - compare two historical versions of a directory, with rename info::
3038 - compare two historical versions of a directory, with rename info::
3039
3039
3040 hg diff --git -r 1.0:1.2 lib/
3040 hg diff --git -r 1.0:1.2 lib/
3041
3041
3042 - get change stats relative to the last change on some date::
3042 - get change stats relative to the last change on some date::
3043
3043
3044 hg diff --stat -r "date('may 2')"
3044 hg diff --stat -r "date('may 2')"
3045
3045
3046 - diff all newly-added files that contain a keyword::
3046 - diff all newly-added files that contain a keyword::
3047
3047
3048 hg diff "set:added() and grep(GNU)"
3048 hg diff "set:added() and grep(GNU)"
3049
3049
3050 - compare a revision and its parents::
3050 - compare a revision and its parents::
3051
3051
3052 hg diff -c 9353 # compare against first parent
3052 hg diff -c 9353 # compare against first parent
3053 hg diff -r 9353^:9353 # same using revset syntax
3053 hg diff -r 9353^:9353 # same using revset syntax
3054 hg diff -r 9353^2:9353 # compare against the second parent
3054 hg diff -r 9353^2:9353 # compare against the second parent
3055
3055
3056 Returns 0 on success.
3056 Returns 0 on success.
3057 """
3057 """
3058
3058
3059 revs = opts.get('rev')
3059 revs = opts.get('rev')
3060 change = opts.get('change')
3060 change = opts.get('change')
3061 stat = opts.get('stat')
3061 stat = opts.get('stat')
3062 reverse = opts.get('reverse')
3062 reverse = opts.get('reverse')
3063
3063
3064 if revs and change:
3064 if revs and change:
3065 msg = _('cannot specify --rev and --change at the same time')
3065 msg = _('cannot specify --rev and --change at the same time')
3066 raise util.Abort(msg)
3066 raise util.Abort(msg)
3067 elif change:
3067 elif change:
3068 node2 = scmutil.revsingle(repo, change, None).node()
3068 node2 = scmutil.revsingle(repo, change, None).node()
3069 node1 = repo[node2].p1().node()
3069 node1 = repo[node2].p1().node()
3070 else:
3070 else:
3071 node1, node2 = scmutil.revpair(repo, revs)
3071 node1, node2 = scmutil.revpair(repo, revs)
3072
3072
3073 if reverse:
3073 if reverse:
3074 node1, node2 = node2, node1
3074 node1, node2 = node2, node1
3075
3075
3076 diffopts = patch.diffallopts(ui, opts)
3076 diffopts = patch.diffallopts(ui, opts)
3077 m = scmutil.match(repo[node2], pats, opts)
3077 m = scmutil.match(repo[node2], pats, opts)
3078 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3078 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3079 listsubrepos=opts.get('subrepos'))
3079 listsubrepos=opts.get('subrepos'))
3080
3080
3081 @command('^export',
3081 @command('^export',
3082 [('o', 'output', '',
3082 [('o', 'output', '',
3083 _('print output to file with formatted name'), _('FORMAT')),
3083 _('print output to file with formatted name'), _('FORMAT')),
3084 ('', 'switch-parent', None, _('diff against the second parent')),
3084 ('', 'switch-parent', None, _('diff against the second parent')),
3085 ('r', 'rev', [], _('revisions to export'), _('REV')),
3085 ('r', 'rev', [], _('revisions to export'), _('REV')),
3086 ] + diffopts,
3086 ] + diffopts,
3087 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3087 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3088 def export(ui, repo, *changesets, **opts):
3088 def export(ui, repo, *changesets, **opts):
3089 """dump the header and diffs for one or more changesets
3089 """dump the header and diffs for one or more changesets
3090
3090
3091 Print the changeset header and diffs for one or more revisions.
3091 Print the changeset header and diffs for one or more revisions.
3092 If no revision is given, the parent of the working directory is used.
3092 If no revision is given, the parent of the working directory is used.
3093
3093
3094 The information shown in the changeset header is: author, date,
3094 The information shown in the changeset header is: author, date,
3095 branch name (if non-default), changeset hash, parent(s) and commit
3095 branch name (if non-default), changeset hash, parent(s) and commit
3096 comment.
3096 comment.
3097
3097
3098 .. note::
3098 .. note::
3099
3099
3100 export may generate unexpected diff output for merge
3100 export may generate unexpected diff output for merge
3101 changesets, as it will compare the merge changeset against its
3101 changesets, as it will compare the merge changeset against its
3102 first parent only.
3102 first parent only.
3103
3103
3104 Output may be to a file, in which case the name of the file is
3104 Output may be to a file, in which case the name of the file is
3105 given using a format string. The formatting rules are as follows:
3105 given using a format string. The formatting rules are as follows:
3106
3106
3107 :``%%``: literal "%" character
3107 :``%%``: literal "%" character
3108 :``%H``: changeset hash (40 hexadecimal digits)
3108 :``%H``: changeset hash (40 hexadecimal digits)
3109 :``%N``: number of patches being generated
3109 :``%N``: number of patches being generated
3110 :``%R``: changeset revision number
3110 :``%R``: changeset revision number
3111 :``%b``: basename of the exporting repository
3111 :``%b``: basename of the exporting repository
3112 :``%h``: short-form changeset hash (12 hexadecimal digits)
3112 :``%h``: short-form changeset hash (12 hexadecimal digits)
3113 :``%m``: first line of the commit message (only alphanumeric characters)
3113 :``%m``: first line of the commit message (only alphanumeric characters)
3114 :``%n``: zero-padded sequence number, starting at 1
3114 :``%n``: zero-padded sequence number, starting at 1
3115 :``%r``: zero-padded changeset revision number
3115 :``%r``: zero-padded changeset revision number
3116
3116
3117 Without the -a/--text option, export will avoid generating diffs
3117 Without the -a/--text option, export will avoid generating diffs
3118 of files it detects as binary. With -a, export will generate a
3118 of files it detects as binary. With -a, export will generate a
3119 diff anyway, probably with undesirable results.
3119 diff anyway, probably with undesirable results.
3120
3120
3121 Use the -g/--git option to generate diffs in the git extended diff
3121 Use the -g/--git option to generate diffs in the git extended diff
3122 format. See :hg:`help diffs` for more information.
3122 format. See :hg:`help diffs` for more information.
3123
3123
3124 With the --switch-parent option, the diff will be against the
3124 With the --switch-parent option, the diff will be against the
3125 second parent. It can be useful to review a merge.
3125 second parent. It can be useful to review a merge.
3126
3126
3127 .. container:: verbose
3127 .. container:: verbose
3128
3128
3129 Examples:
3129 Examples:
3130
3130
3131 - use export and import to transplant a bugfix to the current
3131 - use export and import to transplant a bugfix to the current
3132 branch::
3132 branch::
3133
3133
3134 hg export -r 9353 | hg import -
3134 hg export -r 9353 | hg import -
3135
3135
3136 - export all the changesets between two revisions to a file with
3136 - export all the changesets between two revisions to a file with
3137 rename information::
3137 rename information::
3138
3138
3139 hg export --git -r 123:150 > changes.txt
3139 hg export --git -r 123:150 > changes.txt
3140
3140
3141 - split outgoing changes into a series of patches with
3141 - split outgoing changes into a series of patches with
3142 descriptive names::
3142 descriptive names::
3143
3143
3144 hg export -r "outgoing()" -o "%n-%m.patch"
3144 hg export -r "outgoing()" -o "%n-%m.patch"
3145
3145
3146 Returns 0 on success.
3146 Returns 0 on success.
3147 """
3147 """
3148 changesets += tuple(opts.get('rev', []))
3148 changesets += tuple(opts.get('rev', []))
3149 if not changesets:
3149 if not changesets:
3150 changesets = ['.']
3150 changesets = ['.']
3151 revs = scmutil.revrange(repo, changesets)
3151 revs = scmutil.revrange(repo, changesets)
3152 if not revs:
3152 if not revs:
3153 raise util.Abort(_("export requires at least one changeset"))
3153 raise util.Abort(_("export requires at least one changeset"))
3154 if len(revs) > 1:
3154 if len(revs) > 1:
3155 ui.note(_('exporting patches:\n'))
3155 ui.note(_('exporting patches:\n'))
3156 else:
3156 else:
3157 ui.note(_('exporting patch:\n'))
3157 ui.note(_('exporting patch:\n'))
3158 cmdutil.export(repo, revs, template=opts.get('output'),
3158 cmdutil.export(repo, revs, template=opts.get('output'),
3159 switch_parent=opts.get('switch_parent'),
3159 switch_parent=opts.get('switch_parent'),
3160 opts=patch.diffopts(ui, opts))
3160 opts=patch.diffopts(ui, opts))
3161
3161
3162 @command('files',
3162 @command('files',
3163 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3163 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3164 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3164 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3165 ] + walkopts + formatteropts,
3165 ] + walkopts + formatteropts,
3166 _('[OPTION]... [PATTERN]...'))
3166 _('[OPTION]... [PATTERN]...'))
3167 def files(ui, repo, *pats, **opts):
3167 def files(ui, repo, *pats, **opts):
3168 """list tracked files
3168 """list tracked files
3169
3169
3170 Print files under Mercurial control in the working directory or
3170 Print files under Mercurial control in the working directory or
3171 specified revision whose names match the given patterns (excluding
3171 specified revision whose names match the given patterns (excluding
3172 removed files).
3172 removed files).
3173
3173
3174 If no patterns are given to match, this command prints the names
3174 If no patterns are given to match, this command prints the names
3175 of all files under Mercurial control in the working copy.
3175 of all files under Mercurial control in the working copy.
3176
3176
3177 .. container:: verbose
3177 .. container:: verbose
3178
3178
3179 Examples:
3179 Examples:
3180
3180
3181 - list all files under the current directory::
3181 - list all files under the current directory::
3182
3182
3183 hg files .
3183 hg files .
3184
3184
3185 - shows sizes and flags for current revision::
3185 - shows sizes and flags for current revision::
3186
3186
3187 hg files -vr .
3187 hg files -vr .
3188
3188
3189 - list all files named README::
3189 - list all files named README::
3190
3190
3191 hg files -I "**/README"
3191 hg files -I "**/README"
3192
3192
3193 - list all binary files::
3193 - list all binary files::
3194
3194
3195 hg files "set:binary()"
3195 hg files "set:binary()"
3196
3196
3197 - find files containing a regular expression::
3197 - find files containing a regular expression::
3198
3198
3199 hg files "set:grep('bob')"
3199 hg files "set:grep('bob')"
3200
3200
3201 - search tracked file contents with xargs and grep::
3201 - search tracked file contents with xargs and grep::
3202
3202
3203 hg files -0 | xargs -0 grep foo
3203 hg files -0 | xargs -0 grep foo
3204
3204
3205 See :hg:`help patterns` and :hg:`help filesets` for more information
3205 See :hg:`help patterns` and :hg:`help filesets` for more information
3206 on specifying file patterns.
3206 on specifying file patterns.
3207
3207
3208 Returns 0 if a match is found, 1 otherwise.
3208 Returns 0 if a match is found, 1 otherwise.
3209
3209
3210 """
3210 """
3211 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3211 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3212 rev = ctx.rev()
3212 rev = ctx.rev()
3213 ret = 1
3213 ret = 1
3214
3214
3215 end = '\n'
3215 end = '\n'
3216 if opts.get('print0'):
3216 if opts.get('print0'):
3217 end = '\0'
3217 end = '\0'
3218 fm = ui.formatter('files', opts)
3218 fm = ui.formatter('files', opts)
3219 fmt = '%s' + end
3219 fmt = '%s' + end
3220
3220
3221 m = scmutil.match(ctx, pats, opts)
3221 m = scmutil.match(ctx, pats, opts)
3222 ds = repo.dirstate
3222 ds = repo.dirstate
3223 for f in ctx.matches(m):
3223 for f in ctx.matches(m):
3224 if rev is None and ds[f] == 'r':
3224 if rev is None and ds[f] == 'r':
3225 continue
3225 continue
3226 fm.startitem()
3226 fm.startitem()
3227 if ui.verbose:
3227 if ui.verbose:
3228 fc = ctx[f]
3228 fc = ctx[f]
3229 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3229 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3230 fm.data(abspath=f)
3230 fm.data(abspath=f)
3231 fm.write('path', fmt, m.rel(f))
3231 fm.write('path', fmt, m.rel(f))
3232 ret = 0
3232 ret = 0
3233
3233
3234 fm.end()
3234 fm.end()
3235
3235
3236 return ret
3236 return ret
3237
3237
3238 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3238 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3239 def forget(ui, repo, *pats, **opts):
3239 def forget(ui, repo, *pats, **opts):
3240 """forget the specified files on the next commit
3240 """forget the specified files on the next commit
3241
3241
3242 Mark the specified files so they will no longer be tracked
3242 Mark the specified files so they will no longer be tracked
3243 after the next commit.
3243 after the next commit.
3244
3244
3245 This only removes files from the current branch, not from the
3245 This only removes files from the current branch, not from the
3246 entire project history, and it does not delete them from the
3246 entire project history, and it does not delete them from the
3247 working directory.
3247 working directory.
3248
3248
3249 To undo a forget before the next commit, see :hg:`add`.
3249 To undo a forget before the next commit, see :hg:`add`.
3250
3250
3251 .. container:: verbose
3251 .. container:: verbose
3252
3252
3253 Examples:
3253 Examples:
3254
3254
3255 - forget newly-added binary files::
3255 - forget newly-added binary files::
3256
3256
3257 hg forget "set:added() and binary()"
3257 hg forget "set:added() and binary()"
3258
3258
3259 - forget files that would be excluded by .hgignore::
3259 - forget files that would be excluded by .hgignore::
3260
3260
3261 hg forget "set:hgignore()"
3261 hg forget "set:hgignore()"
3262
3262
3263 Returns 0 on success.
3263 Returns 0 on success.
3264 """
3264 """
3265
3265
3266 if not pats:
3266 if not pats:
3267 raise util.Abort(_('no files specified'))
3267 raise util.Abort(_('no files specified'))
3268
3268
3269 m = scmutil.match(repo[None], pats, opts)
3269 m = scmutil.match(repo[None], pats, opts)
3270 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3270 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3271 return rejected and 1 or 0
3271 return rejected and 1 or 0
3272
3272
3273 @command(
3273 @command(
3274 'graft',
3274 'graft',
3275 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3275 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3276 ('c', 'continue', False, _('resume interrupted graft')),
3276 ('c', 'continue', False, _('resume interrupted graft')),
3277 ('e', 'edit', False, _('invoke editor on commit messages')),
3277 ('e', 'edit', False, _('invoke editor on commit messages')),
3278 ('', 'log', None, _('append graft info to log message')),
3278 ('', 'log', None, _('append graft info to log message')),
3279 ('f', 'force', False, _('force graft')),
3279 ('f', 'force', False, _('force graft')),
3280 ('D', 'currentdate', False,
3280 ('D', 'currentdate', False,
3281 _('record the current date as commit date')),
3281 _('record the current date as commit date')),
3282 ('U', 'currentuser', False,
3282 ('U', 'currentuser', False,
3283 _('record the current user as committer'), _('DATE'))]
3283 _('record the current user as committer'), _('DATE'))]
3284 + commitopts2 + mergetoolopts + dryrunopts,
3284 + commitopts2 + mergetoolopts + dryrunopts,
3285 _('[OPTION]... [-r] REV...'))
3285 _('[OPTION]... [-r] REV...'))
3286 def graft(ui, repo, *revs, **opts):
3286 def graft(ui, repo, *revs, **opts):
3287 '''copy changes from other branches onto the current branch
3287 '''copy changes from other branches onto the current branch
3288
3288
3289 This command uses Mercurial's merge logic to copy individual
3289 This command uses Mercurial's merge logic to copy individual
3290 changes from other branches without merging branches in the
3290 changes from other branches without merging branches in the
3291 history graph. This is sometimes known as 'backporting' or
3291 history graph. This is sometimes known as 'backporting' or
3292 'cherry-picking'. By default, graft will copy user, date, and
3292 'cherry-picking'. By default, graft will copy user, date, and
3293 description from the source changesets.
3293 description from the source changesets.
3294
3294
3295 Changesets that are ancestors of the current revision, that have
3295 Changesets that are ancestors of the current revision, that have
3296 already been grafted, or that are merges will be skipped.
3296 already been grafted, or that are merges will be skipped.
3297
3297
3298 If --log is specified, log messages will have a comment appended
3298 If --log is specified, log messages will have a comment appended
3299 of the form::
3299 of the form::
3300
3300
3301 (grafted from CHANGESETHASH)
3301 (grafted from CHANGESETHASH)
3302
3302
3303 If --force is specified, revisions will be grafted even if they
3303 If --force is specified, revisions will be grafted even if they
3304 are already ancestors of or have been grafted to the destination.
3304 are already ancestors of or have been grafted to the destination.
3305 This is useful when the revisions have since been backed out.
3305 This is useful when the revisions have since been backed out.
3306
3306
3307 If a graft merge results in conflicts, the graft process is
3307 If a graft merge results in conflicts, the graft process is
3308 interrupted so that the current merge can be manually resolved.
3308 interrupted so that the current merge can be manually resolved.
3309 Once all conflicts are addressed, the graft process can be
3309 Once all conflicts are addressed, the graft process can be
3310 continued with the -c/--continue option.
3310 continued with the -c/--continue option.
3311
3311
3312 .. note::
3312 .. note::
3313
3313
3314 The -c/--continue option does not reapply earlier options, except
3314 The -c/--continue option does not reapply earlier options, except
3315 for --force.
3315 for --force.
3316
3316
3317 .. container:: verbose
3317 .. container:: verbose
3318
3318
3319 Examples:
3319 Examples:
3320
3320
3321 - copy a single change to the stable branch and edit its description::
3321 - copy a single change to the stable branch and edit its description::
3322
3322
3323 hg update stable
3323 hg update stable
3324 hg graft --edit 9393
3324 hg graft --edit 9393
3325
3325
3326 - graft a range of changesets with one exception, updating dates::
3326 - graft a range of changesets with one exception, updating dates::
3327
3327
3328 hg graft -D "2085::2093 and not 2091"
3328 hg graft -D "2085::2093 and not 2091"
3329
3329
3330 - continue a graft after resolving conflicts::
3330 - continue a graft after resolving conflicts::
3331
3331
3332 hg graft -c
3332 hg graft -c
3333
3333
3334 - show the source of a grafted changeset::
3334 - show the source of a grafted changeset::
3335
3335
3336 hg log --debug -r .
3336 hg log --debug -r .
3337
3337
3338 See :hg:`help revisions` and :hg:`help revsets` for more about
3338 See :hg:`help revisions` and :hg:`help revsets` for more about
3339 specifying revisions.
3339 specifying revisions.
3340
3340
3341 Returns 0 on successful completion.
3341 Returns 0 on successful completion.
3342 '''
3342 '''
3343
3343
3344 revs = list(revs)
3344 revs = list(revs)
3345 revs.extend(opts['rev'])
3345 revs.extend(opts['rev'])
3346
3346
3347 if not opts.get('user') and opts.get('currentuser'):
3347 if not opts.get('user') and opts.get('currentuser'):
3348 opts['user'] = ui.username()
3348 opts['user'] = ui.username()
3349 if not opts.get('date') and opts.get('currentdate'):
3349 if not opts.get('date') and opts.get('currentdate'):
3350 opts['date'] = "%d %d" % util.makedate()
3350 opts['date'] = "%d %d" % util.makedate()
3351
3351
3352 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3352 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3353
3353
3354 cont = False
3354 cont = False
3355 if opts['continue']:
3355 if opts['continue']:
3356 cont = True
3356 cont = True
3357 if revs:
3357 if revs:
3358 raise util.Abort(_("can't specify --continue and revisions"))
3358 raise util.Abort(_("can't specify --continue and revisions"))
3359 # read in unfinished revisions
3359 # read in unfinished revisions
3360 try:
3360 try:
3361 nodes = repo.opener.read('graftstate').splitlines()
3361 nodes = repo.opener.read('graftstate').splitlines()
3362 revs = [repo[node].rev() for node in nodes]
3362 revs = [repo[node].rev() for node in nodes]
3363 except IOError, inst:
3363 except IOError, inst:
3364 if inst.errno != errno.ENOENT:
3364 if inst.errno != errno.ENOENT:
3365 raise
3365 raise
3366 raise util.Abort(_("no graft state found, can't continue"))
3366 raise util.Abort(_("no graft state found, can't continue"))
3367 else:
3367 else:
3368 cmdutil.checkunfinished(repo)
3368 cmdutil.checkunfinished(repo)
3369 cmdutil.bailifchanged(repo)
3369 cmdutil.bailifchanged(repo)
3370 if not revs:
3370 if not revs:
3371 raise util.Abort(_('no revisions specified'))
3371 raise util.Abort(_('no revisions specified'))
3372 revs = scmutil.revrange(repo, revs)
3372 revs = scmutil.revrange(repo, revs)
3373
3373
3374 skipped = set()
3374 skipped = set()
3375 # check for merges
3375 # check for merges
3376 for rev in repo.revs('%ld and merge()', revs):
3376 for rev in repo.revs('%ld and merge()', revs):
3377 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3377 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3378 skipped.add(rev)
3378 skipped.add(rev)
3379 revs = [r for r in revs if r not in skipped]
3379 revs = [r for r in revs if r not in skipped]
3380 if not revs:
3380 if not revs:
3381 return -1
3381 return -1
3382
3382
3383 # Don't check in the --continue case, in effect retaining --force across
3383 # Don't check in the --continue case, in effect retaining --force across
3384 # --continues. That's because without --force, any revisions we decided to
3384 # --continues. That's because without --force, any revisions we decided to
3385 # skip would have been filtered out here, so they wouldn't have made their
3385 # skip would have been filtered out here, so they wouldn't have made their
3386 # way to the graftstate. With --force, any revisions we would have otherwise
3386 # way to the graftstate. With --force, any revisions we would have otherwise
3387 # skipped would not have been filtered out, and if they hadn't been applied
3387 # skipped would not have been filtered out, and if they hadn't been applied
3388 # already, they'd have been in the graftstate.
3388 # already, they'd have been in the graftstate.
3389 if not (cont or opts.get('force')):
3389 if not (cont or opts.get('force')):
3390 # check for ancestors of dest branch
3390 # check for ancestors of dest branch
3391 crev = repo['.'].rev()
3391 crev = repo['.'].rev()
3392 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3392 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3393 # Cannot use x.remove(y) on smart set, this has to be a list.
3393 # Cannot use x.remove(y) on smart set, this has to be a list.
3394 # XXX make this lazy in the future
3394 # XXX make this lazy in the future
3395 revs = list(revs)
3395 revs = list(revs)
3396 # don't mutate while iterating, create a copy
3396 # don't mutate while iterating, create a copy
3397 for rev in list(revs):
3397 for rev in list(revs):
3398 if rev in ancestors:
3398 if rev in ancestors:
3399 ui.warn(_('skipping ancestor revision %d:%s\n') %
3399 ui.warn(_('skipping ancestor revision %d:%s\n') %
3400 (rev, repo[rev]))
3400 (rev, repo[rev]))
3401 # XXX remove on list is slow
3401 # XXX remove on list is slow
3402 revs.remove(rev)
3402 revs.remove(rev)
3403 if not revs:
3403 if not revs:
3404 return -1
3404 return -1
3405
3405
3406 # analyze revs for earlier grafts
3406 # analyze revs for earlier grafts
3407 ids = {}
3407 ids = {}
3408 for ctx in repo.set("%ld", revs):
3408 for ctx in repo.set("%ld", revs):
3409 ids[ctx.hex()] = ctx.rev()
3409 ids[ctx.hex()] = ctx.rev()
3410 n = ctx.extra().get('source')
3410 n = ctx.extra().get('source')
3411 if n:
3411 if n:
3412 ids[n] = ctx.rev()
3412 ids[n] = ctx.rev()
3413
3413
3414 # check ancestors for earlier grafts
3414 # check ancestors for earlier grafts
3415 ui.debug('scanning for duplicate grafts\n')
3415 ui.debug('scanning for duplicate grafts\n')
3416
3416
3417 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3417 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3418 ctx = repo[rev]
3418 ctx = repo[rev]
3419 n = ctx.extra().get('source')
3419 n = ctx.extra().get('source')
3420 if n in ids:
3420 if n in ids:
3421 try:
3421 try:
3422 r = repo[n].rev()
3422 r = repo[n].rev()
3423 except error.RepoLookupError:
3423 except error.RepoLookupError:
3424 r = None
3424 r = None
3425 if r in revs:
3425 if r in revs:
3426 ui.warn(_('skipping revision %d:%s '
3426 ui.warn(_('skipping revision %d:%s '
3427 '(already grafted to %d:%s)\n')
3427 '(already grafted to %d:%s)\n')
3428 % (r, repo[r], rev, ctx))
3428 % (r, repo[r], rev, ctx))
3429 revs.remove(r)
3429 revs.remove(r)
3430 elif ids[n] in revs:
3430 elif ids[n] in revs:
3431 if r is None:
3431 if r is None:
3432 ui.warn(_('skipping already grafted revision %d:%s '
3432 ui.warn(_('skipping already grafted revision %d:%s '
3433 '(%d:%s also has unknown origin %s)\n')
3433 '(%d:%s also has unknown origin %s)\n')
3434 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3434 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3435 else:
3435 else:
3436 ui.warn(_('skipping already grafted revision %d:%s '
3436 ui.warn(_('skipping already grafted revision %d:%s '
3437 '(%d:%s also has origin %d:%s)\n')
3437 '(%d:%s also has origin %d:%s)\n')
3438 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3438 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3439 revs.remove(ids[n])
3439 revs.remove(ids[n])
3440 elif ctx.hex() in ids:
3440 elif ctx.hex() in ids:
3441 r = ids[ctx.hex()]
3441 r = ids[ctx.hex()]
3442 ui.warn(_('skipping already grafted revision %d:%s '
3442 ui.warn(_('skipping already grafted revision %d:%s '
3443 '(was grafted from %d:%s)\n') %
3443 '(was grafted from %d:%s)\n') %
3444 (r, repo[r], rev, ctx))
3444 (r, repo[r], rev, ctx))
3445 revs.remove(r)
3445 revs.remove(r)
3446 if not revs:
3446 if not revs:
3447 return -1
3447 return -1
3448
3448
3449 wlock = repo.wlock()
3449 wlock = repo.wlock()
3450 try:
3450 try:
3451 for pos, ctx in enumerate(repo.set("%ld", revs)):
3451 for pos, ctx in enumerate(repo.set("%ld", revs)):
3452 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3452 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3453 ctx.description().split('\n', 1)[0])
3453 ctx.description().split('\n', 1)[0])
3454 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3454 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3455 if names:
3455 if names:
3456 desc += ' (%s)' % ' '.join(names)
3456 desc += ' (%s)' % ' '.join(names)
3457 ui.status(_('grafting %s\n') % desc)
3457 ui.status(_('grafting %s\n') % desc)
3458 if opts.get('dry_run'):
3458 if opts.get('dry_run'):
3459 continue
3459 continue
3460
3460
3461 source = ctx.extra().get('source')
3461 source = ctx.extra().get('source')
3462 if not source:
3462 if not source:
3463 source = ctx.hex()
3463 source = ctx.hex()
3464 extra = {'source': source}
3464 extra = {'source': source}
3465 user = ctx.user()
3465 user = ctx.user()
3466 if opts.get('user'):
3466 if opts.get('user'):
3467 user = opts['user']
3467 user = opts['user']
3468 date = ctx.date()
3468 date = ctx.date()
3469 if opts.get('date'):
3469 if opts.get('date'):
3470 date = opts['date']
3470 date = opts['date']
3471 message = ctx.description()
3471 message = ctx.description()
3472 if opts.get('log'):
3472 if opts.get('log'):
3473 message += '\n(grafted from %s)' % ctx.hex()
3473 message += '\n(grafted from %s)' % ctx.hex()
3474
3474
3475 # we don't merge the first commit when continuing
3475 # we don't merge the first commit when continuing
3476 if not cont:
3476 if not cont:
3477 # perform the graft merge with p1(rev) as 'ancestor'
3477 # perform the graft merge with p1(rev) as 'ancestor'
3478 try:
3478 try:
3479 # ui.forcemerge is an internal variable, do not document
3479 # ui.forcemerge is an internal variable, do not document
3480 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3480 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3481 'graft')
3481 'graft')
3482 stats = mergemod.graft(repo, ctx, ctx.p1(),
3482 stats = mergemod.graft(repo, ctx, ctx.p1(),
3483 ['local', 'graft'])
3483 ['local', 'graft'])
3484 finally:
3484 finally:
3485 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3485 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3486 # report any conflicts
3486 # report any conflicts
3487 if stats and stats[3] > 0:
3487 if stats and stats[3] > 0:
3488 # write out state for --continue
3488 # write out state for --continue
3489 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3489 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3490 repo.opener.write('graftstate', ''.join(nodelines))
3490 repo.opener.write('graftstate', ''.join(nodelines))
3491 raise util.Abort(
3491 raise util.Abort(
3492 _("unresolved conflicts, can't continue"),
3492 _("unresolved conflicts, can't continue"),
3493 hint=_('use hg resolve and hg graft --continue'))
3493 hint=_('use hg resolve and hg graft --continue'))
3494 else:
3494 else:
3495 cont = False
3495 cont = False
3496
3496
3497 # commit
3497 # commit
3498 node = repo.commit(text=message, user=user,
3498 node = repo.commit(text=message, user=user,
3499 date=date, extra=extra, editor=editor)
3499 date=date, extra=extra, editor=editor)
3500 if node is None:
3500 if node is None:
3501 ui.warn(_('note: graft of %s created no changes to commit\n') %
3501 ui.warn(
3502 desc)
3502 _('note: graft of %d:%s created no changes to commit\n') %
3503 (ctx.rev(), ctx))
3503 finally:
3504 finally:
3504 wlock.release()
3505 wlock.release()
3505
3506
3506 # remove state when we complete successfully
3507 # remove state when we complete successfully
3507 if not opts.get('dry_run'):
3508 if not opts.get('dry_run'):
3508 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3509 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3509
3510
3510 return 0
3511 return 0
3511
3512
3512 @command('grep',
3513 @command('grep',
3513 [('0', 'print0', None, _('end fields with NUL')),
3514 [('0', 'print0', None, _('end fields with NUL')),
3514 ('', 'all', None, _('print all revisions that match')),
3515 ('', 'all', None, _('print all revisions that match')),
3515 ('a', 'text', None, _('treat all files as text')),
3516 ('a', 'text', None, _('treat all files as text')),
3516 ('f', 'follow', None,
3517 ('f', 'follow', None,
3517 _('follow changeset history,'
3518 _('follow changeset history,'
3518 ' or file history across copies and renames')),
3519 ' or file history across copies and renames')),
3519 ('i', 'ignore-case', None, _('ignore case when matching')),
3520 ('i', 'ignore-case', None, _('ignore case when matching')),
3520 ('l', 'files-with-matches', None,
3521 ('l', 'files-with-matches', None,
3521 _('print only filenames and revisions that match')),
3522 _('print only filenames and revisions that match')),
3522 ('n', 'line-number', None, _('print matching line numbers')),
3523 ('n', 'line-number', None, _('print matching line numbers')),
3523 ('r', 'rev', [],
3524 ('r', 'rev', [],
3524 _('only search files changed within revision range'), _('REV')),
3525 _('only search files changed within revision range'), _('REV')),
3525 ('u', 'user', None, _('list the author (long with -v)')),
3526 ('u', 'user', None, _('list the author (long with -v)')),
3526 ('d', 'date', None, _('list the date (short with -q)')),
3527 ('d', 'date', None, _('list the date (short with -q)')),
3527 ] + walkopts,
3528 ] + walkopts,
3528 _('[OPTION]... PATTERN [FILE]...'),
3529 _('[OPTION]... PATTERN [FILE]...'),
3529 inferrepo=True)
3530 inferrepo=True)
3530 def grep(ui, repo, pattern, *pats, **opts):
3531 def grep(ui, repo, pattern, *pats, **opts):
3531 """search for a pattern in specified files and revisions
3532 """search for a pattern in specified files and revisions
3532
3533
3533 Search revisions of files for a regular expression.
3534 Search revisions of files for a regular expression.
3534
3535
3535 This command behaves differently than Unix grep. It only accepts
3536 This command behaves differently than Unix grep. It only accepts
3536 Python/Perl regexps. It searches repository history, not the
3537 Python/Perl regexps. It searches repository history, not the
3537 working directory. It always prints the revision number in which a
3538 working directory. It always prints the revision number in which a
3538 match appears.
3539 match appears.
3539
3540
3540 By default, grep only prints output for the first revision of a
3541 By default, grep only prints output for the first revision of a
3541 file in which it finds a match. To get it to print every revision
3542 file in which it finds a match. To get it to print every revision
3542 that contains a change in match status ("-" for a match that
3543 that contains a change in match status ("-" for a match that
3543 becomes a non-match, or "+" for a non-match that becomes a match),
3544 becomes a non-match, or "+" for a non-match that becomes a match),
3544 use the --all flag.
3545 use the --all flag.
3545
3546
3546 Returns 0 if a match is found, 1 otherwise.
3547 Returns 0 if a match is found, 1 otherwise.
3547 """
3548 """
3548 reflags = re.M
3549 reflags = re.M
3549 if opts.get('ignore_case'):
3550 if opts.get('ignore_case'):
3550 reflags |= re.I
3551 reflags |= re.I
3551 try:
3552 try:
3552 regexp = util.re.compile(pattern, reflags)
3553 regexp = util.re.compile(pattern, reflags)
3553 except re.error, inst:
3554 except re.error, inst:
3554 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3555 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3555 return 1
3556 return 1
3556 sep, eol = ':', '\n'
3557 sep, eol = ':', '\n'
3557 if opts.get('print0'):
3558 if opts.get('print0'):
3558 sep = eol = '\0'
3559 sep = eol = '\0'
3559
3560
3560 getfile = util.lrucachefunc(repo.file)
3561 getfile = util.lrucachefunc(repo.file)
3561
3562
3562 def matchlines(body):
3563 def matchlines(body):
3563 begin = 0
3564 begin = 0
3564 linenum = 0
3565 linenum = 0
3565 while begin < len(body):
3566 while begin < len(body):
3566 match = regexp.search(body, begin)
3567 match = regexp.search(body, begin)
3567 if not match:
3568 if not match:
3568 break
3569 break
3569 mstart, mend = match.span()
3570 mstart, mend = match.span()
3570 linenum += body.count('\n', begin, mstart) + 1
3571 linenum += body.count('\n', begin, mstart) + 1
3571 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3572 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3572 begin = body.find('\n', mend) + 1 or len(body) + 1
3573 begin = body.find('\n', mend) + 1 or len(body) + 1
3573 lend = begin - 1
3574 lend = begin - 1
3574 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3575 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3575
3576
3576 class linestate(object):
3577 class linestate(object):
3577 def __init__(self, line, linenum, colstart, colend):
3578 def __init__(self, line, linenum, colstart, colend):
3578 self.line = line
3579 self.line = line
3579 self.linenum = linenum
3580 self.linenum = linenum
3580 self.colstart = colstart
3581 self.colstart = colstart
3581 self.colend = colend
3582 self.colend = colend
3582
3583
3583 def __hash__(self):
3584 def __hash__(self):
3584 return hash((self.linenum, self.line))
3585 return hash((self.linenum, self.line))
3585
3586
3586 def __eq__(self, other):
3587 def __eq__(self, other):
3587 return self.line == other.line
3588 return self.line == other.line
3588
3589
3589 def __iter__(self):
3590 def __iter__(self):
3590 yield (self.line[:self.colstart], '')
3591 yield (self.line[:self.colstart], '')
3591 yield (self.line[self.colstart:self.colend], 'grep.match')
3592 yield (self.line[self.colstart:self.colend], 'grep.match')
3592 rest = self.line[self.colend:]
3593 rest = self.line[self.colend:]
3593 while rest != '':
3594 while rest != '':
3594 match = regexp.search(rest)
3595 match = regexp.search(rest)
3595 if not match:
3596 if not match:
3596 yield (rest, '')
3597 yield (rest, '')
3597 break
3598 break
3598 mstart, mend = match.span()
3599 mstart, mend = match.span()
3599 yield (rest[:mstart], '')
3600 yield (rest[:mstart], '')
3600 yield (rest[mstart:mend], 'grep.match')
3601 yield (rest[mstart:mend], 'grep.match')
3601 rest = rest[mend:]
3602 rest = rest[mend:]
3602
3603
3603 matches = {}
3604 matches = {}
3604 copies = {}
3605 copies = {}
3605 def grepbody(fn, rev, body):
3606 def grepbody(fn, rev, body):
3606 matches[rev].setdefault(fn, [])
3607 matches[rev].setdefault(fn, [])
3607 m = matches[rev][fn]
3608 m = matches[rev][fn]
3608 for lnum, cstart, cend, line in matchlines(body):
3609 for lnum, cstart, cend, line in matchlines(body):
3609 s = linestate(line, lnum, cstart, cend)
3610 s = linestate(line, lnum, cstart, cend)
3610 m.append(s)
3611 m.append(s)
3611
3612
3612 def difflinestates(a, b):
3613 def difflinestates(a, b):
3613 sm = difflib.SequenceMatcher(None, a, b)
3614 sm = difflib.SequenceMatcher(None, a, b)
3614 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3615 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3615 if tag == 'insert':
3616 if tag == 'insert':
3616 for i in xrange(blo, bhi):
3617 for i in xrange(blo, bhi):
3617 yield ('+', b[i])
3618 yield ('+', b[i])
3618 elif tag == 'delete':
3619 elif tag == 'delete':
3619 for i in xrange(alo, ahi):
3620 for i in xrange(alo, ahi):
3620 yield ('-', a[i])
3621 yield ('-', a[i])
3621 elif tag == 'replace':
3622 elif tag == 'replace':
3622 for i in xrange(alo, ahi):
3623 for i in xrange(alo, ahi):
3623 yield ('-', a[i])
3624 yield ('-', a[i])
3624 for i in xrange(blo, bhi):
3625 for i in xrange(blo, bhi):
3625 yield ('+', b[i])
3626 yield ('+', b[i])
3626
3627
3627 def display(fn, ctx, pstates, states):
3628 def display(fn, ctx, pstates, states):
3628 rev = ctx.rev()
3629 rev = ctx.rev()
3629 datefunc = ui.quiet and util.shortdate or util.datestr
3630 datefunc = ui.quiet and util.shortdate or util.datestr
3630 found = False
3631 found = False
3631 @util.cachefunc
3632 @util.cachefunc
3632 def binary():
3633 def binary():
3633 flog = getfile(fn)
3634 flog = getfile(fn)
3634 return util.binary(flog.read(ctx.filenode(fn)))
3635 return util.binary(flog.read(ctx.filenode(fn)))
3635
3636
3636 if opts.get('all'):
3637 if opts.get('all'):
3637 iter = difflinestates(pstates, states)
3638 iter = difflinestates(pstates, states)
3638 else:
3639 else:
3639 iter = [('', l) for l in states]
3640 iter = [('', l) for l in states]
3640 for change, l in iter:
3641 for change, l in iter:
3641 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3642 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3642
3643
3643 if opts.get('line_number'):
3644 if opts.get('line_number'):
3644 cols.append((str(l.linenum), 'grep.linenumber'))
3645 cols.append((str(l.linenum), 'grep.linenumber'))
3645 if opts.get('all'):
3646 if opts.get('all'):
3646 cols.append((change, 'grep.change'))
3647 cols.append((change, 'grep.change'))
3647 if opts.get('user'):
3648 if opts.get('user'):
3648 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3649 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3649 if opts.get('date'):
3650 if opts.get('date'):
3650 cols.append((datefunc(ctx.date()), 'grep.date'))
3651 cols.append((datefunc(ctx.date()), 'grep.date'))
3651 for col, label in cols[:-1]:
3652 for col, label in cols[:-1]:
3652 ui.write(col, label=label)
3653 ui.write(col, label=label)
3653 ui.write(sep, label='grep.sep')
3654 ui.write(sep, label='grep.sep')
3654 ui.write(cols[-1][0], label=cols[-1][1])
3655 ui.write(cols[-1][0], label=cols[-1][1])
3655 if not opts.get('files_with_matches'):
3656 if not opts.get('files_with_matches'):
3656 ui.write(sep, label='grep.sep')
3657 ui.write(sep, label='grep.sep')
3657 if not opts.get('text') and binary():
3658 if not opts.get('text') and binary():
3658 ui.write(" Binary file matches")
3659 ui.write(" Binary file matches")
3659 else:
3660 else:
3660 for s, label in l:
3661 for s, label in l:
3661 ui.write(s, label=label)
3662 ui.write(s, label=label)
3662 ui.write(eol)
3663 ui.write(eol)
3663 found = True
3664 found = True
3664 if opts.get('files_with_matches'):
3665 if opts.get('files_with_matches'):
3665 break
3666 break
3666 return found
3667 return found
3667
3668
3668 skip = {}
3669 skip = {}
3669 revfiles = {}
3670 revfiles = {}
3670 matchfn = scmutil.match(repo[None], pats, opts)
3671 matchfn = scmutil.match(repo[None], pats, opts)
3671 found = False
3672 found = False
3672 follow = opts.get('follow')
3673 follow = opts.get('follow')
3673
3674
3674 def prep(ctx, fns):
3675 def prep(ctx, fns):
3675 rev = ctx.rev()
3676 rev = ctx.rev()
3676 pctx = ctx.p1()
3677 pctx = ctx.p1()
3677 parent = pctx.rev()
3678 parent = pctx.rev()
3678 matches.setdefault(rev, {})
3679 matches.setdefault(rev, {})
3679 matches.setdefault(parent, {})
3680 matches.setdefault(parent, {})
3680 files = revfiles.setdefault(rev, [])
3681 files = revfiles.setdefault(rev, [])
3681 for fn in fns:
3682 for fn in fns:
3682 flog = getfile(fn)
3683 flog = getfile(fn)
3683 try:
3684 try:
3684 fnode = ctx.filenode(fn)
3685 fnode = ctx.filenode(fn)
3685 except error.LookupError:
3686 except error.LookupError:
3686 continue
3687 continue
3687
3688
3688 copied = flog.renamed(fnode)
3689 copied = flog.renamed(fnode)
3689 copy = follow and copied and copied[0]
3690 copy = follow and copied and copied[0]
3690 if copy:
3691 if copy:
3691 copies.setdefault(rev, {})[fn] = copy
3692 copies.setdefault(rev, {})[fn] = copy
3692 if fn in skip:
3693 if fn in skip:
3693 if copy:
3694 if copy:
3694 skip[copy] = True
3695 skip[copy] = True
3695 continue
3696 continue
3696 files.append(fn)
3697 files.append(fn)
3697
3698
3698 if fn not in matches[rev]:
3699 if fn not in matches[rev]:
3699 grepbody(fn, rev, flog.read(fnode))
3700 grepbody(fn, rev, flog.read(fnode))
3700
3701
3701 pfn = copy or fn
3702 pfn = copy or fn
3702 if pfn not in matches[parent]:
3703 if pfn not in matches[parent]:
3703 try:
3704 try:
3704 fnode = pctx.filenode(pfn)
3705 fnode = pctx.filenode(pfn)
3705 grepbody(pfn, parent, flog.read(fnode))
3706 grepbody(pfn, parent, flog.read(fnode))
3706 except error.LookupError:
3707 except error.LookupError:
3707 pass
3708 pass
3708
3709
3709 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3710 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3710 rev = ctx.rev()
3711 rev = ctx.rev()
3711 parent = ctx.p1().rev()
3712 parent = ctx.p1().rev()
3712 for fn in sorted(revfiles.get(rev, [])):
3713 for fn in sorted(revfiles.get(rev, [])):
3713 states = matches[rev][fn]
3714 states = matches[rev][fn]
3714 copy = copies.get(rev, {}).get(fn)
3715 copy = copies.get(rev, {}).get(fn)
3715 if fn in skip:
3716 if fn in skip:
3716 if copy:
3717 if copy:
3717 skip[copy] = True
3718 skip[copy] = True
3718 continue
3719 continue
3719 pstates = matches.get(parent, {}).get(copy or fn, [])
3720 pstates = matches.get(parent, {}).get(copy or fn, [])
3720 if pstates or states:
3721 if pstates or states:
3721 r = display(fn, ctx, pstates, states)
3722 r = display(fn, ctx, pstates, states)
3722 found = found or r
3723 found = found or r
3723 if r and not opts.get('all'):
3724 if r and not opts.get('all'):
3724 skip[fn] = True
3725 skip[fn] = True
3725 if copy:
3726 if copy:
3726 skip[copy] = True
3727 skip[copy] = True
3727 del matches[rev]
3728 del matches[rev]
3728 del revfiles[rev]
3729 del revfiles[rev]
3729
3730
3730 return not found
3731 return not found
3731
3732
3732 @command('heads',
3733 @command('heads',
3733 [('r', 'rev', '',
3734 [('r', 'rev', '',
3734 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3735 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3735 ('t', 'topo', False, _('show topological heads only')),
3736 ('t', 'topo', False, _('show topological heads only')),
3736 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3737 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3737 ('c', 'closed', False, _('show normal and closed branch heads')),
3738 ('c', 'closed', False, _('show normal and closed branch heads')),
3738 ] + templateopts,
3739 ] + templateopts,
3739 _('[-ct] [-r STARTREV] [REV]...'))
3740 _('[-ct] [-r STARTREV] [REV]...'))
3740 def heads(ui, repo, *branchrevs, **opts):
3741 def heads(ui, repo, *branchrevs, **opts):
3741 """show branch heads
3742 """show branch heads
3742
3743
3743 With no arguments, show all open branch heads in the repository.
3744 With no arguments, show all open branch heads in the repository.
3744 Branch heads are changesets that have no descendants on the
3745 Branch heads are changesets that have no descendants on the
3745 same branch. They are where development generally takes place and
3746 same branch. They are where development generally takes place and
3746 are the usual targets for update and merge operations.
3747 are the usual targets for update and merge operations.
3747
3748
3748 If one or more REVs are given, only open branch heads on the
3749 If one or more REVs are given, only open branch heads on the
3749 branches associated with the specified changesets are shown. This
3750 branches associated with the specified changesets are shown. This
3750 means that you can use :hg:`heads .` to see the heads on the
3751 means that you can use :hg:`heads .` to see the heads on the
3751 currently checked-out branch.
3752 currently checked-out branch.
3752
3753
3753 If -c/--closed is specified, also show branch heads marked closed
3754 If -c/--closed is specified, also show branch heads marked closed
3754 (see :hg:`commit --close-branch`).
3755 (see :hg:`commit --close-branch`).
3755
3756
3756 If STARTREV is specified, only those heads that are descendants of
3757 If STARTREV is specified, only those heads that are descendants of
3757 STARTREV will be displayed.
3758 STARTREV will be displayed.
3758
3759
3759 If -t/--topo is specified, named branch mechanics will be ignored and only
3760 If -t/--topo is specified, named branch mechanics will be ignored and only
3760 topological heads (changesets with no children) will be shown.
3761 topological heads (changesets with no children) will be shown.
3761
3762
3762 Returns 0 if matching heads are found, 1 if not.
3763 Returns 0 if matching heads are found, 1 if not.
3763 """
3764 """
3764
3765
3765 start = None
3766 start = None
3766 if 'rev' in opts:
3767 if 'rev' in opts:
3767 start = scmutil.revsingle(repo, opts['rev'], None).node()
3768 start = scmutil.revsingle(repo, opts['rev'], None).node()
3768
3769
3769 if opts.get('topo'):
3770 if opts.get('topo'):
3770 heads = [repo[h] for h in repo.heads(start)]
3771 heads = [repo[h] for h in repo.heads(start)]
3771 else:
3772 else:
3772 heads = []
3773 heads = []
3773 for branch in repo.branchmap():
3774 for branch in repo.branchmap():
3774 heads += repo.branchheads(branch, start, opts.get('closed'))
3775 heads += repo.branchheads(branch, start, opts.get('closed'))
3775 heads = [repo[h] for h in heads]
3776 heads = [repo[h] for h in heads]
3776
3777
3777 if branchrevs:
3778 if branchrevs:
3778 branches = set(repo[br].branch() for br in branchrevs)
3779 branches = set(repo[br].branch() for br in branchrevs)
3779 heads = [h for h in heads if h.branch() in branches]
3780 heads = [h for h in heads if h.branch() in branches]
3780
3781
3781 if opts.get('active') and branchrevs:
3782 if opts.get('active') and branchrevs:
3782 dagheads = repo.heads(start)
3783 dagheads = repo.heads(start)
3783 heads = [h for h in heads if h.node() in dagheads]
3784 heads = [h for h in heads if h.node() in dagheads]
3784
3785
3785 if branchrevs:
3786 if branchrevs:
3786 haveheads = set(h.branch() for h in heads)
3787 haveheads = set(h.branch() for h in heads)
3787 if branches - haveheads:
3788 if branches - haveheads:
3788 headless = ', '.join(b for b in branches - haveheads)
3789 headless = ', '.join(b for b in branches - haveheads)
3789 msg = _('no open branch heads found on branches %s')
3790 msg = _('no open branch heads found on branches %s')
3790 if opts.get('rev'):
3791 if opts.get('rev'):
3791 msg += _(' (started at %s)') % opts['rev']
3792 msg += _(' (started at %s)') % opts['rev']
3792 ui.warn((msg + '\n') % headless)
3793 ui.warn((msg + '\n') % headless)
3793
3794
3794 if not heads:
3795 if not heads:
3795 return 1
3796 return 1
3796
3797
3797 heads = sorted(heads, key=lambda x: -x.rev())
3798 heads = sorted(heads, key=lambda x: -x.rev())
3798 displayer = cmdutil.show_changeset(ui, repo, opts)
3799 displayer = cmdutil.show_changeset(ui, repo, opts)
3799 for ctx in heads:
3800 for ctx in heads:
3800 displayer.show(ctx)
3801 displayer.show(ctx)
3801 displayer.close()
3802 displayer.close()
3802
3803
3803 @command('help',
3804 @command('help',
3804 [('e', 'extension', None, _('show only help for extensions')),
3805 [('e', 'extension', None, _('show only help for extensions')),
3805 ('c', 'command', None, _('show only help for commands')),
3806 ('c', 'command', None, _('show only help for commands')),
3806 ('k', 'keyword', '', _('show topics matching keyword')),
3807 ('k', 'keyword', '', _('show topics matching keyword')),
3807 ],
3808 ],
3808 _('[-ec] [TOPIC]'),
3809 _('[-ec] [TOPIC]'),
3809 norepo=True)
3810 norepo=True)
3810 def help_(ui, name=None, **opts):
3811 def help_(ui, name=None, **opts):
3811 """show help for a given topic or a help overview
3812 """show help for a given topic or a help overview
3812
3813
3813 With no arguments, print a list of commands with short help messages.
3814 With no arguments, print a list of commands with short help messages.
3814
3815
3815 Given a topic, extension, or command name, print help for that
3816 Given a topic, extension, or command name, print help for that
3816 topic.
3817 topic.
3817
3818
3818 Returns 0 if successful.
3819 Returns 0 if successful.
3819 """
3820 """
3820
3821
3821 textwidth = min(ui.termwidth(), 80) - 2
3822 textwidth = min(ui.termwidth(), 80) - 2
3822
3823
3823 keep = []
3824 keep = []
3824 if ui.verbose:
3825 if ui.verbose:
3825 keep.append('verbose')
3826 keep.append('verbose')
3826 if sys.platform.startswith('win'):
3827 if sys.platform.startswith('win'):
3827 keep.append('windows')
3828 keep.append('windows')
3828 elif sys.platform == 'OpenVMS':
3829 elif sys.platform == 'OpenVMS':
3829 keep.append('vms')
3830 keep.append('vms')
3830 elif sys.platform == 'plan9':
3831 elif sys.platform == 'plan9':
3831 keep.append('plan9')
3832 keep.append('plan9')
3832 else:
3833 else:
3833 keep.append('unix')
3834 keep.append('unix')
3834 keep.append(sys.platform.lower())
3835 keep.append(sys.platform.lower())
3835
3836
3836 section = None
3837 section = None
3837 if name and '.' in name:
3838 if name and '.' in name:
3838 name, section = name.split('.', 1)
3839 name, section = name.split('.', 1)
3839
3840
3840 text = help.help_(ui, name, **opts)
3841 text = help.help_(ui, name, **opts)
3841
3842
3842 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3843 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3843 section=section)
3844 section=section)
3844 if section and not formatted:
3845 if section and not formatted:
3845 raise util.Abort(_("help section not found"))
3846 raise util.Abort(_("help section not found"))
3846
3847
3847 if 'verbose' in pruned:
3848 if 'verbose' in pruned:
3848 keep.append('omitted')
3849 keep.append('omitted')
3849 else:
3850 else:
3850 keep.append('notomitted')
3851 keep.append('notomitted')
3851 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3852 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3852 section=section)
3853 section=section)
3853 ui.write(formatted)
3854 ui.write(formatted)
3854
3855
3855
3856
3856 @command('identify|id',
3857 @command('identify|id',
3857 [('r', 'rev', '',
3858 [('r', 'rev', '',
3858 _('identify the specified revision'), _('REV')),
3859 _('identify the specified revision'), _('REV')),
3859 ('n', 'num', None, _('show local revision number')),
3860 ('n', 'num', None, _('show local revision number')),
3860 ('i', 'id', None, _('show global revision id')),
3861 ('i', 'id', None, _('show global revision id')),
3861 ('b', 'branch', None, _('show branch')),
3862 ('b', 'branch', None, _('show branch')),
3862 ('t', 'tags', None, _('show tags')),
3863 ('t', 'tags', None, _('show tags')),
3863 ('B', 'bookmarks', None, _('show bookmarks')),
3864 ('B', 'bookmarks', None, _('show bookmarks')),
3864 ] + remoteopts,
3865 ] + remoteopts,
3865 _('[-nibtB] [-r REV] [SOURCE]'),
3866 _('[-nibtB] [-r REV] [SOURCE]'),
3866 optionalrepo=True)
3867 optionalrepo=True)
3867 def identify(ui, repo, source=None, rev=None,
3868 def identify(ui, repo, source=None, rev=None,
3868 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3869 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3869 """identify the working copy or specified revision
3870 """identify the working copy or specified revision
3870
3871
3871 Print a summary identifying the repository state at REV using one or
3872 Print a summary identifying the repository state at REV using one or
3872 two parent hash identifiers, followed by a "+" if the working
3873 two parent hash identifiers, followed by a "+" if the working
3873 directory has uncommitted changes, the branch name (if not default),
3874 directory has uncommitted changes, the branch name (if not default),
3874 a list of tags, and a list of bookmarks.
3875 a list of tags, and a list of bookmarks.
3875
3876
3876 When REV is not given, print a summary of the current state of the
3877 When REV is not given, print a summary of the current state of the
3877 repository.
3878 repository.
3878
3879
3879 Specifying a path to a repository root or Mercurial bundle will
3880 Specifying a path to a repository root or Mercurial bundle will
3880 cause lookup to operate on that repository/bundle.
3881 cause lookup to operate on that repository/bundle.
3881
3882
3882 .. container:: verbose
3883 .. container:: verbose
3883
3884
3884 Examples:
3885 Examples:
3885
3886
3886 - generate a build identifier for the working directory::
3887 - generate a build identifier for the working directory::
3887
3888
3888 hg id --id > build-id.dat
3889 hg id --id > build-id.dat
3889
3890
3890 - find the revision corresponding to a tag::
3891 - find the revision corresponding to a tag::
3891
3892
3892 hg id -n -r 1.3
3893 hg id -n -r 1.3
3893
3894
3894 - check the most recent revision of a remote repository::
3895 - check the most recent revision of a remote repository::
3895
3896
3896 hg id -r tip http://selenic.com/hg/
3897 hg id -r tip http://selenic.com/hg/
3897
3898
3898 Returns 0 if successful.
3899 Returns 0 if successful.
3899 """
3900 """
3900
3901
3901 if not repo and not source:
3902 if not repo and not source:
3902 raise util.Abort(_("there is no Mercurial repository here "
3903 raise util.Abort(_("there is no Mercurial repository here "
3903 "(.hg not found)"))
3904 "(.hg not found)"))
3904
3905
3905 hexfunc = ui.debugflag and hex or short
3906 hexfunc = ui.debugflag and hex or short
3906 default = not (num or id or branch or tags or bookmarks)
3907 default = not (num or id or branch or tags or bookmarks)
3907 output = []
3908 output = []
3908 revs = []
3909 revs = []
3909
3910
3910 if source:
3911 if source:
3911 source, branches = hg.parseurl(ui.expandpath(source))
3912 source, branches = hg.parseurl(ui.expandpath(source))
3912 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3913 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3913 repo = peer.local()
3914 repo = peer.local()
3914 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3915 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3915
3916
3916 if not repo:
3917 if not repo:
3917 if num or branch or tags:
3918 if num or branch or tags:
3918 raise util.Abort(
3919 raise util.Abort(
3919 _("can't query remote revision number, branch, or tags"))
3920 _("can't query remote revision number, branch, or tags"))
3920 if not rev and revs:
3921 if not rev and revs:
3921 rev = revs[0]
3922 rev = revs[0]
3922 if not rev:
3923 if not rev:
3923 rev = "tip"
3924 rev = "tip"
3924
3925
3925 remoterev = peer.lookup(rev)
3926 remoterev = peer.lookup(rev)
3926 if default or id:
3927 if default or id:
3927 output = [hexfunc(remoterev)]
3928 output = [hexfunc(remoterev)]
3928
3929
3929 def getbms():
3930 def getbms():
3930 bms = []
3931 bms = []
3931
3932
3932 if 'bookmarks' in peer.listkeys('namespaces'):
3933 if 'bookmarks' in peer.listkeys('namespaces'):
3933 hexremoterev = hex(remoterev)
3934 hexremoterev = hex(remoterev)
3934 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3935 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3935 if bmr == hexremoterev]
3936 if bmr == hexremoterev]
3936
3937
3937 return sorted(bms)
3938 return sorted(bms)
3938
3939
3939 if bookmarks:
3940 if bookmarks:
3940 output.extend(getbms())
3941 output.extend(getbms())
3941 elif default and not ui.quiet:
3942 elif default and not ui.quiet:
3942 # multiple bookmarks for a single parent separated by '/'
3943 # multiple bookmarks for a single parent separated by '/'
3943 bm = '/'.join(getbms())
3944 bm = '/'.join(getbms())
3944 if bm:
3945 if bm:
3945 output.append(bm)
3946 output.append(bm)
3946 else:
3947 else:
3947 if not rev:
3948 if not rev:
3948 ctx = repo[None]
3949 ctx = repo[None]
3949 parents = ctx.parents()
3950 parents = ctx.parents()
3950 changed = ""
3951 changed = ""
3951 if default or id or num:
3952 if default or id or num:
3952 if (util.any(repo.status())
3953 if (util.any(repo.status())
3953 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3954 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3954 changed = '+'
3955 changed = '+'
3955 if default or id:
3956 if default or id:
3956 output = ["%s%s" %
3957 output = ["%s%s" %
3957 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3958 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3958 if num:
3959 if num:
3959 output.append("%s%s" %
3960 output.append("%s%s" %
3960 ('+'.join([str(p.rev()) for p in parents]), changed))
3961 ('+'.join([str(p.rev()) for p in parents]), changed))
3961 else:
3962 else:
3962 ctx = scmutil.revsingle(repo, rev)
3963 ctx = scmutil.revsingle(repo, rev)
3963 if default or id:
3964 if default or id:
3964 output = [hexfunc(ctx.node())]
3965 output = [hexfunc(ctx.node())]
3965 if num:
3966 if num:
3966 output.append(str(ctx.rev()))
3967 output.append(str(ctx.rev()))
3967
3968
3968 if default and not ui.quiet:
3969 if default and not ui.quiet:
3969 b = ctx.branch()
3970 b = ctx.branch()
3970 if b != 'default':
3971 if b != 'default':
3971 output.append("(%s)" % b)
3972 output.append("(%s)" % b)
3972
3973
3973 # multiple tags for a single parent separated by '/'
3974 # multiple tags for a single parent separated by '/'
3974 t = '/'.join(ctx.tags())
3975 t = '/'.join(ctx.tags())
3975 if t:
3976 if t:
3976 output.append(t)
3977 output.append(t)
3977
3978
3978 # multiple bookmarks for a single parent separated by '/'
3979 # multiple bookmarks for a single parent separated by '/'
3979 bm = '/'.join(ctx.bookmarks())
3980 bm = '/'.join(ctx.bookmarks())
3980 if bm:
3981 if bm:
3981 output.append(bm)
3982 output.append(bm)
3982 else:
3983 else:
3983 if branch:
3984 if branch:
3984 output.append(ctx.branch())
3985 output.append(ctx.branch())
3985
3986
3986 if tags:
3987 if tags:
3987 output.extend(ctx.tags())
3988 output.extend(ctx.tags())
3988
3989
3989 if bookmarks:
3990 if bookmarks:
3990 output.extend(ctx.bookmarks())
3991 output.extend(ctx.bookmarks())
3991
3992
3992 ui.write("%s\n" % ' '.join(output))
3993 ui.write("%s\n" % ' '.join(output))
3993
3994
3994 @command('import|patch',
3995 @command('import|patch',
3995 [('p', 'strip', 1,
3996 [('p', 'strip', 1,
3996 _('directory strip option for patch. This has the same '
3997 _('directory strip option for patch. This has the same '
3997 'meaning as the corresponding patch option'), _('NUM')),
3998 'meaning as the corresponding patch option'), _('NUM')),
3998 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3999 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3999 ('e', 'edit', False, _('invoke editor on commit messages')),
4000 ('e', 'edit', False, _('invoke editor on commit messages')),
4000 ('f', 'force', None,
4001 ('f', 'force', None,
4001 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4002 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4002 ('', 'no-commit', None,
4003 ('', 'no-commit', None,
4003 _("don't commit, just update the working directory")),
4004 _("don't commit, just update the working directory")),
4004 ('', 'bypass', None,
4005 ('', 'bypass', None,
4005 _("apply patch without touching the working directory")),
4006 _("apply patch without touching the working directory")),
4006 ('', 'partial', None,
4007 ('', 'partial', None,
4007 _('commit even if some hunks fail')),
4008 _('commit even if some hunks fail')),
4008 ('', 'exact', None,
4009 ('', 'exact', None,
4009 _('apply patch to the nodes from which it was generated')),
4010 _('apply patch to the nodes from which it was generated')),
4010 ('', 'import-branch', None,
4011 ('', 'import-branch', None,
4011 _('use any branch information in patch (implied by --exact)'))] +
4012 _('use any branch information in patch (implied by --exact)'))] +
4012 commitopts + commitopts2 + similarityopts,
4013 commitopts + commitopts2 + similarityopts,
4013 _('[OPTION]... PATCH...'))
4014 _('[OPTION]... PATCH...'))
4014 def import_(ui, repo, patch1=None, *patches, **opts):
4015 def import_(ui, repo, patch1=None, *patches, **opts):
4015 """import an ordered set of patches
4016 """import an ordered set of patches
4016
4017
4017 Import a list of patches and commit them individually (unless
4018 Import a list of patches and commit them individually (unless
4018 --no-commit is specified).
4019 --no-commit is specified).
4019
4020
4020 Because import first applies changes to the working directory,
4021 Because import first applies changes to the working directory,
4021 import will abort if there are outstanding changes.
4022 import will abort if there are outstanding changes.
4022
4023
4023 You can import a patch straight from a mail message. Even patches
4024 You can import a patch straight from a mail message. Even patches
4024 as attachments work (to use the body part, it must have type
4025 as attachments work (to use the body part, it must have type
4025 text/plain or text/x-patch). From and Subject headers of email
4026 text/plain or text/x-patch). From and Subject headers of email
4026 message are used as default committer and commit message. All
4027 message are used as default committer and commit message. All
4027 text/plain body parts before first diff are added to commit
4028 text/plain body parts before first diff are added to commit
4028 message.
4029 message.
4029
4030
4030 If the imported patch was generated by :hg:`export`, user and
4031 If the imported patch was generated by :hg:`export`, user and
4031 description from patch override values from message headers and
4032 description from patch override values from message headers and
4032 body. Values given on command line with -m/--message and -u/--user
4033 body. Values given on command line with -m/--message and -u/--user
4033 override these.
4034 override these.
4034
4035
4035 If --exact is specified, import will set the working directory to
4036 If --exact is specified, import will set the working directory to
4036 the parent of each patch before applying it, and will abort if the
4037 the parent of each patch before applying it, and will abort if the
4037 resulting changeset has a different ID than the one recorded in
4038 resulting changeset has a different ID than the one recorded in
4038 the patch. This may happen due to character set problems or other
4039 the patch. This may happen due to character set problems or other
4039 deficiencies in the text patch format.
4040 deficiencies in the text patch format.
4040
4041
4041 Use --bypass to apply and commit patches directly to the
4042 Use --bypass to apply and commit patches directly to the
4042 repository, not touching the working directory. Without --exact,
4043 repository, not touching the working directory. Without --exact,
4043 patches will be applied on top of the working directory parent
4044 patches will be applied on top of the working directory parent
4044 revision.
4045 revision.
4045
4046
4046 With -s/--similarity, hg will attempt to discover renames and
4047 With -s/--similarity, hg will attempt to discover renames and
4047 copies in the patch in the same way as :hg:`addremove`.
4048 copies in the patch in the same way as :hg:`addremove`.
4048
4049
4049 Use --partial to ensure a changeset will be created from the patch
4050 Use --partial to ensure a changeset will be created from the patch
4050 even if some hunks fail to apply. Hunks that fail to apply will be
4051 even if some hunks fail to apply. Hunks that fail to apply will be
4051 written to a <target-file>.rej file. Conflicts can then be resolved
4052 written to a <target-file>.rej file. Conflicts can then be resolved
4052 by hand before :hg:`commit --amend` is run to update the created
4053 by hand before :hg:`commit --amend` is run to update the created
4053 changeset. This flag exists to let people import patches that
4054 changeset. This flag exists to let people import patches that
4054 partially apply without losing the associated metadata (author,
4055 partially apply without losing the associated metadata (author,
4055 date, description, ...). Note that when none of the hunk applies
4056 date, description, ...). Note that when none of the hunk applies
4056 cleanly, :hg:`import --partial` will create an empty changeset,
4057 cleanly, :hg:`import --partial` will create an empty changeset,
4057 importing only the patch metadata.
4058 importing only the patch metadata.
4058
4059
4059 To read a patch from standard input, use "-" as the patch name. If
4060 To read a patch from standard input, use "-" as the patch name. If
4060 a URL is specified, the patch will be downloaded from it.
4061 a URL is specified, the patch will be downloaded from it.
4061 See :hg:`help dates` for a list of formats valid for -d/--date.
4062 See :hg:`help dates` for a list of formats valid for -d/--date.
4062
4063
4063 .. container:: verbose
4064 .. container:: verbose
4064
4065
4065 Examples:
4066 Examples:
4066
4067
4067 - import a traditional patch from a website and detect renames::
4068 - import a traditional patch from a website and detect renames::
4068
4069
4069 hg import -s 80 http://example.com/bugfix.patch
4070 hg import -s 80 http://example.com/bugfix.patch
4070
4071
4071 - import a changeset from an hgweb server::
4072 - import a changeset from an hgweb server::
4072
4073
4073 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4074 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4074
4075
4075 - import all the patches in an Unix-style mbox::
4076 - import all the patches in an Unix-style mbox::
4076
4077
4077 hg import incoming-patches.mbox
4078 hg import incoming-patches.mbox
4078
4079
4079 - attempt to exactly restore an exported changeset (not always
4080 - attempt to exactly restore an exported changeset (not always
4080 possible)::
4081 possible)::
4081
4082
4082 hg import --exact proposed-fix.patch
4083 hg import --exact proposed-fix.patch
4083
4084
4084 Returns 0 on success, 1 on partial success (see --partial).
4085 Returns 0 on success, 1 on partial success (see --partial).
4085 """
4086 """
4086
4087
4087 if not patch1:
4088 if not patch1:
4088 raise util.Abort(_('need at least one patch to import'))
4089 raise util.Abort(_('need at least one patch to import'))
4089
4090
4090 patches = (patch1,) + patches
4091 patches = (patch1,) + patches
4091
4092
4092 date = opts.get('date')
4093 date = opts.get('date')
4093 if date:
4094 if date:
4094 opts['date'] = util.parsedate(date)
4095 opts['date'] = util.parsedate(date)
4095
4096
4096 update = not opts.get('bypass')
4097 update = not opts.get('bypass')
4097 if not update and opts.get('no_commit'):
4098 if not update and opts.get('no_commit'):
4098 raise util.Abort(_('cannot use --no-commit with --bypass'))
4099 raise util.Abort(_('cannot use --no-commit with --bypass'))
4099 try:
4100 try:
4100 sim = float(opts.get('similarity') or 0)
4101 sim = float(opts.get('similarity') or 0)
4101 except ValueError:
4102 except ValueError:
4102 raise util.Abort(_('similarity must be a number'))
4103 raise util.Abort(_('similarity must be a number'))
4103 if sim < 0 or sim > 100:
4104 if sim < 0 or sim > 100:
4104 raise util.Abort(_('similarity must be between 0 and 100'))
4105 raise util.Abort(_('similarity must be between 0 and 100'))
4105 if sim and not update:
4106 if sim and not update:
4106 raise util.Abort(_('cannot use --similarity with --bypass'))
4107 raise util.Abort(_('cannot use --similarity with --bypass'))
4107 if opts.get('exact') and opts.get('edit'):
4108 if opts.get('exact') and opts.get('edit'):
4108 raise util.Abort(_('cannot use --exact with --edit'))
4109 raise util.Abort(_('cannot use --exact with --edit'))
4109
4110
4110 if update:
4111 if update:
4111 cmdutil.checkunfinished(repo)
4112 cmdutil.checkunfinished(repo)
4112 if (opts.get('exact') or not opts.get('force')) and update:
4113 if (opts.get('exact') or not opts.get('force')) and update:
4113 cmdutil.bailifchanged(repo)
4114 cmdutil.bailifchanged(repo)
4114
4115
4115 base = opts["base"]
4116 base = opts["base"]
4116 wlock = lock = tr = None
4117 wlock = lock = tr = None
4117 msgs = []
4118 msgs = []
4118 ret = 0
4119 ret = 0
4119
4120
4120
4121
4121 try:
4122 try:
4122 try:
4123 try:
4123 wlock = repo.wlock()
4124 wlock = repo.wlock()
4124 repo.dirstate.beginparentchange()
4125 repo.dirstate.beginparentchange()
4125 if not opts.get('no_commit'):
4126 if not opts.get('no_commit'):
4126 lock = repo.lock()
4127 lock = repo.lock()
4127 tr = repo.transaction('import')
4128 tr = repo.transaction('import')
4128 parents = repo.parents()
4129 parents = repo.parents()
4129 for patchurl in patches:
4130 for patchurl in patches:
4130 if patchurl == '-':
4131 if patchurl == '-':
4131 ui.status(_('applying patch from stdin\n'))
4132 ui.status(_('applying patch from stdin\n'))
4132 patchfile = ui.fin
4133 patchfile = ui.fin
4133 patchurl = 'stdin' # for error message
4134 patchurl = 'stdin' # for error message
4134 else:
4135 else:
4135 patchurl = os.path.join(base, patchurl)
4136 patchurl = os.path.join(base, patchurl)
4136 ui.status(_('applying %s\n') % patchurl)
4137 ui.status(_('applying %s\n') % patchurl)
4137 patchfile = hg.openpath(ui, patchurl)
4138 patchfile = hg.openpath(ui, patchurl)
4138
4139
4139 haspatch = False
4140 haspatch = False
4140 for hunk in patch.split(patchfile):
4141 for hunk in patch.split(patchfile):
4141 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4142 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4142 parents, opts,
4143 parents, opts,
4143 msgs, hg.clean)
4144 msgs, hg.clean)
4144 if msg:
4145 if msg:
4145 haspatch = True
4146 haspatch = True
4146 ui.note(msg + '\n')
4147 ui.note(msg + '\n')
4147 if update or opts.get('exact'):
4148 if update or opts.get('exact'):
4148 parents = repo.parents()
4149 parents = repo.parents()
4149 else:
4150 else:
4150 parents = [repo[node]]
4151 parents = [repo[node]]
4151 if rej:
4152 if rej:
4152 ui.write_err(_("patch applied partially\n"))
4153 ui.write_err(_("patch applied partially\n"))
4153 ui.write_err(_("(fix the .rej files and run "
4154 ui.write_err(_("(fix the .rej files and run "
4154 "`hg commit --amend`)\n"))
4155 "`hg commit --amend`)\n"))
4155 ret = 1
4156 ret = 1
4156 break
4157 break
4157
4158
4158 if not haspatch:
4159 if not haspatch:
4159 raise util.Abort(_('%s: no diffs found') % patchurl)
4160 raise util.Abort(_('%s: no diffs found') % patchurl)
4160
4161
4161 if tr:
4162 if tr:
4162 tr.close()
4163 tr.close()
4163 if msgs:
4164 if msgs:
4164 repo.savecommitmessage('\n* * *\n'.join(msgs))
4165 repo.savecommitmessage('\n* * *\n'.join(msgs))
4165 repo.dirstate.endparentchange()
4166 repo.dirstate.endparentchange()
4166 return ret
4167 return ret
4167 except: # re-raises
4168 except: # re-raises
4168 # wlock.release() indirectly calls dirstate.write(): since
4169 # wlock.release() indirectly calls dirstate.write(): since
4169 # we're crashing, we do not want to change the working dir
4170 # we're crashing, we do not want to change the working dir
4170 # parent after all, so make sure it writes nothing
4171 # parent after all, so make sure it writes nothing
4171 repo.dirstate.invalidate()
4172 repo.dirstate.invalidate()
4172 raise
4173 raise
4173 finally:
4174 finally:
4174 if tr:
4175 if tr:
4175 tr.release()
4176 tr.release()
4176 release(lock, wlock)
4177 release(lock, wlock)
4177
4178
4178 @command('incoming|in',
4179 @command('incoming|in',
4179 [('f', 'force', None,
4180 [('f', 'force', None,
4180 _('run even if remote repository is unrelated')),
4181 _('run even if remote repository is unrelated')),
4181 ('n', 'newest-first', None, _('show newest record first')),
4182 ('n', 'newest-first', None, _('show newest record first')),
4182 ('', 'bundle', '',
4183 ('', 'bundle', '',
4183 _('file to store the bundles into'), _('FILE')),
4184 _('file to store the bundles into'), _('FILE')),
4184 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4185 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4185 ('B', 'bookmarks', False, _("compare bookmarks")),
4186 ('B', 'bookmarks', False, _("compare bookmarks")),
4186 ('b', 'branch', [],
4187 ('b', 'branch', [],
4187 _('a specific branch you would like to pull'), _('BRANCH')),
4188 _('a specific branch you would like to pull'), _('BRANCH')),
4188 ] + logopts + remoteopts + subrepoopts,
4189 ] + logopts + remoteopts + subrepoopts,
4189 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4190 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4190 def incoming(ui, repo, source="default", **opts):
4191 def incoming(ui, repo, source="default", **opts):
4191 """show new changesets found in source
4192 """show new changesets found in source
4192
4193
4193 Show new changesets found in the specified path/URL or the default
4194 Show new changesets found in the specified path/URL or the default
4194 pull location. These are the changesets that would have been pulled
4195 pull location. These are the changesets that would have been pulled
4195 if a pull at the time you issued this command.
4196 if a pull at the time you issued this command.
4196
4197
4197 For remote repository, using --bundle avoids downloading the
4198 For remote repository, using --bundle avoids downloading the
4198 changesets twice if the incoming is followed by a pull.
4199 changesets twice if the incoming is followed by a pull.
4199
4200
4200 See pull for valid source format details.
4201 See pull for valid source format details.
4201
4202
4202 .. container:: verbose
4203 .. container:: verbose
4203
4204
4204 Examples:
4205 Examples:
4205
4206
4206 - show incoming changes with patches and full description::
4207 - show incoming changes with patches and full description::
4207
4208
4208 hg incoming -vp
4209 hg incoming -vp
4209
4210
4210 - show incoming changes excluding merges, store a bundle::
4211 - show incoming changes excluding merges, store a bundle::
4211
4212
4212 hg in -vpM --bundle incoming.hg
4213 hg in -vpM --bundle incoming.hg
4213 hg pull incoming.hg
4214 hg pull incoming.hg
4214
4215
4215 - briefly list changes inside a bundle::
4216 - briefly list changes inside a bundle::
4216
4217
4217 hg in changes.hg -T "{desc|firstline}\\n"
4218 hg in changes.hg -T "{desc|firstline}\\n"
4218
4219
4219 Returns 0 if there are incoming changes, 1 otherwise.
4220 Returns 0 if there are incoming changes, 1 otherwise.
4220 """
4221 """
4221 if opts.get('graph'):
4222 if opts.get('graph'):
4222 cmdutil.checkunsupportedgraphflags([], opts)
4223 cmdutil.checkunsupportedgraphflags([], opts)
4223 def display(other, chlist, displayer):
4224 def display(other, chlist, displayer):
4224 revdag = cmdutil.graphrevs(other, chlist, opts)
4225 revdag = cmdutil.graphrevs(other, chlist, opts)
4225 showparents = [ctx.node() for ctx in repo[None].parents()]
4226 showparents = [ctx.node() for ctx in repo[None].parents()]
4226 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4227 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4227 graphmod.asciiedges)
4228 graphmod.asciiedges)
4228
4229
4229 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4230 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4230 return 0
4231 return 0
4231
4232
4232 if opts.get('bundle') and opts.get('subrepos'):
4233 if opts.get('bundle') and opts.get('subrepos'):
4233 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4234 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4234
4235
4235 if opts.get('bookmarks'):
4236 if opts.get('bookmarks'):
4236 source, branches = hg.parseurl(ui.expandpath(source),
4237 source, branches = hg.parseurl(ui.expandpath(source),
4237 opts.get('branch'))
4238 opts.get('branch'))
4238 other = hg.peer(repo, opts, source)
4239 other = hg.peer(repo, opts, source)
4239 if 'bookmarks' not in other.listkeys('namespaces'):
4240 if 'bookmarks' not in other.listkeys('namespaces'):
4240 ui.warn(_("remote doesn't support bookmarks\n"))
4241 ui.warn(_("remote doesn't support bookmarks\n"))
4241 return 0
4242 return 0
4242 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4243 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4243 return bookmarks.diff(ui, repo, other)
4244 return bookmarks.diff(ui, repo, other)
4244
4245
4245 repo._subtoppath = ui.expandpath(source)
4246 repo._subtoppath = ui.expandpath(source)
4246 try:
4247 try:
4247 return hg.incoming(ui, repo, source, opts)
4248 return hg.incoming(ui, repo, source, opts)
4248 finally:
4249 finally:
4249 del repo._subtoppath
4250 del repo._subtoppath
4250
4251
4251
4252
4252 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4253 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4253 norepo=True)
4254 norepo=True)
4254 def init(ui, dest=".", **opts):
4255 def init(ui, dest=".", **opts):
4255 """create a new repository in the given directory
4256 """create a new repository in the given directory
4256
4257
4257 Initialize a new repository in the given directory. If the given
4258 Initialize a new repository in the given directory. If the given
4258 directory does not exist, it will be created.
4259 directory does not exist, it will be created.
4259
4260
4260 If no directory is given, the current directory is used.
4261 If no directory is given, the current directory is used.
4261
4262
4262 It is possible to specify an ``ssh://`` URL as the destination.
4263 It is possible to specify an ``ssh://`` URL as the destination.
4263 See :hg:`help urls` for more information.
4264 See :hg:`help urls` for more information.
4264
4265
4265 Returns 0 on success.
4266 Returns 0 on success.
4266 """
4267 """
4267 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4268 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4268
4269
4269 @command('locate',
4270 @command('locate',
4270 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4271 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4271 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4272 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4272 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4273 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4273 ] + walkopts,
4274 ] + walkopts,
4274 _('[OPTION]... [PATTERN]...'))
4275 _('[OPTION]... [PATTERN]...'))
4275 def locate(ui, repo, *pats, **opts):
4276 def locate(ui, repo, *pats, **opts):
4276 """locate files matching specific patterns (DEPRECATED)
4277 """locate files matching specific patterns (DEPRECATED)
4277
4278
4278 Print files under Mercurial control in the working directory whose
4279 Print files under Mercurial control in the working directory whose
4279 names match the given patterns.
4280 names match the given patterns.
4280
4281
4281 By default, this command searches all directories in the working
4282 By default, this command searches all directories in the working
4282 directory. To search just the current directory and its
4283 directory. To search just the current directory and its
4283 subdirectories, use "--include .".
4284 subdirectories, use "--include .".
4284
4285
4285 If no patterns are given to match, this command prints the names
4286 If no patterns are given to match, this command prints the names
4286 of all files under Mercurial control in the working directory.
4287 of all files under Mercurial control in the working directory.
4287
4288
4288 If you want to feed the output of this command into the "xargs"
4289 If you want to feed the output of this command into the "xargs"
4289 command, use the -0 option to both this command and "xargs". This
4290 command, use the -0 option to both this command and "xargs". This
4290 will avoid the problem of "xargs" treating single filenames that
4291 will avoid the problem of "xargs" treating single filenames that
4291 contain whitespace as multiple filenames.
4292 contain whitespace as multiple filenames.
4292
4293
4293 See :hg:`help files` for a more versatile command.
4294 See :hg:`help files` for a more versatile command.
4294
4295
4295 Returns 0 if a match is found, 1 otherwise.
4296 Returns 0 if a match is found, 1 otherwise.
4296 """
4297 """
4297 end = opts.get('print0') and '\0' or '\n'
4298 end = opts.get('print0') and '\0' or '\n'
4298 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4299 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4299
4300
4300 ret = 1
4301 ret = 1
4301 ctx = repo[rev]
4302 ctx = repo[rev]
4302 m = scmutil.match(ctx, pats, opts, default='relglob')
4303 m = scmutil.match(ctx, pats, opts, default='relglob')
4303 m.bad = lambda x, y: False
4304 m.bad = lambda x, y: False
4304
4305
4305 for abs in ctx.matches(m):
4306 for abs in ctx.matches(m):
4306 if opts.get('fullpath'):
4307 if opts.get('fullpath'):
4307 ui.write(repo.wjoin(abs), end)
4308 ui.write(repo.wjoin(abs), end)
4308 else:
4309 else:
4309 ui.write(((pats and m.rel(abs)) or abs), end)
4310 ui.write(((pats and m.rel(abs)) or abs), end)
4310 ret = 0
4311 ret = 0
4311
4312
4312 return ret
4313 return ret
4313
4314
4314 @command('^log|history',
4315 @command('^log|history',
4315 [('f', 'follow', None,
4316 [('f', 'follow', None,
4316 _('follow changeset history, or file history across copies and renames')),
4317 _('follow changeset history, or file history across copies and renames')),
4317 ('', 'follow-first', None,
4318 ('', 'follow-first', None,
4318 _('only follow the first parent of merge changesets (DEPRECATED)')),
4319 _('only follow the first parent of merge changesets (DEPRECATED)')),
4319 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4320 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4320 ('C', 'copies', None, _('show copied files')),
4321 ('C', 'copies', None, _('show copied files')),
4321 ('k', 'keyword', [],
4322 ('k', 'keyword', [],
4322 _('do case-insensitive search for a given text'), _('TEXT')),
4323 _('do case-insensitive search for a given text'), _('TEXT')),
4323 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4324 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4324 ('', 'removed', None, _('include revisions where files were removed')),
4325 ('', 'removed', None, _('include revisions where files were removed')),
4325 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4326 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4326 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4327 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4327 ('', 'only-branch', [],
4328 ('', 'only-branch', [],
4328 _('show only changesets within the given named branch (DEPRECATED)'),
4329 _('show only changesets within the given named branch (DEPRECATED)'),
4329 _('BRANCH')),
4330 _('BRANCH')),
4330 ('b', 'branch', [],
4331 ('b', 'branch', [],
4331 _('show changesets within the given named branch'), _('BRANCH')),
4332 _('show changesets within the given named branch'), _('BRANCH')),
4332 ('P', 'prune', [],
4333 ('P', 'prune', [],
4333 _('do not display revision or any of its ancestors'), _('REV')),
4334 _('do not display revision or any of its ancestors'), _('REV')),
4334 ] + logopts + walkopts,
4335 ] + logopts + walkopts,
4335 _('[OPTION]... [FILE]'),
4336 _('[OPTION]... [FILE]'),
4336 inferrepo=True)
4337 inferrepo=True)
4337 def log(ui, repo, *pats, **opts):
4338 def log(ui, repo, *pats, **opts):
4338 """show revision history of entire repository or files
4339 """show revision history of entire repository or files
4339
4340
4340 Print the revision history of the specified files or the entire
4341 Print the revision history of the specified files or the entire
4341 project.
4342 project.
4342
4343
4343 If no revision range is specified, the default is ``tip:0`` unless
4344 If no revision range is specified, the default is ``tip:0`` unless
4344 --follow is set, in which case the working directory parent is
4345 --follow is set, in which case the working directory parent is
4345 used as the starting revision.
4346 used as the starting revision.
4346
4347
4347 File history is shown without following rename or copy history of
4348 File history is shown without following rename or copy history of
4348 files. Use -f/--follow with a filename to follow history across
4349 files. Use -f/--follow with a filename to follow history across
4349 renames and copies. --follow without a filename will only show
4350 renames and copies. --follow without a filename will only show
4350 ancestors or descendants of the starting revision.
4351 ancestors or descendants of the starting revision.
4351
4352
4352 By default this command prints revision number and changeset id,
4353 By default this command prints revision number and changeset id,
4353 tags, non-trivial parents, user, date and time, and a summary for
4354 tags, non-trivial parents, user, date and time, and a summary for
4354 each commit. When the -v/--verbose switch is used, the list of
4355 each commit. When the -v/--verbose switch is used, the list of
4355 changed files and full commit message are shown.
4356 changed files and full commit message are shown.
4356
4357
4357 With --graph the revisions are shown as an ASCII art DAG with the most
4358 With --graph the revisions are shown as an ASCII art DAG with the most
4358 recent changeset at the top.
4359 recent changeset at the top.
4359 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4360 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4360 and '+' represents a fork where the changeset from the lines below is a
4361 and '+' represents a fork where the changeset from the lines below is a
4361 parent of the 'o' merge on the same line.
4362 parent of the 'o' merge on the same line.
4362
4363
4363 .. note::
4364 .. note::
4364
4365
4365 log -p/--patch may generate unexpected diff output for merge
4366 log -p/--patch may generate unexpected diff output for merge
4366 changesets, as it will only compare the merge changeset against
4367 changesets, as it will only compare the merge changeset against
4367 its first parent. Also, only files different from BOTH parents
4368 its first parent. Also, only files different from BOTH parents
4368 will appear in files:.
4369 will appear in files:.
4369
4370
4370 .. note::
4371 .. note::
4371
4372
4372 for performance reasons, log FILE may omit duplicate changes
4373 for performance reasons, log FILE may omit duplicate changes
4373 made on branches and will not show removals or mode changes. To
4374 made on branches and will not show removals or mode changes. To
4374 see all such changes, use the --removed switch.
4375 see all such changes, use the --removed switch.
4375
4376
4376 .. container:: verbose
4377 .. container:: verbose
4377
4378
4378 Some examples:
4379 Some examples:
4379
4380
4380 - changesets with full descriptions and file lists::
4381 - changesets with full descriptions and file lists::
4381
4382
4382 hg log -v
4383 hg log -v
4383
4384
4384 - changesets ancestral to the working directory::
4385 - changesets ancestral to the working directory::
4385
4386
4386 hg log -f
4387 hg log -f
4387
4388
4388 - last 10 commits on the current branch::
4389 - last 10 commits on the current branch::
4389
4390
4390 hg log -l 10 -b .
4391 hg log -l 10 -b .
4391
4392
4392 - changesets showing all modifications of a file, including removals::
4393 - changesets showing all modifications of a file, including removals::
4393
4394
4394 hg log --removed file.c
4395 hg log --removed file.c
4395
4396
4396 - all changesets that touch a directory, with diffs, excluding merges::
4397 - all changesets that touch a directory, with diffs, excluding merges::
4397
4398
4398 hg log -Mp lib/
4399 hg log -Mp lib/
4399
4400
4400 - all revision numbers that match a keyword::
4401 - all revision numbers that match a keyword::
4401
4402
4402 hg log -k bug --template "{rev}\\n"
4403 hg log -k bug --template "{rev}\\n"
4403
4404
4404 - list available log templates::
4405 - list available log templates::
4405
4406
4406 hg log -T list
4407 hg log -T list
4407
4408
4408 - check if a given changeset is included in a tagged release::
4409 - check if a given changeset is included in a tagged release::
4409
4410
4410 hg log -r "a21ccf and ancestor(1.9)"
4411 hg log -r "a21ccf and ancestor(1.9)"
4411
4412
4412 - find all changesets by some user in a date range::
4413 - find all changesets by some user in a date range::
4413
4414
4414 hg log -k alice -d "may 2008 to jul 2008"
4415 hg log -k alice -d "may 2008 to jul 2008"
4415
4416
4416 - summary of all changesets after the last tag::
4417 - summary of all changesets after the last tag::
4417
4418
4418 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4419 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4419
4420
4420 See :hg:`help dates` for a list of formats valid for -d/--date.
4421 See :hg:`help dates` for a list of formats valid for -d/--date.
4421
4422
4422 See :hg:`help revisions` and :hg:`help revsets` for more about
4423 See :hg:`help revisions` and :hg:`help revsets` for more about
4423 specifying revisions.
4424 specifying revisions.
4424
4425
4425 See :hg:`help templates` for more about pre-packaged styles and
4426 See :hg:`help templates` for more about pre-packaged styles and
4426 specifying custom templates.
4427 specifying custom templates.
4427
4428
4428 Returns 0 on success.
4429 Returns 0 on success.
4429
4430
4430 """
4431 """
4431 if opts.get('graph'):
4432 if opts.get('graph'):
4432 return cmdutil.graphlog(ui, repo, *pats, **opts)
4433 return cmdutil.graphlog(ui, repo, *pats, **opts)
4433
4434
4434 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4435 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4435 limit = cmdutil.loglimit(opts)
4436 limit = cmdutil.loglimit(opts)
4436 count = 0
4437 count = 0
4437
4438
4438 getrenamed = None
4439 getrenamed = None
4439 if opts.get('copies'):
4440 if opts.get('copies'):
4440 endrev = None
4441 endrev = None
4441 if opts.get('rev'):
4442 if opts.get('rev'):
4442 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4443 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4443 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4444 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4444
4445
4445 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4446 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4446 for rev in revs:
4447 for rev in revs:
4447 if count == limit:
4448 if count == limit:
4448 break
4449 break
4449 ctx = repo[rev]
4450 ctx = repo[rev]
4450 copies = None
4451 copies = None
4451 if getrenamed is not None and rev:
4452 if getrenamed is not None and rev:
4452 copies = []
4453 copies = []
4453 for fn in ctx.files():
4454 for fn in ctx.files():
4454 rename = getrenamed(fn, rev)
4455 rename = getrenamed(fn, rev)
4455 if rename:
4456 if rename:
4456 copies.append((fn, rename[0]))
4457 copies.append((fn, rename[0]))
4457 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4458 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4458 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4459 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4459 if displayer.flush(rev):
4460 if displayer.flush(rev):
4460 count += 1
4461 count += 1
4461
4462
4462 displayer.close()
4463 displayer.close()
4463
4464
4464 @command('manifest',
4465 @command('manifest',
4465 [('r', 'rev', '', _('revision to display'), _('REV')),
4466 [('r', 'rev', '', _('revision to display'), _('REV')),
4466 ('', 'all', False, _("list files from all revisions"))]
4467 ('', 'all', False, _("list files from all revisions"))]
4467 + formatteropts,
4468 + formatteropts,
4468 _('[-r REV]'))
4469 _('[-r REV]'))
4469 def manifest(ui, repo, node=None, rev=None, **opts):
4470 def manifest(ui, repo, node=None, rev=None, **opts):
4470 """output the current or given revision of the project manifest
4471 """output the current or given revision of the project manifest
4471
4472
4472 Print a list of version controlled files for the given revision.
4473 Print a list of version controlled files for the given revision.
4473 If no revision is given, the first parent of the working directory
4474 If no revision is given, the first parent of the working directory
4474 is used, or the null revision if no revision is checked out.
4475 is used, or the null revision if no revision is checked out.
4475
4476
4476 With -v, print file permissions, symlink and executable bits.
4477 With -v, print file permissions, symlink and executable bits.
4477 With --debug, print file revision hashes.
4478 With --debug, print file revision hashes.
4478
4479
4479 If option --all is specified, the list of all files from all revisions
4480 If option --all is specified, the list of all files from all revisions
4480 is printed. This includes deleted and renamed files.
4481 is printed. This includes deleted and renamed files.
4481
4482
4482 Returns 0 on success.
4483 Returns 0 on success.
4483 """
4484 """
4484
4485
4485 fm = ui.formatter('manifest', opts)
4486 fm = ui.formatter('manifest', opts)
4486
4487
4487 if opts.get('all'):
4488 if opts.get('all'):
4488 if rev or node:
4489 if rev or node:
4489 raise util.Abort(_("can't specify a revision with --all"))
4490 raise util.Abort(_("can't specify a revision with --all"))
4490
4491
4491 res = []
4492 res = []
4492 prefix = "data/"
4493 prefix = "data/"
4493 suffix = ".i"
4494 suffix = ".i"
4494 plen = len(prefix)
4495 plen = len(prefix)
4495 slen = len(suffix)
4496 slen = len(suffix)
4496 lock = repo.lock()
4497 lock = repo.lock()
4497 try:
4498 try:
4498 for fn, b, size in repo.store.datafiles():
4499 for fn, b, size in repo.store.datafiles():
4499 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4500 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4500 res.append(fn[plen:-slen])
4501 res.append(fn[plen:-slen])
4501 finally:
4502 finally:
4502 lock.release()
4503 lock.release()
4503 for f in res:
4504 for f in res:
4504 fm.startitem()
4505 fm.startitem()
4505 fm.write("path", '%s\n', f)
4506 fm.write("path", '%s\n', f)
4506 fm.end()
4507 fm.end()
4507 return
4508 return
4508
4509
4509 if rev and node:
4510 if rev and node:
4510 raise util.Abort(_("please specify just one revision"))
4511 raise util.Abort(_("please specify just one revision"))
4511
4512
4512 if not node:
4513 if not node:
4513 node = rev
4514 node = rev
4514
4515
4515 char = {'l': '@', 'x': '*', '': ''}
4516 char = {'l': '@', 'x': '*', '': ''}
4516 mode = {'l': '644', 'x': '755', '': '644'}
4517 mode = {'l': '644', 'x': '755', '': '644'}
4517 ctx = scmutil.revsingle(repo, node)
4518 ctx = scmutil.revsingle(repo, node)
4518 mf = ctx.manifest()
4519 mf = ctx.manifest()
4519 for f in ctx:
4520 for f in ctx:
4520 fm.startitem()
4521 fm.startitem()
4521 fl = ctx[f].flags()
4522 fl = ctx[f].flags()
4522 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4523 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4523 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4524 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4524 fm.write('path', '%s\n', f)
4525 fm.write('path', '%s\n', f)
4525 fm.end()
4526 fm.end()
4526
4527
4527 @command('^merge',
4528 @command('^merge',
4528 [('f', 'force', None,
4529 [('f', 'force', None,
4529 _('force a merge including outstanding changes (DEPRECATED)')),
4530 _('force a merge including outstanding changes (DEPRECATED)')),
4530 ('r', 'rev', '', _('revision to merge'), _('REV')),
4531 ('r', 'rev', '', _('revision to merge'), _('REV')),
4531 ('P', 'preview', None,
4532 ('P', 'preview', None,
4532 _('review revisions to merge (no merge is performed)'))
4533 _('review revisions to merge (no merge is performed)'))
4533 ] + mergetoolopts,
4534 ] + mergetoolopts,
4534 _('[-P] [-f] [[-r] REV]'))
4535 _('[-P] [-f] [[-r] REV]'))
4535 def merge(ui, repo, node=None, **opts):
4536 def merge(ui, repo, node=None, **opts):
4536 """merge another revision into working directory
4537 """merge another revision into working directory
4537
4538
4538 The current working directory is updated with all changes made in
4539 The current working directory is updated with all changes made in
4539 the requested revision since the last common predecessor revision.
4540 the requested revision since the last common predecessor revision.
4540
4541
4541 Files that changed between either parent are marked as changed for
4542 Files that changed between either parent are marked as changed for
4542 the next commit and a commit must be performed before any further
4543 the next commit and a commit must be performed before any further
4543 updates to the repository are allowed. The next commit will have
4544 updates to the repository are allowed. The next commit will have
4544 two parents.
4545 two parents.
4545
4546
4546 ``--tool`` can be used to specify the merge tool used for file
4547 ``--tool`` can be used to specify the merge tool used for file
4547 merges. It overrides the HGMERGE environment variable and your
4548 merges. It overrides the HGMERGE environment variable and your
4548 configuration files. See :hg:`help merge-tools` for options.
4549 configuration files. See :hg:`help merge-tools` for options.
4549
4550
4550 If no revision is specified, the working directory's parent is a
4551 If no revision is specified, the working directory's parent is a
4551 head revision, and the current branch contains exactly one other
4552 head revision, and the current branch contains exactly one other
4552 head, the other head is merged with by default. Otherwise, an
4553 head, the other head is merged with by default. Otherwise, an
4553 explicit revision with which to merge with must be provided.
4554 explicit revision with which to merge with must be provided.
4554
4555
4555 :hg:`resolve` must be used to resolve unresolved files.
4556 :hg:`resolve` must be used to resolve unresolved files.
4556
4557
4557 To undo an uncommitted merge, use :hg:`update --clean .` which
4558 To undo an uncommitted merge, use :hg:`update --clean .` which
4558 will check out a clean copy of the original merge parent, losing
4559 will check out a clean copy of the original merge parent, losing
4559 all changes.
4560 all changes.
4560
4561
4561 Returns 0 on success, 1 if there are unresolved files.
4562 Returns 0 on success, 1 if there are unresolved files.
4562 """
4563 """
4563
4564
4564 if opts.get('rev') and node:
4565 if opts.get('rev') and node:
4565 raise util.Abort(_("please specify just one revision"))
4566 raise util.Abort(_("please specify just one revision"))
4566 if not node:
4567 if not node:
4567 node = opts.get('rev')
4568 node = opts.get('rev')
4568
4569
4569 if node:
4570 if node:
4570 node = scmutil.revsingle(repo, node).node()
4571 node = scmutil.revsingle(repo, node).node()
4571
4572
4572 if not node and repo._bookmarkcurrent:
4573 if not node and repo._bookmarkcurrent:
4573 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4574 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4574 curhead = repo[repo._bookmarkcurrent].node()
4575 curhead = repo[repo._bookmarkcurrent].node()
4575 if len(bmheads) == 2:
4576 if len(bmheads) == 2:
4576 if curhead == bmheads[0]:
4577 if curhead == bmheads[0]:
4577 node = bmheads[1]
4578 node = bmheads[1]
4578 else:
4579 else:
4579 node = bmheads[0]
4580 node = bmheads[0]
4580 elif len(bmheads) > 2:
4581 elif len(bmheads) > 2:
4581 raise util.Abort(_("multiple matching bookmarks to merge - "
4582 raise util.Abort(_("multiple matching bookmarks to merge - "
4582 "please merge with an explicit rev or bookmark"),
4583 "please merge with an explicit rev or bookmark"),
4583 hint=_("run 'hg heads' to see all heads"))
4584 hint=_("run 'hg heads' to see all heads"))
4584 elif len(bmheads) <= 1:
4585 elif len(bmheads) <= 1:
4585 raise util.Abort(_("no matching bookmark to merge - "
4586 raise util.Abort(_("no matching bookmark to merge - "
4586 "please merge with an explicit rev or bookmark"),
4587 "please merge with an explicit rev or bookmark"),
4587 hint=_("run 'hg heads' to see all heads"))
4588 hint=_("run 'hg heads' to see all heads"))
4588
4589
4589 if not node and not repo._bookmarkcurrent:
4590 if not node and not repo._bookmarkcurrent:
4590 branch = repo[None].branch()
4591 branch = repo[None].branch()
4591 bheads = repo.branchheads(branch)
4592 bheads = repo.branchheads(branch)
4592 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4593 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4593
4594
4594 if len(nbhs) > 2:
4595 if len(nbhs) > 2:
4595 raise util.Abort(_("branch '%s' has %d heads - "
4596 raise util.Abort(_("branch '%s' has %d heads - "
4596 "please merge with an explicit rev")
4597 "please merge with an explicit rev")
4597 % (branch, len(bheads)),
4598 % (branch, len(bheads)),
4598 hint=_("run 'hg heads .' to see heads"))
4599 hint=_("run 'hg heads .' to see heads"))
4599
4600
4600 parent = repo.dirstate.p1()
4601 parent = repo.dirstate.p1()
4601 if len(nbhs) <= 1:
4602 if len(nbhs) <= 1:
4602 if len(bheads) > 1:
4603 if len(bheads) > 1:
4603 raise util.Abort(_("heads are bookmarked - "
4604 raise util.Abort(_("heads are bookmarked - "
4604 "please merge with an explicit rev"),
4605 "please merge with an explicit rev"),
4605 hint=_("run 'hg heads' to see all heads"))
4606 hint=_("run 'hg heads' to see all heads"))
4606 if len(repo.heads()) > 1:
4607 if len(repo.heads()) > 1:
4607 raise util.Abort(_("branch '%s' has one head - "
4608 raise util.Abort(_("branch '%s' has one head - "
4608 "please merge with an explicit rev")
4609 "please merge with an explicit rev")
4609 % branch,
4610 % branch,
4610 hint=_("run 'hg heads' to see all heads"))
4611 hint=_("run 'hg heads' to see all heads"))
4611 msg, hint = _('nothing to merge'), None
4612 msg, hint = _('nothing to merge'), None
4612 if parent != repo.lookup(branch):
4613 if parent != repo.lookup(branch):
4613 hint = _("use 'hg update' instead")
4614 hint = _("use 'hg update' instead")
4614 raise util.Abort(msg, hint=hint)
4615 raise util.Abort(msg, hint=hint)
4615
4616
4616 if parent not in bheads:
4617 if parent not in bheads:
4617 raise util.Abort(_('working directory not at a head revision'),
4618 raise util.Abort(_('working directory not at a head revision'),
4618 hint=_("use 'hg update' or merge with an "
4619 hint=_("use 'hg update' or merge with an "
4619 "explicit revision"))
4620 "explicit revision"))
4620 if parent == nbhs[0]:
4621 if parent == nbhs[0]:
4621 node = nbhs[-1]
4622 node = nbhs[-1]
4622 else:
4623 else:
4623 node = nbhs[0]
4624 node = nbhs[0]
4624
4625
4625 if opts.get('preview'):
4626 if opts.get('preview'):
4626 # find nodes that are ancestors of p2 but not of p1
4627 # find nodes that are ancestors of p2 but not of p1
4627 p1 = repo.lookup('.')
4628 p1 = repo.lookup('.')
4628 p2 = repo.lookup(node)
4629 p2 = repo.lookup(node)
4629 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4630 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4630
4631
4631 displayer = cmdutil.show_changeset(ui, repo, opts)
4632 displayer = cmdutil.show_changeset(ui, repo, opts)
4632 for node in nodes:
4633 for node in nodes:
4633 displayer.show(repo[node])
4634 displayer.show(repo[node])
4634 displayer.close()
4635 displayer.close()
4635 return 0
4636 return 0
4636
4637
4637 try:
4638 try:
4638 # ui.forcemerge is an internal variable, do not document
4639 # ui.forcemerge is an internal variable, do not document
4639 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4640 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4640 return hg.merge(repo, node, force=opts.get('force'))
4641 return hg.merge(repo, node, force=opts.get('force'))
4641 finally:
4642 finally:
4642 ui.setconfig('ui', 'forcemerge', '', 'merge')
4643 ui.setconfig('ui', 'forcemerge', '', 'merge')
4643
4644
4644 @command('outgoing|out',
4645 @command('outgoing|out',
4645 [('f', 'force', None, _('run even when the destination is unrelated')),
4646 [('f', 'force', None, _('run even when the destination is unrelated')),
4646 ('r', 'rev', [],
4647 ('r', 'rev', [],
4647 _('a changeset intended to be included in the destination'), _('REV')),
4648 _('a changeset intended to be included in the destination'), _('REV')),
4648 ('n', 'newest-first', None, _('show newest record first')),
4649 ('n', 'newest-first', None, _('show newest record first')),
4649 ('B', 'bookmarks', False, _('compare bookmarks')),
4650 ('B', 'bookmarks', False, _('compare bookmarks')),
4650 ('b', 'branch', [], _('a specific branch you would like to push'),
4651 ('b', 'branch', [], _('a specific branch you would like to push'),
4651 _('BRANCH')),
4652 _('BRANCH')),
4652 ] + logopts + remoteopts + subrepoopts,
4653 ] + logopts + remoteopts + subrepoopts,
4653 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4654 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4654 def outgoing(ui, repo, dest=None, **opts):
4655 def outgoing(ui, repo, dest=None, **opts):
4655 """show changesets not found in the destination
4656 """show changesets not found in the destination
4656
4657
4657 Show changesets not found in the specified destination repository
4658 Show changesets not found in the specified destination repository
4658 or the default push location. These are the changesets that would
4659 or the default push location. These are the changesets that would
4659 be pushed if a push was requested.
4660 be pushed if a push was requested.
4660
4661
4661 See pull for details of valid destination formats.
4662 See pull for details of valid destination formats.
4662
4663
4663 Returns 0 if there are outgoing changes, 1 otherwise.
4664 Returns 0 if there are outgoing changes, 1 otherwise.
4664 """
4665 """
4665 if opts.get('graph'):
4666 if opts.get('graph'):
4666 cmdutil.checkunsupportedgraphflags([], opts)
4667 cmdutil.checkunsupportedgraphflags([], opts)
4667 o, other = hg._outgoing(ui, repo, dest, opts)
4668 o, other = hg._outgoing(ui, repo, dest, opts)
4668 if not o:
4669 if not o:
4669 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4670 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4670 return
4671 return
4671
4672
4672 revdag = cmdutil.graphrevs(repo, o, opts)
4673 revdag = cmdutil.graphrevs(repo, o, opts)
4673 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4674 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4674 showparents = [ctx.node() for ctx in repo[None].parents()]
4675 showparents = [ctx.node() for ctx in repo[None].parents()]
4675 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4676 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4676 graphmod.asciiedges)
4677 graphmod.asciiedges)
4677 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4678 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4678 return 0
4679 return 0
4679
4680
4680 if opts.get('bookmarks'):
4681 if opts.get('bookmarks'):
4681 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4682 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4682 dest, branches = hg.parseurl(dest, opts.get('branch'))
4683 dest, branches = hg.parseurl(dest, opts.get('branch'))
4683 other = hg.peer(repo, opts, dest)
4684 other = hg.peer(repo, opts, dest)
4684 if 'bookmarks' not in other.listkeys('namespaces'):
4685 if 'bookmarks' not in other.listkeys('namespaces'):
4685 ui.warn(_("remote doesn't support bookmarks\n"))
4686 ui.warn(_("remote doesn't support bookmarks\n"))
4686 return 0
4687 return 0
4687 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4688 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4688 return bookmarks.diff(ui, other, repo)
4689 return bookmarks.diff(ui, other, repo)
4689
4690
4690 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4691 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4691 try:
4692 try:
4692 return hg.outgoing(ui, repo, dest, opts)
4693 return hg.outgoing(ui, repo, dest, opts)
4693 finally:
4694 finally:
4694 del repo._subtoppath
4695 del repo._subtoppath
4695
4696
4696 @command('parents',
4697 @command('parents',
4697 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4698 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4698 ] + templateopts,
4699 ] + templateopts,
4699 _('[-r REV] [FILE]'),
4700 _('[-r REV] [FILE]'),
4700 inferrepo=True)
4701 inferrepo=True)
4701 def parents(ui, repo, file_=None, **opts):
4702 def parents(ui, repo, file_=None, **opts):
4702 """show the parents of the working directory or revision (DEPRECATED)
4703 """show the parents of the working directory or revision (DEPRECATED)
4703
4704
4704 Print the working directory's parent revisions. If a revision is
4705 Print the working directory's parent revisions. If a revision is
4705 given via -r/--rev, the parent of that revision will be printed.
4706 given via -r/--rev, the parent of that revision will be printed.
4706 If a file argument is given, the revision in which the file was
4707 If a file argument is given, the revision in which the file was
4707 last changed (before the working directory revision or the
4708 last changed (before the working directory revision or the
4708 argument to --rev if given) is printed.
4709 argument to --rev if given) is printed.
4709
4710
4710 See :hg:`summary` and :hg:`help revsets` for related information.
4711 See :hg:`summary` and :hg:`help revsets` for related information.
4711
4712
4712 Returns 0 on success.
4713 Returns 0 on success.
4713 """
4714 """
4714
4715
4715 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4716 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4716
4717
4717 if file_:
4718 if file_:
4718 m = scmutil.match(ctx, (file_,), opts)
4719 m = scmutil.match(ctx, (file_,), opts)
4719 if m.anypats() or len(m.files()) != 1:
4720 if m.anypats() or len(m.files()) != 1:
4720 raise util.Abort(_('can only specify an explicit filename'))
4721 raise util.Abort(_('can only specify an explicit filename'))
4721 file_ = m.files()[0]
4722 file_ = m.files()[0]
4722 filenodes = []
4723 filenodes = []
4723 for cp in ctx.parents():
4724 for cp in ctx.parents():
4724 if not cp:
4725 if not cp:
4725 continue
4726 continue
4726 try:
4727 try:
4727 filenodes.append(cp.filenode(file_))
4728 filenodes.append(cp.filenode(file_))
4728 except error.LookupError:
4729 except error.LookupError:
4729 pass
4730 pass
4730 if not filenodes:
4731 if not filenodes:
4731 raise util.Abort(_("'%s' not found in manifest!") % file_)
4732 raise util.Abort(_("'%s' not found in manifest!") % file_)
4732 p = []
4733 p = []
4733 for fn in filenodes:
4734 for fn in filenodes:
4734 fctx = repo.filectx(file_, fileid=fn)
4735 fctx = repo.filectx(file_, fileid=fn)
4735 p.append(fctx.node())
4736 p.append(fctx.node())
4736 else:
4737 else:
4737 p = [cp.node() for cp in ctx.parents()]
4738 p = [cp.node() for cp in ctx.parents()]
4738
4739
4739 displayer = cmdutil.show_changeset(ui, repo, opts)
4740 displayer = cmdutil.show_changeset(ui, repo, opts)
4740 for n in p:
4741 for n in p:
4741 if n != nullid:
4742 if n != nullid:
4742 displayer.show(repo[n])
4743 displayer.show(repo[n])
4743 displayer.close()
4744 displayer.close()
4744
4745
4745 @command('paths', [], _('[NAME]'), optionalrepo=True)
4746 @command('paths', [], _('[NAME]'), optionalrepo=True)
4746 def paths(ui, repo, search=None):
4747 def paths(ui, repo, search=None):
4747 """show aliases for remote repositories
4748 """show aliases for remote repositories
4748
4749
4749 Show definition of symbolic path name NAME. If no name is given,
4750 Show definition of symbolic path name NAME. If no name is given,
4750 show definition of all available names.
4751 show definition of all available names.
4751
4752
4752 Option -q/--quiet suppresses all output when searching for NAME
4753 Option -q/--quiet suppresses all output when searching for NAME
4753 and shows only the path names when listing all definitions.
4754 and shows only the path names when listing all definitions.
4754
4755
4755 Path names are defined in the [paths] section of your
4756 Path names are defined in the [paths] section of your
4756 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4757 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4757 repository, ``.hg/hgrc`` is used, too.
4758 repository, ``.hg/hgrc`` is used, too.
4758
4759
4759 The path names ``default`` and ``default-push`` have a special
4760 The path names ``default`` and ``default-push`` have a special
4760 meaning. When performing a push or pull operation, they are used
4761 meaning. When performing a push or pull operation, they are used
4761 as fallbacks if no location is specified on the command-line.
4762 as fallbacks if no location is specified on the command-line.
4762 When ``default-push`` is set, it will be used for push and
4763 When ``default-push`` is set, it will be used for push and
4763 ``default`` will be used for pull; otherwise ``default`` is used
4764 ``default`` will be used for pull; otherwise ``default`` is used
4764 as the fallback for both. When cloning a repository, the clone
4765 as the fallback for both. When cloning a repository, the clone
4765 source is written as ``default`` in ``.hg/hgrc``. Note that
4766 source is written as ``default`` in ``.hg/hgrc``. Note that
4766 ``default`` and ``default-push`` apply to all inbound (e.g.
4767 ``default`` and ``default-push`` apply to all inbound (e.g.
4767 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4768 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4768 :hg:`bundle`) operations.
4769 :hg:`bundle`) operations.
4769
4770
4770 See :hg:`help urls` for more information.
4771 See :hg:`help urls` for more information.
4771
4772
4772 Returns 0 on success.
4773 Returns 0 on success.
4773 """
4774 """
4774 if search:
4775 if search:
4775 for name, path in ui.configitems("paths"):
4776 for name, path in ui.configitems("paths"):
4776 if name == search:
4777 if name == search:
4777 ui.status("%s\n" % util.hidepassword(path))
4778 ui.status("%s\n" % util.hidepassword(path))
4778 return
4779 return
4779 if not ui.quiet:
4780 if not ui.quiet:
4780 ui.warn(_("not found!\n"))
4781 ui.warn(_("not found!\n"))
4781 return 1
4782 return 1
4782 else:
4783 else:
4783 for name, path in ui.configitems("paths"):
4784 for name, path in ui.configitems("paths"):
4784 if ui.quiet:
4785 if ui.quiet:
4785 ui.write("%s\n" % name)
4786 ui.write("%s\n" % name)
4786 else:
4787 else:
4787 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4788 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4788
4789
4789 @command('phase',
4790 @command('phase',
4790 [('p', 'public', False, _('set changeset phase to public')),
4791 [('p', 'public', False, _('set changeset phase to public')),
4791 ('d', 'draft', False, _('set changeset phase to draft')),
4792 ('d', 'draft', False, _('set changeset phase to draft')),
4792 ('s', 'secret', False, _('set changeset phase to secret')),
4793 ('s', 'secret', False, _('set changeset phase to secret')),
4793 ('f', 'force', False, _('allow to move boundary backward')),
4794 ('f', 'force', False, _('allow to move boundary backward')),
4794 ('r', 'rev', [], _('target revision'), _('REV')),
4795 ('r', 'rev', [], _('target revision'), _('REV')),
4795 ],
4796 ],
4796 _('[-p|-d|-s] [-f] [-r] REV...'))
4797 _('[-p|-d|-s] [-f] [-r] REV...'))
4797 def phase(ui, repo, *revs, **opts):
4798 def phase(ui, repo, *revs, **opts):
4798 """set or show the current phase name
4799 """set or show the current phase name
4799
4800
4800 With no argument, show the phase name of specified revisions.
4801 With no argument, show the phase name of specified revisions.
4801
4802
4802 With one of -p/--public, -d/--draft or -s/--secret, change the
4803 With one of -p/--public, -d/--draft or -s/--secret, change the
4803 phase value of the specified revisions.
4804 phase value of the specified revisions.
4804
4805
4805 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4806 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4806 lower phase to an higher phase. Phases are ordered as follows::
4807 lower phase to an higher phase. Phases are ordered as follows::
4807
4808
4808 public < draft < secret
4809 public < draft < secret
4809
4810
4810 Returns 0 on success, 1 if no phases were changed or some could not
4811 Returns 0 on success, 1 if no phases were changed or some could not
4811 be changed.
4812 be changed.
4812 """
4813 """
4813 # search for a unique phase argument
4814 # search for a unique phase argument
4814 targetphase = None
4815 targetphase = None
4815 for idx, name in enumerate(phases.phasenames):
4816 for idx, name in enumerate(phases.phasenames):
4816 if opts[name]:
4817 if opts[name]:
4817 if targetphase is not None:
4818 if targetphase is not None:
4818 raise util.Abort(_('only one phase can be specified'))
4819 raise util.Abort(_('only one phase can be specified'))
4819 targetphase = idx
4820 targetphase = idx
4820
4821
4821 # look for specified revision
4822 # look for specified revision
4822 revs = list(revs)
4823 revs = list(revs)
4823 revs.extend(opts['rev'])
4824 revs.extend(opts['rev'])
4824 if not revs:
4825 if not revs:
4825 raise util.Abort(_('no revisions specified'))
4826 raise util.Abort(_('no revisions specified'))
4826
4827
4827 revs = scmutil.revrange(repo, revs)
4828 revs = scmutil.revrange(repo, revs)
4828
4829
4829 lock = None
4830 lock = None
4830 ret = 0
4831 ret = 0
4831 if targetphase is None:
4832 if targetphase is None:
4832 # display
4833 # display
4833 for r in revs:
4834 for r in revs:
4834 ctx = repo[r]
4835 ctx = repo[r]
4835 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4836 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4836 else:
4837 else:
4837 tr = None
4838 tr = None
4838 lock = repo.lock()
4839 lock = repo.lock()
4839 try:
4840 try:
4840 tr = repo.transaction("phase")
4841 tr = repo.transaction("phase")
4841 # set phase
4842 # set phase
4842 if not revs:
4843 if not revs:
4843 raise util.Abort(_('empty revision set'))
4844 raise util.Abort(_('empty revision set'))
4844 nodes = [repo[r].node() for r in revs]
4845 nodes = [repo[r].node() for r in revs]
4845 # moving revision from public to draft may hide them
4846 # moving revision from public to draft may hide them
4846 # We have to check result on an unfiltered repository
4847 # We have to check result on an unfiltered repository
4847 unfi = repo.unfiltered()
4848 unfi = repo.unfiltered()
4848 getphase = unfi._phasecache.phase
4849 getphase = unfi._phasecache.phase
4849 olddata = [getphase(unfi, r) for r in unfi]
4850 olddata = [getphase(unfi, r) for r in unfi]
4850 phases.advanceboundary(repo, tr, targetphase, nodes)
4851 phases.advanceboundary(repo, tr, targetphase, nodes)
4851 if opts['force']:
4852 if opts['force']:
4852 phases.retractboundary(repo, tr, targetphase, nodes)
4853 phases.retractboundary(repo, tr, targetphase, nodes)
4853 tr.close()
4854 tr.close()
4854 finally:
4855 finally:
4855 if tr is not None:
4856 if tr is not None:
4856 tr.release()
4857 tr.release()
4857 lock.release()
4858 lock.release()
4858 getphase = unfi._phasecache.phase
4859 getphase = unfi._phasecache.phase
4859 newdata = [getphase(unfi, r) for r in unfi]
4860 newdata = [getphase(unfi, r) for r in unfi]
4860 changes = sum(newdata[r] != olddata[r] for r in unfi)
4861 changes = sum(newdata[r] != olddata[r] for r in unfi)
4861 cl = unfi.changelog
4862 cl = unfi.changelog
4862 rejected = [n for n in nodes
4863 rejected = [n for n in nodes
4863 if newdata[cl.rev(n)] < targetphase]
4864 if newdata[cl.rev(n)] < targetphase]
4864 if rejected:
4865 if rejected:
4865 ui.warn(_('cannot move %i changesets to a higher '
4866 ui.warn(_('cannot move %i changesets to a higher '
4866 'phase, use --force\n') % len(rejected))
4867 'phase, use --force\n') % len(rejected))
4867 ret = 1
4868 ret = 1
4868 if changes:
4869 if changes:
4869 msg = _('phase changed for %i changesets\n') % changes
4870 msg = _('phase changed for %i changesets\n') % changes
4870 if ret:
4871 if ret:
4871 ui.status(msg)
4872 ui.status(msg)
4872 else:
4873 else:
4873 ui.note(msg)
4874 ui.note(msg)
4874 else:
4875 else:
4875 ui.warn(_('no phases changed\n'))
4876 ui.warn(_('no phases changed\n'))
4876 ret = 1
4877 ret = 1
4877 return ret
4878 return ret
4878
4879
4879 def postincoming(ui, repo, modheads, optupdate, checkout):
4880 def postincoming(ui, repo, modheads, optupdate, checkout):
4880 if modheads == 0:
4881 if modheads == 0:
4881 return
4882 return
4882 if optupdate:
4883 if optupdate:
4883 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4884 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4884 try:
4885 try:
4885 ret = hg.update(repo, checkout)
4886 ret = hg.update(repo, checkout)
4886 except util.Abort, inst:
4887 except util.Abort, inst:
4887 ui.warn(_("not updating: %s\n") % str(inst))
4888 ui.warn(_("not updating: %s\n") % str(inst))
4888 if inst.hint:
4889 if inst.hint:
4889 ui.warn(_("(%s)\n") % inst.hint)
4890 ui.warn(_("(%s)\n") % inst.hint)
4890 return 0
4891 return 0
4891 if not ret and not checkout:
4892 if not ret and not checkout:
4892 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4893 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4893 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4894 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4894 return ret
4895 return ret
4895 if modheads > 1:
4896 if modheads > 1:
4896 currentbranchheads = len(repo.branchheads())
4897 currentbranchheads = len(repo.branchheads())
4897 if currentbranchheads == modheads:
4898 if currentbranchheads == modheads:
4898 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4899 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4899 elif currentbranchheads > 1:
4900 elif currentbranchheads > 1:
4900 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4901 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4901 "merge)\n"))
4902 "merge)\n"))
4902 else:
4903 else:
4903 ui.status(_("(run 'hg heads' to see heads)\n"))
4904 ui.status(_("(run 'hg heads' to see heads)\n"))
4904 else:
4905 else:
4905 ui.status(_("(run 'hg update' to get a working copy)\n"))
4906 ui.status(_("(run 'hg update' to get a working copy)\n"))
4906
4907
4907 @command('^pull',
4908 @command('^pull',
4908 [('u', 'update', None,
4909 [('u', 'update', None,
4909 _('update to new branch head if changesets were pulled')),
4910 _('update to new branch head if changesets were pulled')),
4910 ('f', 'force', None, _('run even when remote repository is unrelated')),
4911 ('f', 'force', None, _('run even when remote repository is unrelated')),
4911 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4912 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4912 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4913 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4913 ('b', 'branch', [], _('a specific branch you would like to pull'),
4914 ('b', 'branch', [], _('a specific branch you would like to pull'),
4914 _('BRANCH')),
4915 _('BRANCH')),
4915 ] + remoteopts,
4916 ] + remoteopts,
4916 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4917 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4917 def pull(ui, repo, source="default", **opts):
4918 def pull(ui, repo, source="default", **opts):
4918 """pull changes from the specified source
4919 """pull changes from the specified source
4919
4920
4920 Pull changes from a remote repository to a local one.
4921 Pull changes from a remote repository to a local one.
4921
4922
4922 This finds all changes from the repository at the specified path
4923 This finds all changes from the repository at the specified path
4923 or URL and adds them to a local repository (the current one unless
4924 or URL and adds them to a local repository (the current one unless
4924 -R is specified). By default, this does not update the copy of the
4925 -R is specified). By default, this does not update the copy of the
4925 project in the working directory.
4926 project in the working directory.
4926
4927
4927 Use :hg:`incoming` if you want to see what would have been added
4928 Use :hg:`incoming` if you want to see what would have been added
4928 by a pull at the time you issued this command. If you then decide
4929 by a pull at the time you issued this command. If you then decide
4929 to add those changes to the repository, you should use :hg:`pull
4930 to add those changes to the repository, you should use :hg:`pull
4930 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4931 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4931
4932
4932 If SOURCE is omitted, the 'default' path will be used.
4933 If SOURCE is omitted, the 'default' path will be used.
4933 See :hg:`help urls` for more information.
4934 See :hg:`help urls` for more information.
4934
4935
4935 Returns 0 on success, 1 if an update had unresolved files.
4936 Returns 0 on success, 1 if an update had unresolved files.
4936 """
4937 """
4937 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4938 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4938 other = hg.peer(repo, opts, source)
4939 other = hg.peer(repo, opts, source)
4939 try:
4940 try:
4940 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4941 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4941 revs, checkout = hg.addbranchrevs(repo, other, branches,
4942 revs, checkout = hg.addbranchrevs(repo, other, branches,
4942 opts.get('rev'))
4943 opts.get('rev'))
4943
4944
4944 remotebookmarks = other.listkeys('bookmarks')
4945 remotebookmarks = other.listkeys('bookmarks')
4945
4946
4946 if opts.get('bookmark'):
4947 if opts.get('bookmark'):
4947 if not revs:
4948 if not revs:
4948 revs = []
4949 revs = []
4949 for b in opts['bookmark']:
4950 for b in opts['bookmark']:
4950 if b not in remotebookmarks:
4951 if b not in remotebookmarks:
4951 raise util.Abort(_('remote bookmark %s not found!') % b)
4952 raise util.Abort(_('remote bookmark %s not found!') % b)
4952 revs.append(remotebookmarks[b])
4953 revs.append(remotebookmarks[b])
4953
4954
4954 if revs:
4955 if revs:
4955 try:
4956 try:
4956 revs = [other.lookup(rev) for rev in revs]
4957 revs = [other.lookup(rev) for rev in revs]
4957 except error.CapabilityError:
4958 except error.CapabilityError:
4958 err = _("other repository doesn't support revision lookup, "
4959 err = _("other repository doesn't support revision lookup, "
4959 "so a rev cannot be specified.")
4960 "so a rev cannot be specified.")
4960 raise util.Abort(err)
4961 raise util.Abort(err)
4961
4962
4962 modheads = exchange.pull(repo, other, heads=revs,
4963 modheads = exchange.pull(repo, other, heads=revs,
4963 force=opts.get('force'),
4964 force=opts.get('force'),
4964 bookmarks=opts.get('bookmark', ())).cgresult
4965 bookmarks=opts.get('bookmark', ())).cgresult
4965 if checkout:
4966 if checkout:
4966 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4967 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4967 repo._subtoppath = source
4968 repo._subtoppath = source
4968 try:
4969 try:
4969 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4970 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4970
4971
4971 finally:
4972 finally:
4972 del repo._subtoppath
4973 del repo._subtoppath
4973
4974
4974 finally:
4975 finally:
4975 other.close()
4976 other.close()
4976 return ret
4977 return ret
4977
4978
4978 @command('^push',
4979 @command('^push',
4979 [('f', 'force', None, _('force push')),
4980 [('f', 'force', None, _('force push')),
4980 ('r', 'rev', [],
4981 ('r', 'rev', [],
4981 _('a changeset intended to be included in the destination'),
4982 _('a changeset intended to be included in the destination'),
4982 _('REV')),
4983 _('REV')),
4983 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4984 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4984 ('b', 'branch', [],
4985 ('b', 'branch', [],
4985 _('a specific branch you would like to push'), _('BRANCH')),
4986 _('a specific branch you would like to push'), _('BRANCH')),
4986 ('', 'new-branch', False, _('allow pushing a new branch')),
4987 ('', 'new-branch', False, _('allow pushing a new branch')),
4987 ] + remoteopts,
4988 ] + remoteopts,
4988 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4989 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4989 def push(ui, repo, dest=None, **opts):
4990 def push(ui, repo, dest=None, **opts):
4990 """push changes to the specified destination
4991 """push changes to the specified destination
4991
4992
4992 Push changesets from the local repository to the specified
4993 Push changesets from the local repository to the specified
4993 destination.
4994 destination.
4994
4995
4995 This operation is symmetrical to pull: it is identical to a pull
4996 This operation is symmetrical to pull: it is identical to a pull
4996 in the destination repository from the current one.
4997 in the destination repository from the current one.
4997
4998
4998 By default, push will not allow creation of new heads at the
4999 By default, push will not allow creation of new heads at the
4999 destination, since multiple heads would make it unclear which head
5000 destination, since multiple heads would make it unclear which head
5000 to use. In this situation, it is recommended to pull and merge
5001 to use. In this situation, it is recommended to pull and merge
5001 before pushing.
5002 before pushing.
5002
5003
5003 Use --new-branch if you want to allow push to create a new named
5004 Use --new-branch if you want to allow push to create a new named
5004 branch that is not present at the destination. This allows you to
5005 branch that is not present at the destination. This allows you to
5005 only create a new branch without forcing other changes.
5006 only create a new branch without forcing other changes.
5006
5007
5007 .. note::
5008 .. note::
5008
5009
5009 Extra care should be taken with the -f/--force option,
5010 Extra care should be taken with the -f/--force option,
5010 which will push all new heads on all branches, an action which will
5011 which will push all new heads on all branches, an action which will
5011 almost always cause confusion for collaborators.
5012 almost always cause confusion for collaborators.
5012
5013
5013 If -r/--rev is used, the specified revision and all its ancestors
5014 If -r/--rev is used, the specified revision and all its ancestors
5014 will be pushed to the remote repository.
5015 will be pushed to the remote repository.
5015
5016
5016 If -B/--bookmark is used, the specified bookmarked revision, its
5017 If -B/--bookmark is used, the specified bookmarked revision, its
5017 ancestors, and the bookmark will be pushed to the remote
5018 ancestors, and the bookmark will be pushed to the remote
5018 repository.
5019 repository.
5019
5020
5020 Please see :hg:`help urls` for important details about ``ssh://``
5021 Please see :hg:`help urls` for important details about ``ssh://``
5021 URLs. If DESTINATION is omitted, a default path will be used.
5022 URLs. If DESTINATION is omitted, a default path will be used.
5022
5023
5023 Returns 0 if push was successful, 1 if nothing to push.
5024 Returns 0 if push was successful, 1 if nothing to push.
5024 """
5025 """
5025
5026
5026 if opts.get('bookmark'):
5027 if opts.get('bookmark'):
5027 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5028 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5028 for b in opts['bookmark']:
5029 for b in opts['bookmark']:
5029 # translate -B options to -r so changesets get pushed
5030 # translate -B options to -r so changesets get pushed
5030 if b in repo._bookmarks:
5031 if b in repo._bookmarks:
5031 opts.setdefault('rev', []).append(b)
5032 opts.setdefault('rev', []).append(b)
5032 else:
5033 else:
5033 # if we try to push a deleted bookmark, translate it to null
5034 # if we try to push a deleted bookmark, translate it to null
5034 # this lets simultaneous -r, -b options continue working
5035 # this lets simultaneous -r, -b options continue working
5035 opts.setdefault('rev', []).append("null")
5036 opts.setdefault('rev', []).append("null")
5036
5037
5037 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5038 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5038 dest, branches = hg.parseurl(dest, opts.get('branch'))
5039 dest, branches = hg.parseurl(dest, opts.get('branch'))
5039 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5040 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5040 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5041 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5041 try:
5042 try:
5042 other = hg.peer(repo, opts, dest)
5043 other = hg.peer(repo, opts, dest)
5043 except error.RepoError:
5044 except error.RepoError:
5044 if dest == "default-push":
5045 if dest == "default-push":
5045 raise util.Abort(_("default repository not configured!"),
5046 raise util.Abort(_("default repository not configured!"),
5046 hint=_('see the "path" section in "hg help config"'))
5047 hint=_('see the "path" section in "hg help config"'))
5047 else:
5048 else:
5048 raise
5049 raise
5049
5050
5050 if revs:
5051 if revs:
5051 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5052 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5052
5053
5053 repo._subtoppath = dest
5054 repo._subtoppath = dest
5054 try:
5055 try:
5055 # push subrepos depth-first for coherent ordering
5056 # push subrepos depth-first for coherent ordering
5056 c = repo['']
5057 c = repo['']
5057 subs = c.substate # only repos that are committed
5058 subs = c.substate # only repos that are committed
5058 for s in sorted(subs):
5059 for s in sorted(subs):
5059 result = c.sub(s).push(opts)
5060 result = c.sub(s).push(opts)
5060 if result == 0:
5061 if result == 0:
5061 return not result
5062 return not result
5062 finally:
5063 finally:
5063 del repo._subtoppath
5064 del repo._subtoppath
5064 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5065 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5065 newbranch=opts.get('new_branch'),
5066 newbranch=opts.get('new_branch'),
5066 bookmarks=opts.get('bookmark', ()))
5067 bookmarks=opts.get('bookmark', ()))
5067
5068
5068 result = not pushop.cgresult
5069 result = not pushop.cgresult
5069
5070
5070 if pushop.bkresult is not None:
5071 if pushop.bkresult is not None:
5071 if pushop.bkresult == 2:
5072 if pushop.bkresult == 2:
5072 result = 2
5073 result = 2
5073 elif not result and pushop.bkresult:
5074 elif not result and pushop.bkresult:
5074 result = 2
5075 result = 2
5075
5076
5076 return result
5077 return result
5077
5078
5078 @command('recover', [])
5079 @command('recover', [])
5079 def recover(ui, repo):
5080 def recover(ui, repo):
5080 """roll back an interrupted transaction
5081 """roll back an interrupted transaction
5081
5082
5082 Recover from an interrupted commit or pull.
5083 Recover from an interrupted commit or pull.
5083
5084
5084 This command tries to fix the repository status after an
5085 This command tries to fix the repository status after an
5085 interrupted operation. It should only be necessary when Mercurial
5086 interrupted operation. It should only be necessary when Mercurial
5086 suggests it.
5087 suggests it.
5087
5088
5088 Returns 0 if successful, 1 if nothing to recover or verify fails.
5089 Returns 0 if successful, 1 if nothing to recover or verify fails.
5089 """
5090 """
5090 if repo.recover():
5091 if repo.recover():
5091 return hg.verify(repo)
5092 return hg.verify(repo)
5092 return 1
5093 return 1
5093
5094
5094 @command('^remove|rm',
5095 @command('^remove|rm',
5095 [('A', 'after', None, _('record delete for missing files')),
5096 [('A', 'after', None, _('record delete for missing files')),
5096 ('f', 'force', None,
5097 ('f', 'force', None,
5097 _('remove (and delete) file even if added or modified')),
5098 _('remove (and delete) file even if added or modified')),
5098 ] + subrepoopts + walkopts,
5099 ] + subrepoopts + walkopts,
5099 _('[OPTION]... FILE...'),
5100 _('[OPTION]... FILE...'),
5100 inferrepo=True)
5101 inferrepo=True)
5101 def remove(ui, repo, *pats, **opts):
5102 def remove(ui, repo, *pats, **opts):
5102 """remove the specified files on the next commit
5103 """remove the specified files on the next commit
5103
5104
5104 Schedule the indicated files for removal from the current branch.
5105 Schedule the indicated files for removal from the current branch.
5105
5106
5106 This command schedules the files to be removed at the next commit.
5107 This command schedules the files to be removed at the next commit.
5107 To undo a remove before that, see :hg:`revert`. To undo added
5108 To undo a remove before that, see :hg:`revert`. To undo added
5108 files, see :hg:`forget`.
5109 files, see :hg:`forget`.
5109
5110
5110 .. container:: verbose
5111 .. container:: verbose
5111
5112
5112 -A/--after can be used to remove only files that have already
5113 -A/--after can be used to remove only files that have already
5113 been deleted, -f/--force can be used to force deletion, and -Af
5114 been deleted, -f/--force can be used to force deletion, and -Af
5114 can be used to remove files from the next revision without
5115 can be used to remove files from the next revision without
5115 deleting them from the working directory.
5116 deleting them from the working directory.
5116
5117
5117 The following table details the behavior of remove for different
5118 The following table details the behavior of remove for different
5118 file states (columns) and option combinations (rows). The file
5119 file states (columns) and option combinations (rows). The file
5119 states are Added [A], Clean [C], Modified [M] and Missing [!]
5120 states are Added [A], Clean [C], Modified [M] and Missing [!]
5120 (as reported by :hg:`status`). The actions are Warn, Remove
5121 (as reported by :hg:`status`). The actions are Warn, Remove
5121 (from branch) and Delete (from disk):
5122 (from branch) and Delete (from disk):
5122
5123
5123 ========= == == == ==
5124 ========= == == == ==
5124 opt/state A C M !
5125 opt/state A C M !
5125 ========= == == == ==
5126 ========= == == == ==
5126 none W RD W R
5127 none W RD W R
5127 -f R RD RD R
5128 -f R RD RD R
5128 -A W W W R
5129 -A W W W R
5129 -Af R R R R
5130 -Af R R R R
5130 ========= == == == ==
5131 ========= == == == ==
5131
5132
5132 Note that remove never deletes files in Added [A] state from the
5133 Note that remove never deletes files in Added [A] state from the
5133 working directory, not even if option --force is specified.
5134 working directory, not even if option --force is specified.
5134
5135
5135 Returns 0 on success, 1 if any warnings encountered.
5136 Returns 0 on success, 1 if any warnings encountered.
5136 """
5137 """
5137
5138
5138 after, force = opts.get('after'), opts.get('force')
5139 after, force = opts.get('after'), opts.get('force')
5139 if not pats and not after:
5140 if not pats and not after:
5140 raise util.Abort(_('no files specified'))
5141 raise util.Abort(_('no files specified'))
5141
5142
5142 m = scmutil.match(repo[None], pats, opts)
5143 m = scmutil.match(repo[None], pats, opts)
5143 subrepos = opts.get('subrepos')
5144 subrepos = opts.get('subrepos')
5144 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5145 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5145
5146
5146 @command('rename|move|mv',
5147 @command('rename|move|mv',
5147 [('A', 'after', None, _('record a rename that has already occurred')),
5148 [('A', 'after', None, _('record a rename that has already occurred')),
5148 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5149 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5149 ] + walkopts + dryrunopts,
5150 ] + walkopts + dryrunopts,
5150 _('[OPTION]... SOURCE... DEST'))
5151 _('[OPTION]... SOURCE... DEST'))
5151 def rename(ui, repo, *pats, **opts):
5152 def rename(ui, repo, *pats, **opts):
5152 """rename files; equivalent of copy + remove
5153 """rename files; equivalent of copy + remove
5153
5154
5154 Mark dest as copies of sources; mark sources for deletion. If dest
5155 Mark dest as copies of sources; mark sources for deletion. If dest
5155 is a directory, copies are put in that directory. If dest is a
5156 is a directory, copies are put in that directory. If dest is a
5156 file, there can only be one source.
5157 file, there can only be one source.
5157
5158
5158 By default, this command copies the contents of files as they
5159 By default, this command copies the contents of files as they
5159 exist in the working directory. If invoked with -A/--after, the
5160 exist in the working directory. If invoked with -A/--after, the
5160 operation is recorded, but no copying is performed.
5161 operation is recorded, but no copying is performed.
5161
5162
5162 This command takes effect at the next commit. To undo a rename
5163 This command takes effect at the next commit. To undo a rename
5163 before that, see :hg:`revert`.
5164 before that, see :hg:`revert`.
5164
5165
5165 Returns 0 on success, 1 if errors are encountered.
5166 Returns 0 on success, 1 if errors are encountered.
5166 """
5167 """
5167 wlock = repo.wlock(False)
5168 wlock = repo.wlock(False)
5168 try:
5169 try:
5169 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5170 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5170 finally:
5171 finally:
5171 wlock.release()
5172 wlock.release()
5172
5173
5173 @command('resolve',
5174 @command('resolve',
5174 [('a', 'all', None, _('select all unresolved files')),
5175 [('a', 'all', None, _('select all unresolved files')),
5175 ('l', 'list', None, _('list state of files needing merge')),
5176 ('l', 'list', None, _('list state of files needing merge')),
5176 ('m', 'mark', None, _('mark files as resolved')),
5177 ('m', 'mark', None, _('mark files as resolved')),
5177 ('u', 'unmark', None, _('mark files as unresolved')),
5178 ('u', 'unmark', None, _('mark files as unresolved')),
5178 ('n', 'no-status', None, _('hide status prefix'))]
5179 ('n', 'no-status', None, _('hide status prefix'))]
5179 + mergetoolopts + walkopts,
5180 + mergetoolopts + walkopts,
5180 _('[OPTION]... [FILE]...'),
5181 _('[OPTION]... [FILE]...'),
5181 inferrepo=True)
5182 inferrepo=True)
5182 def resolve(ui, repo, *pats, **opts):
5183 def resolve(ui, repo, *pats, **opts):
5183 """redo merges or set/view the merge status of files
5184 """redo merges or set/view the merge status of files
5184
5185
5185 Merges with unresolved conflicts are often the result of
5186 Merges with unresolved conflicts are often the result of
5186 non-interactive merging using the ``internal:merge`` configuration
5187 non-interactive merging using the ``internal:merge`` configuration
5187 setting, or a command-line merge tool like ``diff3``. The resolve
5188 setting, or a command-line merge tool like ``diff3``. The resolve
5188 command is used to manage the files involved in a merge, after
5189 command is used to manage the files involved in a merge, after
5189 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5190 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5190 working directory must have two parents). See :hg:`help
5191 working directory must have two parents). See :hg:`help
5191 merge-tools` for information on configuring merge tools.
5192 merge-tools` for information on configuring merge tools.
5192
5193
5193 The resolve command can be used in the following ways:
5194 The resolve command can be used in the following ways:
5194
5195
5195 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5196 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5196 files, discarding any previous merge attempts. Re-merging is not
5197 files, discarding any previous merge attempts. Re-merging is not
5197 performed for files already marked as resolved. Use ``--all/-a``
5198 performed for files already marked as resolved. Use ``--all/-a``
5198 to select all unresolved files. ``--tool`` can be used to specify
5199 to select all unresolved files. ``--tool`` can be used to specify
5199 the merge tool used for the given files. It overrides the HGMERGE
5200 the merge tool used for the given files. It overrides the HGMERGE
5200 environment variable and your configuration files. Previous file
5201 environment variable and your configuration files. Previous file
5201 contents are saved with a ``.orig`` suffix.
5202 contents are saved with a ``.orig`` suffix.
5202
5203
5203 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5204 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5204 (e.g. after having manually fixed-up the files). The default is
5205 (e.g. after having manually fixed-up the files). The default is
5205 to mark all unresolved files.
5206 to mark all unresolved files.
5206
5207
5207 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5208 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5208 default is to mark all resolved files.
5209 default is to mark all resolved files.
5209
5210
5210 - :hg:`resolve -l`: list files which had or still have conflicts.
5211 - :hg:`resolve -l`: list files which had or still have conflicts.
5211 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5212 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5212
5213
5213 Note that Mercurial will not let you commit files with unresolved
5214 Note that Mercurial will not let you commit files with unresolved
5214 merge conflicts. You must use :hg:`resolve -m ...` before you can
5215 merge conflicts. You must use :hg:`resolve -m ...` before you can
5215 commit after a conflicting merge.
5216 commit after a conflicting merge.
5216
5217
5217 Returns 0 on success, 1 if any files fail a resolve attempt.
5218 Returns 0 on success, 1 if any files fail a resolve attempt.
5218 """
5219 """
5219
5220
5220 all, mark, unmark, show, nostatus = \
5221 all, mark, unmark, show, nostatus = \
5221 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5222 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5222
5223
5223 if (show and (mark or unmark)) or (mark and unmark):
5224 if (show and (mark or unmark)) or (mark and unmark):
5224 raise util.Abort(_("too many options specified"))
5225 raise util.Abort(_("too many options specified"))
5225 if pats and all:
5226 if pats and all:
5226 raise util.Abort(_("can't specify --all and patterns"))
5227 raise util.Abort(_("can't specify --all and patterns"))
5227 if not (all or pats or show or mark or unmark):
5228 if not (all or pats or show or mark or unmark):
5228 raise util.Abort(_('no files or directories specified'),
5229 raise util.Abort(_('no files or directories specified'),
5229 hint=('use --all to remerge all files'))
5230 hint=('use --all to remerge all files'))
5230
5231
5231 wlock = repo.wlock()
5232 wlock = repo.wlock()
5232 try:
5233 try:
5233 ms = mergemod.mergestate(repo)
5234 ms = mergemod.mergestate(repo)
5234
5235
5235 if not (ms.active() or repo.dirstate.p2() != nullid) and not show:
5236 if not (ms.active() or repo.dirstate.p2() != nullid) and not show:
5236 raise util.Abort(
5237 raise util.Abort(
5237 _('resolve command not applicable when not merging'))
5238 _('resolve command not applicable when not merging'))
5238
5239
5239 m = scmutil.match(repo[None], pats, opts)
5240 m = scmutil.match(repo[None], pats, opts)
5240 ret = 0
5241 ret = 0
5241 didwork = False
5242 didwork = False
5242
5243
5243 for f in ms:
5244 for f in ms:
5244 if not m(f):
5245 if not m(f):
5245 continue
5246 continue
5246
5247
5247 didwork = True
5248 didwork = True
5248
5249
5249 if show:
5250 if show:
5250 if nostatus:
5251 if nostatus:
5251 ui.write("%s\n" % f)
5252 ui.write("%s\n" % f)
5252 else:
5253 else:
5253 ui.write("%s %s\n" % (ms[f].upper(), f),
5254 ui.write("%s %s\n" % (ms[f].upper(), f),
5254 label='resolve.' +
5255 label='resolve.' +
5255 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5256 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5256 elif mark:
5257 elif mark:
5257 ms.mark(f, "r")
5258 ms.mark(f, "r")
5258 elif unmark:
5259 elif unmark:
5259 ms.mark(f, "u")
5260 ms.mark(f, "u")
5260 else:
5261 else:
5261 wctx = repo[None]
5262 wctx = repo[None]
5262
5263
5263 # backup pre-resolve (merge uses .orig for its own purposes)
5264 # backup pre-resolve (merge uses .orig for its own purposes)
5264 a = repo.wjoin(f)
5265 a = repo.wjoin(f)
5265 util.copyfile(a, a + ".resolve")
5266 util.copyfile(a, a + ".resolve")
5266
5267
5267 try:
5268 try:
5268 # resolve file
5269 # resolve file
5269 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5270 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5270 'resolve')
5271 'resolve')
5271 if ms.resolve(f, wctx):
5272 if ms.resolve(f, wctx):
5272 ret = 1
5273 ret = 1
5273 finally:
5274 finally:
5274 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5275 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5275 ms.commit()
5276 ms.commit()
5276
5277
5277 # replace filemerge's .orig file with our resolve file
5278 # replace filemerge's .orig file with our resolve file
5278 util.rename(a + ".resolve", a + ".orig")
5279 util.rename(a + ".resolve", a + ".orig")
5279
5280
5280 ms.commit()
5281 ms.commit()
5281
5282
5282 if not didwork and pats:
5283 if not didwork and pats:
5283 ui.warn(_("arguments do not match paths that need resolving\n"))
5284 ui.warn(_("arguments do not match paths that need resolving\n"))
5284
5285
5285 finally:
5286 finally:
5286 wlock.release()
5287 wlock.release()
5287
5288
5288 # Nudge users into finishing an unfinished operation. We don't print
5289 # Nudge users into finishing an unfinished operation. We don't print
5289 # this with the list/show operation because we want list/show to remain
5290 # this with the list/show operation because we want list/show to remain
5290 # machine readable.
5291 # machine readable.
5291 if not list(ms.unresolved()) and not show:
5292 if not list(ms.unresolved()) and not show:
5292 ui.status(_('(no more unresolved files)\n'))
5293 ui.status(_('(no more unresolved files)\n'))
5293
5294
5294 return ret
5295 return ret
5295
5296
5296 @command('revert',
5297 @command('revert',
5297 [('a', 'all', None, _('revert all changes when no arguments given')),
5298 [('a', 'all', None, _('revert all changes when no arguments given')),
5298 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5299 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5299 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5300 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5300 ('C', 'no-backup', None, _('do not save backup copies of files')),
5301 ('C', 'no-backup', None, _('do not save backup copies of files')),
5301 ] + walkopts + dryrunopts,
5302 ] + walkopts + dryrunopts,
5302 _('[OPTION]... [-r REV] [NAME]...'))
5303 _('[OPTION]... [-r REV] [NAME]...'))
5303 def revert(ui, repo, *pats, **opts):
5304 def revert(ui, repo, *pats, **opts):
5304 """restore files to their checkout state
5305 """restore files to their checkout state
5305
5306
5306 .. note::
5307 .. note::
5307
5308
5308 To check out earlier revisions, you should use :hg:`update REV`.
5309 To check out earlier revisions, you should use :hg:`update REV`.
5309 To cancel an uncommitted merge (and lose your changes),
5310 To cancel an uncommitted merge (and lose your changes),
5310 use :hg:`update --clean .`.
5311 use :hg:`update --clean .`.
5311
5312
5312 With no revision specified, revert the specified files or directories
5313 With no revision specified, revert the specified files or directories
5313 to the contents they had in the parent of the working directory.
5314 to the contents they had in the parent of the working directory.
5314 This restores the contents of files to an unmodified
5315 This restores the contents of files to an unmodified
5315 state and unschedules adds, removes, copies, and renames. If the
5316 state and unschedules adds, removes, copies, and renames. If the
5316 working directory has two parents, you must explicitly specify a
5317 working directory has two parents, you must explicitly specify a
5317 revision.
5318 revision.
5318
5319
5319 Using the -r/--rev or -d/--date options, revert the given files or
5320 Using the -r/--rev or -d/--date options, revert the given files or
5320 directories to their states as of a specific revision. Because
5321 directories to their states as of a specific revision. Because
5321 revert does not change the working directory parents, this will
5322 revert does not change the working directory parents, this will
5322 cause these files to appear modified. This can be helpful to "back
5323 cause these files to appear modified. This can be helpful to "back
5323 out" some or all of an earlier change. See :hg:`backout` for a
5324 out" some or all of an earlier change. See :hg:`backout` for a
5324 related method.
5325 related method.
5325
5326
5326 Modified files are saved with a .orig suffix before reverting.
5327 Modified files are saved with a .orig suffix before reverting.
5327 To disable these backups, use --no-backup.
5328 To disable these backups, use --no-backup.
5328
5329
5329 See :hg:`help dates` for a list of formats valid for -d/--date.
5330 See :hg:`help dates` for a list of formats valid for -d/--date.
5330
5331
5331 Returns 0 on success.
5332 Returns 0 on success.
5332 """
5333 """
5333
5334
5334 if opts.get("date"):
5335 if opts.get("date"):
5335 if opts.get("rev"):
5336 if opts.get("rev"):
5336 raise util.Abort(_("you can't specify a revision and a date"))
5337 raise util.Abort(_("you can't specify a revision and a date"))
5337 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5338 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5338
5339
5339 parent, p2 = repo.dirstate.parents()
5340 parent, p2 = repo.dirstate.parents()
5340 if not opts.get('rev') and p2 != nullid:
5341 if not opts.get('rev') and p2 != nullid:
5341 # revert after merge is a trap for new users (issue2915)
5342 # revert after merge is a trap for new users (issue2915)
5342 raise util.Abort(_('uncommitted merge with no revision specified'),
5343 raise util.Abort(_('uncommitted merge with no revision specified'),
5343 hint=_('use "hg update" or see "hg help revert"'))
5344 hint=_('use "hg update" or see "hg help revert"'))
5344
5345
5345 ctx = scmutil.revsingle(repo, opts.get('rev'))
5346 ctx = scmutil.revsingle(repo, opts.get('rev'))
5346
5347
5347 if not pats and not opts.get('all'):
5348 if not pats and not opts.get('all'):
5348 msg = _("no files or directories specified")
5349 msg = _("no files or directories specified")
5349 if p2 != nullid:
5350 if p2 != nullid:
5350 hint = _("uncommitted merge, use --all to discard all changes,"
5351 hint = _("uncommitted merge, use --all to discard all changes,"
5351 " or 'hg update -C .' to abort the merge")
5352 " or 'hg update -C .' to abort the merge")
5352 raise util.Abort(msg, hint=hint)
5353 raise util.Abort(msg, hint=hint)
5353 dirty = util.any(repo.status())
5354 dirty = util.any(repo.status())
5354 node = ctx.node()
5355 node = ctx.node()
5355 if node != parent:
5356 if node != parent:
5356 if dirty:
5357 if dirty:
5357 hint = _("uncommitted changes, use --all to discard all"
5358 hint = _("uncommitted changes, use --all to discard all"
5358 " changes, or 'hg update %s' to update") % ctx.rev()
5359 " changes, or 'hg update %s' to update") % ctx.rev()
5359 else:
5360 else:
5360 hint = _("use --all to revert all files,"
5361 hint = _("use --all to revert all files,"
5361 " or 'hg update %s' to update") % ctx.rev()
5362 " or 'hg update %s' to update") % ctx.rev()
5362 elif dirty:
5363 elif dirty:
5363 hint = _("uncommitted changes, use --all to discard all changes")
5364 hint = _("uncommitted changes, use --all to discard all changes")
5364 else:
5365 else:
5365 hint = _("use --all to revert all files")
5366 hint = _("use --all to revert all files")
5366 raise util.Abort(msg, hint=hint)
5367 raise util.Abort(msg, hint=hint)
5367
5368
5368 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5369 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5369
5370
5370 @command('rollback', dryrunopts +
5371 @command('rollback', dryrunopts +
5371 [('f', 'force', False, _('ignore safety measures'))])
5372 [('f', 'force', False, _('ignore safety measures'))])
5372 def rollback(ui, repo, **opts):
5373 def rollback(ui, repo, **opts):
5373 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5374 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5374
5375
5375 Please use :hg:`commit --amend` instead of rollback to correct
5376 Please use :hg:`commit --amend` instead of rollback to correct
5376 mistakes in the last commit.
5377 mistakes in the last commit.
5377
5378
5378 This command should be used with care. There is only one level of
5379 This command should be used with care. There is only one level of
5379 rollback, and there is no way to undo a rollback. It will also
5380 rollback, and there is no way to undo a rollback. It will also
5380 restore the dirstate at the time of the last transaction, losing
5381 restore the dirstate at the time of the last transaction, losing
5381 any dirstate changes since that time. This command does not alter
5382 any dirstate changes since that time. This command does not alter
5382 the working directory.
5383 the working directory.
5383
5384
5384 Transactions are used to encapsulate the effects of all commands
5385 Transactions are used to encapsulate the effects of all commands
5385 that create new changesets or propagate existing changesets into a
5386 that create new changesets or propagate existing changesets into a
5386 repository.
5387 repository.
5387
5388
5388 .. container:: verbose
5389 .. container:: verbose
5389
5390
5390 For example, the following commands are transactional, and their
5391 For example, the following commands are transactional, and their
5391 effects can be rolled back:
5392 effects can be rolled back:
5392
5393
5393 - commit
5394 - commit
5394 - import
5395 - import
5395 - pull
5396 - pull
5396 - push (with this repository as the destination)
5397 - push (with this repository as the destination)
5397 - unbundle
5398 - unbundle
5398
5399
5399 To avoid permanent data loss, rollback will refuse to rollback a
5400 To avoid permanent data loss, rollback will refuse to rollback a
5400 commit transaction if it isn't checked out. Use --force to
5401 commit transaction if it isn't checked out. Use --force to
5401 override this protection.
5402 override this protection.
5402
5403
5403 This command is not intended for use on public repositories. Once
5404 This command is not intended for use on public repositories. Once
5404 changes are visible for pull by other users, rolling a transaction
5405 changes are visible for pull by other users, rolling a transaction
5405 back locally is ineffective (someone else may already have pulled
5406 back locally is ineffective (someone else may already have pulled
5406 the changes). Furthermore, a race is possible with readers of the
5407 the changes). Furthermore, a race is possible with readers of the
5407 repository; for example an in-progress pull from the repository
5408 repository; for example an in-progress pull from the repository
5408 may fail if a rollback is performed.
5409 may fail if a rollback is performed.
5409
5410
5410 Returns 0 on success, 1 if no rollback data is available.
5411 Returns 0 on success, 1 if no rollback data is available.
5411 """
5412 """
5412 return repo.rollback(dryrun=opts.get('dry_run'),
5413 return repo.rollback(dryrun=opts.get('dry_run'),
5413 force=opts.get('force'))
5414 force=opts.get('force'))
5414
5415
5415 @command('root', [])
5416 @command('root', [])
5416 def root(ui, repo):
5417 def root(ui, repo):
5417 """print the root (top) of the current working directory
5418 """print the root (top) of the current working directory
5418
5419
5419 Print the root directory of the current repository.
5420 Print the root directory of the current repository.
5420
5421
5421 Returns 0 on success.
5422 Returns 0 on success.
5422 """
5423 """
5423 ui.write(repo.root + "\n")
5424 ui.write(repo.root + "\n")
5424
5425
5425 @command('^serve',
5426 @command('^serve',
5426 [('A', 'accesslog', '', _('name of access log file to write to'),
5427 [('A', 'accesslog', '', _('name of access log file to write to'),
5427 _('FILE')),
5428 _('FILE')),
5428 ('d', 'daemon', None, _('run server in background')),
5429 ('d', 'daemon', None, _('run server in background')),
5429 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5430 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5430 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5431 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5431 # use string type, then we can check if something was passed
5432 # use string type, then we can check if something was passed
5432 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5433 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5433 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5434 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5434 _('ADDR')),
5435 _('ADDR')),
5435 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5436 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5436 _('PREFIX')),
5437 _('PREFIX')),
5437 ('n', 'name', '',
5438 ('n', 'name', '',
5438 _('name to show in web pages (default: working directory)'), _('NAME')),
5439 _('name to show in web pages (default: working directory)'), _('NAME')),
5439 ('', 'web-conf', '',
5440 ('', 'web-conf', '',
5440 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5441 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5441 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5442 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5442 _('FILE')),
5443 _('FILE')),
5443 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5444 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5444 ('', 'stdio', None, _('for remote clients')),
5445 ('', 'stdio', None, _('for remote clients')),
5445 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5446 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5446 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5447 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5447 ('', 'style', '', _('template style to use'), _('STYLE')),
5448 ('', 'style', '', _('template style to use'), _('STYLE')),
5448 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5449 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5449 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5450 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5450 _('[OPTION]...'),
5451 _('[OPTION]...'),
5451 optionalrepo=True)
5452 optionalrepo=True)
5452 def serve(ui, repo, **opts):
5453 def serve(ui, repo, **opts):
5453 """start stand-alone webserver
5454 """start stand-alone webserver
5454
5455
5455 Start a local HTTP repository browser and pull server. You can use
5456 Start a local HTTP repository browser and pull server. You can use
5456 this for ad-hoc sharing and browsing of repositories. It is
5457 this for ad-hoc sharing and browsing of repositories. It is
5457 recommended to use a real web server to serve a repository for
5458 recommended to use a real web server to serve a repository for
5458 longer periods of time.
5459 longer periods of time.
5459
5460
5460 Please note that the server does not implement access control.
5461 Please note that the server does not implement access control.
5461 This means that, by default, anybody can read from the server and
5462 This means that, by default, anybody can read from the server and
5462 nobody can write to it by default. Set the ``web.allow_push``
5463 nobody can write to it by default. Set the ``web.allow_push``
5463 option to ``*`` to allow everybody to push to the server. You
5464 option to ``*`` to allow everybody to push to the server. You
5464 should use a real web server if you need to authenticate users.
5465 should use a real web server if you need to authenticate users.
5465
5466
5466 By default, the server logs accesses to stdout and errors to
5467 By default, the server logs accesses to stdout and errors to
5467 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5468 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5468 files.
5469 files.
5469
5470
5470 To have the server choose a free port number to listen on, specify
5471 To have the server choose a free port number to listen on, specify
5471 a port number of 0; in this case, the server will print the port
5472 a port number of 0; in this case, the server will print the port
5472 number it uses.
5473 number it uses.
5473
5474
5474 Returns 0 on success.
5475 Returns 0 on success.
5475 """
5476 """
5476
5477
5477 if opts["stdio"] and opts["cmdserver"]:
5478 if opts["stdio"] and opts["cmdserver"]:
5478 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5479 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5479
5480
5480 if opts["stdio"]:
5481 if opts["stdio"]:
5481 if repo is None:
5482 if repo is None:
5482 raise error.RepoError(_("there is no Mercurial repository here"
5483 raise error.RepoError(_("there is no Mercurial repository here"
5483 " (.hg not found)"))
5484 " (.hg not found)"))
5484 s = sshserver.sshserver(ui, repo)
5485 s = sshserver.sshserver(ui, repo)
5485 s.serve_forever()
5486 s.serve_forever()
5486
5487
5487 if opts["cmdserver"]:
5488 if opts["cmdserver"]:
5488 service = commandserver.createservice(ui, repo, opts)
5489 service = commandserver.createservice(ui, repo, opts)
5489 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5490 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5490
5491
5491 # this way we can check if something was given in the command-line
5492 # this way we can check if something was given in the command-line
5492 if opts.get('port'):
5493 if opts.get('port'):
5493 opts['port'] = util.getport(opts.get('port'))
5494 opts['port'] = util.getport(opts.get('port'))
5494
5495
5495 baseui = repo and repo.baseui or ui
5496 baseui = repo and repo.baseui or ui
5496 optlist = ("name templates style address port prefix ipv6"
5497 optlist = ("name templates style address port prefix ipv6"
5497 " accesslog errorlog certificate encoding")
5498 " accesslog errorlog certificate encoding")
5498 for o in optlist.split():
5499 for o in optlist.split():
5499 val = opts.get(o, '')
5500 val = opts.get(o, '')
5500 if val in (None, ''): # should check against default options instead
5501 if val in (None, ''): # should check against default options instead
5501 continue
5502 continue
5502 baseui.setconfig("web", o, val, 'serve')
5503 baseui.setconfig("web", o, val, 'serve')
5503 if repo and repo.ui != baseui:
5504 if repo and repo.ui != baseui:
5504 repo.ui.setconfig("web", o, val, 'serve')
5505 repo.ui.setconfig("web", o, val, 'serve')
5505
5506
5506 o = opts.get('web_conf') or opts.get('webdir_conf')
5507 o = opts.get('web_conf') or opts.get('webdir_conf')
5507 if not o:
5508 if not o:
5508 if not repo:
5509 if not repo:
5509 raise error.RepoError(_("there is no Mercurial repository"
5510 raise error.RepoError(_("there is no Mercurial repository"
5510 " here (.hg not found)"))
5511 " here (.hg not found)"))
5511 o = repo
5512 o = repo
5512
5513
5513 app = hgweb.hgweb(o, baseui=baseui)
5514 app = hgweb.hgweb(o, baseui=baseui)
5514 service = httpservice(ui, app, opts)
5515 service = httpservice(ui, app, opts)
5515 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5516 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5516
5517
5517 class httpservice(object):
5518 class httpservice(object):
5518 def __init__(self, ui, app, opts):
5519 def __init__(self, ui, app, opts):
5519 self.ui = ui
5520 self.ui = ui
5520 self.app = app
5521 self.app = app
5521 self.opts = opts
5522 self.opts = opts
5522
5523
5523 def init(self):
5524 def init(self):
5524 util.setsignalhandler()
5525 util.setsignalhandler()
5525 self.httpd = hgweb_server.create_server(self.ui, self.app)
5526 self.httpd = hgweb_server.create_server(self.ui, self.app)
5526
5527
5527 if self.opts['port'] and not self.ui.verbose:
5528 if self.opts['port'] and not self.ui.verbose:
5528 return
5529 return
5529
5530
5530 if self.httpd.prefix:
5531 if self.httpd.prefix:
5531 prefix = self.httpd.prefix.strip('/') + '/'
5532 prefix = self.httpd.prefix.strip('/') + '/'
5532 else:
5533 else:
5533 prefix = ''
5534 prefix = ''
5534
5535
5535 port = ':%d' % self.httpd.port
5536 port = ':%d' % self.httpd.port
5536 if port == ':80':
5537 if port == ':80':
5537 port = ''
5538 port = ''
5538
5539
5539 bindaddr = self.httpd.addr
5540 bindaddr = self.httpd.addr
5540 if bindaddr == '0.0.0.0':
5541 if bindaddr == '0.0.0.0':
5541 bindaddr = '*'
5542 bindaddr = '*'
5542 elif ':' in bindaddr: # IPv6
5543 elif ':' in bindaddr: # IPv6
5543 bindaddr = '[%s]' % bindaddr
5544 bindaddr = '[%s]' % bindaddr
5544
5545
5545 fqaddr = self.httpd.fqaddr
5546 fqaddr = self.httpd.fqaddr
5546 if ':' in fqaddr:
5547 if ':' in fqaddr:
5547 fqaddr = '[%s]' % fqaddr
5548 fqaddr = '[%s]' % fqaddr
5548 if self.opts['port']:
5549 if self.opts['port']:
5549 write = self.ui.status
5550 write = self.ui.status
5550 else:
5551 else:
5551 write = self.ui.write
5552 write = self.ui.write
5552 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5553 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5553 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5554 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5554 self.ui.flush() # avoid buffering of status message
5555 self.ui.flush() # avoid buffering of status message
5555
5556
5556 def run(self):
5557 def run(self):
5557 self.httpd.serve_forever()
5558 self.httpd.serve_forever()
5558
5559
5559
5560
5560 @command('^status|st',
5561 @command('^status|st',
5561 [('A', 'all', None, _('show status of all files')),
5562 [('A', 'all', None, _('show status of all files')),
5562 ('m', 'modified', None, _('show only modified files')),
5563 ('m', 'modified', None, _('show only modified files')),
5563 ('a', 'added', None, _('show only added files')),
5564 ('a', 'added', None, _('show only added files')),
5564 ('r', 'removed', None, _('show only removed files')),
5565 ('r', 'removed', None, _('show only removed files')),
5565 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5566 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5566 ('c', 'clean', None, _('show only files without changes')),
5567 ('c', 'clean', None, _('show only files without changes')),
5567 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5568 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5568 ('i', 'ignored', None, _('show only ignored files')),
5569 ('i', 'ignored', None, _('show only ignored files')),
5569 ('n', 'no-status', None, _('hide status prefix')),
5570 ('n', 'no-status', None, _('hide status prefix')),
5570 ('C', 'copies', None, _('show source of copied files')),
5571 ('C', 'copies', None, _('show source of copied files')),
5571 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5572 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5572 ('', 'rev', [], _('show difference from revision'), _('REV')),
5573 ('', 'rev', [], _('show difference from revision'), _('REV')),
5573 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5574 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5574 ] + walkopts + subrepoopts + formatteropts,
5575 ] + walkopts + subrepoopts + formatteropts,
5575 _('[OPTION]... [FILE]...'),
5576 _('[OPTION]... [FILE]...'),
5576 inferrepo=True)
5577 inferrepo=True)
5577 def status(ui, repo, *pats, **opts):
5578 def status(ui, repo, *pats, **opts):
5578 """show changed files in the working directory
5579 """show changed files in the working directory
5579
5580
5580 Show status of files in the repository. If names are given, only
5581 Show status of files in the repository. If names are given, only
5581 files that match are shown. Files that are clean or ignored or
5582 files that match are shown. Files that are clean or ignored or
5582 the source of a copy/move operation, are not listed unless
5583 the source of a copy/move operation, are not listed unless
5583 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5584 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5584 Unless options described with "show only ..." are given, the
5585 Unless options described with "show only ..." are given, the
5585 options -mardu are used.
5586 options -mardu are used.
5586
5587
5587 Option -q/--quiet hides untracked (unknown and ignored) files
5588 Option -q/--quiet hides untracked (unknown and ignored) files
5588 unless explicitly requested with -u/--unknown or -i/--ignored.
5589 unless explicitly requested with -u/--unknown or -i/--ignored.
5589
5590
5590 .. note::
5591 .. note::
5591
5592
5592 status may appear to disagree with diff if permissions have
5593 status may appear to disagree with diff if permissions have
5593 changed or a merge has occurred. The standard diff format does
5594 changed or a merge has occurred. The standard diff format does
5594 not report permission changes and diff only reports changes
5595 not report permission changes and diff only reports changes
5595 relative to one merge parent.
5596 relative to one merge parent.
5596
5597
5597 If one revision is given, it is used as the base revision.
5598 If one revision is given, it is used as the base revision.
5598 If two revisions are given, the differences between them are
5599 If two revisions are given, the differences between them are
5599 shown. The --change option can also be used as a shortcut to list
5600 shown. The --change option can also be used as a shortcut to list
5600 the changed files of a revision from its first parent.
5601 the changed files of a revision from its first parent.
5601
5602
5602 The codes used to show the status of files are::
5603 The codes used to show the status of files are::
5603
5604
5604 M = modified
5605 M = modified
5605 A = added
5606 A = added
5606 R = removed
5607 R = removed
5607 C = clean
5608 C = clean
5608 ! = missing (deleted by non-hg command, but still tracked)
5609 ! = missing (deleted by non-hg command, but still tracked)
5609 ? = not tracked
5610 ? = not tracked
5610 I = ignored
5611 I = ignored
5611 = origin of the previous file (with --copies)
5612 = origin of the previous file (with --copies)
5612
5613
5613 .. container:: verbose
5614 .. container:: verbose
5614
5615
5615 Examples:
5616 Examples:
5616
5617
5617 - show changes in the working directory relative to a
5618 - show changes in the working directory relative to a
5618 changeset::
5619 changeset::
5619
5620
5620 hg status --rev 9353
5621 hg status --rev 9353
5621
5622
5622 - show all changes including copies in an existing changeset::
5623 - show all changes including copies in an existing changeset::
5623
5624
5624 hg status --copies --change 9353
5625 hg status --copies --change 9353
5625
5626
5626 - get a NUL separated list of added files, suitable for xargs::
5627 - get a NUL separated list of added files, suitable for xargs::
5627
5628
5628 hg status -an0
5629 hg status -an0
5629
5630
5630 Returns 0 on success.
5631 Returns 0 on success.
5631 """
5632 """
5632
5633
5633 revs = opts.get('rev')
5634 revs = opts.get('rev')
5634 change = opts.get('change')
5635 change = opts.get('change')
5635
5636
5636 if revs and change:
5637 if revs and change:
5637 msg = _('cannot specify --rev and --change at the same time')
5638 msg = _('cannot specify --rev and --change at the same time')
5638 raise util.Abort(msg)
5639 raise util.Abort(msg)
5639 elif change:
5640 elif change:
5640 node2 = scmutil.revsingle(repo, change, None).node()
5641 node2 = scmutil.revsingle(repo, change, None).node()
5641 node1 = repo[node2].p1().node()
5642 node1 = repo[node2].p1().node()
5642 else:
5643 else:
5643 node1, node2 = scmutil.revpair(repo, revs)
5644 node1, node2 = scmutil.revpair(repo, revs)
5644
5645
5645 cwd = (pats and repo.getcwd()) or ''
5646 cwd = (pats and repo.getcwd()) or ''
5646 end = opts.get('print0') and '\0' or '\n'
5647 end = opts.get('print0') and '\0' or '\n'
5647 copy = {}
5648 copy = {}
5648 states = 'modified added removed deleted unknown ignored clean'.split()
5649 states = 'modified added removed deleted unknown ignored clean'.split()
5649 show = [k for k in states if opts.get(k)]
5650 show = [k for k in states if opts.get(k)]
5650 if opts.get('all'):
5651 if opts.get('all'):
5651 show += ui.quiet and (states[:4] + ['clean']) or states
5652 show += ui.quiet and (states[:4] + ['clean']) or states
5652 if not show:
5653 if not show:
5653 show = ui.quiet and states[:4] or states[:5]
5654 show = ui.quiet and states[:4] or states[:5]
5654
5655
5655 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5656 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5656 'ignored' in show, 'clean' in show, 'unknown' in show,
5657 'ignored' in show, 'clean' in show, 'unknown' in show,
5657 opts.get('subrepos'))
5658 opts.get('subrepos'))
5658 changestates = zip(states, 'MAR!?IC', stat)
5659 changestates = zip(states, 'MAR!?IC', stat)
5659
5660
5660 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5661 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5661 copy = copies.pathcopies(repo[node1], repo[node2])
5662 copy = copies.pathcopies(repo[node1], repo[node2])
5662
5663
5663 fm = ui.formatter('status', opts)
5664 fm = ui.formatter('status', opts)
5664 fmt = '%s' + end
5665 fmt = '%s' + end
5665 showchar = not opts.get('no_status')
5666 showchar = not opts.get('no_status')
5666
5667
5667 for state, char, files in changestates:
5668 for state, char, files in changestates:
5668 if state in show:
5669 if state in show:
5669 label = 'status.' + state
5670 label = 'status.' + state
5670 for f in files:
5671 for f in files:
5671 fm.startitem()
5672 fm.startitem()
5672 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5673 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5673 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5674 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5674 if f in copy:
5675 if f in copy:
5675 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5676 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5676 label='status.copied')
5677 label='status.copied')
5677 fm.end()
5678 fm.end()
5678
5679
5679 @command('^summary|sum',
5680 @command('^summary|sum',
5680 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5681 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5681 def summary(ui, repo, **opts):
5682 def summary(ui, repo, **opts):
5682 """summarize working directory state
5683 """summarize working directory state
5683
5684
5684 This generates a brief summary of the working directory state,
5685 This generates a brief summary of the working directory state,
5685 including parents, branch, commit status, and available updates.
5686 including parents, branch, commit status, and available updates.
5686
5687
5687 With the --remote option, this will check the default paths for
5688 With the --remote option, this will check the default paths for
5688 incoming and outgoing changes. This can be time-consuming.
5689 incoming and outgoing changes. This can be time-consuming.
5689
5690
5690 Returns 0 on success.
5691 Returns 0 on success.
5691 """
5692 """
5692
5693
5693 ctx = repo[None]
5694 ctx = repo[None]
5694 parents = ctx.parents()
5695 parents = ctx.parents()
5695 pnode = parents[0].node()
5696 pnode = parents[0].node()
5696 marks = []
5697 marks = []
5697
5698
5698 for p in parents:
5699 for p in parents:
5699 # label with log.changeset (instead of log.parent) since this
5700 # label with log.changeset (instead of log.parent) since this
5700 # shows a working directory parent *changeset*:
5701 # shows a working directory parent *changeset*:
5701 # i18n: column positioning for "hg summary"
5702 # i18n: column positioning for "hg summary"
5702 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5703 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5703 label='log.changeset changeset.%s' % p.phasestr())
5704 label='log.changeset changeset.%s' % p.phasestr())
5704 ui.write(' '.join(p.tags()), label='log.tag')
5705 ui.write(' '.join(p.tags()), label='log.tag')
5705 if p.bookmarks():
5706 if p.bookmarks():
5706 marks.extend(p.bookmarks())
5707 marks.extend(p.bookmarks())
5707 if p.rev() == -1:
5708 if p.rev() == -1:
5708 if not len(repo):
5709 if not len(repo):
5709 ui.write(_(' (empty repository)'))
5710 ui.write(_(' (empty repository)'))
5710 else:
5711 else:
5711 ui.write(_(' (no revision checked out)'))
5712 ui.write(_(' (no revision checked out)'))
5712 ui.write('\n')
5713 ui.write('\n')
5713 if p.description():
5714 if p.description():
5714 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5715 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5715 label='log.summary')
5716 label='log.summary')
5716
5717
5717 branch = ctx.branch()
5718 branch = ctx.branch()
5718 bheads = repo.branchheads(branch)
5719 bheads = repo.branchheads(branch)
5719 # i18n: column positioning for "hg summary"
5720 # i18n: column positioning for "hg summary"
5720 m = _('branch: %s\n') % branch
5721 m = _('branch: %s\n') % branch
5721 if branch != 'default':
5722 if branch != 'default':
5722 ui.write(m, label='log.branch')
5723 ui.write(m, label='log.branch')
5723 else:
5724 else:
5724 ui.status(m, label='log.branch')
5725 ui.status(m, label='log.branch')
5725
5726
5726 if marks:
5727 if marks:
5727 current = repo._bookmarkcurrent
5728 current = repo._bookmarkcurrent
5728 # i18n: column positioning for "hg summary"
5729 # i18n: column positioning for "hg summary"
5729 ui.write(_('bookmarks:'), label='log.bookmark')
5730 ui.write(_('bookmarks:'), label='log.bookmark')
5730 if current is not None:
5731 if current is not None:
5731 if current in marks:
5732 if current in marks:
5732 ui.write(' *' + current, label='bookmarks.current')
5733 ui.write(' *' + current, label='bookmarks.current')
5733 marks.remove(current)
5734 marks.remove(current)
5734 else:
5735 else:
5735 ui.write(' [%s]' % current, label='bookmarks.current')
5736 ui.write(' [%s]' % current, label='bookmarks.current')
5736 for m in marks:
5737 for m in marks:
5737 ui.write(' ' + m, label='log.bookmark')
5738 ui.write(' ' + m, label='log.bookmark')
5738 ui.write('\n', label='log.bookmark')
5739 ui.write('\n', label='log.bookmark')
5739
5740
5740 status = repo.status(unknown=True)
5741 status = repo.status(unknown=True)
5741
5742
5742 c = repo.dirstate.copies()
5743 c = repo.dirstate.copies()
5743 copied, renamed = [], []
5744 copied, renamed = [], []
5744 for d, s in c.iteritems():
5745 for d, s in c.iteritems():
5745 if s in status.removed:
5746 if s in status.removed:
5746 status.removed.remove(s)
5747 status.removed.remove(s)
5747 renamed.append(d)
5748 renamed.append(d)
5748 else:
5749 else:
5749 copied.append(d)
5750 copied.append(d)
5750 if d in status.added:
5751 if d in status.added:
5751 status.added.remove(d)
5752 status.added.remove(d)
5752
5753
5753 ms = mergemod.mergestate(repo)
5754 ms = mergemod.mergestate(repo)
5754 unresolved = [f for f in ms if ms[f] == 'u']
5755 unresolved = [f for f in ms if ms[f] == 'u']
5755
5756
5756 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5757 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5757
5758
5758 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5759 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5759 (ui.label(_('%d added'), 'status.added'), status.added),
5760 (ui.label(_('%d added'), 'status.added'), status.added),
5760 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5761 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5761 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5762 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5762 (ui.label(_('%d copied'), 'status.copied'), copied),
5763 (ui.label(_('%d copied'), 'status.copied'), copied),
5763 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5764 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5764 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5765 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5765 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5766 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5766 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5767 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5767 t = []
5768 t = []
5768 for l, s in labels:
5769 for l, s in labels:
5769 if s:
5770 if s:
5770 t.append(l % len(s))
5771 t.append(l % len(s))
5771
5772
5772 t = ', '.join(t)
5773 t = ', '.join(t)
5773 cleanworkdir = False
5774 cleanworkdir = False
5774
5775
5775 if repo.vfs.exists('updatestate'):
5776 if repo.vfs.exists('updatestate'):
5776 t += _(' (interrupted update)')
5777 t += _(' (interrupted update)')
5777 elif len(parents) > 1:
5778 elif len(parents) > 1:
5778 t += _(' (merge)')
5779 t += _(' (merge)')
5779 elif branch != parents[0].branch():
5780 elif branch != parents[0].branch():
5780 t += _(' (new branch)')
5781 t += _(' (new branch)')
5781 elif (parents[0].closesbranch() and
5782 elif (parents[0].closesbranch() and
5782 pnode in repo.branchheads(branch, closed=True)):
5783 pnode in repo.branchheads(branch, closed=True)):
5783 t += _(' (head closed)')
5784 t += _(' (head closed)')
5784 elif not (status.modified or status.added or status.removed or renamed or
5785 elif not (status.modified or status.added or status.removed or renamed or
5785 copied or subs):
5786 copied or subs):
5786 t += _(' (clean)')
5787 t += _(' (clean)')
5787 cleanworkdir = True
5788 cleanworkdir = True
5788 elif pnode not in bheads:
5789 elif pnode not in bheads:
5789 t += _(' (new branch head)')
5790 t += _(' (new branch head)')
5790
5791
5791 if cleanworkdir:
5792 if cleanworkdir:
5792 # i18n: column positioning for "hg summary"
5793 # i18n: column positioning for "hg summary"
5793 ui.status(_('commit: %s\n') % t.strip())
5794 ui.status(_('commit: %s\n') % t.strip())
5794 else:
5795 else:
5795 # i18n: column positioning for "hg summary"
5796 # i18n: column positioning for "hg summary"
5796 ui.write(_('commit: %s\n') % t.strip())
5797 ui.write(_('commit: %s\n') % t.strip())
5797
5798
5798 # all ancestors of branch heads - all ancestors of parent = new csets
5799 # all ancestors of branch heads - all ancestors of parent = new csets
5799 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5800 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5800 bheads))
5801 bheads))
5801
5802
5802 if new == 0:
5803 if new == 0:
5803 # i18n: column positioning for "hg summary"
5804 # i18n: column positioning for "hg summary"
5804 ui.status(_('update: (current)\n'))
5805 ui.status(_('update: (current)\n'))
5805 elif pnode not in bheads:
5806 elif pnode not in bheads:
5806 # i18n: column positioning for "hg summary"
5807 # i18n: column positioning for "hg summary"
5807 ui.write(_('update: %d new changesets (update)\n') % new)
5808 ui.write(_('update: %d new changesets (update)\n') % new)
5808 else:
5809 else:
5809 # i18n: column positioning for "hg summary"
5810 # i18n: column positioning for "hg summary"
5810 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5811 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5811 (new, len(bheads)))
5812 (new, len(bheads)))
5812
5813
5813 cmdutil.summaryhooks(ui, repo)
5814 cmdutil.summaryhooks(ui, repo)
5814
5815
5815 if opts.get('remote'):
5816 if opts.get('remote'):
5816 needsincoming, needsoutgoing = True, True
5817 needsincoming, needsoutgoing = True, True
5817 else:
5818 else:
5818 needsincoming, needsoutgoing = False, False
5819 needsincoming, needsoutgoing = False, False
5819 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5820 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5820 if i:
5821 if i:
5821 needsincoming = True
5822 needsincoming = True
5822 if o:
5823 if o:
5823 needsoutgoing = True
5824 needsoutgoing = True
5824 if not needsincoming and not needsoutgoing:
5825 if not needsincoming and not needsoutgoing:
5825 return
5826 return
5826
5827
5827 def getincoming():
5828 def getincoming():
5828 source, branches = hg.parseurl(ui.expandpath('default'))
5829 source, branches = hg.parseurl(ui.expandpath('default'))
5829 sbranch = branches[0]
5830 sbranch = branches[0]
5830 try:
5831 try:
5831 other = hg.peer(repo, {}, source)
5832 other = hg.peer(repo, {}, source)
5832 except error.RepoError:
5833 except error.RepoError:
5833 if opts.get('remote'):
5834 if opts.get('remote'):
5834 raise
5835 raise
5835 return source, sbranch, None, None, None
5836 return source, sbranch, None, None, None
5836 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5837 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5837 if revs:
5838 if revs:
5838 revs = [other.lookup(rev) for rev in revs]
5839 revs = [other.lookup(rev) for rev in revs]
5839 ui.debug('comparing with %s\n' % util.hidepassword(source))
5840 ui.debug('comparing with %s\n' % util.hidepassword(source))
5840 repo.ui.pushbuffer()
5841 repo.ui.pushbuffer()
5841 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5842 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5842 repo.ui.popbuffer()
5843 repo.ui.popbuffer()
5843 return source, sbranch, other, commoninc, commoninc[1]
5844 return source, sbranch, other, commoninc, commoninc[1]
5844
5845
5845 if needsincoming:
5846 if needsincoming:
5846 source, sbranch, sother, commoninc, incoming = getincoming()
5847 source, sbranch, sother, commoninc, incoming = getincoming()
5847 else:
5848 else:
5848 source = sbranch = sother = commoninc = incoming = None
5849 source = sbranch = sother = commoninc = incoming = None
5849
5850
5850 def getoutgoing():
5851 def getoutgoing():
5851 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5852 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5852 dbranch = branches[0]
5853 dbranch = branches[0]
5853 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5854 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5854 if source != dest:
5855 if source != dest:
5855 try:
5856 try:
5856 dother = hg.peer(repo, {}, dest)
5857 dother = hg.peer(repo, {}, dest)
5857 except error.RepoError:
5858 except error.RepoError:
5858 if opts.get('remote'):
5859 if opts.get('remote'):
5859 raise
5860 raise
5860 return dest, dbranch, None, None
5861 return dest, dbranch, None, None
5861 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5862 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5862 elif sother is None:
5863 elif sother is None:
5863 # there is no explicit destination peer, but source one is invalid
5864 # there is no explicit destination peer, but source one is invalid
5864 return dest, dbranch, None, None
5865 return dest, dbranch, None, None
5865 else:
5866 else:
5866 dother = sother
5867 dother = sother
5867 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5868 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5868 common = None
5869 common = None
5869 else:
5870 else:
5870 common = commoninc
5871 common = commoninc
5871 if revs:
5872 if revs:
5872 revs = [repo.lookup(rev) for rev in revs]
5873 revs = [repo.lookup(rev) for rev in revs]
5873 repo.ui.pushbuffer()
5874 repo.ui.pushbuffer()
5874 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5875 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5875 commoninc=common)
5876 commoninc=common)
5876 repo.ui.popbuffer()
5877 repo.ui.popbuffer()
5877 return dest, dbranch, dother, outgoing
5878 return dest, dbranch, dother, outgoing
5878
5879
5879 if needsoutgoing:
5880 if needsoutgoing:
5880 dest, dbranch, dother, outgoing = getoutgoing()
5881 dest, dbranch, dother, outgoing = getoutgoing()
5881 else:
5882 else:
5882 dest = dbranch = dother = outgoing = None
5883 dest = dbranch = dother = outgoing = None
5883
5884
5884 if opts.get('remote'):
5885 if opts.get('remote'):
5885 t = []
5886 t = []
5886 if incoming:
5887 if incoming:
5887 t.append(_('1 or more incoming'))
5888 t.append(_('1 or more incoming'))
5888 o = outgoing.missing
5889 o = outgoing.missing
5889 if o:
5890 if o:
5890 t.append(_('%d outgoing') % len(o))
5891 t.append(_('%d outgoing') % len(o))
5891 other = dother or sother
5892 other = dother or sother
5892 if 'bookmarks' in other.listkeys('namespaces'):
5893 if 'bookmarks' in other.listkeys('namespaces'):
5893 lmarks = repo.listkeys('bookmarks')
5894 lmarks = repo.listkeys('bookmarks')
5894 rmarks = other.listkeys('bookmarks')
5895 rmarks = other.listkeys('bookmarks')
5895 diff = set(rmarks) - set(lmarks)
5896 diff = set(rmarks) - set(lmarks)
5896 if len(diff) > 0:
5897 if len(diff) > 0:
5897 t.append(_('%d incoming bookmarks') % len(diff))
5898 t.append(_('%d incoming bookmarks') % len(diff))
5898 diff = set(lmarks) - set(rmarks)
5899 diff = set(lmarks) - set(rmarks)
5899 if len(diff) > 0:
5900 if len(diff) > 0:
5900 t.append(_('%d outgoing bookmarks') % len(diff))
5901 t.append(_('%d outgoing bookmarks') % len(diff))
5901
5902
5902 if t:
5903 if t:
5903 # i18n: column positioning for "hg summary"
5904 # i18n: column positioning for "hg summary"
5904 ui.write(_('remote: %s\n') % (', '.join(t)))
5905 ui.write(_('remote: %s\n') % (', '.join(t)))
5905 else:
5906 else:
5906 # i18n: column positioning for "hg summary"
5907 # i18n: column positioning for "hg summary"
5907 ui.status(_('remote: (synced)\n'))
5908 ui.status(_('remote: (synced)\n'))
5908
5909
5909 cmdutil.summaryremotehooks(ui, repo, opts,
5910 cmdutil.summaryremotehooks(ui, repo, opts,
5910 ((source, sbranch, sother, commoninc),
5911 ((source, sbranch, sother, commoninc),
5911 (dest, dbranch, dother, outgoing)))
5912 (dest, dbranch, dother, outgoing)))
5912
5913
5913 @command('tag',
5914 @command('tag',
5914 [('f', 'force', None, _('force tag')),
5915 [('f', 'force', None, _('force tag')),
5915 ('l', 'local', None, _('make the tag local')),
5916 ('l', 'local', None, _('make the tag local')),
5916 ('r', 'rev', '', _('revision to tag'), _('REV')),
5917 ('r', 'rev', '', _('revision to tag'), _('REV')),
5917 ('', 'remove', None, _('remove a tag')),
5918 ('', 'remove', None, _('remove a tag')),
5918 # -l/--local is already there, commitopts cannot be used
5919 # -l/--local is already there, commitopts cannot be used
5919 ('e', 'edit', None, _('invoke editor on commit messages')),
5920 ('e', 'edit', None, _('invoke editor on commit messages')),
5920 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5921 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5921 ] + commitopts2,
5922 ] + commitopts2,
5922 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5923 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5923 def tag(ui, repo, name1, *names, **opts):
5924 def tag(ui, repo, name1, *names, **opts):
5924 """add one or more tags for the current or given revision
5925 """add one or more tags for the current or given revision
5925
5926
5926 Name a particular revision using <name>.
5927 Name a particular revision using <name>.
5927
5928
5928 Tags are used to name particular revisions of the repository and are
5929 Tags are used to name particular revisions of the repository and are
5929 very useful to compare different revisions, to go back to significant
5930 very useful to compare different revisions, to go back to significant
5930 earlier versions or to mark branch points as releases, etc. Changing
5931 earlier versions or to mark branch points as releases, etc. Changing
5931 an existing tag is normally disallowed; use -f/--force to override.
5932 an existing tag is normally disallowed; use -f/--force to override.
5932
5933
5933 If no revision is given, the parent of the working directory is
5934 If no revision is given, the parent of the working directory is
5934 used.
5935 used.
5935
5936
5936 To facilitate version control, distribution, and merging of tags,
5937 To facilitate version control, distribution, and merging of tags,
5937 they are stored as a file named ".hgtags" which is managed similarly
5938 they are stored as a file named ".hgtags" which is managed similarly
5938 to other project files and can be hand-edited if necessary. This
5939 to other project files and can be hand-edited if necessary. This
5939 also means that tagging creates a new commit. The file
5940 also means that tagging creates a new commit. The file
5940 ".hg/localtags" is used for local tags (not shared among
5941 ".hg/localtags" is used for local tags (not shared among
5941 repositories).
5942 repositories).
5942
5943
5943 Tag commits are usually made at the head of a branch. If the parent
5944 Tag commits are usually made at the head of a branch. If the parent
5944 of the working directory is not a branch head, :hg:`tag` aborts; use
5945 of the working directory is not a branch head, :hg:`tag` aborts; use
5945 -f/--force to force the tag commit to be based on a non-head
5946 -f/--force to force the tag commit to be based on a non-head
5946 changeset.
5947 changeset.
5947
5948
5948 See :hg:`help dates` for a list of formats valid for -d/--date.
5949 See :hg:`help dates` for a list of formats valid for -d/--date.
5949
5950
5950 Since tag names have priority over branch names during revision
5951 Since tag names have priority over branch names during revision
5951 lookup, using an existing branch name as a tag name is discouraged.
5952 lookup, using an existing branch name as a tag name is discouraged.
5952
5953
5953 Returns 0 on success.
5954 Returns 0 on success.
5954 """
5955 """
5955 wlock = lock = None
5956 wlock = lock = None
5956 try:
5957 try:
5957 wlock = repo.wlock()
5958 wlock = repo.wlock()
5958 lock = repo.lock()
5959 lock = repo.lock()
5959 rev_ = "."
5960 rev_ = "."
5960 names = [t.strip() for t in (name1,) + names]
5961 names = [t.strip() for t in (name1,) + names]
5961 if len(names) != len(set(names)):
5962 if len(names) != len(set(names)):
5962 raise util.Abort(_('tag names must be unique'))
5963 raise util.Abort(_('tag names must be unique'))
5963 for n in names:
5964 for n in names:
5964 scmutil.checknewlabel(repo, n, 'tag')
5965 scmutil.checknewlabel(repo, n, 'tag')
5965 if not n:
5966 if not n:
5966 raise util.Abort(_('tag names cannot consist entirely of '
5967 raise util.Abort(_('tag names cannot consist entirely of '
5967 'whitespace'))
5968 'whitespace'))
5968 if opts.get('rev') and opts.get('remove'):
5969 if opts.get('rev') and opts.get('remove'):
5969 raise util.Abort(_("--rev and --remove are incompatible"))
5970 raise util.Abort(_("--rev and --remove are incompatible"))
5970 if opts.get('rev'):
5971 if opts.get('rev'):
5971 rev_ = opts['rev']
5972 rev_ = opts['rev']
5972 message = opts.get('message')
5973 message = opts.get('message')
5973 if opts.get('remove'):
5974 if opts.get('remove'):
5974 expectedtype = opts.get('local') and 'local' or 'global'
5975 expectedtype = opts.get('local') and 'local' or 'global'
5975 for n in names:
5976 for n in names:
5976 if not repo.tagtype(n):
5977 if not repo.tagtype(n):
5977 raise util.Abort(_("tag '%s' does not exist") % n)
5978 raise util.Abort(_("tag '%s' does not exist") % n)
5978 if repo.tagtype(n) != expectedtype:
5979 if repo.tagtype(n) != expectedtype:
5979 if expectedtype == 'global':
5980 if expectedtype == 'global':
5980 raise util.Abort(_("tag '%s' is not a global tag") % n)
5981 raise util.Abort(_("tag '%s' is not a global tag") % n)
5981 else:
5982 else:
5982 raise util.Abort(_("tag '%s' is not a local tag") % n)
5983 raise util.Abort(_("tag '%s' is not a local tag") % n)
5983 rev_ = nullid
5984 rev_ = nullid
5984 if not message:
5985 if not message:
5985 # we don't translate commit messages
5986 # we don't translate commit messages
5986 message = 'Removed tag %s' % ', '.join(names)
5987 message = 'Removed tag %s' % ', '.join(names)
5987 elif not opts.get('force'):
5988 elif not opts.get('force'):
5988 for n in names:
5989 for n in names:
5989 if n in repo.tags():
5990 if n in repo.tags():
5990 raise util.Abort(_("tag '%s' already exists "
5991 raise util.Abort(_("tag '%s' already exists "
5991 "(use -f to force)") % n)
5992 "(use -f to force)") % n)
5992 if not opts.get('local'):
5993 if not opts.get('local'):
5993 p1, p2 = repo.dirstate.parents()
5994 p1, p2 = repo.dirstate.parents()
5994 if p2 != nullid:
5995 if p2 != nullid:
5995 raise util.Abort(_('uncommitted merge'))
5996 raise util.Abort(_('uncommitted merge'))
5996 bheads = repo.branchheads()
5997 bheads = repo.branchheads()
5997 if not opts.get('force') and bheads and p1 not in bheads:
5998 if not opts.get('force') and bheads and p1 not in bheads:
5998 raise util.Abort(_('not at a branch head (use -f to force)'))
5999 raise util.Abort(_('not at a branch head (use -f to force)'))
5999 r = scmutil.revsingle(repo, rev_).node()
6000 r = scmutil.revsingle(repo, rev_).node()
6000
6001
6001 if not message:
6002 if not message:
6002 # we don't translate commit messages
6003 # we don't translate commit messages
6003 message = ('Added tag %s for changeset %s' %
6004 message = ('Added tag %s for changeset %s' %
6004 (', '.join(names), short(r)))
6005 (', '.join(names), short(r)))
6005
6006
6006 date = opts.get('date')
6007 date = opts.get('date')
6007 if date:
6008 if date:
6008 date = util.parsedate(date)
6009 date = util.parsedate(date)
6009
6010
6010 if opts.get('remove'):
6011 if opts.get('remove'):
6011 editform = 'tag.remove'
6012 editform = 'tag.remove'
6012 else:
6013 else:
6013 editform = 'tag.add'
6014 editform = 'tag.add'
6014 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6015 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6015
6016
6016 # don't allow tagging the null rev
6017 # don't allow tagging the null rev
6017 if (not opts.get('remove') and
6018 if (not opts.get('remove') and
6018 scmutil.revsingle(repo, rev_).rev() == nullrev):
6019 scmutil.revsingle(repo, rev_).rev() == nullrev):
6019 raise util.Abort(_("cannot tag null revision"))
6020 raise util.Abort(_("cannot tag null revision"))
6020
6021
6021 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6022 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6022 editor=editor)
6023 editor=editor)
6023 finally:
6024 finally:
6024 release(lock, wlock)
6025 release(lock, wlock)
6025
6026
6026 @command('tags', formatteropts, '')
6027 @command('tags', formatteropts, '')
6027 def tags(ui, repo, **opts):
6028 def tags(ui, repo, **opts):
6028 """list repository tags
6029 """list repository tags
6029
6030
6030 This lists both regular and local tags. When the -v/--verbose
6031 This lists both regular and local tags. When the -v/--verbose
6031 switch is used, a third column "local" is printed for local tags.
6032 switch is used, a third column "local" is printed for local tags.
6032
6033
6033 Returns 0 on success.
6034 Returns 0 on success.
6034 """
6035 """
6035
6036
6036 fm = ui.formatter('tags', opts)
6037 fm = ui.formatter('tags', opts)
6037 hexfunc = fm.hexfunc
6038 hexfunc = fm.hexfunc
6038 tagtype = ""
6039 tagtype = ""
6039
6040
6040 for t, n in reversed(repo.tagslist()):
6041 for t, n in reversed(repo.tagslist()):
6041 hn = hexfunc(n)
6042 hn = hexfunc(n)
6042 label = 'tags.normal'
6043 label = 'tags.normal'
6043 tagtype = ''
6044 tagtype = ''
6044 if repo.tagtype(t) == 'local':
6045 if repo.tagtype(t) == 'local':
6045 label = 'tags.local'
6046 label = 'tags.local'
6046 tagtype = 'local'
6047 tagtype = 'local'
6047
6048
6048 fm.startitem()
6049 fm.startitem()
6049 fm.write('tag', '%s', t, label=label)
6050 fm.write('tag', '%s', t, label=label)
6050 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6051 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6051 fm.condwrite(not ui.quiet, 'rev node', fmt,
6052 fm.condwrite(not ui.quiet, 'rev node', fmt,
6052 repo.changelog.rev(n), hn, label=label)
6053 repo.changelog.rev(n), hn, label=label)
6053 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6054 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6054 tagtype, label=label)
6055 tagtype, label=label)
6055 fm.plain('\n')
6056 fm.plain('\n')
6056 fm.end()
6057 fm.end()
6057
6058
6058 @command('tip',
6059 @command('tip',
6059 [('p', 'patch', None, _('show patch')),
6060 [('p', 'patch', None, _('show patch')),
6060 ('g', 'git', None, _('use git extended diff format')),
6061 ('g', 'git', None, _('use git extended diff format')),
6061 ] + templateopts,
6062 ] + templateopts,
6062 _('[-p] [-g]'))
6063 _('[-p] [-g]'))
6063 def tip(ui, repo, **opts):
6064 def tip(ui, repo, **opts):
6064 """show the tip revision (DEPRECATED)
6065 """show the tip revision (DEPRECATED)
6065
6066
6066 The tip revision (usually just called the tip) is the changeset
6067 The tip revision (usually just called the tip) is the changeset
6067 most recently added to the repository (and therefore the most
6068 most recently added to the repository (and therefore the most
6068 recently changed head).
6069 recently changed head).
6069
6070
6070 If you have just made a commit, that commit will be the tip. If
6071 If you have just made a commit, that commit will be the tip. If
6071 you have just pulled changes from another repository, the tip of
6072 you have just pulled changes from another repository, the tip of
6072 that repository becomes the current tip. The "tip" tag is special
6073 that repository becomes the current tip. The "tip" tag is special
6073 and cannot be renamed or assigned to a different changeset.
6074 and cannot be renamed or assigned to a different changeset.
6074
6075
6075 This command is deprecated, please use :hg:`heads` instead.
6076 This command is deprecated, please use :hg:`heads` instead.
6076
6077
6077 Returns 0 on success.
6078 Returns 0 on success.
6078 """
6079 """
6079 displayer = cmdutil.show_changeset(ui, repo, opts)
6080 displayer = cmdutil.show_changeset(ui, repo, opts)
6080 displayer.show(repo['tip'])
6081 displayer.show(repo['tip'])
6081 displayer.close()
6082 displayer.close()
6082
6083
6083 @command('unbundle',
6084 @command('unbundle',
6084 [('u', 'update', None,
6085 [('u', 'update', None,
6085 _('update to new branch head if changesets were unbundled'))],
6086 _('update to new branch head if changesets were unbundled'))],
6086 _('[-u] FILE...'))
6087 _('[-u] FILE...'))
6087 def unbundle(ui, repo, fname1, *fnames, **opts):
6088 def unbundle(ui, repo, fname1, *fnames, **opts):
6088 """apply one or more changegroup files
6089 """apply one or more changegroup files
6089
6090
6090 Apply one or more compressed changegroup files generated by the
6091 Apply one or more compressed changegroup files generated by the
6091 bundle command.
6092 bundle command.
6092
6093
6093 Returns 0 on success, 1 if an update has unresolved files.
6094 Returns 0 on success, 1 if an update has unresolved files.
6094 """
6095 """
6095 fnames = (fname1,) + fnames
6096 fnames = (fname1,) + fnames
6096
6097
6097 lock = repo.lock()
6098 lock = repo.lock()
6098 try:
6099 try:
6099 for fname in fnames:
6100 for fname in fnames:
6100 f = hg.openpath(ui, fname)
6101 f = hg.openpath(ui, fname)
6101 gen = exchange.readbundle(ui, f, fname)
6102 gen = exchange.readbundle(ui, f, fname)
6102 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6103 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6103 'bundle:' + fname)
6104 'bundle:' + fname)
6104 finally:
6105 finally:
6105 lock.release()
6106 lock.release()
6106
6107
6107 return postincoming(ui, repo, modheads, opts.get('update'), None)
6108 return postincoming(ui, repo, modheads, opts.get('update'), None)
6108
6109
6109 @command('^update|up|checkout|co',
6110 @command('^update|up|checkout|co',
6110 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6111 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6111 ('c', 'check', None,
6112 ('c', 'check', None,
6112 _('update across branches if no uncommitted changes')),
6113 _('update across branches if no uncommitted changes')),
6113 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6114 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6114 ('r', 'rev', '', _('revision'), _('REV'))
6115 ('r', 'rev', '', _('revision'), _('REV'))
6115 ] + mergetoolopts,
6116 ] + mergetoolopts,
6116 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6117 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6117 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6118 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6118 tool=None):
6119 tool=None):
6119 """update working directory (or switch revisions)
6120 """update working directory (or switch revisions)
6120
6121
6121 Update the repository's working directory to the specified
6122 Update the repository's working directory to the specified
6122 changeset. If no changeset is specified, update to the tip of the
6123 changeset. If no changeset is specified, update to the tip of the
6123 current named branch and move the current bookmark (see :hg:`help
6124 current named branch and move the current bookmark (see :hg:`help
6124 bookmarks`).
6125 bookmarks`).
6125
6126
6126 Update sets the working directory's parent revision to the specified
6127 Update sets the working directory's parent revision to the specified
6127 changeset (see :hg:`help parents`).
6128 changeset (see :hg:`help parents`).
6128
6129
6129 If the changeset is not a descendant or ancestor of the working
6130 If the changeset is not a descendant or ancestor of the working
6130 directory's parent, the update is aborted. With the -c/--check
6131 directory's parent, the update is aborted. With the -c/--check
6131 option, the working directory is checked for uncommitted changes; if
6132 option, the working directory is checked for uncommitted changes; if
6132 none are found, the working directory is updated to the specified
6133 none are found, the working directory is updated to the specified
6133 changeset.
6134 changeset.
6134
6135
6135 .. container:: verbose
6136 .. container:: verbose
6136
6137
6137 The following rules apply when the working directory contains
6138 The following rules apply when the working directory contains
6138 uncommitted changes:
6139 uncommitted changes:
6139
6140
6140 1. If neither -c/--check nor -C/--clean is specified, and if
6141 1. If neither -c/--check nor -C/--clean is specified, and if
6141 the requested changeset is an ancestor or descendant of
6142 the requested changeset is an ancestor or descendant of
6142 the working directory's parent, the uncommitted changes
6143 the working directory's parent, the uncommitted changes
6143 are merged into the requested changeset and the merged
6144 are merged into the requested changeset and the merged
6144 result is left uncommitted. If the requested changeset is
6145 result is left uncommitted. If the requested changeset is
6145 not an ancestor or descendant (that is, it is on another
6146 not an ancestor or descendant (that is, it is on another
6146 branch), the update is aborted and the uncommitted changes
6147 branch), the update is aborted and the uncommitted changes
6147 are preserved.
6148 are preserved.
6148
6149
6149 2. With the -c/--check option, the update is aborted and the
6150 2. With the -c/--check option, the update is aborted and the
6150 uncommitted changes are preserved.
6151 uncommitted changes are preserved.
6151
6152
6152 3. With the -C/--clean option, uncommitted changes are discarded and
6153 3. With the -C/--clean option, uncommitted changes are discarded and
6153 the working directory is updated to the requested changeset.
6154 the working directory is updated to the requested changeset.
6154
6155
6155 To cancel an uncommitted merge (and lose your changes), use
6156 To cancel an uncommitted merge (and lose your changes), use
6156 :hg:`update --clean .`.
6157 :hg:`update --clean .`.
6157
6158
6158 Use null as the changeset to remove the working directory (like
6159 Use null as the changeset to remove the working directory (like
6159 :hg:`clone -U`).
6160 :hg:`clone -U`).
6160
6161
6161 If you want to revert just one file to an older revision, use
6162 If you want to revert just one file to an older revision, use
6162 :hg:`revert [-r REV] NAME`.
6163 :hg:`revert [-r REV] NAME`.
6163
6164
6164 See :hg:`help dates` for a list of formats valid for -d/--date.
6165 See :hg:`help dates` for a list of formats valid for -d/--date.
6165
6166
6166 Returns 0 on success, 1 if there are unresolved files.
6167 Returns 0 on success, 1 if there are unresolved files.
6167 """
6168 """
6168 if rev and node:
6169 if rev and node:
6169 raise util.Abort(_("please specify just one revision"))
6170 raise util.Abort(_("please specify just one revision"))
6170
6171
6171 if rev is None or rev == '':
6172 if rev is None or rev == '':
6172 rev = node
6173 rev = node
6173
6174
6174 cmdutil.clearunfinished(repo)
6175 cmdutil.clearunfinished(repo)
6175
6176
6176 # with no argument, we also move the current bookmark, if any
6177 # with no argument, we also move the current bookmark, if any
6177 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6178 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6178
6179
6179 # if we defined a bookmark, we have to remember the original bookmark name
6180 # if we defined a bookmark, we have to remember the original bookmark name
6180 brev = rev
6181 brev = rev
6181 rev = scmutil.revsingle(repo, rev, rev).rev()
6182 rev = scmutil.revsingle(repo, rev, rev).rev()
6182
6183
6183 if check and clean:
6184 if check and clean:
6184 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6185 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6185
6186
6186 if date:
6187 if date:
6187 if rev is not None:
6188 if rev is not None:
6188 raise util.Abort(_("you can't specify a revision and a date"))
6189 raise util.Abort(_("you can't specify a revision and a date"))
6189 rev = cmdutil.finddate(ui, repo, date)
6190 rev = cmdutil.finddate(ui, repo, date)
6190
6191
6191 if check:
6192 if check:
6192 c = repo[None]
6193 c = repo[None]
6193 if c.dirty(merge=False, branch=False, missing=True):
6194 if c.dirty(merge=False, branch=False, missing=True):
6194 raise util.Abort(_("uncommitted changes"))
6195 raise util.Abort(_("uncommitted changes"))
6195 if rev is None:
6196 if rev is None:
6196 rev = repo[repo[None].branch()].rev()
6197 rev = repo[repo[None].branch()].rev()
6197
6198
6198 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6199 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6199
6200
6200 if clean:
6201 if clean:
6201 ret = hg.clean(repo, rev)
6202 ret = hg.clean(repo, rev)
6202 else:
6203 else:
6203 ret = hg.update(repo, rev)
6204 ret = hg.update(repo, rev)
6204
6205
6205 if not ret and movemarkfrom:
6206 if not ret and movemarkfrom:
6206 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6207 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6207 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6208 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6208 elif brev in repo._bookmarks:
6209 elif brev in repo._bookmarks:
6209 bookmarks.setcurrent(repo, brev)
6210 bookmarks.setcurrent(repo, brev)
6210 ui.status(_("(activating bookmark %s)\n") % brev)
6211 ui.status(_("(activating bookmark %s)\n") % brev)
6211 elif brev:
6212 elif brev:
6212 if repo._bookmarkcurrent:
6213 if repo._bookmarkcurrent:
6213 ui.status(_("(leaving bookmark %s)\n") %
6214 ui.status(_("(leaving bookmark %s)\n") %
6214 repo._bookmarkcurrent)
6215 repo._bookmarkcurrent)
6215 bookmarks.unsetcurrent(repo)
6216 bookmarks.unsetcurrent(repo)
6216
6217
6217 return ret
6218 return ret
6218
6219
6219 @command('verify', [])
6220 @command('verify', [])
6220 def verify(ui, repo):
6221 def verify(ui, repo):
6221 """verify the integrity of the repository
6222 """verify the integrity of the repository
6222
6223
6223 Verify the integrity of the current repository.
6224 Verify the integrity of the current repository.
6224
6225
6225 This will perform an extensive check of the repository's
6226 This will perform an extensive check of the repository's
6226 integrity, validating the hashes and checksums of each entry in
6227 integrity, validating the hashes and checksums of each entry in
6227 the changelog, manifest, and tracked files, as well as the
6228 the changelog, manifest, and tracked files, as well as the
6228 integrity of their crosslinks and indices.
6229 integrity of their crosslinks and indices.
6229
6230
6230 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6231 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6231 for more information about recovery from corruption of the
6232 for more information about recovery from corruption of the
6232 repository.
6233 repository.
6233
6234
6234 Returns 0 on success, 1 if errors are encountered.
6235 Returns 0 on success, 1 if errors are encountered.
6235 """
6236 """
6236 return hg.verify(repo)
6237 return hg.verify(repo)
6237
6238
6238 @command('version', [], norepo=True)
6239 @command('version', [], norepo=True)
6239 def version_(ui):
6240 def version_(ui):
6240 """output version and copyright information"""
6241 """output version and copyright information"""
6241 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6242 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6242 % util.version())
6243 % util.version())
6243 ui.status(_(
6244 ui.status(_(
6244 "(see http://mercurial.selenic.com for more information)\n"
6245 "(see http://mercurial.selenic.com for more information)\n"
6245 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6246 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6246 "This is free software; see the source for copying conditions. "
6247 "This is free software; see the source for copying conditions. "
6247 "There is NO\nwarranty; "
6248 "There is NO\nwarranty; "
6248 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6249 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6249 ))
6250 ))
6250
6251
6251 ui.note(_("\nEnabled extensions:\n\n"))
6252 ui.note(_("\nEnabled extensions:\n\n"))
6252 if ui.verbose:
6253 if ui.verbose:
6253 # format names and versions into columns
6254 # format names and versions into columns
6254 names = []
6255 names = []
6255 vers = []
6256 vers = []
6256 for name, module in extensions.extensions():
6257 for name, module in extensions.extensions():
6257 names.append(name)
6258 names.append(name)
6258 vers.append(extensions.moduleversion(module))
6259 vers.append(extensions.moduleversion(module))
6259 if names:
6260 if names:
6260 maxnamelen = max(len(n) for n in names)
6261 maxnamelen = max(len(n) for n in names)
6261 for i, name in enumerate(names):
6262 for i, name in enumerate(names):
6262 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6263 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,720 +1,721
1 Create a repo with some stuff in it:
1 Create a repo with some stuff in it:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ echo a > d
6 $ echo a > d
7 $ echo a > e
7 $ echo a > e
8 $ hg ci -qAm0
8 $ hg ci -qAm0
9 $ echo b > a
9 $ echo b > a
10 $ hg ci -m1 -u bar
10 $ hg ci -m1 -u bar
11 $ hg mv a b
11 $ hg mv a b
12 $ hg ci -m2
12 $ hg ci -m2
13 $ hg cp b c
13 $ hg cp b c
14 $ hg ci -m3 -u baz
14 $ hg ci -m3 -u baz
15 $ echo b > d
15 $ echo b > d
16 $ echo f > e
16 $ echo f > e
17 $ hg ci -m4
17 $ hg ci -m4
18 $ hg up -q 3
18 $ hg up -q 3
19 $ echo b > e
19 $ echo b > e
20 $ hg branch -q stable
20 $ hg branch -q stable
21 $ hg ci -m5
21 $ hg ci -m5
22 $ hg merge -q default --tool internal:local
22 $ hg merge -q default --tool internal:local
23 $ hg branch -q default
23 $ hg branch -q default
24 $ hg ci -m6
24 $ hg ci -m6
25 $ hg phase --public 3
25 $ hg phase --public 3
26 $ hg phase --force --secret 6
26 $ hg phase --force --secret 6
27
27
28 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
28 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
29 @ test@6.secret: 6
29 @ test@6.secret: 6
30 |\
30 |\
31 | o test@5.draft: 5
31 | o test@5.draft: 5
32 | |
32 | |
33 o | test@4.draft: 4
33 o | test@4.draft: 4
34 |/
34 |/
35 o baz@3.public: 3
35 o baz@3.public: 3
36 |
36 |
37 o test@2.public: 2
37 o test@2.public: 2
38 |
38 |
39 o bar@1.public: 1
39 o bar@1.public: 1
40 |
40 |
41 o test@0.public: 0
41 o test@0.public: 0
42
42
43
43
44 Need to specify a rev:
44 Need to specify a rev:
45
45
46 $ hg graft
46 $ hg graft
47 abort: no revisions specified
47 abort: no revisions specified
48 [255]
48 [255]
49
49
50 Can't graft ancestor:
50 Can't graft ancestor:
51
51
52 $ hg graft 1 2
52 $ hg graft 1 2
53 skipping ancestor revision 1:5d205f8b35b6
53 skipping ancestor revision 1:5d205f8b35b6
54 skipping ancestor revision 2:5c095ad7e90f
54 skipping ancestor revision 2:5c095ad7e90f
55 [255]
55 [255]
56
56
57 Specify revisions with -r:
57 Specify revisions with -r:
58
58
59 $ hg graft -r 1 -r 2
59 $ hg graft -r 1 -r 2
60 skipping ancestor revision 1:5d205f8b35b6
60 skipping ancestor revision 1:5d205f8b35b6
61 skipping ancestor revision 2:5c095ad7e90f
61 skipping ancestor revision 2:5c095ad7e90f
62 [255]
62 [255]
63
63
64 $ hg graft -r 1 2
64 $ hg graft -r 1 2
65 skipping ancestor revision 2:5c095ad7e90f
65 skipping ancestor revision 2:5c095ad7e90f
66 skipping ancestor revision 1:5d205f8b35b6
66 skipping ancestor revision 1:5d205f8b35b6
67 [255]
67 [255]
68
68
69 Can't graft with dirty wd:
69 Can't graft with dirty wd:
70
70
71 $ hg up -q 0
71 $ hg up -q 0
72 $ echo foo > a
72 $ echo foo > a
73 $ hg graft 1
73 $ hg graft 1
74 abort: uncommitted changes
74 abort: uncommitted changes
75 [255]
75 [255]
76 $ hg revert a
76 $ hg revert a
77
77
78 Graft a rename:
78 Graft a rename:
79 (this also tests that editor is invoked if '--edit' is specified)
79 (this also tests that editor is invoked if '--edit' is specified)
80
80
81 $ hg status --rev "2^1" --rev 2
81 $ hg status --rev "2^1" --rev 2
82 A b
82 A b
83 R a
83 R a
84 $ HGEDITOR=cat hg graft 2 -u foo --edit
84 $ HGEDITOR=cat hg graft 2 -u foo --edit
85 grafting 2:5c095ad7e90f "2"
85 grafting 2:5c095ad7e90f "2"
86 merging a and b to b
86 merging a and b to b
87 2
87 2
88
88
89
89
90 HG: Enter commit message. Lines beginning with 'HG:' are removed.
90 HG: Enter commit message. Lines beginning with 'HG:' are removed.
91 HG: Leave message empty to abort commit.
91 HG: Leave message empty to abort commit.
92 HG: --
92 HG: --
93 HG: user: foo
93 HG: user: foo
94 HG: branch 'default'
94 HG: branch 'default'
95 HG: added b
95 HG: added b
96 HG: removed a
96 HG: removed a
97 $ hg export tip --git
97 $ hg export tip --git
98 # HG changeset patch
98 # HG changeset patch
99 # User foo
99 # User foo
100 # Date 0 0
100 # Date 0 0
101 # Thu Jan 01 00:00:00 1970 +0000
101 # Thu Jan 01 00:00:00 1970 +0000
102 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
102 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
103 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
103 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
104 2
104 2
105
105
106 diff --git a/a b/b
106 diff --git a/a b/b
107 rename from a
107 rename from a
108 rename to b
108 rename to b
109
109
110 Look for extra:source
110 Look for extra:source
111
111
112 $ hg log --debug -r tip
112 $ hg log --debug -r tip
113 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
113 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
114 tag: tip
114 tag: tip
115 phase: draft
115 phase: draft
116 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
116 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
117 parent: -1:0000000000000000000000000000000000000000
117 parent: -1:0000000000000000000000000000000000000000
118 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
118 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
119 user: foo
119 user: foo
120 date: Thu Jan 01 00:00:00 1970 +0000
120 date: Thu Jan 01 00:00:00 1970 +0000
121 files+: b
121 files+: b
122 files-: a
122 files-: a
123 extra: branch=default
123 extra: branch=default
124 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
124 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
125 description:
125 description:
126 2
126 2
127
127
128
128
129
129
130 Graft out of order, skipping a merge and a duplicate
130 Graft out of order, skipping a merge and a duplicate
131 (this also tests that editor is not invoked if '--edit' is not specified)
131 (this also tests that editor is not invoked if '--edit' is not specified)
132
132
133 $ hg graft 1 5 4 3 'merge()' 2 -n
133 $ hg graft 1 5 4 3 'merge()' 2 -n
134 skipping ungraftable merge revision 6
134 skipping ungraftable merge revision 6
135 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
135 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
136 grafting 1:5d205f8b35b6 "1"
136 grafting 1:5d205f8b35b6 "1"
137 grafting 5:97f8bfe72746 "5"
137 grafting 5:97f8bfe72746 "5"
138 grafting 4:9c233e8e184d "4"
138 grafting 4:9c233e8e184d "4"
139 grafting 3:4c60f11aa304 "3"
139 grafting 3:4c60f11aa304 "3"
140
140
141 $ HGEDITOR=cat hg graft 1 5 4 3 'merge()' 2 --debug
141 $ HGEDITOR=cat hg graft 1 5 4 3 'merge()' 2 --debug
142 skipping ungraftable merge revision 6
142 skipping ungraftable merge revision 6
143 scanning for duplicate grafts
143 scanning for duplicate grafts
144 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
144 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
145 grafting 1:5d205f8b35b6 "1"
145 grafting 1:5d205f8b35b6 "1"
146 searching for copies back to rev 1
146 searching for copies back to rev 1
147 unmatched files in local:
147 unmatched files in local:
148 b
148 b
149 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
149 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
150 src: 'a' -> dst: 'b' *
150 src: 'a' -> dst: 'b' *
151 checking for directory renames
151 checking for directory renames
152 resolving manifests
152 resolving manifests
153 branchmerge: True, force: True, partial: False
153 branchmerge: True, force: True, partial: False
154 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
154 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
155 preserving b for resolve of b
155 preserving b for resolve of b
156 b: local copied/moved from a -> m
156 b: local copied/moved from a -> m
157 updating: b 1/1 files (100.00%)
157 updating: b 1/1 files (100.00%)
158 picked tool 'internal:merge' for b (binary False symlink False)
158 picked tool 'internal:merge' for b (binary False symlink False)
159 merging b and a to b
159 merging b and a to b
160 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
160 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
161 premerge successful
161 premerge successful
162 b
162 b
163 grafting 5:97f8bfe72746 "5"
163 grafting 5:97f8bfe72746 "5"
164 searching for copies back to rev 1
164 searching for copies back to rev 1
165 resolving manifests
165 resolving manifests
166 branchmerge: True, force: True, partial: False
166 branchmerge: True, force: True, partial: False
167 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
167 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
168 e: remote is newer -> g
168 e: remote is newer -> g
169 getting e
169 getting e
170 updating: e 1/1 files (100.00%)
170 updating: e 1/1 files (100.00%)
171 b: remote unchanged -> k
171 b: remote unchanged -> k
172 e
172 e
173 grafting 4:9c233e8e184d "4"
173 grafting 4:9c233e8e184d "4"
174 searching for copies back to rev 1
174 searching for copies back to rev 1
175 resolving manifests
175 resolving manifests
176 branchmerge: True, force: True, partial: False
176 branchmerge: True, force: True, partial: False
177 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
177 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
178 preserving e for resolve of e
178 preserving e for resolve of e
179 d: remote is newer -> g
179 d: remote is newer -> g
180 getting d
180 getting d
181 updating: d 1/2 files (50.00%)
181 updating: d 1/2 files (50.00%)
182 b: remote unchanged -> k
182 b: remote unchanged -> k
183 e: versions differ -> m
183 e: versions differ -> m
184 updating: e 2/2 files (100.00%)
184 updating: e 2/2 files (100.00%)
185 picked tool 'internal:merge' for e (binary False symlink False)
185 picked tool 'internal:merge' for e (binary False symlink False)
186 merging e
186 merging e
187 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
187 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
188 warning: conflicts during merge.
188 warning: conflicts during merge.
189 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
189 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
190 abort: unresolved conflicts, can't continue
190 abort: unresolved conflicts, can't continue
191 (use hg resolve and hg graft --continue)
191 (use hg resolve and hg graft --continue)
192 [255]
192 [255]
193
193
194 Commit while interrupted should fail:
194 Commit while interrupted should fail:
195
195
196 $ hg ci -m 'commit interrupted graft'
196 $ hg ci -m 'commit interrupted graft'
197 abort: graft in progress
197 abort: graft in progress
198 (use 'hg graft --continue' or 'hg update' to abort)
198 (use 'hg graft --continue' or 'hg update' to abort)
199 [255]
199 [255]
200
200
201 Abort the graft and try committing:
201 Abort the graft and try committing:
202
202
203 $ hg up -C .
203 $ hg up -C .
204 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
204 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
205 $ echo c >> e
205 $ echo c >> e
206 $ hg ci -mtest
206 $ hg ci -mtest
207
207
208 $ hg strip . --config extensions.mq=
208 $ hg strip . --config extensions.mq=
209 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
209 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
210 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
210 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
211
211
212 Graft again:
212 Graft again:
213
213
214 $ hg graft 1 5 4 3 'merge()' 2
214 $ hg graft 1 5 4 3 'merge()' 2
215 skipping ungraftable merge revision 6
215 skipping ungraftable merge revision 6
216 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
216 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
217 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
217 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
218 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
218 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
219 grafting 4:9c233e8e184d "4"
219 grafting 4:9c233e8e184d "4"
220 merging e
220 merging e
221 warning: conflicts during merge.
221 warning: conflicts during merge.
222 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
222 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
223 abort: unresolved conflicts, can't continue
223 abort: unresolved conflicts, can't continue
224 (use hg resolve and hg graft --continue)
224 (use hg resolve and hg graft --continue)
225 [255]
225 [255]
226
226
227 Continue without resolve should fail:
227 Continue without resolve should fail:
228
228
229 $ hg graft -c
229 $ hg graft -c
230 grafting 4:9c233e8e184d "4"
230 grafting 4:9c233e8e184d "4"
231 abort: unresolved merge conflicts (see hg help resolve)
231 abort: unresolved merge conflicts (see hg help resolve)
232 [255]
232 [255]
233
233
234 Fix up:
234 Fix up:
235
235
236 $ echo b > e
236 $ echo b > e
237 $ hg resolve -m e
237 $ hg resolve -m e
238 (no more unresolved files)
238 (no more unresolved files)
239
239
240 Continue with a revision should fail:
240 Continue with a revision should fail:
241
241
242 $ hg graft -c 6
242 $ hg graft -c 6
243 abort: can't specify --continue and revisions
243 abort: can't specify --continue and revisions
244 [255]
244 [255]
245
245
246 $ hg graft -c -r 6
246 $ hg graft -c -r 6
247 abort: can't specify --continue and revisions
247 abort: can't specify --continue and revisions
248 [255]
248 [255]
249
249
250 Continue for real, clobber usernames
250 Continue for real, clobber usernames
251
251
252 $ hg graft -c -U
252 $ hg graft -c -U
253 grafting 4:9c233e8e184d "4"
253 grafting 4:9c233e8e184d "4"
254 grafting 3:4c60f11aa304 "3"
254 grafting 3:4c60f11aa304 "3"
255
255
256 Compare with original:
256 Compare with original:
257
257
258 $ hg diff -r 6
258 $ hg diff -r 6
259 $ hg status --rev 0:. -C
259 $ hg status --rev 0:. -C
260 M d
260 M d
261 M e
261 M e
262 A b
262 A b
263 a
263 a
264 A c
264 A c
265 a
265 a
266 R a
266 R a
267
267
268 View graph:
268 View graph:
269
269
270 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
270 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
271 @ test@11.draft: 3
271 @ test@11.draft: 3
272 |
272 |
273 o test@10.draft: 4
273 o test@10.draft: 4
274 |
274 |
275 o test@9.draft: 5
275 o test@9.draft: 5
276 |
276 |
277 o bar@8.draft: 1
277 o bar@8.draft: 1
278 |
278 |
279 o foo@7.draft: 2
279 o foo@7.draft: 2
280 |
280 |
281 | o test@6.secret: 6
281 | o test@6.secret: 6
282 | |\
282 | |\
283 | | o test@5.draft: 5
283 | | o test@5.draft: 5
284 | | |
284 | | |
285 | o | test@4.draft: 4
285 | o | test@4.draft: 4
286 | |/
286 | |/
287 | o baz@3.public: 3
287 | o baz@3.public: 3
288 | |
288 | |
289 | o test@2.public: 2
289 | o test@2.public: 2
290 | |
290 | |
291 | o bar@1.public: 1
291 | o bar@1.public: 1
292 |/
292 |/
293 o test@0.public: 0
293 o test@0.public: 0
294
294
295 Graft again onto another branch should preserve the original source
295 Graft again onto another branch should preserve the original source
296 $ hg up -q 0
296 $ hg up -q 0
297 $ echo 'g'>g
297 $ echo 'g'>g
298 $ hg add g
298 $ hg add g
299 $ hg ci -m 7
299 $ hg ci -m 7
300 created new head
300 created new head
301 $ hg graft 7
301 $ hg graft 7
302 grafting 7:ef0ef43d49e7 "2"
302 grafting 7:ef0ef43d49e7 "2"
303
303
304 $ hg log -r 7 --template '{rev}:{node}\n'
304 $ hg log -r 7 --template '{rev}:{node}\n'
305 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
305 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
306 $ hg log -r 2 --template '{rev}:{node}\n'
306 $ hg log -r 2 --template '{rev}:{node}\n'
307 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
307 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
308
308
309 $ hg log --debug -r tip
309 $ hg log --debug -r tip
310 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
310 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
311 tag: tip
311 tag: tip
312 phase: draft
312 phase: draft
313 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
313 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
314 parent: -1:0000000000000000000000000000000000000000
314 parent: -1:0000000000000000000000000000000000000000
315 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
315 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
316 user: foo
316 user: foo
317 date: Thu Jan 01 00:00:00 1970 +0000
317 date: Thu Jan 01 00:00:00 1970 +0000
318 files+: b
318 files+: b
319 files-: a
319 files-: a
320 extra: branch=default
320 extra: branch=default
321 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
321 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
322 description:
322 description:
323 2
323 2
324
324
325
325
326 Disallow grafting an already grafted cset onto its original branch
326 Disallow grafting an already grafted cset onto its original branch
327 $ hg up -q 6
327 $ hg up -q 6
328 $ hg graft 7
328 $ hg graft 7
329 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
329 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
330 [255]
330 [255]
331
331
332 Disallow grafting already grafted csets with the same origin onto each other
332 Disallow grafting already grafted csets with the same origin onto each other
333 $ hg up -q 13
333 $ hg up -q 13
334 $ hg graft 2
334 $ hg graft 2
335 skipping revision 2:5c095ad7e90f (already grafted to 13:9db0f28fd374)
335 skipping revision 2:5c095ad7e90f (already grafted to 13:9db0f28fd374)
336 [255]
336 [255]
337 $ hg graft 7
337 $ hg graft 7
338 skipping already grafted revision 7:ef0ef43d49e7 (13:9db0f28fd374 also has origin 2:5c095ad7e90f)
338 skipping already grafted revision 7:ef0ef43d49e7 (13:9db0f28fd374 also has origin 2:5c095ad7e90f)
339 [255]
339 [255]
340
340
341 $ hg up -q 7
341 $ hg up -q 7
342 $ hg graft 2
342 $ hg graft 2
343 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
343 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
344 [255]
344 [255]
345 $ hg graft tip
345 $ hg graft tip
346 skipping already grafted revision 13:9db0f28fd374 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
346 skipping already grafted revision 13:9db0f28fd374 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
347 [255]
347 [255]
348
348
349 Graft with --log
349 Graft with --log
350
350
351 $ hg up -Cq 1
351 $ hg up -Cq 1
352 $ hg graft 3 --log -u foo
352 $ hg graft 3 --log -u foo
353 grafting 3:4c60f11aa304 "3"
353 grafting 3:4c60f11aa304 "3"
354 warning: can't find ancestor for 'c' copied from 'b'!
354 warning: can't find ancestor for 'c' copied from 'b'!
355 $ hg log --template '{rev} {parents} {desc}\n' -r tip
355 $ hg log --template '{rev} {parents} {desc}\n' -r tip
356 14 1:5d205f8b35b6 3
356 14 1:5d205f8b35b6 3
357 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
357 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
358
358
359 Resolve conflicted graft
359 Resolve conflicted graft
360 $ hg up -q 0
360 $ hg up -q 0
361 $ echo b > a
361 $ echo b > a
362 $ hg ci -m 8
362 $ hg ci -m 8
363 created new head
363 created new head
364 $ echo c > a
364 $ echo c > a
365 $ hg ci -m 9
365 $ hg ci -m 9
366 $ hg graft 1 --tool internal:fail
366 $ hg graft 1 --tool internal:fail
367 grafting 1:5d205f8b35b6 "1"
367 grafting 1:5d205f8b35b6 "1"
368 abort: unresolved conflicts, can't continue
368 abort: unresolved conflicts, can't continue
369 (use hg resolve and hg graft --continue)
369 (use hg resolve and hg graft --continue)
370 [255]
370 [255]
371 $ hg resolve --all
371 $ hg resolve --all
372 merging a
372 merging a
373 warning: conflicts during merge.
373 warning: conflicts during merge.
374 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
374 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
375 [1]
375 [1]
376 $ cat a
376 $ cat a
377 <<<<<<< local: aaa4406d4f0a - test: 9
377 <<<<<<< local: aaa4406d4f0a - test: 9
378 c
378 c
379 =======
379 =======
380 b
380 b
381 >>>>>>> other: 5d205f8b35b6 - bar: 1
381 >>>>>>> other: 5d205f8b35b6 - bar: 1
382 $ echo b > a
382 $ echo b > a
383 $ hg resolve -m a
383 $ hg resolve -m a
384 (no more unresolved files)
384 (no more unresolved files)
385 $ hg graft -c
385 $ hg graft -c
386 grafting 1:5d205f8b35b6 "1"
386 grafting 1:5d205f8b35b6 "1"
387 $ hg export tip --git
387 $ hg export tip --git
388 # HG changeset patch
388 # HG changeset patch
389 # User bar
389 # User bar
390 # Date 0 0
390 # Date 0 0
391 # Thu Jan 01 00:00:00 1970 +0000
391 # Thu Jan 01 00:00:00 1970 +0000
392 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
392 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
393 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
393 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
394 1
394 1
395
395
396 diff --git a/a b/a
396 diff --git a/a b/a
397 --- a/a
397 --- a/a
398 +++ b/a
398 +++ b/a
399 @@ -1,1 +1,1 @@
399 @@ -1,1 +1,1 @@
400 -c
400 -c
401 +b
401 +b
402
402
403 Resolve conflicted graft with rename
403 Resolve conflicted graft with rename
404 $ echo c > a
404 $ echo c > a
405 $ hg ci -m 10
405 $ hg ci -m 10
406 $ hg graft 2 --tool internal:fail
406 $ hg graft 2 --tool internal:fail
407 grafting 2:5c095ad7e90f "2"
407 grafting 2:5c095ad7e90f "2"
408 abort: unresolved conflicts, can't continue
408 abort: unresolved conflicts, can't continue
409 (use hg resolve and hg graft --continue)
409 (use hg resolve and hg graft --continue)
410 [255]
410 [255]
411 $ hg resolve --all
411 $ hg resolve --all
412 merging a and b to b
412 merging a and b to b
413 (no more unresolved files)
413 (no more unresolved files)
414 $ hg graft -c
414 $ hg graft -c
415 grafting 2:5c095ad7e90f "2"
415 grafting 2:5c095ad7e90f "2"
416 $ hg export tip --git
416 $ hg export tip --git
417 # HG changeset patch
417 # HG changeset patch
418 # User test
418 # User test
419 # Date 0 0
419 # Date 0 0
420 # Thu Jan 01 00:00:00 1970 +0000
420 # Thu Jan 01 00:00:00 1970 +0000
421 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
421 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
422 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
422 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
423 2
423 2
424
424
425 diff --git a/a b/b
425 diff --git a/a b/b
426 rename from a
426 rename from a
427 rename to b
427 rename to b
428
428
429 Test simple origin(), with and without args
429 Test simple origin(), with and without args
430 $ hg log -r 'origin()'
430 $ hg log -r 'origin()'
431 changeset: 1:5d205f8b35b6
431 changeset: 1:5d205f8b35b6
432 user: bar
432 user: bar
433 date: Thu Jan 01 00:00:00 1970 +0000
433 date: Thu Jan 01 00:00:00 1970 +0000
434 summary: 1
434 summary: 1
435
435
436 changeset: 2:5c095ad7e90f
436 changeset: 2:5c095ad7e90f
437 user: test
437 user: test
438 date: Thu Jan 01 00:00:00 1970 +0000
438 date: Thu Jan 01 00:00:00 1970 +0000
439 summary: 2
439 summary: 2
440
440
441 changeset: 3:4c60f11aa304
441 changeset: 3:4c60f11aa304
442 user: baz
442 user: baz
443 date: Thu Jan 01 00:00:00 1970 +0000
443 date: Thu Jan 01 00:00:00 1970 +0000
444 summary: 3
444 summary: 3
445
445
446 changeset: 4:9c233e8e184d
446 changeset: 4:9c233e8e184d
447 user: test
447 user: test
448 date: Thu Jan 01 00:00:00 1970 +0000
448 date: Thu Jan 01 00:00:00 1970 +0000
449 summary: 4
449 summary: 4
450
450
451 changeset: 5:97f8bfe72746
451 changeset: 5:97f8bfe72746
452 branch: stable
452 branch: stable
453 parent: 3:4c60f11aa304
453 parent: 3:4c60f11aa304
454 user: test
454 user: test
455 date: Thu Jan 01 00:00:00 1970 +0000
455 date: Thu Jan 01 00:00:00 1970 +0000
456 summary: 5
456 summary: 5
457
457
458 $ hg log -r 'origin(7)'
458 $ hg log -r 'origin(7)'
459 changeset: 2:5c095ad7e90f
459 changeset: 2:5c095ad7e90f
460 user: test
460 user: test
461 date: Thu Jan 01 00:00:00 1970 +0000
461 date: Thu Jan 01 00:00:00 1970 +0000
462 summary: 2
462 summary: 2
463
463
464 Now transplant a graft to test following through copies
464 Now transplant a graft to test following through copies
465 $ hg up -q 0
465 $ hg up -q 0
466 $ hg branch -q dev
466 $ hg branch -q dev
467 $ hg ci -qm "dev branch"
467 $ hg ci -qm "dev branch"
468 $ hg --config extensions.transplant= transplant -q 7
468 $ hg --config extensions.transplant= transplant -q 7
469 $ hg log -r 'origin(.)'
469 $ hg log -r 'origin(.)'
470 changeset: 2:5c095ad7e90f
470 changeset: 2:5c095ad7e90f
471 user: test
471 user: test
472 date: Thu Jan 01 00:00:00 1970 +0000
472 date: Thu Jan 01 00:00:00 1970 +0000
473 summary: 2
473 summary: 2
474
474
475 Test that the graft and transplant markers in extra are converted, allowing
475 Test that the graft and transplant markers in extra are converted, allowing
476 origin() to still work. Note that these recheck the immediately preceeding two
476 origin() to still work. Note that these recheck the immediately preceeding two
477 tests.
477 tests.
478 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
478 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
479
479
480 The graft case
480 The graft case
481 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
481 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
482 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
482 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
483 branch=default
483 branch=default
484 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
484 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
485 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
485 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
486 $ hg -R ../converted log -r 'origin(7)'
486 $ hg -R ../converted log -r 'origin(7)'
487 changeset: 2:e0213322b2c1
487 changeset: 2:e0213322b2c1
488 user: test
488 user: test
489 date: Thu Jan 01 00:00:00 1970 +0000
489 date: Thu Jan 01 00:00:00 1970 +0000
490 summary: 2
490 summary: 2
491
491
492 Test that template correctly expands more than one 'extra' (issue4362)
492 Test that template correctly expands more than one 'extra' (issue4362)
493 $ hg -R ../converted log -r 7 --template "{extras % ' Extra: {extra}\n'}"
493 $ hg -R ../converted log -r 7 --template "{extras % ' Extra: {extra}\n'}"
494 Extra: branch=default
494 Extra: branch=default
495 Extra: convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
495 Extra: convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
496 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
496 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
497
497
498 The transplant case
498 The transplant case
499 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
499 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
500 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
500 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
501 branch=dev
501 branch=dev
502 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
502 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
503 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
503 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
504 `h\x9b (esc)
504 `h\x9b (esc)
505 $ hg -R ../converted log -r 'origin(tip)'
505 $ hg -R ../converted log -r 'origin(tip)'
506 changeset: 2:e0213322b2c1
506 changeset: 2:e0213322b2c1
507 user: test
507 user: test
508 date: Thu Jan 01 00:00:00 1970 +0000
508 date: Thu Jan 01 00:00:00 1970 +0000
509 summary: 2
509 summary: 2
510
510
511
511
512 Test simple destination
512 Test simple destination
513 $ hg log -r 'destination()'
513 $ hg log -r 'destination()'
514 changeset: 7:ef0ef43d49e7
514 changeset: 7:ef0ef43d49e7
515 parent: 0:68795b066622
515 parent: 0:68795b066622
516 user: foo
516 user: foo
517 date: Thu Jan 01 00:00:00 1970 +0000
517 date: Thu Jan 01 00:00:00 1970 +0000
518 summary: 2
518 summary: 2
519
519
520 changeset: 8:6b9e5368ca4e
520 changeset: 8:6b9e5368ca4e
521 user: bar
521 user: bar
522 date: Thu Jan 01 00:00:00 1970 +0000
522 date: Thu Jan 01 00:00:00 1970 +0000
523 summary: 1
523 summary: 1
524
524
525 changeset: 9:1905859650ec
525 changeset: 9:1905859650ec
526 user: test
526 user: test
527 date: Thu Jan 01 00:00:00 1970 +0000
527 date: Thu Jan 01 00:00:00 1970 +0000
528 summary: 5
528 summary: 5
529
529
530 changeset: 10:52dc0b4c6907
530 changeset: 10:52dc0b4c6907
531 user: test
531 user: test
532 date: Thu Jan 01 00:00:00 1970 +0000
532 date: Thu Jan 01 00:00:00 1970 +0000
533 summary: 4
533 summary: 4
534
534
535 changeset: 11:882b35362a6b
535 changeset: 11:882b35362a6b
536 user: test
536 user: test
537 date: Thu Jan 01 00:00:00 1970 +0000
537 date: Thu Jan 01 00:00:00 1970 +0000
538 summary: 3
538 summary: 3
539
539
540 changeset: 13:9db0f28fd374
540 changeset: 13:9db0f28fd374
541 user: foo
541 user: foo
542 date: Thu Jan 01 00:00:00 1970 +0000
542 date: Thu Jan 01 00:00:00 1970 +0000
543 summary: 2
543 summary: 2
544
544
545 changeset: 14:f64defefacee
545 changeset: 14:f64defefacee
546 parent: 1:5d205f8b35b6
546 parent: 1:5d205f8b35b6
547 user: foo
547 user: foo
548 date: Thu Jan 01 00:00:00 1970 +0000
548 date: Thu Jan 01 00:00:00 1970 +0000
549 summary: 3
549 summary: 3
550
550
551 changeset: 17:f67661df0c48
551 changeset: 17:f67661df0c48
552 user: bar
552 user: bar
553 date: Thu Jan 01 00:00:00 1970 +0000
553 date: Thu Jan 01 00:00:00 1970 +0000
554 summary: 1
554 summary: 1
555
555
556 changeset: 19:9627f653b421
556 changeset: 19:9627f653b421
557 user: test
557 user: test
558 date: Thu Jan 01 00:00:00 1970 +0000
558 date: Thu Jan 01 00:00:00 1970 +0000
559 summary: 2
559 summary: 2
560
560
561 changeset: 21:7e61b508e709
561 changeset: 21:7e61b508e709
562 branch: dev
562 branch: dev
563 tag: tip
563 tag: tip
564 user: foo
564 user: foo
565 date: Thu Jan 01 00:00:00 1970 +0000
565 date: Thu Jan 01 00:00:00 1970 +0000
566 summary: 2
566 summary: 2
567
567
568 $ hg log -r 'destination(2)'
568 $ hg log -r 'destination(2)'
569 changeset: 7:ef0ef43d49e7
569 changeset: 7:ef0ef43d49e7
570 parent: 0:68795b066622
570 parent: 0:68795b066622
571 user: foo
571 user: foo
572 date: Thu Jan 01 00:00:00 1970 +0000
572 date: Thu Jan 01 00:00:00 1970 +0000
573 summary: 2
573 summary: 2
574
574
575 changeset: 13:9db0f28fd374
575 changeset: 13:9db0f28fd374
576 user: foo
576 user: foo
577 date: Thu Jan 01 00:00:00 1970 +0000
577 date: Thu Jan 01 00:00:00 1970 +0000
578 summary: 2
578 summary: 2
579
579
580 changeset: 19:9627f653b421
580 changeset: 19:9627f653b421
581 user: test
581 user: test
582 date: Thu Jan 01 00:00:00 1970 +0000
582 date: Thu Jan 01 00:00:00 1970 +0000
583 summary: 2
583 summary: 2
584
584
585 changeset: 21:7e61b508e709
585 changeset: 21:7e61b508e709
586 branch: dev
586 branch: dev
587 tag: tip
587 tag: tip
588 user: foo
588 user: foo
589 date: Thu Jan 01 00:00:00 1970 +0000
589 date: Thu Jan 01 00:00:00 1970 +0000
590 summary: 2
590 summary: 2
591
591
592 Transplants of grafts can find a destination...
592 Transplants of grafts can find a destination...
593 $ hg log -r 'destination(7)'
593 $ hg log -r 'destination(7)'
594 changeset: 21:7e61b508e709
594 changeset: 21:7e61b508e709
595 branch: dev
595 branch: dev
596 tag: tip
596 tag: tip
597 user: foo
597 user: foo
598 date: Thu Jan 01 00:00:00 1970 +0000
598 date: Thu Jan 01 00:00:00 1970 +0000
599 summary: 2
599 summary: 2
600
600
601 ... grafts of grafts unfortunately can't
601 ... grafts of grafts unfortunately can't
602 $ hg graft -q 13
602 $ hg graft -q 13
603 $ hg log -r 'destination(13)'
603 $ hg log -r 'destination(13)'
604 All copies of a cset
604 All copies of a cset
605 $ hg log -r 'origin(13) or destination(origin(13))'
605 $ hg log -r 'origin(13) or destination(origin(13))'
606 changeset: 2:5c095ad7e90f
606 changeset: 2:5c095ad7e90f
607 user: test
607 user: test
608 date: Thu Jan 01 00:00:00 1970 +0000
608 date: Thu Jan 01 00:00:00 1970 +0000
609 summary: 2
609 summary: 2
610
610
611 changeset: 7:ef0ef43d49e7
611 changeset: 7:ef0ef43d49e7
612 parent: 0:68795b066622
612 parent: 0:68795b066622
613 user: foo
613 user: foo
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 changeset: 13:9db0f28fd374
617 changeset: 13:9db0f28fd374
618 user: foo
618 user: foo
619 date: Thu Jan 01 00:00:00 1970 +0000
619 date: Thu Jan 01 00:00:00 1970 +0000
620 summary: 2
620 summary: 2
621
621
622 changeset: 19:9627f653b421
622 changeset: 19:9627f653b421
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: 2
625 summary: 2
626
626
627 changeset: 21:7e61b508e709
627 changeset: 21:7e61b508e709
628 branch: dev
628 branch: dev
629 user: foo
629 user: foo
630 date: Thu Jan 01 00:00:00 1970 +0000
630 date: Thu Jan 01 00:00:00 1970 +0000
631 summary: 2
631 summary: 2
632
632
633 changeset: 22:1313d0a825e2
633 changeset: 22:1313d0a825e2
634 branch: dev
634 branch: dev
635 tag: tip
635 tag: tip
636 user: foo
636 user: foo
637 date: Thu Jan 01 00:00:00 1970 +0000
637 date: Thu Jan 01 00:00:00 1970 +0000
638 summary: 2
638 summary: 2
639
639
640
640
641 graft works on complex revset
641 graft works on complex revset
642
642
643 $ hg graft 'origin(13) or destination(origin(13))'
643 $ hg graft 'origin(13) or destination(origin(13))'
644 skipping ancestor revision 21:7e61b508e709
644 skipping ancestor revision 21:7e61b508e709
645 skipping ancestor revision 22:1313d0a825e2
645 skipping ancestor revision 22:1313d0a825e2
646 skipping revision 2:5c095ad7e90f (already grafted to 22:1313d0a825e2)
646 skipping revision 2:5c095ad7e90f (already grafted to 22:1313d0a825e2)
647 grafting 7:ef0ef43d49e7 "2"
647 grafting 7:ef0ef43d49e7 "2"
648 grafting 13:9db0f28fd374 "2"
648 grafting 13:9db0f28fd374 "2"
649 grafting 19:9627f653b421 "2"
649 grafting 19:9627f653b421 "2"
650 merging b
650 merging b
651
651
652 graft with --force (still doesn't graft merges)
652 graft with --force (still doesn't graft merges)
653
653
654 $ hg graft 19 0 6
654 $ hg graft 19 0 6
655 skipping ungraftable merge revision 6
655 skipping ungraftable merge revision 6
656 skipping ancestor revision 0:68795b066622
656 skipping ancestor revision 0:68795b066622
657 skipping already grafted revision 19:9627f653b421 (22:1313d0a825e2 also has origin 2:5c095ad7e90f)
657 skipping already grafted revision 19:9627f653b421 (22:1313d0a825e2 also has origin 2:5c095ad7e90f)
658 [255]
658 [255]
659 $ hg graft 19 0 6 --force
659 $ hg graft 19 0 6 --force
660 skipping ungraftable merge revision 6
660 skipping ungraftable merge revision 6
661 grafting 19:9627f653b421 "2"
661 grafting 19:9627f653b421 "2"
662 merging b
662 merging b
663 grafting 0:68795b066622 "0"
663 grafting 0:68795b066622 "0"
664
664
665 graft --force after backout
665 graft --force after backout
666
666
667 $ echo abc > a
667 $ echo abc > a
668 $ hg ci -m 28
668 $ hg ci -m 28
669 $ hg backout 28
669 $ hg backout 28
670 reverting a
670 reverting a
671 changeset 29:484c03b8dfa4 backs out changeset 28:6c56f0f7f033
671 changeset 29:484c03b8dfa4 backs out changeset 28:6c56f0f7f033
672 $ hg graft 28
672 $ hg graft 28
673 skipping ancestor revision 28:6c56f0f7f033
673 skipping ancestor revision 28:6c56f0f7f033
674 [255]
674 [255]
675 $ hg graft 28 --force
675 $ hg graft 28 --force
676 grafting 28:6c56f0f7f033 "28"
676 grafting 28:6c56f0f7f033 "28"
677 merging a
677 merging a
678 $ cat a
678 $ cat a
679 abc
679 abc
680
680
681 graft --continue after --force
681 graft --continue after --force
682
682
683 $ echo def > a
683 $ echo def > a
684 $ hg ci -m 31
684 $ hg ci -m 31
685 $ hg graft 28 --force --tool internal:fail
685 $ hg graft 28 --force --tool internal:fail
686 grafting 28:6c56f0f7f033 "28"
686 grafting 28:6c56f0f7f033 "28"
687 abort: unresolved conflicts, can't continue
687 abort: unresolved conflicts, can't continue
688 (use hg resolve and hg graft --continue)
688 (use hg resolve and hg graft --continue)
689 [255]
689 [255]
690 $ hg resolve --all
690 $ hg resolve --all
691 merging a
691 merging a
692 warning: conflicts during merge.
692 warning: conflicts during merge.
693 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
693 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
694 [1]
694 [1]
695 $ echo abc > a
695 $ echo abc > a
696 $ hg resolve -m a
696 $ hg resolve -m a
697 (no more unresolved files)
697 (no more unresolved files)
698 $ hg graft -c
698 $ hg graft -c
699 grafting 28:6c56f0f7f033 "28"
699 grafting 28:6c56f0f7f033 "28"
700 $ cat a
700 $ cat a
701 abc
701 abc
702
702
703 Continue testing same origin policy, using revision numbers from test above
703 Continue testing same origin policy, using revision numbers from test above
704 but do some destructive editing of the repo:
704 but do some destructive editing of the repo:
705
705
706 $ hg up -qC 7
706 $ hg up -qC 7
707 $ hg tag -l -r 13 tmp
707 $ hg tag -l -r 13 tmp
708 $ hg --config extensions.mq= strip 2
708 $ hg --config extensions.mq= strip 2
709 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-backup.hg (glob)
709 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-backup.hg (glob)
710 $ hg graft tmp
710 $ hg graft tmp
711 skipping already grafted revision 8:9db0f28fd374 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
711 skipping already grafted revision 8:9db0f28fd374 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
712 [255]
712 [255]
713
713
714 Empty graft
714 Empty graft
715
715
716 $ hg up -qr 26
716 $ hg up -qr 26
717 $ hg tag -f something
717 $ hg tag -f something
718 $ hg graft -qr 27
718 $ hg graft -qr 27
719 $ hg graft -qf 27
719 $ hg graft -f 27
720 note: graft of 27:3aaa8b6725f0 "28" created no changes to commit
720 grafting 27:3aaa8b6725f0 "28"
721 note: graft of 27:3aaa8b6725f0 created no changes to commit
General Comments 0
You need to be logged in to leave comments. Login now