##// END OF EJS Templates
commit: improve --close-branch documentation...
Matt Mackall -
r25304:9bc11716 default
parent child Browse files
Show More
@@ -1,6489 +1,6495 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno, shlex
11 import os, re, difflib, time, tempfile, errno, shlex
12 import sys, socket
12 import sys, socket
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb, commandserver
16 import sshserver, hgweb, commandserver
17 import extensions
17 import extensions
18 from hgweb import server as hgweb_server
18 from hgweb import server as hgweb_server
19 import merge as mergemod
19 import merge as mergemod
20 import minirst, revset, fileset
20 import minirst, revset, fileset
21 import dagparser, context, simplemerge, graphmod, 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, bundle2
24 import phases, obsolete, exchange, bundle2
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 (EXPERIMENTAL)'), _('TEMPLATE')),
108 _('display with template (EXPERIMENTAL)'), _('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 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
151 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
152 ]
152 ]
153
153
154 mergetoolopts = [
154 mergetoolopts = [
155 ('t', 'tool', '', _('specify merge tool')),
155 ('t', 'tool', '', _('specify merge tool')),
156 ]
156 ]
157
157
158 similarityopts = [
158 similarityopts = [
159 ('s', 'similarity', '',
159 ('s', 'similarity', '',
160 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
160 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
161 ]
161 ]
162
162
163 subrepoopts = [
163 subrepoopts = [
164 ('S', 'subrepos', None,
164 ('S', 'subrepos', None,
165 _('recurse into subrepositories'))
165 _('recurse into subrepositories'))
166 ]
166 ]
167
167
168 # Commands start here, listed alphabetically
168 # Commands start here, listed alphabetically
169
169
170 @command('^add',
170 @command('^add',
171 walkopts + subrepoopts + dryrunopts,
171 walkopts + subrepoopts + dryrunopts,
172 _('[OPTION]... [FILE]...'),
172 _('[OPTION]... [FILE]...'),
173 inferrepo=True)
173 inferrepo=True)
174 def add(ui, repo, *pats, **opts):
174 def add(ui, repo, *pats, **opts):
175 """add the specified files on the next commit
175 """add the specified files on the next commit
176
176
177 Schedule files to be version controlled and added to the
177 Schedule files to be version controlled and added to the
178 repository.
178 repository.
179
179
180 The files will be added to the repository at the next commit. To
180 The files will be added to the repository at the next commit. To
181 undo an add before that, see :hg:`forget`.
181 undo an add before that, see :hg:`forget`.
182
182
183 If no names are given, add all files to the repository.
183 If no names are given, add all files to the repository.
184
184
185 .. container:: verbose
185 .. container:: verbose
186
186
187 An example showing how new (unknown) files are added
187 An example showing how new (unknown) files are added
188 automatically by :hg:`add`::
188 automatically by :hg:`add`::
189
189
190 $ ls
190 $ ls
191 foo.c
191 foo.c
192 $ hg status
192 $ hg status
193 ? foo.c
193 ? foo.c
194 $ hg add
194 $ hg add
195 adding foo.c
195 adding foo.c
196 $ hg status
196 $ hg status
197 A foo.c
197 A foo.c
198
198
199 Returns 0 if all files are successfully added.
199 Returns 0 if all files are successfully added.
200 """
200 """
201
201
202 m = scmutil.match(repo[None], pats, opts)
202 m = scmutil.match(repo[None], pats, opts)
203 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
203 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
204 return rejected and 1 or 0
204 return rejected and 1 or 0
205
205
206 @command('addremove',
206 @command('addremove',
207 similarityopts + subrepoopts + walkopts + dryrunopts,
207 similarityopts + subrepoopts + 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 matcher = scmutil.match(repo[None], pats, opts)
238 matcher = scmutil.match(repo[None], pats, opts)
239 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
239 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
240
240
241 @command('^annotate|blame',
241 @command('^annotate|blame',
242 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
242 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
243 ('', 'follow', None,
243 ('', 'follow', None,
244 _('follow copies/renames and list the filename (DEPRECATED)')),
244 _('follow copies/renames and list the filename (DEPRECATED)')),
245 ('', 'no-follow', None, _("don't follow copies and renames")),
245 ('', 'no-follow', None, _("don't follow copies and renames")),
246 ('a', 'text', None, _('treat all files as text')),
246 ('a', 'text', None, _('treat all files as text')),
247 ('u', 'user', None, _('list the author (long with -v)')),
247 ('u', 'user', None, _('list the author (long with -v)')),
248 ('f', 'file', None, _('list the filename')),
248 ('f', 'file', None, _('list the filename')),
249 ('d', 'date', None, _('list the date (short with -q)')),
249 ('d', 'date', None, _('list the date (short with -q)')),
250 ('n', 'number', None, _('list the revision number (default)')),
250 ('n', 'number', None, _('list the revision number (default)')),
251 ('c', 'changeset', None, _('list the changeset')),
251 ('c', 'changeset', None, _('list the changeset')),
252 ('l', 'line-number', None, _('show line number at the first appearance'))
252 ('l', 'line-number', None, _('show line number at the first appearance'))
253 ] + diffwsopts + walkopts + formatteropts,
253 ] + diffwsopts + walkopts + formatteropts,
254 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
254 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
255 inferrepo=True)
255 inferrepo=True)
256 def annotate(ui, repo, *pats, **opts):
256 def annotate(ui, repo, *pats, **opts):
257 """show changeset information by line for each file
257 """show changeset information by line for each file
258
258
259 List changes in files, showing the revision id responsible for
259 List changes in files, showing the revision id responsible for
260 each line
260 each line
261
261
262 This command is useful for discovering when a change was made and
262 This command is useful for discovering when a change was made and
263 by whom.
263 by whom.
264
264
265 Without the -a/--text option, annotate will avoid processing files
265 Without the -a/--text option, annotate will avoid processing files
266 it detects as binary. With -a, annotate will annotate the file
266 it detects as binary. With -a, annotate will annotate the file
267 anyway, although the results will probably be neither useful
267 anyway, although the results will probably be neither useful
268 nor desirable.
268 nor desirable.
269
269
270 Returns 0 on success.
270 Returns 0 on success.
271 """
271 """
272 if not pats:
272 if not pats:
273 raise util.Abort(_('at least one filename or pattern is required'))
273 raise util.Abort(_('at least one filename or pattern is required'))
274
274
275 if opts.get('follow'):
275 if opts.get('follow'):
276 # --follow is deprecated and now just an alias for -f/--file
276 # --follow is deprecated and now just an alias for -f/--file
277 # to mimic the behavior of Mercurial before version 1.5
277 # to mimic the behavior of Mercurial before version 1.5
278 opts['file'] = True
278 opts['file'] = True
279
279
280 ctx = scmutil.revsingle(repo, opts.get('rev'))
280 ctx = scmutil.revsingle(repo, opts.get('rev'))
281
281
282 fm = ui.formatter('annotate', opts)
282 fm = ui.formatter('annotate', opts)
283 if ui.quiet:
283 if ui.quiet:
284 datefunc = util.shortdate
284 datefunc = util.shortdate
285 else:
285 else:
286 datefunc = util.datestr
286 datefunc = util.datestr
287 if ctx.rev() is None:
287 if ctx.rev() is None:
288 def hexfn(node):
288 def hexfn(node):
289 if node is None:
289 if node is None:
290 return None
290 return None
291 else:
291 else:
292 return fm.hexfunc(node)
292 return fm.hexfunc(node)
293 if opts.get('changeset'):
293 if opts.get('changeset'):
294 # omit "+" suffix which is appended to node hex
294 # omit "+" suffix which is appended to node hex
295 def formatrev(rev):
295 def formatrev(rev):
296 if rev is None:
296 if rev is None:
297 return '%d' % ctx.p1().rev()
297 return '%d' % ctx.p1().rev()
298 else:
298 else:
299 return '%d' % rev
299 return '%d' % rev
300 else:
300 else:
301 def formatrev(rev):
301 def formatrev(rev):
302 if rev is None:
302 if rev is None:
303 return '%d+' % ctx.p1().rev()
303 return '%d+' % ctx.p1().rev()
304 else:
304 else:
305 return '%d ' % rev
305 return '%d ' % rev
306 def formathex(hex):
306 def formathex(hex):
307 if hex is None:
307 if hex is None:
308 return '%s+' % fm.hexfunc(ctx.p1().node())
308 return '%s+' % fm.hexfunc(ctx.p1().node())
309 else:
309 else:
310 return '%s ' % hex
310 return '%s ' % hex
311 else:
311 else:
312 hexfn = fm.hexfunc
312 hexfn = fm.hexfunc
313 formatrev = formathex = str
313 formatrev = formathex = str
314
314
315 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
315 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
316 ('number', ' ', lambda x: x[0].rev(), formatrev),
316 ('number', ' ', lambda x: x[0].rev(), formatrev),
317 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
317 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
318 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
318 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
319 ('file', ' ', lambda x: x[0].path(), str),
319 ('file', ' ', lambda x: x[0].path(), str),
320 ('line_number', ':', lambda x: x[1], str),
320 ('line_number', ':', lambda x: x[1], str),
321 ]
321 ]
322 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
322 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
323
323
324 if (not opts.get('user') and not opts.get('changeset')
324 if (not opts.get('user') and not opts.get('changeset')
325 and not opts.get('date') and not opts.get('file')):
325 and not opts.get('date') and not opts.get('file')):
326 opts['number'] = True
326 opts['number'] = True
327
327
328 linenumber = opts.get('line_number') is not None
328 linenumber = opts.get('line_number') is not None
329 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
329 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
330 raise util.Abort(_('at least one of -n/-c is required for -l'))
330 raise util.Abort(_('at least one of -n/-c is required for -l'))
331
331
332 if fm:
332 if fm:
333 def makefunc(get, fmt):
333 def makefunc(get, fmt):
334 return get
334 return get
335 else:
335 else:
336 def makefunc(get, fmt):
336 def makefunc(get, fmt):
337 return lambda x: fmt(get(x))
337 return lambda x: fmt(get(x))
338 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
338 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
339 if opts.get(op)]
339 if opts.get(op)]
340 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
340 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
341 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
341 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
342 if opts.get(op))
342 if opts.get(op))
343
343
344 def bad(x, y):
344 def bad(x, y):
345 raise util.Abort("%s: %s" % (x, y))
345 raise util.Abort("%s: %s" % (x, y))
346
346
347 m = scmutil.match(ctx, pats, opts)
347 m = scmutil.match(ctx, pats, opts)
348 m.bad = bad
348 m.bad = bad
349 follow = not opts.get('no_follow')
349 follow = not opts.get('no_follow')
350 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
350 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
351 whitespace=True)
351 whitespace=True)
352 for abs in ctx.walk(m):
352 for abs in ctx.walk(m):
353 fctx = ctx[abs]
353 fctx = ctx[abs]
354 if not opts.get('text') and util.binary(fctx.data()):
354 if not opts.get('text') and util.binary(fctx.data()):
355 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
355 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
356 continue
356 continue
357
357
358 lines = fctx.annotate(follow=follow, linenumber=linenumber,
358 lines = fctx.annotate(follow=follow, linenumber=linenumber,
359 diffopts=diffopts)
359 diffopts=diffopts)
360 formats = []
360 formats = []
361 pieces = []
361 pieces = []
362
362
363 for f, sep in funcmap:
363 for f, sep in funcmap:
364 l = [f(n) for n, dummy in lines]
364 l = [f(n) for n, dummy in lines]
365 if l:
365 if l:
366 if fm:
366 if fm:
367 formats.append(['%s' for x in l])
367 formats.append(['%s' for x in l])
368 else:
368 else:
369 sizes = [encoding.colwidth(x) for x in l]
369 sizes = [encoding.colwidth(x) for x in l]
370 ml = max(sizes)
370 ml = max(sizes)
371 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
371 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
372 pieces.append(l)
372 pieces.append(l)
373
373
374 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
374 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
375 fm.startitem()
375 fm.startitem()
376 fm.write(fields, "".join(f), *p)
376 fm.write(fields, "".join(f), *p)
377 fm.write('line', ": %s", l[1])
377 fm.write('line', ": %s", l[1])
378
378
379 if lines and not lines[-1][1].endswith('\n'):
379 if lines and not lines[-1][1].endswith('\n'):
380 fm.plain('\n')
380 fm.plain('\n')
381
381
382 fm.end()
382 fm.end()
383
383
384 @command('archive',
384 @command('archive',
385 [('', 'no-decode', None, _('do not pass files through decoders')),
385 [('', 'no-decode', None, _('do not pass files through decoders')),
386 ('p', 'prefix', '', _('directory prefix for files in archive'),
386 ('p', 'prefix', '', _('directory prefix for files in archive'),
387 _('PREFIX')),
387 _('PREFIX')),
388 ('r', 'rev', '', _('revision to distribute'), _('REV')),
388 ('r', 'rev', '', _('revision to distribute'), _('REV')),
389 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
389 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
390 ] + subrepoopts + walkopts,
390 ] + subrepoopts + walkopts,
391 _('[OPTION]... DEST'))
391 _('[OPTION]... DEST'))
392 def archive(ui, repo, dest, **opts):
392 def archive(ui, repo, dest, **opts):
393 '''create an unversioned archive of a repository revision
393 '''create an unversioned archive of a repository revision
394
394
395 By default, the revision used is the parent of the working
395 By default, the revision used is the parent of the working
396 directory; use -r/--rev to specify a different revision.
396 directory; use -r/--rev to specify a different revision.
397
397
398 The archive type is automatically detected based on file
398 The archive type is automatically detected based on file
399 extension (or override using -t/--type).
399 extension (or override using -t/--type).
400
400
401 .. container:: verbose
401 .. container:: verbose
402
402
403 Examples:
403 Examples:
404
404
405 - create a zip file containing the 1.0 release::
405 - create a zip file containing the 1.0 release::
406
406
407 hg archive -r 1.0 project-1.0.zip
407 hg archive -r 1.0 project-1.0.zip
408
408
409 - create a tarball excluding .hg files::
409 - create a tarball excluding .hg files::
410
410
411 hg archive project.tar.gz -X ".hg*"
411 hg archive project.tar.gz -X ".hg*"
412
412
413 Valid types are:
413 Valid types are:
414
414
415 :``files``: a directory full of files (default)
415 :``files``: a directory full of files (default)
416 :``tar``: tar archive, uncompressed
416 :``tar``: tar archive, uncompressed
417 :``tbz2``: tar archive, compressed using bzip2
417 :``tbz2``: tar archive, compressed using bzip2
418 :``tgz``: tar archive, compressed using gzip
418 :``tgz``: tar archive, compressed using gzip
419 :``uzip``: zip archive, uncompressed
419 :``uzip``: zip archive, uncompressed
420 :``zip``: zip archive, compressed using deflate
420 :``zip``: zip archive, compressed using deflate
421
421
422 The exact name of the destination archive or directory is given
422 The exact name of the destination archive or directory is given
423 using a format string; see :hg:`help export` for details.
423 using a format string; see :hg:`help export` for details.
424
424
425 Each member added to an archive file has a directory prefix
425 Each member added to an archive file has a directory prefix
426 prepended. Use -p/--prefix to specify a format string for the
426 prepended. Use -p/--prefix to specify a format string for the
427 prefix. The default is the basename of the archive, with suffixes
427 prefix. The default is the basename of the archive, with suffixes
428 removed.
428 removed.
429
429
430 Returns 0 on success.
430 Returns 0 on success.
431 '''
431 '''
432
432
433 ctx = scmutil.revsingle(repo, opts.get('rev'))
433 ctx = scmutil.revsingle(repo, opts.get('rev'))
434 if not ctx:
434 if not ctx:
435 raise util.Abort(_('no working directory: please specify a revision'))
435 raise util.Abort(_('no working directory: please specify a revision'))
436 node = ctx.node()
436 node = ctx.node()
437 dest = cmdutil.makefilename(repo, dest, node)
437 dest = cmdutil.makefilename(repo, dest, node)
438 if os.path.realpath(dest) == repo.root:
438 if os.path.realpath(dest) == repo.root:
439 raise util.Abort(_('repository root cannot be destination'))
439 raise util.Abort(_('repository root cannot be destination'))
440
440
441 kind = opts.get('type') or archival.guesskind(dest) or 'files'
441 kind = opts.get('type') or archival.guesskind(dest) or 'files'
442 prefix = opts.get('prefix')
442 prefix = opts.get('prefix')
443
443
444 if dest == '-':
444 if dest == '-':
445 if kind == 'files':
445 if kind == 'files':
446 raise util.Abort(_('cannot archive plain files to stdout'))
446 raise util.Abort(_('cannot archive plain files to stdout'))
447 dest = cmdutil.makefileobj(repo, dest)
447 dest = cmdutil.makefileobj(repo, dest)
448 if not prefix:
448 if not prefix:
449 prefix = os.path.basename(repo.root) + '-%h'
449 prefix = os.path.basename(repo.root) + '-%h'
450
450
451 prefix = cmdutil.makefilename(repo, prefix, node)
451 prefix = cmdutil.makefilename(repo, prefix, node)
452 matchfn = scmutil.match(ctx, [], opts)
452 matchfn = scmutil.match(ctx, [], opts)
453 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
453 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
454 matchfn, prefix, subrepos=opts.get('subrepos'))
454 matchfn, prefix, subrepos=opts.get('subrepos'))
455
455
456 @command('backout',
456 @command('backout',
457 [('', 'merge', None, _('merge with old dirstate parent after backout')),
457 [('', 'merge', None, _('merge with old dirstate parent after backout')),
458 ('', 'commit', None, _('commit if no conflicts were encountered')),
458 ('', 'commit', None, _('commit if no conflicts were encountered')),
459 ('', 'parent', '',
459 ('', 'parent', '',
460 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
460 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
461 ('r', 'rev', '', _('revision to backout'), _('REV')),
461 ('r', 'rev', '', _('revision to backout'), _('REV')),
462 ('e', 'edit', False, _('invoke editor on commit messages')),
462 ('e', 'edit', False, _('invoke editor on commit messages')),
463 ] + mergetoolopts + walkopts + commitopts + commitopts2,
463 ] + mergetoolopts + walkopts + commitopts + commitopts2,
464 _('[OPTION]... [-r] REV'))
464 _('[OPTION]... [-r] REV'))
465 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
465 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
466 '''reverse effect of earlier changeset
466 '''reverse effect of earlier changeset
467
467
468 Prepare a new changeset with the effect of REV undone in the
468 Prepare a new changeset with the effect of REV undone in the
469 current working directory.
469 current working directory.
470
470
471 If REV is the parent of the working directory, then this new changeset
471 If REV is the parent of the working directory, then this new changeset
472 is committed automatically. Otherwise, hg needs to merge the
472 is committed automatically. Otherwise, hg needs to merge the
473 changes and the merged result is left uncommitted.
473 changes and the merged result is left uncommitted.
474
474
475 .. note::
475 .. note::
476
476
477 backout cannot be used to fix either an unwanted or
477 backout cannot be used to fix either an unwanted or
478 incorrect merge.
478 incorrect merge.
479
479
480 .. container:: verbose
480 .. container:: verbose
481
481
482 By default, the pending changeset will have one parent,
482 By default, the pending changeset will have one parent,
483 maintaining a linear history. With --merge, the pending
483 maintaining a linear history. With --merge, the pending
484 changeset will instead have two parents: the old parent of the
484 changeset will instead have two parents: the old parent of the
485 working directory and a new child of REV that simply undoes REV.
485 working directory and a new child of REV that simply undoes REV.
486
486
487 Before version 1.7, the behavior without --merge was equivalent
487 Before version 1.7, the behavior without --merge was equivalent
488 to specifying --merge followed by :hg:`update --clean .` to
488 to specifying --merge followed by :hg:`update --clean .` to
489 cancel the merge and leave the child of REV as a head to be
489 cancel the merge and leave the child of REV as a head to be
490 merged separately.
490 merged separately.
491
491
492 See :hg:`help dates` for a list of formats valid for -d/--date.
492 See :hg:`help dates` for a list of formats valid for -d/--date.
493
493
494 Returns 0 on success, 1 if nothing to backout or there are unresolved
494 Returns 0 on success, 1 if nothing to backout or there are unresolved
495 files.
495 files.
496 '''
496 '''
497 if rev and node:
497 if rev and node:
498 raise util.Abort(_("please specify just one revision"))
498 raise util.Abort(_("please specify just one revision"))
499
499
500 if not rev:
500 if not rev:
501 rev = node
501 rev = node
502
502
503 if not rev:
503 if not rev:
504 raise util.Abort(_("please specify a revision to backout"))
504 raise util.Abort(_("please specify a revision to backout"))
505
505
506 date = opts.get('date')
506 date = opts.get('date')
507 if date:
507 if date:
508 opts['date'] = util.parsedate(date)
508 opts['date'] = util.parsedate(date)
509
509
510 cmdutil.checkunfinished(repo)
510 cmdutil.checkunfinished(repo)
511 cmdutil.bailifchanged(repo)
511 cmdutil.bailifchanged(repo)
512 node = scmutil.revsingle(repo, rev).node()
512 node = scmutil.revsingle(repo, rev).node()
513
513
514 op1, op2 = repo.dirstate.parents()
514 op1, op2 = repo.dirstate.parents()
515 if not repo.changelog.isancestor(node, op1):
515 if not repo.changelog.isancestor(node, op1):
516 raise util.Abort(_('cannot backout change that is not an ancestor'))
516 raise util.Abort(_('cannot backout change that is not an ancestor'))
517
517
518 p1, p2 = repo.changelog.parents(node)
518 p1, p2 = repo.changelog.parents(node)
519 if p1 == nullid:
519 if p1 == nullid:
520 raise util.Abort(_('cannot backout a change with no parents'))
520 raise util.Abort(_('cannot backout a change with no parents'))
521 if p2 != nullid:
521 if p2 != nullid:
522 if not opts.get('parent'):
522 if not opts.get('parent'):
523 raise util.Abort(_('cannot backout a merge changeset'))
523 raise util.Abort(_('cannot backout a merge changeset'))
524 p = repo.lookup(opts['parent'])
524 p = repo.lookup(opts['parent'])
525 if p not in (p1, p2):
525 if p not in (p1, p2):
526 raise util.Abort(_('%s is not a parent of %s') %
526 raise util.Abort(_('%s is not a parent of %s') %
527 (short(p), short(node)))
527 (short(p), short(node)))
528 parent = p
528 parent = p
529 else:
529 else:
530 if opts.get('parent'):
530 if opts.get('parent'):
531 raise util.Abort(_('cannot use --parent on non-merge changeset'))
531 raise util.Abort(_('cannot use --parent on non-merge changeset'))
532 parent = p1
532 parent = p1
533
533
534 # the backout should appear on the same branch
534 # the backout should appear on the same branch
535 wlock = repo.wlock()
535 wlock = repo.wlock()
536 try:
536 try:
537 branch = repo.dirstate.branch()
537 branch = repo.dirstate.branch()
538 bheads = repo.branchheads(branch)
538 bheads = repo.branchheads(branch)
539 rctx = scmutil.revsingle(repo, hex(parent))
539 rctx = scmutil.revsingle(repo, hex(parent))
540 if not opts.get('merge') and op1 != node:
540 if not opts.get('merge') and op1 != node:
541 try:
541 try:
542 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
542 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
543 'backout')
543 'backout')
544 repo.dirstate.beginparentchange()
544 repo.dirstate.beginparentchange()
545 stats = mergemod.update(repo, parent, True, True, False,
545 stats = mergemod.update(repo, parent, True, True, False,
546 node, False)
546 node, False)
547 repo.setparents(op1, op2)
547 repo.setparents(op1, op2)
548 repo.dirstate.endparentchange()
548 repo.dirstate.endparentchange()
549 hg._showstats(repo, stats)
549 hg._showstats(repo, stats)
550 if stats[3]:
550 if stats[3]:
551 repo.ui.status(_("use 'hg resolve' to retry unresolved "
551 repo.ui.status(_("use 'hg resolve' to retry unresolved "
552 "file merges\n"))
552 "file merges\n"))
553 return 1
553 return 1
554 elif not commit:
554 elif not commit:
555 msg = _("changeset %s backed out, "
555 msg = _("changeset %s backed out, "
556 "don't forget to commit.\n")
556 "don't forget to commit.\n")
557 ui.status(msg % short(node))
557 ui.status(msg % short(node))
558 return 0
558 return 0
559 finally:
559 finally:
560 ui.setconfig('ui', 'forcemerge', '', '')
560 ui.setconfig('ui', 'forcemerge', '', '')
561 else:
561 else:
562 hg.clean(repo, node, show_stats=False)
562 hg.clean(repo, node, show_stats=False)
563 repo.dirstate.setbranch(branch)
563 repo.dirstate.setbranch(branch)
564 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
564 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
565
565
566
566
567 def commitfunc(ui, repo, message, match, opts):
567 def commitfunc(ui, repo, message, match, opts):
568 editform = 'backout'
568 editform = 'backout'
569 e = cmdutil.getcommiteditor(editform=editform, **opts)
569 e = cmdutil.getcommiteditor(editform=editform, **opts)
570 if not message:
570 if not message:
571 # we don't translate commit messages
571 # we don't translate commit messages
572 message = "Backed out changeset %s" % short(node)
572 message = "Backed out changeset %s" % short(node)
573 e = cmdutil.getcommiteditor(edit=True, editform=editform)
573 e = cmdutil.getcommiteditor(edit=True, editform=editform)
574 return repo.commit(message, opts.get('user'), opts.get('date'),
574 return repo.commit(message, opts.get('user'), opts.get('date'),
575 match, editor=e)
575 match, editor=e)
576 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
576 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
577 if not newnode:
577 if not newnode:
578 ui.status(_("nothing changed\n"))
578 ui.status(_("nothing changed\n"))
579 return 1
579 return 1
580 cmdutil.commitstatus(repo, newnode, branch, bheads)
580 cmdutil.commitstatus(repo, newnode, branch, bheads)
581
581
582 def nice(node):
582 def nice(node):
583 return '%d:%s' % (repo.changelog.rev(node), short(node))
583 return '%d:%s' % (repo.changelog.rev(node), short(node))
584 ui.status(_('changeset %s backs out changeset %s\n') %
584 ui.status(_('changeset %s backs out changeset %s\n') %
585 (nice(repo.changelog.tip()), nice(node)))
585 (nice(repo.changelog.tip()), nice(node)))
586 if opts.get('merge') and op1 != node:
586 if opts.get('merge') and op1 != node:
587 hg.clean(repo, op1, show_stats=False)
587 hg.clean(repo, op1, show_stats=False)
588 ui.status(_('merging with changeset %s\n')
588 ui.status(_('merging with changeset %s\n')
589 % nice(repo.changelog.tip()))
589 % nice(repo.changelog.tip()))
590 try:
590 try:
591 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
591 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
592 'backout')
592 'backout')
593 return hg.merge(repo, hex(repo.changelog.tip()))
593 return hg.merge(repo, hex(repo.changelog.tip()))
594 finally:
594 finally:
595 ui.setconfig('ui', 'forcemerge', '', '')
595 ui.setconfig('ui', 'forcemerge', '', '')
596 finally:
596 finally:
597 wlock.release()
597 wlock.release()
598 return 0
598 return 0
599
599
600 @command('bisect',
600 @command('bisect',
601 [('r', 'reset', False, _('reset bisect state')),
601 [('r', 'reset', False, _('reset bisect state')),
602 ('g', 'good', False, _('mark changeset good')),
602 ('g', 'good', False, _('mark changeset good')),
603 ('b', 'bad', False, _('mark changeset bad')),
603 ('b', 'bad', False, _('mark changeset bad')),
604 ('s', 'skip', False, _('skip testing changeset')),
604 ('s', 'skip', False, _('skip testing changeset')),
605 ('e', 'extend', False, _('extend the bisect range')),
605 ('e', 'extend', False, _('extend the bisect range')),
606 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
606 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
607 ('U', 'noupdate', False, _('do not update to target'))],
607 ('U', 'noupdate', False, _('do not update to target'))],
608 _("[-gbsr] [-U] [-c CMD] [REV]"))
608 _("[-gbsr] [-U] [-c CMD] [REV]"))
609 def bisect(ui, repo, rev=None, extra=None, command=None,
609 def bisect(ui, repo, rev=None, extra=None, command=None,
610 reset=None, good=None, bad=None, skip=None, extend=None,
610 reset=None, good=None, bad=None, skip=None, extend=None,
611 noupdate=None):
611 noupdate=None):
612 """subdivision search of changesets
612 """subdivision search of changesets
613
613
614 This command helps to find changesets which introduce problems. To
614 This command helps to find changesets which introduce problems. To
615 use, mark the earliest changeset you know exhibits the problem as
615 use, mark the earliest changeset you know exhibits the problem as
616 bad, then mark the latest changeset which is free from the problem
616 bad, then mark the latest changeset which is free from the problem
617 as good. Bisect will update your working directory to a revision
617 as good. Bisect will update your working directory to a revision
618 for testing (unless the -U/--noupdate option is specified). Once
618 for testing (unless the -U/--noupdate option is specified). Once
619 you have performed tests, mark the working directory as good or
619 you have performed tests, mark the working directory as good or
620 bad, and bisect will either update to another candidate changeset
620 bad, and bisect will either update to another candidate changeset
621 or announce that it has found the bad revision.
621 or announce that it has found the bad revision.
622
622
623 As a shortcut, you can also use the revision argument to mark a
623 As a shortcut, you can also use the revision argument to mark a
624 revision as good or bad without checking it out first.
624 revision as good or bad without checking it out first.
625
625
626 If you supply a command, it will be used for automatic bisection.
626 If you supply a command, it will be used for automatic bisection.
627 The environment variable HG_NODE will contain the ID of the
627 The environment variable HG_NODE will contain the ID of the
628 changeset being tested. The exit status of the command will be
628 changeset being tested. The exit status of the command will be
629 used to mark revisions as good or bad: status 0 means good, 125
629 used to mark revisions as good or bad: status 0 means good, 125
630 means to skip the revision, 127 (command not found) will abort the
630 means to skip the revision, 127 (command not found) will abort the
631 bisection, and any other non-zero exit status means the revision
631 bisection, and any other non-zero exit status means the revision
632 is bad.
632 is bad.
633
633
634 .. container:: verbose
634 .. container:: verbose
635
635
636 Some examples:
636 Some examples:
637
637
638 - start a bisection with known bad revision 34, and good revision 12::
638 - start a bisection with known bad revision 34, and good revision 12::
639
639
640 hg bisect --bad 34
640 hg bisect --bad 34
641 hg bisect --good 12
641 hg bisect --good 12
642
642
643 - advance the current bisection by marking current revision as good or
643 - advance the current bisection by marking current revision as good or
644 bad::
644 bad::
645
645
646 hg bisect --good
646 hg bisect --good
647 hg bisect --bad
647 hg bisect --bad
648
648
649 - mark the current revision, or a known revision, to be skipped (e.g. if
649 - mark the current revision, or a known revision, to be skipped (e.g. if
650 that revision is not usable because of another issue)::
650 that revision is not usable because of another issue)::
651
651
652 hg bisect --skip
652 hg bisect --skip
653 hg bisect --skip 23
653 hg bisect --skip 23
654
654
655 - skip all revisions that do not touch directories ``foo`` or ``bar``::
655 - skip all revisions that do not touch directories ``foo`` or ``bar``::
656
656
657 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
657 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
658
658
659 - forget the current bisection::
659 - forget the current bisection::
660
660
661 hg bisect --reset
661 hg bisect --reset
662
662
663 - use 'make && make tests' to automatically find the first broken
663 - use 'make && make tests' to automatically find the first broken
664 revision::
664 revision::
665
665
666 hg bisect --reset
666 hg bisect --reset
667 hg bisect --bad 34
667 hg bisect --bad 34
668 hg bisect --good 12
668 hg bisect --good 12
669 hg bisect --command "make && make tests"
669 hg bisect --command "make && make tests"
670
670
671 - see all changesets whose states are already known in the current
671 - see all changesets whose states are already known in the current
672 bisection::
672 bisection::
673
673
674 hg log -r "bisect(pruned)"
674 hg log -r "bisect(pruned)"
675
675
676 - see the changeset currently being bisected (especially useful
676 - see the changeset currently being bisected (especially useful
677 if running with -U/--noupdate)::
677 if running with -U/--noupdate)::
678
678
679 hg log -r "bisect(current)"
679 hg log -r "bisect(current)"
680
680
681 - see all changesets that took part in the current bisection::
681 - see all changesets that took part in the current bisection::
682
682
683 hg log -r "bisect(range)"
683 hg log -r "bisect(range)"
684
684
685 - you can even get a nice graph::
685 - you can even get a nice graph::
686
686
687 hg log --graph -r "bisect(range)"
687 hg log --graph -r "bisect(range)"
688
688
689 See :hg:`help revsets` for more about the `bisect()` keyword.
689 See :hg:`help revsets` for more about the `bisect()` keyword.
690
690
691 Returns 0 on success.
691 Returns 0 on success.
692 """
692 """
693 def extendbisectrange(nodes, good):
693 def extendbisectrange(nodes, good):
694 # bisect is incomplete when it ends on a merge node and
694 # bisect is incomplete when it ends on a merge node and
695 # one of the parent was not checked.
695 # one of the parent was not checked.
696 parents = repo[nodes[0]].parents()
696 parents = repo[nodes[0]].parents()
697 if len(parents) > 1:
697 if len(parents) > 1:
698 if good:
698 if good:
699 side = state['bad']
699 side = state['bad']
700 else:
700 else:
701 side = state['good']
701 side = state['good']
702 num = len(set(i.node() for i in parents) & set(side))
702 num = len(set(i.node() for i in parents) & set(side))
703 if num == 1:
703 if num == 1:
704 return parents[0].ancestor(parents[1])
704 return parents[0].ancestor(parents[1])
705 return None
705 return None
706
706
707 def print_result(nodes, good):
707 def print_result(nodes, good):
708 displayer = cmdutil.show_changeset(ui, repo, {})
708 displayer = cmdutil.show_changeset(ui, repo, {})
709 if len(nodes) == 1:
709 if len(nodes) == 1:
710 # narrowed it down to a single revision
710 # narrowed it down to a single revision
711 if good:
711 if good:
712 ui.write(_("The first good revision is:\n"))
712 ui.write(_("The first good revision is:\n"))
713 else:
713 else:
714 ui.write(_("The first bad revision is:\n"))
714 ui.write(_("The first bad revision is:\n"))
715 displayer.show(repo[nodes[0]])
715 displayer.show(repo[nodes[0]])
716 extendnode = extendbisectrange(nodes, good)
716 extendnode = extendbisectrange(nodes, good)
717 if extendnode is not None:
717 if extendnode is not None:
718 ui.write(_('Not all ancestors of this changeset have been'
718 ui.write(_('Not all ancestors of this changeset have been'
719 ' checked.\nUse bisect --extend to continue the '
719 ' checked.\nUse bisect --extend to continue the '
720 'bisection from\nthe common ancestor, %s.\n')
720 'bisection from\nthe common ancestor, %s.\n')
721 % extendnode)
721 % extendnode)
722 else:
722 else:
723 # multiple possible revisions
723 # multiple possible revisions
724 if good:
724 if good:
725 ui.write(_("Due to skipped revisions, the first "
725 ui.write(_("Due to skipped revisions, the first "
726 "good revision could be any of:\n"))
726 "good revision could be any of:\n"))
727 else:
727 else:
728 ui.write(_("Due to skipped revisions, the first "
728 ui.write(_("Due to skipped revisions, the first "
729 "bad revision could be any of:\n"))
729 "bad revision could be any of:\n"))
730 for n in nodes:
730 for n in nodes:
731 displayer.show(repo[n])
731 displayer.show(repo[n])
732 displayer.close()
732 displayer.close()
733
733
734 def check_state(state, interactive=True):
734 def check_state(state, interactive=True):
735 if not state['good'] or not state['bad']:
735 if not state['good'] or not state['bad']:
736 if (good or bad or skip or reset) and interactive:
736 if (good or bad or skip or reset) and interactive:
737 return
737 return
738 if not state['good']:
738 if not state['good']:
739 raise util.Abort(_('cannot bisect (no known good revisions)'))
739 raise util.Abort(_('cannot bisect (no known good revisions)'))
740 else:
740 else:
741 raise util.Abort(_('cannot bisect (no known bad revisions)'))
741 raise util.Abort(_('cannot bisect (no known bad revisions)'))
742 return True
742 return True
743
743
744 # backward compatibility
744 # backward compatibility
745 if rev in "good bad reset init".split():
745 if rev in "good bad reset init".split():
746 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
746 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
747 cmd, rev, extra = rev, extra, None
747 cmd, rev, extra = rev, extra, None
748 if cmd == "good":
748 if cmd == "good":
749 good = True
749 good = True
750 elif cmd == "bad":
750 elif cmd == "bad":
751 bad = True
751 bad = True
752 else:
752 else:
753 reset = True
753 reset = True
754 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
754 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
755 raise util.Abort(_('incompatible arguments'))
755 raise util.Abort(_('incompatible arguments'))
756
756
757 cmdutil.checkunfinished(repo)
757 cmdutil.checkunfinished(repo)
758
758
759 if reset:
759 if reset:
760 p = repo.join("bisect.state")
760 p = repo.join("bisect.state")
761 if os.path.exists(p):
761 if os.path.exists(p):
762 os.unlink(p)
762 os.unlink(p)
763 return
763 return
764
764
765 state = hbisect.load_state(repo)
765 state = hbisect.load_state(repo)
766
766
767 if command:
767 if command:
768 changesets = 1
768 changesets = 1
769 if noupdate:
769 if noupdate:
770 try:
770 try:
771 node = state['current'][0]
771 node = state['current'][0]
772 except LookupError:
772 except LookupError:
773 raise util.Abort(_('current bisect revision is unknown - '
773 raise util.Abort(_('current bisect revision is unknown - '
774 'start a new bisect to fix'))
774 'start a new bisect to fix'))
775 else:
775 else:
776 node, p2 = repo.dirstate.parents()
776 node, p2 = repo.dirstate.parents()
777 if p2 != nullid:
777 if p2 != nullid:
778 raise util.Abort(_('current bisect revision is a merge'))
778 raise util.Abort(_('current bisect revision is a merge'))
779 try:
779 try:
780 while changesets:
780 while changesets:
781 # update state
781 # update state
782 state['current'] = [node]
782 state['current'] = [node]
783 hbisect.save_state(repo, state)
783 hbisect.save_state(repo, state)
784 status = ui.system(command, environ={'HG_NODE': hex(node)})
784 status = ui.system(command, environ={'HG_NODE': hex(node)})
785 if status == 125:
785 if status == 125:
786 transition = "skip"
786 transition = "skip"
787 elif status == 0:
787 elif status == 0:
788 transition = "good"
788 transition = "good"
789 # status < 0 means process was killed
789 # status < 0 means process was killed
790 elif status == 127:
790 elif status == 127:
791 raise util.Abort(_("failed to execute %s") % command)
791 raise util.Abort(_("failed to execute %s") % command)
792 elif status < 0:
792 elif status < 0:
793 raise util.Abort(_("%s killed") % command)
793 raise util.Abort(_("%s killed") % command)
794 else:
794 else:
795 transition = "bad"
795 transition = "bad"
796 ctx = scmutil.revsingle(repo, rev, node)
796 ctx = scmutil.revsingle(repo, rev, node)
797 rev = None # clear for future iterations
797 rev = None # clear for future iterations
798 state[transition].append(ctx.node())
798 state[transition].append(ctx.node())
799 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
799 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
800 check_state(state, interactive=False)
800 check_state(state, interactive=False)
801 # bisect
801 # bisect
802 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
802 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
803 # update to next check
803 # update to next check
804 node = nodes[0]
804 node = nodes[0]
805 if not noupdate:
805 if not noupdate:
806 cmdutil.bailifchanged(repo)
806 cmdutil.bailifchanged(repo)
807 hg.clean(repo, node, show_stats=False)
807 hg.clean(repo, node, show_stats=False)
808 finally:
808 finally:
809 state['current'] = [node]
809 state['current'] = [node]
810 hbisect.save_state(repo, state)
810 hbisect.save_state(repo, state)
811 print_result(nodes, bgood)
811 print_result(nodes, bgood)
812 return
812 return
813
813
814 # update state
814 # update state
815
815
816 if rev:
816 if rev:
817 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
817 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
818 else:
818 else:
819 nodes = [repo.lookup('.')]
819 nodes = [repo.lookup('.')]
820
820
821 if good or bad or skip:
821 if good or bad or skip:
822 if good:
822 if good:
823 state['good'] += nodes
823 state['good'] += nodes
824 elif bad:
824 elif bad:
825 state['bad'] += nodes
825 state['bad'] += nodes
826 elif skip:
826 elif skip:
827 state['skip'] += nodes
827 state['skip'] += nodes
828 hbisect.save_state(repo, state)
828 hbisect.save_state(repo, state)
829
829
830 if not check_state(state):
830 if not check_state(state):
831 return
831 return
832
832
833 # actually bisect
833 # actually bisect
834 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
834 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
835 if extend:
835 if extend:
836 if not changesets:
836 if not changesets:
837 extendnode = extendbisectrange(nodes, good)
837 extendnode = extendbisectrange(nodes, good)
838 if extendnode is not None:
838 if extendnode is not None:
839 ui.write(_("Extending search to changeset %d:%s\n")
839 ui.write(_("Extending search to changeset %d:%s\n")
840 % (extendnode.rev(), extendnode))
840 % (extendnode.rev(), extendnode))
841 state['current'] = [extendnode.node()]
841 state['current'] = [extendnode.node()]
842 hbisect.save_state(repo, state)
842 hbisect.save_state(repo, state)
843 if noupdate:
843 if noupdate:
844 return
844 return
845 cmdutil.bailifchanged(repo)
845 cmdutil.bailifchanged(repo)
846 return hg.clean(repo, extendnode.node())
846 return hg.clean(repo, extendnode.node())
847 raise util.Abort(_("nothing to extend"))
847 raise util.Abort(_("nothing to extend"))
848
848
849 if changesets == 0:
849 if changesets == 0:
850 print_result(nodes, good)
850 print_result(nodes, good)
851 else:
851 else:
852 assert len(nodes) == 1 # only a single node can be tested next
852 assert len(nodes) == 1 # only a single node can be tested next
853 node = nodes[0]
853 node = nodes[0]
854 # compute the approximate number of remaining tests
854 # compute the approximate number of remaining tests
855 tests, size = 0, 2
855 tests, size = 0, 2
856 while size <= changesets:
856 while size <= changesets:
857 tests, size = tests + 1, size * 2
857 tests, size = tests + 1, size * 2
858 rev = repo.changelog.rev(node)
858 rev = repo.changelog.rev(node)
859 ui.write(_("Testing changeset %d:%s "
859 ui.write(_("Testing changeset %d:%s "
860 "(%d changesets remaining, ~%d tests)\n")
860 "(%d changesets remaining, ~%d tests)\n")
861 % (rev, short(node), changesets, tests))
861 % (rev, short(node), changesets, tests))
862 state['current'] = [node]
862 state['current'] = [node]
863 hbisect.save_state(repo, state)
863 hbisect.save_state(repo, state)
864 if not noupdate:
864 if not noupdate:
865 cmdutil.bailifchanged(repo)
865 cmdutil.bailifchanged(repo)
866 return hg.clean(repo, node)
866 return hg.clean(repo, node)
867
867
868 @command('bookmarks|bookmark',
868 @command('bookmarks|bookmark',
869 [('f', 'force', False, _('force')),
869 [('f', 'force', False, _('force')),
870 ('r', 'rev', '', _('revision'), _('REV')),
870 ('r', 'rev', '', _('revision'), _('REV')),
871 ('d', 'delete', False, _('delete a given bookmark')),
871 ('d', 'delete', False, _('delete a given bookmark')),
872 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
872 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
873 ('i', 'inactive', False, _('mark a bookmark inactive')),
873 ('i', 'inactive', False, _('mark a bookmark inactive')),
874 ] + formatteropts,
874 ] + formatteropts,
875 _('hg bookmarks [OPTIONS]... [NAME]...'))
875 _('hg bookmarks [OPTIONS]... [NAME]...'))
876 def bookmark(ui, repo, *names, **opts):
876 def bookmark(ui, repo, *names, **opts):
877 '''create a new bookmark or list existing bookmarks
877 '''create a new bookmark or list existing bookmarks
878
878
879 Bookmarks are labels on changesets to help track lines of development.
879 Bookmarks are labels on changesets to help track lines of development.
880 Bookmarks are unversioned and can be moved, renamed and deleted.
880 Bookmarks are unversioned and can be moved, renamed and deleted.
881 Deleting or moving a bookmark has no effect on the associated changesets.
881 Deleting or moving a bookmark has no effect on the associated changesets.
882
882
883 Creating or updating to a bookmark causes it to be marked as 'active'.
883 Creating or updating to a bookmark causes it to be marked as 'active'.
884 The active bookmark is indicated with a '*'.
884 The active bookmark is indicated with a '*'.
885 When a commit is made, the active bookmark will advance to the new commit.
885 When a commit is made, the active bookmark will advance to the new commit.
886 A plain :hg:`update` will also advance an active bookmark, if possible.
886 A plain :hg:`update` will also advance an active bookmark, if possible.
887 Updating away from a bookmark will cause it to be deactivated.
887 Updating away from a bookmark will cause it to be deactivated.
888
888
889 Bookmarks can be pushed and pulled between repositories (see
889 Bookmarks can be pushed and pulled between repositories (see
890 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
890 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
891 diverged, a new 'divergent bookmark' of the form 'name@path' will
891 diverged, a new 'divergent bookmark' of the form 'name@path' will
892 be created. Using :hg:`merge` will resolve the divergence.
892 be created. Using :hg:`merge` will resolve the divergence.
893
893
894 A bookmark named '@' has the special property that :hg:`clone` will
894 A bookmark named '@' has the special property that :hg:`clone` will
895 check it out by default if it exists.
895 check it out by default if it exists.
896
896
897 .. container:: verbose
897 .. container:: verbose
898
898
899 Examples:
899 Examples:
900
900
901 - create an active bookmark for a new line of development::
901 - create an active bookmark for a new line of development::
902
902
903 hg book new-feature
903 hg book new-feature
904
904
905 - create an inactive bookmark as a place marker::
905 - create an inactive bookmark as a place marker::
906
906
907 hg book -i reviewed
907 hg book -i reviewed
908
908
909 - create an inactive bookmark on another changeset::
909 - create an inactive bookmark on another changeset::
910
910
911 hg book -r .^ tested
911 hg book -r .^ tested
912
912
913 - move the '@' bookmark from another branch::
913 - move the '@' bookmark from another branch::
914
914
915 hg book -f @
915 hg book -f @
916 '''
916 '''
917 force = opts.get('force')
917 force = opts.get('force')
918 rev = opts.get('rev')
918 rev = opts.get('rev')
919 delete = opts.get('delete')
919 delete = opts.get('delete')
920 rename = opts.get('rename')
920 rename = opts.get('rename')
921 inactive = opts.get('inactive')
921 inactive = opts.get('inactive')
922
922
923 def checkformat(mark):
923 def checkformat(mark):
924 mark = mark.strip()
924 mark = mark.strip()
925 if not mark:
925 if not mark:
926 raise util.Abort(_("bookmark names cannot consist entirely of "
926 raise util.Abort(_("bookmark names cannot consist entirely of "
927 "whitespace"))
927 "whitespace"))
928 scmutil.checknewlabel(repo, mark, 'bookmark')
928 scmutil.checknewlabel(repo, mark, 'bookmark')
929 return mark
929 return mark
930
930
931 def checkconflict(repo, mark, cur, force=False, target=None):
931 def checkconflict(repo, mark, cur, force=False, target=None):
932 if mark in marks and not force:
932 if mark in marks and not force:
933 if target:
933 if target:
934 if marks[mark] == target and target == cur:
934 if marks[mark] == target and target == cur:
935 # re-activating a bookmark
935 # re-activating a bookmark
936 return
936 return
937 anc = repo.changelog.ancestors([repo[target].rev()])
937 anc = repo.changelog.ancestors([repo[target].rev()])
938 bmctx = repo[marks[mark]]
938 bmctx = repo[marks[mark]]
939 divs = [repo[b].node() for b in marks
939 divs = [repo[b].node() for b in marks
940 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
940 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
941
941
942 # allow resolving a single divergent bookmark even if moving
942 # allow resolving a single divergent bookmark even if moving
943 # the bookmark across branches when a revision is specified
943 # the bookmark across branches when a revision is specified
944 # that contains a divergent bookmark
944 # that contains a divergent bookmark
945 if bmctx.rev() not in anc and target in divs:
945 if bmctx.rev() not in anc and target in divs:
946 bookmarks.deletedivergent(repo, [target], mark)
946 bookmarks.deletedivergent(repo, [target], mark)
947 return
947 return
948
948
949 deletefrom = [b for b in divs
949 deletefrom = [b for b in divs
950 if repo[b].rev() in anc or b == target]
950 if repo[b].rev() in anc or b == target]
951 bookmarks.deletedivergent(repo, deletefrom, mark)
951 bookmarks.deletedivergent(repo, deletefrom, mark)
952 if bookmarks.validdest(repo, bmctx, repo[target]):
952 if bookmarks.validdest(repo, bmctx, repo[target]):
953 ui.status(_("moving bookmark '%s' forward from %s\n") %
953 ui.status(_("moving bookmark '%s' forward from %s\n") %
954 (mark, short(bmctx.node())))
954 (mark, short(bmctx.node())))
955 return
955 return
956 raise util.Abort(_("bookmark '%s' already exists "
956 raise util.Abort(_("bookmark '%s' already exists "
957 "(use -f to force)") % mark)
957 "(use -f to force)") % mark)
958 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
958 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
959 and not force):
959 and not force):
960 raise util.Abort(
960 raise util.Abort(
961 _("a bookmark cannot have the name of an existing branch"))
961 _("a bookmark cannot have the name of an existing branch"))
962
962
963 if delete and rename:
963 if delete and rename:
964 raise util.Abort(_("--delete and --rename are incompatible"))
964 raise util.Abort(_("--delete and --rename are incompatible"))
965 if delete and rev:
965 if delete and rev:
966 raise util.Abort(_("--rev is incompatible with --delete"))
966 raise util.Abort(_("--rev is incompatible with --delete"))
967 if rename and rev:
967 if rename and rev:
968 raise util.Abort(_("--rev is incompatible with --rename"))
968 raise util.Abort(_("--rev is incompatible with --rename"))
969 if not names and (delete or rev):
969 if not names and (delete or rev):
970 raise util.Abort(_("bookmark name required"))
970 raise util.Abort(_("bookmark name required"))
971
971
972 if delete or rename or names or inactive:
972 if delete or rename or names or inactive:
973 wlock = repo.wlock()
973 wlock = repo.wlock()
974 try:
974 try:
975 cur = repo.changectx('.').node()
975 cur = repo.changectx('.').node()
976 marks = repo._bookmarks
976 marks = repo._bookmarks
977 if delete:
977 if delete:
978 for mark in names:
978 for mark in names:
979 if mark not in marks:
979 if mark not in marks:
980 raise util.Abort(_("bookmark '%s' does not exist") %
980 raise util.Abort(_("bookmark '%s' does not exist") %
981 mark)
981 mark)
982 if mark == repo._activebookmark:
982 if mark == repo._activebookmark:
983 bookmarks.deactivate(repo)
983 bookmarks.deactivate(repo)
984 del marks[mark]
984 del marks[mark]
985 marks.write()
985 marks.write()
986
986
987 elif rename:
987 elif rename:
988 if not names:
988 if not names:
989 raise util.Abort(_("new bookmark name required"))
989 raise util.Abort(_("new bookmark name required"))
990 elif len(names) > 1:
990 elif len(names) > 1:
991 raise util.Abort(_("only one new bookmark name allowed"))
991 raise util.Abort(_("only one new bookmark name allowed"))
992 mark = checkformat(names[0])
992 mark = checkformat(names[0])
993 if rename not in marks:
993 if rename not in marks:
994 raise util.Abort(_("bookmark '%s' does not exist") % rename)
994 raise util.Abort(_("bookmark '%s' does not exist") % rename)
995 checkconflict(repo, mark, cur, force)
995 checkconflict(repo, mark, cur, force)
996 marks[mark] = marks[rename]
996 marks[mark] = marks[rename]
997 if repo._activebookmark == rename and not inactive:
997 if repo._activebookmark == rename and not inactive:
998 bookmarks.activate(repo, mark)
998 bookmarks.activate(repo, mark)
999 del marks[rename]
999 del marks[rename]
1000 marks.write()
1000 marks.write()
1001
1001
1002 elif names:
1002 elif names:
1003 newact = None
1003 newact = None
1004 for mark in names:
1004 for mark in names:
1005 mark = checkformat(mark)
1005 mark = checkformat(mark)
1006 if newact is None:
1006 if newact is None:
1007 newact = mark
1007 newact = mark
1008 if inactive and mark == repo._activebookmark:
1008 if inactive and mark == repo._activebookmark:
1009 bookmarks.deactivate(repo)
1009 bookmarks.deactivate(repo)
1010 return
1010 return
1011 tgt = cur
1011 tgt = cur
1012 if rev:
1012 if rev:
1013 tgt = scmutil.revsingle(repo, rev).node()
1013 tgt = scmutil.revsingle(repo, rev).node()
1014 checkconflict(repo, mark, cur, force, tgt)
1014 checkconflict(repo, mark, cur, force, tgt)
1015 marks[mark] = tgt
1015 marks[mark] = tgt
1016 if not inactive and cur == marks[newact] and not rev:
1016 if not inactive and cur == marks[newact] and not rev:
1017 bookmarks.activate(repo, newact)
1017 bookmarks.activate(repo, newact)
1018 elif cur != tgt and newact == repo._activebookmark:
1018 elif cur != tgt and newact == repo._activebookmark:
1019 bookmarks.deactivate(repo)
1019 bookmarks.deactivate(repo)
1020 marks.write()
1020 marks.write()
1021
1021
1022 elif inactive:
1022 elif inactive:
1023 if len(marks) == 0:
1023 if len(marks) == 0:
1024 ui.status(_("no bookmarks set\n"))
1024 ui.status(_("no bookmarks set\n"))
1025 elif not repo._activebookmark:
1025 elif not repo._activebookmark:
1026 ui.status(_("no active bookmark\n"))
1026 ui.status(_("no active bookmark\n"))
1027 else:
1027 else:
1028 bookmarks.deactivate(repo)
1028 bookmarks.deactivate(repo)
1029 finally:
1029 finally:
1030 wlock.release()
1030 wlock.release()
1031 else: # show bookmarks
1031 else: # show bookmarks
1032 fm = ui.formatter('bookmarks', opts)
1032 fm = ui.formatter('bookmarks', opts)
1033 hexfn = fm.hexfunc
1033 hexfn = fm.hexfunc
1034 marks = repo._bookmarks
1034 marks = repo._bookmarks
1035 if len(marks) == 0 and not fm:
1035 if len(marks) == 0 and not fm:
1036 ui.status(_("no bookmarks set\n"))
1036 ui.status(_("no bookmarks set\n"))
1037 for bmark, n in sorted(marks.iteritems()):
1037 for bmark, n in sorted(marks.iteritems()):
1038 current = repo._activebookmark
1038 current = repo._activebookmark
1039 if bmark == current:
1039 if bmark == current:
1040 prefix, label = '*', 'bookmarks.current'
1040 prefix, label = '*', 'bookmarks.current'
1041 else:
1041 else:
1042 prefix, label = ' ', ''
1042 prefix, label = ' ', ''
1043
1043
1044 fm.startitem()
1044 fm.startitem()
1045 if not ui.quiet:
1045 if not ui.quiet:
1046 fm.plain(' %s ' % prefix, label=label)
1046 fm.plain(' %s ' % prefix, label=label)
1047 fm.write('bookmark', '%s', bmark, label=label)
1047 fm.write('bookmark', '%s', bmark, label=label)
1048 pad = " " * (25 - encoding.colwidth(bmark))
1048 pad = " " * (25 - encoding.colwidth(bmark))
1049 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1049 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1050 repo.changelog.rev(n), hexfn(n), label=label)
1050 repo.changelog.rev(n), hexfn(n), label=label)
1051 fm.data(active=(bmark == current))
1051 fm.data(active=(bmark == current))
1052 fm.plain('\n')
1052 fm.plain('\n')
1053 fm.end()
1053 fm.end()
1054
1054
1055 @command('branch',
1055 @command('branch',
1056 [('f', 'force', None,
1056 [('f', 'force', None,
1057 _('set branch name even if it shadows an existing branch')),
1057 _('set branch name even if it shadows an existing branch')),
1058 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1058 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1059 _('[-fC] [NAME]'))
1059 _('[-fC] [NAME]'))
1060 def branch(ui, repo, label=None, **opts):
1060 def branch(ui, repo, label=None, **opts):
1061 """set or show the current branch name
1061 """set or show the current branch name
1062
1062
1063 .. note::
1063 .. note::
1064
1064
1065 Branch names are permanent and global. Use :hg:`bookmark` to create a
1065 Branch names are permanent and global. Use :hg:`bookmark` to create a
1066 light-weight bookmark instead. See :hg:`help glossary` for more
1066 light-weight bookmark instead. See :hg:`help glossary` for more
1067 information about named branches and bookmarks.
1067 information about named branches and bookmarks.
1068
1068
1069 With no argument, show the current branch name. With one argument,
1069 With no argument, show the current branch name. With one argument,
1070 set the working directory branch name (the branch will not exist
1070 set the working directory branch name (the branch will not exist
1071 in the repository until the next commit). Standard practice
1071 in the repository until the next commit). Standard practice
1072 recommends that primary development take place on the 'default'
1072 recommends that primary development take place on the 'default'
1073 branch.
1073 branch.
1074
1074
1075 Unless -f/--force is specified, branch will not let you set a
1075 Unless -f/--force is specified, branch will not let you set a
1076 branch name that already exists.
1076 branch name that already exists.
1077
1077
1078 Use -C/--clean to reset the working directory branch to that of
1078 Use -C/--clean to reset the working directory branch to that of
1079 the parent of the working directory, negating a previous branch
1079 the parent of the working directory, negating a previous branch
1080 change.
1080 change.
1081
1081
1082 Use the command :hg:`update` to switch to an existing branch. Use
1082 Use the command :hg:`update` to switch to an existing branch. Use
1083 :hg:`commit --close-branch` to mark this branch as closed.
1083 :hg:`commit --close-branch` to mark this branch head as closed.
1084 When all heads of the branch are closed, the branch will be
1085 considered closed.
1084
1086
1085 Returns 0 on success.
1087 Returns 0 on success.
1086 """
1088 """
1087 if label:
1089 if label:
1088 label = label.strip()
1090 label = label.strip()
1089
1091
1090 if not opts.get('clean') and not label:
1092 if not opts.get('clean') and not label:
1091 ui.write("%s\n" % repo.dirstate.branch())
1093 ui.write("%s\n" % repo.dirstate.branch())
1092 return
1094 return
1093
1095
1094 wlock = repo.wlock()
1096 wlock = repo.wlock()
1095 try:
1097 try:
1096 if opts.get('clean'):
1098 if opts.get('clean'):
1097 label = repo[None].p1().branch()
1099 label = repo[None].p1().branch()
1098 repo.dirstate.setbranch(label)
1100 repo.dirstate.setbranch(label)
1099 ui.status(_('reset working directory to branch %s\n') % label)
1101 ui.status(_('reset working directory to branch %s\n') % label)
1100 elif label:
1102 elif label:
1101 if not opts.get('force') and label in repo.branchmap():
1103 if not opts.get('force') and label in repo.branchmap():
1102 if label not in [p.branch() for p in repo.parents()]:
1104 if label not in [p.branch() for p in repo.parents()]:
1103 raise util.Abort(_('a branch of the same name already'
1105 raise util.Abort(_('a branch of the same name already'
1104 ' exists'),
1106 ' exists'),
1105 # i18n: "it" refers to an existing branch
1107 # i18n: "it" refers to an existing branch
1106 hint=_("use 'hg update' to switch to it"))
1108 hint=_("use 'hg update' to switch to it"))
1107 scmutil.checknewlabel(repo, label, 'branch')
1109 scmutil.checknewlabel(repo, label, 'branch')
1108 repo.dirstate.setbranch(label)
1110 repo.dirstate.setbranch(label)
1109 ui.status(_('marked working directory as branch %s\n') % label)
1111 ui.status(_('marked working directory as branch %s\n') % label)
1110
1112
1111 # find any open named branches aside from default
1113 # find any open named branches aside from default
1112 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1114 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1113 if n != "default" and not c]
1115 if n != "default" and not c]
1114 if not others:
1116 if not others:
1115 ui.status(_('(branches are permanent and global, '
1117 ui.status(_('(branches are permanent and global, '
1116 'did you want a bookmark?)\n'))
1118 'did you want a bookmark?)\n'))
1117 finally:
1119 finally:
1118 wlock.release()
1120 wlock.release()
1119
1121
1120 @command('branches',
1122 @command('branches',
1121 [('a', 'active', False,
1123 [('a', 'active', False,
1122 _('show only branches that have unmerged heads (DEPRECATED)')),
1124 _('show only branches that have unmerged heads (DEPRECATED)')),
1123 ('c', 'closed', False, _('show normal and closed branches')),
1125 ('c', 'closed', False, _('show normal and closed branches')),
1124 ] + formatteropts,
1126 ] + formatteropts,
1125 _('[-ac]'))
1127 _('[-ac]'))
1126 def branches(ui, repo, active=False, closed=False, **opts):
1128 def branches(ui, repo, active=False, closed=False, **opts):
1127 """list repository named branches
1129 """list repository named branches
1128
1130
1129 List the repository's named branches, indicating which ones are
1131 List the repository's named branches, indicating which ones are
1130 inactive. If -c/--closed is specified, also list branches which have
1132 inactive. If -c/--closed is specified, also list branches which have
1131 been marked closed (see :hg:`commit --close-branch`).
1133 been marked closed (see :hg:`commit --close-branch`).
1132
1134
1133 Use the command :hg:`update` to switch to an existing branch.
1135 Use the command :hg:`update` to switch to an existing branch.
1134
1136
1135 Returns 0.
1137 Returns 0.
1136 """
1138 """
1137
1139
1138 fm = ui.formatter('branches', opts)
1140 fm = ui.formatter('branches', opts)
1139 hexfunc = fm.hexfunc
1141 hexfunc = fm.hexfunc
1140
1142
1141 allheads = set(repo.heads())
1143 allheads = set(repo.heads())
1142 branches = []
1144 branches = []
1143 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1145 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1144 isactive = not isclosed and bool(set(heads) & allheads)
1146 isactive = not isclosed and bool(set(heads) & allheads)
1145 branches.append((tag, repo[tip], isactive, not isclosed))
1147 branches.append((tag, repo[tip], isactive, not isclosed))
1146 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1148 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1147 reverse=True)
1149 reverse=True)
1148
1150
1149 for tag, ctx, isactive, isopen in branches:
1151 for tag, ctx, isactive, isopen in branches:
1150 if active and not isactive:
1152 if active and not isactive:
1151 continue
1153 continue
1152 if isactive:
1154 if isactive:
1153 label = 'branches.active'
1155 label = 'branches.active'
1154 notice = ''
1156 notice = ''
1155 elif not isopen:
1157 elif not isopen:
1156 if not closed:
1158 if not closed:
1157 continue
1159 continue
1158 label = 'branches.closed'
1160 label = 'branches.closed'
1159 notice = _(' (closed)')
1161 notice = _(' (closed)')
1160 else:
1162 else:
1161 label = 'branches.inactive'
1163 label = 'branches.inactive'
1162 notice = _(' (inactive)')
1164 notice = _(' (inactive)')
1163 current = (tag == repo.dirstate.branch())
1165 current = (tag == repo.dirstate.branch())
1164 if current:
1166 if current:
1165 label = 'branches.current'
1167 label = 'branches.current'
1166
1168
1167 fm.startitem()
1169 fm.startitem()
1168 fm.write('branch', '%s', tag, label=label)
1170 fm.write('branch', '%s', tag, label=label)
1169 rev = ctx.rev()
1171 rev = ctx.rev()
1170 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1172 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1171 fmt = ' ' * padsize + ' %d:%s'
1173 fmt = ' ' * padsize + ' %d:%s'
1172 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1174 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1173 label='log.changeset changeset.%s' % ctx.phasestr())
1175 label='log.changeset changeset.%s' % ctx.phasestr())
1174 fm.data(active=isactive, closed=not isopen, current=current)
1176 fm.data(active=isactive, closed=not isopen, current=current)
1175 if not ui.quiet:
1177 if not ui.quiet:
1176 fm.plain(notice)
1178 fm.plain(notice)
1177 fm.plain('\n')
1179 fm.plain('\n')
1178 fm.end()
1180 fm.end()
1179
1181
1180 @command('bundle',
1182 @command('bundle',
1181 [('f', 'force', None, _('run even when the destination is unrelated')),
1183 [('f', 'force', None, _('run even when the destination is unrelated')),
1182 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1184 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1183 _('REV')),
1185 _('REV')),
1184 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1186 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1185 _('BRANCH')),
1187 _('BRANCH')),
1186 ('', 'base', [],
1188 ('', 'base', [],
1187 _('a base changeset assumed to be available at the destination'),
1189 _('a base changeset assumed to be available at the destination'),
1188 _('REV')),
1190 _('REV')),
1189 ('a', 'all', None, _('bundle all changesets in the repository')),
1191 ('a', 'all', None, _('bundle all changesets in the repository')),
1190 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1192 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1191 ] + remoteopts,
1193 ] + remoteopts,
1192 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1194 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1193 def bundle(ui, repo, fname, dest=None, **opts):
1195 def bundle(ui, repo, fname, dest=None, **opts):
1194 """create a changegroup file
1196 """create a changegroup file
1195
1197
1196 Generate a compressed changegroup file collecting changesets not
1198 Generate a compressed changegroup file collecting changesets not
1197 known to be in another repository.
1199 known to be in another repository.
1198
1200
1199 If you omit the destination repository, then hg assumes the
1201 If you omit the destination repository, then hg assumes the
1200 destination will have all the nodes you specify with --base
1202 destination will have all the nodes you specify with --base
1201 parameters. To create a bundle containing all changesets, use
1203 parameters. To create a bundle containing all changesets, use
1202 -a/--all (or --base null).
1204 -a/--all (or --base null).
1203
1205
1204 You can change compression method with the -t/--type option.
1206 You can change compression method with the -t/--type option.
1205 The available compression methods are: none, bzip2, and
1207 The available compression methods are: none, bzip2, and
1206 gzip (by default, bundles are compressed using bzip2).
1208 gzip (by default, bundles are compressed using bzip2).
1207
1209
1208 The bundle file can then be transferred using conventional means
1210 The bundle file can then be transferred using conventional means
1209 and applied to another repository with the unbundle or pull
1211 and applied to another repository with the unbundle or pull
1210 command. This is useful when direct push and pull are not
1212 command. This is useful when direct push and pull are not
1211 available or when exporting an entire repository is undesirable.
1213 available or when exporting an entire repository is undesirable.
1212
1214
1213 Applying bundles preserves all changeset contents including
1215 Applying bundles preserves all changeset contents including
1214 permissions, copy/rename information, and revision history.
1216 permissions, copy/rename information, and revision history.
1215
1217
1216 Returns 0 on success, 1 if no changes found.
1218 Returns 0 on success, 1 if no changes found.
1217 """
1219 """
1218 revs = None
1220 revs = None
1219 if 'rev' in opts:
1221 if 'rev' in opts:
1220 revs = scmutil.revrange(repo, opts['rev'])
1222 revs = scmutil.revrange(repo, opts['rev'])
1221
1223
1222 bundletype = opts.get('type', 'bzip2').lower()
1224 bundletype = opts.get('type', 'bzip2').lower()
1223 btypes = {'none': 'HG10UN',
1225 btypes = {'none': 'HG10UN',
1224 'bzip2': 'HG10BZ',
1226 'bzip2': 'HG10BZ',
1225 'gzip': 'HG10GZ',
1227 'gzip': 'HG10GZ',
1226 'bundle2': 'HG20'}
1228 'bundle2': 'HG20'}
1227 bundletype = btypes.get(bundletype)
1229 bundletype = btypes.get(bundletype)
1228 if bundletype not in changegroup.bundletypes:
1230 if bundletype not in changegroup.bundletypes:
1229 raise util.Abort(_('unknown bundle type specified with --type'))
1231 raise util.Abort(_('unknown bundle type specified with --type'))
1230
1232
1231 if opts.get('all'):
1233 if opts.get('all'):
1232 base = ['null']
1234 base = ['null']
1233 else:
1235 else:
1234 base = scmutil.revrange(repo, opts.get('base'))
1236 base = scmutil.revrange(repo, opts.get('base'))
1235 # TODO: get desired bundlecaps from command line.
1237 # TODO: get desired bundlecaps from command line.
1236 bundlecaps = None
1238 bundlecaps = None
1237 if base:
1239 if base:
1238 if dest:
1240 if dest:
1239 raise util.Abort(_("--base is incompatible with specifying "
1241 raise util.Abort(_("--base is incompatible with specifying "
1240 "a destination"))
1242 "a destination"))
1241 common = [repo.lookup(rev) for rev in base]
1243 common = [repo.lookup(rev) for rev in base]
1242 heads = revs and map(repo.lookup, revs) or revs
1244 heads = revs and map(repo.lookup, revs) or revs
1243 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1245 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1244 common=common, bundlecaps=bundlecaps)
1246 common=common, bundlecaps=bundlecaps)
1245 outgoing = None
1247 outgoing = None
1246 else:
1248 else:
1247 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1249 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1248 dest, branches = hg.parseurl(dest, opts.get('branch'))
1250 dest, branches = hg.parseurl(dest, opts.get('branch'))
1249 other = hg.peer(repo, opts, dest)
1251 other = hg.peer(repo, opts, dest)
1250 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1252 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1251 heads = revs and map(repo.lookup, revs) or revs
1253 heads = revs and map(repo.lookup, revs) or revs
1252 outgoing = discovery.findcommonoutgoing(repo, other,
1254 outgoing = discovery.findcommonoutgoing(repo, other,
1253 onlyheads=heads,
1255 onlyheads=heads,
1254 force=opts.get('force'),
1256 force=opts.get('force'),
1255 portable=True)
1257 portable=True)
1256 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1258 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1257 bundlecaps)
1259 bundlecaps)
1258 if not cg:
1260 if not cg:
1259 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1261 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1260 return 1
1262 return 1
1261
1263
1262 changegroup.writebundle(ui, cg, fname, bundletype)
1264 changegroup.writebundle(ui, cg, fname, bundletype)
1263
1265
1264 @command('cat',
1266 @command('cat',
1265 [('o', 'output', '',
1267 [('o', 'output', '',
1266 _('print output to file with formatted name'), _('FORMAT')),
1268 _('print output to file with formatted name'), _('FORMAT')),
1267 ('r', 'rev', '', _('print the given revision'), _('REV')),
1269 ('r', 'rev', '', _('print the given revision'), _('REV')),
1268 ('', 'decode', None, _('apply any matching decode filter')),
1270 ('', 'decode', None, _('apply any matching decode filter')),
1269 ] + walkopts,
1271 ] + walkopts,
1270 _('[OPTION]... FILE...'),
1272 _('[OPTION]... FILE...'),
1271 inferrepo=True)
1273 inferrepo=True)
1272 def cat(ui, repo, file1, *pats, **opts):
1274 def cat(ui, repo, file1, *pats, **opts):
1273 """output the current or given revision of files
1275 """output the current or given revision of files
1274
1276
1275 Print the specified files as they were at the given revision. If
1277 Print the specified files as they were at the given revision. If
1276 no revision is given, the parent of the working directory is used.
1278 no revision is given, the parent of the working directory is used.
1277
1279
1278 Output may be to a file, in which case the name of the file is
1280 Output may be to a file, in which case the name of the file is
1279 given using a format string. The formatting rules as follows:
1281 given using a format string. The formatting rules as follows:
1280
1282
1281 :``%%``: literal "%" character
1283 :``%%``: literal "%" character
1282 :``%s``: basename of file being printed
1284 :``%s``: basename of file being printed
1283 :``%d``: dirname of file being printed, or '.' if in repository root
1285 :``%d``: dirname of file being printed, or '.' if in repository root
1284 :``%p``: root-relative path name of file being printed
1286 :``%p``: root-relative path name of file being printed
1285 :``%H``: changeset hash (40 hexadecimal digits)
1287 :``%H``: changeset hash (40 hexadecimal digits)
1286 :``%R``: changeset revision number
1288 :``%R``: changeset revision number
1287 :``%h``: short-form changeset hash (12 hexadecimal digits)
1289 :``%h``: short-form changeset hash (12 hexadecimal digits)
1288 :``%r``: zero-padded changeset revision number
1290 :``%r``: zero-padded changeset revision number
1289 :``%b``: basename of the exporting repository
1291 :``%b``: basename of the exporting repository
1290
1292
1291 Returns 0 on success.
1293 Returns 0 on success.
1292 """
1294 """
1293 ctx = scmutil.revsingle(repo, opts.get('rev'))
1295 ctx = scmutil.revsingle(repo, opts.get('rev'))
1294 m = scmutil.match(ctx, (file1,) + pats, opts)
1296 m = scmutil.match(ctx, (file1,) + pats, opts)
1295
1297
1296 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1298 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1297
1299
1298 @command('^clone',
1300 @command('^clone',
1299 [('U', 'noupdate', None, _('the clone will include an empty working '
1301 [('U', 'noupdate', None, _('the clone will include an empty working '
1300 'directory (only a repository)')),
1302 'directory (only a repository)')),
1301 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1303 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1302 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1304 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1303 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1305 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1304 ('', 'pull', None, _('use pull protocol to copy metadata')),
1306 ('', 'pull', None, _('use pull protocol to copy metadata')),
1305 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1307 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1306 ] + remoteopts,
1308 ] + remoteopts,
1307 _('[OPTION]... SOURCE [DEST]'),
1309 _('[OPTION]... SOURCE [DEST]'),
1308 norepo=True)
1310 norepo=True)
1309 def clone(ui, source, dest=None, **opts):
1311 def clone(ui, source, dest=None, **opts):
1310 """make a copy of an existing repository
1312 """make a copy of an existing repository
1311
1313
1312 Create a copy of an existing repository in a new directory.
1314 Create a copy of an existing repository in a new directory.
1313
1315
1314 If no destination directory name is specified, it defaults to the
1316 If no destination directory name is specified, it defaults to the
1315 basename of the source.
1317 basename of the source.
1316
1318
1317 The location of the source is added to the new repository's
1319 The location of the source is added to the new repository's
1318 ``.hg/hgrc`` file, as the default to be used for future pulls.
1320 ``.hg/hgrc`` file, as the default to be used for future pulls.
1319
1321
1320 Only local paths and ``ssh://`` URLs are supported as
1322 Only local paths and ``ssh://`` URLs are supported as
1321 destinations. For ``ssh://`` destinations, no working directory or
1323 destinations. For ``ssh://`` destinations, no working directory or
1322 ``.hg/hgrc`` will be created on the remote side.
1324 ``.hg/hgrc`` will be created on the remote side.
1323
1325
1324 To pull only a subset of changesets, specify one or more revisions
1326 To pull only a subset of changesets, specify one or more revisions
1325 identifiers with -r/--rev or branches with -b/--branch. The
1327 identifiers with -r/--rev or branches with -b/--branch. The
1326 resulting clone will contain only the specified changesets and
1328 resulting clone will contain only the specified changesets and
1327 their ancestors. These options (or 'clone src#rev dest') imply
1329 their ancestors. These options (or 'clone src#rev dest') imply
1328 --pull, even for local source repositories. Note that specifying a
1330 --pull, even for local source repositories. Note that specifying a
1329 tag will include the tagged changeset but not the changeset
1331 tag will include the tagged changeset but not the changeset
1330 containing the tag.
1332 containing the tag.
1331
1333
1332 If the source repository has a bookmark called '@' set, that
1334 If the source repository has a bookmark called '@' set, that
1333 revision will be checked out in the new repository by default.
1335 revision will be checked out in the new repository by default.
1334
1336
1335 To check out a particular version, use -u/--update, or
1337 To check out a particular version, use -u/--update, or
1336 -U/--noupdate to create a clone with no working directory.
1338 -U/--noupdate to create a clone with no working directory.
1337
1339
1338 .. container:: verbose
1340 .. container:: verbose
1339
1341
1340 For efficiency, hardlinks are used for cloning whenever the
1342 For efficiency, hardlinks are used for cloning whenever the
1341 source and destination are on the same filesystem (note this
1343 source and destination are on the same filesystem (note this
1342 applies only to the repository data, not to the working
1344 applies only to the repository data, not to the working
1343 directory). Some filesystems, such as AFS, implement hardlinking
1345 directory). Some filesystems, such as AFS, implement hardlinking
1344 incorrectly, but do not report errors. In these cases, use the
1346 incorrectly, but do not report errors. In these cases, use the
1345 --pull option to avoid hardlinking.
1347 --pull option to avoid hardlinking.
1346
1348
1347 In some cases, you can clone repositories and the working
1349 In some cases, you can clone repositories and the working
1348 directory using full hardlinks with ::
1350 directory using full hardlinks with ::
1349
1351
1350 $ cp -al REPO REPOCLONE
1352 $ cp -al REPO REPOCLONE
1351
1353
1352 This is the fastest way to clone, but it is not always safe. The
1354 This is the fastest way to clone, but it is not always safe. The
1353 operation is not atomic (making sure REPO is not modified during
1355 operation is not atomic (making sure REPO is not modified during
1354 the operation is up to you) and you have to make sure your
1356 the operation is up to you) and you have to make sure your
1355 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1357 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1356 so). Also, this is not compatible with certain extensions that
1358 so). Also, this is not compatible with certain extensions that
1357 place their metadata under the .hg directory, such as mq.
1359 place their metadata under the .hg directory, such as mq.
1358
1360
1359 Mercurial will update the working directory to the first applicable
1361 Mercurial will update the working directory to the first applicable
1360 revision from this list:
1362 revision from this list:
1361
1363
1362 a) null if -U or the source repository has no changesets
1364 a) null if -U or the source repository has no changesets
1363 b) if -u . and the source repository is local, the first parent of
1365 b) if -u . and the source repository is local, the first parent of
1364 the source repository's working directory
1366 the source repository's working directory
1365 c) the changeset specified with -u (if a branch name, this means the
1367 c) the changeset specified with -u (if a branch name, this means the
1366 latest head of that branch)
1368 latest head of that branch)
1367 d) the changeset specified with -r
1369 d) the changeset specified with -r
1368 e) the tipmost head specified with -b
1370 e) the tipmost head specified with -b
1369 f) the tipmost head specified with the url#branch source syntax
1371 f) the tipmost head specified with the url#branch source syntax
1370 g) the revision marked with the '@' bookmark, if present
1372 g) the revision marked with the '@' bookmark, if present
1371 h) the tipmost head of the default branch
1373 h) the tipmost head of the default branch
1372 i) tip
1374 i) tip
1373
1375
1374 Examples:
1376 Examples:
1375
1377
1376 - clone a remote repository to a new directory named hg/::
1378 - clone a remote repository to a new directory named hg/::
1377
1379
1378 hg clone http://selenic.com/hg
1380 hg clone http://selenic.com/hg
1379
1381
1380 - create a lightweight local clone::
1382 - create a lightweight local clone::
1381
1383
1382 hg clone project/ project-feature/
1384 hg clone project/ project-feature/
1383
1385
1384 - clone from an absolute path on an ssh server (note double-slash)::
1386 - clone from an absolute path on an ssh server (note double-slash)::
1385
1387
1386 hg clone ssh://user@server//home/projects/alpha/
1388 hg clone ssh://user@server//home/projects/alpha/
1387
1389
1388 - do a high-speed clone over a LAN while checking out a
1390 - do a high-speed clone over a LAN while checking out a
1389 specified version::
1391 specified version::
1390
1392
1391 hg clone --uncompressed http://server/repo -u 1.5
1393 hg clone --uncompressed http://server/repo -u 1.5
1392
1394
1393 - create a repository without changesets after a particular revision::
1395 - create a repository without changesets after a particular revision::
1394
1396
1395 hg clone -r 04e544 experimental/ good/
1397 hg clone -r 04e544 experimental/ good/
1396
1398
1397 - clone (and track) a particular named branch::
1399 - clone (and track) a particular named branch::
1398
1400
1399 hg clone http://selenic.com/hg#stable
1401 hg clone http://selenic.com/hg#stable
1400
1402
1401 See :hg:`help urls` for details on specifying URLs.
1403 See :hg:`help urls` for details on specifying URLs.
1402
1404
1403 Returns 0 on success.
1405 Returns 0 on success.
1404 """
1406 """
1405 if opts.get('noupdate') and opts.get('updaterev'):
1407 if opts.get('noupdate') and opts.get('updaterev'):
1406 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1408 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1407
1409
1408 r = hg.clone(ui, opts, source, dest,
1410 r = hg.clone(ui, opts, source, dest,
1409 pull=opts.get('pull'),
1411 pull=opts.get('pull'),
1410 stream=opts.get('uncompressed'),
1412 stream=opts.get('uncompressed'),
1411 rev=opts.get('rev'),
1413 rev=opts.get('rev'),
1412 update=opts.get('updaterev') or not opts.get('noupdate'),
1414 update=opts.get('updaterev') or not opts.get('noupdate'),
1413 branch=opts.get('branch'))
1415 branch=opts.get('branch'))
1414
1416
1415 return r is None
1417 return r is None
1416
1418
1417 @command('^commit|ci',
1419 @command('^commit|ci',
1418 [('A', 'addremove', None,
1420 [('A', 'addremove', None,
1419 _('mark new/missing files as added/removed before committing')),
1421 _('mark new/missing files as added/removed before committing')),
1420 ('', 'close-branch', None,
1422 ('', 'close-branch', None,
1421 _('mark a branch as closed, hiding it from the branch list')),
1423 _('mark a branch head as closed')),
1422 ('', 'amend', None, _('amend the parent of the working directory')),
1424 ('', 'amend', None, _('amend the parent of the working directory')),
1423 ('s', 'secret', None, _('use the secret phase for committing')),
1425 ('s', 'secret', None, _('use the secret phase for committing')),
1424 ('e', 'edit', None, _('invoke editor on commit messages')),
1426 ('e', 'edit', None, _('invoke editor on commit messages')),
1425 ('i', 'interactive', None, _('use interactive mode')),
1427 ('i', 'interactive', None, _('use interactive mode')),
1426 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1428 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1427 _('[OPTION]... [FILE]...'),
1429 _('[OPTION]... [FILE]...'),
1428 inferrepo=True)
1430 inferrepo=True)
1429 def commit(ui, repo, *pats, **opts):
1431 def commit(ui, repo, *pats, **opts):
1430 """commit the specified files or all outstanding changes
1432 """commit the specified files or all outstanding changes
1431
1433
1432 Commit changes to the given files into the repository. Unlike a
1434 Commit changes to the given files into the repository. Unlike a
1433 centralized SCM, this operation is a local operation. See
1435 centralized SCM, this operation is a local operation. See
1434 :hg:`push` for a way to actively distribute your changes.
1436 :hg:`push` for a way to actively distribute your changes.
1435
1437
1436 If a list of files is omitted, all changes reported by :hg:`status`
1438 If a list of files is omitted, all changes reported by :hg:`status`
1437 will be committed.
1439 will be committed.
1438
1440
1439 If you are committing the result of a merge, do not provide any
1441 If you are committing the result of a merge, do not provide any
1440 filenames or -I/-X filters.
1442 filenames or -I/-X filters.
1441
1443
1442 If no commit message is specified, Mercurial starts your
1444 If no commit message is specified, Mercurial starts your
1443 configured editor where you can enter a message. In case your
1445 configured editor where you can enter a message. In case your
1444 commit fails, you will find a backup of your message in
1446 commit fails, you will find a backup of your message in
1445 ``.hg/last-message.txt``.
1447 ``.hg/last-message.txt``.
1446
1448
1449 The --close-branch flag can be used to mark the current branch
1450 head closed. When all heads of a branch are closed, the branch
1451 will be considered closed and no longer listed.
1452
1447 The --amend flag can be used to amend the parent of the
1453 The --amend flag can be used to amend the parent of the
1448 working directory with a new commit that contains the changes
1454 working directory with a new commit that contains the changes
1449 in the parent in addition to those currently reported by :hg:`status`,
1455 in the parent in addition to those currently reported by :hg:`status`,
1450 if there are any. The old commit is stored in a backup bundle in
1456 if there are any. The old commit is stored in a backup bundle in
1451 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1457 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1452 on how to restore it).
1458 on how to restore it).
1453
1459
1454 Message, user and date are taken from the amended commit unless
1460 Message, user and date are taken from the amended commit unless
1455 specified. When a message isn't specified on the command line,
1461 specified. When a message isn't specified on the command line,
1456 the editor will open with the message of the amended commit.
1462 the editor will open with the message of the amended commit.
1457
1463
1458 It is not possible to amend public changesets (see :hg:`help phases`)
1464 It is not possible to amend public changesets (see :hg:`help phases`)
1459 or changesets that have children.
1465 or changesets that have children.
1460
1466
1461 See :hg:`help dates` for a list of formats valid for -d/--date.
1467 See :hg:`help dates` for a list of formats valid for -d/--date.
1462
1468
1463 Returns 0 on success, 1 if nothing changed.
1469 Returns 0 on success, 1 if nothing changed.
1464 """
1470 """
1465 if opts.get('interactive'):
1471 if opts.get('interactive'):
1466 opts.pop('interactive')
1472 opts.pop('interactive')
1467 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1473 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1468 cmdutil.recordfilter, *pats, **opts)
1474 cmdutil.recordfilter, *pats, **opts)
1469 return
1475 return
1470
1476
1471 if opts.get('subrepos'):
1477 if opts.get('subrepos'):
1472 if opts.get('amend'):
1478 if opts.get('amend'):
1473 raise util.Abort(_('cannot amend with --subrepos'))
1479 raise util.Abort(_('cannot amend with --subrepos'))
1474 # Let --subrepos on the command line override config setting.
1480 # Let --subrepos on the command line override config setting.
1475 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1481 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1476
1482
1477 cmdutil.checkunfinished(repo, commit=True)
1483 cmdutil.checkunfinished(repo, commit=True)
1478
1484
1479 branch = repo[None].branch()
1485 branch = repo[None].branch()
1480 bheads = repo.branchheads(branch)
1486 bheads = repo.branchheads(branch)
1481
1487
1482 extra = {}
1488 extra = {}
1483 if opts.get('close_branch'):
1489 if opts.get('close_branch'):
1484 extra['close'] = 1
1490 extra['close'] = 1
1485
1491
1486 if not bheads:
1492 if not bheads:
1487 raise util.Abort(_('can only close branch heads'))
1493 raise util.Abort(_('can only close branch heads'))
1488 elif opts.get('amend'):
1494 elif opts.get('amend'):
1489 if repo.parents()[0].p1().branch() != branch and \
1495 if repo.parents()[0].p1().branch() != branch and \
1490 repo.parents()[0].p2().branch() != branch:
1496 repo.parents()[0].p2().branch() != branch:
1491 raise util.Abort(_('can only close branch heads'))
1497 raise util.Abort(_('can only close branch heads'))
1492
1498
1493 if opts.get('amend'):
1499 if opts.get('amend'):
1494 if ui.configbool('ui', 'commitsubrepos'):
1500 if ui.configbool('ui', 'commitsubrepos'):
1495 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1501 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1496
1502
1497 old = repo['.']
1503 old = repo['.']
1498 if not old.mutable():
1504 if not old.mutable():
1499 raise util.Abort(_('cannot amend public changesets'))
1505 raise util.Abort(_('cannot amend public changesets'))
1500 if len(repo[None].parents()) > 1:
1506 if len(repo[None].parents()) > 1:
1501 raise util.Abort(_('cannot amend while merging'))
1507 raise util.Abort(_('cannot amend while merging'))
1502 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1508 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1503 if not allowunstable and old.children():
1509 if not allowunstable and old.children():
1504 raise util.Abort(_('cannot amend changeset with children'))
1510 raise util.Abort(_('cannot amend changeset with children'))
1505
1511
1506 # commitfunc is used only for temporary amend commit by cmdutil.amend
1512 # commitfunc is used only for temporary amend commit by cmdutil.amend
1507 def commitfunc(ui, repo, message, match, opts):
1513 def commitfunc(ui, repo, message, match, opts):
1508 return repo.commit(message,
1514 return repo.commit(message,
1509 opts.get('user') or old.user(),
1515 opts.get('user') or old.user(),
1510 opts.get('date') or old.date(),
1516 opts.get('date') or old.date(),
1511 match,
1517 match,
1512 extra=extra)
1518 extra=extra)
1513
1519
1514 current = repo._activebookmark
1520 current = repo._activebookmark
1515 marks = old.bookmarks()
1521 marks = old.bookmarks()
1516 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1522 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1517 if node == old.node():
1523 if node == old.node():
1518 ui.status(_("nothing changed\n"))
1524 ui.status(_("nothing changed\n"))
1519 return 1
1525 return 1
1520 elif marks:
1526 elif marks:
1521 ui.debug('moving bookmarks %r from %s to %s\n' %
1527 ui.debug('moving bookmarks %r from %s to %s\n' %
1522 (marks, old.hex(), hex(node)))
1528 (marks, old.hex(), hex(node)))
1523 newmarks = repo._bookmarks
1529 newmarks = repo._bookmarks
1524 for bm in marks:
1530 for bm in marks:
1525 newmarks[bm] = node
1531 newmarks[bm] = node
1526 if bm == current:
1532 if bm == current:
1527 bookmarks.activate(repo, bm)
1533 bookmarks.activate(repo, bm)
1528 newmarks.write()
1534 newmarks.write()
1529 else:
1535 else:
1530 def commitfunc(ui, repo, message, match, opts):
1536 def commitfunc(ui, repo, message, match, opts):
1531 backup = ui.backupconfig('phases', 'new-commit')
1537 backup = ui.backupconfig('phases', 'new-commit')
1532 baseui = repo.baseui
1538 baseui = repo.baseui
1533 basebackup = baseui.backupconfig('phases', 'new-commit')
1539 basebackup = baseui.backupconfig('phases', 'new-commit')
1534 try:
1540 try:
1535 if opts.get('secret'):
1541 if opts.get('secret'):
1536 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1542 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1537 # Propagate to subrepos
1543 # Propagate to subrepos
1538 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1544 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1539
1545
1540 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1546 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1541 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1547 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1542 return repo.commit(message, opts.get('user'), opts.get('date'),
1548 return repo.commit(message, opts.get('user'), opts.get('date'),
1543 match,
1549 match,
1544 editor=editor,
1550 editor=editor,
1545 extra=extra)
1551 extra=extra)
1546 finally:
1552 finally:
1547 ui.restoreconfig(backup)
1553 ui.restoreconfig(backup)
1548 repo.baseui.restoreconfig(basebackup)
1554 repo.baseui.restoreconfig(basebackup)
1549
1555
1550
1556
1551 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1557 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1552
1558
1553 if not node:
1559 if not node:
1554 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1560 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1555 if stat[3]:
1561 if stat[3]:
1556 ui.status(_("nothing changed (%d missing files, see "
1562 ui.status(_("nothing changed (%d missing files, see "
1557 "'hg status')\n") % len(stat[3]))
1563 "'hg status')\n") % len(stat[3]))
1558 else:
1564 else:
1559 ui.status(_("nothing changed\n"))
1565 ui.status(_("nothing changed\n"))
1560 return 1
1566 return 1
1561
1567
1562 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1568 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1563
1569
1564 @command('config|showconfig|debugconfig',
1570 @command('config|showconfig|debugconfig',
1565 [('u', 'untrusted', None, _('show untrusted configuration options')),
1571 [('u', 'untrusted', None, _('show untrusted configuration options')),
1566 ('e', 'edit', None, _('edit user config')),
1572 ('e', 'edit', None, _('edit user config')),
1567 ('l', 'local', None, _('edit repository config')),
1573 ('l', 'local', None, _('edit repository config')),
1568 ('g', 'global', None, _('edit global config'))],
1574 ('g', 'global', None, _('edit global config'))],
1569 _('[-u] [NAME]...'),
1575 _('[-u] [NAME]...'),
1570 optionalrepo=True)
1576 optionalrepo=True)
1571 def config(ui, repo, *values, **opts):
1577 def config(ui, repo, *values, **opts):
1572 """show combined config settings from all hgrc files
1578 """show combined config settings from all hgrc files
1573
1579
1574 With no arguments, print names and values of all config items.
1580 With no arguments, print names and values of all config items.
1575
1581
1576 With one argument of the form section.name, print just the value
1582 With one argument of the form section.name, print just the value
1577 of that config item.
1583 of that config item.
1578
1584
1579 With multiple arguments, print names and values of all config
1585 With multiple arguments, print names and values of all config
1580 items with matching section names.
1586 items with matching section names.
1581
1587
1582 With --edit, start an editor on the user-level config file. With
1588 With --edit, start an editor on the user-level config file. With
1583 --global, edit the system-wide config file. With --local, edit the
1589 --global, edit the system-wide config file. With --local, edit the
1584 repository-level config file.
1590 repository-level config file.
1585
1591
1586 With --debug, the source (filename and line number) is printed
1592 With --debug, the source (filename and line number) is printed
1587 for each config item.
1593 for each config item.
1588
1594
1589 See :hg:`help config` for more information about config files.
1595 See :hg:`help config` for more information about config files.
1590
1596
1591 Returns 0 on success, 1 if NAME does not exist.
1597 Returns 0 on success, 1 if NAME does not exist.
1592
1598
1593 """
1599 """
1594
1600
1595 if opts.get('edit') or opts.get('local') or opts.get('global'):
1601 if opts.get('edit') or opts.get('local') or opts.get('global'):
1596 if opts.get('local') and opts.get('global'):
1602 if opts.get('local') and opts.get('global'):
1597 raise util.Abort(_("can't use --local and --global together"))
1603 raise util.Abort(_("can't use --local and --global together"))
1598
1604
1599 if opts.get('local'):
1605 if opts.get('local'):
1600 if not repo:
1606 if not repo:
1601 raise util.Abort(_("can't use --local outside a repository"))
1607 raise util.Abort(_("can't use --local outside a repository"))
1602 paths = [repo.join('hgrc')]
1608 paths = [repo.join('hgrc')]
1603 elif opts.get('global'):
1609 elif opts.get('global'):
1604 paths = scmutil.systemrcpath()
1610 paths = scmutil.systemrcpath()
1605 else:
1611 else:
1606 paths = scmutil.userrcpath()
1612 paths = scmutil.userrcpath()
1607
1613
1608 for f in paths:
1614 for f in paths:
1609 if os.path.exists(f):
1615 if os.path.exists(f):
1610 break
1616 break
1611 else:
1617 else:
1612 if opts.get('global'):
1618 if opts.get('global'):
1613 samplehgrc = uimod.samplehgrcs['global']
1619 samplehgrc = uimod.samplehgrcs['global']
1614 elif opts.get('local'):
1620 elif opts.get('local'):
1615 samplehgrc = uimod.samplehgrcs['local']
1621 samplehgrc = uimod.samplehgrcs['local']
1616 else:
1622 else:
1617 samplehgrc = uimod.samplehgrcs['user']
1623 samplehgrc = uimod.samplehgrcs['user']
1618
1624
1619 f = paths[0]
1625 f = paths[0]
1620 fp = open(f, "w")
1626 fp = open(f, "w")
1621 fp.write(samplehgrc)
1627 fp.write(samplehgrc)
1622 fp.close()
1628 fp.close()
1623
1629
1624 editor = ui.geteditor()
1630 editor = ui.geteditor()
1625 ui.system("%s \"%s\"" % (editor, f),
1631 ui.system("%s \"%s\"" % (editor, f),
1626 onerr=util.Abort, errprefix=_("edit failed"))
1632 onerr=util.Abort, errprefix=_("edit failed"))
1627 return
1633 return
1628
1634
1629 for f in scmutil.rcpath():
1635 for f in scmutil.rcpath():
1630 ui.debug('read config from: %s\n' % f)
1636 ui.debug('read config from: %s\n' % f)
1631 untrusted = bool(opts.get('untrusted'))
1637 untrusted = bool(opts.get('untrusted'))
1632 if values:
1638 if values:
1633 sections = [v for v in values if '.' not in v]
1639 sections = [v for v in values if '.' not in v]
1634 items = [v for v in values if '.' in v]
1640 items = [v for v in values if '.' in v]
1635 if len(items) > 1 or items and sections:
1641 if len(items) > 1 or items and sections:
1636 raise util.Abort(_('only one config item permitted'))
1642 raise util.Abort(_('only one config item permitted'))
1637 matched = False
1643 matched = False
1638 for section, name, value in ui.walkconfig(untrusted=untrusted):
1644 for section, name, value in ui.walkconfig(untrusted=untrusted):
1639 value = str(value).replace('\n', '\\n')
1645 value = str(value).replace('\n', '\\n')
1640 sectname = section + '.' + name
1646 sectname = section + '.' + name
1641 if values:
1647 if values:
1642 for v in values:
1648 for v in values:
1643 if v == section:
1649 if v == section:
1644 ui.debug('%s: ' %
1650 ui.debug('%s: ' %
1645 ui.configsource(section, name, untrusted))
1651 ui.configsource(section, name, untrusted))
1646 ui.write('%s=%s\n' % (sectname, value))
1652 ui.write('%s=%s\n' % (sectname, value))
1647 matched = True
1653 matched = True
1648 elif v == sectname:
1654 elif v == sectname:
1649 ui.debug('%s: ' %
1655 ui.debug('%s: ' %
1650 ui.configsource(section, name, untrusted))
1656 ui.configsource(section, name, untrusted))
1651 ui.write(value, '\n')
1657 ui.write(value, '\n')
1652 matched = True
1658 matched = True
1653 else:
1659 else:
1654 ui.debug('%s: ' %
1660 ui.debug('%s: ' %
1655 ui.configsource(section, name, untrusted))
1661 ui.configsource(section, name, untrusted))
1656 ui.write('%s=%s\n' % (sectname, value))
1662 ui.write('%s=%s\n' % (sectname, value))
1657 matched = True
1663 matched = True
1658 if matched:
1664 if matched:
1659 return 0
1665 return 0
1660 return 1
1666 return 1
1661
1667
1662 @command('copy|cp',
1668 @command('copy|cp',
1663 [('A', 'after', None, _('record a copy that has already occurred')),
1669 [('A', 'after', None, _('record a copy that has already occurred')),
1664 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1670 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1665 ] + walkopts + dryrunopts,
1671 ] + walkopts + dryrunopts,
1666 _('[OPTION]... [SOURCE]... DEST'))
1672 _('[OPTION]... [SOURCE]... DEST'))
1667 def copy(ui, repo, *pats, **opts):
1673 def copy(ui, repo, *pats, **opts):
1668 """mark files as copied for the next commit
1674 """mark files as copied for the next commit
1669
1675
1670 Mark dest as having copies of source files. If dest is a
1676 Mark dest as having copies of source files. If dest is a
1671 directory, copies are put in that directory. If dest is a file,
1677 directory, copies are put in that directory. If dest is a file,
1672 the source must be a single file.
1678 the source must be a single file.
1673
1679
1674 By default, this command copies the contents of files as they
1680 By default, this command copies the contents of files as they
1675 exist in the working directory. If invoked with -A/--after, the
1681 exist in the working directory. If invoked with -A/--after, the
1676 operation is recorded, but no copying is performed.
1682 operation is recorded, but no copying is performed.
1677
1683
1678 This command takes effect with the next commit. To undo a copy
1684 This command takes effect with the next commit. To undo a copy
1679 before that, see :hg:`revert`.
1685 before that, see :hg:`revert`.
1680
1686
1681 Returns 0 on success, 1 if errors are encountered.
1687 Returns 0 on success, 1 if errors are encountered.
1682 """
1688 """
1683 wlock = repo.wlock(False)
1689 wlock = repo.wlock(False)
1684 try:
1690 try:
1685 return cmdutil.copy(ui, repo, pats, opts)
1691 return cmdutil.copy(ui, repo, pats, opts)
1686 finally:
1692 finally:
1687 wlock.release()
1693 wlock.release()
1688
1694
1689 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1695 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1690 def debugancestor(ui, repo, *args):
1696 def debugancestor(ui, repo, *args):
1691 """find the ancestor revision of two revisions in a given index"""
1697 """find the ancestor revision of two revisions in a given index"""
1692 if len(args) == 3:
1698 if len(args) == 3:
1693 index, rev1, rev2 = args
1699 index, rev1, rev2 = args
1694 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1700 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1695 lookup = r.lookup
1701 lookup = r.lookup
1696 elif len(args) == 2:
1702 elif len(args) == 2:
1697 if not repo:
1703 if not repo:
1698 raise util.Abort(_("there is no Mercurial repository here "
1704 raise util.Abort(_("there is no Mercurial repository here "
1699 "(.hg not found)"))
1705 "(.hg not found)"))
1700 rev1, rev2 = args
1706 rev1, rev2 = args
1701 r = repo.changelog
1707 r = repo.changelog
1702 lookup = repo.lookup
1708 lookup = repo.lookup
1703 else:
1709 else:
1704 raise util.Abort(_('either two or three arguments required'))
1710 raise util.Abort(_('either two or three arguments required'))
1705 a = r.ancestor(lookup(rev1), lookup(rev2))
1711 a = r.ancestor(lookup(rev1), lookup(rev2))
1706 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1712 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1707
1713
1708 @command('debugbuilddag',
1714 @command('debugbuilddag',
1709 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1715 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1710 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1716 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1711 ('n', 'new-file', None, _('add new file at each rev'))],
1717 ('n', 'new-file', None, _('add new file at each rev'))],
1712 _('[OPTION]... [TEXT]'))
1718 _('[OPTION]... [TEXT]'))
1713 def debugbuilddag(ui, repo, text=None,
1719 def debugbuilddag(ui, repo, text=None,
1714 mergeable_file=False,
1720 mergeable_file=False,
1715 overwritten_file=False,
1721 overwritten_file=False,
1716 new_file=False):
1722 new_file=False):
1717 """builds a repo with a given DAG from scratch in the current empty repo
1723 """builds a repo with a given DAG from scratch in the current empty repo
1718
1724
1719 The description of the DAG is read from stdin if not given on the
1725 The description of the DAG is read from stdin if not given on the
1720 command line.
1726 command line.
1721
1727
1722 Elements:
1728 Elements:
1723
1729
1724 - "+n" is a linear run of n nodes based on the current default parent
1730 - "+n" is a linear run of n nodes based on the current default parent
1725 - "." is a single node based on the current default parent
1731 - "." is a single node based on the current default parent
1726 - "$" resets the default parent to null (implied at the start);
1732 - "$" resets the default parent to null (implied at the start);
1727 otherwise the default parent is always the last node created
1733 otherwise the default parent is always the last node created
1728 - "<p" sets the default parent to the backref p
1734 - "<p" sets the default parent to the backref p
1729 - "*p" is a fork at parent p, which is a backref
1735 - "*p" is a fork at parent p, which is a backref
1730 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1736 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1731 - "/p2" is a merge of the preceding node and p2
1737 - "/p2" is a merge of the preceding node and p2
1732 - ":tag" defines a local tag for the preceding node
1738 - ":tag" defines a local tag for the preceding node
1733 - "@branch" sets the named branch for subsequent nodes
1739 - "@branch" sets the named branch for subsequent nodes
1734 - "#...\\n" is a comment up to the end of the line
1740 - "#...\\n" is a comment up to the end of the line
1735
1741
1736 Whitespace between the above elements is ignored.
1742 Whitespace between the above elements is ignored.
1737
1743
1738 A backref is either
1744 A backref is either
1739
1745
1740 - a number n, which references the node curr-n, where curr is the current
1746 - a number n, which references the node curr-n, where curr is the current
1741 node, or
1747 node, or
1742 - the name of a local tag you placed earlier using ":tag", or
1748 - the name of a local tag you placed earlier using ":tag", or
1743 - empty to denote the default parent.
1749 - empty to denote the default parent.
1744
1750
1745 All string valued-elements are either strictly alphanumeric, or must
1751 All string valued-elements are either strictly alphanumeric, or must
1746 be enclosed in double quotes ("..."), with "\\" as escape character.
1752 be enclosed in double quotes ("..."), with "\\" as escape character.
1747 """
1753 """
1748
1754
1749 if text is None:
1755 if text is None:
1750 ui.status(_("reading DAG from stdin\n"))
1756 ui.status(_("reading DAG from stdin\n"))
1751 text = ui.fin.read()
1757 text = ui.fin.read()
1752
1758
1753 cl = repo.changelog
1759 cl = repo.changelog
1754 if len(cl) > 0:
1760 if len(cl) > 0:
1755 raise util.Abort(_('repository is not empty'))
1761 raise util.Abort(_('repository is not empty'))
1756
1762
1757 # determine number of revs in DAG
1763 # determine number of revs in DAG
1758 total = 0
1764 total = 0
1759 for type, data in dagparser.parsedag(text):
1765 for type, data in dagparser.parsedag(text):
1760 if type == 'n':
1766 if type == 'n':
1761 total += 1
1767 total += 1
1762
1768
1763 if mergeable_file:
1769 if mergeable_file:
1764 linesperrev = 2
1770 linesperrev = 2
1765 # make a file with k lines per rev
1771 # make a file with k lines per rev
1766 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1772 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1767 initialmergedlines.append("")
1773 initialmergedlines.append("")
1768
1774
1769 tags = []
1775 tags = []
1770
1776
1771 lock = tr = None
1777 lock = tr = None
1772 try:
1778 try:
1773 lock = repo.lock()
1779 lock = repo.lock()
1774 tr = repo.transaction("builddag")
1780 tr = repo.transaction("builddag")
1775
1781
1776 at = -1
1782 at = -1
1777 atbranch = 'default'
1783 atbranch = 'default'
1778 nodeids = []
1784 nodeids = []
1779 id = 0
1785 id = 0
1780 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1786 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1781 for type, data in dagparser.parsedag(text):
1787 for type, data in dagparser.parsedag(text):
1782 if type == 'n':
1788 if type == 'n':
1783 ui.note(('node %s\n' % str(data)))
1789 ui.note(('node %s\n' % str(data)))
1784 id, ps = data
1790 id, ps = data
1785
1791
1786 files = []
1792 files = []
1787 fctxs = {}
1793 fctxs = {}
1788
1794
1789 p2 = None
1795 p2 = None
1790 if mergeable_file:
1796 if mergeable_file:
1791 fn = "mf"
1797 fn = "mf"
1792 p1 = repo[ps[0]]
1798 p1 = repo[ps[0]]
1793 if len(ps) > 1:
1799 if len(ps) > 1:
1794 p2 = repo[ps[1]]
1800 p2 = repo[ps[1]]
1795 pa = p1.ancestor(p2)
1801 pa = p1.ancestor(p2)
1796 base, local, other = [x[fn].data() for x in (pa, p1,
1802 base, local, other = [x[fn].data() for x in (pa, p1,
1797 p2)]
1803 p2)]
1798 m3 = simplemerge.Merge3Text(base, local, other)
1804 m3 = simplemerge.Merge3Text(base, local, other)
1799 ml = [l.strip() for l in m3.merge_lines()]
1805 ml = [l.strip() for l in m3.merge_lines()]
1800 ml.append("")
1806 ml.append("")
1801 elif at > 0:
1807 elif at > 0:
1802 ml = p1[fn].data().split("\n")
1808 ml = p1[fn].data().split("\n")
1803 else:
1809 else:
1804 ml = initialmergedlines
1810 ml = initialmergedlines
1805 ml[id * linesperrev] += " r%i" % id
1811 ml[id * linesperrev] += " r%i" % id
1806 mergedtext = "\n".join(ml)
1812 mergedtext = "\n".join(ml)
1807 files.append(fn)
1813 files.append(fn)
1808 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1814 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1809
1815
1810 if overwritten_file:
1816 if overwritten_file:
1811 fn = "of"
1817 fn = "of"
1812 files.append(fn)
1818 files.append(fn)
1813 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1819 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1814
1820
1815 if new_file:
1821 if new_file:
1816 fn = "nf%i" % id
1822 fn = "nf%i" % id
1817 files.append(fn)
1823 files.append(fn)
1818 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1824 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1819 if len(ps) > 1:
1825 if len(ps) > 1:
1820 if not p2:
1826 if not p2:
1821 p2 = repo[ps[1]]
1827 p2 = repo[ps[1]]
1822 for fn in p2:
1828 for fn in p2:
1823 if fn.startswith("nf"):
1829 if fn.startswith("nf"):
1824 files.append(fn)
1830 files.append(fn)
1825 fctxs[fn] = p2[fn]
1831 fctxs[fn] = p2[fn]
1826
1832
1827 def fctxfn(repo, cx, path):
1833 def fctxfn(repo, cx, path):
1828 return fctxs.get(path)
1834 return fctxs.get(path)
1829
1835
1830 if len(ps) == 0 or ps[0] < 0:
1836 if len(ps) == 0 or ps[0] < 0:
1831 pars = [None, None]
1837 pars = [None, None]
1832 elif len(ps) == 1:
1838 elif len(ps) == 1:
1833 pars = [nodeids[ps[0]], None]
1839 pars = [nodeids[ps[0]], None]
1834 else:
1840 else:
1835 pars = [nodeids[p] for p in ps]
1841 pars = [nodeids[p] for p in ps]
1836 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1842 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1837 date=(id, 0),
1843 date=(id, 0),
1838 user="debugbuilddag",
1844 user="debugbuilddag",
1839 extra={'branch': atbranch})
1845 extra={'branch': atbranch})
1840 nodeid = repo.commitctx(cx)
1846 nodeid = repo.commitctx(cx)
1841 nodeids.append(nodeid)
1847 nodeids.append(nodeid)
1842 at = id
1848 at = id
1843 elif type == 'l':
1849 elif type == 'l':
1844 id, name = data
1850 id, name = data
1845 ui.note(('tag %s\n' % name))
1851 ui.note(('tag %s\n' % name))
1846 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1852 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1847 elif type == 'a':
1853 elif type == 'a':
1848 ui.note(('branch %s\n' % data))
1854 ui.note(('branch %s\n' % data))
1849 atbranch = data
1855 atbranch = data
1850 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1856 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1851 tr.close()
1857 tr.close()
1852
1858
1853 if tags:
1859 if tags:
1854 repo.vfs.write("localtags", "".join(tags))
1860 repo.vfs.write("localtags", "".join(tags))
1855 finally:
1861 finally:
1856 ui.progress(_('building'), None)
1862 ui.progress(_('building'), None)
1857 release(tr, lock)
1863 release(tr, lock)
1858
1864
1859 @command('debugbundle',
1865 @command('debugbundle',
1860 [('a', 'all', None, _('show all details'))],
1866 [('a', 'all', None, _('show all details'))],
1861 _('FILE'),
1867 _('FILE'),
1862 norepo=True)
1868 norepo=True)
1863 def debugbundle(ui, bundlepath, all=None, **opts):
1869 def debugbundle(ui, bundlepath, all=None, **opts):
1864 """lists the contents of a bundle"""
1870 """lists the contents of a bundle"""
1865 f = hg.openpath(ui, bundlepath)
1871 f = hg.openpath(ui, bundlepath)
1866 try:
1872 try:
1867 gen = exchange.readbundle(ui, f, bundlepath)
1873 gen = exchange.readbundle(ui, f, bundlepath)
1868 if isinstance(gen, bundle2.unbundle20):
1874 if isinstance(gen, bundle2.unbundle20):
1869 return _debugbundle2(ui, gen, all=all, **opts)
1875 return _debugbundle2(ui, gen, all=all, **opts)
1870 if all:
1876 if all:
1871 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1877 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1872
1878
1873 def showchunks(named):
1879 def showchunks(named):
1874 ui.write("\n%s\n" % named)
1880 ui.write("\n%s\n" % named)
1875 chain = None
1881 chain = None
1876 while True:
1882 while True:
1877 chunkdata = gen.deltachunk(chain)
1883 chunkdata = gen.deltachunk(chain)
1878 if not chunkdata:
1884 if not chunkdata:
1879 break
1885 break
1880 node = chunkdata['node']
1886 node = chunkdata['node']
1881 p1 = chunkdata['p1']
1887 p1 = chunkdata['p1']
1882 p2 = chunkdata['p2']
1888 p2 = chunkdata['p2']
1883 cs = chunkdata['cs']
1889 cs = chunkdata['cs']
1884 deltabase = chunkdata['deltabase']
1890 deltabase = chunkdata['deltabase']
1885 delta = chunkdata['delta']
1891 delta = chunkdata['delta']
1886 ui.write("%s %s %s %s %s %s\n" %
1892 ui.write("%s %s %s %s %s %s\n" %
1887 (hex(node), hex(p1), hex(p2),
1893 (hex(node), hex(p1), hex(p2),
1888 hex(cs), hex(deltabase), len(delta)))
1894 hex(cs), hex(deltabase), len(delta)))
1889 chain = node
1895 chain = node
1890
1896
1891 chunkdata = gen.changelogheader()
1897 chunkdata = gen.changelogheader()
1892 showchunks("changelog")
1898 showchunks("changelog")
1893 chunkdata = gen.manifestheader()
1899 chunkdata = gen.manifestheader()
1894 showchunks("manifest")
1900 showchunks("manifest")
1895 while True:
1901 while True:
1896 chunkdata = gen.filelogheader()
1902 chunkdata = gen.filelogheader()
1897 if not chunkdata:
1903 if not chunkdata:
1898 break
1904 break
1899 fname = chunkdata['filename']
1905 fname = chunkdata['filename']
1900 showchunks(fname)
1906 showchunks(fname)
1901 else:
1907 else:
1902 if isinstance(gen, bundle2.unbundle20):
1908 if isinstance(gen, bundle2.unbundle20):
1903 raise util.Abort(_('use debugbundle2 for this file'))
1909 raise util.Abort(_('use debugbundle2 for this file'))
1904 chunkdata = gen.changelogheader()
1910 chunkdata = gen.changelogheader()
1905 chain = None
1911 chain = None
1906 while True:
1912 while True:
1907 chunkdata = gen.deltachunk(chain)
1913 chunkdata = gen.deltachunk(chain)
1908 if not chunkdata:
1914 if not chunkdata:
1909 break
1915 break
1910 node = chunkdata['node']
1916 node = chunkdata['node']
1911 ui.write("%s\n" % hex(node))
1917 ui.write("%s\n" % hex(node))
1912 chain = node
1918 chain = node
1913 finally:
1919 finally:
1914 f.close()
1920 f.close()
1915
1921
1916 def _debugbundle2(ui, gen, **opts):
1922 def _debugbundle2(ui, gen, **opts):
1917 """lists the contents of a bundle2"""
1923 """lists the contents of a bundle2"""
1918 if not isinstance(gen, bundle2.unbundle20):
1924 if not isinstance(gen, bundle2.unbundle20):
1919 raise util.Abort(_('not a bundle2 file'))
1925 raise util.Abort(_('not a bundle2 file'))
1920 ui.write(('Stream params: %s\n' % repr(gen.params)))
1926 ui.write(('Stream params: %s\n' % repr(gen.params)))
1921 for part in gen.iterparts():
1927 for part in gen.iterparts():
1922 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1928 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1923 if part.type == 'changegroup':
1929 if part.type == 'changegroup':
1924 version = part.params.get('version', '01')
1930 version = part.params.get('version', '01')
1925 cg = changegroup.packermap[version][1](part, 'UN')
1931 cg = changegroup.packermap[version][1](part, 'UN')
1926 chunkdata = cg.changelogheader()
1932 chunkdata = cg.changelogheader()
1927 chain = None
1933 chain = None
1928 while True:
1934 while True:
1929 chunkdata = cg.deltachunk(chain)
1935 chunkdata = cg.deltachunk(chain)
1930 if not chunkdata:
1936 if not chunkdata:
1931 break
1937 break
1932 node = chunkdata['node']
1938 node = chunkdata['node']
1933 ui.write(" %s\n" % hex(node))
1939 ui.write(" %s\n" % hex(node))
1934 chain = node
1940 chain = node
1935
1941
1936 @command('debugcheckstate', [], '')
1942 @command('debugcheckstate', [], '')
1937 def debugcheckstate(ui, repo):
1943 def debugcheckstate(ui, repo):
1938 """validate the correctness of the current dirstate"""
1944 """validate the correctness of the current dirstate"""
1939 parent1, parent2 = repo.dirstate.parents()
1945 parent1, parent2 = repo.dirstate.parents()
1940 m1 = repo[parent1].manifest()
1946 m1 = repo[parent1].manifest()
1941 m2 = repo[parent2].manifest()
1947 m2 = repo[parent2].manifest()
1942 errors = 0
1948 errors = 0
1943 for f in repo.dirstate:
1949 for f in repo.dirstate:
1944 state = repo.dirstate[f]
1950 state = repo.dirstate[f]
1945 if state in "nr" and f not in m1:
1951 if state in "nr" and f not in m1:
1946 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1952 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1947 errors += 1
1953 errors += 1
1948 if state in "a" and f in m1:
1954 if state in "a" and f in m1:
1949 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1955 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1950 errors += 1
1956 errors += 1
1951 if state in "m" and f not in m1 and f not in m2:
1957 if state in "m" and f not in m1 and f not in m2:
1952 ui.warn(_("%s in state %s, but not in either manifest\n") %
1958 ui.warn(_("%s in state %s, but not in either manifest\n") %
1953 (f, state))
1959 (f, state))
1954 errors += 1
1960 errors += 1
1955 for f in m1:
1961 for f in m1:
1956 state = repo.dirstate[f]
1962 state = repo.dirstate[f]
1957 if state not in "nrm":
1963 if state not in "nrm":
1958 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1964 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1959 errors += 1
1965 errors += 1
1960 if errors:
1966 if errors:
1961 error = _(".hg/dirstate inconsistent with current parent's manifest")
1967 error = _(".hg/dirstate inconsistent with current parent's manifest")
1962 raise util.Abort(error)
1968 raise util.Abort(error)
1963
1969
1964 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1970 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1965 def debugcommands(ui, cmd='', *args):
1971 def debugcommands(ui, cmd='', *args):
1966 """list all available commands and options"""
1972 """list all available commands and options"""
1967 for cmd, vals in sorted(table.iteritems()):
1973 for cmd, vals in sorted(table.iteritems()):
1968 cmd = cmd.split('|')[0].strip('^')
1974 cmd = cmd.split('|')[0].strip('^')
1969 opts = ', '.join([i[1] for i in vals[1]])
1975 opts = ', '.join([i[1] for i in vals[1]])
1970 ui.write('%s: %s\n' % (cmd, opts))
1976 ui.write('%s: %s\n' % (cmd, opts))
1971
1977
1972 @command('debugcomplete',
1978 @command('debugcomplete',
1973 [('o', 'options', None, _('show the command options'))],
1979 [('o', 'options', None, _('show the command options'))],
1974 _('[-o] CMD'),
1980 _('[-o] CMD'),
1975 norepo=True)
1981 norepo=True)
1976 def debugcomplete(ui, cmd='', **opts):
1982 def debugcomplete(ui, cmd='', **opts):
1977 """returns the completion list associated with the given command"""
1983 """returns the completion list associated with the given command"""
1978
1984
1979 if opts.get('options'):
1985 if opts.get('options'):
1980 options = []
1986 options = []
1981 otables = [globalopts]
1987 otables = [globalopts]
1982 if cmd:
1988 if cmd:
1983 aliases, entry = cmdutil.findcmd(cmd, table, False)
1989 aliases, entry = cmdutil.findcmd(cmd, table, False)
1984 otables.append(entry[1])
1990 otables.append(entry[1])
1985 for t in otables:
1991 for t in otables:
1986 for o in t:
1992 for o in t:
1987 if "(DEPRECATED)" in o[3]:
1993 if "(DEPRECATED)" in o[3]:
1988 continue
1994 continue
1989 if o[0]:
1995 if o[0]:
1990 options.append('-%s' % o[0])
1996 options.append('-%s' % o[0])
1991 options.append('--%s' % o[1])
1997 options.append('--%s' % o[1])
1992 ui.write("%s\n" % "\n".join(options))
1998 ui.write("%s\n" % "\n".join(options))
1993 return
1999 return
1994
2000
1995 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2001 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1996 if ui.verbose:
2002 if ui.verbose:
1997 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2003 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1998 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2004 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1999
2005
2000 @command('debugdag',
2006 @command('debugdag',
2001 [('t', 'tags', None, _('use tags as labels')),
2007 [('t', 'tags', None, _('use tags as labels')),
2002 ('b', 'branches', None, _('annotate with branch names')),
2008 ('b', 'branches', None, _('annotate with branch names')),
2003 ('', 'dots', None, _('use dots for runs')),
2009 ('', 'dots', None, _('use dots for runs')),
2004 ('s', 'spaces', None, _('separate elements by spaces'))],
2010 ('s', 'spaces', None, _('separate elements by spaces'))],
2005 _('[OPTION]... [FILE [REV]...]'),
2011 _('[OPTION]... [FILE [REV]...]'),
2006 optionalrepo=True)
2012 optionalrepo=True)
2007 def debugdag(ui, repo, file_=None, *revs, **opts):
2013 def debugdag(ui, repo, file_=None, *revs, **opts):
2008 """format the changelog or an index DAG as a concise textual description
2014 """format the changelog or an index DAG as a concise textual description
2009
2015
2010 If you pass a revlog index, the revlog's DAG is emitted. If you list
2016 If you pass a revlog index, the revlog's DAG is emitted. If you list
2011 revision numbers, they get labeled in the output as rN.
2017 revision numbers, they get labeled in the output as rN.
2012
2018
2013 Otherwise, the changelog DAG of the current repo is emitted.
2019 Otherwise, the changelog DAG of the current repo is emitted.
2014 """
2020 """
2015 spaces = opts.get('spaces')
2021 spaces = opts.get('spaces')
2016 dots = opts.get('dots')
2022 dots = opts.get('dots')
2017 if file_:
2023 if file_:
2018 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2024 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2019 revs = set((int(r) for r in revs))
2025 revs = set((int(r) for r in revs))
2020 def events():
2026 def events():
2021 for r in rlog:
2027 for r in rlog:
2022 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2028 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2023 if p != -1))
2029 if p != -1))
2024 if r in revs:
2030 if r in revs:
2025 yield 'l', (r, "r%i" % r)
2031 yield 'l', (r, "r%i" % r)
2026 elif repo:
2032 elif repo:
2027 cl = repo.changelog
2033 cl = repo.changelog
2028 tags = opts.get('tags')
2034 tags = opts.get('tags')
2029 branches = opts.get('branches')
2035 branches = opts.get('branches')
2030 if tags:
2036 if tags:
2031 labels = {}
2037 labels = {}
2032 for l, n in repo.tags().items():
2038 for l, n in repo.tags().items():
2033 labels.setdefault(cl.rev(n), []).append(l)
2039 labels.setdefault(cl.rev(n), []).append(l)
2034 def events():
2040 def events():
2035 b = "default"
2041 b = "default"
2036 for r in cl:
2042 for r in cl:
2037 if branches:
2043 if branches:
2038 newb = cl.read(cl.node(r))[5]['branch']
2044 newb = cl.read(cl.node(r))[5]['branch']
2039 if newb != b:
2045 if newb != b:
2040 yield 'a', newb
2046 yield 'a', newb
2041 b = newb
2047 b = newb
2042 yield 'n', (r, list(p for p in cl.parentrevs(r)
2048 yield 'n', (r, list(p for p in cl.parentrevs(r)
2043 if p != -1))
2049 if p != -1))
2044 if tags:
2050 if tags:
2045 ls = labels.get(r)
2051 ls = labels.get(r)
2046 if ls:
2052 if ls:
2047 for l in ls:
2053 for l in ls:
2048 yield 'l', (r, l)
2054 yield 'l', (r, l)
2049 else:
2055 else:
2050 raise util.Abort(_('need repo for changelog dag'))
2056 raise util.Abort(_('need repo for changelog dag'))
2051
2057
2052 for line in dagparser.dagtextlines(events(),
2058 for line in dagparser.dagtextlines(events(),
2053 addspaces=spaces,
2059 addspaces=spaces,
2054 wraplabels=True,
2060 wraplabels=True,
2055 wrapannotations=True,
2061 wrapannotations=True,
2056 wrapnonlinear=dots,
2062 wrapnonlinear=dots,
2057 usedots=dots,
2063 usedots=dots,
2058 maxlinewidth=70):
2064 maxlinewidth=70):
2059 ui.write(line)
2065 ui.write(line)
2060 ui.write("\n")
2066 ui.write("\n")
2061
2067
2062 @command('debugdata',
2068 @command('debugdata',
2063 [('c', 'changelog', False, _('open changelog')),
2069 [('c', 'changelog', False, _('open changelog')),
2064 ('m', 'manifest', False, _('open manifest')),
2070 ('m', 'manifest', False, _('open manifest')),
2065 ('', 'dir', False, _('open directory manifest'))],
2071 ('', 'dir', False, _('open directory manifest'))],
2066 _('-c|-m|FILE REV'))
2072 _('-c|-m|FILE REV'))
2067 def debugdata(ui, repo, file_, rev=None, **opts):
2073 def debugdata(ui, repo, file_, rev=None, **opts):
2068 """dump the contents of a data file revision"""
2074 """dump the contents of a data file revision"""
2069 if opts.get('changelog') or opts.get('manifest'):
2075 if opts.get('changelog') or opts.get('manifest'):
2070 file_, rev = None, file_
2076 file_, rev = None, file_
2071 elif rev is None:
2077 elif rev is None:
2072 raise error.CommandError('debugdata', _('invalid arguments'))
2078 raise error.CommandError('debugdata', _('invalid arguments'))
2073 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2079 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2074 try:
2080 try:
2075 ui.write(r.revision(r.lookup(rev)))
2081 ui.write(r.revision(r.lookup(rev)))
2076 except KeyError:
2082 except KeyError:
2077 raise util.Abort(_('invalid revision identifier %s') % rev)
2083 raise util.Abort(_('invalid revision identifier %s') % rev)
2078
2084
2079 @command('debugdate',
2085 @command('debugdate',
2080 [('e', 'extended', None, _('try extended date formats'))],
2086 [('e', 'extended', None, _('try extended date formats'))],
2081 _('[-e] DATE [RANGE]'),
2087 _('[-e] DATE [RANGE]'),
2082 norepo=True, optionalrepo=True)
2088 norepo=True, optionalrepo=True)
2083 def debugdate(ui, date, range=None, **opts):
2089 def debugdate(ui, date, range=None, **opts):
2084 """parse and display a date"""
2090 """parse and display a date"""
2085 if opts["extended"]:
2091 if opts["extended"]:
2086 d = util.parsedate(date, util.extendeddateformats)
2092 d = util.parsedate(date, util.extendeddateformats)
2087 else:
2093 else:
2088 d = util.parsedate(date)
2094 d = util.parsedate(date)
2089 ui.write(("internal: %s %s\n") % d)
2095 ui.write(("internal: %s %s\n") % d)
2090 ui.write(("standard: %s\n") % util.datestr(d))
2096 ui.write(("standard: %s\n") % util.datestr(d))
2091 if range:
2097 if range:
2092 m = util.matchdate(range)
2098 m = util.matchdate(range)
2093 ui.write(("match: %s\n") % m(d[0]))
2099 ui.write(("match: %s\n") % m(d[0]))
2094
2100
2095 @command('debugdiscovery',
2101 @command('debugdiscovery',
2096 [('', 'old', None, _('use old-style discovery')),
2102 [('', 'old', None, _('use old-style discovery')),
2097 ('', 'nonheads', None,
2103 ('', 'nonheads', None,
2098 _('use old-style discovery with non-heads included')),
2104 _('use old-style discovery with non-heads included')),
2099 ] + remoteopts,
2105 ] + remoteopts,
2100 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2106 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2101 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2107 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2102 """runs the changeset discovery protocol in isolation"""
2108 """runs the changeset discovery protocol in isolation"""
2103 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2109 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2104 opts.get('branch'))
2110 opts.get('branch'))
2105 remote = hg.peer(repo, opts, remoteurl)
2111 remote = hg.peer(repo, opts, remoteurl)
2106 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2112 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2107
2113
2108 # make sure tests are repeatable
2114 # make sure tests are repeatable
2109 random.seed(12323)
2115 random.seed(12323)
2110
2116
2111 def doit(localheads, remoteheads, remote=remote):
2117 def doit(localheads, remoteheads, remote=remote):
2112 if opts.get('old'):
2118 if opts.get('old'):
2113 if localheads:
2119 if localheads:
2114 raise util.Abort('cannot use localheads with old style '
2120 raise util.Abort('cannot use localheads with old style '
2115 'discovery')
2121 'discovery')
2116 if not util.safehasattr(remote, 'branches'):
2122 if not util.safehasattr(remote, 'branches'):
2117 # enable in-client legacy support
2123 # enable in-client legacy support
2118 remote = localrepo.locallegacypeer(remote.local())
2124 remote = localrepo.locallegacypeer(remote.local())
2119 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2125 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2120 force=True)
2126 force=True)
2121 common = set(common)
2127 common = set(common)
2122 if not opts.get('nonheads'):
2128 if not opts.get('nonheads'):
2123 ui.write(("unpruned common: %s\n") %
2129 ui.write(("unpruned common: %s\n") %
2124 " ".join(sorted(short(n) for n in common)))
2130 " ".join(sorted(short(n) for n in common)))
2125 dag = dagutil.revlogdag(repo.changelog)
2131 dag = dagutil.revlogdag(repo.changelog)
2126 all = dag.ancestorset(dag.internalizeall(common))
2132 all = dag.ancestorset(dag.internalizeall(common))
2127 common = dag.externalizeall(dag.headsetofconnecteds(all))
2133 common = dag.externalizeall(dag.headsetofconnecteds(all))
2128 else:
2134 else:
2129 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2135 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2130 common = set(common)
2136 common = set(common)
2131 rheads = set(hds)
2137 rheads = set(hds)
2132 lheads = set(repo.heads())
2138 lheads = set(repo.heads())
2133 ui.write(("common heads: %s\n") %
2139 ui.write(("common heads: %s\n") %
2134 " ".join(sorted(short(n) for n in common)))
2140 " ".join(sorted(short(n) for n in common)))
2135 if lheads <= common:
2141 if lheads <= common:
2136 ui.write(("local is subset\n"))
2142 ui.write(("local is subset\n"))
2137 elif rheads <= common:
2143 elif rheads <= common:
2138 ui.write(("remote is subset\n"))
2144 ui.write(("remote is subset\n"))
2139
2145
2140 serverlogs = opts.get('serverlog')
2146 serverlogs = opts.get('serverlog')
2141 if serverlogs:
2147 if serverlogs:
2142 for filename in serverlogs:
2148 for filename in serverlogs:
2143 logfile = open(filename, 'r')
2149 logfile = open(filename, 'r')
2144 try:
2150 try:
2145 line = logfile.readline()
2151 line = logfile.readline()
2146 while line:
2152 while line:
2147 parts = line.strip().split(';')
2153 parts = line.strip().split(';')
2148 op = parts[1]
2154 op = parts[1]
2149 if op == 'cg':
2155 if op == 'cg':
2150 pass
2156 pass
2151 elif op == 'cgss':
2157 elif op == 'cgss':
2152 doit(parts[2].split(' '), parts[3].split(' '))
2158 doit(parts[2].split(' '), parts[3].split(' '))
2153 elif op == 'unb':
2159 elif op == 'unb':
2154 doit(parts[3].split(' '), parts[2].split(' '))
2160 doit(parts[3].split(' '), parts[2].split(' '))
2155 line = logfile.readline()
2161 line = logfile.readline()
2156 finally:
2162 finally:
2157 logfile.close()
2163 logfile.close()
2158
2164
2159 else:
2165 else:
2160 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2166 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2161 opts.get('remote_head'))
2167 opts.get('remote_head'))
2162 localrevs = opts.get('local_head')
2168 localrevs = opts.get('local_head')
2163 doit(localrevs, remoterevs)
2169 doit(localrevs, remoterevs)
2164
2170
2165 @command('debugfileset',
2171 @command('debugfileset',
2166 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2172 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2167 _('[-r REV] FILESPEC'))
2173 _('[-r REV] FILESPEC'))
2168 def debugfileset(ui, repo, expr, **opts):
2174 def debugfileset(ui, repo, expr, **opts):
2169 '''parse and apply a fileset specification'''
2175 '''parse and apply a fileset specification'''
2170 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2176 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2171 if ui.verbose:
2177 if ui.verbose:
2172 tree = fileset.parse(expr)
2178 tree = fileset.parse(expr)
2173 ui.note(fileset.prettyformat(tree), "\n")
2179 ui.note(fileset.prettyformat(tree), "\n")
2174
2180
2175 for f in ctx.getfileset(expr):
2181 for f in ctx.getfileset(expr):
2176 ui.write("%s\n" % f)
2182 ui.write("%s\n" % f)
2177
2183
2178 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2184 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2179 def debugfsinfo(ui, path="."):
2185 def debugfsinfo(ui, path="."):
2180 """show information detected about current filesystem"""
2186 """show information detected about current filesystem"""
2181 util.writefile('.debugfsinfo', '')
2187 util.writefile('.debugfsinfo', '')
2182 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2188 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2183 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2189 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2184 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2190 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2185 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2191 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2186 and 'yes' or 'no'))
2192 and 'yes' or 'no'))
2187 os.unlink('.debugfsinfo')
2193 os.unlink('.debugfsinfo')
2188
2194
2189 @command('debuggetbundle',
2195 @command('debuggetbundle',
2190 [('H', 'head', [], _('id of head node'), _('ID')),
2196 [('H', 'head', [], _('id of head node'), _('ID')),
2191 ('C', 'common', [], _('id of common node'), _('ID')),
2197 ('C', 'common', [], _('id of common node'), _('ID')),
2192 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2198 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2193 _('REPO FILE [-H|-C ID]...'),
2199 _('REPO FILE [-H|-C ID]...'),
2194 norepo=True)
2200 norepo=True)
2195 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2201 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2196 """retrieves a bundle from a repo
2202 """retrieves a bundle from a repo
2197
2203
2198 Every ID must be a full-length hex node id string. Saves the bundle to the
2204 Every ID must be a full-length hex node id string. Saves the bundle to the
2199 given file.
2205 given file.
2200 """
2206 """
2201 repo = hg.peer(ui, opts, repopath)
2207 repo = hg.peer(ui, opts, repopath)
2202 if not repo.capable('getbundle'):
2208 if not repo.capable('getbundle'):
2203 raise util.Abort("getbundle() not supported by target repository")
2209 raise util.Abort("getbundle() not supported by target repository")
2204 args = {}
2210 args = {}
2205 if common:
2211 if common:
2206 args['common'] = [bin(s) for s in common]
2212 args['common'] = [bin(s) for s in common]
2207 if head:
2213 if head:
2208 args['heads'] = [bin(s) for s in head]
2214 args['heads'] = [bin(s) for s in head]
2209 # TODO: get desired bundlecaps from command line.
2215 # TODO: get desired bundlecaps from command line.
2210 args['bundlecaps'] = None
2216 args['bundlecaps'] = None
2211 bundle = repo.getbundle('debug', **args)
2217 bundle = repo.getbundle('debug', **args)
2212
2218
2213 bundletype = opts.get('type', 'bzip2').lower()
2219 bundletype = opts.get('type', 'bzip2').lower()
2214 btypes = {'none': 'HG10UN',
2220 btypes = {'none': 'HG10UN',
2215 'bzip2': 'HG10BZ',
2221 'bzip2': 'HG10BZ',
2216 'gzip': 'HG10GZ',
2222 'gzip': 'HG10GZ',
2217 'bundle2': 'HG20'}
2223 'bundle2': 'HG20'}
2218 bundletype = btypes.get(bundletype)
2224 bundletype = btypes.get(bundletype)
2219 if bundletype not in changegroup.bundletypes:
2225 if bundletype not in changegroup.bundletypes:
2220 raise util.Abort(_('unknown bundle type specified with --type'))
2226 raise util.Abort(_('unknown bundle type specified with --type'))
2221 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2227 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2222
2228
2223 @command('debugignore', [], '')
2229 @command('debugignore', [], '')
2224 def debugignore(ui, repo, *values, **opts):
2230 def debugignore(ui, repo, *values, **opts):
2225 """display the combined ignore pattern"""
2231 """display the combined ignore pattern"""
2226 ignore = repo.dirstate._ignore
2232 ignore = repo.dirstate._ignore
2227 includepat = getattr(ignore, 'includepat', None)
2233 includepat = getattr(ignore, 'includepat', None)
2228 if includepat is not None:
2234 if includepat is not None:
2229 ui.write("%s\n" % includepat)
2235 ui.write("%s\n" % includepat)
2230 else:
2236 else:
2231 raise util.Abort(_("no ignore patterns found"))
2237 raise util.Abort(_("no ignore patterns found"))
2232
2238
2233 @command('debugindex',
2239 @command('debugindex',
2234 [('c', 'changelog', False, _('open changelog')),
2240 [('c', 'changelog', False, _('open changelog')),
2235 ('m', 'manifest', False, _('open manifest')),
2241 ('m', 'manifest', False, _('open manifest')),
2236 ('', 'dir', False, _('open directory manifest')),
2242 ('', 'dir', False, _('open directory manifest')),
2237 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2243 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2238 _('[-f FORMAT] -c|-m|FILE'),
2244 _('[-f FORMAT] -c|-m|FILE'),
2239 optionalrepo=True)
2245 optionalrepo=True)
2240 def debugindex(ui, repo, file_=None, **opts):
2246 def debugindex(ui, repo, file_=None, **opts):
2241 """dump the contents of an index file"""
2247 """dump the contents of an index file"""
2242 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2248 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2243 format = opts.get('format', 0)
2249 format = opts.get('format', 0)
2244 if format not in (0, 1):
2250 if format not in (0, 1):
2245 raise util.Abort(_("unknown format %d") % format)
2251 raise util.Abort(_("unknown format %d") % format)
2246
2252
2247 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2253 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2248 if generaldelta:
2254 if generaldelta:
2249 basehdr = ' delta'
2255 basehdr = ' delta'
2250 else:
2256 else:
2251 basehdr = ' base'
2257 basehdr = ' base'
2252
2258
2253 if ui.debugflag:
2259 if ui.debugflag:
2254 shortfn = hex
2260 shortfn = hex
2255 else:
2261 else:
2256 shortfn = short
2262 shortfn = short
2257
2263
2258 # There might not be anything in r, so have a sane default
2264 # There might not be anything in r, so have a sane default
2259 idlen = 12
2265 idlen = 12
2260 for i in r:
2266 for i in r:
2261 idlen = len(shortfn(r.node(i)))
2267 idlen = len(shortfn(r.node(i)))
2262 break
2268 break
2263
2269
2264 if format == 0:
2270 if format == 0:
2265 ui.write(" rev offset length " + basehdr + " linkrev"
2271 ui.write(" rev offset length " + basehdr + " linkrev"
2266 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2272 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2267 elif format == 1:
2273 elif format == 1:
2268 ui.write(" rev flag offset length"
2274 ui.write(" rev flag offset length"
2269 " size " + basehdr + " link p1 p2"
2275 " size " + basehdr + " link p1 p2"
2270 " %s\n" % "nodeid".rjust(idlen))
2276 " %s\n" % "nodeid".rjust(idlen))
2271
2277
2272 for i in r:
2278 for i in r:
2273 node = r.node(i)
2279 node = r.node(i)
2274 if generaldelta:
2280 if generaldelta:
2275 base = r.deltaparent(i)
2281 base = r.deltaparent(i)
2276 else:
2282 else:
2277 base = r.chainbase(i)
2283 base = r.chainbase(i)
2278 if format == 0:
2284 if format == 0:
2279 try:
2285 try:
2280 pp = r.parents(node)
2286 pp = r.parents(node)
2281 except Exception:
2287 except Exception:
2282 pp = [nullid, nullid]
2288 pp = [nullid, nullid]
2283 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2289 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2284 i, r.start(i), r.length(i), base, r.linkrev(i),
2290 i, r.start(i), r.length(i), base, r.linkrev(i),
2285 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2291 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2286 elif format == 1:
2292 elif format == 1:
2287 pr = r.parentrevs(i)
2293 pr = r.parentrevs(i)
2288 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2294 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2289 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2295 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2290 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2296 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2291
2297
2292 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2298 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2293 def debugindexdot(ui, repo, file_):
2299 def debugindexdot(ui, repo, file_):
2294 """dump an index DAG as a graphviz dot file"""
2300 """dump an index DAG as a graphviz dot file"""
2295 r = None
2301 r = None
2296 if repo:
2302 if repo:
2297 filelog = repo.file(file_)
2303 filelog = repo.file(file_)
2298 if len(filelog):
2304 if len(filelog):
2299 r = filelog
2305 r = filelog
2300 if not r:
2306 if not r:
2301 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2307 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2302 ui.write(("digraph G {\n"))
2308 ui.write(("digraph G {\n"))
2303 for i in r:
2309 for i in r:
2304 node = r.node(i)
2310 node = r.node(i)
2305 pp = r.parents(node)
2311 pp = r.parents(node)
2306 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2312 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2307 if pp[1] != nullid:
2313 if pp[1] != nullid:
2308 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2314 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2309 ui.write("}\n")
2315 ui.write("}\n")
2310
2316
2311 @command('debuginstall', [], '', norepo=True)
2317 @command('debuginstall', [], '', norepo=True)
2312 def debuginstall(ui):
2318 def debuginstall(ui):
2313 '''test Mercurial installation
2319 '''test Mercurial installation
2314
2320
2315 Returns 0 on success.
2321 Returns 0 on success.
2316 '''
2322 '''
2317
2323
2318 def writetemp(contents):
2324 def writetemp(contents):
2319 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2325 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2320 f = os.fdopen(fd, "wb")
2326 f = os.fdopen(fd, "wb")
2321 f.write(contents)
2327 f.write(contents)
2322 f.close()
2328 f.close()
2323 return name
2329 return name
2324
2330
2325 problems = 0
2331 problems = 0
2326
2332
2327 # encoding
2333 # encoding
2328 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2334 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2329 try:
2335 try:
2330 encoding.fromlocal("test")
2336 encoding.fromlocal("test")
2331 except util.Abort, inst:
2337 except util.Abort, inst:
2332 ui.write(" %s\n" % inst)
2338 ui.write(" %s\n" % inst)
2333 ui.write(_(" (check that your locale is properly set)\n"))
2339 ui.write(_(" (check that your locale is properly set)\n"))
2334 problems += 1
2340 problems += 1
2335
2341
2336 # Python
2342 # Python
2337 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2343 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2338 ui.status(_("checking Python version (%s)\n")
2344 ui.status(_("checking Python version (%s)\n")
2339 % ("%s.%s.%s" % sys.version_info[:3]))
2345 % ("%s.%s.%s" % sys.version_info[:3]))
2340 ui.status(_("checking Python lib (%s)...\n")
2346 ui.status(_("checking Python lib (%s)...\n")
2341 % os.path.dirname(os.__file__))
2347 % os.path.dirname(os.__file__))
2342
2348
2343 # compiled modules
2349 # compiled modules
2344 ui.status(_("checking installed modules (%s)...\n")
2350 ui.status(_("checking installed modules (%s)...\n")
2345 % os.path.dirname(__file__))
2351 % os.path.dirname(__file__))
2346 try:
2352 try:
2347 import bdiff, mpatch, base85, osutil
2353 import bdiff, mpatch, base85, osutil
2348 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2354 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2349 except Exception, inst:
2355 except Exception, inst:
2350 ui.write(" %s\n" % inst)
2356 ui.write(" %s\n" % inst)
2351 ui.write(_(" One or more extensions could not be found"))
2357 ui.write(_(" One or more extensions could not be found"))
2352 ui.write(_(" (check that you compiled the extensions)\n"))
2358 ui.write(_(" (check that you compiled the extensions)\n"))
2353 problems += 1
2359 problems += 1
2354
2360
2355 # templates
2361 # templates
2356 import templater
2362 import templater
2357 p = templater.templatepaths()
2363 p = templater.templatepaths()
2358 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2364 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2359 if p:
2365 if p:
2360 m = templater.templatepath("map-cmdline.default")
2366 m = templater.templatepath("map-cmdline.default")
2361 if m:
2367 if m:
2362 # template found, check if it is working
2368 # template found, check if it is working
2363 try:
2369 try:
2364 templater.templater(m)
2370 templater.templater(m)
2365 except Exception, inst:
2371 except Exception, inst:
2366 ui.write(" %s\n" % inst)
2372 ui.write(" %s\n" % inst)
2367 p = None
2373 p = None
2368 else:
2374 else:
2369 ui.write(_(" template 'default' not found\n"))
2375 ui.write(_(" template 'default' not found\n"))
2370 p = None
2376 p = None
2371 else:
2377 else:
2372 ui.write(_(" no template directories found\n"))
2378 ui.write(_(" no template directories found\n"))
2373 if not p:
2379 if not p:
2374 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2380 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2375 problems += 1
2381 problems += 1
2376
2382
2377 # editor
2383 # editor
2378 ui.status(_("checking commit editor...\n"))
2384 ui.status(_("checking commit editor...\n"))
2379 editor = ui.geteditor()
2385 editor = ui.geteditor()
2380 editor = util.expandpath(editor)
2386 editor = util.expandpath(editor)
2381 cmdpath = util.findexe(shlex.split(editor)[0])
2387 cmdpath = util.findexe(shlex.split(editor)[0])
2382 if not cmdpath:
2388 if not cmdpath:
2383 if editor == 'vi':
2389 if editor == 'vi':
2384 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2390 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2385 ui.write(_(" (specify a commit editor in your configuration"
2391 ui.write(_(" (specify a commit editor in your configuration"
2386 " file)\n"))
2392 " file)\n"))
2387 else:
2393 else:
2388 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2394 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2389 ui.write(_(" (specify a commit editor in your configuration"
2395 ui.write(_(" (specify a commit editor in your configuration"
2390 " file)\n"))
2396 " file)\n"))
2391 problems += 1
2397 problems += 1
2392
2398
2393 # check username
2399 # check username
2394 ui.status(_("checking username...\n"))
2400 ui.status(_("checking username...\n"))
2395 try:
2401 try:
2396 ui.username()
2402 ui.username()
2397 except util.Abort, e:
2403 except util.Abort, e:
2398 ui.write(" %s\n" % e)
2404 ui.write(" %s\n" % e)
2399 ui.write(_(" (specify a username in your configuration file)\n"))
2405 ui.write(_(" (specify a username in your configuration file)\n"))
2400 problems += 1
2406 problems += 1
2401
2407
2402 if not problems:
2408 if not problems:
2403 ui.status(_("no problems detected\n"))
2409 ui.status(_("no problems detected\n"))
2404 else:
2410 else:
2405 ui.write(_("%s problems detected,"
2411 ui.write(_("%s problems detected,"
2406 " please check your install!\n") % problems)
2412 " please check your install!\n") % problems)
2407
2413
2408 return problems
2414 return problems
2409
2415
2410 @command('debugknown', [], _('REPO ID...'), norepo=True)
2416 @command('debugknown', [], _('REPO ID...'), norepo=True)
2411 def debugknown(ui, repopath, *ids, **opts):
2417 def debugknown(ui, repopath, *ids, **opts):
2412 """test whether node ids are known to a repo
2418 """test whether node ids are known to a repo
2413
2419
2414 Every ID must be a full-length hex node id string. Returns a list of 0s
2420 Every ID must be a full-length hex node id string. Returns a list of 0s
2415 and 1s indicating unknown/known.
2421 and 1s indicating unknown/known.
2416 """
2422 """
2417 repo = hg.peer(ui, opts, repopath)
2423 repo = hg.peer(ui, opts, repopath)
2418 if not repo.capable('known'):
2424 if not repo.capable('known'):
2419 raise util.Abort("known() not supported by target repository")
2425 raise util.Abort("known() not supported by target repository")
2420 flags = repo.known([bin(s) for s in ids])
2426 flags = repo.known([bin(s) for s in ids])
2421 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2427 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2422
2428
2423 @command('debuglabelcomplete', [], _('LABEL...'))
2429 @command('debuglabelcomplete', [], _('LABEL...'))
2424 def debuglabelcomplete(ui, repo, *args):
2430 def debuglabelcomplete(ui, repo, *args):
2425 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2431 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2426 debugnamecomplete(ui, repo, *args)
2432 debugnamecomplete(ui, repo, *args)
2427
2433
2428 @command('debugnamecomplete', [], _('NAME...'))
2434 @command('debugnamecomplete', [], _('NAME...'))
2429 def debugnamecomplete(ui, repo, *args):
2435 def debugnamecomplete(ui, repo, *args):
2430 '''complete "names" - tags, open branch names, bookmark names'''
2436 '''complete "names" - tags, open branch names, bookmark names'''
2431
2437
2432 names = set()
2438 names = set()
2433 # since we previously only listed open branches, we will handle that
2439 # since we previously only listed open branches, we will handle that
2434 # specially (after this for loop)
2440 # specially (after this for loop)
2435 for name, ns in repo.names.iteritems():
2441 for name, ns in repo.names.iteritems():
2436 if name != 'branches':
2442 if name != 'branches':
2437 names.update(ns.listnames(repo))
2443 names.update(ns.listnames(repo))
2438 names.update(tag for (tag, heads, tip, closed)
2444 names.update(tag for (tag, heads, tip, closed)
2439 in repo.branchmap().iterbranches() if not closed)
2445 in repo.branchmap().iterbranches() if not closed)
2440 completions = set()
2446 completions = set()
2441 if not args:
2447 if not args:
2442 args = ['']
2448 args = ['']
2443 for a in args:
2449 for a in args:
2444 completions.update(n for n in names if n.startswith(a))
2450 completions.update(n for n in names if n.startswith(a))
2445 ui.write('\n'.join(sorted(completions)))
2451 ui.write('\n'.join(sorted(completions)))
2446 ui.write('\n')
2452 ui.write('\n')
2447
2453
2448 @command('debuglocks',
2454 @command('debuglocks',
2449 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2455 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2450 ('W', 'force-wlock', None,
2456 ('W', 'force-wlock', None,
2451 _('free the working state lock (DANGEROUS)'))],
2457 _('free the working state lock (DANGEROUS)'))],
2452 _('[OPTION]...'))
2458 _('[OPTION]...'))
2453 def debuglocks(ui, repo, **opts):
2459 def debuglocks(ui, repo, **opts):
2454 """show or modify state of locks
2460 """show or modify state of locks
2455
2461
2456 By default, this command will show which locks are held. This
2462 By default, this command will show which locks are held. This
2457 includes the user and process holding the lock, the amount of time
2463 includes the user and process holding the lock, the amount of time
2458 the lock has been held, and the machine name where the process is
2464 the lock has been held, and the machine name where the process is
2459 running if it's not local.
2465 running if it's not local.
2460
2466
2461 Locks protect the integrity of Mercurial's data, so should be
2467 Locks protect the integrity of Mercurial's data, so should be
2462 treated with care. System crashes or other interruptions may cause
2468 treated with care. System crashes or other interruptions may cause
2463 locks to not be properly released, though Mercurial will usually
2469 locks to not be properly released, though Mercurial will usually
2464 detect and remove such stale locks automatically.
2470 detect and remove such stale locks automatically.
2465
2471
2466 However, detecting stale locks may not always be possible (for
2472 However, detecting stale locks may not always be possible (for
2467 instance, on a shared filesystem). Removing locks may also be
2473 instance, on a shared filesystem). Removing locks may also be
2468 blocked by filesystem permissions.
2474 blocked by filesystem permissions.
2469
2475
2470 Returns 0 if no locks are held.
2476 Returns 0 if no locks are held.
2471
2477
2472 """
2478 """
2473
2479
2474 if opts.get('force_lock'):
2480 if opts.get('force_lock'):
2475 repo.svfs.unlink('lock')
2481 repo.svfs.unlink('lock')
2476 if opts.get('force_wlock'):
2482 if opts.get('force_wlock'):
2477 repo.vfs.unlink('wlock')
2483 repo.vfs.unlink('wlock')
2478 if opts.get('force_lock') or opts.get('force_lock'):
2484 if opts.get('force_lock') or opts.get('force_lock'):
2479 return 0
2485 return 0
2480
2486
2481 now = time.time()
2487 now = time.time()
2482 held = 0
2488 held = 0
2483
2489
2484 def report(vfs, name, method):
2490 def report(vfs, name, method):
2485 # this causes stale locks to get reaped for more accurate reporting
2491 # this causes stale locks to get reaped for more accurate reporting
2486 try:
2492 try:
2487 l = method(False)
2493 l = method(False)
2488 except error.LockHeld:
2494 except error.LockHeld:
2489 l = None
2495 l = None
2490
2496
2491 if l:
2497 if l:
2492 l.release()
2498 l.release()
2493 else:
2499 else:
2494 try:
2500 try:
2495 stat = vfs.lstat(name)
2501 stat = vfs.lstat(name)
2496 age = now - stat.st_mtime
2502 age = now - stat.st_mtime
2497 user = util.username(stat.st_uid)
2503 user = util.username(stat.st_uid)
2498 locker = vfs.readlock(name)
2504 locker = vfs.readlock(name)
2499 if ":" in locker:
2505 if ":" in locker:
2500 host, pid = locker.split(':')
2506 host, pid = locker.split(':')
2501 if host == socket.gethostname():
2507 if host == socket.gethostname():
2502 locker = 'user %s, process %s' % (user, pid)
2508 locker = 'user %s, process %s' % (user, pid)
2503 else:
2509 else:
2504 locker = 'user %s, process %s, host %s' \
2510 locker = 'user %s, process %s, host %s' \
2505 % (user, pid, host)
2511 % (user, pid, host)
2506 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2512 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2507 return 1
2513 return 1
2508 except OSError, e:
2514 except OSError, e:
2509 if e.errno != errno.ENOENT:
2515 if e.errno != errno.ENOENT:
2510 raise
2516 raise
2511
2517
2512 ui.write("%-6s free\n" % (name + ":"))
2518 ui.write("%-6s free\n" % (name + ":"))
2513 return 0
2519 return 0
2514
2520
2515 held += report(repo.svfs, "lock", repo.lock)
2521 held += report(repo.svfs, "lock", repo.lock)
2516 held += report(repo.vfs, "wlock", repo.wlock)
2522 held += report(repo.vfs, "wlock", repo.wlock)
2517
2523
2518 return held
2524 return held
2519
2525
2520 @command('debugobsolete',
2526 @command('debugobsolete',
2521 [('', 'flags', 0, _('markers flag')),
2527 [('', 'flags', 0, _('markers flag')),
2522 ('', 'record-parents', False,
2528 ('', 'record-parents', False,
2523 _('record parent information for the precursor')),
2529 _('record parent information for the precursor')),
2524 ('r', 'rev', [], _('display markers relevant to REV')),
2530 ('r', 'rev', [], _('display markers relevant to REV')),
2525 ] + commitopts2,
2531 ] + commitopts2,
2526 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2532 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2527 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2533 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2528 """create arbitrary obsolete marker
2534 """create arbitrary obsolete marker
2529
2535
2530 With no arguments, displays the list of obsolescence markers."""
2536 With no arguments, displays the list of obsolescence markers."""
2531
2537
2532 def parsenodeid(s):
2538 def parsenodeid(s):
2533 try:
2539 try:
2534 # We do not use revsingle/revrange functions here to accept
2540 # We do not use revsingle/revrange functions here to accept
2535 # arbitrary node identifiers, possibly not present in the
2541 # arbitrary node identifiers, possibly not present in the
2536 # local repository.
2542 # local repository.
2537 n = bin(s)
2543 n = bin(s)
2538 if len(n) != len(nullid):
2544 if len(n) != len(nullid):
2539 raise TypeError()
2545 raise TypeError()
2540 return n
2546 return n
2541 except TypeError:
2547 except TypeError:
2542 raise util.Abort('changeset references must be full hexadecimal '
2548 raise util.Abort('changeset references must be full hexadecimal '
2543 'node identifiers')
2549 'node identifiers')
2544
2550
2545 if precursor is not None:
2551 if precursor is not None:
2546 if opts['rev']:
2552 if opts['rev']:
2547 raise util.Abort('cannot select revision when creating marker')
2553 raise util.Abort('cannot select revision when creating marker')
2548 metadata = {}
2554 metadata = {}
2549 metadata['user'] = opts['user'] or ui.username()
2555 metadata['user'] = opts['user'] or ui.username()
2550 succs = tuple(parsenodeid(succ) for succ in successors)
2556 succs = tuple(parsenodeid(succ) for succ in successors)
2551 l = repo.lock()
2557 l = repo.lock()
2552 try:
2558 try:
2553 tr = repo.transaction('debugobsolete')
2559 tr = repo.transaction('debugobsolete')
2554 try:
2560 try:
2555 date = opts.get('date')
2561 date = opts.get('date')
2556 if date:
2562 if date:
2557 date = util.parsedate(date)
2563 date = util.parsedate(date)
2558 else:
2564 else:
2559 date = None
2565 date = None
2560 prec = parsenodeid(precursor)
2566 prec = parsenodeid(precursor)
2561 parents = None
2567 parents = None
2562 if opts['record_parents']:
2568 if opts['record_parents']:
2563 if prec not in repo.unfiltered():
2569 if prec not in repo.unfiltered():
2564 raise util.Abort('cannot used --record-parents on '
2570 raise util.Abort('cannot used --record-parents on '
2565 'unknown changesets')
2571 'unknown changesets')
2566 parents = repo.unfiltered()[prec].parents()
2572 parents = repo.unfiltered()[prec].parents()
2567 parents = tuple(p.node() for p in parents)
2573 parents = tuple(p.node() for p in parents)
2568 repo.obsstore.create(tr, prec, succs, opts['flags'],
2574 repo.obsstore.create(tr, prec, succs, opts['flags'],
2569 parents=parents, date=date,
2575 parents=parents, date=date,
2570 metadata=metadata)
2576 metadata=metadata)
2571 tr.close()
2577 tr.close()
2572 except ValueError, exc:
2578 except ValueError, exc:
2573 raise util.Abort(_('bad obsmarker input: %s') % exc)
2579 raise util.Abort(_('bad obsmarker input: %s') % exc)
2574 finally:
2580 finally:
2575 tr.release()
2581 tr.release()
2576 finally:
2582 finally:
2577 l.release()
2583 l.release()
2578 else:
2584 else:
2579 if opts['rev']:
2585 if opts['rev']:
2580 revs = scmutil.revrange(repo, opts['rev'])
2586 revs = scmutil.revrange(repo, opts['rev'])
2581 nodes = [repo[r].node() for r in revs]
2587 nodes = [repo[r].node() for r in revs]
2582 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2588 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2583 markers.sort(key=lambda x: x._data)
2589 markers.sort(key=lambda x: x._data)
2584 else:
2590 else:
2585 markers = obsolete.getmarkers(repo)
2591 markers = obsolete.getmarkers(repo)
2586
2592
2587 for m in markers:
2593 for m in markers:
2588 cmdutil.showmarker(ui, m)
2594 cmdutil.showmarker(ui, m)
2589
2595
2590 @command('debugpathcomplete',
2596 @command('debugpathcomplete',
2591 [('f', 'full', None, _('complete an entire path')),
2597 [('f', 'full', None, _('complete an entire path')),
2592 ('n', 'normal', None, _('show only normal files')),
2598 ('n', 'normal', None, _('show only normal files')),
2593 ('a', 'added', None, _('show only added files')),
2599 ('a', 'added', None, _('show only added files')),
2594 ('r', 'removed', None, _('show only removed files'))],
2600 ('r', 'removed', None, _('show only removed files'))],
2595 _('FILESPEC...'))
2601 _('FILESPEC...'))
2596 def debugpathcomplete(ui, repo, *specs, **opts):
2602 def debugpathcomplete(ui, repo, *specs, **opts):
2597 '''complete part or all of a tracked path
2603 '''complete part or all of a tracked path
2598
2604
2599 This command supports shells that offer path name completion. It
2605 This command supports shells that offer path name completion. It
2600 currently completes only files already known to the dirstate.
2606 currently completes only files already known to the dirstate.
2601
2607
2602 Completion extends only to the next path segment unless
2608 Completion extends only to the next path segment unless
2603 --full is specified, in which case entire paths are used.'''
2609 --full is specified, in which case entire paths are used.'''
2604
2610
2605 def complete(path, acceptable):
2611 def complete(path, acceptable):
2606 dirstate = repo.dirstate
2612 dirstate = repo.dirstate
2607 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2613 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2608 rootdir = repo.root + os.sep
2614 rootdir = repo.root + os.sep
2609 if spec != repo.root and not spec.startswith(rootdir):
2615 if spec != repo.root and not spec.startswith(rootdir):
2610 return [], []
2616 return [], []
2611 if os.path.isdir(spec):
2617 if os.path.isdir(spec):
2612 spec += '/'
2618 spec += '/'
2613 spec = spec[len(rootdir):]
2619 spec = spec[len(rootdir):]
2614 fixpaths = os.sep != '/'
2620 fixpaths = os.sep != '/'
2615 if fixpaths:
2621 if fixpaths:
2616 spec = spec.replace(os.sep, '/')
2622 spec = spec.replace(os.sep, '/')
2617 speclen = len(spec)
2623 speclen = len(spec)
2618 fullpaths = opts['full']
2624 fullpaths = opts['full']
2619 files, dirs = set(), set()
2625 files, dirs = set(), set()
2620 adddir, addfile = dirs.add, files.add
2626 adddir, addfile = dirs.add, files.add
2621 for f, st in dirstate.iteritems():
2627 for f, st in dirstate.iteritems():
2622 if f.startswith(spec) and st[0] in acceptable:
2628 if f.startswith(spec) and st[0] in acceptable:
2623 if fixpaths:
2629 if fixpaths:
2624 f = f.replace('/', os.sep)
2630 f = f.replace('/', os.sep)
2625 if fullpaths:
2631 if fullpaths:
2626 addfile(f)
2632 addfile(f)
2627 continue
2633 continue
2628 s = f.find(os.sep, speclen)
2634 s = f.find(os.sep, speclen)
2629 if s >= 0:
2635 if s >= 0:
2630 adddir(f[:s])
2636 adddir(f[:s])
2631 else:
2637 else:
2632 addfile(f)
2638 addfile(f)
2633 return files, dirs
2639 return files, dirs
2634
2640
2635 acceptable = ''
2641 acceptable = ''
2636 if opts['normal']:
2642 if opts['normal']:
2637 acceptable += 'nm'
2643 acceptable += 'nm'
2638 if opts['added']:
2644 if opts['added']:
2639 acceptable += 'a'
2645 acceptable += 'a'
2640 if opts['removed']:
2646 if opts['removed']:
2641 acceptable += 'r'
2647 acceptable += 'r'
2642 cwd = repo.getcwd()
2648 cwd = repo.getcwd()
2643 if not specs:
2649 if not specs:
2644 specs = ['.']
2650 specs = ['.']
2645
2651
2646 files, dirs = set(), set()
2652 files, dirs = set(), set()
2647 for spec in specs:
2653 for spec in specs:
2648 f, d = complete(spec, acceptable or 'nmar')
2654 f, d = complete(spec, acceptable or 'nmar')
2649 files.update(f)
2655 files.update(f)
2650 dirs.update(d)
2656 dirs.update(d)
2651 files.update(dirs)
2657 files.update(dirs)
2652 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2658 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2653 ui.write('\n')
2659 ui.write('\n')
2654
2660
2655 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2661 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2656 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2662 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2657 '''access the pushkey key/value protocol
2663 '''access the pushkey key/value protocol
2658
2664
2659 With two args, list the keys in the given namespace.
2665 With two args, list the keys in the given namespace.
2660
2666
2661 With five args, set a key to new if it currently is set to old.
2667 With five args, set a key to new if it currently is set to old.
2662 Reports success or failure.
2668 Reports success or failure.
2663 '''
2669 '''
2664
2670
2665 target = hg.peer(ui, {}, repopath)
2671 target = hg.peer(ui, {}, repopath)
2666 if keyinfo:
2672 if keyinfo:
2667 key, old, new = keyinfo
2673 key, old, new = keyinfo
2668 r = target.pushkey(namespace, key, old, new)
2674 r = target.pushkey(namespace, key, old, new)
2669 ui.status(str(r) + '\n')
2675 ui.status(str(r) + '\n')
2670 return not r
2676 return not r
2671 else:
2677 else:
2672 for k, v in sorted(target.listkeys(namespace).iteritems()):
2678 for k, v in sorted(target.listkeys(namespace).iteritems()):
2673 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2679 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2674 v.encode('string-escape')))
2680 v.encode('string-escape')))
2675
2681
2676 @command('debugpvec', [], _('A B'))
2682 @command('debugpvec', [], _('A B'))
2677 def debugpvec(ui, repo, a, b=None):
2683 def debugpvec(ui, repo, a, b=None):
2678 ca = scmutil.revsingle(repo, a)
2684 ca = scmutil.revsingle(repo, a)
2679 cb = scmutil.revsingle(repo, b)
2685 cb = scmutil.revsingle(repo, b)
2680 pa = pvec.ctxpvec(ca)
2686 pa = pvec.ctxpvec(ca)
2681 pb = pvec.ctxpvec(cb)
2687 pb = pvec.ctxpvec(cb)
2682 if pa == pb:
2688 if pa == pb:
2683 rel = "="
2689 rel = "="
2684 elif pa > pb:
2690 elif pa > pb:
2685 rel = ">"
2691 rel = ">"
2686 elif pa < pb:
2692 elif pa < pb:
2687 rel = "<"
2693 rel = "<"
2688 elif pa | pb:
2694 elif pa | pb:
2689 rel = "|"
2695 rel = "|"
2690 ui.write(_("a: %s\n") % pa)
2696 ui.write(_("a: %s\n") % pa)
2691 ui.write(_("b: %s\n") % pb)
2697 ui.write(_("b: %s\n") % pb)
2692 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2698 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2693 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2699 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2694 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2700 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2695 pa.distance(pb), rel))
2701 pa.distance(pb), rel))
2696
2702
2697 @command('debugrebuilddirstate|debugrebuildstate',
2703 @command('debugrebuilddirstate|debugrebuildstate',
2698 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2704 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2699 _('[-r REV]'))
2705 _('[-r REV]'))
2700 def debugrebuilddirstate(ui, repo, rev):
2706 def debugrebuilddirstate(ui, repo, rev):
2701 """rebuild the dirstate as it would look like for the given revision
2707 """rebuild the dirstate as it would look like for the given revision
2702
2708
2703 If no revision is specified the first current parent will be used.
2709 If no revision is specified the first current parent will be used.
2704
2710
2705 The dirstate will be set to the files of the given revision.
2711 The dirstate will be set to the files of the given revision.
2706 The actual working directory content or existing dirstate
2712 The actual working directory content or existing dirstate
2707 information such as adds or removes is not considered.
2713 information such as adds or removes is not considered.
2708
2714
2709 One use of this command is to make the next :hg:`status` invocation
2715 One use of this command is to make the next :hg:`status` invocation
2710 check the actual file content.
2716 check the actual file content.
2711 """
2717 """
2712 ctx = scmutil.revsingle(repo, rev)
2718 ctx = scmutil.revsingle(repo, rev)
2713 wlock = repo.wlock()
2719 wlock = repo.wlock()
2714 try:
2720 try:
2715 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2721 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2716 finally:
2722 finally:
2717 wlock.release()
2723 wlock.release()
2718
2724
2719 @command('debugrename',
2725 @command('debugrename',
2720 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2726 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2721 _('[-r REV] FILE'))
2727 _('[-r REV] FILE'))
2722 def debugrename(ui, repo, file1, *pats, **opts):
2728 def debugrename(ui, repo, file1, *pats, **opts):
2723 """dump rename information"""
2729 """dump rename information"""
2724
2730
2725 ctx = scmutil.revsingle(repo, opts.get('rev'))
2731 ctx = scmutil.revsingle(repo, opts.get('rev'))
2726 m = scmutil.match(ctx, (file1,) + pats, opts)
2732 m = scmutil.match(ctx, (file1,) + pats, opts)
2727 for abs in ctx.walk(m):
2733 for abs in ctx.walk(m):
2728 fctx = ctx[abs]
2734 fctx = ctx[abs]
2729 o = fctx.filelog().renamed(fctx.filenode())
2735 o = fctx.filelog().renamed(fctx.filenode())
2730 rel = m.rel(abs)
2736 rel = m.rel(abs)
2731 if o:
2737 if o:
2732 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2738 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2733 else:
2739 else:
2734 ui.write(_("%s not renamed\n") % rel)
2740 ui.write(_("%s not renamed\n") % rel)
2735
2741
2736 @command('debugrevlog',
2742 @command('debugrevlog',
2737 [('c', 'changelog', False, _('open changelog')),
2743 [('c', 'changelog', False, _('open changelog')),
2738 ('m', 'manifest', False, _('open manifest')),
2744 ('m', 'manifest', False, _('open manifest')),
2739 ('', 'dir', False, _('open directory manifest')),
2745 ('', 'dir', False, _('open directory manifest')),
2740 ('d', 'dump', False, _('dump index data'))],
2746 ('d', 'dump', False, _('dump index data'))],
2741 _('-c|-m|FILE'),
2747 _('-c|-m|FILE'),
2742 optionalrepo=True)
2748 optionalrepo=True)
2743 def debugrevlog(ui, repo, file_=None, **opts):
2749 def debugrevlog(ui, repo, file_=None, **opts):
2744 """show data and statistics about a revlog"""
2750 """show data and statistics about a revlog"""
2745 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2751 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2746
2752
2747 if opts.get("dump"):
2753 if opts.get("dump"):
2748 numrevs = len(r)
2754 numrevs = len(r)
2749 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2755 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2750 " rawsize totalsize compression heads chainlen\n")
2756 " rawsize totalsize compression heads chainlen\n")
2751 ts = 0
2757 ts = 0
2752 heads = set()
2758 heads = set()
2753
2759
2754 for rev in xrange(numrevs):
2760 for rev in xrange(numrevs):
2755 dbase = r.deltaparent(rev)
2761 dbase = r.deltaparent(rev)
2756 if dbase == -1:
2762 if dbase == -1:
2757 dbase = rev
2763 dbase = rev
2758 cbase = r.chainbase(rev)
2764 cbase = r.chainbase(rev)
2759 clen = r.chainlen(rev)
2765 clen = r.chainlen(rev)
2760 p1, p2 = r.parentrevs(rev)
2766 p1, p2 = r.parentrevs(rev)
2761 rs = r.rawsize(rev)
2767 rs = r.rawsize(rev)
2762 ts = ts + rs
2768 ts = ts + rs
2763 heads -= set(r.parentrevs(rev))
2769 heads -= set(r.parentrevs(rev))
2764 heads.add(rev)
2770 heads.add(rev)
2765 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2771 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2766 "%11d %5d %8d\n" %
2772 "%11d %5d %8d\n" %
2767 (rev, p1, p2, r.start(rev), r.end(rev),
2773 (rev, p1, p2, r.start(rev), r.end(rev),
2768 r.start(dbase), r.start(cbase),
2774 r.start(dbase), r.start(cbase),
2769 r.start(p1), r.start(p2),
2775 r.start(p1), r.start(p2),
2770 rs, ts, ts / r.end(rev), len(heads), clen))
2776 rs, ts, ts / r.end(rev), len(heads), clen))
2771 return 0
2777 return 0
2772
2778
2773 v = r.version
2779 v = r.version
2774 format = v & 0xFFFF
2780 format = v & 0xFFFF
2775 flags = []
2781 flags = []
2776 gdelta = False
2782 gdelta = False
2777 if v & revlog.REVLOGNGINLINEDATA:
2783 if v & revlog.REVLOGNGINLINEDATA:
2778 flags.append('inline')
2784 flags.append('inline')
2779 if v & revlog.REVLOGGENERALDELTA:
2785 if v & revlog.REVLOGGENERALDELTA:
2780 gdelta = True
2786 gdelta = True
2781 flags.append('generaldelta')
2787 flags.append('generaldelta')
2782 if not flags:
2788 if not flags:
2783 flags = ['(none)']
2789 flags = ['(none)']
2784
2790
2785 nummerges = 0
2791 nummerges = 0
2786 numfull = 0
2792 numfull = 0
2787 numprev = 0
2793 numprev = 0
2788 nump1 = 0
2794 nump1 = 0
2789 nump2 = 0
2795 nump2 = 0
2790 numother = 0
2796 numother = 0
2791 nump1prev = 0
2797 nump1prev = 0
2792 nump2prev = 0
2798 nump2prev = 0
2793 chainlengths = []
2799 chainlengths = []
2794
2800
2795 datasize = [None, 0, 0L]
2801 datasize = [None, 0, 0L]
2796 fullsize = [None, 0, 0L]
2802 fullsize = [None, 0, 0L]
2797 deltasize = [None, 0, 0L]
2803 deltasize = [None, 0, 0L]
2798
2804
2799 def addsize(size, l):
2805 def addsize(size, l):
2800 if l[0] is None or size < l[0]:
2806 if l[0] is None or size < l[0]:
2801 l[0] = size
2807 l[0] = size
2802 if size > l[1]:
2808 if size > l[1]:
2803 l[1] = size
2809 l[1] = size
2804 l[2] += size
2810 l[2] += size
2805
2811
2806 numrevs = len(r)
2812 numrevs = len(r)
2807 for rev in xrange(numrevs):
2813 for rev in xrange(numrevs):
2808 p1, p2 = r.parentrevs(rev)
2814 p1, p2 = r.parentrevs(rev)
2809 delta = r.deltaparent(rev)
2815 delta = r.deltaparent(rev)
2810 if format > 0:
2816 if format > 0:
2811 addsize(r.rawsize(rev), datasize)
2817 addsize(r.rawsize(rev), datasize)
2812 if p2 != nullrev:
2818 if p2 != nullrev:
2813 nummerges += 1
2819 nummerges += 1
2814 size = r.length(rev)
2820 size = r.length(rev)
2815 if delta == nullrev:
2821 if delta == nullrev:
2816 chainlengths.append(0)
2822 chainlengths.append(0)
2817 numfull += 1
2823 numfull += 1
2818 addsize(size, fullsize)
2824 addsize(size, fullsize)
2819 else:
2825 else:
2820 chainlengths.append(chainlengths[delta] + 1)
2826 chainlengths.append(chainlengths[delta] + 1)
2821 addsize(size, deltasize)
2827 addsize(size, deltasize)
2822 if delta == rev - 1:
2828 if delta == rev - 1:
2823 numprev += 1
2829 numprev += 1
2824 if delta == p1:
2830 if delta == p1:
2825 nump1prev += 1
2831 nump1prev += 1
2826 elif delta == p2:
2832 elif delta == p2:
2827 nump2prev += 1
2833 nump2prev += 1
2828 elif delta == p1:
2834 elif delta == p1:
2829 nump1 += 1
2835 nump1 += 1
2830 elif delta == p2:
2836 elif delta == p2:
2831 nump2 += 1
2837 nump2 += 1
2832 elif delta != nullrev:
2838 elif delta != nullrev:
2833 numother += 1
2839 numother += 1
2834
2840
2835 # Adjust size min value for empty cases
2841 # Adjust size min value for empty cases
2836 for size in (datasize, fullsize, deltasize):
2842 for size in (datasize, fullsize, deltasize):
2837 if size[0] is None:
2843 if size[0] is None:
2838 size[0] = 0
2844 size[0] = 0
2839
2845
2840 numdeltas = numrevs - numfull
2846 numdeltas = numrevs - numfull
2841 numoprev = numprev - nump1prev - nump2prev
2847 numoprev = numprev - nump1prev - nump2prev
2842 totalrawsize = datasize[2]
2848 totalrawsize = datasize[2]
2843 datasize[2] /= numrevs
2849 datasize[2] /= numrevs
2844 fulltotal = fullsize[2]
2850 fulltotal = fullsize[2]
2845 fullsize[2] /= numfull
2851 fullsize[2] /= numfull
2846 deltatotal = deltasize[2]
2852 deltatotal = deltasize[2]
2847 if numrevs - numfull > 0:
2853 if numrevs - numfull > 0:
2848 deltasize[2] /= numrevs - numfull
2854 deltasize[2] /= numrevs - numfull
2849 totalsize = fulltotal + deltatotal
2855 totalsize = fulltotal + deltatotal
2850 avgchainlen = sum(chainlengths) / numrevs
2856 avgchainlen = sum(chainlengths) / numrevs
2851 maxchainlen = max(chainlengths)
2857 maxchainlen = max(chainlengths)
2852 compratio = totalrawsize / totalsize
2858 compratio = totalrawsize / totalsize
2853
2859
2854 basedfmtstr = '%%%dd\n'
2860 basedfmtstr = '%%%dd\n'
2855 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2861 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2856
2862
2857 def dfmtstr(max):
2863 def dfmtstr(max):
2858 return basedfmtstr % len(str(max))
2864 return basedfmtstr % len(str(max))
2859 def pcfmtstr(max, padding=0):
2865 def pcfmtstr(max, padding=0):
2860 return basepcfmtstr % (len(str(max)), ' ' * padding)
2866 return basepcfmtstr % (len(str(max)), ' ' * padding)
2861
2867
2862 def pcfmt(value, total):
2868 def pcfmt(value, total):
2863 return (value, 100 * float(value) / total)
2869 return (value, 100 * float(value) / total)
2864
2870
2865 ui.write(('format : %d\n') % format)
2871 ui.write(('format : %d\n') % format)
2866 ui.write(('flags : %s\n') % ', '.join(flags))
2872 ui.write(('flags : %s\n') % ', '.join(flags))
2867
2873
2868 ui.write('\n')
2874 ui.write('\n')
2869 fmt = pcfmtstr(totalsize)
2875 fmt = pcfmtstr(totalsize)
2870 fmt2 = dfmtstr(totalsize)
2876 fmt2 = dfmtstr(totalsize)
2871 ui.write(('revisions : ') + fmt2 % numrevs)
2877 ui.write(('revisions : ') + fmt2 % numrevs)
2872 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2878 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2873 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2879 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2874 ui.write(('revisions : ') + fmt2 % numrevs)
2880 ui.write(('revisions : ') + fmt2 % numrevs)
2875 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2881 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2876 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2882 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2877 ui.write(('revision size : ') + fmt2 % totalsize)
2883 ui.write(('revision size : ') + fmt2 % totalsize)
2878 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2884 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2879 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2885 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2880
2886
2881 ui.write('\n')
2887 ui.write('\n')
2882 fmt = dfmtstr(max(avgchainlen, compratio))
2888 fmt = dfmtstr(max(avgchainlen, compratio))
2883 ui.write(('avg chain length : ') + fmt % avgchainlen)
2889 ui.write(('avg chain length : ') + fmt % avgchainlen)
2884 ui.write(('max chain length : ') + fmt % maxchainlen)
2890 ui.write(('max chain length : ') + fmt % maxchainlen)
2885 ui.write(('compression ratio : ') + fmt % compratio)
2891 ui.write(('compression ratio : ') + fmt % compratio)
2886
2892
2887 if format > 0:
2893 if format > 0:
2888 ui.write('\n')
2894 ui.write('\n')
2889 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2895 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2890 % tuple(datasize))
2896 % tuple(datasize))
2891 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2897 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2892 % tuple(fullsize))
2898 % tuple(fullsize))
2893 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2899 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2894 % tuple(deltasize))
2900 % tuple(deltasize))
2895
2901
2896 if numdeltas > 0:
2902 if numdeltas > 0:
2897 ui.write('\n')
2903 ui.write('\n')
2898 fmt = pcfmtstr(numdeltas)
2904 fmt = pcfmtstr(numdeltas)
2899 fmt2 = pcfmtstr(numdeltas, 4)
2905 fmt2 = pcfmtstr(numdeltas, 4)
2900 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2906 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2901 if numprev > 0:
2907 if numprev > 0:
2902 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2908 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2903 numprev))
2909 numprev))
2904 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2910 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2905 numprev))
2911 numprev))
2906 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2912 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2907 numprev))
2913 numprev))
2908 if gdelta:
2914 if gdelta:
2909 ui.write(('deltas against p1 : ')
2915 ui.write(('deltas against p1 : ')
2910 + fmt % pcfmt(nump1, numdeltas))
2916 + fmt % pcfmt(nump1, numdeltas))
2911 ui.write(('deltas against p2 : ')
2917 ui.write(('deltas against p2 : ')
2912 + fmt % pcfmt(nump2, numdeltas))
2918 + fmt % pcfmt(nump2, numdeltas))
2913 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2919 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2914 numdeltas))
2920 numdeltas))
2915
2921
2916 @command('debugrevspec',
2922 @command('debugrevspec',
2917 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2923 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2918 ('REVSPEC'))
2924 ('REVSPEC'))
2919 def debugrevspec(ui, repo, expr, **opts):
2925 def debugrevspec(ui, repo, expr, **opts):
2920 """parse and apply a revision specification
2926 """parse and apply a revision specification
2921
2927
2922 Use --verbose to print the parsed tree before and after aliases
2928 Use --verbose to print the parsed tree before and after aliases
2923 expansion.
2929 expansion.
2924 """
2930 """
2925 if ui.verbose:
2931 if ui.verbose:
2926 tree = revset.parse(expr)
2932 tree = revset.parse(expr)
2927 ui.note(revset.prettyformat(tree), "\n")
2933 ui.note(revset.prettyformat(tree), "\n")
2928 newtree = revset.findaliases(ui, tree)
2934 newtree = revset.findaliases(ui, tree)
2929 if newtree != tree:
2935 if newtree != tree:
2930 ui.note(revset.prettyformat(newtree), "\n")
2936 ui.note(revset.prettyformat(newtree), "\n")
2931 tree = newtree
2937 tree = newtree
2932 newtree = revset.foldconcat(tree)
2938 newtree = revset.foldconcat(tree)
2933 if newtree != tree:
2939 if newtree != tree:
2934 ui.note(revset.prettyformat(newtree), "\n")
2940 ui.note(revset.prettyformat(newtree), "\n")
2935 if opts["optimize"]:
2941 if opts["optimize"]:
2936 weight, optimizedtree = revset.optimize(newtree, True)
2942 weight, optimizedtree = revset.optimize(newtree, True)
2937 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2943 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2938 func = revset.match(ui, expr)
2944 func = revset.match(ui, expr)
2939 revs = func(repo)
2945 revs = func(repo)
2940 if ui.verbose:
2946 if ui.verbose:
2941 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2947 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2942 for c in revs:
2948 for c in revs:
2943 ui.write("%s\n" % c)
2949 ui.write("%s\n" % c)
2944
2950
2945 @command('debugsetparents', [], _('REV1 [REV2]'))
2951 @command('debugsetparents', [], _('REV1 [REV2]'))
2946 def debugsetparents(ui, repo, rev1, rev2=None):
2952 def debugsetparents(ui, repo, rev1, rev2=None):
2947 """manually set the parents of the current working directory
2953 """manually set the parents of the current working directory
2948
2954
2949 This is useful for writing repository conversion tools, but should
2955 This is useful for writing repository conversion tools, but should
2950 be used with care. For example, neither the working directory nor the
2956 be used with care. For example, neither the working directory nor the
2951 dirstate is updated, so file status may be incorrect after running this
2957 dirstate is updated, so file status may be incorrect after running this
2952 command.
2958 command.
2953
2959
2954 Returns 0 on success.
2960 Returns 0 on success.
2955 """
2961 """
2956
2962
2957 r1 = scmutil.revsingle(repo, rev1).node()
2963 r1 = scmutil.revsingle(repo, rev1).node()
2958 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2964 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2959
2965
2960 wlock = repo.wlock()
2966 wlock = repo.wlock()
2961 try:
2967 try:
2962 repo.dirstate.beginparentchange()
2968 repo.dirstate.beginparentchange()
2963 repo.setparents(r1, r2)
2969 repo.setparents(r1, r2)
2964 repo.dirstate.endparentchange()
2970 repo.dirstate.endparentchange()
2965 finally:
2971 finally:
2966 wlock.release()
2972 wlock.release()
2967
2973
2968 @command('debugdirstate|debugstate',
2974 @command('debugdirstate|debugstate',
2969 [('', 'nodates', None, _('do not display the saved mtime')),
2975 [('', 'nodates', None, _('do not display the saved mtime')),
2970 ('', 'datesort', None, _('sort by saved mtime'))],
2976 ('', 'datesort', None, _('sort by saved mtime'))],
2971 _('[OPTION]...'))
2977 _('[OPTION]...'))
2972 def debugstate(ui, repo, nodates=None, datesort=None):
2978 def debugstate(ui, repo, nodates=None, datesort=None):
2973 """show the contents of the current dirstate"""
2979 """show the contents of the current dirstate"""
2974 timestr = ""
2980 timestr = ""
2975 if datesort:
2981 if datesort:
2976 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2982 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2977 else:
2983 else:
2978 keyfunc = None # sort by filename
2984 keyfunc = None # sort by filename
2979 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2985 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2980 if ent[3] == -1:
2986 if ent[3] == -1:
2981 timestr = 'unset '
2987 timestr = 'unset '
2982 elif nodates:
2988 elif nodates:
2983 timestr = 'set '
2989 timestr = 'set '
2984 else:
2990 else:
2985 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2991 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2986 time.localtime(ent[3]))
2992 time.localtime(ent[3]))
2987 if ent[1] & 020000:
2993 if ent[1] & 020000:
2988 mode = 'lnk'
2994 mode = 'lnk'
2989 else:
2995 else:
2990 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2996 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2991 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2997 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2992 for f in repo.dirstate.copies():
2998 for f in repo.dirstate.copies():
2993 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2999 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2994
3000
2995 @command('debugsub',
3001 @command('debugsub',
2996 [('r', 'rev', '',
3002 [('r', 'rev', '',
2997 _('revision to check'), _('REV'))],
3003 _('revision to check'), _('REV'))],
2998 _('[-r REV] [REV]'))
3004 _('[-r REV] [REV]'))
2999 def debugsub(ui, repo, rev=None):
3005 def debugsub(ui, repo, rev=None):
3000 ctx = scmutil.revsingle(repo, rev, None)
3006 ctx = scmutil.revsingle(repo, rev, None)
3001 for k, v in sorted(ctx.substate.items()):
3007 for k, v in sorted(ctx.substate.items()):
3002 ui.write(('path %s\n') % k)
3008 ui.write(('path %s\n') % k)
3003 ui.write((' source %s\n') % v[0])
3009 ui.write((' source %s\n') % v[0])
3004 ui.write((' revision %s\n') % v[1])
3010 ui.write((' revision %s\n') % v[1])
3005
3011
3006 @command('debugsuccessorssets',
3012 @command('debugsuccessorssets',
3007 [],
3013 [],
3008 _('[REV]'))
3014 _('[REV]'))
3009 def debugsuccessorssets(ui, repo, *revs):
3015 def debugsuccessorssets(ui, repo, *revs):
3010 """show set of successors for revision
3016 """show set of successors for revision
3011
3017
3012 A successors set of changeset A is a consistent group of revisions that
3018 A successors set of changeset A is a consistent group of revisions that
3013 succeed A. It contains non-obsolete changesets only.
3019 succeed A. It contains non-obsolete changesets only.
3014
3020
3015 In most cases a changeset A has a single successors set containing a single
3021 In most cases a changeset A has a single successors set containing a single
3016 successor (changeset A replaced by A').
3022 successor (changeset A replaced by A').
3017
3023
3018 A changeset that is made obsolete with no successors are called "pruned".
3024 A changeset that is made obsolete with no successors are called "pruned".
3019 Such changesets have no successors sets at all.
3025 Such changesets have no successors sets at all.
3020
3026
3021 A changeset that has been "split" will have a successors set containing
3027 A changeset that has been "split" will have a successors set containing
3022 more than one successor.
3028 more than one successor.
3023
3029
3024 A changeset that has been rewritten in multiple different ways is called
3030 A changeset that has been rewritten in multiple different ways is called
3025 "divergent". Such changesets have multiple successor sets (each of which
3031 "divergent". Such changesets have multiple successor sets (each of which
3026 may also be split, i.e. have multiple successors).
3032 may also be split, i.e. have multiple successors).
3027
3033
3028 Results are displayed as follows::
3034 Results are displayed as follows::
3029
3035
3030 <rev1>
3036 <rev1>
3031 <successors-1A>
3037 <successors-1A>
3032 <rev2>
3038 <rev2>
3033 <successors-2A>
3039 <successors-2A>
3034 <successors-2B1> <successors-2B2> <successors-2B3>
3040 <successors-2B1> <successors-2B2> <successors-2B3>
3035
3041
3036 Here rev2 has two possible (i.e. divergent) successors sets. The first
3042 Here rev2 has two possible (i.e. divergent) successors sets. The first
3037 holds one element, whereas the second holds three (i.e. the changeset has
3043 holds one element, whereas the second holds three (i.e. the changeset has
3038 been split).
3044 been split).
3039 """
3045 """
3040 # passed to successorssets caching computation from one call to another
3046 # passed to successorssets caching computation from one call to another
3041 cache = {}
3047 cache = {}
3042 ctx2str = str
3048 ctx2str = str
3043 node2str = short
3049 node2str = short
3044 if ui.debug():
3050 if ui.debug():
3045 def ctx2str(ctx):
3051 def ctx2str(ctx):
3046 return ctx.hex()
3052 return ctx.hex()
3047 node2str = hex
3053 node2str = hex
3048 for rev in scmutil.revrange(repo, revs):
3054 for rev in scmutil.revrange(repo, revs):
3049 ctx = repo[rev]
3055 ctx = repo[rev]
3050 ui.write('%s\n'% ctx2str(ctx))
3056 ui.write('%s\n'% ctx2str(ctx))
3051 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3057 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3052 if succsset:
3058 if succsset:
3053 ui.write(' ')
3059 ui.write(' ')
3054 ui.write(node2str(succsset[0]))
3060 ui.write(node2str(succsset[0]))
3055 for node in succsset[1:]:
3061 for node in succsset[1:]:
3056 ui.write(' ')
3062 ui.write(' ')
3057 ui.write(node2str(node))
3063 ui.write(node2str(node))
3058 ui.write('\n')
3064 ui.write('\n')
3059
3065
3060 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3066 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3061 def debugwalk(ui, repo, *pats, **opts):
3067 def debugwalk(ui, repo, *pats, **opts):
3062 """show how files match on given patterns"""
3068 """show how files match on given patterns"""
3063 m = scmutil.match(repo[None], pats, opts)
3069 m = scmutil.match(repo[None], pats, opts)
3064 items = list(repo.walk(m))
3070 items = list(repo.walk(m))
3065 if not items:
3071 if not items:
3066 return
3072 return
3067 f = lambda fn: fn
3073 f = lambda fn: fn
3068 if ui.configbool('ui', 'slash') and os.sep != '/':
3074 if ui.configbool('ui', 'slash') and os.sep != '/':
3069 f = lambda fn: util.normpath(fn)
3075 f = lambda fn: util.normpath(fn)
3070 fmt = 'f %%-%ds %%-%ds %%s' % (
3076 fmt = 'f %%-%ds %%-%ds %%s' % (
3071 max([len(abs) for abs in items]),
3077 max([len(abs) for abs in items]),
3072 max([len(m.rel(abs)) for abs in items]))
3078 max([len(m.rel(abs)) for abs in items]))
3073 for abs in items:
3079 for abs in items:
3074 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3080 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3075 ui.write("%s\n" % line.rstrip())
3081 ui.write("%s\n" % line.rstrip())
3076
3082
3077 @command('debugwireargs',
3083 @command('debugwireargs',
3078 [('', 'three', '', 'three'),
3084 [('', 'three', '', 'three'),
3079 ('', 'four', '', 'four'),
3085 ('', 'four', '', 'four'),
3080 ('', 'five', '', 'five'),
3086 ('', 'five', '', 'five'),
3081 ] + remoteopts,
3087 ] + remoteopts,
3082 _('REPO [OPTIONS]... [ONE [TWO]]'),
3088 _('REPO [OPTIONS]... [ONE [TWO]]'),
3083 norepo=True)
3089 norepo=True)
3084 def debugwireargs(ui, repopath, *vals, **opts):
3090 def debugwireargs(ui, repopath, *vals, **opts):
3085 repo = hg.peer(ui, opts, repopath)
3091 repo = hg.peer(ui, opts, repopath)
3086 for opt in remoteopts:
3092 for opt in remoteopts:
3087 del opts[opt[1]]
3093 del opts[opt[1]]
3088 args = {}
3094 args = {}
3089 for k, v in opts.iteritems():
3095 for k, v in opts.iteritems():
3090 if v:
3096 if v:
3091 args[k] = v
3097 args[k] = v
3092 # run twice to check that we don't mess up the stream for the next command
3098 # run twice to check that we don't mess up the stream for the next command
3093 res1 = repo.debugwireargs(*vals, **args)
3099 res1 = repo.debugwireargs(*vals, **args)
3094 res2 = repo.debugwireargs(*vals, **args)
3100 res2 = repo.debugwireargs(*vals, **args)
3095 ui.write("%s\n" % res1)
3101 ui.write("%s\n" % res1)
3096 if res1 != res2:
3102 if res1 != res2:
3097 ui.warn("%s\n" % res2)
3103 ui.warn("%s\n" % res2)
3098
3104
3099 @command('^diff',
3105 @command('^diff',
3100 [('r', 'rev', [], _('revision'), _('REV')),
3106 [('r', 'rev', [], _('revision'), _('REV')),
3101 ('c', 'change', '', _('change made by revision'), _('REV'))
3107 ('c', 'change', '', _('change made by revision'), _('REV'))
3102 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3108 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3103 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3109 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3104 inferrepo=True)
3110 inferrepo=True)
3105 def diff(ui, repo, *pats, **opts):
3111 def diff(ui, repo, *pats, **opts):
3106 """diff repository (or selected files)
3112 """diff repository (or selected files)
3107
3113
3108 Show differences between revisions for the specified files.
3114 Show differences between revisions for the specified files.
3109
3115
3110 Differences between files are shown using the unified diff format.
3116 Differences between files are shown using the unified diff format.
3111
3117
3112 .. note::
3118 .. note::
3113
3119
3114 diff may generate unexpected results for merges, as it will
3120 diff may generate unexpected results for merges, as it will
3115 default to comparing against the working directory's first
3121 default to comparing against the working directory's first
3116 parent changeset if no revisions are specified.
3122 parent changeset if no revisions are specified.
3117
3123
3118 When two revision arguments are given, then changes are shown
3124 When two revision arguments are given, then changes are shown
3119 between those revisions. If only one revision is specified then
3125 between those revisions. If only one revision is specified then
3120 that revision is compared to the working directory, and, when no
3126 that revision is compared to the working directory, and, when no
3121 revisions are specified, the working directory files are compared
3127 revisions are specified, the working directory files are compared
3122 to its parent.
3128 to its parent.
3123
3129
3124 Alternatively you can specify -c/--change with a revision to see
3130 Alternatively you can specify -c/--change with a revision to see
3125 the changes in that changeset relative to its first parent.
3131 the changes in that changeset relative to its first parent.
3126
3132
3127 Without the -a/--text option, diff will avoid generating diffs of
3133 Without the -a/--text option, diff will avoid generating diffs of
3128 files it detects as binary. With -a, diff will generate a diff
3134 files it detects as binary. With -a, diff will generate a diff
3129 anyway, probably with undesirable results.
3135 anyway, probably with undesirable results.
3130
3136
3131 Use the -g/--git option to generate diffs in the git extended diff
3137 Use the -g/--git option to generate diffs in the git extended diff
3132 format. For more information, read :hg:`help diffs`.
3138 format. For more information, read :hg:`help diffs`.
3133
3139
3134 .. container:: verbose
3140 .. container:: verbose
3135
3141
3136 Examples:
3142 Examples:
3137
3143
3138 - compare a file in the current working directory to its parent::
3144 - compare a file in the current working directory to its parent::
3139
3145
3140 hg diff foo.c
3146 hg diff foo.c
3141
3147
3142 - compare two historical versions of a directory, with rename info::
3148 - compare two historical versions of a directory, with rename info::
3143
3149
3144 hg diff --git -r 1.0:1.2 lib/
3150 hg diff --git -r 1.0:1.2 lib/
3145
3151
3146 - get change stats relative to the last change on some date::
3152 - get change stats relative to the last change on some date::
3147
3153
3148 hg diff --stat -r "date('may 2')"
3154 hg diff --stat -r "date('may 2')"
3149
3155
3150 - diff all newly-added files that contain a keyword::
3156 - diff all newly-added files that contain a keyword::
3151
3157
3152 hg diff "set:added() and grep(GNU)"
3158 hg diff "set:added() and grep(GNU)"
3153
3159
3154 - compare a revision and its parents::
3160 - compare a revision and its parents::
3155
3161
3156 hg diff -c 9353 # compare against first parent
3162 hg diff -c 9353 # compare against first parent
3157 hg diff -r 9353^:9353 # same using revset syntax
3163 hg diff -r 9353^:9353 # same using revset syntax
3158 hg diff -r 9353^2:9353 # compare against the second parent
3164 hg diff -r 9353^2:9353 # compare against the second parent
3159
3165
3160 Returns 0 on success.
3166 Returns 0 on success.
3161 """
3167 """
3162
3168
3163 revs = opts.get('rev')
3169 revs = opts.get('rev')
3164 change = opts.get('change')
3170 change = opts.get('change')
3165 stat = opts.get('stat')
3171 stat = opts.get('stat')
3166 reverse = opts.get('reverse')
3172 reverse = opts.get('reverse')
3167
3173
3168 if revs and change:
3174 if revs and change:
3169 msg = _('cannot specify --rev and --change at the same time')
3175 msg = _('cannot specify --rev and --change at the same time')
3170 raise util.Abort(msg)
3176 raise util.Abort(msg)
3171 elif change:
3177 elif change:
3172 node2 = scmutil.revsingle(repo, change, None).node()
3178 node2 = scmutil.revsingle(repo, change, None).node()
3173 node1 = repo[node2].p1().node()
3179 node1 = repo[node2].p1().node()
3174 else:
3180 else:
3175 node1, node2 = scmutil.revpair(repo, revs)
3181 node1, node2 = scmutil.revpair(repo, revs)
3176
3182
3177 if reverse:
3183 if reverse:
3178 node1, node2 = node2, node1
3184 node1, node2 = node2, node1
3179
3185
3180 diffopts = patch.diffallopts(ui, opts)
3186 diffopts = patch.diffallopts(ui, opts)
3181 m = scmutil.match(repo[node2], pats, opts)
3187 m = scmutil.match(repo[node2], pats, opts)
3182 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3188 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3183 listsubrepos=opts.get('subrepos'),
3189 listsubrepos=opts.get('subrepos'),
3184 root=opts.get('root'))
3190 root=opts.get('root'))
3185
3191
3186 @command('^export',
3192 @command('^export',
3187 [('o', 'output', '',
3193 [('o', 'output', '',
3188 _('print output to file with formatted name'), _('FORMAT')),
3194 _('print output to file with formatted name'), _('FORMAT')),
3189 ('', 'switch-parent', None, _('diff against the second parent')),
3195 ('', 'switch-parent', None, _('diff against the second parent')),
3190 ('r', 'rev', [], _('revisions to export'), _('REV')),
3196 ('r', 'rev', [], _('revisions to export'), _('REV')),
3191 ] + diffopts,
3197 ] + diffopts,
3192 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3198 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3193 def export(ui, repo, *changesets, **opts):
3199 def export(ui, repo, *changesets, **opts):
3194 """dump the header and diffs for one or more changesets
3200 """dump the header and diffs for one or more changesets
3195
3201
3196 Print the changeset header and diffs for one or more revisions.
3202 Print the changeset header and diffs for one or more revisions.
3197 If no revision is given, the parent of the working directory is used.
3203 If no revision is given, the parent of the working directory is used.
3198
3204
3199 The information shown in the changeset header is: author, date,
3205 The information shown in the changeset header is: author, date,
3200 branch name (if non-default), changeset hash, parent(s) and commit
3206 branch name (if non-default), changeset hash, parent(s) and commit
3201 comment.
3207 comment.
3202
3208
3203 .. note::
3209 .. note::
3204
3210
3205 export may generate unexpected diff output for merge
3211 export may generate unexpected diff output for merge
3206 changesets, as it will compare the merge changeset against its
3212 changesets, as it will compare the merge changeset against its
3207 first parent only.
3213 first parent only.
3208
3214
3209 Output may be to a file, in which case the name of the file is
3215 Output may be to a file, in which case the name of the file is
3210 given using a format string. The formatting rules are as follows:
3216 given using a format string. The formatting rules are as follows:
3211
3217
3212 :``%%``: literal "%" character
3218 :``%%``: literal "%" character
3213 :``%H``: changeset hash (40 hexadecimal digits)
3219 :``%H``: changeset hash (40 hexadecimal digits)
3214 :``%N``: number of patches being generated
3220 :``%N``: number of patches being generated
3215 :``%R``: changeset revision number
3221 :``%R``: changeset revision number
3216 :``%b``: basename of the exporting repository
3222 :``%b``: basename of the exporting repository
3217 :``%h``: short-form changeset hash (12 hexadecimal digits)
3223 :``%h``: short-form changeset hash (12 hexadecimal digits)
3218 :``%m``: first line of the commit message (only alphanumeric characters)
3224 :``%m``: first line of the commit message (only alphanumeric characters)
3219 :``%n``: zero-padded sequence number, starting at 1
3225 :``%n``: zero-padded sequence number, starting at 1
3220 :``%r``: zero-padded changeset revision number
3226 :``%r``: zero-padded changeset revision number
3221
3227
3222 Without the -a/--text option, export will avoid generating diffs
3228 Without the -a/--text option, export will avoid generating diffs
3223 of files it detects as binary. With -a, export will generate a
3229 of files it detects as binary. With -a, export will generate a
3224 diff anyway, probably with undesirable results.
3230 diff anyway, probably with undesirable results.
3225
3231
3226 Use the -g/--git option to generate diffs in the git extended diff
3232 Use the -g/--git option to generate diffs in the git extended diff
3227 format. See :hg:`help diffs` for more information.
3233 format. See :hg:`help diffs` for more information.
3228
3234
3229 With the --switch-parent option, the diff will be against the
3235 With the --switch-parent option, the diff will be against the
3230 second parent. It can be useful to review a merge.
3236 second parent. It can be useful to review a merge.
3231
3237
3232 .. container:: verbose
3238 .. container:: verbose
3233
3239
3234 Examples:
3240 Examples:
3235
3241
3236 - use export and import to transplant a bugfix to the current
3242 - use export and import to transplant a bugfix to the current
3237 branch::
3243 branch::
3238
3244
3239 hg export -r 9353 | hg import -
3245 hg export -r 9353 | hg import -
3240
3246
3241 - export all the changesets between two revisions to a file with
3247 - export all the changesets between two revisions to a file with
3242 rename information::
3248 rename information::
3243
3249
3244 hg export --git -r 123:150 > changes.txt
3250 hg export --git -r 123:150 > changes.txt
3245
3251
3246 - split outgoing changes into a series of patches with
3252 - split outgoing changes into a series of patches with
3247 descriptive names::
3253 descriptive names::
3248
3254
3249 hg export -r "outgoing()" -o "%n-%m.patch"
3255 hg export -r "outgoing()" -o "%n-%m.patch"
3250
3256
3251 Returns 0 on success.
3257 Returns 0 on success.
3252 """
3258 """
3253 changesets += tuple(opts.get('rev', []))
3259 changesets += tuple(opts.get('rev', []))
3254 if not changesets:
3260 if not changesets:
3255 changesets = ['.']
3261 changesets = ['.']
3256 revs = scmutil.revrange(repo, changesets)
3262 revs = scmutil.revrange(repo, changesets)
3257 if not revs:
3263 if not revs:
3258 raise util.Abort(_("export requires at least one changeset"))
3264 raise util.Abort(_("export requires at least one changeset"))
3259 if len(revs) > 1:
3265 if len(revs) > 1:
3260 ui.note(_('exporting patches:\n'))
3266 ui.note(_('exporting patches:\n'))
3261 else:
3267 else:
3262 ui.note(_('exporting patch:\n'))
3268 ui.note(_('exporting patch:\n'))
3263 cmdutil.export(repo, revs, template=opts.get('output'),
3269 cmdutil.export(repo, revs, template=opts.get('output'),
3264 switch_parent=opts.get('switch_parent'),
3270 switch_parent=opts.get('switch_parent'),
3265 opts=patch.diffallopts(ui, opts))
3271 opts=patch.diffallopts(ui, opts))
3266
3272
3267 @command('files',
3273 @command('files',
3268 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3274 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3269 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3275 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3270 ] + walkopts + formatteropts + subrepoopts,
3276 ] + walkopts + formatteropts + subrepoopts,
3271 _('[OPTION]... [PATTERN]...'))
3277 _('[OPTION]... [PATTERN]...'))
3272 def files(ui, repo, *pats, **opts):
3278 def files(ui, repo, *pats, **opts):
3273 """list tracked files
3279 """list tracked files
3274
3280
3275 Print files under Mercurial control in the working directory or
3281 Print files under Mercurial control in the working directory or
3276 specified revision whose names match the given patterns (excluding
3282 specified revision whose names match the given patterns (excluding
3277 removed files).
3283 removed files).
3278
3284
3279 If no patterns are given to match, this command prints the names
3285 If no patterns are given to match, this command prints the names
3280 of all files under Mercurial control in the working directory.
3286 of all files under Mercurial control in the working directory.
3281
3287
3282 .. container:: verbose
3288 .. container:: verbose
3283
3289
3284 Examples:
3290 Examples:
3285
3291
3286 - list all files under the current directory::
3292 - list all files under the current directory::
3287
3293
3288 hg files .
3294 hg files .
3289
3295
3290 - shows sizes and flags for current revision::
3296 - shows sizes and flags for current revision::
3291
3297
3292 hg files -vr .
3298 hg files -vr .
3293
3299
3294 - list all files named README::
3300 - list all files named README::
3295
3301
3296 hg files -I "**/README"
3302 hg files -I "**/README"
3297
3303
3298 - list all binary files::
3304 - list all binary files::
3299
3305
3300 hg files "set:binary()"
3306 hg files "set:binary()"
3301
3307
3302 - find files containing a regular expression::
3308 - find files containing a regular expression::
3303
3309
3304 hg files "set:grep('bob')"
3310 hg files "set:grep('bob')"
3305
3311
3306 - search tracked file contents with xargs and grep::
3312 - search tracked file contents with xargs and grep::
3307
3313
3308 hg files -0 | xargs -0 grep foo
3314 hg files -0 | xargs -0 grep foo
3309
3315
3310 See :hg:`help patterns` and :hg:`help filesets` for more information
3316 See :hg:`help patterns` and :hg:`help filesets` for more information
3311 on specifying file patterns.
3317 on specifying file patterns.
3312
3318
3313 Returns 0 if a match is found, 1 otherwise.
3319 Returns 0 if a match is found, 1 otherwise.
3314
3320
3315 """
3321 """
3316 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3322 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3317
3323
3318 end = '\n'
3324 end = '\n'
3319 if opts.get('print0'):
3325 if opts.get('print0'):
3320 end = '\0'
3326 end = '\0'
3321 fm = ui.formatter('files', opts)
3327 fm = ui.formatter('files', opts)
3322 fmt = '%s' + end
3328 fmt = '%s' + end
3323
3329
3324 m = scmutil.match(ctx, pats, opts)
3330 m = scmutil.match(ctx, pats, opts)
3325 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3331 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3326
3332
3327 fm.end()
3333 fm.end()
3328
3334
3329 return ret
3335 return ret
3330
3336
3331 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3337 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3332 def forget(ui, repo, *pats, **opts):
3338 def forget(ui, repo, *pats, **opts):
3333 """forget the specified files on the next commit
3339 """forget the specified files on the next commit
3334
3340
3335 Mark the specified files so they will no longer be tracked
3341 Mark the specified files so they will no longer be tracked
3336 after the next commit.
3342 after the next commit.
3337
3343
3338 This only removes files from the current branch, not from the
3344 This only removes files from the current branch, not from the
3339 entire project history, and it does not delete them from the
3345 entire project history, and it does not delete them from the
3340 working directory.
3346 working directory.
3341
3347
3342 To undo a forget before the next commit, see :hg:`add`.
3348 To undo a forget before the next commit, see :hg:`add`.
3343
3349
3344 .. container:: verbose
3350 .. container:: verbose
3345
3351
3346 Examples:
3352 Examples:
3347
3353
3348 - forget newly-added binary files::
3354 - forget newly-added binary files::
3349
3355
3350 hg forget "set:added() and binary()"
3356 hg forget "set:added() and binary()"
3351
3357
3352 - forget files that would be excluded by .hgignore::
3358 - forget files that would be excluded by .hgignore::
3353
3359
3354 hg forget "set:hgignore()"
3360 hg forget "set:hgignore()"
3355
3361
3356 Returns 0 on success.
3362 Returns 0 on success.
3357 """
3363 """
3358
3364
3359 if not pats:
3365 if not pats:
3360 raise util.Abort(_('no files specified'))
3366 raise util.Abort(_('no files specified'))
3361
3367
3362 m = scmutil.match(repo[None], pats, opts)
3368 m = scmutil.match(repo[None], pats, opts)
3363 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3369 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3364 return rejected and 1 or 0
3370 return rejected and 1 or 0
3365
3371
3366 @command(
3372 @command(
3367 'graft',
3373 'graft',
3368 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3374 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3369 ('c', 'continue', False, _('resume interrupted graft')),
3375 ('c', 'continue', False, _('resume interrupted graft')),
3370 ('e', 'edit', False, _('invoke editor on commit messages')),
3376 ('e', 'edit', False, _('invoke editor on commit messages')),
3371 ('', 'log', None, _('append graft info to log message')),
3377 ('', 'log', None, _('append graft info to log message')),
3372 ('f', 'force', False, _('force graft')),
3378 ('f', 'force', False, _('force graft')),
3373 ('D', 'currentdate', False,
3379 ('D', 'currentdate', False,
3374 _('record the current date as commit date')),
3380 _('record the current date as commit date')),
3375 ('U', 'currentuser', False,
3381 ('U', 'currentuser', False,
3376 _('record the current user as committer'), _('DATE'))]
3382 _('record the current user as committer'), _('DATE'))]
3377 + commitopts2 + mergetoolopts + dryrunopts,
3383 + commitopts2 + mergetoolopts + dryrunopts,
3378 _('[OPTION]... [-r] REV...'))
3384 _('[OPTION]... [-r] REV...'))
3379 def graft(ui, repo, *revs, **opts):
3385 def graft(ui, repo, *revs, **opts):
3380 '''copy changes from other branches onto the current branch
3386 '''copy changes from other branches onto the current branch
3381
3387
3382 This command uses Mercurial's merge logic to copy individual
3388 This command uses Mercurial's merge logic to copy individual
3383 changes from other branches without merging branches in the
3389 changes from other branches without merging branches in the
3384 history graph. This is sometimes known as 'backporting' or
3390 history graph. This is sometimes known as 'backporting' or
3385 'cherry-picking'. By default, graft will copy user, date, and
3391 'cherry-picking'. By default, graft will copy user, date, and
3386 description from the source changesets.
3392 description from the source changesets.
3387
3393
3388 Changesets that are ancestors of the current revision, that have
3394 Changesets that are ancestors of the current revision, that have
3389 already been grafted, or that are merges will be skipped.
3395 already been grafted, or that are merges will be skipped.
3390
3396
3391 If --log is specified, log messages will have a comment appended
3397 If --log is specified, log messages will have a comment appended
3392 of the form::
3398 of the form::
3393
3399
3394 (grafted from CHANGESETHASH)
3400 (grafted from CHANGESETHASH)
3395
3401
3396 If --force is specified, revisions will be grafted even if they
3402 If --force is specified, revisions will be grafted even if they
3397 are already ancestors of or have been grafted to the destination.
3403 are already ancestors of or have been grafted to the destination.
3398 This is useful when the revisions have since been backed out.
3404 This is useful when the revisions have since been backed out.
3399
3405
3400 If a graft merge results in conflicts, the graft process is
3406 If a graft merge results in conflicts, the graft process is
3401 interrupted so that the current merge can be manually resolved.
3407 interrupted so that the current merge can be manually resolved.
3402 Once all conflicts are addressed, the graft process can be
3408 Once all conflicts are addressed, the graft process can be
3403 continued with the -c/--continue option.
3409 continued with the -c/--continue option.
3404
3410
3405 .. note::
3411 .. note::
3406
3412
3407 The -c/--continue option does not reapply earlier options, except
3413 The -c/--continue option does not reapply earlier options, except
3408 for --force.
3414 for --force.
3409
3415
3410 .. container:: verbose
3416 .. container:: verbose
3411
3417
3412 Examples:
3418 Examples:
3413
3419
3414 - copy a single change to the stable branch and edit its description::
3420 - copy a single change to the stable branch and edit its description::
3415
3421
3416 hg update stable
3422 hg update stable
3417 hg graft --edit 9393
3423 hg graft --edit 9393
3418
3424
3419 - graft a range of changesets with one exception, updating dates::
3425 - graft a range of changesets with one exception, updating dates::
3420
3426
3421 hg graft -D "2085::2093 and not 2091"
3427 hg graft -D "2085::2093 and not 2091"
3422
3428
3423 - continue a graft after resolving conflicts::
3429 - continue a graft after resolving conflicts::
3424
3430
3425 hg graft -c
3431 hg graft -c
3426
3432
3427 - show the source of a grafted changeset::
3433 - show the source of a grafted changeset::
3428
3434
3429 hg log --debug -r .
3435 hg log --debug -r .
3430
3436
3431 See :hg:`help revisions` and :hg:`help revsets` for more about
3437 See :hg:`help revisions` and :hg:`help revsets` for more about
3432 specifying revisions.
3438 specifying revisions.
3433
3439
3434 Returns 0 on successful completion.
3440 Returns 0 on successful completion.
3435 '''
3441 '''
3436
3442
3437 revs = list(revs)
3443 revs = list(revs)
3438 revs.extend(opts['rev'])
3444 revs.extend(opts['rev'])
3439
3445
3440 if not opts.get('user') and opts.get('currentuser'):
3446 if not opts.get('user') and opts.get('currentuser'):
3441 opts['user'] = ui.username()
3447 opts['user'] = ui.username()
3442 if not opts.get('date') and opts.get('currentdate'):
3448 if not opts.get('date') and opts.get('currentdate'):
3443 opts['date'] = "%d %d" % util.makedate()
3449 opts['date'] = "%d %d" % util.makedate()
3444
3450
3445 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3451 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3446
3452
3447 cont = False
3453 cont = False
3448 if opts['continue']:
3454 if opts['continue']:
3449 cont = True
3455 cont = True
3450 if revs:
3456 if revs:
3451 raise util.Abort(_("can't specify --continue and revisions"))
3457 raise util.Abort(_("can't specify --continue and revisions"))
3452 # read in unfinished revisions
3458 # read in unfinished revisions
3453 try:
3459 try:
3454 nodes = repo.vfs.read('graftstate').splitlines()
3460 nodes = repo.vfs.read('graftstate').splitlines()
3455 revs = [repo[node].rev() for node in nodes]
3461 revs = [repo[node].rev() for node in nodes]
3456 except IOError, inst:
3462 except IOError, inst:
3457 if inst.errno != errno.ENOENT:
3463 if inst.errno != errno.ENOENT:
3458 raise
3464 raise
3459 raise util.Abort(_("no graft state found, can't continue"))
3465 raise util.Abort(_("no graft state found, can't continue"))
3460 else:
3466 else:
3461 cmdutil.checkunfinished(repo)
3467 cmdutil.checkunfinished(repo)
3462 cmdutil.bailifchanged(repo)
3468 cmdutil.bailifchanged(repo)
3463 if not revs:
3469 if not revs:
3464 raise util.Abort(_('no revisions specified'))
3470 raise util.Abort(_('no revisions specified'))
3465 revs = scmutil.revrange(repo, revs)
3471 revs = scmutil.revrange(repo, revs)
3466
3472
3467 skipped = set()
3473 skipped = set()
3468 # check for merges
3474 # check for merges
3469 for rev in repo.revs('%ld and merge()', revs):
3475 for rev in repo.revs('%ld and merge()', revs):
3470 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3476 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3471 skipped.add(rev)
3477 skipped.add(rev)
3472 revs = [r for r in revs if r not in skipped]
3478 revs = [r for r in revs if r not in skipped]
3473 if not revs:
3479 if not revs:
3474 return -1
3480 return -1
3475
3481
3476 # Don't check in the --continue case, in effect retaining --force across
3482 # Don't check in the --continue case, in effect retaining --force across
3477 # --continues. That's because without --force, any revisions we decided to
3483 # --continues. That's because without --force, any revisions we decided to
3478 # skip would have been filtered out here, so they wouldn't have made their
3484 # skip would have been filtered out here, so they wouldn't have made their
3479 # way to the graftstate. With --force, any revisions we would have otherwise
3485 # way to the graftstate. With --force, any revisions we would have otherwise
3480 # skipped would not have been filtered out, and if they hadn't been applied
3486 # skipped would not have been filtered out, and if they hadn't been applied
3481 # already, they'd have been in the graftstate.
3487 # already, they'd have been in the graftstate.
3482 if not (cont or opts.get('force')):
3488 if not (cont or opts.get('force')):
3483 # check for ancestors of dest branch
3489 # check for ancestors of dest branch
3484 crev = repo['.'].rev()
3490 crev = repo['.'].rev()
3485 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3491 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3486 # Cannot use x.remove(y) on smart set, this has to be a list.
3492 # Cannot use x.remove(y) on smart set, this has to be a list.
3487 # XXX make this lazy in the future
3493 # XXX make this lazy in the future
3488 revs = list(revs)
3494 revs = list(revs)
3489 # don't mutate while iterating, create a copy
3495 # don't mutate while iterating, create a copy
3490 for rev in list(revs):
3496 for rev in list(revs):
3491 if rev in ancestors:
3497 if rev in ancestors:
3492 ui.warn(_('skipping ancestor revision %d:%s\n') %
3498 ui.warn(_('skipping ancestor revision %d:%s\n') %
3493 (rev, repo[rev]))
3499 (rev, repo[rev]))
3494 # XXX remove on list is slow
3500 # XXX remove on list is slow
3495 revs.remove(rev)
3501 revs.remove(rev)
3496 if not revs:
3502 if not revs:
3497 return -1
3503 return -1
3498
3504
3499 # analyze revs for earlier grafts
3505 # analyze revs for earlier grafts
3500 ids = {}
3506 ids = {}
3501 for ctx in repo.set("%ld", revs):
3507 for ctx in repo.set("%ld", revs):
3502 ids[ctx.hex()] = ctx.rev()
3508 ids[ctx.hex()] = ctx.rev()
3503 n = ctx.extra().get('source')
3509 n = ctx.extra().get('source')
3504 if n:
3510 if n:
3505 ids[n] = ctx.rev()
3511 ids[n] = ctx.rev()
3506
3512
3507 # check ancestors for earlier grafts
3513 # check ancestors for earlier grafts
3508 ui.debug('scanning for duplicate grafts\n')
3514 ui.debug('scanning for duplicate grafts\n')
3509
3515
3510 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3516 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3511 ctx = repo[rev]
3517 ctx = repo[rev]
3512 n = ctx.extra().get('source')
3518 n = ctx.extra().get('source')
3513 if n in ids:
3519 if n in ids:
3514 try:
3520 try:
3515 r = repo[n].rev()
3521 r = repo[n].rev()
3516 except error.RepoLookupError:
3522 except error.RepoLookupError:
3517 r = None
3523 r = None
3518 if r in revs:
3524 if r in revs:
3519 ui.warn(_('skipping revision %d:%s '
3525 ui.warn(_('skipping revision %d:%s '
3520 '(already grafted to %d:%s)\n')
3526 '(already grafted to %d:%s)\n')
3521 % (r, repo[r], rev, ctx))
3527 % (r, repo[r], rev, ctx))
3522 revs.remove(r)
3528 revs.remove(r)
3523 elif ids[n] in revs:
3529 elif ids[n] in revs:
3524 if r is None:
3530 if r is None:
3525 ui.warn(_('skipping already grafted revision %d:%s '
3531 ui.warn(_('skipping already grafted revision %d:%s '
3526 '(%d:%s also has unknown origin %s)\n')
3532 '(%d:%s also has unknown origin %s)\n')
3527 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3533 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3528 else:
3534 else:
3529 ui.warn(_('skipping already grafted revision %d:%s '
3535 ui.warn(_('skipping already grafted revision %d:%s '
3530 '(%d:%s also has origin %d:%s)\n')
3536 '(%d:%s also has origin %d:%s)\n')
3531 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3537 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3532 revs.remove(ids[n])
3538 revs.remove(ids[n])
3533 elif ctx.hex() in ids:
3539 elif ctx.hex() in ids:
3534 r = ids[ctx.hex()]
3540 r = ids[ctx.hex()]
3535 ui.warn(_('skipping already grafted revision %d:%s '
3541 ui.warn(_('skipping already grafted revision %d:%s '
3536 '(was grafted from %d:%s)\n') %
3542 '(was grafted from %d:%s)\n') %
3537 (r, repo[r], rev, ctx))
3543 (r, repo[r], rev, ctx))
3538 revs.remove(r)
3544 revs.remove(r)
3539 if not revs:
3545 if not revs:
3540 return -1
3546 return -1
3541
3547
3542 wlock = repo.wlock()
3548 wlock = repo.wlock()
3543 try:
3549 try:
3544 for pos, ctx in enumerate(repo.set("%ld", revs)):
3550 for pos, ctx in enumerate(repo.set("%ld", revs)):
3545 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3551 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3546 ctx.description().split('\n', 1)[0])
3552 ctx.description().split('\n', 1)[0])
3547 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3553 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3548 if names:
3554 if names:
3549 desc += ' (%s)' % ' '.join(names)
3555 desc += ' (%s)' % ' '.join(names)
3550 ui.status(_('grafting %s\n') % desc)
3556 ui.status(_('grafting %s\n') % desc)
3551 if opts.get('dry_run'):
3557 if opts.get('dry_run'):
3552 continue
3558 continue
3553
3559
3554 source = ctx.extra().get('source')
3560 source = ctx.extra().get('source')
3555 extra = {}
3561 extra = {}
3556 if source:
3562 if source:
3557 extra['source'] = source
3563 extra['source'] = source
3558 extra['intermediate-source'] = ctx.hex()
3564 extra['intermediate-source'] = ctx.hex()
3559 else:
3565 else:
3560 extra['source'] = ctx.hex()
3566 extra['source'] = ctx.hex()
3561 user = ctx.user()
3567 user = ctx.user()
3562 if opts.get('user'):
3568 if opts.get('user'):
3563 user = opts['user']
3569 user = opts['user']
3564 date = ctx.date()
3570 date = ctx.date()
3565 if opts.get('date'):
3571 if opts.get('date'):
3566 date = opts['date']
3572 date = opts['date']
3567 message = ctx.description()
3573 message = ctx.description()
3568 if opts.get('log'):
3574 if opts.get('log'):
3569 message += '\n(grafted from %s)' % ctx.hex()
3575 message += '\n(grafted from %s)' % ctx.hex()
3570
3576
3571 # we don't merge the first commit when continuing
3577 # we don't merge the first commit when continuing
3572 if not cont:
3578 if not cont:
3573 # perform the graft merge with p1(rev) as 'ancestor'
3579 # perform the graft merge with p1(rev) as 'ancestor'
3574 try:
3580 try:
3575 # ui.forcemerge is an internal variable, do not document
3581 # ui.forcemerge is an internal variable, do not document
3576 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3582 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3577 'graft')
3583 'graft')
3578 stats = mergemod.graft(repo, ctx, ctx.p1(),
3584 stats = mergemod.graft(repo, ctx, ctx.p1(),
3579 ['local', 'graft'])
3585 ['local', 'graft'])
3580 finally:
3586 finally:
3581 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3587 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3582 # report any conflicts
3588 # report any conflicts
3583 if stats and stats[3] > 0:
3589 if stats and stats[3] > 0:
3584 # write out state for --continue
3590 # write out state for --continue
3585 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3591 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3586 repo.vfs.write('graftstate', ''.join(nodelines))
3592 repo.vfs.write('graftstate', ''.join(nodelines))
3587 raise util.Abort(
3593 raise util.Abort(
3588 _("unresolved conflicts, can't continue"),
3594 _("unresolved conflicts, can't continue"),
3589 hint=_('use hg resolve and hg graft --continue'))
3595 hint=_('use hg resolve and hg graft --continue'))
3590 else:
3596 else:
3591 cont = False
3597 cont = False
3592
3598
3593 # commit
3599 # commit
3594 node = repo.commit(text=message, user=user,
3600 node = repo.commit(text=message, user=user,
3595 date=date, extra=extra, editor=editor)
3601 date=date, extra=extra, editor=editor)
3596 if node is None:
3602 if node is None:
3597 ui.warn(
3603 ui.warn(
3598 _('note: graft of %d:%s created no changes to commit\n') %
3604 _('note: graft of %d:%s created no changes to commit\n') %
3599 (ctx.rev(), ctx))
3605 (ctx.rev(), ctx))
3600 finally:
3606 finally:
3601 wlock.release()
3607 wlock.release()
3602
3608
3603 # remove state when we complete successfully
3609 # remove state when we complete successfully
3604 if not opts.get('dry_run'):
3610 if not opts.get('dry_run'):
3605 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3611 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3606
3612
3607 return 0
3613 return 0
3608
3614
3609 @command('grep',
3615 @command('grep',
3610 [('0', 'print0', None, _('end fields with NUL')),
3616 [('0', 'print0', None, _('end fields with NUL')),
3611 ('', 'all', None, _('print all revisions that match')),
3617 ('', 'all', None, _('print all revisions that match')),
3612 ('a', 'text', None, _('treat all files as text')),
3618 ('a', 'text', None, _('treat all files as text')),
3613 ('f', 'follow', None,
3619 ('f', 'follow', None,
3614 _('follow changeset history,'
3620 _('follow changeset history,'
3615 ' or file history across copies and renames')),
3621 ' or file history across copies and renames')),
3616 ('i', 'ignore-case', None, _('ignore case when matching')),
3622 ('i', 'ignore-case', None, _('ignore case when matching')),
3617 ('l', 'files-with-matches', None,
3623 ('l', 'files-with-matches', None,
3618 _('print only filenames and revisions that match')),
3624 _('print only filenames and revisions that match')),
3619 ('n', 'line-number', None, _('print matching line numbers')),
3625 ('n', 'line-number', None, _('print matching line numbers')),
3620 ('r', 'rev', [],
3626 ('r', 'rev', [],
3621 _('only search files changed within revision range'), _('REV')),
3627 _('only search files changed within revision range'), _('REV')),
3622 ('u', 'user', None, _('list the author (long with -v)')),
3628 ('u', 'user', None, _('list the author (long with -v)')),
3623 ('d', 'date', None, _('list the date (short with -q)')),
3629 ('d', 'date', None, _('list the date (short with -q)')),
3624 ] + walkopts,
3630 ] + walkopts,
3625 _('[OPTION]... PATTERN [FILE]...'),
3631 _('[OPTION]... PATTERN [FILE]...'),
3626 inferrepo=True)
3632 inferrepo=True)
3627 def grep(ui, repo, pattern, *pats, **opts):
3633 def grep(ui, repo, pattern, *pats, **opts):
3628 """search for a pattern in specified files and revisions
3634 """search for a pattern in specified files and revisions
3629
3635
3630 Search revisions of files for a regular expression.
3636 Search revisions of files for a regular expression.
3631
3637
3632 This command behaves differently than Unix grep. It only accepts
3638 This command behaves differently than Unix grep. It only accepts
3633 Python/Perl regexps. It searches repository history, not the
3639 Python/Perl regexps. It searches repository history, not the
3634 working directory. It always prints the revision number in which a
3640 working directory. It always prints the revision number in which a
3635 match appears.
3641 match appears.
3636
3642
3637 By default, grep only prints output for the first revision of a
3643 By default, grep only prints output for the first revision of a
3638 file in which it finds a match. To get it to print every revision
3644 file in which it finds a match. To get it to print every revision
3639 that contains a change in match status ("-" for a match that
3645 that contains a change in match status ("-" for a match that
3640 becomes a non-match, or "+" for a non-match that becomes a match),
3646 becomes a non-match, or "+" for a non-match that becomes a match),
3641 use the --all flag.
3647 use the --all flag.
3642
3648
3643 Returns 0 if a match is found, 1 otherwise.
3649 Returns 0 if a match is found, 1 otherwise.
3644 """
3650 """
3645 reflags = re.M
3651 reflags = re.M
3646 if opts.get('ignore_case'):
3652 if opts.get('ignore_case'):
3647 reflags |= re.I
3653 reflags |= re.I
3648 try:
3654 try:
3649 regexp = util.re.compile(pattern, reflags)
3655 regexp = util.re.compile(pattern, reflags)
3650 except re.error, inst:
3656 except re.error, inst:
3651 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3657 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3652 return 1
3658 return 1
3653 sep, eol = ':', '\n'
3659 sep, eol = ':', '\n'
3654 if opts.get('print0'):
3660 if opts.get('print0'):
3655 sep = eol = '\0'
3661 sep = eol = '\0'
3656
3662
3657 getfile = util.lrucachefunc(repo.file)
3663 getfile = util.lrucachefunc(repo.file)
3658
3664
3659 def matchlines(body):
3665 def matchlines(body):
3660 begin = 0
3666 begin = 0
3661 linenum = 0
3667 linenum = 0
3662 while begin < len(body):
3668 while begin < len(body):
3663 match = regexp.search(body, begin)
3669 match = regexp.search(body, begin)
3664 if not match:
3670 if not match:
3665 break
3671 break
3666 mstart, mend = match.span()
3672 mstart, mend = match.span()
3667 linenum += body.count('\n', begin, mstart) + 1
3673 linenum += body.count('\n', begin, mstart) + 1
3668 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3674 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3669 begin = body.find('\n', mend) + 1 or len(body) + 1
3675 begin = body.find('\n', mend) + 1 or len(body) + 1
3670 lend = begin - 1
3676 lend = begin - 1
3671 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3677 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3672
3678
3673 class linestate(object):
3679 class linestate(object):
3674 def __init__(self, line, linenum, colstart, colend):
3680 def __init__(self, line, linenum, colstart, colend):
3675 self.line = line
3681 self.line = line
3676 self.linenum = linenum
3682 self.linenum = linenum
3677 self.colstart = colstart
3683 self.colstart = colstart
3678 self.colend = colend
3684 self.colend = colend
3679
3685
3680 def __hash__(self):
3686 def __hash__(self):
3681 return hash((self.linenum, self.line))
3687 return hash((self.linenum, self.line))
3682
3688
3683 def __eq__(self, other):
3689 def __eq__(self, other):
3684 return self.line == other.line
3690 return self.line == other.line
3685
3691
3686 def __iter__(self):
3692 def __iter__(self):
3687 yield (self.line[:self.colstart], '')
3693 yield (self.line[:self.colstart], '')
3688 yield (self.line[self.colstart:self.colend], 'grep.match')
3694 yield (self.line[self.colstart:self.colend], 'grep.match')
3689 rest = self.line[self.colend:]
3695 rest = self.line[self.colend:]
3690 while rest != '':
3696 while rest != '':
3691 match = regexp.search(rest)
3697 match = regexp.search(rest)
3692 if not match:
3698 if not match:
3693 yield (rest, '')
3699 yield (rest, '')
3694 break
3700 break
3695 mstart, mend = match.span()
3701 mstart, mend = match.span()
3696 yield (rest[:mstart], '')
3702 yield (rest[:mstart], '')
3697 yield (rest[mstart:mend], 'grep.match')
3703 yield (rest[mstart:mend], 'grep.match')
3698 rest = rest[mend:]
3704 rest = rest[mend:]
3699
3705
3700 matches = {}
3706 matches = {}
3701 copies = {}
3707 copies = {}
3702 def grepbody(fn, rev, body):
3708 def grepbody(fn, rev, body):
3703 matches[rev].setdefault(fn, [])
3709 matches[rev].setdefault(fn, [])
3704 m = matches[rev][fn]
3710 m = matches[rev][fn]
3705 for lnum, cstart, cend, line in matchlines(body):
3711 for lnum, cstart, cend, line in matchlines(body):
3706 s = linestate(line, lnum, cstart, cend)
3712 s = linestate(line, lnum, cstart, cend)
3707 m.append(s)
3713 m.append(s)
3708
3714
3709 def difflinestates(a, b):
3715 def difflinestates(a, b):
3710 sm = difflib.SequenceMatcher(None, a, b)
3716 sm = difflib.SequenceMatcher(None, a, b)
3711 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3717 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3712 if tag == 'insert':
3718 if tag == 'insert':
3713 for i in xrange(blo, bhi):
3719 for i in xrange(blo, bhi):
3714 yield ('+', b[i])
3720 yield ('+', b[i])
3715 elif tag == 'delete':
3721 elif tag == 'delete':
3716 for i in xrange(alo, ahi):
3722 for i in xrange(alo, ahi):
3717 yield ('-', a[i])
3723 yield ('-', a[i])
3718 elif tag == 'replace':
3724 elif tag == 'replace':
3719 for i in xrange(alo, ahi):
3725 for i in xrange(alo, ahi):
3720 yield ('-', a[i])
3726 yield ('-', a[i])
3721 for i in xrange(blo, bhi):
3727 for i in xrange(blo, bhi):
3722 yield ('+', b[i])
3728 yield ('+', b[i])
3723
3729
3724 def display(fn, ctx, pstates, states):
3730 def display(fn, ctx, pstates, states):
3725 rev = ctx.rev()
3731 rev = ctx.rev()
3726 if ui.quiet:
3732 if ui.quiet:
3727 datefunc = util.shortdate
3733 datefunc = util.shortdate
3728 else:
3734 else:
3729 datefunc = util.datestr
3735 datefunc = util.datestr
3730 found = False
3736 found = False
3731 @util.cachefunc
3737 @util.cachefunc
3732 def binary():
3738 def binary():
3733 flog = getfile(fn)
3739 flog = getfile(fn)
3734 return util.binary(flog.read(ctx.filenode(fn)))
3740 return util.binary(flog.read(ctx.filenode(fn)))
3735
3741
3736 if opts.get('all'):
3742 if opts.get('all'):
3737 iter = difflinestates(pstates, states)
3743 iter = difflinestates(pstates, states)
3738 else:
3744 else:
3739 iter = [('', l) for l in states]
3745 iter = [('', l) for l in states]
3740 for change, l in iter:
3746 for change, l in iter:
3741 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3747 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3742
3748
3743 if opts.get('line_number'):
3749 if opts.get('line_number'):
3744 cols.append((str(l.linenum), 'grep.linenumber'))
3750 cols.append((str(l.linenum), 'grep.linenumber'))
3745 if opts.get('all'):
3751 if opts.get('all'):
3746 cols.append((change, 'grep.change'))
3752 cols.append((change, 'grep.change'))
3747 if opts.get('user'):
3753 if opts.get('user'):
3748 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3754 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3749 if opts.get('date'):
3755 if opts.get('date'):
3750 cols.append((datefunc(ctx.date()), 'grep.date'))
3756 cols.append((datefunc(ctx.date()), 'grep.date'))
3751 for col, label in cols[:-1]:
3757 for col, label in cols[:-1]:
3752 ui.write(col, label=label)
3758 ui.write(col, label=label)
3753 ui.write(sep, label='grep.sep')
3759 ui.write(sep, label='grep.sep')
3754 ui.write(cols[-1][0], label=cols[-1][1])
3760 ui.write(cols[-1][0], label=cols[-1][1])
3755 if not opts.get('files_with_matches'):
3761 if not opts.get('files_with_matches'):
3756 ui.write(sep, label='grep.sep')
3762 ui.write(sep, label='grep.sep')
3757 if not opts.get('text') and binary():
3763 if not opts.get('text') and binary():
3758 ui.write(" Binary file matches")
3764 ui.write(" Binary file matches")
3759 else:
3765 else:
3760 for s, label in l:
3766 for s, label in l:
3761 ui.write(s, label=label)
3767 ui.write(s, label=label)
3762 ui.write(eol)
3768 ui.write(eol)
3763 found = True
3769 found = True
3764 if opts.get('files_with_matches'):
3770 if opts.get('files_with_matches'):
3765 break
3771 break
3766 return found
3772 return found
3767
3773
3768 skip = {}
3774 skip = {}
3769 revfiles = {}
3775 revfiles = {}
3770 matchfn = scmutil.match(repo[None], pats, opts)
3776 matchfn = scmutil.match(repo[None], pats, opts)
3771 found = False
3777 found = False
3772 follow = opts.get('follow')
3778 follow = opts.get('follow')
3773
3779
3774 def prep(ctx, fns):
3780 def prep(ctx, fns):
3775 rev = ctx.rev()
3781 rev = ctx.rev()
3776 pctx = ctx.p1()
3782 pctx = ctx.p1()
3777 parent = pctx.rev()
3783 parent = pctx.rev()
3778 matches.setdefault(rev, {})
3784 matches.setdefault(rev, {})
3779 matches.setdefault(parent, {})
3785 matches.setdefault(parent, {})
3780 files = revfiles.setdefault(rev, [])
3786 files = revfiles.setdefault(rev, [])
3781 for fn in fns:
3787 for fn in fns:
3782 flog = getfile(fn)
3788 flog = getfile(fn)
3783 try:
3789 try:
3784 fnode = ctx.filenode(fn)
3790 fnode = ctx.filenode(fn)
3785 except error.LookupError:
3791 except error.LookupError:
3786 continue
3792 continue
3787
3793
3788 copied = flog.renamed(fnode)
3794 copied = flog.renamed(fnode)
3789 copy = follow and copied and copied[0]
3795 copy = follow and copied and copied[0]
3790 if copy:
3796 if copy:
3791 copies.setdefault(rev, {})[fn] = copy
3797 copies.setdefault(rev, {})[fn] = copy
3792 if fn in skip:
3798 if fn in skip:
3793 if copy:
3799 if copy:
3794 skip[copy] = True
3800 skip[copy] = True
3795 continue
3801 continue
3796 files.append(fn)
3802 files.append(fn)
3797
3803
3798 if fn not in matches[rev]:
3804 if fn not in matches[rev]:
3799 grepbody(fn, rev, flog.read(fnode))
3805 grepbody(fn, rev, flog.read(fnode))
3800
3806
3801 pfn = copy or fn
3807 pfn = copy or fn
3802 if pfn not in matches[parent]:
3808 if pfn not in matches[parent]:
3803 try:
3809 try:
3804 fnode = pctx.filenode(pfn)
3810 fnode = pctx.filenode(pfn)
3805 grepbody(pfn, parent, flog.read(fnode))
3811 grepbody(pfn, parent, flog.read(fnode))
3806 except error.LookupError:
3812 except error.LookupError:
3807 pass
3813 pass
3808
3814
3809 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3815 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3810 rev = ctx.rev()
3816 rev = ctx.rev()
3811 parent = ctx.p1().rev()
3817 parent = ctx.p1().rev()
3812 for fn in sorted(revfiles.get(rev, [])):
3818 for fn in sorted(revfiles.get(rev, [])):
3813 states = matches[rev][fn]
3819 states = matches[rev][fn]
3814 copy = copies.get(rev, {}).get(fn)
3820 copy = copies.get(rev, {}).get(fn)
3815 if fn in skip:
3821 if fn in skip:
3816 if copy:
3822 if copy:
3817 skip[copy] = True
3823 skip[copy] = True
3818 continue
3824 continue
3819 pstates = matches.get(parent, {}).get(copy or fn, [])
3825 pstates = matches.get(parent, {}).get(copy or fn, [])
3820 if pstates or states:
3826 if pstates or states:
3821 r = display(fn, ctx, pstates, states)
3827 r = display(fn, ctx, pstates, states)
3822 found = found or r
3828 found = found or r
3823 if r and not opts.get('all'):
3829 if r and not opts.get('all'):
3824 skip[fn] = True
3830 skip[fn] = True
3825 if copy:
3831 if copy:
3826 skip[copy] = True
3832 skip[copy] = True
3827 del matches[rev]
3833 del matches[rev]
3828 del revfiles[rev]
3834 del revfiles[rev]
3829
3835
3830 return not found
3836 return not found
3831
3837
3832 @command('heads',
3838 @command('heads',
3833 [('r', 'rev', '',
3839 [('r', 'rev', '',
3834 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3840 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3835 ('t', 'topo', False, _('show topological heads only')),
3841 ('t', 'topo', False, _('show topological heads only')),
3836 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3842 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3837 ('c', 'closed', False, _('show normal and closed branch heads')),
3843 ('c', 'closed', False, _('show normal and closed branch heads')),
3838 ] + templateopts,
3844 ] + templateopts,
3839 _('[-ct] [-r STARTREV] [REV]...'))
3845 _('[-ct] [-r STARTREV] [REV]...'))
3840 def heads(ui, repo, *branchrevs, **opts):
3846 def heads(ui, repo, *branchrevs, **opts):
3841 """show branch heads
3847 """show branch heads
3842
3848
3843 With no arguments, show all open branch heads in the repository.
3849 With no arguments, show all open branch heads in the repository.
3844 Branch heads are changesets that have no descendants on the
3850 Branch heads are changesets that have no descendants on the
3845 same branch. They are where development generally takes place and
3851 same branch. They are where development generally takes place and
3846 are the usual targets for update and merge operations.
3852 are the usual targets for update and merge operations.
3847
3853
3848 If one or more REVs are given, only open branch heads on the
3854 If one or more REVs are given, only open branch heads on the
3849 branches associated with the specified changesets are shown. This
3855 branches associated with the specified changesets are shown. This
3850 means that you can use :hg:`heads .` to see the heads on the
3856 means that you can use :hg:`heads .` to see the heads on the
3851 currently checked-out branch.
3857 currently checked-out branch.
3852
3858
3853 If -c/--closed is specified, also show branch heads marked closed
3859 If -c/--closed is specified, also show branch heads marked closed
3854 (see :hg:`commit --close-branch`).
3860 (see :hg:`commit --close-branch`).
3855
3861
3856 If STARTREV is specified, only those heads that are descendants of
3862 If STARTREV is specified, only those heads that are descendants of
3857 STARTREV will be displayed.
3863 STARTREV will be displayed.
3858
3864
3859 If -t/--topo is specified, named branch mechanics will be ignored and only
3865 If -t/--topo is specified, named branch mechanics will be ignored and only
3860 topological heads (changesets with no children) will be shown.
3866 topological heads (changesets with no children) will be shown.
3861
3867
3862 Returns 0 if matching heads are found, 1 if not.
3868 Returns 0 if matching heads are found, 1 if not.
3863 """
3869 """
3864
3870
3865 start = None
3871 start = None
3866 if 'rev' in opts:
3872 if 'rev' in opts:
3867 start = scmutil.revsingle(repo, opts['rev'], None).node()
3873 start = scmutil.revsingle(repo, opts['rev'], None).node()
3868
3874
3869 if opts.get('topo'):
3875 if opts.get('topo'):
3870 heads = [repo[h] for h in repo.heads(start)]
3876 heads = [repo[h] for h in repo.heads(start)]
3871 else:
3877 else:
3872 heads = []
3878 heads = []
3873 for branch in repo.branchmap():
3879 for branch in repo.branchmap():
3874 heads += repo.branchheads(branch, start, opts.get('closed'))
3880 heads += repo.branchheads(branch, start, opts.get('closed'))
3875 heads = [repo[h] for h in heads]
3881 heads = [repo[h] for h in heads]
3876
3882
3877 if branchrevs:
3883 if branchrevs:
3878 branches = set(repo[br].branch() for br in branchrevs)
3884 branches = set(repo[br].branch() for br in branchrevs)
3879 heads = [h for h in heads if h.branch() in branches]
3885 heads = [h for h in heads if h.branch() in branches]
3880
3886
3881 if opts.get('active') and branchrevs:
3887 if opts.get('active') and branchrevs:
3882 dagheads = repo.heads(start)
3888 dagheads = repo.heads(start)
3883 heads = [h for h in heads if h.node() in dagheads]
3889 heads = [h for h in heads if h.node() in dagheads]
3884
3890
3885 if branchrevs:
3891 if branchrevs:
3886 haveheads = set(h.branch() for h in heads)
3892 haveheads = set(h.branch() for h in heads)
3887 if branches - haveheads:
3893 if branches - haveheads:
3888 headless = ', '.join(b for b in branches - haveheads)
3894 headless = ', '.join(b for b in branches - haveheads)
3889 msg = _('no open branch heads found on branches %s')
3895 msg = _('no open branch heads found on branches %s')
3890 if opts.get('rev'):
3896 if opts.get('rev'):
3891 msg += _(' (started at %s)') % opts['rev']
3897 msg += _(' (started at %s)') % opts['rev']
3892 ui.warn((msg + '\n') % headless)
3898 ui.warn((msg + '\n') % headless)
3893
3899
3894 if not heads:
3900 if not heads:
3895 return 1
3901 return 1
3896
3902
3897 heads = sorted(heads, key=lambda x: -x.rev())
3903 heads = sorted(heads, key=lambda x: -x.rev())
3898 displayer = cmdutil.show_changeset(ui, repo, opts)
3904 displayer = cmdutil.show_changeset(ui, repo, opts)
3899 for ctx in heads:
3905 for ctx in heads:
3900 displayer.show(ctx)
3906 displayer.show(ctx)
3901 displayer.close()
3907 displayer.close()
3902
3908
3903 @command('help',
3909 @command('help',
3904 [('e', 'extension', None, _('show only help for extensions')),
3910 [('e', 'extension', None, _('show only help for extensions')),
3905 ('c', 'command', None, _('show only help for commands')),
3911 ('c', 'command', None, _('show only help for commands')),
3906 ('k', 'keyword', '', _('show topics matching keyword')),
3912 ('k', 'keyword', '', _('show topics matching keyword')),
3907 ],
3913 ],
3908 _('[-ec] [TOPIC]'),
3914 _('[-ec] [TOPIC]'),
3909 norepo=True)
3915 norepo=True)
3910 def help_(ui, name=None, **opts):
3916 def help_(ui, name=None, **opts):
3911 """show help for a given topic or a help overview
3917 """show help for a given topic or a help overview
3912
3918
3913 With no arguments, print a list of commands with short help messages.
3919 With no arguments, print a list of commands with short help messages.
3914
3920
3915 Given a topic, extension, or command name, print help for that
3921 Given a topic, extension, or command name, print help for that
3916 topic.
3922 topic.
3917
3923
3918 Returns 0 if successful.
3924 Returns 0 if successful.
3919 """
3925 """
3920
3926
3921 textwidth = min(ui.termwidth(), 80) - 2
3927 textwidth = min(ui.termwidth(), 80) - 2
3922
3928
3923 keep = []
3929 keep = []
3924 if ui.verbose:
3930 if ui.verbose:
3925 keep.append('verbose')
3931 keep.append('verbose')
3926 if sys.platform.startswith('win'):
3932 if sys.platform.startswith('win'):
3927 keep.append('windows')
3933 keep.append('windows')
3928 elif sys.platform == 'OpenVMS':
3934 elif sys.platform == 'OpenVMS':
3929 keep.append('vms')
3935 keep.append('vms')
3930 elif sys.platform == 'plan9':
3936 elif sys.platform == 'plan9':
3931 keep.append('plan9')
3937 keep.append('plan9')
3932 else:
3938 else:
3933 keep.append('unix')
3939 keep.append('unix')
3934 keep.append(sys.platform.lower())
3940 keep.append(sys.platform.lower())
3935
3941
3936 section = None
3942 section = None
3937 if name and '.' in name:
3943 if name and '.' in name:
3938 name, section = name.split('.', 1)
3944 name, section = name.split('.', 1)
3939
3945
3940 text = help.help_(ui, name, **opts)
3946 text = help.help_(ui, name, **opts)
3941
3947
3942 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3948 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3943 section=section)
3949 section=section)
3944 if section and not formatted:
3950 if section and not formatted:
3945 raise util.Abort(_("help section not found"))
3951 raise util.Abort(_("help section not found"))
3946
3952
3947 if 'verbose' in pruned:
3953 if 'verbose' in pruned:
3948 keep.append('omitted')
3954 keep.append('omitted')
3949 else:
3955 else:
3950 keep.append('notomitted')
3956 keep.append('notomitted')
3951 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3957 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3952 section=section)
3958 section=section)
3953 ui.write(formatted)
3959 ui.write(formatted)
3954
3960
3955
3961
3956 @command('identify|id',
3962 @command('identify|id',
3957 [('r', 'rev', '',
3963 [('r', 'rev', '',
3958 _('identify the specified revision'), _('REV')),
3964 _('identify the specified revision'), _('REV')),
3959 ('n', 'num', None, _('show local revision number')),
3965 ('n', 'num', None, _('show local revision number')),
3960 ('i', 'id', None, _('show global revision id')),
3966 ('i', 'id', None, _('show global revision id')),
3961 ('b', 'branch', None, _('show branch')),
3967 ('b', 'branch', None, _('show branch')),
3962 ('t', 'tags', None, _('show tags')),
3968 ('t', 'tags', None, _('show tags')),
3963 ('B', 'bookmarks', None, _('show bookmarks')),
3969 ('B', 'bookmarks', None, _('show bookmarks')),
3964 ] + remoteopts,
3970 ] + remoteopts,
3965 _('[-nibtB] [-r REV] [SOURCE]'),
3971 _('[-nibtB] [-r REV] [SOURCE]'),
3966 optionalrepo=True)
3972 optionalrepo=True)
3967 def identify(ui, repo, source=None, rev=None,
3973 def identify(ui, repo, source=None, rev=None,
3968 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3974 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3969 """identify the working directory or specified revision
3975 """identify the working directory or specified revision
3970
3976
3971 Print a summary identifying the repository state at REV using one or
3977 Print a summary identifying the repository state at REV using one or
3972 two parent hash identifiers, followed by a "+" if the working
3978 two parent hash identifiers, followed by a "+" if the working
3973 directory has uncommitted changes, the branch name (if not default),
3979 directory has uncommitted changes, the branch name (if not default),
3974 a list of tags, and a list of bookmarks.
3980 a list of tags, and a list of bookmarks.
3975
3981
3976 When REV is not given, print a summary of the current state of the
3982 When REV is not given, print a summary of the current state of the
3977 repository.
3983 repository.
3978
3984
3979 Specifying a path to a repository root or Mercurial bundle will
3985 Specifying a path to a repository root or Mercurial bundle will
3980 cause lookup to operate on that repository/bundle.
3986 cause lookup to operate on that repository/bundle.
3981
3987
3982 .. container:: verbose
3988 .. container:: verbose
3983
3989
3984 Examples:
3990 Examples:
3985
3991
3986 - generate a build identifier for the working directory::
3992 - generate a build identifier for the working directory::
3987
3993
3988 hg id --id > build-id.dat
3994 hg id --id > build-id.dat
3989
3995
3990 - find the revision corresponding to a tag::
3996 - find the revision corresponding to a tag::
3991
3997
3992 hg id -n -r 1.3
3998 hg id -n -r 1.3
3993
3999
3994 - check the most recent revision of a remote repository::
4000 - check the most recent revision of a remote repository::
3995
4001
3996 hg id -r tip http://selenic.com/hg/
4002 hg id -r tip http://selenic.com/hg/
3997
4003
3998 Returns 0 if successful.
4004 Returns 0 if successful.
3999 """
4005 """
4000
4006
4001 if not repo and not source:
4007 if not repo and not source:
4002 raise util.Abort(_("there is no Mercurial repository here "
4008 raise util.Abort(_("there is no Mercurial repository here "
4003 "(.hg not found)"))
4009 "(.hg not found)"))
4004
4010
4005 if ui.debugflag:
4011 if ui.debugflag:
4006 hexfunc = hex
4012 hexfunc = hex
4007 else:
4013 else:
4008 hexfunc = short
4014 hexfunc = short
4009 default = not (num or id or branch or tags or bookmarks)
4015 default = not (num or id or branch or tags or bookmarks)
4010 output = []
4016 output = []
4011 revs = []
4017 revs = []
4012
4018
4013 if source:
4019 if source:
4014 source, branches = hg.parseurl(ui.expandpath(source))
4020 source, branches = hg.parseurl(ui.expandpath(source))
4015 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4021 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4016 repo = peer.local()
4022 repo = peer.local()
4017 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4023 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4018
4024
4019 if not repo:
4025 if not repo:
4020 if num or branch or tags:
4026 if num or branch or tags:
4021 raise util.Abort(
4027 raise util.Abort(
4022 _("can't query remote revision number, branch, or tags"))
4028 _("can't query remote revision number, branch, or tags"))
4023 if not rev and revs:
4029 if not rev and revs:
4024 rev = revs[0]
4030 rev = revs[0]
4025 if not rev:
4031 if not rev:
4026 rev = "tip"
4032 rev = "tip"
4027
4033
4028 remoterev = peer.lookup(rev)
4034 remoterev = peer.lookup(rev)
4029 if default or id:
4035 if default or id:
4030 output = [hexfunc(remoterev)]
4036 output = [hexfunc(remoterev)]
4031
4037
4032 def getbms():
4038 def getbms():
4033 bms = []
4039 bms = []
4034
4040
4035 if 'bookmarks' in peer.listkeys('namespaces'):
4041 if 'bookmarks' in peer.listkeys('namespaces'):
4036 hexremoterev = hex(remoterev)
4042 hexremoterev = hex(remoterev)
4037 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4043 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4038 if bmr == hexremoterev]
4044 if bmr == hexremoterev]
4039
4045
4040 return sorted(bms)
4046 return sorted(bms)
4041
4047
4042 if bookmarks:
4048 if bookmarks:
4043 output.extend(getbms())
4049 output.extend(getbms())
4044 elif default and not ui.quiet:
4050 elif default and not ui.quiet:
4045 # multiple bookmarks for a single parent separated by '/'
4051 # multiple bookmarks for a single parent separated by '/'
4046 bm = '/'.join(getbms())
4052 bm = '/'.join(getbms())
4047 if bm:
4053 if bm:
4048 output.append(bm)
4054 output.append(bm)
4049 else:
4055 else:
4050 if not rev:
4056 if not rev:
4051 ctx = repo[None]
4057 ctx = repo[None]
4052 parents = ctx.parents()
4058 parents = ctx.parents()
4053 changed = ""
4059 changed = ""
4054 if default or id or num:
4060 if default or id or num:
4055 if (any(repo.status())
4061 if (any(repo.status())
4056 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4062 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4057 changed = '+'
4063 changed = '+'
4058 if default or id:
4064 if default or id:
4059 output = ["%s%s" %
4065 output = ["%s%s" %
4060 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4066 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4061 if num:
4067 if num:
4062 output.append("%s%s" %
4068 output.append("%s%s" %
4063 ('+'.join([str(p.rev()) for p in parents]), changed))
4069 ('+'.join([str(p.rev()) for p in parents]), changed))
4064 else:
4070 else:
4065 ctx = scmutil.revsingle(repo, rev)
4071 ctx = scmutil.revsingle(repo, rev)
4066 if default or id:
4072 if default or id:
4067 output = [hexfunc(ctx.node())]
4073 output = [hexfunc(ctx.node())]
4068 if num:
4074 if num:
4069 output.append(str(ctx.rev()))
4075 output.append(str(ctx.rev()))
4070
4076
4071 if default and not ui.quiet:
4077 if default and not ui.quiet:
4072 b = ctx.branch()
4078 b = ctx.branch()
4073 if b != 'default':
4079 if b != 'default':
4074 output.append("(%s)" % b)
4080 output.append("(%s)" % b)
4075
4081
4076 # multiple tags for a single parent separated by '/'
4082 # multiple tags for a single parent separated by '/'
4077 t = '/'.join(ctx.tags())
4083 t = '/'.join(ctx.tags())
4078 if t:
4084 if t:
4079 output.append(t)
4085 output.append(t)
4080
4086
4081 # multiple bookmarks for a single parent separated by '/'
4087 # multiple bookmarks for a single parent separated by '/'
4082 bm = '/'.join(ctx.bookmarks())
4088 bm = '/'.join(ctx.bookmarks())
4083 if bm:
4089 if bm:
4084 output.append(bm)
4090 output.append(bm)
4085 else:
4091 else:
4086 if branch:
4092 if branch:
4087 output.append(ctx.branch())
4093 output.append(ctx.branch())
4088
4094
4089 if tags:
4095 if tags:
4090 output.extend(ctx.tags())
4096 output.extend(ctx.tags())
4091
4097
4092 if bookmarks:
4098 if bookmarks:
4093 output.extend(ctx.bookmarks())
4099 output.extend(ctx.bookmarks())
4094
4100
4095 ui.write("%s\n" % ' '.join(output))
4101 ui.write("%s\n" % ' '.join(output))
4096
4102
4097 @command('import|patch',
4103 @command('import|patch',
4098 [('p', 'strip', 1,
4104 [('p', 'strip', 1,
4099 _('directory strip option for patch. This has the same '
4105 _('directory strip option for patch. This has the same '
4100 'meaning as the corresponding patch option'), _('NUM')),
4106 'meaning as the corresponding patch option'), _('NUM')),
4101 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4107 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4102 ('e', 'edit', False, _('invoke editor on commit messages')),
4108 ('e', 'edit', False, _('invoke editor on commit messages')),
4103 ('f', 'force', None,
4109 ('f', 'force', None,
4104 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4110 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4105 ('', 'no-commit', None,
4111 ('', 'no-commit', None,
4106 _("don't commit, just update the working directory")),
4112 _("don't commit, just update the working directory")),
4107 ('', 'bypass', None,
4113 ('', 'bypass', None,
4108 _("apply patch without touching the working directory")),
4114 _("apply patch without touching the working directory")),
4109 ('', 'partial', None,
4115 ('', 'partial', None,
4110 _('commit even if some hunks fail')),
4116 _('commit even if some hunks fail')),
4111 ('', 'exact', None,
4117 ('', 'exact', None,
4112 _('apply patch to the nodes from which it was generated')),
4118 _('apply patch to the nodes from which it was generated')),
4113 ('', 'prefix', '',
4119 ('', 'prefix', '',
4114 _('apply patch to subdirectory'), _('DIR')),
4120 _('apply patch to subdirectory'), _('DIR')),
4115 ('', 'import-branch', None,
4121 ('', 'import-branch', None,
4116 _('use any branch information in patch (implied by --exact)'))] +
4122 _('use any branch information in patch (implied by --exact)'))] +
4117 commitopts + commitopts2 + similarityopts,
4123 commitopts + commitopts2 + similarityopts,
4118 _('[OPTION]... PATCH...'))
4124 _('[OPTION]... PATCH...'))
4119 def import_(ui, repo, patch1=None, *patches, **opts):
4125 def import_(ui, repo, patch1=None, *patches, **opts):
4120 """import an ordered set of patches
4126 """import an ordered set of patches
4121
4127
4122 Import a list of patches and commit them individually (unless
4128 Import a list of patches and commit them individually (unless
4123 --no-commit is specified).
4129 --no-commit is specified).
4124
4130
4125 Because import first applies changes to the working directory,
4131 Because import first applies changes to the working directory,
4126 import will abort if there are outstanding changes.
4132 import will abort if there are outstanding changes.
4127
4133
4128 You can import a patch straight from a mail message. Even patches
4134 You can import a patch straight from a mail message. Even patches
4129 as attachments work (to use the body part, it must have type
4135 as attachments work (to use the body part, it must have type
4130 text/plain or text/x-patch). From and Subject headers of email
4136 text/plain or text/x-patch). From and Subject headers of email
4131 message are used as default committer and commit message. All
4137 message are used as default committer and commit message. All
4132 text/plain body parts before first diff are added to commit
4138 text/plain body parts before first diff are added to commit
4133 message.
4139 message.
4134
4140
4135 If the imported patch was generated by :hg:`export`, user and
4141 If the imported patch was generated by :hg:`export`, user and
4136 description from patch override values from message headers and
4142 description from patch override values from message headers and
4137 body. Values given on command line with -m/--message and -u/--user
4143 body. Values given on command line with -m/--message and -u/--user
4138 override these.
4144 override these.
4139
4145
4140 If --exact is specified, import will set the working directory to
4146 If --exact is specified, import will set the working directory to
4141 the parent of each patch before applying it, and will abort if the
4147 the parent of each patch before applying it, and will abort if the
4142 resulting changeset has a different ID than the one recorded in
4148 resulting changeset has a different ID than the one recorded in
4143 the patch. This may happen due to character set problems or other
4149 the patch. This may happen due to character set problems or other
4144 deficiencies in the text patch format.
4150 deficiencies in the text patch format.
4145
4151
4146 Use --bypass to apply and commit patches directly to the
4152 Use --bypass to apply and commit patches directly to the
4147 repository, not touching the working directory. Without --exact,
4153 repository, not touching the working directory. Without --exact,
4148 patches will be applied on top of the working directory parent
4154 patches will be applied on top of the working directory parent
4149 revision.
4155 revision.
4150
4156
4151 With -s/--similarity, hg will attempt to discover renames and
4157 With -s/--similarity, hg will attempt to discover renames and
4152 copies in the patch in the same way as :hg:`addremove`.
4158 copies in the patch in the same way as :hg:`addremove`.
4153
4159
4154 Use --partial to ensure a changeset will be created from the patch
4160 Use --partial to ensure a changeset will be created from the patch
4155 even if some hunks fail to apply. Hunks that fail to apply will be
4161 even if some hunks fail to apply. Hunks that fail to apply will be
4156 written to a <target-file>.rej file. Conflicts can then be resolved
4162 written to a <target-file>.rej file. Conflicts can then be resolved
4157 by hand before :hg:`commit --amend` is run to update the created
4163 by hand before :hg:`commit --amend` is run to update the created
4158 changeset. This flag exists to let people import patches that
4164 changeset. This flag exists to let people import patches that
4159 partially apply without losing the associated metadata (author,
4165 partially apply without losing the associated metadata (author,
4160 date, description, ...). Note that when none of the hunk applies
4166 date, description, ...). Note that when none of the hunk applies
4161 cleanly, :hg:`import --partial` will create an empty changeset,
4167 cleanly, :hg:`import --partial` will create an empty changeset,
4162 importing only the patch metadata.
4168 importing only the patch metadata.
4163
4169
4164 To read a patch from standard input, use "-" as the patch name. If
4170 To read a patch from standard input, use "-" as the patch name. If
4165 a URL is specified, the patch will be downloaded from it.
4171 a URL is specified, the patch will be downloaded from it.
4166 See :hg:`help dates` for a list of formats valid for -d/--date.
4172 See :hg:`help dates` for a list of formats valid for -d/--date.
4167
4173
4168 .. container:: verbose
4174 .. container:: verbose
4169
4175
4170 Examples:
4176 Examples:
4171
4177
4172 - import a traditional patch from a website and detect renames::
4178 - import a traditional patch from a website and detect renames::
4173
4179
4174 hg import -s 80 http://example.com/bugfix.patch
4180 hg import -s 80 http://example.com/bugfix.patch
4175
4181
4176 - import a changeset from an hgweb server::
4182 - import a changeset from an hgweb server::
4177
4183
4178 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4184 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4179
4185
4180 - import all the patches in an Unix-style mbox::
4186 - import all the patches in an Unix-style mbox::
4181
4187
4182 hg import incoming-patches.mbox
4188 hg import incoming-patches.mbox
4183
4189
4184 - attempt to exactly restore an exported changeset (not always
4190 - attempt to exactly restore an exported changeset (not always
4185 possible)::
4191 possible)::
4186
4192
4187 hg import --exact proposed-fix.patch
4193 hg import --exact proposed-fix.patch
4188
4194
4189 Returns 0 on success, 1 on partial success (see --partial).
4195 Returns 0 on success, 1 on partial success (see --partial).
4190 """
4196 """
4191
4197
4192 if not patch1:
4198 if not patch1:
4193 raise util.Abort(_('need at least one patch to import'))
4199 raise util.Abort(_('need at least one patch to import'))
4194
4200
4195 patches = (patch1,) + patches
4201 patches = (patch1,) + patches
4196
4202
4197 date = opts.get('date')
4203 date = opts.get('date')
4198 if date:
4204 if date:
4199 opts['date'] = util.parsedate(date)
4205 opts['date'] = util.parsedate(date)
4200
4206
4201 update = not opts.get('bypass')
4207 update = not opts.get('bypass')
4202 if not update and opts.get('no_commit'):
4208 if not update and opts.get('no_commit'):
4203 raise util.Abort(_('cannot use --no-commit with --bypass'))
4209 raise util.Abort(_('cannot use --no-commit with --bypass'))
4204 try:
4210 try:
4205 sim = float(opts.get('similarity') or 0)
4211 sim = float(opts.get('similarity') or 0)
4206 except ValueError:
4212 except ValueError:
4207 raise util.Abort(_('similarity must be a number'))
4213 raise util.Abort(_('similarity must be a number'))
4208 if sim < 0 or sim > 100:
4214 if sim < 0 or sim > 100:
4209 raise util.Abort(_('similarity must be between 0 and 100'))
4215 raise util.Abort(_('similarity must be between 0 and 100'))
4210 if sim and not update:
4216 if sim and not update:
4211 raise util.Abort(_('cannot use --similarity with --bypass'))
4217 raise util.Abort(_('cannot use --similarity with --bypass'))
4212 if opts.get('exact') and opts.get('edit'):
4218 if opts.get('exact') and opts.get('edit'):
4213 raise util.Abort(_('cannot use --exact with --edit'))
4219 raise util.Abort(_('cannot use --exact with --edit'))
4214 if opts.get('exact') and opts.get('prefix'):
4220 if opts.get('exact') and opts.get('prefix'):
4215 raise util.Abort(_('cannot use --exact with --prefix'))
4221 raise util.Abort(_('cannot use --exact with --prefix'))
4216
4222
4217 if update:
4223 if update:
4218 cmdutil.checkunfinished(repo)
4224 cmdutil.checkunfinished(repo)
4219 if (opts.get('exact') or not opts.get('force')) and update:
4225 if (opts.get('exact') or not opts.get('force')) and update:
4220 cmdutil.bailifchanged(repo)
4226 cmdutil.bailifchanged(repo)
4221
4227
4222 base = opts["base"]
4228 base = opts["base"]
4223 wlock = dsguard = lock = tr = None
4229 wlock = dsguard = lock = tr = None
4224 msgs = []
4230 msgs = []
4225 ret = 0
4231 ret = 0
4226
4232
4227
4233
4228 try:
4234 try:
4229 try:
4235 try:
4230 wlock = repo.wlock()
4236 wlock = repo.wlock()
4231 dsguard = cmdutil.dirstateguard(repo, 'import')
4237 dsguard = cmdutil.dirstateguard(repo, 'import')
4232 if not opts.get('no_commit'):
4238 if not opts.get('no_commit'):
4233 lock = repo.lock()
4239 lock = repo.lock()
4234 tr = repo.transaction('import')
4240 tr = repo.transaction('import')
4235 parents = repo.parents()
4241 parents = repo.parents()
4236 for patchurl in patches:
4242 for patchurl in patches:
4237 if patchurl == '-':
4243 if patchurl == '-':
4238 ui.status(_('applying patch from stdin\n'))
4244 ui.status(_('applying patch from stdin\n'))
4239 patchfile = ui.fin
4245 patchfile = ui.fin
4240 patchurl = 'stdin' # for error message
4246 patchurl = 'stdin' # for error message
4241 else:
4247 else:
4242 patchurl = os.path.join(base, patchurl)
4248 patchurl = os.path.join(base, patchurl)
4243 ui.status(_('applying %s\n') % patchurl)
4249 ui.status(_('applying %s\n') % patchurl)
4244 patchfile = hg.openpath(ui, patchurl)
4250 patchfile = hg.openpath(ui, patchurl)
4245
4251
4246 haspatch = False
4252 haspatch = False
4247 for hunk in patch.split(patchfile):
4253 for hunk in patch.split(patchfile):
4248 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4254 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4249 parents, opts,
4255 parents, opts,
4250 msgs, hg.clean)
4256 msgs, hg.clean)
4251 if msg:
4257 if msg:
4252 haspatch = True
4258 haspatch = True
4253 ui.note(msg + '\n')
4259 ui.note(msg + '\n')
4254 if update or opts.get('exact'):
4260 if update or opts.get('exact'):
4255 parents = repo.parents()
4261 parents = repo.parents()
4256 else:
4262 else:
4257 parents = [repo[node]]
4263 parents = [repo[node]]
4258 if rej:
4264 if rej:
4259 ui.write_err(_("patch applied partially\n"))
4265 ui.write_err(_("patch applied partially\n"))
4260 ui.write_err(_("(fix the .rej files and run "
4266 ui.write_err(_("(fix the .rej files and run "
4261 "`hg commit --amend`)\n"))
4267 "`hg commit --amend`)\n"))
4262 ret = 1
4268 ret = 1
4263 break
4269 break
4264
4270
4265 if not haspatch:
4271 if not haspatch:
4266 raise util.Abort(_('%s: no diffs found') % patchurl)
4272 raise util.Abort(_('%s: no diffs found') % patchurl)
4267
4273
4268 if tr:
4274 if tr:
4269 tr.close()
4275 tr.close()
4270 if msgs:
4276 if msgs:
4271 repo.savecommitmessage('\n* * *\n'.join(msgs))
4277 repo.savecommitmessage('\n* * *\n'.join(msgs))
4272 dsguard.close()
4278 dsguard.close()
4273 return ret
4279 return ret
4274 finally:
4280 finally:
4275 # TODO: get rid of this meaningless try/finally enclosing.
4281 # TODO: get rid of this meaningless try/finally enclosing.
4276 # this is kept only to reduce changes in a patch.
4282 # this is kept only to reduce changes in a patch.
4277 pass
4283 pass
4278 finally:
4284 finally:
4279 if tr:
4285 if tr:
4280 tr.release()
4286 tr.release()
4281 release(lock, dsguard, wlock)
4287 release(lock, dsguard, wlock)
4282
4288
4283 @command('incoming|in',
4289 @command('incoming|in',
4284 [('f', 'force', None,
4290 [('f', 'force', None,
4285 _('run even if remote repository is unrelated')),
4291 _('run even if remote repository is unrelated')),
4286 ('n', 'newest-first', None, _('show newest record first')),
4292 ('n', 'newest-first', None, _('show newest record first')),
4287 ('', 'bundle', '',
4293 ('', 'bundle', '',
4288 _('file to store the bundles into'), _('FILE')),
4294 _('file to store the bundles into'), _('FILE')),
4289 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4295 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4290 ('B', 'bookmarks', False, _("compare bookmarks")),
4296 ('B', 'bookmarks', False, _("compare bookmarks")),
4291 ('b', 'branch', [],
4297 ('b', 'branch', [],
4292 _('a specific branch you would like to pull'), _('BRANCH')),
4298 _('a specific branch you would like to pull'), _('BRANCH')),
4293 ] + logopts + remoteopts + subrepoopts,
4299 ] + logopts + remoteopts + subrepoopts,
4294 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4300 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4295 def incoming(ui, repo, source="default", **opts):
4301 def incoming(ui, repo, source="default", **opts):
4296 """show new changesets found in source
4302 """show new changesets found in source
4297
4303
4298 Show new changesets found in the specified path/URL or the default
4304 Show new changesets found in the specified path/URL or the default
4299 pull location. These are the changesets that would have been pulled
4305 pull location. These are the changesets that would have been pulled
4300 if a pull at the time you issued this command.
4306 if a pull at the time you issued this command.
4301
4307
4302 See pull for valid source format details.
4308 See pull for valid source format details.
4303
4309
4304 .. container:: verbose
4310 .. container:: verbose
4305
4311
4306 With -B/--bookmarks, the result of bookmark comparison between
4312 With -B/--bookmarks, the result of bookmark comparison between
4307 local and remote repositories is displayed. With -v/--verbose,
4313 local and remote repositories is displayed. With -v/--verbose,
4308 status is also displayed for each bookmark like below::
4314 status is also displayed for each bookmark like below::
4309
4315
4310 BM1 01234567890a added
4316 BM1 01234567890a added
4311 BM2 1234567890ab advanced
4317 BM2 1234567890ab advanced
4312 BM3 234567890abc diverged
4318 BM3 234567890abc diverged
4313 BM4 34567890abcd changed
4319 BM4 34567890abcd changed
4314
4320
4315 The action taken locally when pulling depends on the
4321 The action taken locally when pulling depends on the
4316 status of each bookmark:
4322 status of each bookmark:
4317
4323
4318 :``added``: pull will create it
4324 :``added``: pull will create it
4319 :``advanced``: pull will update it
4325 :``advanced``: pull will update it
4320 :``diverged``: pull will create a divergent bookmark
4326 :``diverged``: pull will create a divergent bookmark
4321 :``changed``: result depends on remote changesets
4327 :``changed``: result depends on remote changesets
4322
4328
4323 From the point of view of pulling behavior, bookmark
4329 From the point of view of pulling behavior, bookmark
4324 existing only in the remote repository are treated as ``added``,
4330 existing only in the remote repository are treated as ``added``,
4325 even if it is in fact locally deleted.
4331 even if it is in fact locally deleted.
4326
4332
4327 .. container:: verbose
4333 .. container:: verbose
4328
4334
4329 For remote repository, using --bundle avoids downloading the
4335 For remote repository, using --bundle avoids downloading the
4330 changesets twice if the incoming is followed by a pull.
4336 changesets twice if the incoming is followed by a pull.
4331
4337
4332 Examples:
4338 Examples:
4333
4339
4334 - show incoming changes with patches and full description::
4340 - show incoming changes with patches and full description::
4335
4341
4336 hg incoming -vp
4342 hg incoming -vp
4337
4343
4338 - show incoming changes excluding merges, store a bundle::
4344 - show incoming changes excluding merges, store a bundle::
4339
4345
4340 hg in -vpM --bundle incoming.hg
4346 hg in -vpM --bundle incoming.hg
4341 hg pull incoming.hg
4347 hg pull incoming.hg
4342
4348
4343 - briefly list changes inside a bundle::
4349 - briefly list changes inside a bundle::
4344
4350
4345 hg in changes.hg -T "{desc|firstline}\\n"
4351 hg in changes.hg -T "{desc|firstline}\\n"
4346
4352
4347 Returns 0 if there are incoming changes, 1 otherwise.
4353 Returns 0 if there are incoming changes, 1 otherwise.
4348 """
4354 """
4349 if opts.get('graph'):
4355 if opts.get('graph'):
4350 cmdutil.checkunsupportedgraphflags([], opts)
4356 cmdutil.checkunsupportedgraphflags([], opts)
4351 def display(other, chlist, displayer):
4357 def display(other, chlist, displayer):
4352 revdag = cmdutil.graphrevs(other, chlist, opts)
4358 revdag = cmdutil.graphrevs(other, chlist, opts)
4353 showparents = [ctx.node() for ctx in repo[None].parents()]
4359 showparents = [ctx.node() for ctx in repo[None].parents()]
4354 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4360 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4355 graphmod.asciiedges)
4361 graphmod.asciiedges)
4356
4362
4357 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4363 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4358 return 0
4364 return 0
4359
4365
4360 if opts.get('bundle') and opts.get('subrepos'):
4366 if opts.get('bundle') and opts.get('subrepos'):
4361 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4367 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4362
4368
4363 if opts.get('bookmarks'):
4369 if opts.get('bookmarks'):
4364 source, branches = hg.parseurl(ui.expandpath(source),
4370 source, branches = hg.parseurl(ui.expandpath(source),
4365 opts.get('branch'))
4371 opts.get('branch'))
4366 other = hg.peer(repo, opts, source)
4372 other = hg.peer(repo, opts, source)
4367 if 'bookmarks' not in other.listkeys('namespaces'):
4373 if 'bookmarks' not in other.listkeys('namespaces'):
4368 ui.warn(_("remote doesn't support bookmarks\n"))
4374 ui.warn(_("remote doesn't support bookmarks\n"))
4369 return 0
4375 return 0
4370 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4376 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4371 return bookmarks.incoming(ui, repo, other)
4377 return bookmarks.incoming(ui, repo, other)
4372
4378
4373 repo._subtoppath = ui.expandpath(source)
4379 repo._subtoppath = ui.expandpath(source)
4374 try:
4380 try:
4375 return hg.incoming(ui, repo, source, opts)
4381 return hg.incoming(ui, repo, source, opts)
4376 finally:
4382 finally:
4377 del repo._subtoppath
4383 del repo._subtoppath
4378
4384
4379
4385
4380 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4386 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4381 norepo=True)
4387 norepo=True)
4382 def init(ui, dest=".", **opts):
4388 def init(ui, dest=".", **opts):
4383 """create a new repository in the given directory
4389 """create a new repository in the given directory
4384
4390
4385 Initialize a new repository in the given directory. If the given
4391 Initialize a new repository in the given directory. If the given
4386 directory does not exist, it will be created.
4392 directory does not exist, it will be created.
4387
4393
4388 If no directory is given, the current directory is used.
4394 If no directory is given, the current directory is used.
4389
4395
4390 It is possible to specify an ``ssh://`` URL as the destination.
4396 It is possible to specify an ``ssh://`` URL as the destination.
4391 See :hg:`help urls` for more information.
4397 See :hg:`help urls` for more information.
4392
4398
4393 Returns 0 on success.
4399 Returns 0 on success.
4394 """
4400 """
4395 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4401 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4396
4402
4397 @command('locate',
4403 @command('locate',
4398 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4404 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4399 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4405 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4400 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4406 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4401 ] + walkopts,
4407 ] + walkopts,
4402 _('[OPTION]... [PATTERN]...'))
4408 _('[OPTION]... [PATTERN]...'))
4403 def locate(ui, repo, *pats, **opts):
4409 def locate(ui, repo, *pats, **opts):
4404 """locate files matching specific patterns (DEPRECATED)
4410 """locate files matching specific patterns (DEPRECATED)
4405
4411
4406 Print files under Mercurial control in the working directory whose
4412 Print files under Mercurial control in the working directory whose
4407 names match the given patterns.
4413 names match the given patterns.
4408
4414
4409 By default, this command searches all directories in the working
4415 By default, this command searches all directories in the working
4410 directory. To search just the current directory and its
4416 directory. To search just the current directory and its
4411 subdirectories, use "--include .".
4417 subdirectories, use "--include .".
4412
4418
4413 If no patterns are given to match, this command prints the names
4419 If no patterns are given to match, this command prints the names
4414 of all files under Mercurial control in the working directory.
4420 of all files under Mercurial control in the working directory.
4415
4421
4416 If you want to feed the output of this command into the "xargs"
4422 If you want to feed the output of this command into the "xargs"
4417 command, use the -0 option to both this command and "xargs". This
4423 command, use the -0 option to both this command and "xargs". This
4418 will avoid the problem of "xargs" treating single filenames that
4424 will avoid the problem of "xargs" treating single filenames that
4419 contain whitespace as multiple filenames.
4425 contain whitespace as multiple filenames.
4420
4426
4421 See :hg:`help files` for a more versatile command.
4427 See :hg:`help files` for a more versatile command.
4422
4428
4423 Returns 0 if a match is found, 1 otherwise.
4429 Returns 0 if a match is found, 1 otherwise.
4424 """
4430 """
4425 if opts.get('print0'):
4431 if opts.get('print0'):
4426 end = '\0'
4432 end = '\0'
4427 else:
4433 else:
4428 end = '\n'
4434 end = '\n'
4429 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4435 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4430
4436
4431 ret = 1
4437 ret = 1
4432 ctx = repo[rev]
4438 ctx = repo[rev]
4433 m = scmutil.match(ctx, pats, opts, default='relglob')
4439 m = scmutil.match(ctx, pats, opts, default='relglob')
4434 m.bad = lambda x, y: False
4440 m.bad = lambda x, y: False
4435
4441
4436 for abs in ctx.matches(m):
4442 for abs in ctx.matches(m):
4437 if opts.get('fullpath'):
4443 if opts.get('fullpath'):
4438 ui.write(repo.wjoin(abs), end)
4444 ui.write(repo.wjoin(abs), end)
4439 else:
4445 else:
4440 ui.write(((pats and m.rel(abs)) or abs), end)
4446 ui.write(((pats and m.rel(abs)) or abs), end)
4441 ret = 0
4447 ret = 0
4442
4448
4443 return ret
4449 return ret
4444
4450
4445 @command('^log|history',
4451 @command('^log|history',
4446 [('f', 'follow', None,
4452 [('f', 'follow', None,
4447 _('follow changeset history, or file history across copies and renames')),
4453 _('follow changeset history, or file history across copies and renames')),
4448 ('', 'follow-first', None,
4454 ('', 'follow-first', None,
4449 _('only follow the first parent of merge changesets (DEPRECATED)')),
4455 _('only follow the first parent of merge changesets (DEPRECATED)')),
4450 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4456 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4451 ('C', 'copies', None, _('show copied files')),
4457 ('C', 'copies', None, _('show copied files')),
4452 ('k', 'keyword', [],
4458 ('k', 'keyword', [],
4453 _('do case-insensitive search for a given text'), _('TEXT')),
4459 _('do case-insensitive search for a given text'), _('TEXT')),
4454 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4460 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4455 ('', 'removed', None, _('include revisions where files were removed')),
4461 ('', 'removed', None, _('include revisions where files were removed')),
4456 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4462 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4457 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4463 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4458 ('', 'only-branch', [],
4464 ('', 'only-branch', [],
4459 _('show only changesets within the given named branch (DEPRECATED)'),
4465 _('show only changesets within the given named branch (DEPRECATED)'),
4460 _('BRANCH')),
4466 _('BRANCH')),
4461 ('b', 'branch', [],
4467 ('b', 'branch', [],
4462 _('show changesets within the given named branch'), _('BRANCH')),
4468 _('show changesets within the given named branch'), _('BRANCH')),
4463 ('P', 'prune', [],
4469 ('P', 'prune', [],
4464 _('do not display revision or any of its ancestors'), _('REV')),
4470 _('do not display revision or any of its ancestors'), _('REV')),
4465 ] + logopts + walkopts,
4471 ] + logopts + walkopts,
4466 _('[OPTION]... [FILE]'),
4472 _('[OPTION]... [FILE]'),
4467 inferrepo=True)
4473 inferrepo=True)
4468 def log(ui, repo, *pats, **opts):
4474 def log(ui, repo, *pats, **opts):
4469 """show revision history of entire repository or files
4475 """show revision history of entire repository or files
4470
4476
4471 Print the revision history of the specified files or the entire
4477 Print the revision history of the specified files or the entire
4472 project.
4478 project.
4473
4479
4474 If no revision range is specified, the default is ``tip:0`` unless
4480 If no revision range is specified, the default is ``tip:0`` unless
4475 --follow is set, in which case the working directory parent is
4481 --follow is set, in which case the working directory parent is
4476 used as the starting revision.
4482 used as the starting revision.
4477
4483
4478 File history is shown without following rename or copy history of
4484 File history is shown without following rename or copy history of
4479 files. Use -f/--follow with a filename to follow history across
4485 files. Use -f/--follow with a filename to follow history across
4480 renames and copies. --follow without a filename will only show
4486 renames and copies. --follow without a filename will only show
4481 ancestors or descendants of the starting revision.
4487 ancestors or descendants of the starting revision.
4482
4488
4483 By default this command prints revision number and changeset id,
4489 By default this command prints revision number and changeset id,
4484 tags, non-trivial parents, user, date and time, and a summary for
4490 tags, non-trivial parents, user, date and time, and a summary for
4485 each commit. When the -v/--verbose switch is used, the list of
4491 each commit. When the -v/--verbose switch is used, the list of
4486 changed files and full commit message are shown.
4492 changed files and full commit message are shown.
4487
4493
4488 With --graph the revisions are shown as an ASCII art DAG with the most
4494 With --graph the revisions are shown as an ASCII art DAG with the most
4489 recent changeset at the top.
4495 recent changeset at the top.
4490 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4496 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4491 and '+' represents a fork where the changeset from the lines below is a
4497 and '+' represents a fork where the changeset from the lines below is a
4492 parent of the 'o' merge on the same line.
4498 parent of the 'o' merge on the same line.
4493
4499
4494 .. note::
4500 .. note::
4495
4501
4496 log -p/--patch may generate unexpected diff output for merge
4502 log -p/--patch may generate unexpected diff output for merge
4497 changesets, as it will only compare the merge changeset against
4503 changesets, as it will only compare the merge changeset against
4498 its first parent. Also, only files different from BOTH parents
4504 its first parent. Also, only files different from BOTH parents
4499 will appear in files:.
4505 will appear in files:.
4500
4506
4501 .. note::
4507 .. note::
4502
4508
4503 for performance reasons, log FILE may omit duplicate changes
4509 for performance reasons, log FILE may omit duplicate changes
4504 made on branches and will not show removals or mode changes. To
4510 made on branches and will not show removals or mode changes. To
4505 see all such changes, use the --removed switch.
4511 see all such changes, use the --removed switch.
4506
4512
4507 .. container:: verbose
4513 .. container:: verbose
4508
4514
4509 Some examples:
4515 Some examples:
4510
4516
4511 - changesets with full descriptions and file lists::
4517 - changesets with full descriptions and file lists::
4512
4518
4513 hg log -v
4519 hg log -v
4514
4520
4515 - changesets ancestral to the working directory::
4521 - changesets ancestral to the working directory::
4516
4522
4517 hg log -f
4523 hg log -f
4518
4524
4519 - last 10 commits on the current branch::
4525 - last 10 commits on the current branch::
4520
4526
4521 hg log -l 10 -b .
4527 hg log -l 10 -b .
4522
4528
4523 - changesets showing all modifications of a file, including removals::
4529 - changesets showing all modifications of a file, including removals::
4524
4530
4525 hg log --removed file.c
4531 hg log --removed file.c
4526
4532
4527 - all changesets that touch a directory, with diffs, excluding merges::
4533 - all changesets that touch a directory, with diffs, excluding merges::
4528
4534
4529 hg log -Mp lib/
4535 hg log -Mp lib/
4530
4536
4531 - all revision numbers that match a keyword::
4537 - all revision numbers that match a keyword::
4532
4538
4533 hg log -k bug --template "{rev}\\n"
4539 hg log -k bug --template "{rev}\\n"
4534
4540
4535 - list available log templates::
4541 - list available log templates::
4536
4542
4537 hg log -T list
4543 hg log -T list
4538
4544
4539 - check if a given changeset is included in a tagged release::
4545 - check if a given changeset is included in a tagged release::
4540
4546
4541 hg log -r "a21ccf and ancestor(1.9)"
4547 hg log -r "a21ccf and ancestor(1.9)"
4542
4548
4543 - find all changesets by some user in a date range::
4549 - find all changesets by some user in a date range::
4544
4550
4545 hg log -k alice -d "may 2008 to jul 2008"
4551 hg log -k alice -d "may 2008 to jul 2008"
4546
4552
4547 - summary of all changesets after the last tag::
4553 - summary of all changesets after the last tag::
4548
4554
4549 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4555 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4550
4556
4551 See :hg:`help dates` for a list of formats valid for -d/--date.
4557 See :hg:`help dates` for a list of formats valid for -d/--date.
4552
4558
4553 See :hg:`help revisions` and :hg:`help revsets` for more about
4559 See :hg:`help revisions` and :hg:`help revsets` for more about
4554 specifying revisions.
4560 specifying revisions.
4555
4561
4556 See :hg:`help templates` for more about pre-packaged styles and
4562 See :hg:`help templates` for more about pre-packaged styles and
4557 specifying custom templates.
4563 specifying custom templates.
4558
4564
4559 Returns 0 on success.
4565 Returns 0 on success.
4560
4566
4561 """
4567 """
4562 if opts.get('follow') and opts.get('rev'):
4568 if opts.get('follow') and opts.get('rev'):
4563 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4569 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4564 del opts['follow']
4570 del opts['follow']
4565
4571
4566 if opts.get('graph'):
4572 if opts.get('graph'):
4567 return cmdutil.graphlog(ui, repo, *pats, **opts)
4573 return cmdutil.graphlog(ui, repo, *pats, **opts)
4568
4574
4569 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4575 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4570 limit = cmdutil.loglimit(opts)
4576 limit = cmdutil.loglimit(opts)
4571 count = 0
4577 count = 0
4572
4578
4573 getrenamed = None
4579 getrenamed = None
4574 if opts.get('copies'):
4580 if opts.get('copies'):
4575 endrev = None
4581 endrev = None
4576 if opts.get('rev'):
4582 if opts.get('rev'):
4577 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4583 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4578 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4584 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4579
4585
4580 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4586 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4581 for rev in revs:
4587 for rev in revs:
4582 if count == limit:
4588 if count == limit:
4583 break
4589 break
4584 ctx = repo[rev]
4590 ctx = repo[rev]
4585 copies = None
4591 copies = None
4586 if getrenamed is not None and rev:
4592 if getrenamed is not None and rev:
4587 copies = []
4593 copies = []
4588 for fn in ctx.files():
4594 for fn in ctx.files():
4589 rename = getrenamed(fn, rev)
4595 rename = getrenamed(fn, rev)
4590 if rename:
4596 if rename:
4591 copies.append((fn, rename[0]))
4597 copies.append((fn, rename[0]))
4592 if filematcher:
4598 if filematcher:
4593 revmatchfn = filematcher(ctx.rev())
4599 revmatchfn = filematcher(ctx.rev())
4594 else:
4600 else:
4595 revmatchfn = None
4601 revmatchfn = None
4596 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4602 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4597 if displayer.flush(rev):
4603 if displayer.flush(rev):
4598 count += 1
4604 count += 1
4599
4605
4600 displayer.close()
4606 displayer.close()
4601
4607
4602 @command('manifest',
4608 @command('manifest',
4603 [('r', 'rev', '', _('revision to display'), _('REV')),
4609 [('r', 'rev', '', _('revision to display'), _('REV')),
4604 ('', 'all', False, _("list files from all revisions"))]
4610 ('', 'all', False, _("list files from all revisions"))]
4605 + formatteropts,
4611 + formatteropts,
4606 _('[-r REV]'))
4612 _('[-r REV]'))
4607 def manifest(ui, repo, node=None, rev=None, **opts):
4613 def manifest(ui, repo, node=None, rev=None, **opts):
4608 """output the current or given revision of the project manifest
4614 """output the current or given revision of the project manifest
4609
4615
4610 Print a list of version controlled files for the given revision.
4616 Print a list of version controlled files for the given revision.
4611 If no revision is given, the first parent of the working directory
4617 If no revision is given, the first parent of the working directory
4612 is used, or the null revision if no revision is checked out.
4618 is used, or the null revision if no revision is checked out.
4613
4619
4614 With -v, print file permissions, symlink and executable bits.
4620 With -v, print file permissions, symlink and executable bits.
4615 With --debug, print file revision hashes.
4621 With --debug, print file revision hashes.
4616
4622
4617 If option --all is specified, the list of all files from all revisions
4623 If option --all is specified, the list of all files from all revisions
4618 is printed. This includes deleted and renamed files.
4624 is printed. This includes deleted and renamed files.
4619
4625
4620 Returns 0 on success.
4626 Returns 0 on success.
4621 """
4627 """
4622
4628
4623 fm = ui.formatter('manifest', opts)
4629 fm = ui.formatter('manifest', opts)
4624
4630
4625 if opts.get('all'):
4631 if opts.get('all'):
4626 if rev or node:
4632 if rev or node:
4627 raise util.Abort(_("can't specify a revision with --all"))
4633 raise util.Abort(_("can't specify a revision with --all"))
4628
4634
4629 res = []
4635 res = []
4630 prefix = "data/"
4636 prefix = "data/"
4631 suffix = ".i"
4637 suffix = ".i"
4632 plen = len(prefix)
4638 plen = len(prefix)
4633 slen = len(suffix)
4639 slen = len(suffix)
4634 lock = repo.lock()
4640 lock = repo.lock()
4635 try:
4641 try:
4636 for fn, b, size in repo.store.datafiles():
4642 for fn, b, size in repo.store.datafiles():
4637 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4643 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4638 res.append(fn[plen:-slen])
4644 res.append(fn[plen:-slen])
4639 finally:
4645 finally:
4640 lock.release()
4646 lock.release()
4641 for f in res:
4647 for f in res:
4642 fm.startitem()
4648 fm.startitem()
4643 fm.write("path", '%s\n', f)
4649 fm.write("path", '%s\n', f)
4644 fm.end()
4650 fm.end()
4645 return
4651 return
4646
4652
4647 if rev and node:
4653 if rev and node:
4648 raise util.Abort(_("please specify just one revision"))
4654 raise util.Abort(_("please specify just one revision"))
4649
4655
4650 if not node:
4656 if not node:
4651 node = rev
4657 node = rev
4652
4658
4653 char = {'l': '@', 'x': '*', '': ''}
4659 char = {'l': '@', 'x': '*', '': ''}
4654 mode = {'l': '644', 'x': '755', '': '644'}
4660 mode = {'l': '644', 'x': '755', '': '644'}
4655 ctx = scmutil.revsingle(repo, node)
4661 ctx = scmutil.revsingle(repo, node)
4656 mf = ctx.manifest()
4662 mf = ctx.manifest()
4657 for f in ctx:
4663 for f in ctx:
4658 fm.startitem()
4664 fm.startitem()
4659 fl = ctx[f].flags()
4665 fl = ctx[f].flags()
4660 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4666 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4661 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4667 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4662 fm.write('path', '%s\n', f)
4668 fm.write('path', '%s\n', f)
4663 fm.end()
4669 fm.end()
4664
4670
4665 @command('^merge',
4671 @command('^merge',
4666 [('f', 'force', None,
4672 [('f', 'force', None,
4667 _('force a merge including outstanding changes (DEPRECATED)')),
4673 _('force a merge including outstanding changes (DEPRECATED)')),
4668 ('r', 'rev', '', _('revision to merge'), _('REV')),
4674 ('r', 'rev', '', _('revision to merge'), _('REV')),
4669 ('P', 'preview', None,
4675 ('P', 'preview', None,
4670 _('review revisions to merge (no merge is performed)'))
4676 _('review revisions to merge (no merge is performed)'))
4671 ] + mergetoolopts,
4677 ] + mergetoolopts,
4672 _('[-P] [-f] [[-r] REV]'))
4678 _('[-P] [-f] [[-r] REV]'))
4673 def merge(ui, repo, node=None, **opts):
4679 def merge(ui, repo, node=None, **opts):
4674 """merge another revision into working directory
4680 """merge another revision into working directory
4675
4681
4676 The current working directory is updated with all changes made in
4682 The current working directory is updated with all changes made in
4677 the requested revision since the last common predecessor revision.
4683 the requested revision since the last common predecessor revision.
4678
4684
4679 Files that changed between either parent are marked as changed for
4685 Files that changed between either parent are marked as changed for
4680 the next commit and a commit must be performed before any further
4686 the next commit and a commit must be performed before any further
4681 updates to the repository are allowed. The next commit will have
4687 updates to the repository are allowed. The next commit will have
4682 two parents.
4688 two parents.
4683
4689
4684 ``--tool`` can be used to specify the merge tool used for file
4690 ``--tool`` can be used to specify the merge tool used for file
4685 merges. It overrides the HGMERGE environment variable and your
4691 merges. It overrides the HGMERGE environment variable and your
4686 configuration files. See :hg:`help merge-tools` for options.
4692 configuration files. See :hg:`help merge-tools` for options.
4687
4693
4688 If no revision is specified, the working directory's parent is a
4694 If no revision is specified, the working directory's parent is a
4689 head revision, and the current branch contains exactly one other
4695 head revision, and the current branch contains exactly one other
4690 head, the other head is merged with by default. Otherwise, an
4696 head, the other head is merged with by default. Otherwise, an
4691 explicit revision with which to merge with must be provided.
4697 explicit revision with which to merge with must be provided.
4692
4698
4693 :hg:`resolve` must be used to resolve unresolved files.
4699 :hg:`resolve` must be used to resolve unresolved files.
4694
4700
4695 To undo an uncommitted merge, use :hg:`update --clean .` which
4701 To undo an uncommitted merge, use :hg:`update --clean .` which
4696 will check out a clean copy of the original merge parent, losing
4702 will check out a clean copy of the original merge parent, losing
4697 all changes.
4703 all changes.
4698
4704
4699 Returns 0 on success, 1 if there are unresolved files.
4705 Returns 0 on success, 1 if there are unresolved files.
4700 """
4706 """
4701
4707
4702 if opts.get('rev') and node:
4708 if opts.get('rev') and node:
4703 raise util.Abort(_("please specify just one revision"))
4709 raise util.Abort(_("please specify just one revision"))
4704 if not node:
4710 if not node:
4705 node = opts.get('rev')
4711 node = opts.get('rev')
4706
4712
4707 if node:
4713 if node:
4708 node = scmutil.revsingle(repo, node).node()
4714 node = scmutil.revsingle(repo, node).node()
4709
4715
4710 if not node and repo._activebookmark:
4716 if not node and repo._activebookmark:
4711 bmheads = repo.bookmarkheads(repo._activebookmark)
4717 bmheads = repo.bookmarkheads(repo._activebookmark)
4712 curhead = repo[repo._activebookmark].node()
4718 curhead = repo[repo._activebookmark].node()
4713 if len(bmheads) == 2:
4719 if len(bmheads) == 2:
4714 if curhead == bmheads[0]:
4720 if curhead == bmheads[0]:
4715 node = bmheads[1]
4721 node = bmheads[1]
4716 else:
4722 else:
4717 node = bmheads[0]
4723 node = bmheads[0]
4718 elif len(bmheads) > 2:
4724 elif len(bmheads) > 2:
4719 raise util.Abort(_("multiple matching bookmarks to merge - "
4725 raise util.Abort(_("multiple matching bookmarks to merge - "
4720 "please merge with an explicit rev or bookmark"),
4726 "please merge with an explicit rev or bookmark"),
4721 hint=_("run 'hg heads' to see all heads"))
4727 hint=_("run 'hg heads' to see all heads"))
4722 elif len(bmheads) <= 1:
4728 elif len(bmheads) <= 1:
4723 raise util.Abort(_("no matching bookmark to merge - "
4729 raise util.Abort(_("no matching bookmark to merge - "
4724 "please merge with an explicit rev or bookmark"),
4730 "please merge with an explicit rev or bookmark"),
4725 hint=_("run 'hg heads' to see all heads"))
4731 hint=_("run 'hg heads' to see all heads"))
4726
4732
4727 if not node and not repo._activebookmark:
4733 if not node and not repo._activebookmark:
4728 branch = repo[None].branch()
4734 branch = repo[None].branch()
4729 bheads = repo.branchheads(branch)
4735 bheads = repo.branchheads(branch)
4730 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4736 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4731
4737
4732 if len(nbhs) > 2:
4738 if len(nbhs) > 2:
4733 raise util.Abort(_("branch '%s' has %d heads - "
4739 raise util.Abort(_("branch '%s' has %d heads - "
4734 "please merge with an explicit rev")
4740 "please merge with an explicit rev")
4735 % (branch, len(bheads)),
4741 % (branch, len(bheads)),
4736 hint=_("run 'hg heads .' to see heads"))
4742 hint=_("run 'hg heads .' to see heads"))
4737
4743
4738 parent = repo.dirstate.p1()
4744 parent = repo.dirstate.p1()
4739 if len(nbhs) <= 1:
4745 if len(nbhs) <= 1:
4740 if len(bheads) > 1:
4746 if len(bheads) > 1:
4741 raise util.Abort(_("heads are bookmarked - "
4747 raise util.Abort(_("heads are bookmarked - "
4742 "please merge with an explicit rev"),
4748 "please merge with an explicit rev"),
4743 hint=_("run 'hg heads' to see all heads"))
4749 hint=_("run 'hg heads' to see all heads"))
4744 if len(repo.heads()) > 1:
4750 if len(repo.heads()) > 1:
4745 raise util.Abort(_("branch '%s' has one head - "
4751 raise util.Abort(_("branch '%s' has one head - "
4746 "please merge with an explicit rev")
4752 "please merge with an explicit rev")
4747 % branch,
4753 % branch,
4748 hint=_("run 'hg heads' to see all heads"))
4754 hint=_("run 'hg heads' to see all heads"))
4749 msg, hint = _('nothing to merge'), None
4755 msg, hint = _('nothing to merge'), None
4750 if parent != repo.lookup(branch):
4756 if parent != repo.lookup(branch):
4751 hint = _("use 'hg update' instead")
4757 hint = _("use 'hg update' instead")
4752 raise util.Abort(msg, hint=hint)
4758 raise util.Abort(msg, hint=hint)
4753
4759
4754 if parent not in bheads:
4760 if parent not in bheads:
4755 raise util.Abort(_('working directory not at a head revision'),
4761 raise util.Abort(_('working directory not at a head revision'),
4756 hint=_("use 'hg update' or merge with an "
4762 hint=_("use 'hg update' or merge with an "
4757 "explicit revision"))
4763 "explicit revision"))
4758 if parent == nbhs[0]:
4764 if parent == nbhs[0]:
4759 node = nbhs[-1]
4765 node = nbhs[-1]
4760 else:
4766 else:
4761 node = nbhs[0]
4767 node = nbhs[0]
4762
4768
4763 if opts.get('preview'):
4769 if opts.get('preview'):
4764 # find nodes that are ancestors of p2 but not of p1
4770 # find nodes that are ancestors of p2 but not of p1
4765 p1 = repo.lookup('.')
4771 p1 = repo.lookup('.')
4766 p2 = repo.lookup(node)
4772 p2 = repo.lookup(node)
4767 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4773 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4768
4774
4769 displayer = cmdutil.show_changeset(ui, repo, opts)
4775 displayer = cmdutil.show_changeset(ui, repo, opts)
4770 for node in nodes:
4776 for node in nodes:
4771 displayer.show(repo[node])
4777 displayer.show(repo[node])
4772 displayer.close()
4778 displayer.close()
4773 return 0
4779 return 0
4774
4780
4775 try:
4781 try:
4776 # ui.forcemerge is an internal variable, do not document
4782 # ui.forcemerge is an internal variable, do not document
4777 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4783 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4778 return hg.merge(repo, node, force=opts.get('force'))
4784 return hg.merge(repo, node, force=opts.get('force'))
4779 finally:
4785 finally:
4780 ui.setconfig('ui', 'forcemerge', '', 'merge')
4786 ui.setconfig('ui', 'forcemerge', '', 'merge')
4781
4787
4782 @command('outgoing|out',
4788 @command('outgoing|out',
4783 [('f', 'force', None, _('run even when the destination is unrelated')),
4789 [('f', 'force', None, _('run even when the destination is unrelated')),
4784 ('r', 'rev', [],
4790 ('r', 'rev', [],
4785 _('a changeset intended to be included in the destination'), _('REV')),
4791 _('a changeset intended to be included in the destination'), _('REV')),
4786 ('n', 'newest-first', None, _('show newest record first')),
4792 ('n', 'newest-first', None, _('show newest record first')),
4787 ('B', 'bookmarks', False, _('compare bookmarks')),
4793 ('B', 'bookmarks', False, _('compare bookmarks')),
4788 ('b', 'branch', [], _('a specific branch you would like to push'),
4794 ('b', 'branch', [], _('a specific branch you would like to push'),
4789 _('BRANCH')),
4795 _('BRANCH')),
4790 ] + logopts + remoteopts + subrepoopts,
4796 ] + logopts + remoteopts + subrepoopts,
4791 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4797 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4792 def outgoing(ui, repo, dest=None, **opts):
4798 def outgoing(ui, repo, dest=None, **opts):
4793 """show changesets not found in the destination
4799 """show changesets not found in the destination
4794
4800
4795 Show changesets not found in the specified destination repository
4801 Show changesets not found in the specified destination repository
4796 or the default push location. These are the changesets that would
4802 or the default push location. These are the changesets that would
4797 be pushed if a push was requested.
4803 be pushed if a push was requested.
4798
4804
4799 See pull for details of valid destination formats.
4805 See pull for details of valid destination formats.
4800
4806
4801 .. container:: verbose
4807 .. container:: verbose
4802
4808
4803 With -B/--bookmarks, the result of bookmark comparison between
4809 With -B/--bookmarks, the result of bookmark comparison between
4804 local and remote repositories is displayed. With -v/--verbose,
4810 local and remote repositories is displayed. With -v/--verbose,
4805 status is also displayed for each bookmark like below::
4811 status is also displayed for each bookmark like below::
4806
4812
4807 BM1 01234567890a added
4813 BM1 01234567890a added
4808 BM2 deleted
4814 BM2 deleted
4809 BM3 234567890abc advanced
4815 BM3 234567890abc advanced
4810 BM4 34567890abcd diverged
4816 BM4 34567890abcd diverged
4811 BM5 4567890abcde changed
4817 BM5 4567890abcde changed
4812
4818
4813 The action taken when pushing depends on the
4819 The action taken when pushing depends on the
4814 status of each bookmark:
4820 status of each bookmark:
4815
4821
4816 :``added``: push with ``-B`` will create it
4822 :``added``: push with ``-B`` will create it
4817 :``deleted``: push with ``-B`` will delete it
4823 :``deleted``: push with ``-B`` will delete it
4818 :``advanced``: push will update it
4824 :``advanced``: push will update it
4819 :``diverged``: push with ``-B`` will update it
4825 :``diverged``: push with ``-B`` will update it
4820 :``changed``: push with ``-B`` will update it
4826 :``changed``: push with ``-B`` will update it
4821
4827
4822 From the point of view of pushing behavior, bookmarks
4828 From the point of view of pushing behavior, bookmarks
4823 existing only in the remote repository are treated as
4829 existing only in the remote repository are treated as
4824 ``deleted``, even if it is in fact added remotely.
4830 ``deleted``, even if it is in fact added remotely.
4825
4831
4826 Returns 0 if there are outgoing changes, 1 otherwise.
4832 Returns 0 if there are outgoing changes, 1 otherwise.
4827 """
4833 """
4828 if opts.get('graph'):
4834 if opts.get('graph'):
4829 cmdutil.checkunsupportedgraphflags([], opts)
4835 cmdutil.checkunsupportedgraphflags([], opts)
4830 o, other = hg._outgoing(ui, repo, dest, opts)
4836 o, other = hg._outgoing(ui, repo, dest, opts)
4831 if not o:
4837 if not o:
4832 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4838 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4833 return
4839 return
4834
4840
4835 revdag = cmdutil.graphrevs(repo, o, opts)
4841 revdag = cmdutil.graphrevs(repo, o, opts)
4836 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4842 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4837 showparents = [ctx.node() for ctx in repo[None].parents()]
4843 showparents = [ctx.node() for ctx in repo[None].parents()]
4838 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4844 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4839 graphmod.asciiedges)
4845 graphmod.asciiedges)
4840 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4846 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4841 return 0
4847 return 0
4842
4848
4843 if opts.get('bookmarks'):
4849 if opts.get('bookmarks'):
4844 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4850 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4845 dest, branches = hg.parseurl(dest, opts.get('branch'))
4851 dest, branches = hg.parseurl(dest, opts.get('branch'))
4846 other = hg.peer(repo, opts, dest)
4852 other = hg.peer(repo, opts, dest)
4847 if 'bookmarks' not in other.listkeys('namespaces'):
4853 if 'bookmarks' not in other.listkeys('namespaces'):
4848 ui.warn(_("remote doesn't support bookmarks\n"))
4854 ui.warn(_("remote doesn't support bookmarks\n"))
4849 return 0
4855 return 0
4850 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4856 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4851 return bookmarks.outgoing(ui, repo, other)
4857 return bookmarks.outgoing(ui, repo, other)
4852
4858
4853 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4859 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4854 try:
4860 try:
4855 return hg.outgoing(ui, repo, dest, opts)
4861 return hg.outgoing(ui, repo, dest, opts)
4856 finally:
4862 finally:
4857 del repo._subtoppath
4863 del repo._subtoppath
4858
4864
4859 @command('parents',
4865 @command('parents',
4860 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4866 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4861 ] + templateopts,
4867 ] + templateopts,
4862 _('[-r REV] [FILE]'),
4868 _('[-r REV] [FILE]'),
4863 inferrepo=True)
4869 inferrepo=True)
4864 def parents(ui, repo, file_=None, **opts):
4870 def parents(ui, repo, file_=None, **opts):
4865 """show the parents of the working directory or revision (DEPRECATED)
4871 """show the parents of the working directory or revision (DEPRECATED)
4866
4872
4867 Print the working directory's parent revisions. If a revision is
4873 Print the working directory's parent revisions. If a revision is
4868 given via -r/--rev, the parent of that revision will be printed.
4874 given via -r/--rev, the parent of that revision will be printed.
4869 If a file argument is given, the revision in which the file was
4875 If a file argument is given, the revision in which the file was
4870 last changed (before the working directory revision or the
4876 last changed (before the working directory revision or the
4871 argument to --rev if given) is printed.
4877 argument to --rev if given) is printed.
4872
4878
4873 See :hg:`summary` and :hg:`help revsets` for related information.
4879 See :hg:`summary` and :hg:`help revsets` for related information.
4874
4880
4875 Returns 0 on success.
4881 Returns 0 on success.
4876 """
4882 """
4877
4883
4878 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4884 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4879
4885
4880 if file_:
4886 if file_:
4881 m = scmutil.match(ctx, (file_,), opts)
4887 m = scmutil.match(ctx, (file_,), opts)
4882 if m.anypats() or len(m.files()) != 1:
4888 if m.anypats() or len(m.files()) != 1:
4883 raise util.Abort(_('can only specify an explicit filename'))
4889 raise util.Abort(_('can only specify an explicit filename'))
4884 file_ = m.files()[0]
4890 file_ = m.files()[0]
4885 filenodes = []
4891 filenodes = []
4886 for cp in ctx.parents():
4892 for cp in ctx.parents():
4887 if not cp:
4893 if not cp:
4888 continue
4894 continue
4889 try:
4895 try:
4890 filenodes.append(cp.filenode(file_))
4896 filenodes.append(cp.filenode(file_))
4891 except error.LookupError:
4897 except error.LookupError:
4892 pass
4898 pass
4893 if not filenodes:
4899 if not filenodes:
4894 raise util.Abort(_("'%s' not found in manifest!") % file_)
4900 raise util.Abort(_("'%s' not found in manifest!") % file_)
4895 p = []
4901 p = []
4896 for fn in filenodes:
4902 for fn in filenodes:
4897 fctx = repo.filectx(file_, fileid=fn)
4903 fctx = repo.filectx(file_, fileid=fn)
4898 p.append(fctx.node())
4904 p.append(fctx.node())
4899 else:
4905 else:
4900 p = [cp.node() for cp in ctx.parents()]
4906 p = [cp.node() for cp in ctx.parents()]
4901
4907
4902 displayer = cmdutil.show_changeset(ui, repo, opts)
4908 displayer = cmdutil.show_changeset(ui, repo, opts)
4903 for n in p:
4909 for n in p:
4904 if n != nullid:
4910 if n != nullid:
4905 displayer.show(repo[n])
4911 displayer.show(repo[n])
4906 displayer.close()
4912 displayer.close()
4907
4913
4908 @command('paths', [], _('[NAME]'), optionalrepo=True)
4914 @command('paths', [], _('[NAME]'), optionalrepo=True)
4909 def paths(ui, repo, search=None):
4915 def paths(ui, repo, search=None):
4910 """show aliases for remote repositories
4916 """show aliases for remote repositories
4911
4917
4912 Show definition of symbolic path name NAME. If no name is given,
4918 Show definition of symbolic path name NAME. If no name is given,
4913 show definition of all available names.
4919 show definition of all available names.
4914
4920
4915 Option -q/--quiet suppresses all output when searching for NAME
4921 Option -q/--quiet suppresses all output when searching for NAME
4916 and shows only the path names when listing all definitions.
4922 and shows only the path names when listing all definitions.
4917
4923
4918 Path names are defined in the [paths] section of your
4924 Path names are defined in the [paths] section of your
4919 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4925 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4920 repository, ``.hg/hgrc`` is used, too.
4926 repository, ``.hg/hgrc`` is used, too.
4921
4927
4922 The path names ``default`` and ``default-push`` have a special
4928 The path names ``default`` and ``default-push`` have a special
4923 meaning. When performing a push or pull operation, they are used
4929 meaning. When performing a push or pull operation, they are used
4924 as fallbacks if no location is specified on the command-line.
4930 as fallbacks if no location is specified on the command-line.
4925 When ``default-push`` is set, it will be used for push and
4931 When ``default-push`` is set, it will be used for push and
4926 ``default`` will be used for pull; otherwise ``default`` is used
4932 ``default`` will be used for pull; otherwise ``default`` is used
4927 as the fallback for both. When cloning a repository, the clone
4933 as the fallback for both. When cloning a repository, the clone
4928 source is written as ``default`` in ``.hg/hgrc``. Note that
4934 source is written as ``default`` in ``.hg/hgrc``. Note that
4929 ``default`` and ``default-push`` apply to all inbound (e.g.
4935 ``default`` and ``default-push`` apply to all inbound (e.g.
4930 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4936 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4931 :hg:`bundle`) operations.
4937 :hg:`bundle`) operations.
4932
4938
4933 See :hg:`help urls` for more information.
4939 See :hg:`help urls` for more information.
4934
4940
4935 Returns 0 on success.
4941 Returns 0 on success.
4936 """
4942 """
4937 if search:
4943 if search:
4938 for name, path in sorted(ui.paths.iteritems()):
4944 for name, path in sorted(ui.paths.iteritems()):
4939 if name == search:
4945 if name == search:
4940 ui.status("%s\n" % util.hidepassword(path.loc))
4946 ui.status("%s\n" % util.hidepassword(path.loc))
4941 return
4947 return
4942 if not ui.quiet:
4948 if not ui.quiet:
4943 ui.warn(_("not found!\n"))
4949 ui.warn(_("not found!\n"))
4944 return 1
4950 return 1
4945 else:
4951 else:
4946 for name, path in sorted(ui.paths.iteritems()):
4952 for name, path in sorted(ui.paths.iteritems()):
4947 if ui.quiet:
4953 if ui.quiet:
4948 ui.write("%s\n" % name)
4954 ui.write("%s\n" % name)
4949 else:
4955 else:
4950 ui.write("%s = %s\n" % (name,
4956 ui.write("%s = %s\n" % (name,
4951 util.hidepassword(path.loc)))
4957 util.hidepassword(path.loc)))
4952
4958
4953 @command('phase',
4959 @command('phase',
4954 [('p', 'public', False, _('set changeset phase to public')),
4960 [('p', 'public', False, _('set changeset phase to public')),
4955 ('d', 'draft', False, _('set changeset phase to draft')),
4961 ('d', 'draft', False, _('set changeset phase to draft')),
4956 ('s', 'secret', False, _('set changeset phase to secret')),
4962 ('s', 'secret', False, _('set changeset phase to secret')),
4957 ('f', 'force', False, _('allow to move boundary backward')),
4963 ('f', 'force', False, _('allow to move boundary backward')),
4958 ('r', 'rev', [], _('target revision'), _('REV')),
4964 ('r', 'rev', [], _('target revision'), _('REV')),
4959 ],
4965 ],
4960 _('[-p|-d|-s] [-f] [-r] [REV...]'))
4966 _('[-p|-d|-s] [-f] [-r] [REV...]'))
4961 def phase(ui, repo, *revs, **opts):
4967 def phase(ui, repo, *revs, **opts):
4962 """set or show the current phase name
4968 """set or show the current phase name
4963
4969
4964 With no argument, show the phase name of the current revision(s).
4970 With no argument, show the phase name of the current revision(s).
4965
4971
4966 With one of -p/--public, -d/--draft or -s/--secret, change the
4972 With one of -p/--public, -d/--draft or -s/--secret, change the
4967 phase value of the specified revisions.
4973 phase value of the specified revisions.
4968
4974
4969 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4975 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4970 lower phase to an higher phase. Phases are ordered as follows::
4976 lower phase to an higher phase. Phases are ordered as follows::
4971
4977
4972 public < draft < secret
4978 public < draft < secret
4973
4979
4974 Returns 0 on success, 1 if no phases were changed or some could not
4980 Returns 0 on success, 1 if no phases were changed or some could not
4975 be changed.
4981 be changed.
4976 """
4982 """
4977 # search for a unique phase argument
4983 # search for a unique phase argument
4978 targetphase = None
4984 targetphase = None
4979 for idx, name in enumerate(phases.phasenames):
4985 for idx, name in enumerate(phases.phasenames):
4980 if opts[name]:
4986 if opts[name]:
4981 if targetphase is not None:
4987 if targetphase is not None:
4982 raise util.Abort(_('only one phase can be specified'))
4988 raise util.Abort(_('only one phase can be specified'))
4983 targetphase = idx
4989 targetphase = idx
4984
4990
4985 # look for specified revision
4991 # look for specified revision
4986 revs = list(revs)
4992 revs = list(revs)
4987 revs.extend(opts['rev'])
4993 revs.extend(opts['rev'])
4988 if not revs:
4994 if not revs:
4989 # display both parents as the second parent phase can influence
4995 # display both parents as the second parent phase can influence
4990 # the phase of a merge commit
4996 # the phase of a merge commit
4991 revs = [c.rev() for c in repo[None].parents()]
4997 revs = [c.rev() for c in repo[None].parents()]
4992
4998
4993 revs = scmutil.revrange(repo, revs)
4999 revs = scmutil.revrange(repo, revs)
4994
5000
4995 lock = None
5001 lock = None
4996 ret = 0
5002 ret = 0
4997 if targetphase is None:
5003 if targetphase is None:
4998 # display
5004 # display
4999 for r in revs:
5005 for r in revs:
5000 ctx = repo[r]
5006 ctx = repo[r]
5001 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5007 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5002 else:
5008 else:
5003 tr = None
5009 tr = None
5004 lock = repo.lock()
5010 lock = repo.lock()
5005 try:
5011 try:
5006 tr = repo.transaction("phase")
5012 tr = repo.transaction("phase")
5007 # set phase
5013 # set phase
5008 if not revs:
5014 if not revs:
5009 raise util.Abort(_('empty revision set'))
5015 raise util.Abort(_('empty revision set'))
5010 nodes = [repo[r].node() for r in revs]
5016 nodes = [repo[r].node() for r in revs]
5011 # moving revision from public to draft may hide them
5017 # moving revision from public to draft may hide them
5012 # We have to check result on an unfiltered repository
5018 # We have to check result on an unfiltered repository
5013 unfi = repo.unfiltered()
5019 unfi = repo.unfiltered()
5014 getphase = unfi._phasecache.phase
5020 getphase = unfi._phasecache.phase
5015 olddata = [getphase(unfi, r) for r in unfi]
5021 olddata = [getphase(unfi, r) for r in unfi]
5016 phases.advanceboundary(repo, tr, targetphase, nodes)
5022 phases.advanceboundary(repo, tr, targetphase, nodes)
5017 if opts['force']:
5023 if opts['force']:
5018 phases.retractboundary(repo, tr, targetphase, nodes)
5024 phases.retractboundary(repo, tr, targetphase, nodes)
5019 tr.close()
5025 tr.close()
5020 finally:
5026 finally:
5021 if tr is not None:
5027 if tr is not None:
5022 tr.release()
5028 tr.release()
5023 lock.release()
5029 lock.release()
5024 getphase = unfi._phasecache.phase
5030 getphase = unfi._phasecache.phase
5025 newdata = [getphase(unfi, r) for r in unfi]
5031 newdata = [getphase(unfi, r) for r in unfi]
5026 changes = sum(newdata[r] != olddata[r] for r in unfi)
5032 changes = sum(newdata[r] != olddata[r] for r in unfi)
5027 cl = unfi.changelog
5033 cl = unfi.changelog
5028 rejected = [n for n in nodes
5034 rejected = [n for n in nodes
5029 if newdata[cl.rev(n)] < targetphase]
5035 if newdata[cl.rev(n)] < targetphase]
5030 if rejected:
5036 if rejected:
5031 ui.warn(_('cannot move %i changesets to a higher '
5037 ui.warn(_('cannot move %i changesets to a higher '
5032 'phase, use --force\n') % len(rejected))
5038 'phase, use --force\n') % len(rejected))
5033 ret = 1
5039 ret = 1
5034 if changes:
5040 if changes:
5035 msg = _('phase changed for %i changesets\n') % changes
5041 msg = _('phase changed for %i changesets\n') % changes
5036 if ret:
5042 if ret:
5037 ui.status(msg)
5043 ui.status(msg)
5038 else:
5044 else:
5039 ui.note(msg)
5045 ui.note(msg)
5040 else:
5046 else:
5041 ui.warn(_('no phases changed\n'))
5047 ui.warn(_('no phases changed\n'))
5042 ret = 1
5048 ret = 1
5043 return ret
5049 return ret
5044
5050
5045 def postincoming(ui, repo, modheads, optupdate, checkout):
5051 def postincoming(ui, repo, modheads, optupdate, checkout):
5046 if modheads == 0:
5052 if modheads == 0:
5047 return
5053 return
5048 if optupdate:
5054 if optupdate:
5049 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5055 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
5050 try:
5056 try:
5051 ret = hg.update(repo, checkout)
5057 ret = hg.update(repo, checkout)
5052 except util.Abort, inst:
5058 except util.Abort, inst:
5053 ui.warn(_("not updating: %s\n") % str(inst))
5059 ui.warn(_("not updating: %s\n") % str(inst))
5054 if inst.hint:
5060 if inst.hint:
5055 ui.warn(_("(%s)\n") % inst.hint)
5061 ui.warn(_("(%s)\n") % inst.hint)
5056 return 0
5062 return 0
5057 if not ret and not checkout:
5063 if not ret and not checkout:
5058 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5064 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5059 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5065 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5060 return ret
5066 return ret
5061 if modheads > 1:
5067 if modheads > 1:
5062 currentbranchheads = len(repo.branchheads())
5068 currentbranchheads = len(repo.branchheads())
5063 if currentbranchheads == modheads:
5069 if currentbranchheads == modheads:
5064 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5070 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5065 elif currentbranchheads > 1:
5071 elif currentbranchheads > 1:
5066 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5072 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5067 "merge)\n"))
5073 "merge)\n"))
5068 else:
5074 else:
5069 ui.status(_("(run 'hg heads' to see heads)\n"))
5075 ui.status(_("(run 'hg heads' to see heads)\n"))
5070 else:
5076 else:
5071 ui.status(_("(run 'hg update' to get a working copy)\n"))
5077 ui.status(_("(run 'hg update' to get a working copy)\n"))
5072
5078
5073 @command('^pull',
5079 @command('^pull',
5074 [('u', 'update', None,
5080 [('u', 'update', None,
5075 _('update to new branch head if changesets were pulled')),
5081 _('update to new branch head if changesets were pulled')),
5076 ('f', 'force', None, _('run even when remote repository is unrelated')),
5082 ('f', 'force', None, _('run even when remote repository is unrelated')),
5077 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5083 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5078 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5084 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5079 ('b', 'branch', [], _('a specific branch you would like to pull'),
5085 ('b', 'branch', [], _('a specific branch you would like to pull'),
5080 _('BRANCH')),
5086 _('BRANCH')),
5081 ] + remoteopts,
5087 ] + remoteopts,
5082 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5088 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5083 def pull(ui, repo, source="default", **opts):
5089 def pull(ui, repo, source="default", **opts):
5084 """pull changes from the specified source
5090 """pull changes from the specified source
5085
5091
5086 Pull changes from a remote repository to a local one.
5092 Pull changes from a remote repository to a local one.
5087
5093
5088 This finds all changes from the repository at the specified path
5094 This finds all changes from the repository at the specified path
5089 or URL and adds them to a local repository (the current one unless
5095 or URL and adds them to a local repository (the current one unless
5090 -R is specified). By default, this does not update the copy of the
5096 -R is specified). By default, this does not update the copy of the
5091 project in the working directory.
5097 project in the working directory.
5092
5098
5093 Use :hg:`incoming` if you want to see what would have been added
5099 Use :hg:`incoming` if you want to see what would have been added
5094 by a pull at the time you issued this command. If you then decide
5100 by a pull at the time you issued this command. If you then decide
5095 to add those changes to the repository, you should use :hg:`pull
5101 to add those changes to the repository, you should use :hg:`pull
5096 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5102 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5097
5103
5098 If SOURCE is omitted, the 'default' path will be used.
5104 If SOURCE is omitted, the 'default' path will be used.
5099 See :hg:`help urls` for more information.
5105 See :hg:`help urls` for more information.
5100
5106
5101 Returns 0 on success, 1 if an update had unresolved files.
5107 Returns 0 on success, 1 if an update had unresolved files.
5102 """
5108 """
5103 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5109 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5104 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5110 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5105 other = hg.peer(repo, opts, source)
5111 other = hg.peer(repo, opts, source)
5106 try:
5112 try:
5107 revs, checkout = hg.addbranchrevs(repo, other, branches,
5113 revs, checkout = hg.addbranchrevs(repo, other, branches,
5108 opts.get('rev'))
5114 opts.get('rev'))
5109
5115
5110 remotebookmarks = other.listkeys('bookmarks')
5116 remotebookmarks = other.listkeys('bookmarks')
5111
5117
5112 if opts.get('bookmark'):
5118 if opts.get('bookmark'):
5113 if not revs:
5119 if not revs:
5114 revs = []
5120 revs = []
5115 for b in opts['bookmark']:
5121 for b in opts['bookmark']:
5116 if b not in remotebookmarks:
5122 if b not in remotebookmarks:
5117 raise util.Abort(_('remote bookmark %s not found!') % b)
5123 raise util.Abort(_('remote bookmark %s not found!') % b)
5118 revs.append(remotebookmarks[b])
5124 revs.append(remotebookmarks[b])
5119
5125
5120 if revs:
5126 if revs:
5121 try:
5127 try:
5122 revs = [other.lookup(rev) for rev in revs]
5128 revs = [other.lookup(rev) for rev in revs]
5123 except error.CapabilityError:
5129 except error.CapabilityError:
5124 err = _("other repository doesn't support revision lookup, "
5130 err = _("other repository doesn't support revision lookup, "
5125 "so a rev cannot be specified.")
5131 "so a rev cannot be specified.")
5126 raise util.Abort(err)
5132 raise util.Abort(err)
5127
5133
5128 modheads = exchange.pull(repo, other, heads=revs,
5134 modheads = exchange.pull(repo, other, heads=revs,
5129 force=opts.get('force'),
5135 force=opts.get('force'),
5130 bookmarks=opts.get('bookmark', ())).cgresult
5136 bookmarks=opts.get('bookmark', ())).cgresult
5131 if checkout:
5137 if checkout:
5132 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5138 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5133 repo._subtoppath = source
5139 repo._subtoppath = source
5134 try:
5140 try:
5135 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5141 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5136
5142
5137 finally:
5143 finally:
5138 del repo._subtoppath
5144 del repo._subtoppath
5139
5145
5140 finally:
5146 finally:
5141 other.close()
5147 other.close()
5142 return ret
5148 return ret
5143
5149
5144 @command('^push',
5150 @command('^push',
5145 [('f', 'force', None, _('force push')),
5151 [('f', 'force', None, _('force push')),
5146 ('r', 'rev', [],
5152 ('r', 'rev', [],
5147 _('a changeset intended to be included in the destination'),
5153 _('a changeset intended to be included in the destination'),
5148 _('REV')),
5154 _('REV')),
5149 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5155 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5150 ('b', 'branch', [],
5156 ('b', 'branch', [],
5151 _('a specific branch you would like to push'), _('BRANCH')),
5157 _('a specific branch you would like to push'), _('BRANCH')),
5152 ('', 'new-branch', False, _('allow pushing a new branch')),
5158 ('', 'new-branch', False, _('allow pushing a new branch')),
5153 ] + remoteopts,
5159 ] + remoteopts,
5154 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5160 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5155 def push(ui, repo, dest=None, **opts):
5161 def push(ui, repo, dest=None, **opts):
5156 """push changes to the specified destination
5162 """push changes to the specified destination
5157
5163
5158 Push changesets from the local repository to the specified
5164 Push changesets from the local repository to the specified
5159 destination.
5165 destination.
5160
5166
5161 This operation is symmetrical to pull: it is identical to a pull
5167 This operation is symmetrical to pull: it is identical to a pull
5162 in the destination repository from the current one.
5168 in the destination repository from the current one.
5163
5169
5164 By default, push will not allow creation of new heads at the
5170 By default, push will not allow creation of new heads at the
5165 destination, since multiple heads would make it unclear which head
5171 destination, since multiple heads would make it unclear which head
5166 to use. In this situation, it is recommended to pull and merge
5172 to use. In this situation, it is recommended to pull and merge
5167 before pushing.
5173 before pushing.
5168
5174
5169 Use --new-branch if you want to allow push to create a new named
5175 Use --new-branch if you want to allow push to create a new named
5170 branch that is not present at the destination. This allows you to
5176 branch that is not present at the destination. This allows you to
5171 only create a new branch without forcing other changes.
5177 only create a new branch without forcing other changes.
5172
5178
5173 .. note::
5179 .. note::
5174
5180
5175 Extra care should be taken with the -f/--force option,
5181 Extra care should be taken with the -f/--force option,
5176 which will push all new heads on all branches, an action which will
5182 which will push all new heads on all branches, an action which will
5177 almost always cause confusion for collaborators.
5183 almost always cause confusion for collaborators.
5178
5184
5179 If -r/--rev is used, the specified revision and all its ancestors
5185 If -r/--rev is used, the specified revision and all its ancestors
5180 will be pushed to the remote repository.
5186 will be pushed to the remote repository.
5181
5187
5182 If -B/--bookmark is used, the specified bookmarked revision, its
5188 If -B/--bookmark is used, the specified bookmarked revision, its
5183 ancestors, and the bookmark will be pushed to the remote
5189 ancestors, and the bookmark will be pushed to the remote
5184 repository.
5190 repository.
5185
5191
5186 Please see :hg:`help urls` for important details about ``ssh://``
5192 Please see :hg:`help urls` for important details about ``ssh://``
5187 URLs. If DESTINATION is omitted, a default path will be used.
5193 URLs. If DESTINATION is omitted, a default path will be used.
5188
5194
5189 Returns 0 if push was successful, 1 if nothing to push.
5195 Returns 0 if push was successful, 1 if nothing to push.
5190 """
5196 """
5191
5197
5192 if opts.get('bookmark'):
5198 if opts.get('bookmark'):
5193 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5199 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5194 for b in opts['bookmark']:
5200 for b in opts['bookmark']:
5195 # translate -B options to -r so changesets get pushed
5201 # translate -B options to -r so changesets get pushed
5196 if b in repo._bookmarks:
5202 if b in repo._bookmarks:
5197 opts.setdefault('rev', []).append(b)
5203 opts.setdefault('rev', []).append(b)
5198 else:
5204 else:
5199 # if we try to push a deleted bookmark, translate it to null
5205 # if we try to push a deleted bookmark, translate it to null
5200 # this lets simultaneous -r, -b options continue working
5206 # this lets simultaneous -r, -b options continue working
5201 opts.setdefault('rev', []).append("null")
5207 opts.setdefault('rev', []).append("null")
5202
5208
5203 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5209 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5204 dest, branches = hg.parseurl(dest, opts.get('branch'))
5210 dest, branches = hg.parseurl(dest, opts.get('branch'))
5205 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5211 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5206 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5212 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5207 try:
5213 try:
5208 other = hg.peer(repo, opts, dest)
5214 other = hg.peer(repo, opts, dest)
5209 except error.RepoError:
5215 except error.RepoError:
5210 if dest == "default-push":
5216 if dest == "default-push":
5211 raise util.Abort(_("default repository not configured!"),
5217 raise util.Abort(_("default repository not configured!"),
5212 hint=_('see the "path" section in "hg help config"'))
5218 hint=_('see the "path" section in "hg help config"'))
5213 else:
5219 else:
5214 raise
5220 raise
5215
5221
5216 if revs:
5222 if revs:
5217 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5223 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5218 if not revs:
5224 if not revs:
5219 raise util.Abort(_("specified revisions evaluate to an empty set"),
5225 raise util.Abort(_("specified revisions evaluate to an empty set"),
5220 hint=_("use different revision arguments"))
5226 hint=_("use different revision arguments"))
5221
5227
5222 repo._subtoppath = dest
5228 repo._subtoppath = dest
5223 try:
5229 try:
5224 # push subrepos depth-first for coherent ordering
5230 # push subrepos depth-first for coherent ordering
5225 c = repo['']
5231 c = repo['']
5226 subs = c.substate # only repos that are committed
5232 subs = c.substate # only repos that are committed
5227 for s in sorted(subs):
5233 for s in sorted(subs):
5228 result = c.sub(s).push(opts)
5234 result = c.sub(s).push(opts)
5229 if result == 0:
5235 if result == 0:
5230 return not result
5236 return not result
5231 finally:
5237 finally:
5232 del repo._subtoppath
5238 del repo._subtoppath
5233 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5239 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5234 newbranch=opts.get('new_branch'),
5240 newbranch=opts.get('new_branch'),
5235 bookmarks=opts.get('bookmark', ()))
5241 bookmarks=opts.get('bookmark', ()))
5236
5242
5237 result = not pushop.cgresult
5243 result = not pushop.cgresult
5238
5244
5239 if pushop.bkresult is not None:
5245 if pushop.bkresult is not None:
5240 if pushop.bkresult == 2:
5246 if pushop.bkresult == 2:
5241 result = 2
5247 result = 2
5242 elif not result and pushop.bkresult:
5248 elif not result and pushop.bkresult:
5243 result = 2
5249 result = 2
5244
5250
5245 return result
5251 return result
5246
5252
5247 @command('recover', [])
5253 @command('recover', [])
5248 def recover(ui, repo):
5254 def recover(ui, repo):
5249 """roll back an interrupted transaction
5255 """roll back an interrupted transaction
5250
5256
5251 Recover from an interrupted commit or pull.
5257 Recover from an interrupted commit or pull.
5252
5258
5253 This command tries to fix the repository status after an
5259 This command tries to fix the repository status after an
5254 interrupted operation. It should only be necessary when Mercurial
5260 interrupted operation. It should only be necessary when Mercurial
5255 suggests it.
5261 suggests it.
5256
5262
5257 Returns 0 if successful, 1 if nothing to recover or verify fails.
5263 Returns 0 if successful, 1 if nothing to recover or verify fails.
5258 """
5264 """
5259 if repo.recover():
5265 if repo.recover():
5260 return hg.verify(repo)
5266 return hg.verify(repo)
5261 return 1
5267 return 1
5262
5268
5263 @command('^remove|rm',
5269 @command('^remove|rm',
5264 [('A', 'after', None, _('record delete for missing files')),
5270 [('A', 'after', None, _('record delete for missing files')),
5265 ('f', 'force', None,
5271 ('f', 'force', None,
5266 _('remove (and delete) file even if added or modified')),
5272 _('remove (and delete) file even if added or modified')),
5267 ] + subrepoopts + walkopts,
5273 ] + subrepoopts + walkopts,
5268 _('[OPTION]... FILE...'),
5274 _('[OPTION]... FILE...'),
5269 inferrepo=True)
5275 inferrepo=True)
5270 def remove(ui, repo, *pats, **opts):
5276 def remove(ui, repo, *pats, **opts):
5271 """remove the specified files on the next commit
5277 """remove the specified files on the next commit
5272
5278
5273 Schedule the indicated files for removal from the current branch.
5279 Schedule the indicated files for removal from the current branch.
5274
5280
5275 This command schedules the files to be removed at the next commit.
5281 This command schedules the files to be removed at the next commit.
5276 To undo a remove before that, see :hg:`revert`. To undo added
5282 To undo a remove before that, see :hg:`revert`. To undo added
5277 files, see :hg:`forget`.
5283 files, see :hg:`forget`.
5278
5284
5279 .. container:: verbose
5285 .. container:: verbose
5280
5286
5281 -A/--after can be used to remove only files that have already
5287 -A/--after can be used to remove only files that have already
5282 been deleted, -f/--force can be used to force deletion, and -Af
5288 been deleted, -f/--force can be used to force deletion, and -Af
5283 can be used to remove files from the next revision without
5289 can be used to remove files from the next revision without
5284 deleting them from the working directory.
5290 deleting them from the working directory.
5285
5291
5286 The following table details the behavior of remove for different
5292 The following table details the behavior of remove for different
5287 file states (columns) and option combinations (rows). The file
5293 file states (columns) and option combinations (rows). The file
5288 states are Added [A], Clean [C], Modified [M] and Missing [!]
5294 states are Added [A], Clean [C], Modified [M] and Missing [!]
5289 (as reported by :hg:`status`). The actions are Warn, Remove
5295 (as reported by :hg:`status`). The actions are Warn, Remove
5290 (from branch) and Delete (from disk):
5296 (from branch) and Delete (from disk):
5291
5297
5292 ========= == == == ==
5298 ========= == == == ==
5293 opt/state A C M !
5299 opt/state A C M !
5294 ========= == == == ==
5300 ========= == == == ==
5295 none W RD W R
5301 none W RD W R
5296 -f R RD RD R
5302 -f R RD RD R
5297 -A W W W R
5303 -A W W W R
5298 -Af R R R R
5304 -Af R R R R
5299 ========= == == == ==
5305 ========= == == == ==
5300
5306
5301 Note that remove never deletes files in Added [A] state from the
5307 Note that remove never deletes files in Added [A] state from the
5302 working directory, not even if option --force is specified.
5308 working directory, not even if option --force is specified.
5303
5309
5304 Returns 0 on success, 1 if any warnings encountered.
5310 Returns 0 on success, 1 if any warnings encountered.
5305 """
5311 """
5306
5312
5307 after, force = opts.get('after'), opts.get('force')
5313 after, force = opts.get('after'), opts.get('force')
5308 if not pats and not after:
5314 if not pats and not after:
5309 raise util.Abort(_('no files specified'))
5315 raise util.Abort(_('no files specified'))
5310
5316
5311 m = scmutil.match(repo[None], pats, opts)
5317 m = scmutil.match(repo[None], pats, opts)
5312 subrepos = opts.get('subrepos')
5318 subrepos = opts.get('subrepos')
5313 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5319 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5314
5320
5315 @command('rename|move|mv',
5321 @command('rename|move|mv',
5316 [('A', 'after', None, _('record a rename that has already occurred')),
5322 [('A', 'after', None, _('record a rename that has already occurred')),
5317 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5323 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5318 ] + walkopts + dryrunopts,
5324 ] + walkopts + dryrunopts,
5319 _('[OPTION]... SOURCE... DEST'))
5325 _('[OPTION]... SOURCE... DEST'))
5320 def rename(ui, repo, *pats, **opts):
5326 def rename(ui, repo, *pats, **opts):
5321 """rename files; equivalent of copy + remove
5327 """rename files; equivalent of copy + remove
5322
5328
5323 Mark dest as copies of sources; mark sources for deletion. If dest
5329 Mark dest as copies of sources; mark sources for deletion. If dest
5324 is a directory, copies are put in that directory. If dest is a
5330 is a directory, copies are put in that directory. If dest is a
5325 file, there can only be one source.
5331 file, there can only be one source.
5326
5332
5327 By default, this command copies the contents of files as they
5333 By default, this command copies the contents of files as they
5328 exist in the working directory. If invoked with -A/--after, the
5334 exist in the working directory. If invoked with -A/--after, the
5329 operation is recorded, but no copying is performed.
5335 operation is recorded, but no copying is performed.
5330
5336
5331 This command takes effect at the next commit. To undo a rename
5337 This command takes effect at the next commit. To undo a rename
5332 before that, see :hg:`revert`.
5338 before that, see :hg:`revert`.
5333
5339
5334 Returns 0 on success, 1 if errors are encountered.
5340 Returns 0 on success, 1 if errors are encountered.
5335 """
5341 """
5336 wlock = repo.wlock(False)
5342 wlock = repo.wlock(False)
5337 try:
5343 try:
5338 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5344 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5339 finally:
5345 finally:
5340 wlock.release()
5346 wlock.release()
5341
5347
5342 @command('resolve',
5348 @command('resolve',
5343 [('a', 'all', None, _('select all unresolved files')),
5349 [('a', 'all', None, _('select all unresolved files')),
5344 ('l', 'list', None, _('list state of files needing merge')),
5350 ('l', 'list', None, _('list state of files needing merge')),
5345 ('m', 'mark', None, _('mark files as resolved')),
5351 ('m', 'mark', None, _('mark files as resolved')),
5346 ('u', 'unmark', None, _('mark files as unresolved')),
5352 ('u', 'unmark', None, _('mark files as unresolved')),
5347 ('n', 'no-status', None, _('hide status prefix'))]
5353 ('n', 'no-status', None, _('hide status prefix'))]
5348 + mergetoolopts + walkopts + formatteropts,
5354 + mergetoolopts + walkopts + formatteropts,
5349 _('[OPTION]... [FILE]...'),
5355 _('[OPTION]... [FILE]...'),
5350 inferrepo=True)
5356 inferrepo=True)
5351 def resolve(ui, repo, *pats, **opts):
5357 def resolve(ui, repo, *pats, **opts):
5352 """redo merges or set/view the merge status of files
5358 """redo merges or set/view the merge status of files
5353
5359
5354 Merges with unresolved conflicts are often the result of
5360 Merges with unresolved conflicts are often the result of
5355 non-interactive merging using the ``internal:merge`` configuration
5361 non-interactive merging using the ``internal:merge`` configuration
5356 setting, or a command-line merge tool like ``diff3``. The resolve
5362 setting, or a command-line merge tool like ``diff3``. The resolve
5357 command is used to manage the files involved in a merge, after
5363 command is used to manage the files involved in a merge, after
5358 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5364 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5359 working directory must have two parents). See :hg:`help
5365 working directory must have two parents). See :hg:`help
5360 merge-tools` for information on configuring merge tools.
5366 merge-tools` for information on configuring merge tools.
5361
5367
5362 The resolve command can be used in the following ways:
5368 The resolve command can be used in the following ways:
5363
5369
5364 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5370 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5365 files, discarding any previous merge attempts. Re-merging is not
5371 files, discarding any previous merge attempts. Re-merging is not
5366 performed for files already marked as resolved. Use ``--all/-a``
5372 performed for files already marked as resolved. Use ``--all/-a``
5367 to select all unresolved files. ``--tool`` can be used to specify
5373 to select all unresolved files. ``--tool`` can be used to specify
5368 the merge tool used for the given files. It overrides the HGMERGE
5374 the merge tool used for the given files. It overrides the HGMERGE
5369 environment variable and your configuration files. Previous file
5375 environment variable and your configuration files. Previous file
5370 contents are saved with a ``.orig`` suffix.
5376 contents are saved with a ``.orig`` suffix.
5371
5377
5372 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5378 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5373 (e.g. after having manually fixed-up the files). The default is
5379 (e.g. after having manually fixed-up the files). The default is
5374 to mark all unresolved files.
5380 to mark all unresolved files.
5375
5381
5376 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5382 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5377 default is to mark all resolved files.
5383 default is to mark all resolved files.
5378
5384
5379 - :hg:`resolve -l`: list files which had or still have conflicts.
5385 - :hg:`resolve -l`: list files which had or still have conflicts.
5380 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5386 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5381
5387
5382 Note that Mercurial will not let you commit files with unresolved
5388 Note that Mercurial will not let you commit files with unresolved
5383 merge conflicts. You must use :hg:`resolve -m ...` before you can
5389 merge conflicts. You must use :hg:`resolve -m ...` before you can
5384 commit after a conflicting merge.
5390 commit after a conflicting merge.
5385
5391
5386 Returns 0 on success, 1 if any files fail a resolve attempt.
5392 Returns 0 on success, 1 if any files fail a resolve attempt.
5387 """
5393 """
5388
5394
5389 all, mark, unmark, show, nostatus = \
5395 all, mark, unmark, show, nostatus = \
5390 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5396 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5391
5397
5392 if (show and (mark or unmark)) or (mark and unmark):
5398 if (show and (mark or unmark)) or (mark and unmark):
5393 raise util.Abort(_("too many options specified"))
5399 raise util.Abort(_("too many options specified"))
5394 if pats and all:
5400 if pats and all:
5395 raise util.Abort(_("can't specify --all and patterns"))
5401 raise util.Abort(_("can't specify --all and patterns"))
5396 if not (all or pats or show or mark or unmark):
5402 if not (all or pats or show or mark or unmark):
5397 raise util.Abort(_('no files or directories specified'),
5403 raise util.Abort(_('no files or directories specified'),
5398 hint=('use --all to remerge all files'))
5404 hint=('use --all to remerge all files'))
5399
5405
5400 if show:
5406 if show:
5401 fm = ui.formatter('resolve', opts)
5407 fm = ui.formatter('resolve', opts)
5402 ms = mergemod.mergestate(repo)
5408 ms = mergemod.mergestate(repo)
5403 m = scmutil.match(repo[None], pats, opts)
5409 m = scmutil.match(repo[None], pats, opts)
5404 for f in ms:
5410 for f in ms:
5405 if not m(f):
5411 if not m(f):
5406 continue
5412 continue
5407 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5413 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5408 fm.startitem()
5414 fm.startitem()
5409 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5415 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5410 fm.write('path', '%s\n', f, label=l)
5416 fm.write('path', '%s\n', f, label=l)
5411 fm.end()
5417 fm.end()
5412 return 0
5418 return 0
5413
5419
5414 wlock = repo.wlock()
5420 wlock = repo.wlock()
5415 try:
5421 try:
5416 ms = mergemod.mergestate(repo)
5422 ms = mergemod.mergestate(repo)
5417
5423
5418 if not (ms.active() or repo.dirstate.p2() != nullid):
5424 if not (ms.active() or repo.dirstate.p2() != nullid):
5419 raise util.Abort(
5425 raise util.Abort(
5420 _('resolve command not applicable when not merging'))
5426 _('resolve command not applicable when not merging'))
5421
5427
5422 m = scmutil.match(repo[None], pats, opts)
5428 m = scmutil.match(repo[None], pats, opts)
5423 ret = 0
5429 ret = 0
5424 didwork = False
5430 didwork = False
5425
5431
5426 for f in ms:
5432 for f in ms:
5427 if not m(f):
5433 if not m(f):
5428 continue
5434 continue
5429
5435
5430 didwork = True
5436 didwork = True
5431
5437
5432 if mark:
5438 if mark:
5433 ms.mark(f, "r")
5439 ms.mark(f, "r")
5434 elif unmark:
5440 elif unmark:
5435 ms.mark(f, "u")
5441 ms.mark(f, "u")
5436 else:
5442 else:
5437 wctx = repo[None]
5443 wctx = repo[None]
5438
5444
5439 # backup pre-resolve (merge uses .orig for its own purposes)
5445 # backup pre-resolve (merge uses .orig for its own purposes)
5440 a = repo.wjoin(f)
5446 a = repo.wjoin(f)
5441 util.copyfile(a, a + ".resolve")
5447 util.copyfile(a, a + ".resolve")
5442
5448
5443 try:
5449 try:
5444 # resolve file
5450 # resolve file
5445 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5451 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5446 'resolve')
5452 'resolve')
5447 if ms.resolve(f, wctx):
5453 if ms.resolve(f, wctx):
5448 ret = 1
5454 ret = 1
5449 finally:
5455 finally:
5450 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5456 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5451 ms.commit()
5457 ms.commit()
5452
5458
5453 # replace filemerge's .orig file with our resolve file
5459 # replace filemerge's .orig file with our resolve file
5454 util.rename(a + ".resolve", a + ".orig")
5460 util.rename(a + ".resolve", a + ".orig")
5455
5461
5456 ms.commit()
5462 ms.commit()
5457
5463
5458 if not didwork and pats:
5464 if not didwork and pats:
5459 ui.warn(_("arguments do not match paths that need resolving\n"))
5465 ui.warn(_("arguments do not match paths that need resolving\n"))
5460
5466
5461 finally:
5467 finally:
5462 wlock.release()
5468 wlock.release()
5463
5469
5464 # Nudge users into finishing an unfinished operation
5470 # Nudge users into finishing an unfinished operation
5465 if not list(ms.unresolved()):
5471 if not list(ms.unresolved()):
5466 ui.status(_('(no more unresolved files)\n'))
5472 ui.status(_('(no more unresolved files)\n'))
5467
5473
5468 return ret
5474 return ret
5469
5475
5470 @command('revert',
5476 @command('revert',
5471 [('a', 'all', None, _('revert all changes when no arguments given')),
5477 [('a', 'all', None, _('revert all changes when no arguments given')),
5472 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5478 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5473 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5479 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5474 ('C', 'no-backup', None, _('do not save backup copies of files')),
5480 ('C', 'no-backup', None, _('do not save backup copies of files')),
5475 ('i', 'interactive', None,
5481 ('i', 'interactive', None,
5476 _('interactively select the changes (EXPERIMENTAL)')),
5482 _('interactively select the changes (EXPERIMENTAL)')),
5477 ] + walkopts + dryrunopts,
5483 ] + walkopts + dryrunopts,
5478 _('[OPTION]... [-r REV] [NAME]...'))
5484 _('[OPTION]... [-r REV] [NAME]...'))
5479 def revert(ui, repo, *pats, **opts):
5485 def revert(ui, repo, *pats, **opts):
5480 """restore files to their checkout state
5486 """restore files to their checkout state
5481
5487
5482 .. note::
5488 .. note::
5483
5489
5484 To check out earlier revisions, you should use :hg:`update REV`.
5490 To check out earlier revisions, you should use :hg:`update REV`.
5485 To cancel an uncommitted merge (and lose your changes),
5491 To cancel an uncommitted merge (and lose your changes),
5486 use :hg:`update --clean .`.
5492 use :hg:`update --clean .`.
5487
5493
5488 With no revision specified, revert the specified files or directories
5494 With no revision specified, revert the specified files or directories
5489 to the contents they had in the parent of the working directory.
5495 to the contents they had in the parent of the working directory.
5490 This restores the contents of files to an unmodified
5496 This restores the contents of files to an unmodified
5491 state and unschedules adds, removes, copies, and renames. If the
5497 state and unschedules adds, removes, copies, and renames. If the
5492 working directory has two parents, you must explicitly specify a
5498 working directory has two parents, you must explicitly specify a
5493 revision.
5499 revision.
5494
5500
5495 Using the -r/--rev or -d/--date options, revert the given files or
5501 Using the -r/--rev or -d/--date options, revert the given files or
5496 directories to their states as of a specific revision. Because
5502 directories to their states as of a specific revision. Because
5497 revert does not change the working directory parents, this will
5503 revert does not change the working directory parents, this will
5498 cause these files to appear modified. This can be helpful to "back
5504 cause these files to appear modified. This can be helpful to "back
5499 out" some or all of an earlier change. See :hg:`backout` for a
5505 out" some or all of an earlier change. See :hg:`backout` for a
5500 related method.
5506 related method.
5501
5507
5502 Modified files are saved with a .orig suffix before reverting.
5508 Modified files are saved with a .orig suffix before reverting.
5503 To disable these backups, use --no-backup.
5509 To disable these backups, use --no-backup.
5504
5510
5505 See :hg:`help dates` for a list of formats valid for -d/--date.
5511 See :hg:`help dates` for a list of formats valid for -d/--date.
5506
5512
5507 Returns 0 on success.
5513 Returns 0 on success.
5508 """
5514 """
5509
5515
5510 if opts.get("date"):
5516 if opts.get("date"):
5511 if opts.get("rev"):
5517 if opts.get("rev"):
5512 raise util.Abort(_("you can't specify a revision and a date"))
5518 raise util.Abort(_("you can't specify a revision and a date"))
5513 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5519 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5514
5520
5515 parent, p2 = repo.dirstate.parents()
5521 parent, p2 = repo.dirstate.parents()
5516 if not opts.get('rev') and p2 != nullid:
5522 if not opts.get('rev') and p2 != nullid:
5517 # revert after merge is a trap for new users (issue2915)
5523 # revert after merge is a trap for new users (issue2915)
5518 raise util.Abort(_('uncommitted merge with no revision specified'),
5524 raise util.Abort(_('uncommitted merge with no revision specified'),
5519 hint=_('use "hg update" or see "hg help revert"'))
5525 hint=_('use "hg update" or see "hg help revert"'))
5520
5526
5521 ctx = scmutil.revsingle(repo, opts.get('rev'))
5527 ctx = scmutil.revsingle(repo, opts.get('rev'))
5522
5528
5523 if (not (pats or opts.get('include') or opts.get('exclude') or
5529 if (not (pats or opts.get('include') or opts.get('exclude') or
5524 opts.get('all') or opts.get('interactive'))):
5530 opts.get('all') or opts.get('interactive'))):
5525 msg = _("no files or directories specified")
5531 msg = _("no files or directories specified")
5526 if p2 != nullid:
5532 if p2 != nullid:
5527 hint = _("uncommitted merge, use --all to discard all changes,"
5533 hint = _("uncommitted merge, use --all to discard all changes,"
5528 " or 'hg update -C .' to abort the merge")
5534 " or 'hg update -C .' to abort the merge")
5529 raise util.Abort(msg, hint=hint)
5535 raise util.Abort(msg, hint=hint)
5530 dirty = any(repo.status())
5536 dirty = any(repo.status())
5531 node = ctx.node()
5537 node = ctx.node()
5532 if node != parent:
5538 if node != parent:
5533 if dirty:
5539 if dirty:
5534 hint = _("uncommitted changes, use --all to discard all"
5540 hint = _("uncommitted changes, use --all to discard all"
5535 " changes, or 'hg update %s' to update") % ctx.rev()
5541 " changes, or 'hg update %s' to update") % ctx.rev()
5536 else:
5542 else:
5537 hint = _("use --all to revert all files,"
5543 hint = _("use --all to revert all files,"
5538 " or 'hg update %s' to update") % ctx.rev()
5544 " or 'hg update %s' to update") % ctx.rev()
5539 elif dirty:
5545 elif dirty:
5540 hint = _("uncommitted changes, use --all to discard all changes")
5546 hint = _("uncommitted changes, use --all to discard all changes")
5541 else:
5547 else:
5542 hint = _("use --all to revert all files")
5548 hint = _("use --all to revert all files")
5543 raise util.Abort(msg, hint=hint)
5549 raise util.Abort(msg, hint=hint)
5544
5550
5545 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5551 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5546
5552
5547 @command('rollback', dryrunopts +
5553 @command('rollback', dryrunopts +
5548 [('f', 'force', False, _('ignore safety measures'))])
5554 [('f', 'force', False, _('ignore safety measures'))])
5549 def rollback(ui, repo, **opts):
5555 def rollback(ui, repo, **opts):
5550 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5556 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5551
5557
5552 Please use :hg:`commit --amend` instead of rollback to correct
5558 Please use :hg:`commit --amend` instead of rollback to correct
5553 mistakes in the last commit.
5559 mistakes in the last commit.
5554
5560
5555 This command should be used with care. There is only one level of
5561 This command should be used with care. There is only one level of
5556 rollback, and there is no way to undo a rollback. It will also
5562 rollback, and there is no way to undo a rollback. It will also
5557 restore the dirstate at the time of the last transaction, losing
5563 restore the dirstate at the time of the last transaction, losing
5558 any dirstate changes since that time. This command does not alter
5564 any dirstate changes since that time. This command does not alter
5559 the working directory.
5565 the working directory.
5560
5566
5561 Transactions are used to encapsulate the effects of all commands
5567 Transactions are used to encapsulate the effects of all commands
5562 that create new changesets or propagate existing changesets into a
5568 that create new changesets or propagate existing changesets into a
5563 repository.
5569 repository.
5564
5570
5565 .. container:: verbose
5571 .. container:: verbose
5566
5572
5567 For example, the following commands are transactional, and their
5573 For example, the following commands are transactional, and their
5568 effects can be rolled back:
5574 effects can be rolled back:
5569
5575
5570 - commit
5576 - commit
5571 - import
5577 - import
5572 - pull
5578 - pull
5573 - push (with this repository as the destination)
5579 - push (with this repository as the destination)
5574 - unbundle
5580 - unbundle
5575
5581
5576 To avoid permanent data loss, rollback will refuse to rollback a
5582 To avoid permanent data loss, rollback will refuse to rollback a
5577 commit transaction if it isn't checked out. Use --force to
5583 commit transaction if it isn't checked out. Use --force to
5578 override this protection.
5584 override this protection.
5579
5585
5580 This command is not intended for use on public repositories. Once
5586 This command is not intended for use on public repositories. Once
5581 changes are visible for pull by other users, rolling a transaction
5587 changes are visible for pull by other users, rolling a transaction
5582 back locally is ineffective (someone else may already have pulled
5588 back locally is ineffective (someone else may already have pulled
5583 the changes). Furthermore, a race is possible with readers of the
5589 the changes). Furthermore, a race is possible with readers of the
5584 repository; for example an in-progress pull from the repository
5590 repository; for example an in-progress pull from the repository
5585 may fail if a rollback is performed.
5591 may fail if a rollback is performed.
5586
5592
5587 Returns 0 on success, 1 if no rollback data is available.
5593 Returns 0 on success, 1 if no rollback data is available.
5588 """
5594 """
5589 return repo.rollback(dryrun=opts.get('dry_run'),
5595 return repo.rollback(dryrun=opts.get('dry_run'),
5590 force=opts.get('force'))
5596 force=opts.get('force'))
5591
5597
5592 @command('root', [])
5598 @command('root', [])
5593 def root(ui, repo):
5599 def root(ui, repo):
5594 """print the root (top) of the current working directory
5600 """print the root (top) of the current working directory
5595
5601
5596 Print the root directory of the current repository.
5602 Print the root directory of the current repository.
5597
5603
5598 Returns 0 on success.
5604 Returns 0 on success.
5599 """
5605 """
5600 ui.write(repo.root + "\n")
5606 ui.write(repo.root + "\n")
5601
5607
5602 @command('^serve',
5608 @command('^serve',
5603 [('A', 'accesslog', '', _('name of access log file to write to'),
5609 [('A', 'accesslog', '', _('name of access log file to write to'),
5604 _('FILE')),
5610 _('FILE')),
5605 ('d', 'daemon', None, _('run server in background')),
5611 ('d', 'daemon', None, _('run server in background')),
5606 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5612 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5607 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5613 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5608 # use string type, then we can check if something was passed
5614 # use string type, then we can check if something was passed
5609 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5615 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5610 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5616 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5611 _('ADDR')),
5617 _('ADDR')),
5612 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5618 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5613 _('PREFIX')),
5619 _('PREFIX')),
5614 ('n', 'name', '',
5620 ('n', 'name', '',
5615 _('name to show in web pages (default: working directory)'), _('NAME')),
5621 _('name to show in web pages (default: working directory)'), _('NAME')),
5616 ('', 'web-conf', '',
5622 ('', 'web-conf', '',
5617 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5623 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5618 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5624 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5619 _('FILE')),
5625 _('FILE')),
5620 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5626 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5621 ('', 'stdio', None, _('for remote clients')),
5627 ('', 'stdio', None, _('for remote clients')),
5622 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5628 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5623 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5629 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5624 ('', 'style', '', _('template style to use'), _('STYLE')),
5630 ('', 'style', '', _('template style to use'), _('STYLE')),
5625 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5631 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5626 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5632 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5627 _('[OPTION]...'),
5633 _('[OPTION]...'),
5628 optionalrepo=True)
5634 optionalrepo=True)
5629 def serve(ui, repo, **opts):
5635 def serve(ui, repo, **opts):
5630 """start stand-alone webserver
5636 """start stand-alone webserver
5631
5637
5632 Start a local HTTP repository browser and pull server. You can use
5638 Start a local HTTP repository browser and pull server. You can use
5633 this for ad-hoc sharing and browsing of repositories. It is
5639 this for ad-hoc sharing and browsing of repositories. It is
5634 recommended to use a real web server to serve a repository for
5640 recommended to use a real web server to serve a repository for
5635 longer periods of time.
5641 longer periods of time.
5636
5642
5637 Please note that the server does not implement access control.
5643 Please note that the server does not implement access control.
5638 This means that, by default, anybody can read from the server and
5644 This means that, by default, anybody can read from the server and
5639 nobody can write to it by default. Set the ``web.allow_push``
5645 nobody can write to it by default. Set the ``web.allow_push``
5640 option to ``*`` to allow everybody to push to the server. You
5646 option to ``*`` to allow everybody to push to the server. You
5641 should use a real web server if you need to authenticate users.
5647 should use a real web server if you need to authenticate users.
5642
5648
5643 By default, the server logs accesses to stdout and errors to
5649 By default, the server logs accesses to stdout and errors to
5644 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5650 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5645 files.
5651 files.
5646
5652
5647 To have the server choose a free port number to listen on, specify
5653 To have the server choose a free port number to listen on, specify
5648 a port number of 0; in this case, the server will print the port
5654 a port number of 0; in this case, the server will print the port
5649 number it uses.
5655 number it uses.
5650
5656
5651 Returns 0 on success.
5657 Returns 0 on success.
5652 """
5658 """
5653
5659
5654 if opts["stdio"] and opts["cmdserver"]:
5660 if opts["stdio"] and opts["cmdserver"]:
5655 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5661 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5656
5662
5657 if opts["stdio"]:
5663 if opts["stdio"]:
5658 if repo is None:
5664 if repo is None:
5659 raise error.RepoError(_("there is no Mercurial repository here"
5665 raise error.RepoError(_("there is no Mercurial repository here"
5660 " (.hg not found)"))
5666 " (.hg not found)"))
5661 s = sshserver.sshserver(ui, repo)
5667 s = sshserver.sshserver(ui, repo)
5662 s.serve_forever()
5668 s.serve_forever()
5663
5669
5664 if opts["cmdserver"]:
5670 if opts["cmdserver"]:
5665 service = commandserver.createservice(ui, repo, opts)
5671 service = commandserver.createservice(ui, repo, opts)
5666 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5672 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5667
5673
5668 # this way we can check if something was given in the command-line
5674 # this way we can check if something was given in the command-line
5669 if opts.get('port'):
5675 if opts.get('port'):
5670 opts['port'] = util.getport(opts.get('port'))
5676 opts['port'] = util.getport(opts.get('port'))
5671
5677
5672 if repo:
5678 if repo:
5673 baseui = repo.baseui
5679 baseui = repo.baseui
5674 else:
5680 else:
5675 baseui = ui
5681 baseui = ui
5676 optlist = ("name templates style address port prefix ipv6"
5682 optlist = ("name templates style address port prefix ipv6"
5677 " accesslog errorlog certificate encoding")
5683 " accesslog errorlog certificate encoding")
5678 for o in optlist.split():
5684 for o in optlist.split():
5679 val = opts.get(o, '')
5685 val = opts.get(o, '')
5680 if val in (None, ''): # should check against default options instead
5686 if val in (None, ''): # should check against default options instead
5681 continue
5687 continue
5682 baseui.setconfig("web", o, val, 'serve')
5688 baseui.setconfig("web", o, val, 'serve')
5683 if repo and repo.ui != baseui:
5689 if repo and repo.ui != baseui:
5684 repo.ui.setconfig("web", o, val, 'serve')
5690 repo.ui.setconfig("web", o, val, 'serve')
5685
5691
5686 o = opts.get('web_conf') or opts.get('webdir_conf')
5692 o = opts.get('web_conf') or opts.get('webdir_conf')
5687 if not o:
5693 if not o:
5688 if not repo:
5694 if not repo:
5689 raise error.RepoError(_("there is no Mercurial repository"
5695 raise error.RepoError(_("there is no Mercurial repository"
5690 " here (.hg not found)"))
5696 " here (.hg not found)"))
5691 o = repo
5697 o = repo
5692
5698
5693 app = hgweb.hgweb(o, baseui=baseui)
5699 app = hgweb.hgweb(o, baseui=baseui)
5694 service = httpservice(ui, app, opts)
5700 service = httpservice(ui, app, opts)
5695 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5701 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5696
5702
5697 class httpservice(object):
5703 class httpservice(object):
5698 def __init__(self, ui, app, opts):
5704 def __init__(self, ui, app, opts):
5699 self.ui = ui
5705 self.ui = ui
5700 self.app = app
5706 self.app = app
5701 self.opts = opts
5707 self.opts = opts
5702
5708
5703 def init(self):
5709 def init(self):
5704 util.setsignalhandler()
5710 util.setsignalhandler()
5705 self.httpd = hgweb_server.create_server(self.ui, self.app)
5711 self.httpd = hgweb_server.create_server(self.ui, self.app)
5706
5712
5707 if self.opts['port'] and not self.ui.verbose:
5713 if self.opts['port'] and not self.ui.verbose:
5708 return
5714 return
5709
5715
5710 if self.httpd.prefix:
5716 if self.httpd.prefix:
5711 prefix = self.httpd.prefix.strip('/') + '/'
5717 prefix = self.httpd.prefix.strip('/') + '/'
5712 else:
5718 else:
5713 prefix = ''
5719 prefix = ''
5714
5720
5715 port = ':%d' % self.httpd.port
5721 port = ':%d' % self.httpd.port
5716 if port == ':80':
5722 if port == ':80':
5717 port = ''
5723 port = ''
5718
5724
5719 bindaddr = self.httpd.addr
5725 bindaddr = self.httpd.addr
5720 if bindaddr == '0.0.0.0':
5726 if bindaddr == '0.0.0.0':
5721 bindaddr = '*'
5727 bindaddr = '*'
5722 elif ':' in bindaddr: # IPv6
5728 elif ':' in bindaddr: # IPv6
5723 bindaddr = '[%s]' % bindaddr
5729 bindaddr = '[%s]' % bindaddr
5724
5730
5725 fqaddr = self.httpd.fqaddr
5731 fqaddr = self.httpd.fqaddr
5726 if ':' in fqaddr:
5732 if ':' in fqaddr:
5727 fqaddr = '[%s]' % fqaddr
5733 fqaddr = '[%s]' % fqaddr
5728 if self.opts['port']:
5734 if self.opts['port']:
5729 write = self.ui.status
5735 write = self.ui.status
5730 else:
5736 else:
5731 write = self.ui.write
5737 write = self.ui.write
5732 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5738 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5733 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5739 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5734 self.ui.flush() # avoid buffering of status message
5740 self.ui.flush() # avoid buffering of status message
5735
5741
5736 def run(self):
5742 def run(self):
5737 self.httpd.serve_forever()
5743 self.httpd.serve_forever()
5738
5744
5739
5745
5740 @command('^status|st',
5746 @command('^status|st',
5741 [('A', 'all', None, _('show status of all files')),
5747 [('A', 'all', None, _('show status of all files')),
5742 ('m', 'modified', None, _('show only modified files')),
5748 ('m', 'modified', None, _('show only modified files')),
5743 ('a', 'added', None, _('show only added files')),
5749 ('a', 'added', None, _('show only added files')),
5744 ('r', 'removed', None, _('show only removed files')),
5750 ('r', 'removed', None, _('show only removed files')),
5745 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5751 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5746 ('c', 'clean', None, _('show only files without changes')),
5752 ('c', 'clean', None, _('show only files without changes')),
5747 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5753 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5748 ('i', 'ignored', None, _('show only ignored files')),
5754 ('i', 'ignored', None, _('show only ignored files')),
5749 ('n', 'no-status', None, _('hide status prefix')),
5755 ('n', 'no-status', None, _('hide status prefix')),
5750 ('C', 'copies', None, _('show source of copied files')),
5756 ('C', 'copies', None, _('show source of copied files')),
5751 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5757 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5752 ('', 'rev', [], _('show difference from revision'), _('REV')),
5758 ('', 'rev', [], _('show difference from revision'), _('REV')),
5753 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5759 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5754 ] + walkopts + subrepoopts + formatteropts,
5760 ] + walkopts + subrepoopts + formatteropts,
5755 _('[OPTION]... [FILE]...'),
5761 _('[OPTION]... [FILE]...'),
5756 inferrepo=True)
5762 inferrepo=True)
5757 def status(ui, repo, *pats, **opts):
5763 def status(ui, repo, *pats, **opts):
5758 """show changed files in the working directory
5764 """show changed files in the working directory
5759
5765
5760 Show status of files in the repository. If names are given, only
5766 Show status of files in the repository. If names are given, only
5761 files that match are shown. Files that are clean or ignored or
5767 files that match are shown. Files that are clean or ignored or
5762 the source of a copy/move operation, are not listed unless
5768 the source of a copy/move operation, are not listed unless
5763 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5769 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5764 Unless options described with "show only ..." are given, the
5770 Unless options described with "show only ..." are given, the
5765 options -mardu are used.
5771 options -mardu are used.
5766
5772
5767 Option -q/--quiet hides untracked (unknown and ignored) files
5773 Option -q/--quiet hides untracked (unknown and ignored) files
5768 unless explicitly requested with -u/--unknown or -i/--ignored.
5774 unless explicitly requested with -u/--unknown or -i/--ignored.
5769
5775
5770 .. note::
5776 .. note::
5771
5777
5772 status may appear to disagree with diff if permissions have
5778 status may appear to disagree with diff if permissions have
5773 changed or a merge has occurred. The standard diff format does
5779 changed or a merge has occurred. The standard diff format does
5774 not report permission changes and diff only reports changes
5780 not report permission changes and diff only reports changes
5775 relative to one merge parent.
5781 relative to one merge parent.
5776
5782
5777 If one revision is given, it is used as the base revision.
5783 If one revision is given, it is used as the base revision.
5778 If two revisions are given, the differences between them are
5784 If two revisions are given, the differences between them are
5779 shown. The --change option can also be used as a shortcut to list
5785 shown. The --change option can also be used as a shortcut to list
5780 the changed files of a revision from its first parent.
5786 the changed files of a revision from its first parent.
5781
5787
5782 The codes used to show the status of files are::
5788 The codes used to show the status of files are::
5783
5789
5784 M = modified
5790 M = modified
5785 A = added
5791 A = added
5786 R = removed
5792 R = removed
5787 C = clean
5793 C = clean
5788 ! = missing (deleted by non-hg command, but still tracked)
5794 ! = missing (deleted by non-hg command, but still tracked)
5789 ? = not tracked
5795 ? = not tracked
5790 I = ignored
5796 I = ignored
5791 = origin of the previous file (with --copies)
5797 = origin of the previous file (with --copies)
5792
5798
5793 .. container:: verbose
5799 .. container:: verbose
5794
5800
5795 Examples:
5801 Examples:
5796
5802
5797 - show changes in the working directory relative to a
5803 - show changes in the working directory relative to a
5798 changeset::
5804 changeset::
5799
5805
5800 hg status --rev 9353
5806 hg status --rev 9353
5801
5807
5802 - show changes in the working directory relative to the
5808 - show changes in the working directory relative to the
5803 current directory (see :hg:`help patterns` for more information)::
5809 current directory (see :hg:`help patterns` for more information)::
5804
5810
5805 hg status re:
5811 hg status re:
5806
5812
5807 - show all changes including copies in an existing changeset::
5813 - show all changes including copies in an existing changeset::
5808
5814
5809 hg status --copies --change 9353
5815 hg status --copies --change 9353
5810
5816
5811 - get a NUL separated list of added files, suitable for xargs::
5817 - get a NUL separated list of added files, suitable for xargs::
5812
5818
5813 hg status -an0
5819 hg status -an0
5814
5820
5815 Returns 0 on success.
5821 Returns 0 on success.
5816 """
5822 """
5817
5823
5818 revs = opts.get('rev')
5824 revs = opts.get('rev')
5819 change = opts.get('change')
5825 change = opts.get('change')
5820
5826
5821 if revs and change:
5827 if revs and change:
5822 msg = _('cannot specify --rev and --change at the same time')
5828 msg = _('cannot specify --rev and --change at the same time')
5823 raise util.Abort(msg)
5829 raise util.Abort(msg)
5824 elif change:
5830 elif change:
5825 node2 = scmutil.revsingle(repo, change, None).node()
5831 node2 = scmutil.revsingle(repo, change, None).node()
5826 node1 = repo[node2].p1().node()
5832 node1 = repo[node2].p1().node()
5827 else:
5833 else:
5828 node1, node2 = scmutil.revpair(repo, revs)
5834 node1, node2 = scmutil.revpair(repo, revs)
5829
5835
5830 if pats:
5836 if pats:
5831 cwd = repo.getcwd()
5837 cwd = repo.getcwd()
5832 else:
5838 else:
5833 cwd = ''
5839 cwd = ''
5834
5840
5835 if opts.get('print0'):
5841 if opts.get('print0'):
5836 end = '\0'
5842 end = '\0'
5837 else:
5843 else:
5838 end = '\n'
5844 end = '\n'
5839 copy = {}
5845 copy = {}
5840 states = 'modified added removed deleted unknown ignored clean'.split()
5846 states = 'modified added removed deleted unknown ignored clean'.split()
5841 show = [k for k in states if opts.get(k)]
5847 show = [k for k in states if opts.get(k)]
5842 if opts.get('all'):
5848 if opts.get('all'):
5843 show += ui.quiet and (states[:4] + ['clean']) or states
5849 show += ui.quiet and (states[:4] + ['clean']) or states
5844 if not show:
5850 if not show:
5845 if ui.quiet:
5851 if ui.quiet:
5846 show = states[:4]
5852 show = states[:4]
5847 else:
5853 else:
5848 show = states[:5]
5854 show = states[:5]
5849
5855
5850 m = scmutil.match(repo[node2], pats, opts)
5856 m = scmutil.match(repo[node2], pats, opts)
5851 stat = repo.status(node1, node2, m,
5857 stat = repo.status(node1, node2, m,
5852 'ignored' in show, 'clean' in show, 'unknown' in show,
5858 'ignored' in show, 'clean' in show, 'unknown' in show,
5853 opts.get('subrepos'))
5859 opts.get('subrepos'))
5854 changestates = zip(states, 'MAR!?IC', stat)
5860 changestates = zip(states, 'MAR!?IC', stat)
5855
5861
5856 if (opts.get('all') or opts.get('copies')
5862 if (opts.get('all') or opts.get('copies')
5857 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5863 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
5858 copy = copies.pathcopies(repo[node1], repo[node2], m)
5864 copy = copies.pathcopies(repo[node1], repo[node2], m)
5859
5865
5860 fm = ui.formatter('status', opts)
5866 fm = ui.formatter('status', opts)
5861 fmt = '%s' + end
5867 fmt = '%s' + end
5862 showchar = not opts.get('no_status')
5868 showchar = not opts.get('no_status')
5863
5869
5864 for state, char, files in changestates:
5870 for state, char, files in changestates:
5865 if state in show:
5871 if state in show:
5866 label = 'status.' + state
5872 label = 'status.' + state
5867 for f in files:
5873 for f in files:
5868 fm.startitem()
5874 fm.startitem()
5869 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5875 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5870 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5876 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5871 if f in copy:
5877 if f in copy:
5872 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5878 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5873 label='status.copied')
5879 label='status.copied')
5874 fm.end()
5880 fm.end()
5875
5881
5876 @command('^summary|sum',
5882 @command('^summary|sum',
5877 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5883 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5878 def summary(ui, repo, **opts):
5884 def summary(ui, repo, **opts):
5879 """summarize working directory state
5885 """summarize working directory state
5880
5886
5881 This generates a brief summary of the working directory state,
5887 This generates a brief summary of the working directory state,
5882 including parents, branch, commit status, phase and available updates.
5888 including parents, branch, commit status, phase and available updates.
5883
5889
5884 With the --remote option, this will check the default paths for
5890 With the --remote option, this will check the default paths for
5885 incoming and outgoing changes. This can be time-consuming.
5891 incoming and outgoing changes. This can be time-consuming.
5886
5892
5887 Returns 0 on success.
5893 Returns 0 on success.
5888 """
5894 """
5889
5895
5890 ctx = repo[None]
5896 ctx = repo[None]
5891 parents = ctx.parents()
5897 parents = ctx.parents()
5892 pnode = parents[0].node()
5898 pnode = parents[0].node()
5893 marks = []
5899 marks = []
5894
5900
5895 for p in parents:
5901 for p in parents:
5896 # label with log.changeset (instead of log.parent) since this
5902 # label with log.changeset (instead of log.parent) since this
5897 # shows a working directory parent *changeset*:
5903 # shows a working directory parent *changeset*:
5898 # i18n: column positioning for "hg summary"
5904 # i18n: column positioning for "hg summary"
5899 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5905 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5900 label='log.changeset changeset.%s' % p.phasestr())
5906 label='log.changeset changeset.%s' % p.phasestr())
5901 ui.write(' '.join(p.tags()), label='log.tag')
5907 ui.write(' '.join(p.tags()), label='log.tag')
5902 if p.bookmarks():
5908 if p.bookmarks():
5903 marks.extend(p.bookmarks())
5909 marks.extend(p.bookmarks())
5904 if p.rev() == -1:
5910 if p.rev() == -1:
5905 if not len(repo):
5911 if not len(repo):
5906 ui.write(_(' (empty repository)'))
5912 ui.write(_(' (empty repository)'))
5907 else:
5913 else:
5908 ui.write(_(' (no revision checked out)'))
5914 ui.write(_(' (no revision checked out)'))
5909 ui.write('\n')
5915 ui.write('\n')
5910 if p.description():
5916 if p.description():
5911 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5917 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5912 label='log.summary')
5918 label='log.summary')
5913
5919
5914 branch = ctx.branch()
5920 branch = ctx.branch()
5915 bheads = repo.branchheads(branch)
5921 bheads = repo.branchheads(branch)
5916 # i18n: column positioning for "hg summary"
5922 # i18n: column positioning for "hg summary"
5917 m = _('branch: %s\n') % branch
5923 m = _('branch: %s\n') % branch
5918 if branch != 'default':
5924 if branch != 'default':
5919 ui.write(m, label='log.branch')
5925 ui.write(m, label='log.branch')
5920 else:
5926 else:
5921 ui.status(m, label='log.branch')
5927 ui.status(m, label='log.branch')
5922
5928
5923 if marks:
5929 if marks:
5924 current = repo._activebookmark
5930 current = repo._activebookmark
5925 # i18n: column positioning for "hg summary"
5931 # i18n: column positioning for "hg summary"
5926 ui.write(_('bookmarks:'), label='log.bookmark')
5932 ui.write(_('bookmarks:'), label='log.bookmark')
5927 if current is not None:
5933 if current is not None:
5928 if current in marks:
5934 if current in marks:
5929 ui.write(' *' + current, label='bookmarks.current')
5935 ui.write(' *' + current, label='bookmarks.current')
5930 marks.remove(current)
5936 marks.remove(current)
5931 else:
5937 else:
5932 ui.write(' [%s]' % current, label='bookmarks.current')
5938 ui.write(' [%s]' % current, label='bookmarks.current')
5933 for m in marks:
5939 for m in marks:
5934 ui.write(' ' + m, label='log.bookmark')
5940 ui.write(' ' + m, label='log.bookmark')
5935 ui.write('\n', label='log.bookmark')
5941 ui.write('\n', label='log.bookmark')
5936
5942
5937 status = repo.status(unknown=True)
5943 status = repo.status(unknown=True)
5938
5944
5939 c = repo.dirstate.copies()
5945 c = repo.dirstate.copies()
5940 copied, renamed = [], []
5946 copied, renamed = [], []
5941 for d, s in c.iteritems():
5947 for d, s in c.iteritems():
5942 if s in status.removed:
5948 if s in status.removed:
5943 status.removed.remove(s)
5949 status.removed.remove(s)
5944 renamed.append(d)
5950 renamed.append(d)
5945 else:
5951 else:
5946 copied.append(d)
5952 copied.append(d)
5947 if d in status.added:
5953 if d in status.added:
5948 status.added.remove(d)
5954 status.added.remove(d)
5949
5955
5950 ms = mergemod.mergestate(repo)
5956 ms = mergemod.mergestate(repo)
5951 unresolved = [f for f in ms if ms[f] == 'u']
5957 unresolved = [f for f in ms if ms[f] == 'u']
5952
5958
5953 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5959 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5954
5960
5955 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5961 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5956 (ui.label(_('%d added'), 'status.added'), status.added),
5962 (ui.label(_('%d added'), 'status.added'), status.added),
5957 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5963 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5958 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5964 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5959 (ui.label(_('%d copied'), 'status.copied'), copied),
5965 (ui.label(_('%d copied'), 'status.copied'), copied),
5960 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5966 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5961 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5967 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5962 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5968 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5963 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5969 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5964 t = []
5970 t = []
5965 for l, s in labels:
5971 for l, s in labels:
5966 if s:
5972 if s:
5967 t.append(l % len(s))
5973 t.append(l % len(s))
5968
5974
5969 t = ', '.join(t)
5975 t = ', '.join(t)
5970 cleanworkdir = False
5976 cleanworkdir = False
5971
5977
5972 if repo.vfs.exists('updatestate'):
5978 if repo.vfs.exists('updatestate'):
5973 t += _(' (interrupted update)')
5979 t += _(' (interrupted update)')
5974 elif len(parents) > 1:
5980 elif len(parents) > 1:
5975 t += _(' (merge)')
5981 t += _(' (merge)')
5976 elif branch != parents[0].branch():
5982 elif branch != parents[0].branch():
5977 t += _(' (new branch)')
5983 t += _(' (new branch)')
5978 elif (parents[0].closesbranch() and
5984 elif (parents[0].closesbranch() and
5979 pnode in repo.branchheads(branch, closed=True)):
5985 pnode in repo.branchheads(branch, closed=True)):
5980 t += _(' (head closed)')
5986 t += _(' (head closed)')
5981 elif not (status.modified or status.added or status.removed or renamed or
5987 elif not (status.modified or status.added or status.removed or renamed or
5982 copied or subs):
5988 copied or subs):
5983 t += _(' (clean)')
5989 t += _(' (clean)')
5984 cleanworkdir = True
5990 cleanworkdir = True
5985 elif pnode not in bheads:
5991 elif pnode not in bheads:
5986 t += _(' (new branch head)')
5992 t += _(' (new branch head)')
5987
5993
5988 if cleanworkdir:
5994 if cleanworkdir:
5989 # i18n: column positioning for "hg summary"
5995 # i18n: column positioning for "hg summary"
5990 ui.status(_('commit: %s\n') % t.strip())
5996 ui.status(_('commit: %s\n') % t.strip())
5991 else:
5997 else:
5992 # i18n: column positioning for "hg summary"
5998 # i18n: column positioning for "hg summary"
5993 ui.write(_('commit: %s\n') % t.strip())
5999 ui.write(_('commit: %s\n') % t.strip())
5994
6000
5995 # all ancestors of branch heads - all ancestors of parent = new csets
6001 # all ancestors of branch heads - all ancestors of parent = new csets
5996 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6002 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5997 bheads))
6003 bheads))
5998
6004
5999 if new == 0:
6005 if new == 0:
6000 # i18n: column positioning for "hg summary"
6006 # i18n: column positioning for "hg summary"
6001 ui.status(_('update: (current)\n'))
6007 ui.status(_('update: (current)\n'))
6002 elif pnode not in bheads:
6008 elif pnode not in bheads:
6003 # i18n: column positioning for "hg summary"
6009 # i18n: column positioning for "hg summary"
6004 ui.write(_('update: %d new changesets (update)\n') % new)
6010 ui.write(_('update: %d new changesets (update)\n') % new)
6005 else:
6011 else:
6006 # i18n: column positioning for "hg summary"
6012 # i18n: column positioning for "hg summary"
6007 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6013 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6008 (new, len(bheads)))
6014 (new, len(bheads)))
6009
6015
6010 t = []
6016 t = []
6011 draft = len(repo.revs('draft()'))
6017 draft = len(repo.revs('draft()'))
6012 if draft:
6018 if draft:
6013 t.append(_('%d draft') % draft)
6019 t.append(_('%d draft') % draft)
6014 secret = len(repo.revs('secret()'))
6020 secret = len(repo.revs('secret()'))
6015 if secret:
6021 if secret:
6016 t.append(_('%d secret') % secret)
6022 t.append(_('%d secret') % secret)
6017
6023
6018 if parents:
6024 if parents:
6019 parentphase = max(p.phase() for p in parents)
6025 parentphase = max(p.phase() for p in parents)
6020 else:
6026 else:
6021 parentphase = phases.public
6027 parentphase = phases.public
6022
6028
6023 if draft or secret:
6029 if draft or secret:
6024 ui.status(_('phases: %s (%s)\n') % (', '.join(t),
6030 ui.status(_('phases: %s (%s)\n') % (', '.join(t),
6025 phases.phasenames[parentphase]))
6031 phases.phasenames[parentphase]))
6026 else:
6032 else:
6027 ui.note(_('phases: (%s)\n') % phases.phasenames[parentphase])
6033 ui.note(_('phases: (%s)\n') % phases.phasenames[parentphase])
6028
6034
6029 cmdutil.summaryhooks(ui, repo)
6035 cmdutil.summaryhooks(ui, repo)
6030
6036
6031 if opts.get('remote'):
6037 if opts.get('remote'):
6032 needsincoming, needsoutgoing = True, True
6038 needsincoming, needsoutgoing = True, True
6033 else:
6039 else:
6034 needsincoming, needsoutgoing = False, False
6040 needsincoming, needsoutgoing = False, False
6035 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6041 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6036 if i:
6042 if i:
6037 needsincoming = True
6043 needsincoming = True
6038 if o:
6044 if o:
6039 needsoutgoing = True
6045 needsoutgoing = True
6040 if not needsincoming and not needsoutgoing:
6046 if not needsincoming and not needsoutgoing:
6041 return
6047 return
6042
6048
6043 def getincoming():
6049 def getincoming():
6044 source, branches = hg.parseurl(ui.expandpath('default'))
6050 source, branches = hg.parseurl(ui.expandpath('default'))
6045 sbranch = branches[0]
6051 sbranch = branches[0]
6046 try:
6052 try:
6047 other = hg.peer(repo, {}, source)
6053 other = hg.peer(repo, {}, source)
6048 except error.RepoError:
6054 except error.RepoError:
6049 if opts.get('remote'):
6055 if opts.get('remote'):
6050 raise
6056 raise
6051 return source, sbranch, None, None, None
6057 return source, sbranch, None, None, None
6052 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6058 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6053 if revs:
6059 if revs:
6054 revs = [other.lookup(rev) for rev in revs]
6060 revs = [other.lookup(rev) for rev in revs]
6055 ui.debug('comparing with %s\n' % util.hidepassword(source))
6061 ui.debug('comparing with %s\n' % util.hidepassword(source))
6056 repo.ui.pushbuffer()
6062 repo.ui.pushbuffer()
6057 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6063 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6058 repo.ui.popbuffer()
6064 repo.ui.popbuffer()
6059 return source, sbranch, other, commoninc, commoninc[1]
6065 return source, sbranch, other, commoninc, commoninc[1]
6060
6066
6061 if needsincoming:
6067 if needsincoming:
6062 source, sbranch, sother, commoninc, incoming = getincoming()
6068 source, sbranch, sother, commoninc, incoming = getincoming()
6063 else:
6069 else:
6064 source = sbranch = sother = commoninc = incoming = None
6070 source = sbranch = sother = commoninc = incoming = None
6065
6071
6066 def getoutgoing():
6072 def getoutgoing():
6067 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6073 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6068 dbranch = branches[0]
6074 dbranch = branches[0]
6069 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6075 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6070 if source != dest:
6076 if source != dest:
6071 try:
6077 try:
6072 dother = hg.peer(repo, {}, dest)
6078 dother = hg.peer(repo, {}, dest)
6073 except error.RepoError:
6079 except error.RepoError:
6074 if opts.get('remote'):
6080 if opts.get('remote'):
6075 raise
6081 raise
6076 return dest, dbranch, None, None
6082 return dest, dbranch, None, None
6077 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6083 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6078 elif sother is None:
6084 elif sother is None:
6079 # there is no explicit destination peer, but source one is invalid
6085 # there is no explicit destination peer, but source one is invalid
6080 return dest, dbranch, None, None
6086 return dest, dbranch, None, None
6081 else:
6087 else:
6082 dother = sother
6088 dother = sother
6083 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6089 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6084 common = None
6090 common = None
6085 else:
6091 else:
6086 common = commoninc
6092 common = commoninc
6087 if revs:
6093 if revs:
6088 revs = [repo.lookup(rev) for rev in revs]
6094 revs = [repo.lookup(rev) for rev in revs]
6089 repo.ui.pushbuffer()
6095 repo.ui.pushbuffer()
6090 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6096 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6091 commoninc=common)
6097 commoninc=common)
6092 repo.ui.popbuffer()
6098 repo.ui.popbuffer()
6093 return dest, dbranch, dother, outgoing
6099 return dest, dbranch, dother, outgoing
6094
6100
6095 if needsoutgoing:
6101 if needsoutgoing:
6096 dest, dbranch, dother, outgoing = getoutgoing()
6102 dest, dbranch, dother, outgoing = getoutgoing()
6097 else:
6103 else:
6098 dest = dbranch = dother = outgoing = None
6104 dest = dbranch = dother = outgoing = None
6099
6105
6100 if opts.get('remote'):
6106 if opts.get('remote'):
6101 t = []
6107 t = []
6102 if incoming:
6108 if incoming:
6103 t.append(_('1 or more incoming'))
6109 t.append(_('1 or more incoming'))
6104 o = outgoing.missing
6110 o = outgoing.missing
6105 if o:
6111 if o:
6106 t.append(_('%d outgoing') % len(o))
6112 t.append(_('%d outgoing') % len(o))
6107 other = dother or sother
6113 other = dother or sother
6108 if 'bookmarks' in other.listkeys('namespaces'):
6114 if 'bookmarks' in other.listkeys('namespaces'):
6109 counts = bookmarks.summary(repo, other)
6115 counts = bookmarks.summary(repo, other)
6110 if counts[0] > 0:
6116 if counts[0] > 0:
6111 t.append(_('%d incoming bookmarks') % counts[0])
6117 t.append(_('%d incoming bookmarks') % counts[0])
6112 if counts[1] > 0:
6118 if counts[1] > 0:
6113 t.append(_('%d outgoing bookmarks') % counts[1])
6119 t.append(_('%d outgoing bookmarks') % counts[1])
6114
6120
6115 if t:
6121 if t:
6116 # i18n: column positioning for "hg summary"
6122 # i18n: column positioning for "hg summary"
6117 ui.write(_('remote: %s\n') % (', '.join(t)))
6123 ui.write(_('remote: %s\n') % (', '.join(t)))
6118 else:
6124 else:
6119 # i18n: column positioning for "hg summary"
6125 # i18n: column positioning for "hg summary"
6120 ui.status(_('remote: (synced)\n'))
6126 ui.status(_('remote: (synced)\n'))
6121
6127
6122 cmdutil.summaryremotehooks(ui, repo, opts,
6128 cmdutil.summaryremotehooks(ui, repo, opts,
6123 ((source, sbranch, sother, commoninc),
6129 ((source, sbranch, sother, commoninc),
6124 (dest, dbranch, dother, outgoing)))
6130 (dest, dbranch, dother, outgoing)))
6125
6131
6126 @command('tag',
6132 @command('tag',
6127 [('f', 'force', None, _('force tag')),
6133 [('f', 'force', None, _('force tag')),
6128 ('l', 'local', None, _('make the tag local')),
6134 ('l', 'local', None, _('make the tag local')),
6129 ('r', 'rev', '', _('revision to tag'), _('REV')),
6135 ('r', 'rev', '', _('revision to tag'), _('REV')),
6130 ('', 'remove', None, _('remove a tag')),
6136 ('', 'remove', None, _('remove a tag')),
6131 # -l/--local is already there, commitopts cannot be used
6137 # -l/--local is already there, commitopts cannot be used
6132 ('e', 'edit', None, _('invoke editor on commit messages')),
6138 ('e', 'edit', None, _('invoke editor on commit messages')),
6133 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6139 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6134 ] + commitopts2,
6140 ] + commitopts2,
6135 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6141 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6136 def tag(ui, repo, name1, *names, **opts):
6142 def tag(ui, repo, name1, *names, **opts):
6137 """add one or more tags for the current or given revision
6143 """add one or more tags for the current or given revision
6138
6144
6139 Name a particular revision using <name>.
6145 Name a particular revision using <name>.
6140
6146
6141 Tags are used to name particular revisions of the repository and are
6147 Tags are used to name particular revisions of the repository and are
6142 very useful to compare different revisions, to go back to significant
6148 very useful to compare different revisions, to go back to significant
6143 earlier versions or to mark branch points as releases, etc. Changing
6149 earlier versions or to mark branch points as releases, etc. Changing
6144 an existing tag is normally disallowed; use -f/--force to override.
6150 an existing tag is normally disallowed; use -f/--force to override.
6145
6151
6146 If no revision is given, the parent of the working directory is
6152 If no revision is given, the parent of the working directory is
6147 used.
6153 used.
6148
6154
6149 To facilitate version control, distribution, and merging of tags,
6155 To facilitate version control, distribution, and merging of tags,
6150 they are stored as a file named ".hgtags" which is managed similarly
6156 they are stored as a file named ".hgtags" which is managed similarly
6151 to other project files and can be hand-edited if necessary. This
6157 to other project files and can be hand-edited if necessary. This
6152 also means that tagging creates a new commit. The file
6158 also means that tagging creates a new commit. The file
6153 ".hg/localtags" is used for local tags (not shared among
6159 ".hg/localtags" is used for local tags (not shared among
6154 repositories).
6160 repositories).
6155
6161
6156 Tag commits are usually made at the head of a branch. If the parent
6162 Tag commits are usually made at the head of a branch. If the parent
6157 of the working directory is not a branch head, :hg:`tag` aborts; use
6163 of the working directory is not a branch head, :hg:`tag` aborts; use
6158 -f/--force to force the tag commit to be based on a non-head
6164 -f/--force to force the tag commit to be based on a non-head
6159 changeset.
6165 changeset.
6160
6166
6161 See :hg:`help dates` for a list of formats valid for -d/--date.
6167 See :hg:`help dates` for a list of formats valid for -d/--date.
6162
6168
6163 Since tag names have priority over branch names during revision
6169 Since tag names have priority over branch names during revision
6164 lookup, using an existing branch name as a tag name is discouraged.
6170 lookup, using an existing branch name as a tag name is discouraged.
6165
6171
6166 Returns 0 on success.
6172 Returns 0 on success.
6167 """
6173 """
6168 wlock = lock = None
6174 wlock = lock = None
6169 try:
6175 try:
6170 wlock = repo.wlock()
6176 wlock = repo.wlock()
6171 lock = repo.lock()
6177 lock = repo.lock()
6172 rev_ = "."
6178 rev_ = "."
6173 names = [t.strip() for t in (name1,) + names]
6179 names = [t.strip() for t in (name1,) + names]
6174 if len(names) != len(set(names)):
6180 if len(names) != len(set(names)):
6175 raise util.Abort(_('tag names must be unique'))
6181 raise util.Abort(_('tag names must be unique'))
6176 for n in names:
6182 for n in names:
6177 scmutil.checknewlabel(repo, n, 'tag')
6183 scmutil.checknewlabel(repo, n, 'tag')
6178 if not n:
6184 if not n:
6179 raise util.Abort(_('tag names cannot consist entirely of '
6185 raise util.Abort(_('tag names cannot consist entirely of '
6180 'whitespace'))
6186 'whitespace'))
6181 if opts.get('rev') and opts.get('remove'):
6187 if opts.get('rev') and opts.get('remove'):
6182 raise util.Abort(_("--rev and --remove are incompatible"))
6188 raise util.Abort(_("--rev and --remove are incompatible"))
6183 if opts.get('rev'):
6189 if opts.get('rev'):
6184 rev_ = opts['rev']
6190 rev_ = opts['rev']
6185 message = opts.get('message')
6191 message = opts.get('message')
6186 if opts.get('remove'):
6192 if opts.get('remove'):
6187 if opts.get('local'):
6193 if opts.get('local'):
6188 expectedtype = 'local'
6194 expectedtype = 'local'
6189 else:
6195 else:
6190 expectedtype = 'global'
6196 expectedtype = 'global'
6191
6197
6192 for n in names:
6198 for n in names:
6193 if not repo.tagtype(n):
6199 if not repo.tagtype(n):
6194 raise util.Abort(_("tag '%s' does not exist") % n)
6200 raise util.Abort(_("tag '%s' does not exist") % n)
6195 if repo.tagtype(n) != expectedtype:
6201 if repo.tagtype(n) != expectedtype:
6196 if expectedtype == 'global':
6202 if expectedtype == 'global':
6197 raise util.Abort(_("tag '%s' is not a global tag") % n)
6203 raise util.Abort(_("tag '%s' is not a global tag") % n)
6198 else:
6204 else:
6199 raise util.Abort(_("tag '%s' is not a local tag") % n)
6205 raise util.Abort(_("tag '%s' is not a local tag") % n)
6200 rev_ = nullid
6206 rev_ = nullid
6201 if not message:
6207 if not message:
6202 # we don't translate commit messages
6208 # we don't translate commit messages
6203 message = 'Removed tag %s' % ', '.join(names)
6209 message = 'Removed tag %s' % ', '.join(names)
6204 elif not opts.get('force'):
6210 elif not opts.get('force'):
6205 for n in names:
6211 for n in names:
6206 if n in repo.tags():
6212 if n in repo.tags():
6207 raise util.Abort(_("tag '%s' already exists "
6213 raise util.Abort(_("tag '%s' already exists "
6208 "(use -f to force)") % n)
6214 "(use -f to force)") % n)
6209 if not opts.get('local'):
6215 if not opts.get('local'):
6210 p1, p2 = repo.dirstate.parents()
6216 p1, p2 = repo.dirstate.parents()
6211 if p2 != nullid:
6217 if p2 != nullid:
6212 raise util.Abort(_('uncommitted merge'))
6218 raise util.Abort(_('uncommitted merge'))
6213 bheads = repo.branchheads()
6219 bheads = repo.branchheads()
6214 if not opts.get('force') and bheads and p1 not in bheads:
6220 if not opts.get('force') and bheads and p1 not in bheads:
6215 raise util.Abort(_('not at a branch head (use -f to force)'))
6221 raise util.Abort(_('not at a branch head (use -f to force)'))
6216 r = scmutil.revsingle(repo, rev_).node()
6222 r = scmutil.revsingle(repo, rev_).node()
6217
6223
6218 if not message:
6224 if not message:
6219 # we don't translate commit messages
6225 # we don't translate commit messages
6220 message = ('Added tag %s for changeset %s' %
6226 message = ('Added tag %s for changeset %s' %
6221 (', '.join(names), short(r)))
6227 (', '.join(names), short(r)))
6222
6228
6223 date = opts.get('date')
6229 date = opts.get('date')
6224 if date:
6230 if date:
6225 date = util.parsedate(date)
6231 date = util.parsedate(date)
6226
6232
6227 if opts.get('remove'):
6233 if opts.get('remove'):
6228 editform = 'tag.remove'
6234 editform = 'tag.remove'
6229 else:
6235 else:
6230 editform = 'tag.add'
6236 editform = 'tag.add'
6231 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6237 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6232
6238
6233 # don't allow tagging the null rev
6239 # don't allow tagging the null rev
6234 if (not opts.get('remove') and
6240 if (not opts.get('remove') and
6235 scmutil.revsingle(repo, rev_).rev() == nullrev):
6241 scmutil.revsingle(repo, rev_).rev() == nullrev):
6236 raise util.Abort(_("cannot tag null revision"))
6242 raise util.Abort(_("cannot tag null revision"))
6237
6243
6238 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6244 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6239 editor=editor)
6245 editor=editor)
6240 finally:
6246 finally:
6241 release(lock, wlock)
6247 release(lock, wlock)
6242
6248
6243 @command('tags', formatteropts, '')
6249 @command('tags', formatteropts, '')
6244 def tags(ui, repo, **opts):
6250 def tags(ui, repo, **opts):
6245 """list repository tags
6251 """list repository tags
6246
6252
6247 This lists both regular and local tags. When the -v/--verbose
6253 This lists both regular and local tags. When the -v/--verbose
6248 switch is used, a third column "local" is printed for local tags.
6254 switch is used, a third column "local" is printed for local tags.
6249
6255
6250 Returns 0 on success.
6256 Returns 0 on success.
6251 """
6257 """
6252
6258
6253 fm = ui.formatter('tags', opts)
6259 fm = ui.formatter('tags', opts)
6254 hexfunc = fm.hexfunc
6260 hexfunc = fm.hexfunc
6255 tagtype = ""
6261 tagtype = ""
6256
6262
6257 for t, n in reversed(repo.tagslist()):
6263 for t, n in reversed(repo.tagslist()):
6258 hn = hexfunc(n)
6264 hn = hexfunc(n)
6259 label = 'tags.normal'
6265 label = 'tags.normal'
6260 tagtype = ''
6266 tagtype = ''
6261 if repo.tagtype(t) == 'local':
6267 if repo.tagtype(t) == 'local':
6262 label = 'tags.local'
6268 label = 'tags.local'
6263 tagtype = 'local'
6269 tagtype = 'local'
6264
6270
6265 fm.startitem()
6271 fm.startitem()
6266 fm.write('tag', '%s', t, label=label)
6272 fm.write('tag', '%s', t, label=label)
6267 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6273 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6268 fm.condwrite(not ui.quiet, 'rev node', fmt,
6274 fm.condwrite(not ui.quiet, 'rev node', fmt,
6269 repo.changelog.rev(n), hn, label=label)
6275 repo.changelog.rev(n), hn, label=label)
6270 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6276 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6271 tagtype, label=label)
6277 tagtype, label=label)
6272 fm.plain('\n')
6278 fm.plain('\n')
6273 fm.end()
6279 fm.end()
6274
6280
6275 @command('tip',
6281 @command('tip',
6276 [('p', 'patch', None, _('show patch')),
6282 [('p', 'patch', None, _('show patch')),
6277 ('g', 'git', None, _('use git extended diff format')),
6283 ('g', 'git', None, _('use git extended diff format')),
6278 ] + templateopts,
6284 ] + templateopts,
6279 _('[-p] [-g]'))
6285 _('[-p] [-g]'))
6280 def tip(ui, repo, **opts):
6286 def tip(ui, repo, **opts):
6281 """show the tip revision (DEPRECATED)
6287 """show the tip revision (DEPRECATED)
6282
6288
6283 The tip revision (usually just called the tip) is the changeset
6289 The tip revision (usually just called the tip) is the changeset
6284 most recently added to the repository (and therefore the most
6290 most recently added to the repository (and therefore the most
6285 recently changed head).
6291 recently changed head).
6286
6292
6287 If you have just made a commit, that commit will be the tip. If
6293 If you have just made a commit, that commit will be the tip. If
6288 you have just pulled changes from another repository, the tip of
6294 you have just pulled changes from another repository, the tip of
6289 that repository becomes the current tip. The "tip" tag is special
6295 that repository becomes the current tip. The "tip" tag is special
6290 and cannot be renamed or assigned to a different changeset.
6296 and cannot be renamed or assigned to a different changeset.
6291
6297
6292 This command is deprecated, please use :hg:`heads` instead.
6298 This command is deprecated, please use :hg:`heads` instead.
6293
6299
6294 Returns 0 on success.
6300 Returns 0 on success.
6295 """
6301 """
6296 displayer = cmdutil.show_changeset(ui, repo, opts)
6302 displayer = cmdutil.show_changeset(ui, repo, opts)
6297 displayer.show(repo['tip'])
6303 displayer.show(repo['tip'])
6298 displayer.close()
6304 displayer.close()
6299
6305
6300 @command('unbundle',
6306 @command('unbundle',
6301 [('u', 'update', None,
6307 [('u', 'update', None,
6302 _('update to new branch head if changesets were unbundled'))],
6308 _('update to new branch head if changesets were unbundled'))],
6303 _('[-u] FILE...'))
6309 _('[-u] FILE...'))
6304 def unbundle(ui, repo, fname1, *fnames, **opts):
6310 def unbundle(ui, repo, fname1, *fnames, **opts):
6305 """apply one or more changegroup files
6311 """apply one or more changegroup files
6306
6312
6307 Apply one or more compressed changegroup files generated by the
6313 Apply one or more compressed changegroup files generated by the
6308 bundle command.
6314 bundle command.
6309
6315
6310 Returns 0 on success, 1 if an update has unresolved files.
6316 Returns 0 on success, 1 if an update has unresolved files.
6311 """
6317 """
6312 fnames = (fname1,) + fnames
6318 fnames = (fname1,) + fnames
6313
6319
6314 lock = repo.lock()
6320 lock = repo.lock()
6315 try:
6321 try:
6316 for fname in fnames:
6322 for fname in fnames:
6317 f = hg.openpath(ui, fname)
6323 f = hg.openpath(ui, fname)
6318 gen = exchange.readbundle(ui, f, fname)
6324 gen = exchange.readbundle(ui, f, fname)
6319 if isinstance(gen, bundle2.unbundle20):
6325 if isinstance(gen, bundle2.unbundle20):
6320 tr = repo.transaction('unbundle')
6326 tr = repo.transaction('unbundle')
6321 try:
6327 try:
6322 op = bundle2.processbundle(repo, gen, lambda: tr)
6328 op = bundle2.processbundle(repo, gen, lambda: tr)
6323 tr.close()
6329 tr.close()
6324 finally:
6330 finally:
6325 if tr:
6331 if tr:
6326 tr.release()
6332 tr.release()
6327 changes = [r.get('result', 0)
6333 changes = [r.get('result', 0)
6328 for r in op.records['changegroup']]
6334 for r in op.records['changegroup']]
6329 modheads = changegroup.combineresults(changes)
6335 modheads = changegroup.combineresults(changes)
6330 else:
6336 else:
6331 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6337 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6332 'bundle:' + fname)
6338 'bundle:' + fname)
6333 finally:
6339 finally:
6334 lock.release()
6340 lock.release()
6335
6341
6336 return postincoming(ui, repo, modheads, opts.get('update'), None)
6342 return postincoming(ui, repo, modheads, opts.get('update'), None)
6337
6343
6338 @command('^update|up|checkout|co',
6344 @command('^update|up|checkout|co',
6339 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6345 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6340 ('c', 'check', None,
6346 ('c', 'check', None,
6341 _('update across branches if no uncommitted changes')),
6347 _('update across branches if no uncommitted changes')),
6342 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6348 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6343 ('r', 'rev', '', _('revision'), _('REV'))
6349 ('r', 'rev', '', _('revision'), _('REV'))
6344 ] + mergetoolopts,
6350 ] + mergetoolopts,
6345 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6351 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6346 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6352 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6347 tool=None):
6353 tool=None):
6348 """update working directory (or switch revisions)
6354 """update working directory (or switch revisions)
6349
6355
6350 Update the repository's working directory to the specified
6356 Update the repository's working directory to the specified
6351 changeset. If no changeset is specified, update to the tip of the
6357 changeset. If no changeset is specified, update to the tip of the
6352 current named branch and move the current bookmark (see :hg:`help
6358 current named branch and move the current bookmark (see :hg:`help
6353 bookmarks`).
6359 bookmarks`).
6354
6360
6355 Update sets the working directory's parent revision to the specified
6361 Update sets the working directory's parent revision to the specified
6356 changeset (see :hg:`help parents`).
6362 changeset (see :hg:`help parents`).
6357
6363
6358 If the changeset is not a descendant or ancestor of the working
6364 If the changeset is not a descendant or ancestor of the working
6359 directory's parent, the update is aborted. With the -c/--check
6365 directory's parent, the update is aborted. With the -c/--check
6360 option, the working directory is checked for uncommitted changes; if
6366 option, the working directory is checked for uncommitted changes; if
6361 none are found, the working directory is updated to the specified
6367 none are found, the working directory is updated to the specified
6362 changeset.
6368 changeset.
6363
6369
6364 .. container:: verbose
6370 .. container:: verbose
6365
6371
6366 The following rules apply when the working directory contains
6372 The following rules apply when the working directory contains
6367 uncommitted changes:
6373 uncommitted changes:
6368
6374
6369 1. If neither -c/--check nor -C/--clean is specified, and if
6375 1. If neither -c/--check nor -C/--clean is specified, and if
6370 the requested changeset is an ancestor or descendant of
6376 the requested changeset is an ancestor or descendant of
6371 the working directory's parent, the uncommitted changes
6377 the working directory's parent, the uncommitted changes
6372 are merged into the requested changeset and the merged
6378 are merged into the requested changeset and the merged
6373 result is left uncommitted. If the requested changeset is
6379 result is left uncommitted. If the requested changeset is
6374 not an ancestor or descendant (that is, it is on another
6380 not an ancestor or descendant (that is, it is on another
6375 branch), the update is aborted and the uncommitted changes
6381 branch), the update is aborted and the uncommitted changes
6376 are preserved.
6382 are preserved.
6377
6383
6378 2. With the -c/--check option, the update is aborted and the
6384 2. With the -c/--check option, the update is aborted and the
6379 uncommitted changes are preserved.
6385 uncommitted changes are preserved.
6380
6386
6381 3. With the -C/--clean option, uncommitted changes are discarded and
6387 3. With the -C/--clean option, uncommitted changes are discarded and
6382 the working directory is updated to the requested changeset.
6388 the working directory is updated to the requested changeset.
6383
6389
6384 To cancel an uncommitted merge (and lose your changes), use
6390 To cancel an uncommitted merge (and lose your changes), use
6385 :hg:`update --clean .`.
6391 :hg:`update --clean .`.
6386
6392
6387 Use null as the changeset to remove the working directory (like
6393 Use null as the changeset to remove the working directory (like
6388 :hg:`clone -U`).
6394 :hg:`clone -U`).
6389
6395
6390 If you want to revert just one file to an older revision, use
6396 If you want to revert just one file to an older revision, use
6391 :hg:`revert [-r REV] NAME`.
6397 :hg:`revert [-r REV] NAME`.
6392
6398
6393 See :hg:`help dates` for a list of formats valid for -d/--date.
6399 See :hg:`help dates` for a list of formats valid for -d/--date.
6394
6400
6395 Returns 0 on success, 1 if there are unresolved files.
6401 Returns 0 on success, 1 if there are unresolved files.
6396 """
6402 """
6397 if rev and node:
6403 if rev and node:
6398 raise util.Abort(_("please specify just one revision"))
6404 raise util.Abort(_("please specify just one revision"))
6399
6405
6400 if rev is None or rev == '':
6406 if rev is None or rev == '':
6401 rev = node
6407 rev = node
6402
6408
6403 cmdutil.clearunfinished(repo)
6409 cmdutil.clearunfinished(repo)
6404
6410
6405 # with no argument, we also move the current bookmark, if any
6411 # with no argument, we also move the current bookmark, if any
6406 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6412 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6407
6413
6408 # if we defined a bookmark, we have to remember the original bookmark name
6414 # if we defined a bookmark, we have to remember the original bookmark name
6409 brev = rev
6415 brev = rev
6410 rev = scmutil.revsingle(repo, rev, rev).rev()
6416 rev = scmutil.revsingle(repo, rev, rev).rev()
6411
6417
6412 if check and clean:
6418 if check and clean:
6413 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6419 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6414
6420
6415 if date:
6421 if date:
6416 if rev is not None:
6422 if rev is not None:
6417 raise util.Abort(_("you can't specify a revision and a date"))
6423 raise util.Abort(_("you can't specify a revision and a date"))
6418 rev = cmdutil.finddate(ui, repo, date)
6424 rev = cmdutil.finddate(ui, repo, date)
6419
6425
6420 if check:
6426 if check:
6421 cmdutil.bailifchanged(repo, merge=False)
6427 cmdutil.bailifchanged(repo, merge=False)
6422 if rev is None:
6428 if rev is None:
6423 rev = repo[repo[None].branch()].rev()
6429 rev = repo[repo[None].branch()].rev()
6424
6430
6425 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6431 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6426
6432
6427 if clean:
6433 if clean:
6428 ret = hg.clean(repo, rev)
6434 ret = hg.clean(repo, rev)
6429 else:
6435 else:
6430 ret = hg.update(repo, rev)
6436 ret = hg.update(repo, rev)
6431
6437
6432 if not ret and movemarkfrom:
6438 if not ret and movemarkfrom:
6433 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6439 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6434 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6440 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6435 elif brev in repo._bookmarks:
6441 elif brev in repo._bookmarks:
6436 bookmarks.activate(repo, brev)
6442 bookmarks.activate(repo, brev)
6437 ui.status(_("(activating bookmark %s)\n") % brev)
6443 ui.status(_("(activating bookmark %s)\n") % brev)
6438 elif brev:
6444 elif brev:
6439 if repo._activebookmark:
6445 if repo._activebookmark:
6440 ui.status(_("(leaving bookmark %s)\n") %
6446 ui.status(_("(leaving bookmark %s)\n") %
6441 repo._activebookmark)
6447 repo._activebookmark)
6442 bookmarks.deactivate(repo)
6448 bookmarks.deactivate(repo)
6443
6449
6444 return ret
6450 return ret
6445
6451
6446 @command('verify', [])
6452 @command('verify', [])
6447 def verify(ui, repo):
6453 def verify(ui, repo):
6448 """verify the integrity of the repository
6454 """verify the integrity of the repository
6449
6455
6450 Verify the integrity of the current repository.
6456 Verify the integrity of the current repository.
6451
6457
6452 This will perform an extensive check of the repository's
6458 This will perform an extensive check of the repository's
6453 integrity, validating the hashes and checksums of each entry in
6459 integrity, validating the hashes and checksums of each entry in
6454 the changelog, manifest, and tracked files, as well as the
6460 the changelog, manifest, and tracked files, as well as the
6455 integrity of their crosslinks and indices.
6461 integrity of their crosslinks and indices.
6456
6462
6457 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6463 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6458 for more information about recovery from corruption of the
6464 for more information about recovery from corruption of the
6459 repository.
6465 repository.
6460
6466
6461 Returns 0 on success, 1 if errors are encountered.
6467 Returns 0 on success, 1 if errors are encountered.
6462 """
6468 """
6463 return hg.verify(repo)
6469 return hg.verify(repo)
6464
6470
6465 @command('version', [], norepo=True)
6471 @command('version', [], norepo=True)
6466 def version_(ui):
6472 def version_(ui):
6467 """output version and copyright information"""
6473 """output version and copyright information"""
6468 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6474 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6469 % util.version())
6475 % util.version())
6470 ui.status(_(
6476 ui.status(_(
6471 "(see http://mercurial.selenic.com for more information)\n"
6477 "(see http://mercurial.selenic.com for more information)\n"
6472 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6478 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6473 "This is free software; see the source for copying conditions. "
6479 "This is free software; see the source for copying conditions. "
6474 "There is NO\nwarranty; "
6480 "There is NO\nwarranty; "
6475 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6481 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6476 ))
6482 ))
6477
6483
6478 ui.note(_("\nEnabled extensions:\n\n"))
6484 ui.note(_("\nEnabled extensions:\n\n"))
6479 if ui.verbose:
6485 if ui.verbose:
6480 # format names and versions into columns
6486 # format names and versions into columns
6481 names = []
6487 names = []
6482 vers = []
6488 vers = []
6483 for name, module in extensions.extensions():
6489 for name, module in extensions.extensions():
6484 names.append(name)
6490 names.append(name)
6485 vers.append(extensions.moduleversion(module))
6491 vers.append(extensions.moduleversion(module))
6486 if names:
6492 if names:
6487 maxnamelen = max(len(n) for n in names)
6493 maxnamelen = max(len(n) for n in names)
6488 for i, name in enumerate(names):
6494 for i, name in enumerate(names):
6489 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6495 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,410 +1,409 b''
1 Create configuration
1 Create configuration
2
2
3 $ echo "[ui]" >> $HGRCPATH
3 $ echo "[ui]" >> $HGRCPATH
4 $ echo "interactive=true" >> $HGRCPATH
4 $ echo "interactive=true" >> $HGRCPATH
5
5
6 help record (no record)
6 help record (no record)
7
7
8 $ hg help record
8 $ hg help record
9 record extension - commands to interactively select changes for
9 record extension - commands to interactively select changes for
10 commit/qrefresh
10 commit/qrefresh
11
11
12 (use "hg help extensions" for information on enabling extensions)
12 (use "hg help extensions" for information on enabling extensions)
13
13
14 help qrecord (no record)
14 help qrecord (no record)
15
15
16 $ hg help qrecord
16 $ hg help qrecord
17 'qrecord' is provided by the following extension:
17 'qrecord' is provided by the following extension:
18
18
19 record commands to interactively select changes for commit/qrefresh
19 record commands to interactively select changes for commit/qrefresh
20
20
21 (use "hg help extensions" for information on enabling extensions)
21 (use "hg help extensions" for information on enabling extensions)
22
22
23 $ echo "[extensions]" >> $HGRCPATH
23 $ echo "[extensions]" >> $HGRCPATH
24 $ echo "record=" >> $HGRCPATH
24 $ echo "record=" >> $HGRCPATH
25
25
26 help record (record)
26 help record (record)
27
27
28 $ hg help record
28 $ hg help record
29 hg record [OPTION]... [FILE]...
29 hg record [OPTION]... [FILE]...
30
30
31 interactively select changes to commit
31 interactively select changes to commit
32
32
33 If a list of files is omitted, all changes reported by "hg status" will be
33 If a list of files is omitted, all changes reported by "hg status" will be
34 candidates for recording.
34 candidates for recording.
35
35
36 See "hg help dates" for a list of formats valid for -d/--date.
36 See "hg help dates" for a list of formats valid for -d/--date.
37
37
38 You will be prompted for whether to record changes to each modified file,
38 You will be prompted for whether to record changes to each modified file,
39 and for files with multiple changes, for each change to use. For each
39 and for files with multiple changes, for each change to use. For each
40 query, the following responses are possible:
40 query, the following responses are possible:
41
41
42 y - record this change
42 y - record this change
43 n - skip this change
43 n - skip this change
44 e - edit this change manually
44 e - edit this change manually
45
45
46 s - skip remaining changes to this file
46 s - skip remaining changes to this file
47 f - record remaining changes to this file
47 f - record remaining changes to this file
48
48
49 d - done, skip remaining changes and files
49 d - done, skip remaining changes and files
50 a - record all changes to all remaining files
50 a - record all changes to all remaining files
51 q - quit, recording no changes
51 q - quit, recording no changes
52
52
53 ? - display help
53 ? - display help
54
54
55 This command is not available when committing a merge.
55 This command is not available when committing a merge.
56
56
57 options ([+] can be repeated):
57 options ([+] can be repeated):
58
58
59 -A --addremove mark new/missing files as added/removed before
59 -A --addremove mark new/missing files as added/removed before
60 committing
60 committing
61 --close-branch mark a branch as closed, hiding it from the branch
61 --close-branch mark a branch head as closed
62 list
63 --amend amend the parent of the working directory
62 --amend amend the parent of the working directory
64 -s --secret use the secret phase for committing
63 -s --secret use the secret phase for committing
65 -e --edit invoke editor on commit messages
64 -e --edit invoke editor on commit messages
66 -I --include PATTERN [+] include names matching the given patterns
65 -I --include PATTERN [+] include names matching the given patterns
67 -X --exclude PATTERN [+] exclude names matching the given patterns
66 -X --exclude PATTERN [+] exclude names matching the given patterns
68 -m --message TEXT use text as commit message
67 -m --message TEXT use text as commit message
69 -l --logfile FILE read commit message from file
68 -l --logfile FILE read commit message from file
70 -d --date DATE record the specified date as commit date
69 -d --date DATE record the specified date as commit date
71 -u --user USER record the specified user as committer
70 -u --user USER record the specified user as committer
72 -S --subrepos recurse into subrepositories
71 -S --subrepos recurse into subrepositories
73 -w --ignore-all-space ignore white space when comparing lines
72 -w --ignore-all-space ignore white space when comparing lines
74 -b --ignore-space-change ignore changes in the amount of white space
73 -b --ignore-space-change ignore changes in the amount of white space
75 -B --ignore-blank-lines ignore changes whose lines are all blank
74 -B --ignore-blank-lines ignore changes whose lines are all blank
76
75
77 (some details hidden, use --verbose to show complete help)
76 (some details hidden, use --verbose to show complete help)
78
77
79 help (no mq, so no qrecord)
78 help (no mq, so no qrecord)
80
79
81 $ hg help qrecord
80 $ hg help qrecord
82 hg qrecord [OPTION]... PATCH [FILE]...
81 hg qrecord [OPTION]... PATCH [FILE]...
83
82
84 interactively record a new patch
83 interactively record a new patch
85
84
86 See "hg help qnew" & "hg help record" for more information and usage.
85 See "hg help qnew" & "hg help record" for more information and usage.
87
86
88 (some details hidden, use --verbose to show complete help)
87 (some details hidden, use --verbose to show complete help)
89
88
90 $ hg init a
89 $ hg init a
91
90
92 qrecord (mq not present)
91 qrecord (mq not present)
93
92
94 $ hg -R a qrecord
93 $ hg -R a qrecord
95 hg qrecord: invalid arguments
94 hg qrecord: invalid arguments
96 hg qrecord [OPTION]... PATCH [FILE]...
95 hg qrecord [OPTION]... PATCH [FILE]...
97
96
98 interactively record a new patch
97 interactively record a new patch
99
98
100 (use "hg qrecord -h" to show more help)
99 (use "hg qrecord -h" to show more help)
101 [255]
100 [255]
102
101
103 qrecord patch (mq not present)
102 qrecord patch (mq not present)
104
103
105 $ hg -R a qrecord patch
104 $ hg -R a qrecord patch
106 abort: 'mq' extension not loaded
105 abort: 'mq' extension not loaded
107 [255]
106 [255]
108
107
109 help (bad mq)
108 help (bad mq)
110
109
111 $ echo "mq=nonexistent" >> $HGRCPATH
110 $ echo "mq=nonexistent" >> $HGRCPATH
112 $ hg help qrecord
111 $ hg help qrecord
113 *** failed to import extension mq from nonexistent: [Errno *] * (glob)
112 *** failed to import extension mq from nonexistent: [Errno *] * (glob)
114 hg qrecord [OPTION]... PATCH [FILE]...
113 hg qrecord [OPTION]... PATCH [FILE]...
115
114
116 interactively record a new patch
115 interactively record a new patch
117
116
118 See "hg help qnew" & "hg help record" for more information and usage.
117 See "hg help qnew" & "hg help record" for more information and usage.
119
118
120 (some details hidden, use --verbose to show complete help)
119 (some details hidden, use --verbose to show complete help)
121
120
122 help (mq present)
121 help (mq present)
123
122
124 $ sed 's/mq=nonexistent/mq=/' $HGRCPATH > hgrc.tmp
123 $ sed 's/mq=nonexistent/mq=/' $HGRCPATH > hgrc.tmp
125 $ mv hgrc.tmp $HGRCPATH
124 $ mv hgrc.tmp $HGRCPATH
126
125
127 $ hg help qrecord
126 $ hg help qrecord
128 hg qrecord [OPTION]... PATCH [FILE]...
127 hg qrecord [OPTION]... PATCH [FILE]...
129
128
130 interactively record a new patch
129 interactively record a new patch
131
130
132 See "hg help qnew" & "hg help record" for more information and usage.
131 See "hg help qnew" & "hg help record" for more information and usage.
133
132
134 options ([+] can be repeated):
133 options ([+] can be repeated):
135
134
136 -e --edit invoke editor on commit messages
135 -e --edit invoke editor on commit messages
137 -g --git use git extended diff format
136 -g --git use git extended diff format
138 -U --currentuser add "From: <current user>" to patch
137 -U --currentuser add "From: <current user>" to patch
139 -u --user USER add "From: <USER>" to patch
138 -u --user USER add "From: <USER>" to patch
140 -D --currentdate add "Date: <current date>" to patch
139 -D --currentdate add "Date: <current date>" to patch
141 -d --date DATE add "Date: <DATE>" to patch
140 -d --date DATE add "Date: <DATE>" to patch
142 -I --include PATTERN [+] include names matching the given patterns
141 -I --include PATTERN [+] include names matching the given patterns
143 -X --exclude PATTERN [+] exclude names matching the given patterns
142 -X --exclude PATTERN [+] exclude names matching the given patterns
144 -m --message TEXT use text as commit message
143 -m --message TEXT use text as commit message
145 -l --logfile FILE read commit message from file
144 -l --logfile FILE read commit message from file
146 -w --ignore-all-space ignore white space when comparing lines
145 -w --ignore-all-space ignore white space when comparing lines
147 -b --ignore-space-change ignore changes in the amount of white space
146 -b --ignore-space-change ignore changes in the amount of white space
148 -B --ignore-blank-lines ignore changes whose lines are all blank
147 -B --ignore-blank-lines ignore changes whose lines are all blank
149 --mq operate on patch repository
148 --mq operate on patch repository
150
149
151 (some details hidden, use --verbose to show complete help)
150 (some details hidden, use --verbose to show complete help)
152
151
153 $ cd a
152 $ cd a
154
153
155 Base commit
154 Base commit
156
155
157 $ cat > 1.txt <<EOF
156 $ cat > 1.txt <<EOF
158 > 1
157 > 1
159 > 2
158 > 2
160 > 3
159 > 3
161 > 4
160 > 4
162 > 5
161 > 5
163 > EOF
162 > EOF
164 $ cat > 2.txt <<EOF
163 $ cat > 2.txt <<EOF
165 > a
164 > a
166 > b
165 > b
167 > c
166 > c
168 > d
167 > d
169 > e
168 > e
170 > f
169 > f
171 > EOF
170 > EOF
172
171
173 $ mkdir dir
172 $ mkdir dir
174 $ cat > dir/a.txt <<EOF
173 $ cat > dir/a.txt <<EOF
175 > hello world
174 > hello world
176 >
175 >
177 > someone
176 > someone
178 > up
177 > up
179 > there
178 > there
180 > loves
179 > loves
181 > me
180 > me
182 > EOF
181 > EOF
183
182
184 $ hg add 1.txt 2.txt dir/a.txt
183 $ hg add 1.txt 2.txt dir/a.txt
185 $ hg commit -m 'initial checkin'
184 $ hg commit -m 'initial checkin'
186
185
187 Changing files
186 Changing files
188
187
189 $ sed -e 's/2/2 2/;s/4/4 4/' 1.txt > 1.txt.new
188 $ sed -e 's/2/2 2/;s/4/4 4/' 1.txt > 1.txt.new
190 $ sed -e 's/b/b b/' 2.txt > 2.txt.new
189 $ sed -e 's/b/b b/' 2.txt > 2.txt.new
191 $ sed -e 's/hello world/hello world!/' dir/a.txt > dir/a.txt.new
190 $ sed -e 's/hello world/hello world!/' dir/a.txt > dir/a.txt.new
192
191
193 $ mv -f 1.txt.new 1.txt
192 $ mv -f 1.txt.new 1.txt
194 $ mv -f 2.txt.new 2.txt
193 $ mv -f 2.txt.new 2.txt
195 $ mv -f dir/a.txt.new dir/a.txt
194 $ mv -f dir/a.txt.new dir/a.txt
196
195
197 Whole diff
196 Whole diff
198
197
199 $ hg diff --nodates
198 $ hg diff --nodates
200 diff -r 1057167b20ef 1.txt
199 diff -r 1057167b20ef 1.txt
201 --- a/1.txt
200 --- a/1.txt
202 +++ b/1.txt
201 +++ b/1.txt
203 @@ -1,5 +1,5 @@
202 @@ -1,5 +1,5 @@
204 1
203 1
205 -2
204 -2
206 +2 2
205 +2 2
207 3
206 3
208 -4
207 -4
209 +4 4
208 +4 4
210 5
209 5
211 diff -r 1057167b20ef 2.txt
210 diff -r 1057167b20ef 2.txt
212 --- a/2.txt
211 --- a/2.txt
213 +++ b/2.txt
212 +++ b/2.txt
214 @@ -1,5 +1,5 @@
213 @@ -1,5 +1,5 @@
215 a
214 a
216 -b
215 -b
217 +b b
216 +b b
218 c
217 c
219 d
218 d
220 e
219 e
221 diff -r 1057167b20ef dir/a.txt
220 diff -r 1057167b20ef dir/a.txt
222 --- a/dir/a.txt
221 --- a/dir/a.txt
223 +++ b/dir/a.txt
222 +++ b/dir/a.txt
224 @@ -1,4 +1,4 @@
223 @@ -1,4 +1,4 @@
225 -hello world
224 -hello world
226 +hello world!
225 +hello world!
227
226
228 someone
227 someone
229 up
228 up
230
229
231 qrecord with bad patch name, should abort before prompting
230 qrecord with bad patch name, should abort before prompting
232
231
233 $ hg qrecord .hg
232 $ hg qrecord .hg
234 abort: patch name cannot begin with ".hg"
233 abort: patch name cannot begin with ".hg"
235 [255]
234 [255]
236
235
237 qrecord a.patch
236 qrecord a.patch
238
237
239 $ hg qrecord -d '0 0' -m aaa a.patch <<EOF
238 $ hg qrecord -d '0 0' -m aaa a.patch <<EOF
240 > y
239 > y
241 > y
240 > y
242 > n
241 > n
243 > y
242 > y
244 > y
243 > y
245 > n
244 > n
246 > EOF
245 > EOF
247 diff --git a/1.txt b/1.txt
246 diff --git a/1.txt b/1.txt
248 2 hunks, 2 lines changed
247 2 hunks, 2 lines changed
249 examine changes to '1.txt'? [Ynesfdaq?] y
248 examine changes to '1.txt'? [Ynesfdaq?] y
250
249
251 @@ -1,3 +1,3 @@
250 @@ -1,3 +1,3 @@
252 1
251 1
253 -2
252 -2
254 +2 2
253 +2 2
255 3
254 3
256 record change 1/4 to '1.txt'? [Ynesfdaq?] y
255 record change 1/4 to '1.txt'? [Ynesfdaq?] y
257
256
258 @@ -3,3 +3,3 @@
257 @@ -3,3 +3,3 @@
259 3
258 3
260 -4
259 -4
261 +4 4
260 +4 4
262 5
261 5
263 record change 2/4 to '1.txt'? [Ynesfdaq?] n
262 record change 2/4 to '1.txt'? [Ynesfdaq?] n
264
263
265 diff --git a/2.txt b/2.txt
264 diff --git a/2.txt b/2.txt
266 1 hunks, 1 lines changed
265 1 hunks, 1 lines changed
267 examine changes to '2.txt'? [Ynesfdaq?] y
266 examine changes to '2.txt'? [Ynesfdaq?] y
268
267
269 @@ -1,5 +1,5 @@
268 @@ -1,5 +1,5 @@
270 a
269 a
271 -b
270 -b
272 +b b
271 +b b
273 c
272 c
274 d
273 d
275 e
274 e
276 record change 3/4 to '2.txt'? [Ynesfdaq?] y
275 record change 3/4 to '2.txt'? [Ynesfdaq?] y
277
276
278 diff --git a/dir/a.txt b/dir/a.txt
277 diff --git a/dir/a.txt b/dir/a.txt
279 1 hunks, 1 lines changed
278 1 hunks, 1 lines changed
280 examine changes to 'dir/a.txt'? [Ynesfdaq?] n
279 examine changes to 'dir/a.txt'? [Ynesfdaq?] n
281
280
282
281
283 After qrecord a.patch 'tip'"
282 After qrecord a.patch 'tip'"
284
283
285 $ hg tip -p
284 $ hg tip -p
286 changeset: 1:5d1ca63427ee
285 changeset: 1:5d1ca63427ee
287 tag: a.patch
286 tag: a.patch
288 tag: qbase
287 tag: qbase
289 tag: qtip
288 tag: qtip
290 tag: tip
289 tag: tip
291 user: test
290 user: test
292 date: Thu Jan 01 00:00:00 1970 +0000
291 date: Thu Jan 01 00:00:00 1970 +0000
293 summary: aaa
292 summary: aaa
294
293
295 diff -r 1057167b20ef -r 5d1ca63427ee 1.txt
294 diff -r 1057167b20ef -r 5d1ca63427ee 1.txt
296 --- a/1.txt Thu Jan 01 00:00:00 1970 +0000
295 --- a/1.txt Thu Jan 01 00:00:00 1970 +0000
297 +++ b/1.txt Thu Jan 01 00:00:00 1970 +0000
296 +++ b/1.txt Thu Jan 01 00:00:00 1970 +0000
298 @@ -1,5 +1,5 @@
297 @@ -1,5 +1,5 @@
299 1
298 1
300 -2
299 -2
301 +2 2
300 +2 2
302 3
301 3
303 4
302 4
304 5
303 5
305 diff -r 1057167b20ef -r 5d1ca63427ee 2.txt
304 diff -r 1057167b20ef -r 5d1ca63427ee 2.txt
306 --- a/2.txt Thu Jan 01 00:00:00 1970 +0000
305 --- a/2.txt Thu Jan 01 00:00:00 1970 +0000
307 +++ b/2.txt Thu Jan 01 00:00:00 1970 +0000
306 +++ b/2.txt Thu Jan 01 00:00:00 1970 +0000
308 @@ -1,5 +1,5 @@
307 @@ -1,5 +1,5 @@
309 a
308 a
310 -b
309 -b
311 +b b
310 +b b
312 c
311 c
313 d
312 d
314 e
313 e
315
314
316
315
317 After qrecord a.patch 'diff'"
316 After qrecord a.patch 'diff'"
318
317
319 $ hg diff --nodates
318 $ hg diff --nodates
320 diff -r 5d1ca63427ee 1.txt
319 diff -r 5d1ca63427ee 1.txt
321 --- a/1.txt
320 --- a/1.txt
322 +++ b/1.txt
321 +++ b/1.txt
323 @@ -1,5 +1,5 @@
322 @@ -1,5 +1,5 @@
324 1
323 1
325 2 2
324 2 2
326 3
325 3
327 -4
326 -4
328 +4 4
327 +4 4
329 5
328 5
330 diff -r 5d1ca63427ee dir/a.txt
329 diff -r 5d1ca63427ee dir/a.txt
331 --- a/dir/a.txt
330 --- a/dir/a.txt
332 +++ b/dir/a.txt
331 +++ b/dir/a.txt
333 @@ -1,4 +1,4 @@
332 @@ -1,4 +1,4 @@
334 -hello world
333 -hello world
335 +hello world!
334 +hello world!
336
335
337 someone
336 someone
338 up
337 up
339
338
340 qrecord b.patch
339 qrecord b.patch
341
340
342 $ hg qrecord -d '0 0' -m bbb b.patch <<EOF
341 $ hg qrecord -d '0 0' -m bbb b.patch <<EOF
343 > y
342 > y
344 > y
343 > y
345 > y
344 > y
346 > y
345 > y
347 > EOF
346 > EOF
348 diff --git a/1.txt b/1.txt
347 diff --git a/1.txt b/1.txt
349 1 hunks, 1 lines changed
348 1 hunks, 1 lines changed
350 examine changes to '1.txt'? [Ynesfdaq?] y
349 examine changes to '1.txt'? [Ynesfdaq?] y
351
350
352 @@ -1,5 +1,5 @@
351 @@ -1,5 +1,5 @@
353 1
352 1
354 2 2
353 2 2
355 3
354 3
356 -4
355 -4
357 +4 4
356 +4 4
358 5
357 5
359 record change 1/2 to '1.txt'? [Ynesfdaq?] y
358 record change 1/2 to '1.txt'? [Ynesfdaq?] y
360
359
361 diff --git a/dir/a.txt b/dir/a.txt
360 diff --git a/dir/a.txt b/dir/a.txt
362 1 hunks, 1 lines changed
361 1 hunks, 1 lines changed
363 examine changes to 'dir/a.txt'? [Ynesfdaq?] y
362 examine changes to 'dir/a.txt'? [Ynesfdaq?] y
364
363
365 @@ -1,4 +1,4 @@
364 @@ -1,4 +1,4 @@
366 -hello world
365 -hello world
367 +hello world!
366 +hello world!
368
367
369 someone
368 someone
370 up
369 up
371 record change 2/2 to 'dir/a.txt'? [Ynesfdaq?] y
370 record change 2/2 to 'dir/a.txt'? [Ynesfdaq?] y
372
371
373
372
374 After qrecord b.patch 'tip'
373 After qrecord b.patch 'tip'
375
374
376 $ hg tip -p
375 $ hg tip -p
377 changeset: 2:b056198bf878
376 changeset: 2:b056198bf878
378 tag: b.patch
377 tag: b.patch
379 tag: qtip
378 tag: qtip
380 tag: tip
379 tag: tip
381 user: test
380 user: test
382 date: Thu Jan 01 00:00:00 1970 +0000
381 date: Thu Jan 01 00:00:00 1970 +0000
383 summary: bbb
382 summary: bbb
384
383
385 diff -r 5d1ca63427ee -r b056198bf878 1.txt
384 diff -r 5d1ca63427ee -r b056198bf878 1.txt
386 --- a/1.txt Thu Jan 01 00:00:00 1970 +0000
385 --- a/1.txt Thu Jan 01 00:00:00 1970 +0000
387 +++ b/1.txt Thu Jan 01 00:00:00 1970 +0000
386 +++ b/1.txt Thu Jan 01 00:00:00 1970 +0000
388 @@ -1,5 +1,5 @@
387 @@ -1,5 +1,5 @@
389 1
388 1
390 2 2
389 2 2
391 3
390 3
392 -4
391 -4
393 +4 4
392 +4 4
394 5
393 5
395 diff -r 5d1ca63427ee -r b056198bf878 dir/a.txt
394 diff -r 5d1ca63427ee -r b056198bf878 dir/a.txt
396 --- a/dir/a.txt Thu Jan 01 00:00:00 1970 +0000
395 --- a/dir/a.txt Thu Jan 01 00:00:00 1970 +0000
397 +++ b/dir/a.txt Thu Jan 01 00:00:00 1970 +0000
396 +++ b/dir/a.txt Thu Jan 01 00:00:00 1970 +0000
398 @@ -1,4 +1,4 @@
397 @@ -1,4 +1,4 @@
399 -hello world
398 -hello world
400 +hello world!
399 +hello world!
401
400
402 someone
401 someone
403 up
402 up
404
403
405
404
406 After qrecord b.patch 'diff'
405 After qrecord b.patch 'diff'
407
406
408 $ hg diff --nodates
407 $ hg diff --nodates
409
408
410 $ cd ..
409 $ cd ..
@@ -1,88 +1,87 b''
1 Set up a repo
1 Set up a repo
2
2
3 $ cat <<EOF >> $HGRCPATH
3 $ cat <<EOF >> $HGRCPATH
4 > [ui]
4 > [ui]
5 > interactive = true
5 > interactive = true
6 > [extensions]
6 > [extensions]
7 > record =
7 > record =
8 > EOF
8 > EOF
9
9
10 $ hg init a
10 $ hg init a
11 $ cd a
11 $ cd a
12
12
13 Record help
13 Record help
14
14
15 $ hg record -h
15 $ hg record -h
16 hg record [OPTION]... [FILE]...
16 hg record [OPTION]... [FILE]...
17
17
18 interactively select changes to commit
18 interactively select changes to commit
19
19
20 If a list of files is omitted, all changes reported by "hg status" will be
20 If a list of files is omitted, all changes reported by "hg status" will be
21 candidates for recording.
21 candidates for recording.
22
22
23 See "hg help dates" for a list of formats valid for -d/--date.
23 See "hg help dates" for a list of formats valid for -d/--date.
24
24
25 You will be prompted for whether to record changes to each modified file,
25 You will be prompted for whether to record changes to each modified file,
26 and for files with multiple changes, for each change to use. For each
26 and for files with multiple changes, for each change to use. For each
27 query, the following responses are possible:
27 query, the following responses are possible:
28
28
29 y - record this change
29 y - record this change
30 n - skip this change
30 n - skip this change
31 e - edit this change manually
31 e - edit this change manually
32
32
33 s - skip remaining changes to this file
33 s - skip remaining changes to this file
34 f - record remaining changes to this file
34 f - record remaining changes to this file
35
35
36 d - done, skip remaining changes and files
36 d - done, skip remaining changes and files
37 a - record all changes to all remaining files
37 a - record all changes to all remaining files
38 q - quit, recording no changes
38 q - quit, recording no changes
39
39
40 ? - display help
40 ? - display help
41
41
42 This command is not available when committing a merge.
42 This command is not available when committing a merge.
43
43
44 options ([+] can be repeated):
44 options ([+] can be repeated):
45
45
46 -A --addremove mark new/missing files as added/removed before
46 -A --addremove mark new/missing files as added/removed before
47 committing
47 committing
48 --close-branch mark a branch as closed, hiding it from the branch
48 --close-branch mark a branch head as closed
49 list
50 --amend amend the parent of the working directory
49 --amend amend the parent of the working directory
51 -s --secret use the secret phase for committing
50 -s --secret use the secret phase for committing
52 -e --edit invoke editor on commit messages
51 -e --edit invoke editor on commit messages
53 -I --include PATTERN [+] include names matching the given patterns
52 -I --include PATTERN [+] include names matching the given patterns
54 -X --exclude PATTERN [+] exclude names matching the given patterns
53 -X --exclude PATTERN [+] exclude names matching the given patterns
55 -m --message TEXT use text as commit message
54 -m --message TEXT use text as commit message
56 -l --logfile FILE read commit message from file
55 -l --logfile FILE read commit message from file
57 -d --date DATE record the specified date as commit date
56 -d --date DATE record the specified date as commit date
58 -u --user USER record the specified user as committer
57 -u --user USER record the specified user as committer
59 -S --subrepos recurse into subrepositories
58 -S --subrepos recurse into subrepositories
60 -w --ignore-all-space ignore white space when comparing lines
59 -w --ignore-all-space ignore white space when comparing lines
61 -b --ignore-space-change ignore changes in the amount of white space
60 -b --ignore-space-change ignore changes in the amount of white space
62 -B --ignore-blank-lines ignore changes whose lines are all blank
61 -B --ignore-blank-lines ignore changes whose lines are all blank
63
62
64 (some details hidden, use --verbose to show complete help)
63 (some details hidden, use --verbose to show complete help)
65
64
66 Select no files
65 Select no files
67
66
68 $ touch empty-rw
67 $ touch empty-rw
69 $ hg add empty-rw
68 $ hg add empty-rw
70
69
71 $ hg record empty-rw<<EOF
70 $ hg record empty-rw<<EOF
72 > n
71 > n
73 > EOF
72 > EOF
74 diff --git a/empty-rw b/empty-rw
73 diff --git a/empty-rw b/empty-rw
75 new file mode 100644
74 new file mode 100644
76 examine changes to 'empty-rw'? [Ynesfdaq?] n
75 examine changes to 'empty-rw'? [Ynesfdaq?] n
77
76
78 no changes to record
77 no changes to record
79
78
80 $ hg tip -p
79 $ hg tip -p
81 changeset: -1:000000000000
80 changeset: -1:000000000000
82 tag: tip
81 tag: tip
83 user:
82 user:
84 date: Thu Jan 01 00:00:00 1970 +0000
83 date: Thu Jan 01 00:00:00 1970 +0000
85
84
86
85
87
86
88
87
General Comments 0
You need to be logged in to leave comments. Login now