##// END OF EJS Templates
graft: record intermediate grafts in extras...
Durham Goode -
r24644:51930a71 default
parent child Browse files
Show More
@@ -1,6410 +1,6413 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 (DEPRECATED)'), _('TEMPLATE')),
108 _('display with template (DEPRECATED)'), _('TEMPLATE')),
109 ]
109 ]
110
110
111 templateopts = [
111 templateopts = [
112 ('', 'style', '',
112 ('', 'style', '',
113 _('display using template map file (DEPRECATED)'), _('STYLE')),
113 _('display using template map file (DEPRECATED)'), _('STYLE')),
114 ('T', 'template', '',
114 ('T', 'template', '',
115 _('display with template'), _('TEMPLATE')),
115 _('display with template'), _('TEMPLATE')),
116 ]
116 ]
117
117
118 logopts = [
118 logopts = [
119 ('p', 'patch', None, _('show patch')),
119 ('p', 'patch', None, _('show patch')),
120 ('g', 'git', None, _('use git extended diff format')),
120 ('g', 'git', None, _('use git extended diff format')),
121 ('l', 'limit', '',
121 ('l', 'limit', '',
122 _('limit number of changes displayed'), _('NUM')),
122 _('limit number of changes displayed'), _('NUM')),
123 ('M', 'no-merges', None, _('do not show merges')),
123 ('M', 'no-merges', None, _('do not show merges')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('', 'stat', None, _('output diffstat-style summary of changes')),
125 ('G', 'graph', None, _("show the revision DAG")),
125 ('G', 'graph', None, _("show the revision DAG")),
126 ] + templateopts
126 ] + templateopts
127
127
128 diffopts = [
128 diffopts = [
129 ('a', 'text', None, _('treat all files as text')),
129 ('a', 'text', None, _('treat all files as text')),
130 ('g', 'git', None, _('use git extended diff format')),
130 ('g', 'git', None, _('use git extended diff format')),
131 ('', 'nodates', None, _('omit dates from diff headers'))
131 ('', 'nodates', None, _('omit dates from diff headers'))
132 ]
132 ]
133
133
134 diffwsopts = [
134 diffwsopts = [
135 ('w', 'ignore-all-space', None,
135 ('w', 'ignore-all-space', None,
136 _('ignore white space when comparing lines')),
136 _('ignore white space when comparing lines')),
137 ('b', 'ignore-space-change', None,
137 ('b', 'ignore-space-change', None,
138 _('ignore changes in the amount of white space')),
138 _('ignore changes in the amount of white space')),
139 ('B', 'ignore-blank-lines', None,
139 ('B', 'ignore-blank-lines', None,
140 _('ignore changes whose lines are all blank')),
140 _('ignore changes whose lines are all blank')),
141 ]
141 ]
142
142
143 diffopts2 = [
143 diffopts2 = [
144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
144 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
145 ('p', 'show-function', None, _('show which function each change is in')),
145 ('p', 'show-function', None, _('show which function each change is in')),
146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
146 ('', 'reverse', None, _('produce a diff that undoes the changes')),
147 ] + diffwsopts + [
147 ] + diffwsopts + [
148 ('U', 'unified', '',
148 ('U', 'unified', '',
149 _('number of lines of context to show'), _('NUM')),
149 _('number of lines of context to show'), _('NUM')),
150 ('', 'stat', None, _('output diffstat-style summary of changes')),
150 ('', 'stat', None, _('output diffstat-style summary of changes')),
151 ('', '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 By default, annotate files in the parent of the working directory.
270 By default, annotate files in the parent of the working directory.
271 Use -r "wdir()" to annotate the working directory files.
271 Use -r "wdir()" to annotate the working directory files.
272
272
273 Returns 0 on success.
273 Returns 0 on success.
274 """
274 """
275 if not pats:
275 if not pats:
276 raise util.Abort(_('at least one filename or pattern is required'))
276 raise util.Abort(_('at least one filename or pattern is required'))
277
277
278 if opts.get('follow'):
278 if opts.get('follow'):
279 # --follow is deprecated and now just an alias for -f/--file
279 # --follow is deprecated and now just an alias for -f/--file
280 # to mimic the behavior of Mercurial before version 1.5
280 # to mimic the behavior of Mercurial before version 1.5
281 opts['file'] = True
281 opts['file'] = True
282
282
283 ctx = scmutil.revsingle(repo, opts.get('rev'))
283 ctx = scmutil.revsingle(repo, opts.get('rev'))
284
284
285 fm = ui.formatter('annotate', opts)
285 fm = ui.formatter('annotate', opts)
286 if ui.quiet:
286 if ui.quiet:
287 datefunc = util.shortdate
287 datefunc = util.shortdate
288 else:
288 else:
289 datefunc = util.datestr
289 datefunc = util.datestr
290 if ctx.rev() is None:
290 if ctx.rev() is None:
291 def hexfn(node):
291 def hexfn(node):
292 if node is None:
292 if node is None:
293 return None
293 return None
294 else:
294 else:
295 return fm.hexfunc(node)
295 return fm.hexfunc(node)
296 if opts.get('changeset'):
296 if opts.get('changeset'):
297 # omit "+" suffix which is appended to node hex
297 # omit "+" suffix which is appended to node hex
298 def formatrev(rev):
298 def formatrev(rev):
299 if rev is None:
299 if rev is None:
300 return '%d' % ctx.p1().rev()
300 return '%d' % ctx.p1().rev()
301 else:
301 else:
302 return '%d' % rev
302 return '%d' % rev
303 else:
303 else:
304 def formatrev(rev):
304 def formatrev(rev):
305 if rev is None:
305 if rev is None:
306 return '%d+' % ctx.p1().rev()
306 return '%d+' % ctx.p1().rev()
307 else:
307 else:
308 return '%d ' % rev
308 return '%d ' % rev
309 def formathex(hex):
309 def formathex(hex):
310 if hex is None:
310 if hex is None:
311 return '%s+' % fm.hexfunc(ctx.p1().node())
311 return '%s+' % fm.hexfunc(ctx.p1().node())
312 else:
312 else:
313 return '%s ' % hex
313 return '%s ' % hex
314 else:
314 else:
315 hexfn = fm.hexfunc
315 hexfn = fm.hexfunc
316 formatrev = formathex = str
316 formatrev = formathex = str
317
317
318 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
318 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
319 ('number', ' ', lambda x: x[0].rev(), formatrev),
319 ('number', ' ', lambda x: x[0].rev(), formatrev),
320 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
320 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
321 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
321 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
322 ('file', ' ', lambda x: x[0].path(), str),
322 ('file', ' ', lambda x: x[0].path(), str),
323 ('line_number', ':', lambda x: x[1], str),
323 ('line_number', ':', lambda x: x[1], str),
324 ]
324 ]
325 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
325 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
326
326
327 if (not opts.get('user') and not opts.get('changeset')
327 if (not opts.get('user') and not opts.get('changeset')
328 and not opts.get('date') and not opts.get('file')):
328 and not opts.get('date') and not opts.get('file')):
329 opts['number'] = True
329 opts['number'] = True
330
330
331 linenumber = opts.get('line_number') is not None
331 linenumber = opts.get('line_number') is not None
332 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
332 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
333 raise util.Abort(_('at least one of -n/-c is required for -l'))
333 raise util.Abort(_('at least one of -n/-c is required for -l'))
334
334
335 if fm:
335 if fm:
336 def makefunc(get, fmt):
336 def makefunc(get, fmt):
337 return get
337 return get
338 else:
338 else:
339 def makefunc(get, fmt):
339 def makefunc(get, fmt):
340 return lambda x: fmt(get(x))
340 return lambda x: fmt(get(x))
341 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
341 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
342 if opts.get(op)]
342 if opts.get(op)]
343 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
343 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
344 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
344 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
345 if opts.get(op))
345 if opts.get(op))
346
346
347 def bad(x, y):
347 def bad(x, y):
348 raise util.Abort("%s: %s" % (x, y))
348 raise util.Abort("%s: %s" % (x, y))
349
349
350 m = scmutil.match(ctx, pats, opts)
350 m = scmutil.match(ctx, pats, opts)
351 m.bad = bad
351 m.bad = bad
352 follow = not opts.get('no_follow')
352 follow = not opts.get('no_follow')
353 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
353 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
354 whitespace=True)
354 whitespace=True)
355 for abs in ctx.walk(m):
355 for abs in ctx.walk(m):
356 fctx = ctx[abs]
356 fctx = ctx[abs]
357 if not opts.get('text') and util.binary(fctx.data()):
357 if not opts.get('text') and util.binary(fctx.data()):
358 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
358 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
359 continue
359 continue
360
360
361 lines = fctx.annotate(follow=follow, linenumber=linenumber,
361 lines = fctx.annotate(follow=follow, linenumber=linenumber,
362 diffopts=diffopts)
362 diffopts=diffopts)
363 formats = []
363 formats = []
364 pieces = []
364 pieces = []
365
365
366 for f, sep in funcmap:
366 for f, sep in funcmap:
367 l = [f(n) for n, dummy in lines]
367 l = [f(n) for n, dummy in lines]
368 if l:
368 if l:
369 if fm:
369 if fm:
370 formats.append(['%s' for x in l])
370 formats.append(['%s' for x in l])
371 else:
371 else:
372 sizes = [encoding.colwidth(x) for x in l]
372 sizes = [encoding.colwidth(x) for x in l]
373 ml = max(sizes)
373 ml = max(sizes)
374 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
374 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
375 pieces.append(l)
375 pieces.append(l)
376
376
377 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
377 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
378 fm.startitem()
378 fm.startitem()
379 fm.write(fields, "".join(f), *p)
379 fm.write(fields, "".join(f), *p)
380 fm.write('line', ": %s", l[1])
380 fm.write('line', ": %s", l[1])
381
381
382 if lines and not lines[-1][1].endswith('\n'):
382 if lines and not lines[-1][1].endswith('\n'):
383 fm.plain('\n')
383 fm.plain('\n')
384
384
385 fm.end()
385 fm.end()
386
386
387 @command('archive',
387 @command('archive',
388 [('', 'no-decode', None, _('do not pass files through decoders')),
388 [('', 'no-decode', None, _('do not pass files through decoders')),
389 ('p', 'prefix', '', _('directory prefix for files in archive'),
389 ('p', 'prefix', '', _('directory prefix for files in archive'),
390 _('PREFIX')),
390 _('PREFIX')),
391 ('r', 'rev', '', _('revision to distribute'), _('REV')),
391 ('r', 'rev', '', _('revision to distribute'), _('REV')),
392 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
392 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
393 ] + subrepoopts + walkopts,
393 ] + subrepoopts + walkopts,
394 _('[OPTION]... DEST'))
394 _('[OPTION]... DEST'))
395 def archive(ui, repo, dest, **opts):
395 def archive(ui, repo, dest, **opts):
396 '''create an unversioned archive of a repository revision
396 '''create an unversioned archive of a repository revision
397
397
398 By default, the revision used is the parent of the working
398 By default, the revision used is the parent of the working
399 directory; use -r/--rev to specify a different revision.
399 directory; use -r/--rev to specify a different revision.
400
400
401 The archive type is automatically detected based on file
401 The archive type is automatically detected based on file
402 extension (or override using -t/--type).
402 extension (or override using -t/--type).
403
403
404 .. container:: verbose
404 .. container:: verbose
405
405
406 Examples:
406 Examples:
407
407
408 - create a zip file containing the 1.0 release::
408 - create a zip file containing the 1.0 release::
409
409
410 hg archive -r 1.0 project-1.0.zip
410 hg archive -r 1.0 project-1.0.zip
411
411
412 - create a tarball excluding .hg files::
412 - create a tarball excluding .hg files::
413
413
414 hg archive project.tar.gz -X ".hg*"
414 hg archive project.tar.gz -X ".hg*"
415
415
416 Valid types are:
416 Valid types are:
417
417
418 :``files``: a directory full of files (default)
418 :``files``: a directory full of files (default)
419 :``tar``: tar archive, uncompressed
419 :``tar``: tar archive, uncompressed
420 :``tbz2``: tar archive, compressed using bzip2
420 :``tbz2``: tar archive, compressed using bzip2
421 :``tgz``: tar archive, compressed using gzip
421 :``tgz``: tar archive, compressed using gzip
422 :``uzip``: zip archive, uncompressed
422 :``uzip``: zip archive, uncompressed
423 :``zip``: zip archive, compressed using deflate
423 :``zip``: zip archive, compressed using deflate
424
424
425 The exact name of the destination archive or directory is given
425 The exact name of the destination archive or directory is given
426 using a format string; see :hg:`help export` for details.
426 using a format string; see :hg:`help export` for details.
427
427
428 Each member added to an archive file has a directory prefix
428 Each member added to an archive file has a directory prefix
429 prepended. Use -p/--prefix to specify a format string for the
429 prepended. Use -p/--prefix to specify a format string for the
430 prefix. The default is the basename of the archive, with suffixes
430 prefix. The default is the basename of the archive, with suffixes
431 removed.
431 removed.
432
432
433 Returns 0 on success.
433 Returns 0 on success.
434 '''
434 '''
435
435
436 ctx = scmutil.revsingle(repo, opts.get('rev'))
436 ctx = scmutil.revsingle(repo, opts.get('rev'))
437 if not ctx:
437 if not ctx:
438 raise util.Abort(_('no working directory: please specify a revision'))
438 raise util.Abort(_('no working directory: please specify a revision'))
439 node = ctx.node()
439 node = ctx.node()
440 dest = cmdutil.makefilename(repo, dest, node)
440 dest = cmdutil.makefilename(repo, dest, node)
441 if os.path.realpath(dest) == repo.root:
441 if os.path.realpath(dest) == repo.root:
442 raise util.Abort(_('repository root cannot be destination'))
442 raise util.Abort(_('repository root cannot be destination'))
443
443
444 kind = opts.get('type') or archival.guesskind(dest) or 'files'
444 kind = opts.get('type') or archival.guesskind(dest) or 'files'
445 prefix = opts.get('prefix')
445 prefix = opts.get('prefix')
446
446
447 if dest == '-':
447 if dest == '-':
448 if kind == 'files':
448 if kind == 'files':
449 raise util.Abort(_('cannot archive plain files to stdout'))
449 raise util.Abort(_('cannot archive plain files to stdout'))
450 dest = cmdutil.makefileobj(repo, dest)
450 dest = cmdutil.makefileobj(repo, dest)
451 if not prefix:
451 if not prefix:
452 prefix = os.path.basename(repo.root) + '-%h'
452 prefix = os.path.basename(repo.root) + '-%h'
453
453
454 prefix = cmdutil.makefilename(repo, prefix, node)
454 prefix = cmdutil.makefilename(repo, prefix, node)
455 matchfn = scmutil.match(ctx, [], opts)
455 matchfn = scmutil.match(ctx, [], opts)
456 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
456 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
457 matchfn, prefix, subrepos=opts.get('subrepos'))
457 matchfn, prefix, subrepos=opts.get('subrepos'))
458
458
459 @command('backout',
459 @command('backout',
460 [('', 'merge', None, _('merge with old dirstate parent after backout')),
460 [('', 'merge', None, _('merge with old dirstate parent after backout')),
461 ('', 'commit', None, _('commit if no conflicts were encountered')),
461 ('', 'commit', None, _('commit if no conflicts were encountered')),
462 ('', 'parent', '',
462 ('', 'parent', '',
463 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
463 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
464 ('r', 'rev', '', _('revision to backout'), _('REV')),
464 ('r', 'rev', '', _('revision to backout'), _('REV')),
465 ('e', 'edit', False, _('invoke editor on commit messages')),
465 ('e', 'edit', False, _('invoke editor on commit messages')),
466 ] + mergetoolopts + walkopts + commitopts + commitopts2,
466 ] + mergetoolopts + walkopts + commitopts + commitopts2,
467 _('[OPTION]... [-r] REV'))
467 _('[OPTION]... [-r] REV'))
468 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
468 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
469 '''reverse effect of earlier changeset
469 '''reverse effect of earlier changeset
470
470
471 Prepare a new changeset with the effect of REV undone in the
471 Prepare a new changeset with the effect of REV undone in the
472 current working directory.
472 current working directory.
473
473
474 If REV is the parent of the working directory, then this new changeset
474 If REV is the parent of the working directory, then this new changeset
475 is committed automatically. Otherwise, hg needs to merge the
475 is committed automatically. Otherwise, hg needs to merge the
476 changes and the merged result is left uncommitted.
476 changes and the merged result is left uncommitted.
477
477
478 .. note::
478 .. note::
479
479
480 backout cannot be used to fix either an unwanted or
480 backout cannot be used to fix either an unwanted or
481 incorrect merge.
481 incorrect merge.
482
482
483 .. container:: verbose
483 .. container:: verbose
484
484
485 By default, the pending changeset will have one parent,
485 By default, the pending changeset will have one parent,
486 maintaining a linear history. With --merge, the pending
486 maintaining a linear history. With --merge, the pending
487 changeset will instead have two parents: the old parent of the
487 changeset will instead have two parents: the old parent of the
488 working directory and a new child of REV that simply undoes REV.
488 working directory and a new child of REV that simply undoes REV.
489
489
490 Before version 1.7, the behavior without --merge was equivalent
490 Before version 1.7, the behavior without --merge was equivalent
491 to specifying --merge followed by :hg:`update --clean .` to
491 to specifying --merge followed by :hg:`update --clean .` to
492 cancel the merge and leave the child of REV as a head to be
492 cancel the merge and leave the child of REV as a head to be
493 merged separately.
493 merged separately.
494
494
495 See :hg:`help dates` for a list of formats valid for -d/--date.
495 See :hg:`help dates` for a list of formats valid for -d/--date.
496
496
497 Returns 0 on success, 1 if nothing to backout or there are unresolved
497 Returns 0 on success, 1 if nothing to backout or there are unresolved
498 files.
498 files.
499 '''
499 '''
500 if rev and node:
500 if rev and node:
501 raise util.Abort(_("please specify just one revision"))
501 raise util.Abort(_("please specify just one revision"))
502
502
503 if not rev:
503 if not rev:
504 rev = node
504 rev = node
505
505
506 if not rev:
506 if not rev:
507 raise util.Abort(_("please specify a revision to backout"))
507 raise util.Abort(_("please specify a revision to backout"))
508
508
509 date = opts.get('date')
509 date = opts.get('date')
510 if date:
510 if date:
511 opts['date'] = util.parsedate(date)
511 opts['date'] = util.parsedate(date)
512
512
513 cmdutil.checkunfinished(repo)
513 cmdutil.checkunfinished(repo)
514 cmdutil.bailifchanged(repo)
514 cmdutil.bailifchanged(repo)
515 node = scmutil.revsingle(repo, rev).node()
515 node = scmutil.revsingle(repo, rev).node()
516
516
517 op1, op2 = repo.dirstate.parents()
517 op1, op2 = repo.dirstate.parents()
518 if not repo.changelog.isancestor(node, op1):
518 if not repo.changelog.isancestor(node, op1):
519 raise util.Abort(_('cannot backout change that is not an ancestor'))
519 raise util.Abort(_('cannot backout change that is not an ancestor'))
520
520
521 p1, p2 = repo.changelog.parents(node)
521 p1, p2 = repo.changelog.parents(node)
522 if p1 == nullid:
522 if p1 == nullid:
523 raise util.Abort(_('cannot backout a change with no parents'))
523 raise util.Abort(_('cannot backout a change with no parents'))
524 if p2 != nullid:
524 if p2 != nullid:
525 if not opts.get('parent'):
525 if not opts.get('parent'):
526 raise util.Abort(_('cannot backout a merge changeset'))
526 raise util.Abort(_('cannot backout a merge changeset'))
527 p = repo.lookup(opts['parent'])
527 p = repo.lookup(opts['parent'])
528 if p not in (p1, p2):
528 if p not in (p1, p2):
529 raise util.Abort(_('%s is not a parent of %s') %
529 raise util.Abort(_('%s is not a parent of %s') %
530 (short(p), short(node)))
530 (short(p), short(node)))
531 parent = p
531 parent = p
532 else:
532 else:
533 if opts.get('parent'):
533 if opts.get('parent'):
534 raise util.Abort(_('cannot use --parent on non-merge changeset'))
534 raise util.Abort(_('cannot use --parent on non-merge changeset'))
535 parent = p1
535 parent = p1
536
536
537 # the backout should appear on the same branch
537 # the backout should appear on the same branch
538 wlock = repo.wlock()
538 wlock = repo.wlock()
539 try:
539 try:
540 branch = repo.dirstate.branch()
540 branch = repo.dirstate.branch()
541 bheads = repo.branchheads(branch)
541 bheads = repo.branchheads(branch)
542 rctx = scmutil.revsingle(repo, hex(parent))
542 rctx = scmutil.revsingle(repo, hex(parent))
543 if not opts.get('merge') and op1 != node:
543 if not opts.get('merge') and op1 != node:
544 try:
544 try:
545 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
545 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
546 'backout')
546 'backout')
547 repo.dirstate.beginparentchange()
547 repo.dirstate.beginparentchange()
548 stats = mergemod.update(repo, parent, True, True, False,
548 stats = mergemod.update(repo, parent, True, True, False,
549 node, False)
549 node, False)
550 repo.setparents(op1, op2)
550 repo.setparents(op1, op2)
551 repo.dirstate.endparentchange()
551 repo.dirstate.endparentchange()
552 hg._showstats(repo, stats)
552 hg._showstats(repo, stats)
553 if stats[3]:
553 if stats[3]:
554 repo.ui.status(_("use 'hg resolve' to retry unresolved "
554 repo.ui.status(_("use 'hg resolve' to retry unresolved "
555 "file merges\n"))
555 "file merges\n"))
556 return 1
556 return 1
557 elif not commit:
557 elif not commit:
558 msg = _("changeset %s backed out, "
558 msg = _("changeset %s backed out, "
559 "don't forget to commit.\n")
559 "don't forget to commit.\n")
560 ui.status(msg % short(node))
560 ui.status(msg % short(node))
561 return 0
561 return 0
562 finally:
562 finally:
563 ui.setconfig('ui', 'forcemerge', '', '')
563 ui.setconfig('ui', 'forcemerge', '', '')
564 else:
564 else:
565 hg.clean(repo, node, show_stats=False)
565 hg.clean(repo, node, show_stats=False)
566 repo.dirstate.setbranch(branch)
566 repo.dirstate.setbranch(branch)
567 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
567 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
568
568
569
569
570 def commitfunc(ui, repo, message, match, opts):
570 def commitfunc(ui, repo, message, match, opts):
571 editform = 'backout'
571 editform = 'backout'
572 e = cmdutil.getcommiteditor(editform=editform, **opts)
572 e = cmdutil.getcommiteditor(editform=editform, **opts)
573 if not message:
573 if not message:
574 # we don't translate commit messages
574 # we don't translate commit messages
575 message = "Backed out changeset %s" % short(node)
575 message = "Backed out changeset %s" % short(node)
576 e = cmdutil.getcommiteditor(edit=True, editform=editform)
576 e = cmdutil.getcommiteditor(edit=True, editform=editform)
577 return repo.commit(message, opts.get('user'), opts.get('date'),
577 return repo.commit(message, opts.get('user'), opts.get('date'),
578 match, editor=e)
578 match, editor=e)
579 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
579 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
580 if not newnode:
580 if not newnode:
581 ui.status(_("nothing changed\n"))
581 ui.status(_("nothing changed\n"))
582 return 1
582 return 1
583 cmdutil.commitstatus(repo, newnode, branch, bheads)
583 cmdutil.commitstatus(repo, newnode, branch, bheads)
584
584
585 def nice(node):
585 def nice(node):
586 return '%d:%s' % (repo.changelog.rev(node), short(node))
586 return '%d:%s' % (repo.changelog.rev(node), short(node))
587 ui.status(_('changeset %s backs out changeset %s\n') %
587 ui.status(_('changeset %s backs out changeset %s\n') %
588 (nice(repo.changelog.tip()), nice(node)))
588 (nice(repo.changelog.tip()), nice(node)))
589 if opts.get('merge') and op1 != node:
589 if opts.get('merge') and op1 != node:
590 hg.clean(repo, op1, show_stats=False)
590 hg.clean(repo, op1, show_stats=False)
591 ui.status(_('merging with changeset %s\n')
591 ui.status(_('merging with changeset %s\n')
592 % nice(repo.changelog.tip()))
592 % nice(repo.changelog.tip()))
593 try:
593 try:
594 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
594 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
595 'backout')
595 'backout')
596 return hg.merge(repo, hex(repo.changelog.tip()))
596 return hg.merge(repo, hex(repo.changelog.tip()))
597 finally:
597 finally:
598 ui.setconfig('ui', 'forcemerge', '', '')
598 ui.setconfig('ui', 'forcemerge', '', '')
599 finally:
599 finally:
600 wlock.release()
600 wlock.release()
601 return 0
601 return 0
602
602
603 @command('bisect',
603 @command('bisect',
604 [('r', 'reset', False, _('reset bisect state')),
604 [('r', 'reset', False, _('reset bisect state')),
605 ('g', 'good', False, _('mark changeset good')),
605 ('g', 'good', False, _('mark changeset good')),
606 ('b', 'bad', False, _('mark changeset bad')),
606 ('b', 'bad', False, _('mark changeset bad')),
607 ('s', 'skip', False, _('skip testing changeset')),
607 ('s', 'skip', False, _('skip testing changeset')),
608 ('e', 'extend', False, _('extend the bisect range')),
608 ('e', 'extend', False, _('extend the bisect range')),
609 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
609 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
610 ('U', 'noupdate', False, _('do not update to target'))],
610 ('U', 'noupdate', False, _('do not update to target'))],
611 _("[-gbsr] [-U] [-c CMD] [REV]"))
611 _("[-gbsr] [-U] [-c CMD] [REV]"))
612 def bisect(ui, repo, rev=None, extra=None, command=None,
612 def bisect(ui, repo, rev=None, extra=None, command=None,
613 reset=None, good=None, bad=None, skip=None, extend=None,
613 reset=None, good=None, bad=None, skip=None, extend=None,
614 noupdate=None):
614 noupdate=None):
615 """subdivision search of changesets
615 """subdivision search of changesets
616
616
617 This command helps to find changesets which introduce problems. To
617 This command helps to find changesets which introduce problems. To
618 use, mark the earliest changeset you know exhibits the problem as
618 use, mark the earliest changeset you know exhibits the problem as
619 bad, then mark the latest changeset which is free from the problem
619 bad, then mark the latest changeset which is free from the problem
620 as good. Bisect will update your working directory to a revision
620 as good. Bisect will update your working directory to a revision
621 for testing (unless the -U/--noupdate option is specified). Once
621 for testing (unless the -U/--noupdate option is specified). Once
622 you have performed tests, mark the working directory as good or
622 you have performed tests, mark the working directory as good or
623 bad, and bisect will either update to another candidate changeset
623 bad, and bisect will either update to another candidate changeset
624 or announce that it has found the bad revision.
624 or announce that it has found the bad revision.
625
625
626 As a shortcut, you can also use the revision argument to mark a
626 As a shortcut, you can also use the revision argument to mark a
627 revision as good or bad without checking it out first.
627 revision as good or bad without checking it out first.
628
628
629 If you supply a command, it will be used for automatic bisection.
629 If you supply a command, it will be used for automatic bisection.
630 The environment variable HG_NODE will contain the ID of the
630 The environment variable HG_NODE will contain the ID of the
631 changeset being tested. The exit status of the command will be
631 changeset being tested. The exit status of the command will be
632 used to mark revisions as good or bad: status 0 means good, 125
632 used to mark revisions as good or bad: status 0 means good, 125
633 means to skip the revision, 127 (command not found) will abort the
633 means to skip the revision, 127 (command not found) will abort the
634 bisection, and any other non-zero exit status means the revision
634 bisection, and any other non-zero exit status means the revision
635 is bad.
635 is bad.
636
636
637 .. container:: verbose
637 .. container:: verbose
638
638
639 Some examples:
639 Some examples:
640
640
641 - start a bisection with known bad revision 34, and good revision 12::
641 - start a bisection with known bad revision 34, and good revision 12::
642
642
643 hg bisect --bad 34
643 hg bisect --bad 34
644 hg bisect --good 12
644 hg bisect --good 12
645
645
646 - advance the current bisection by marking current revision as good or
646 - advance the current bisection by marking current revision as good or
647 bad::
647 bad::
648
648
649 hg bisect --good
649 hg bisect --good
650 hg bisect --bad
650 hg bisect --bad
651
651
652 - mark the current revision, or a known revision, to be skipped (e.g. if
652 - mark the current revision, or a known revision, to be skipped (e.g. if
653 that revision is not usable because of another issue)::
653 that revision is not usable because of another issue)::
654
654
655 hg bisect --skip
655 hg bisect --skip
656 hg bisect --skip 23
656 hg bisect --skip 23
657
657
658 - skip all revisions that do not touch directories ``foo`` or ``bar``::
658 - skip all revisions that do not touch directories ``foo`` or ``bar``::
659
659
660 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
660 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
661
661
662 - forget the current bisection::
662 - forget the current bisection::
663
663
664 hg bisect --reset
664 hg bisect --reset
665
665
666 - use 'make && make tests' to automatically find the first broken
666 - use 'make && make tests' to automatically find the first broken
667 revision::
667 revision::
668
668
669 hg bisect --reset
669 hg bisect --reset
670 hg bisect --bad 34
670 hg bisect --bad 34
671 hg bisect --good 12
671 hg bisect --good 12
672 hg bisect --command "make && make tests"
672 hg bisect --command "make && make tests"
673
673
674 - see all changesets whose states are already known in the current
674 - see all changesets whose states are already known in the current
675 bisection::
675 bisection::
676
676
677 hg log -r "bisect(pruned)"
677 hg log -r "bisect(pruned)"
678
678
679 - see the changeset currently being bisected (especially useful
679 - see the changeset currently being bisected (especially useful
680 if running with -U/--noupdate)::
680 if running with -U/--noupdate)::
681
681
682 hg log -r "bisect(current)"
682 hg log -r "bisect(current)"
683
683
684 - see all changesets that took part in the current bisection::
684 - see all changesets that took part in the current bisection::
685
685
686 hg log -r "bisect(range)"
686 hg log -r "bisect(range)"
687
687
688 - you can even get a nice graph::
688 - you can even get a nice graph::
689
689
690 hg log --graph -r "bisect(range)"
690 hg log --graph -r "bisect(range)"
691
691
692 See :hg:`help revsets` for more about the `bisect()` keyword.
692 See :hg:`help revsets` for more about the `bisect()` keyword.
693
693
694 Returns 0 on success.
694 Returns 0 on success.
695 """
695 """
696 def extendbisectrange(nodes, good):
696 def extendbisectrange(nodes, good):
697 # bisect is incomplete when it ends on a merge node and
697 # bisect is incomplete when it ends on a merge node and
698 # one of the parent was not checked.
698 # one of the parent was not checked.
699 parents = repo[nodes[0]].parents()
699 parents = repo[nodes[0]].parents()
700 if len(parents) > 1:
700 if len(parents) > 1:
701 if good:
701 if good:
702 side = state['bad']
702 side = state['bad']
703 else:
703 else:
704 side = state['good']
704 side = state['good']
705 num = len(set(i.node() for i in parents) & set(side))
705 num = len(set(i.node() for i in parents) & set(side))
706 if num == 1:
706 if num == 1:
707 return parents[0].ancestor(parents[1])
707 return parents[0].ancestor(parents[1])
708 return None
708 return None
709
709
710 def print_result(nodes, good):
710 def print_result(nodes, good):
711 displayer = cmdutil.show_changeset(ui, repo, {})
711 displayer = cmdutil.show_changeset(ui, repo, {})
712 if len(nodes) == 1:
712 if len(nodes) == 1:
713 # narrowed it down to a single revision
713 # narrowed it down to a single revision
714 if good:
714 if good:
715 ui.write(_("The first good revision is:\n"))
715 ui.write(_("The first good revision is:\n"))
716 else:
716 else:
717 ui.write(_("The first bad revision is:\n"))
717 ui.write(_("The first bad revision is:\n"))
718 displayer.show(repo[nodes[0]])
718 displayer.show(repo[nodes[0]])
719 extendnode = extendbisectrange(nodes, good)
719 extendnode = extendbisectrange(nodes, good)
720 if extendnode is not None:
720 if extendnode is not None:
721 ui.write(_('Not all ancestors of this changeset have been'
721 ui.write(_('Not all ancestors of this changeset have been'
722 ' checked.\nUse bisect --extend to continue the '
722 ' checked.\nUse bisect --extend to continue the '
723 'bisection from\nthe common ancestor, %s.\n')
723 'bisection from\nthe common ancestor, %s.\n')
724 % extendnode)
724 % extendnode)
725 else:
725 else:
726 # multiple possible revisions
726 # multiple possible revisions
727 if good:
727 if good:
728 ui.write(_("Due to skipped revisions, the first "
728 ui.write(_("Due to skipped revisions, the first "
729 "good revision could be any of:\n"))
729 "good revision could be any of:\n"))
730 else:
730 else:
731 ui.write(_("Due to skipped revisions, the first "
731 ui.write(_("Due to skipped revisions, the first "
732 "bad revision could be any of:\n"))
732 "bad revision could be any of:\n"))
733 for n in nodes:
733 for n in nodes:
734 displayer.show(repo[n])
734 displayer.show(repo[n])
735 displayer.close()
735 displayer.close()
736
736
737 def check_state(state, interactive=True):
737 def check_state(state, interactive=True):
738 if not state['good'] or not state['bad']:
738 if not state['good'] or not state['bad']:
739 if (good or bad or skip or reset) and interactive:
739 if (good or bad or skip or reset) and interactive:
740 return
740 return
741 if not state['good']:
741 if not state['good']:
742 raise util.Abort(_('cannot bisect (no known good revisions)'))
742 raise util.Abort(_('cannot bisect (no known good revisions)'))
743 else:
743 else:
744 raise util.Abort(_('cannot bisect (no known bad revisions)'))
744 raise util.Abort(_('cannot bisect (no known bad revisions)'))
745 return True
745 return True
746
746
747 # backward compatibility
747 # backward compatibility
748 if rev in "good bad reset init".split():
748 if rev in "good bad reset init".split():
749 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
749 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
750 cmd, rev, extra = rev, extra, None
750 cmd, rev, extra = rev, extra, None
751 if cmd == "good":
751 if cmd == "good":
752 good = True
752 good = True
753 elif cmd == "bad":
753 elif cmd == "bad":
754 bad = True
754 bad = True
755 else:
755 else:
756 reset = True
756 reset = True
757 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
757 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
758 raise util.Abort(_('incompatible arguments'))
758 raise util.Abort(_('incompatible arguments'))
759
759
760 cmdutil.checkunfinished(repo)
760 cmdutil.checkunfinished(repo)
761
761
762 if reset:
762 if reset:
763 p = repo.join("bisect.state")
763 p = repo.join("bisect.state")
764 if os.path.exists(p):
764 if os.path.exists(p):
765 os.unlink(p)
765 os.unlink(p)
766 return
766 return
767
767
768 state = hbisect.load_state(repo)
768 state = hbisect.load_state(repo)
769
769
770 if command:
770 if command:
771 changesets = 1
771 changesets = 1
772 if noupdate:
772 if noupdate:
773 try:
773 try:
774 node = state['current'][0]
774 node = state['current'][0]
775 except LookupError:
775 except LookupError:
776 raise util.Abort(_('current bisect revision is unknown - '
776 raise util.Abort(_('current bisect revision is unknown - '
777 'start a new bisect to fix'))
777 'start a new bisect to fix'))
778 else:
778 else:
779 node, p2 = repo.dirstate.parents()
779 node, p2 = repo.dirstate.parents()
780 if p2 != nullid:
780 if p2 != nullid:
781 raise util.Abort(_('current bisect revision is a merge'))
781 raise util.Abort(_('current bisect revision is a merge'))
782 try:
782 try:
783 while changesets:
783 while changesets:
784 # update state
784 # update state
785 state['current'] = [node]
785 state['current'] = [node]
786 hbisect.save_state(repo, state)
786 hbisect.save_state(repo, state)
787 status = ui.system(command, environ={'HG_NODE': hex(node)})
787 status = ui.system(command, environ={'HG_NODE': hex(node)})
788 if status == 125:
788 if status == 125:
789 transition = "skip"
789 transition = "skip"
790 elif status == 0:
790 elif status == 0:
791 transition = "good"
791 transition = "good"
792 # status < 0 means process was killed
792 # status < 0 means process was killed
793 elif status == 127:
793 elif status == 127:
794 raise util.Abort(_("failed to execute %s") % command)
794 raise util.Abort(_("failed to execute %s") % command)
795 elif status < 0:
795 elif status < 0:
796 raise util.Abort(_("%s killed") % command)
796 raise util.Abort(_("%s killed") % command)
797 else:
797 else:
798 transition = "bad"
798 transition = "bad"
799 ctx = scmutil.revsingle(repo, rev, node)
799 ctx = scmutil.revsingle(repo, rev, node)
800 rev = None # clear for future iterations
800 rev = None # clear for future iterations
801 state[transition].append(ctx.node())
801 state[transition].append(ctx.node())
802 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
802 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
803 check_state(state, interactive=False)
803 check_state(state, interactive=False)
804 # bisect
804 # bisect
805 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
805 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
806 # update to next check
806 # update to next check
807 node = nodes[0]
807 node = nodes[0]
808 if not noupdate:
808 if not noupdate:
809 cmdutil.bailifchanged(repo)
809 cmdutil.bailifchanged(repo)
810 hg.clean(repo, node, show_stats=False)
810 hg.clean(repo, node, show_stats=False)
811 finally:
811 finally:
812 state['current'] = [node]
812 state['current'] = [node]
813 hbisect.save_state(repo, state)
813 hbisect.save_state(repo, state)
814 print_result(nodes, bgood)
814 print_result(nodes, bgood)
815 return
815 return
816
816
817 # update state
817 # update state
818
818
819 if rev:
819 if rev:
820 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
820 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
821 else:
821 else:
822 nodes = [repo.lookup('.')]
822 nodes = [repo.lookup('.')]
823
823
824 if good or bad or skip:
824 if good or bad or skip:
825 if good:
825 if good:
826 state['good'] += nodes
826 state['good'] += nodes
827 elif bad:
827 elif bad:
828 state['bad'] += nodes
828 state['bad'] += nodes
829 elif skip:
829 elif skip:
830 state['skip'] += nodes
830 state['skip'] += nodes
831 hbisect.save_state(repo, state)
831 hbisect.save_state(repo, state)
832
832
833 if not check_state(state):
833 if not check_state(state):
834 return
834 return
835
835
836 # actually bisect
836 # actually bisect
837 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
837 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
838 if extend:
838 if extend:
839 if not changesets:
839 if not changesets:
840 extendnode = extendbisectrange(nodes, good)
840 extendnode = extendbisectrange(nodes, good)
841 if extendnode is not None:
841 if extendnode is not None:
842 ui.write(_("Extending search to changeset %d:%s\n")
842 ui.write(_("Extending search to changeset %d:%s\n")
843 % (extendnode.rev(), extendnode))
843 % (extendnode.rev(), extendnode))
844 state['current'] = [extendnode.node()]
844 state['current'] = [extendnode.node()]
845 hbisect.save_state(repo, state)
845 hbisect.save_state(repo, state)
846 if noupdate:
846 if noupdate:
847 return
847 return
848 cmdutil.bailifchanged(repo)
848 cmdutil.bailifchanged(repo)
849 return hg.clean(repo, extendnode.node())
849 return hg.clean(repo, extendnode.node())
850 raise util.Abort(_("nothing to extend"))
850 raise util.Abort(_("nothing to extend"))
851
851
852 if changesets == 0:
852 if changesets == 0:
853 print_result(nodes, good)
853 print_result(nodes, good)
854 else:
854 else:
855 assert len(nodes) == 1 # only a single node can be tested next
855 assert len(nodes) == 1 # only a single node can be tested next
856 node = nodes[0]
856 node = nodes[0]
857 # compute the approximate number of remaining tests
857 # compute the approximate number of remaining tests
858 tests, size = 0, 2
858 tests, size = 0, 2
859 while size <= changesets:
859 while size <= changesets:
860 tests, size = tests + 1, size * 2
860 tests, size = tests + 1, size * 2
861 rev = repo.changelog.rev(node)
861 rev = repo.changelog.rev(node)
862 ui.write(_("Testing changeset %d:%s "
862 ui.write(_("Testing changeset %d:%s "
863 "(%d changesets remaining, ~%d tests)\n")
863 "(%d changesets remaining, ~%d tests)\n")
864 % (rev, short(node), changesets, tests))
864 % (rev, short(node), changesets, tests))
865 state['current'] = [node]
865 state['current'] = [node]
866 hbisect.save_state(repo, state)
866 hbisect.save_state(repo, state)
867 if not noupdate:
867 if not noupdate:
868 cmdutil.bailifchanged(repo)
868 cmdutil.bailifchanged(repo)
869 return hg.clean(repo, node)
869 return hg.clean(repo, node)
870
870
871 @command('bookmarks|bookmark',
871 @command('bookmarks|bookmark',
872 [('f', 'force', False, _('force')),
872 [('f', 'force', False, _('force')),
873 ('r', 'rev', '', _('revision'), _('REV')),
873 ('r', 'rev', '', _('revision'), _('REV')),
874 ('d', 'delete', False, _('delete a given bookmark')),
874 ('d', 'delete', False, _('delete a given bookmark')),
875 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
875 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
876 ('i', 'inactive', False, _('mark a bookmark inactive')),
876 ('i', 'inactive', False, _('mark a bookmark inactive')),
877 ] + formatteropts,
877 ] + formatteropts,
878 _('hg bookmarks [OPTIONS]... [NAME]...'))
878 _('hg bookmarks [OPTIONS]... [NAME]...'))
879 def bookmark(ui, repo, *names, **opts):
879 def bookmark(ui, repo, *names, **opts):
880 '''create a new bookmark or list existing bookmarks
880 '''create a new bookmark or list existing bookmarks
881
881
882 Bookmarks are labels on changesets to help track lines of development.
882 Bookmarks are labels on changesets to help track lines of development.
883 Bookmarks are unversioned and can be moved, renamed and deleted.
883 Bookmarks are unversioned and can be moved, renamed and deleted.
884 Deleting or moving a bookmark has no effect on the associated changesets.
884 Deleting or moving a bookmark has no effect on the associated changesets.
885
885
886 Creating or updating to a bookmark causes it to be marked as 'active'.
886 Creating or updating to a bookmark causes it to be marked as 'active'.
887 The active bookmark is indicated with a '*'.
887 The active bookmark is indicated with a '*'.
888 When a commit is made, the active bookmark will advance to the new commit.
888 When a commit is made, the active bookmark will advance to the new commit.
889 A plain :hg:`update` will also advance an active bookmark, if possible.
889 A plain :hg:`update` will also advance an active bookmark, if possible.
890 Updating away from a bookmark will cause it to be deactivated.
890 Updating away from a bookmark will cause it to be deactivated.
891
891
892 Bookmarks can be pushed and pulled between repositories (see
892 Bookmarks can be pushed and pulled between repositories (see
893 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
893 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
894 diverged, a new 'divergent bookmark' of the form 'name@path' will
894 diverged, a new 'divergent bookmark' of the form 'name@path' will
895 be created. Using :hg:`merge` will resolve the divergence.
895 be created. Using :hg:`merge` will resolve the divergence.
896
896
897 A bookmark named '@' has the special property that :hg:`clone` will
897 A bookmark named '@' has the special property that :hg:`clone` will
898 check it out by default if it exists.
898 check it out by default if it exists.
899
899
900 .. container:: verbose
900 .. container:: verbose
901
901
902 Examples:
902 Examples:
903
903
904 - create an active bookmark for a new line of development::
904 - create an active bookmark for a new line of development::
905
905
906 hg book new-feature
906 hg book new-feature
907
907
908 - create an inactive bookmark as a place marker::
908 - create an inactive bookmark as a place marker::
909
909
910 hg book -i reviewed
910 hg book -i reviewed
911
911
912 - create an inactive bookmark on another changeset::
912 - create an inactive bookmark on another changeset::
913
913
914 hg book -r .^ tested
914 hg book -r .^ tested
915
915
916 - move the '@' bookmark from another branch::
916 - move the '@' bookmark from another branch::
917
917
918 hg book -f @
918 hg book -f @
919 '''
919 '''
920 force = opts.get('force')
920 force = opts.get('force')
921 rev = opts.get('rev')
921 rev = opts.get('rev')
922 delete = opts.get('delete')
922 delete = opts.get('delete')
923 rename = opts.get('rename')
923 rename = opts.get('rename')
924 inactive = opts.get('inactive')
924 inactive = opts.get('inactive')
925
925
926 def checkformat(mark):
926 def checkformat(mark):
927 mark = mark.strip()
927 mark = mark.strip()
928 if not mark:
928 if not mark:
929 raise util.Abort(_("bookmark names cannot consist entirely of "
929 raise util.Abort(_("bookmark names cannot consist entirely of "
930 "whitespace"))
930 "whitespace"))
931 scmutil.checknewlabel(repo, mark, 'bookmark')
931 scmutil.checknewlabel(repo, mark, 'bookmark')
932 return mark
932 return mark
933
933
934 def checkconflict(repo, mark, cur, force=False, target=None):
934 def checkconflict(repo, mark, cur, force=False, target=None):
935 if mark in marks and not force:
935 if mark in marks and not force:
936 if target:
936 if target:
937 if marks[mark] == target and target == cur:
937 if marks[mark] == target and target == cur:
938 # re-activating a bookmark
938 # re-activating a bookmark
939 return
939 return
940 anc = repo.changelog.ancestors([repo[target].rev()])
940 anc = repo.changelog.ancestors([repo[target].rev()])
941 bmctx = repo[marks[mark]]
941 bmctx = repo[marks[mark]]
942 divs = [repo[b].node() for b in marks
942 divs = [repo[b].node() for b in marks
943 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
943 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
944
944
945 # allow resolving a single divergent bookmark even if moving
945 # allow resolving a single divergent bookmark even if moving
946 # the bookmark across branches when a revision is specified
946 # the bookmark across branches when a revision is specified
947 # that contains a divergent bookmark
947 # that contains a divergent bookmark
948 if bmctx.rev() not in anc and target in divs:
948 if bmctx.rev() not in anc and target in divs:
949 bookmarks.deletedivergent(repo, [target], mark)
949 bookmarks.deletedivergent(repo, [target], mark)
950 return
950 return
951
951
952 deletefrom = [b for b in divs
952 deletefrom = [b for b in divs
953 if repo[b].rev() in anc or b == target]
953 if repo[b].rev() in anc or b == target]
954 bookmarks.deletedivergent(repo, deletefrom, mark)
954 bookmarks.deletedivergent(repo, deletefrom, mark)
955 if bookmarks.validdest(repo, bmctx, repo[target]):
955 if bookmarks.validdest(repo, bmctx, repo[target]):
956 ui.status(_("moving bookmark '%s' forward from %s\n") %
956 ui.status(_("moving bookmark '%s' forward from %s\n") %
957 (mark, short(bmctx.node())))
957 (mark, short(bmctx.node())))
958 return
958 return
959 raise util.Abort(_("bookmark '%s' already exists "
959 raise util.Abort(_("bookmark '%s' already exists "
960 "(use -f to force)") % mark)
960 "(use -f to force)") % mark)
961 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
961 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
962 and not force):
962 and not force):
963 raise util.Abort(
963 raise util.Abort(
964 _("a bookmark cannot have the name of an existing branch"))
964 _("a bookmark cannot have the name of an existing branch"))
965
965
966 if delete and rename:
966 if delete and rename:
967 raise util.Abort(_("--delete and --rename are incompatible"))
967 raise util.Abort(_("--delete and --rename are incompatible"))
968 if delete and rev:
968 if delete and rev:
969 raise util.Abort(_("--rev is incompatible with --delete"))
969 raise util.Abort(_("--rev is incompatible with --delete"))
970 if rename and rev:
970 if rename and rev:
971 raise util.Abort(_("--rev is incompatible with --rename"))
971 raise util.Abort(_("--rev is incompatible with --rename"))
972 if not names and (delete or rev):
972 if not names and (delete or rev):
973 raise util.Abort(_("bookmark name required"))
973 raise util.Abort(_("bookmark name required"))
974
974
975 if delete or rename or names or inactive:
975 if delete or rename or names or inactive:
976 wlock = repo.wlock()
976 wlock = repo.wlock()
977 try:
977 try:
978 cur = repo.changectx('.').node()
978 cur = repo.changectx('.').node()
979 marks = repo._bookmarks
979 marks = repo._bookmarks
980 if delete:
980 if delete:
981 for mark in names:
981 for mark in names:
982 if mark not in marks:
982 if mark not in marks:
983 raise util.Abort(_("bookmark '%s' does not exist") %
983 raise util.Abort(_("bookmark '%s' does not exist") %
984 mark)
984 mark)
985 if mark == repo._bookmarkcurrent:
985 if mark == repo._bookmarkcurrent:
986 bookmarks.unsetcurrent(repo)
986 bookmarks.unsetcurrent(repo)
987 del marks[mark]
987 del marks[mark]
988 marks.write()
988 marks.write()
989
989
990 elif rename:
990 elif rename:
991 if not names:
991 if not names:
992 raise util.Abort(_("new bookmark name required"))
992 raise util.Abort(_("new bookmark name required"))
993 elif len(names) > 1:
993 elif len(names) > 1:
994 raise util.Abort(_("only one new bookmark name allowed"))
994 raise util.Abort(_("only one new bookmark name allowed"))
995 mark = checkformat(names[0])
995 mark = checkformat(names[0])
996 if rename not in marks:
996 if rename not in marks:
997 raise util.Abort(_("bookmark '%s' does not exist") % rename)
997 raise util.Abort(_("bookmark '%s' does not exist") % rename)
998 checkconflict(repo, mark, cur, force)
998 checkconflict(repo, mark, cur, force)
999 marks[mark] = marks[rename]
999 marks[mark] = marks[rename]
1000 if repo._bookmarkcurrent == rename and not inactive:
1000 if repo._bookmarkcurrent == rename and not inactive:
1001 bookmarks.setcurrent(repo, mark)
1001 bookmarks.setcurrent(repo, mark)
1002 del marks[rename]
1002 del marks[rename]
1003 marks.write()
1003 marks.write()
1004
1004
1005 elif names:
1005 elif names:
1006 newact = None
1006 newact = None
1007 for mark in names:
1007 for mark in names:
1008 mark = checkformat(mark)
1008 mark = checkformat(mark)
1009 if newact is None:
1009 if newact is None:
1010 newact = mark
1010 newact = mark
1011 if inactive and mark == repo._bookmarkcurrent:
1011 if inactive and mark == repo._bookmarkcurrent:
1012 bookmarks.unsetcurrent(repo)
1012 bookmarks.unsetcurrent(repo)
1013 return
1013 return
1014 tgt = cur
1014 tgt = cur
1015 if rev:
1015 if rev:
1016 tgt = scmutil.revsingle(repo, rev).node()
1016 tgt = scmutil.revsingle(repo, rev).node()
1017 checkconflict(repo, mark, cur, force, tgt)
1017 checkconflict(repo, mark, cur, force, tgt)
1018 marks[mark] = tgt
1018 marks[mark] = tgt
1019 if not inactive and cur == marks[newact] and not rev:
1019 if not inactive and cur == marks[newact] and not rev:
1020 bookmarks.setcurrent(repo, newact)
1020 bookmarks.setcurrent(repo, newact)
1021 elif cur != tgt and newact == repo._bookmarkcurrent:
1021 elif cur != tgt and newact == repo._bookmarkcurrent:
1022 bookmarks.unsetcurrent(repo)
1022 bookmarks.unsetcurrent(repo)
1023 marks.write()
1023 marks.write()
1024
1024
1025 elif inactive:
1025 elif inactive:
1026 if len(marks) == 0:
1026 if len(marks) == 0:
1027 ui.status(_("no bookmarks set\n"))
1027 ui.status(_("no bookmarks set\n"))
1028 elif not repo._bookmarkcurrent:
1028 elif not repo._bookmarkcurrent:
1029 ui.status(_("no active bookmark\n"))
1029 ui.status(_("no active bookmark\n"))
1030 else:
1030 else:
1031 bookmarks.unsetcurrent(repo)
1031 bookmarks.unsetcurrent(repo)
1032 finally:
1032 finally:
1033 wlock.release()
1033 wlock.release()
1034 else: # show bookmarks
1034 else: # show bookmarks
1035 fm = ui.formatter('bookmarks', opts)
1035 fm = ui.formatter('bookmarks', opts)
1036 hexfn = fm.hexfunc
1036 hexfn = fm.hexfunc
1037 marks = repo._bookmarks
1037 marks = repo._bookmarks
1038 if len(marks) == 0 and not fm:
1038 if len(marks) == 0 and not fm:
1039 ui.status(_("no bookmarks set\n"))
1039 ui.status(_("no bookmarks set\n"))
1040 for bmark, n in sorted(marks.iteritems()):
1040 for bmark, n in sorted(marks.iteritems()):
1041 current = repo._bookmarkcurrent
1041 current = repo._bookmarkcurrent
1042 if bmark == current:
1042 if bmark == current:
1043 prefix, label = '*', 'bookmarks.current'
1043 prefix, label = '*', 'bookmarks.current'
1044 else:
1044 else:
1045 prefix, label = ' ', ''
1045 prefix, label = ' ', ''
1046
1046
1047 fm.startitem()
1047 fm.startitem()
1048 if not ui.quiet:
1048 if not ui.quiet:
1049 fm.plain(' %s ' % prefix, label=label)
1049 fm.plain(' %s ' % prefix, label=label)
1050 fm.write('bookmark', '%s', bmark, label=label)
1050 fm.write('bookmark', '%s', bmark, label=label)
1051 pad = " " * (25 - encoding.colwidth(bmark))
1051 pad = " " * (25 - encoding.colwidth(bmark))
1052 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1052 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1053 repo.changelog.rev(n), hexfn(n), label=label)
1053 repo.changelog.rev(n), hexfn(n), label=label)
1054 fm.data(active=(bmark == current))
1054 fm.data(active=(bmark == current))
1055 fm.plain('\n')
1055 fm.plain('\n')
1056 fm.end()
1056 fm.end()
1057
1057
1058 @command('branch',
1058 @command('branch',
1059 [('f', 'force', None,
1059 [('f', 'force', None,
1060 _('set branch name even if it shadows an existing branch')),
1060 _('set branch name even if it shadows an existing branch')),
1061 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1061 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1062 _('[-fC] [NAME]'))
1062 _('[-fC] [NAME]'))
1063 def branch(ui, repo, label=None, **opts):
1063 def branch(ui, repo, label=None, **opts):
1064 """set or show the current branch name
1064 """set or show the current branch name
1065
1065
1066 .. note::
1066 .. note::
1067
1067
1068 Branch names are permanent and global. Use :hg:`bookmark` to create a
1068 Branch names are permanent and global. Use :hg:`bookmark` to create a
1069 light-weight bookmark instead. See :hg:`help glossary` for more
1069 light-weight bookmark instead. See :hg:`help glossary` for more
1070 information about named branches and bookmarks.
1070 information about named branches and bookmarks.
1071
1071
1072 With no argument, show the current branch name. With one argument,
1072 With no argument, show the current branch name. With one argument,
1073 set the working directory branch name (the branch will not exist
1073 set the working directory branch name (the branch will not exist
1074 in the repository until the next commit). Standard practice
1074 in the repository until the next commit). Standard practice
1075 recommends that primary development take place on the 'default'
1075 recommends that primary development take place on the 'default'
1076 branch.
1076 branch.
1077
1077
1078 Unless -f/--force is specified, branch will not let you set a
1078 Unless -f/--force is specified, branch will not let you set a
1079 branch name that already exists.
1079 branch name that already exists.
1080
1080
1081 Use -C/--clean to reset the working directory branch to that of
1081 Use -C/--clean to reset the working directory branch to that of
1082 the parent of the working directory, negating a previous branch
1082 the parent of the working directory, negating a previous branch
1083 change.
1083 change.
1084
1084
1085 Use the command :hg:`update` to switch to an existing branch. Use
1085 Use the command :hg:`update` to switch to an existing branch. Use
1086 :hg:`commit --close-branch` to mark this branch as closed.
1086 :hg:`commit --close-branch` to mark this branch as closed.
1087
1087
1088 Returns 0 on success.
1088 Returns 0 on success.
1089 """
1089 """
1090 if label:
1090 if label:
1091 label = label.strip()
1091 label = label.strip()
1092
1092
1093 if not opts.get('clean') and not label:
1093 if not opts.get('clean') and not label:
1094 ui.write("%s\n" % repo.dirstate.branch())
1094 ui.write("%s\n" % repo.dirstate.branch())
1095 return
1095 return
1096
1096
1097 wlock = repo.wlock()
1097 wlock = repo.wlock()
1098 try:
1098 try:
1099 if opts.get('clean'):
1099 if opts.get('clean'):
1100 label = repo[None].p1().branch()
1100 label = repo[None].p1().branch()
1101 repo.dirstate.setbranch(label)
1101 repo.dirstate.setbranch(label)
1102 ui.status(_('reset working directory to branch %s\n') % label)
1102 ui.status(_('reset working directory to branch %s\n') % label)
1103 elif label:
1103 elif label:
1104 if not opts.get('force') and label in repo.branchmap():
1104 if not opts.get('force') and label in repo.branchmap():
1105 if label not in [p.branch() for p in repo.parents()]:
1105 if label not in [p.branch() for p in repo.parents()]:
1106 raise util.Abort(_('a branch of the same name already'
1106 raise util.Abort(_('a branch of the same name already'
1107 ' exists'),
1107 ' exists'),
1108 # i18n: "it" refers to an existing branch
1108 # i18n: "it" refers to an existing branch
1109 hint=_("use 'hg update' to switch to it"))
1109 hint=_("use 'hg update' to switch to it"))
1110 scmutil.checknewlabel(repo, label, 'branch')
1110 scmutil.checknewlabel(repo, label, 'branch')
1111 repo.dirstate.setbranch(label)
1111 repo.dirstate.setbranch(label)
1112 ui.status(_('marked working directory as branch %s\n') % label)
1112 ui.status(_('marked working directory as branch %s\n') % label)
1113 ui.status(_('(branches are permanent and global, '
1113 ui.status(_('(branches are permanent and global, '
1114 'did you want a bookmark?)\n'))
1114 'did you want a bookmark?)\n'))
1115 finally:
1115 finally:
1116 wlock.release()
1116 wlock.release()
1117
1117
1118 @command('branches',
1118 @command('branches',
1119 [('a', 'active', False,
1119 [('a', 'active', False,
1120 _('show only branches that have unmerged heads (DEPRECATED)')),
1120 _('show only branches that have unmerged heads (DEPRECATED)')),
1121 ('c', 'closed', False, _('show normal and closed branches')),
1121 ('c', 'closed', False, _('show normal and closed branches')),
1122 ] + formatteropts,
1122 ] + formatteropts,
1123 _('[-ac]'))
1123 _('[-ac]'))
1124 def branches(ui, repo, active=False, closed=False, **opts):
1124 def branches(ui, repo, active=False, closed=False, **opts):
1125 """list repository named branches
1125 """list repository named branches
1126
1126
1127 List the repository's named branches, indicating which ones are
1127 List the repository's named branches, indicating which ones are
1128 inactive. If -c/--closed is specified, also list branches which have
1128 inactive. If -c/--closed is specified, also list branches which have
1129 been marked closed (see :hg:`commit --close-branch`).
1129 been marked closed (see :hg:`commit --close-branch`).
1130
1130
1131 Use the command :hg:`update` to switch to an existing branch.
1131 Use the command :hg:`update` to switch to an existing branch.
1132
1132
1133 Returns 0.
1133 Returns 0.
1134 """
1134 """
1135
1135
1136 fm = ui.formatter('branches', opts)
1136 fm = ui.formatter('branches', opts)
1137 hexfunc = fm.hexfunc
1137 hexfunc = fm.hexfunc
1138
1138
1139 allheads = set(repo.heads())
1139 allheads = set(repo.heads())
1140 branches = []
1140 branches = []
1141 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1141 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1142 isactive = not isclosed and bool(set(heads) & allheads)
1142 isactive = not isclosed and bool(set(heads) & allheads)
1143 branches.append((tag, repo[tip], isactive, not isclosed))
1143 branches.append((tag, repo[tip], isactive, not isclosed))
1144 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1144 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1145 reverse=True)
1145 reverse=True)
1146
1146
1147 for tag, ctx, isactive, isopen in branches:
1147 for tag, ctx, isactive, isopen in branches:
1148 if active and not isactive:
1148 if active and not isactive:
1149 continue
1149 continue
1150 if isactive:
1150 if isactive:
1151 label = 'branches.active'
1151 label = 'branches.active'
1152 notice = ''
1152 notice = ''
1153 elif not isopen:
1153 elif not isopen:
1154 if not closed:
1154 if not closed:
1155 continue
1155 continue
1156 label = 'branches.closed'
1156 label = 'branches.closed'
1157 notice = _(' (closed)')
1157 notice = _(' (closed)')
1158 else:
1158 else:
1159 label = 'branches.inactive'
1159 label = 'branches.inactive'
1160 notice = _(' (inactive)')
1160 notice = _(' (inactive)')
1161 current = (tag == repo.dirstate.branch())
1161 current = (tag == repo.dirstate.branch())
1162 if current:
1162 if current:
1163 label = 'branches.current'
1163 label = 'branches.current'
1164
1164
1165 fm.startitem()
1165 fm.startitem()
1166 fm.write('branch', '%s', tag, label=label)
1166 fm.write('branch', '%s', tag, label=label)
1167 rev = ctx.rev()
1167 rev = ctx.rev()
1168 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1168 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1169 fmt = ' ' * padsize + ' %d:%s'
1169 fmt = ' ' * padsize + ' %d:%s'
1170 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1170 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1171 label='log.changeset changeset.%s' % ctx.phasestr())
1171 label='log.changeset changeset.%s' % ctx.phasestr())
1172 fm.data(active=isactive, closed=not isopen, current=current)
1172 fm.data(active=isactive, closed=not isopen, current=current)
1173 if not ui.quiet:
1173 if not ui.quiet:
1174 fm.plain(notice)
1174 fm.plain(notice)
1175 fm.plain('\n')
1175 fm.plain('\n')
1176 fm.end()
1176 fm.end()
1177
1177
1178 @command('bundle',
1178 @command('bundle',
1179 [('f', 'force', None, _('run even when the destination is unrelated')),
1179 [('f', 'force', None, _('run even when the destination is unrelated')),
1180 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1180 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1181 _('REV')),
1181 _('REV')),
1182 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1182 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1183 _('BRANCH')),
1183 _('BRANCH')),
1184 ('', 'base', [],
1184 ('', 'base', [],
1185 _('a base changeset assumed to be available at the destination'),
1185 _('a base changeset assumed to be available at the destination'),
1186 _('REV')),
1186 _('REV')),
1187 ('a', 'all', None, _('bundle all changesets in the repository')),
1187 ('a', 'all', None, _('bundle all changesets in the repository')),
1188 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1188 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1189 ] + remoteopts,
1189 ] + remoteopts,
1190 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1190 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1191 def bundle(ui, repo, fname, dest=None, **opts):
1191 def bundle(ui, repo, fname, dest=None, **opts):
1192 """create a changegroup file
1192 """create a changegroup file
1193
1193
1194 Generate a compressed changegroup file collecting changesets not
1194 Generate a compressed changegroup file collecting changesets not
1195 known to be in another repository.
1195 known to be in another repository.
1196
1196
1197 If you omit the destination repository, then hg assumes the
1197 If you omit the destination repository, then hg assumes the
1198 destination will have all the nodes you specify with --base
1198 destination will have all the nodes you specify with --base
1199 parameters. To create a bundle containing all changesets, use
1199 parameters. To create a bundle containing all changesets, use
1200 -a/--all (or --base null).
1200 -a/--all (or --base null).
1201
1201
1202 You can change compression method with the -t/--type option.
1202 You can change compression method with the -t/--type option.
1203 The available compression methods are: none, bzip2, and
1203 The available compression methods are: none, bzip2, and
1204 gzip (by default, bundles are compressed using bzip2).
1204 gzip (by default, bundles are compressed using bzip2).
1205
1205
1206 The bundle file can then be transferred using conventional means
1206 The bundle file can then be transferred using conventional means
1207 and applied to another repository with the unbundle or pull
1207 and applied to another repository with the unbundle or pull
1208 command. This is useful when direct push and pull are not
1208 command. This is useful when direct push and pull are not
1209 available or when exporting an entire repository is undesirable.
1209 available or when exporting an entire repository is undesirable.
1210
1210
1211 Applying bundles preserves all changeset contents including
1211 Applying bundles preserves all changeset contents including
1212 permissions, copy/rename information, and revision history.
1212 permissions, copy/rename information, and revision history.
1213
1213
1214 Returns 0 on success, 1 if no changes found.
1214 Returns 0 on success, 1 if no changes found.
1215 """
1215 """
1216 revs = None
1216 revs = None
1217 if 'rev' in opts:
1217 if 'rev' in opts:
1218 revs = scmutil.revrange(repo, opts['rev'])
1218 revs = scmutil.revrange(repo, opts['rev'])
1219
1219
1220 bundletype = opts.get('type', 'bzip2').lower()
1220 bundletype = opts.get('type', 'bzip2').lower()
1221 btypes = {'none': 'HG10UN',
1221 btypes = {'none': 'HG10UN',
1222 'bzip2': 'HG10BZ',
1222 'bzip2': 'HG10BZ',
1223 'gzip': 'HG10GZ',
1223 'gzip': 'HG10GZ',
1224 'bundle2': 'HG2Y'}
1224 'bundle2': 'HG2Y'}
1225 bundletype = btypes.get(bundletype)
1225 bundletype = btypes.get(bundletype)
1226 if bundletype not in changegroup.bundletypes:
1226 if bundletype not in changegroup.bundletypes:
1227 raise util.Abort(_('unknown bundle type specified with --type'))
1227 raise util.Abort(_('unknown bundle type specified with --type'))
1228
1228
1229 if opts.get('all'):
1229 if opts.get('all'):
1230 base = ['null']
1230 base = ['null']
1231 else:
1231 else:
1232 base = scmutil.revrange(repo, opts.get('base'))
1232 base = scmutil.revrange(repo, opts.get('base'))
1233 # TODO: get desired bundlecaps from command line.
1233 # TODO: get desired bundlecaps from command line.
1234 bundlecaps = None
1234 bundlecaps = None
1235 if base:
1235 if base:
1236 if dest:
1236 if dest:
1237 raise util.Abort(_("--base is incompatible with specifying "
1237 raise util.Abort(_("--base is incompatible with specifying "
1238 "a destination"))
1238 "a destination"))
1239 common = [repo.lookup(rev) for rev in base]
1239 common = [repo.lookup(rev) for rev in base]
1240 heads = revs and map(repo.lookup, revs) or revs
1240 heads = revs and map(repo.lookup, revs) or revs
1241 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1241 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1242 common=common, bundlecaps=bundlecaps)
1242 common=common, bundlecaps=bundlecaps)
1243 outgoing = None
1243 outgoing = None
1244 else:
1244 else:
1245 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1245 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1246 dest, branches = hg.parseurl(dest, opts.get('branch'))
1246 dest, branches = hg.parseurl(dest, opts.get('branch'))
1247 other = hg.peer(repo, opts, dest)
1247 other = hg.peer(repo, opts, dest)
1248 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1248 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1249 heads = revs and map(repo.lookup, revs) or revs
1249 heads = revs and map(repo.lookup, revs) or revs
1250 outgoing = discovery.findcommonoutgoing(repo, other,
1250 outgoing = discovery.findcommonoutgoing(repo, other,
1251 onlyheads=heads,
1251 onlyheads=heads,
1252 force=opts.get('force'),
1252 force=opts.get('force'),
1253 portable=True)
1253 portable=True)
1254 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1254 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1255 bundlecaps)
1255 bundlecaps)
1256 if not cg:
1256 if not cg:
1257 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1257 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1258 return 1
1258 return 1
1259
1259
1260 changegroup.writebundle(ui, cg, fname, bundletype)
1260 changegroup.writebundle(ui, cg, fname, bundletype)
1261
1261
1262 @command('cat',
1262 @command('cat',
1263 [('o', 'output', '',
1263 [('o', 'output', '',
1264 _('print output to file with formatted name'), _('FORMAT')),
1264 _('print output to file with formatted name'), _('FORMAT')),
1265 ('r', 'rev', '', _('print the given revision'), _('REV')),
1265 ('r', 'rev', '', _('print the given revision'), _('REV')),
1266 ('', 'decode', None, _('apply any matching decode filter')),
1266 ('', 'decode', None, _('apply any matching decode filter')),
1267 ] + walkopts,
1267 ] + walkopts,
1268 _('[OPTION]... FILE...'),
1268 _('[OPTION]... FILE...'),
1269 inferrepo=True)
1269 inferrepo=True)
1270 def cat(ui, repo, file1, *pats, **opts):
1270 def cat(ui, repo, file1, *pats, **opts):
1271 """output the current or given revision of files
1271 """output the current or given revision of files
1272
1272
1273 Print the specified files as they were at the given revision. If
1273 Print the specified files as they were at the given revision. If
1274 no revision is given, the parent of the working directory is used.
1274 no revision is given, the parent of the working directory is used.
1275
1275
1276 Output may be to a file, in which case the name of the file is
1276 Output may be to a file, in which case the name of the file is
1277 given using a format string. The formatting rules as follows:
1277 given using a format string. The formatting rules as follows:
1278
1278
1279 :``%%``: literal "%" character
1279 :``%%``: literal "%" character
1280 :``%s``: basename of file being printed
1280 :``%s``: basename of file being printed
1281 :``%d``: dirname of file being printed, or '.' if in repository root
1281 :``%d``: dirname of file being printed, or '.' if in repository root
1282 :``%p``: root-relative path name of file being printed
1282 :``%p``: root-relative path name of file being printed
1283 :``%H``: changeset hash (40 hexadecimal digits)
1283 :``%H``: changeset hash (40 hexadecimal digits)
1284 :``%R``: changeset revision number
1284 :``%R``: changeset revision number
1285 :``%h``: short-form changeset hash (12 hexadecimal digits)
1285 :``%h``: short-form changeset hash (12 hexadecimal digits)
1286 :``%r``: zero-padded changeset revision number
1286 :``%r``: zero-padded changeset revision number
1287 :``%b``: basename of the exporting repository
1287 :``%b``: basename of the exporting repository
1288
1288
1289 Returns 0 on success.
1289 Returns 0 on success.
1290 """
1290 """
1291 ctx = scmutil.revsingle(repo, opts.get('rev'))
1291 ctx = scmutil.revsingle(repo, opts.get('rev'))
1292 m = scmutil.match(ctx, (file1,) + pats, opts)
1292 m = scmutil.match(ctx, (file1,) + pats, opts)
1293
1293
1294 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1294 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1295
1295
1296 @command('^clone',
1296 @command('^clone',
1297 [('U', 'noupdate', None, _('the clone will include an empty working '
1297 [('U', 'noupdate', None, _('the clone will include an empty working '
1298 'directory (only a repository)')),
1298 'directory (only a repository)')),
1299 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1299 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1300 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1300 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1301 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1301 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1302 ('', 'pull', None, _('use pull protocol to copy metadata')),
1302 ('', 'pull', None, _('use pull protocol to copy metadata')),
1303 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1303 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1304 ] + remoteopts,
1304 ] + remoteopts,
1305 _('[OPTION]... SOURCE [DEST]'),
1305 _('[OPTION]... SOURCE [DEST]'),
1306 norepo=True)
1306 norepo=True)
1307 def clone(ui, source, dest=None, **opts):
1307 def clone(ui, source, dest=None, **opts):
1308 """make a copy of an existing repository
1308 """make a copy of an existing repository
1309
1309
1310 Create a copy of an existing repository in a new directory.
1310 Create a copy of an existing repository in a new directory.
1311
1311
1312 If no destination directory name is specified, it defaults to the
1312 If no destination directory name is specified, it defaults to the
1313 basename of the source.
1313 basename of the source.
1314
1314
1315 The location of the source is added to the new repository's
1315 The location of the source is added to the new repository's
1316 ``.hg/hgrc`` file, as the default to be used for future pulls.
1316 ``.hg/hgrc`` file, as the default to be used for future pulls.
1317
1317
1318 Only local paths and ``ssh://`` URLs are supported as
1318 Only local paths and ``ssh://`` URLs are supported as
1319 destinations. For ``ssh://`` destinations, no working directory or
1319 destinations. For ``ssh://`` destinations, no working directory or
1320 ``.hg/hgrc`` will be created on the remote side.
1320 ``.hg/hgrc`` will be created on the remote side.
1321
1321
1322 To pull only a subset of changesets, specify one or more revisions
1322 To pull only a subset of changesets, specify one or more revisions
1323 identifiers with -r/--rev or branches with -b/--branch. The
1323 identifiers with -r/--rev or branches with -b/--branch. The
1324 resulting clone will contain only the specified changesets and
1324 resulting clone will contain only the specified changesets and
1325 their ancestors. These options (or 'clone src#rev dest') imply
1325 their ancestors. These options (or 'clone src#rev dest') imply
1326 --pull, even for local source repositories. Note that specifying a
1326 --pull, even for local source repositories. Note that specifying a
1327 tag will include the tagged changeset but not the changeset
1327 tag will include the tagged changeset but not the changeset
1328 containing the tag.
1328 containing the tag.
1329
1329
1330 If the source repository has a bookmark called '@' set, that
1330 If the source repository has a bookmark called '@' set, that
1331 revision will be checked out in the new repository by default.
1331 revision will be checked out in the new repository by default.
1332
1332
1333 To check out a particular version, use -u/--update, or
1333 To check out a particular version, use -u/--update, or
1334 -U/--noupdate to create a clone with no working directory.
1334 -U/--noupdate to create a clone with no working directory.
1335
1335
1336 .. container:: verbose
1336 .. container:: verbose
1337
1337
1338 For efficiency, hardlinks are used for cloning whenever the
1338 For efficiency, hardlinks are used for cloning whenever the
1339 source and destination are on the same filesystem (note this
1339 source and destination are on the same filesystem (note this
1340 applies only to the repository data, not to the working
1340 applies only to the repository data, not to the working
1341 directory). Some filesystems, such as AFS, implement hardlinking
1341 directory). Some filesystems, such as AFS, implement hardlinking
1342 incorrectly, but do not report errors. In these cases, use the
1342 incorrectly, but do not report errors. In these cases, use the
1343 --pull option to avoid hardlinking.
1343 --pull option to avoid hardlinking.
1344
1344
1345 In some cases, you can clone repositories and the working
1345 In some cases, you can clone repositories and the working
1346 directory using full hardlinks with ::
1346 directory using full hardlinks with ::
1347
1347
1348 $ cp -al REPO REPOCLONE
1348 $ cp -al REPO REPOCLONE
1349
1349
1350 This is the fastest way to clone, but it is not always safe. The
1350 This is the fastest way to clone, but it is not always safe. The
1351 operation is not atomic (making sure REPO is not modified during
1351 operation is not atomic (making sure REPO is not modified during
1352 the operation is up to you) and you have to make sure your
1352 the operation is up to you) and you have to make sure your
1353 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1353 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1354 so). Also, this is not compatible with certain extensions that
1354 so). Also, this is not compatible with certain extensions that
1355 place their metadata under the .hg directory, such as mq.
1355 place their metadata under the .hg directory, such as mq.
1356
1356
1357 Mercurial will update the working directory to the first applicable
1357 Mercurial will update the working directory to the first applicable
1358 revision from this list:
1358 revision from this list:
1359
1359
1360 a) null if -U or the source repository has no changesets
1360 a) null if -U or the source repository has no changesets
1361 b) if -u . and the source repository is local, the first parent of
1361 b) if -u . and the source repository is local, the first parent of
1362 the source repository's working directory
1362 the source repository's working directory
1363 c) the changeset specified with -u (if a branch name, this means the
1363 c) the changeset specified with -u (if a branch name, this means the
1364 latest head of that branch)
1364 latest head of that branch)
1365 d) the changeset specified with -r
1365 d) the changeset specified with -r
1366 e) the tipmost head specified with -b
1366 e) the tipmost head specified with -b
1367 f) the tipmost head specified with the url#branch source syntax
1367 f) the tipmost head specified with the url#branch source syntax
1368 g) the revision marked with the '@' bookmark, if present
1368 g) the revision marked with the '@' bookmark, if present
1369 h) the tipmost head of the default branch
1369 h) the tipmost head of the default branch
1370 i) tip
1370 i) tip
1371
1371
1372 Examples:
1372 Examples:
1373
1373
1374 - clone a remote repository to a new directory named hg/::
1374 - clone a remote repository to a new directory named hg/::
1375
1375
1376 hg clone http://selenic.com/hg
1376 hg clone http://selenic.com/hg
1377
1377
1378 - create a lightweight local clone::
1378 - create a lightweight local clone::
1379
1379
1380 hg clone project/ project-feature/
1380 hg clone project/ project-feature/
1381
1381
1382 - clone from an absolute path on an ssh server (note double-slash)::
1382 - clone from an absolute path on an ssh server (note double-slash)::
1383
1383
1384 hg clone ssh://user@server//home/projects/alpha/
1384 hg clone ssh://user@server//home/projects/alpha/
1385
1385
1386 - do a high-speed clone over a LAN while checking out a
1386 - do a high-speed clone over a LAN while checking out a
1387 specified version::
1387 specified version::
1388
1388
1389 hg clone --uncompressed http://server/repo -u 1.5
1389 hg clone --uncompressed http://server/repo -u 1.5
1390
1390
1391 - create a repository without changesets after a particular revision::
1391 - create a repository without changesets after a particular revision::
1392
1392
1393 hg clone -r 04e544 experimental/ good/
1393 hg clone -r 04e544 experimental/ good/
1394
1394
1395 - clone (and track) a particular named branch::
1395 - clone (and track) a particular named branch::
1396
1396
1397 hg clone http://selenic.com/hg#stable
1397 hg clone http://selenic.com/hg#stable
1398
1398
1399 See :hg:`help urls` for details on specifying URLs.
1399 See :hg:`help urls` for details on specifying URLs.
1400
1400
1401 Returns 0 on success.
1401 Returns 0 on success.
1402 """
1402 """
1403 if opts.get('noupdate') and opts.get('updaterev'):
1403 if opts.get('noupdate') and opts.get('updaterev'):
1404 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1404 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1405
1405
1406 r = hg.clone(ui, opts, source, dest,
1406 r = hg.clone(ui, opts, source, dest,
1407 pull=opts.get('pull'),
1407 pull=opts.get('pull'),
1408 stream=opts.get('uncompressed'),
1408 stream=opts.get('uncompressed'),
1409 rev=opts.get('rev'),
1409 rev=opts.get('rev'),
1410 update=opts.get('updaterev') or not opts.get('noupdate'),
1410 update=opts.get('updaterev') or not opts.get('noupdate'),
1411 branch=opts.get('branch'))
1411 branch=opts.get('branch'))
1412
1412
1413 return r is None
1413 return r is None
1414
1414
1415 @command('^commit|ci',
1415 @command('^commit|ci',
1416 [('A', 'addremove', None,
1416 [('A', 'addremove', None,
1417 _('mark new/missing files as added/removed before committing')),
1417 _('mark new/missing files as added/removed before committing')),
1418 ('', 'close-branch', None,
1418 ('', 'close-branch', None,
1419 _('mark a branch as closed, hiding it from the branch list')),
1419 _('mark a branch as closed, hiding it from the branch list')),
1420 ('', 'amend', None, _('amend the parent of the working directory')),
1420 ('', 'amend', None, _('amend the parent of the working directory')),
1421 ('s', 'secret', None, _('use the secret phase for committing')),
1421 ('s', 'secret', None, _('use the secret phase for committing')),
1422 ('e', 'edit', None, _('invoke editor on commit messages')),
1422 ('e', 'edit', None, _('invoke editor on commit messages')),
1423 ('i', 'interactive', None, _('use interactive mode')),
1423 ('i', 'interactive', None, _('use interactive mode')),
1424 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1424 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1425 _('[OPTION]... [FILE]...'),
1425 _('[OPTION]... [FILE]...'),
1426 inferrepo=True)
1426 inferrepo=True)
1427 def commit(ui, repo, *pats, **opts):
1427 def commit(ui, repo, *pats, **opts):
1428 """commit the specified files or all outstanding changes
1428 """commit the specified files or all outstanding changes
1429
1429
1430 Commit changes to the given files into the repository. Unlike a
1430 Commit changes to the given files into the repository. Unlike a
1431 centralized SCM, this operation is a local operation. See
1431 centralized SCM, this operation is a local operation. See
1432 :hg:`push` for a way to actively distribute your changes.
1432 :hg:`push` for a way to actively distribute your changes.
1433
1433
1434 If a list of files is omitted, all changes reported by :hg:`status`
1434 If a list of files is omitted, all changes reported by :hg:`status`
1435 will be committed.
1435 will be committed.
1436
1436
1437 If you are committing the result of a merge, do not provide any
1437 If you are committing the result of a merge, do not provide any
1438 filenames or -I/-X filters.
1438 filenames or -I/-X filters.
1439
1439
1440 If no commit message is specified, Mercurial starts your
1440 If no commit message is specified, Mercurial starts your
1441 configured editor where you can enter a message. In case your
1441 configured editor where you can enter a message. In case your
1442 commit fails, you will find a backup of your message in
1442 commit fails, you will find a backup of your message in
1443 ``.hg/last-message.txt``.
1443 ``.hg/last-message.txt``.
1444
1444
1445 The --amend flag can be used to amend the parent of the
1445 The --amend flag can be used to amend the parent of the
1446 working directory with a new commit that contains the changes
1446 working directory with a new commit that contains the changes
1447 in the parent in addition to those currently reported by :hg:`status`,
1447 in the parent in addition to those currently reported by :hg:`status`,
1448 if there are any. The old commit is stored in a backup bundle in
1448 if there are any. The old commit is stored in a backup bundle in
1449 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1449 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1450 on how to restore it).
1450 on how to restore it).
1451
1451
1452 Message, user and date are taken from the amended commit unless
1452 Message, user and date are taken from the amended commit unless
1453 specified. When a message isn't specified on the command line,
1453 specified. When a message isn't specified on the command line,
1454 the editor will open with the message of the amended commit.
1454 the editor will open with the message of the amended commit.
1455
1455
1456 It is not possible to amend public changesets (see :hg:`help phases`)
1456 It is not possible to amend public changesets (see :hg:`help phases`)
1457 or changesets that have children.
1457 or changesets that have children.
1458
1458
1459 See :hg:`help dates` for a list of formats valid for -d/--date.
1459 See :hg:`help dates` for a list of formats valid for -d/--date.
1460
1460
1461 Returns 0 on success, 1 if nothing changed.
1461 Returns 0 on success, 1 if nothing changed.
1462 """
1462 """
1463 if opts.get('interactive'):
1463 if opts.get('interactive'):
1464 opts.pop('interactive')
1464 opts.pop('interactive')
1465 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1465 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1466 cmdutil.recordfilter, *pats, **opts)
1466 cmdutil.recordfilter, *pats, **opts)
1467 return
1467 return
1468
1468
1469 if opts.get('subrepos'):
1469 if opts.get('subrepos'):
1470 if opts.get('amend'):
1470 if opts.get('amend'):
1471 raise util.Abort(_('cannot amend with --subrepos'))
1471 raise util.Abort(_('cannot amend with --subrepos'))
1472 # Let --subrepos on the command line override config setting.
1472 # Let --subrepos on the command line override config setting.
1473 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1473 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1474
1474
1475 cmdutil.checkunfinished(repo, commit=True)
1475 cmdutil.checkunfinished(repo, commit=True)
1476
1476
1477 branch = repo[None].branch()
1477 branch = repo[None].branch()
1478 bheads = repo.branchheads(branch)
1478 bheads = repo.branchheads(branch)
1479
1479
1480 extra = {}
1480 extra = {}
1481 if opts.get('close_branch'):
1481 if opts.get('close_branch'):
1482 extra['close'] = 1
1482 extra['close'] = 1
1483
1483
1484 if not bheads:
1484 if not bheads:
1485 raise util.Abort(_('can only close branch heads'))
1485 raise util.Abort(_('can only close branch heads'))
1486 elif opts.get('amend'):
1486 elif opts.get('amend'):
1487 if repo.parents()[0].p1().branch() != branch and \
1487 if repo.parents()[0].p1().branch() != branch and \
1488 repo.parents()[0].p2().branch() != branch:
1488 repo.parents()[0].p2().branch() != branch:
1489 raise util.Abort(_('can only close branch heads'))
1489 raise util.Abort(_('can only close branch heads'))
1490
1490
1491 if opts.get('amend'):
1491 if opts.get('amend'):
1492 if ui.configbool('ui', 'commitsubrepos'):
1492 if ui.configbool('ui', 'commitsubrepos'):
1493 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1493 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1494
1494
1495 old = repo['.']
1495 old = repo['.']
1496 if not old.mutable():
1496 if not old.mutable():
1497 raise util.Abort(_('cannot amend public changesets'))
1497 raise util.Abort(_('cannot amend public changesets'))
1498 if len(repo[None].parents()) > 1:
1498 if len(repo[None].parents()) > 1:
1499 raise util.Abort(_('cannot amend while merging'))
1499 raise util.Abort(_('cannot amend while merging'))
1500 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1500 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1501 if not allowunstable and old.children():
1501 if not allowunstable and old.children():
1502 raise util.Abort(_('cannot amend changeset with children'))
1502 raise util.Abort(_('cannot amend changeset with children'))
1503
1503
1504 # commitfunc is used only for temporary amend commit by cmdutil.amend
1504 # commitfunc is used only for temporary amend commit by cmdutil.amend
1505 def commitfunc(ui, repo, message, match, opts):
1505 def commitfunc(ui, repo, message, match, opts):
1506 return repo.commit(message,
1506 return repo.commit(message,
1507 opts.get('user') or old.user(),
1507 opts.get('user') or old.user(),
1508 opts.get('date') or old.date(),
1508 opts.get('date') or old.date(),
1509 match,
1509 match,
1510 extra=extra)
1510 extra=extra)
1511
1511
1512 current = repo._bookmarkcurrent
1512 current = repo._bookmarkcurrent
1513 marks = old.bookmarks()
1513 marks = old.bookmarks()
1514 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1514 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1515 if node == old.node():
1515 if node == old.node():
1516 ui.status(_("nothing changed\n"))
1516 ui.status(_("nothing changed\n"))
1517 return 1
1517 return 1
1518 elif marks:
1518 elif marks:
1519 ui.debug('moving bookmarks %r from %s to %s\n' %
1519 ui.debug('moving bookmarks %r from %s to %s\n' %
1520 (marks, old.hex(), hex(node)))
1520 (marks, old.hex(), hex(node)))
1521 newmarks = repo._bookmarks
1521 newmarks = repo._bookmarks
1522 for bm in marks:
1522 for bm in marks:
1523 newmarks[bm] = node
1523 newmarks[bm] = node
1524 if bm == current:
1524 if bm == current:
1525 bookmarks.setcurrent(repo, bm)
1525 bookmarks.setcurrent(repo, bm)
1526 newmarks.write()
1526 newmarks.write()
1527 else:
1527 else:
1528 def commitfunc(ui, repo, message, match, opts):
1528 def commitfunc(ui, repo, message, match, opts):
1529 backup = ui.backupconfig('phases', 'new-commit')
1529 backup = ui.backupconfig('phases', 'new-commit')
1530 baseui = repo.baseui
1530 baseui = repo.baseui
1531 basebackup = baseui.backupconfig('phases', 'new-commit')
1531 basebackup = baseui.backupconfig('phases', 'new-commit')
1532 try:
1532 try:
1533 if opts.get('secret'):
1533 if opts.get('secret'):
1534 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1534 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1535 # Propagate to subrepos
1535 # Propagate to subrepos
1536 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1536 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1537
1537
1538 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1538 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1539 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1539 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1540 return repo.commit(message, opts.get('user'), opts.get('date'),
1540 return repo.commit(message, opts.get('user'), opts.get('date'),
1541 match,
1541 match,
1542 editor=editor,
1542 editor=editor,
1543 extra=extra)
1543 extra=extra)
1544 finally:
1544 finally:
1545 ui.restoreconfig(backup)
1545 ui.restoreconfig(backup)
1546 repo.baseui.restoreconfig(basebackup)
1546 repo.baseui.restoreconfig(basebackup)
1547
1547
1548
1548
1549 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1549 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1550
1550
1551 if not node:
1551 if not node:
1552 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1552 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1553 if stat[3]:
1553 if stat[3]:
1554 ui.status(_("nothing changed (%d missing files, see "
1554 ui.status(_("nothing changed (%d missing files, see "
1555 "'hg status')\n") % len(stat[3]))
1555 "'hg status')\n") % len(stat[3]))
1556 else:
1556 else:
1557 ui.status(_("nothing changed\n"))
1557 ui.status(_("nothing changed\n"))
1558 return 1
1558 return 1
1559
1559
1560 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1560 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1561
1561
1562 @command('config|showconfig|debugconfig',
1562 @command('config|showconfig|debugconfig',
1563 [('u', 'untrusted', None, _('show untrusted configuration options')),
1563 [('u', 'untrusted', None, _('show untrusted configuration options')),
1564 ('e', 'edit', None, _('edit user config')),
1564 ('e', 'edit', None, _('edit user config')),
1565 ('l', 'local', None, _('edit repository config')),
1565 ('l', 'local', None, _('edit repository config')),
1566 ('g', 'global', None, _('edit global config'))],
1566 ('g', 'global', None, _('edit global config'))],
1567 _('[-u] [NAME]...'),
1567 _('[-u] [NAME]...'),
1568 optionalrepo=True)
1568 optionalrepo=True)
1569 def config(ui, repo, *values, **opts):
1569 def config(ui, repo, *values, **opts):
1570 """show combined config settings from all hgrc files
1570 """show combined config settings from all hgrc files
1571
1571
1572 With no arguments, print names and values of all config items.
1572 With no arguments, print names and values of all config items.
1573
1573
1574 With one argument of the form section.name, print just the value
1574 With one argument of the form section.name, print just the value
1575 of that config item.
1575 of that config item.
1576
1576
1577 With multiple arguments, print names and values of all config
1577 With multiple arguments, print names and values of all config
1578 items with matching section names.
1578 items with matching section names.
1579
1579
1580 With --edit, start an editor on the user-level config file. With
1580 With --edit, start an editor on the user-level config file. With
1581 --global, edit the system-wide config file. With --local, edit the
1581 --global, edit the system-wide config file. With --local, edit the
1582 repository-level config file.
1582 repository-level config file.
1583
1583
1584 With --debug, the source (filename and line number) is printed
1584 With --debug, the source (filename and line number) is printed
1585 for each config item.
1585 for each config item.
1586
1586
1587 See :hg:`help config` for more information about config files.
1587 See :hg:`help config` for more information about config files.
1588
1588
1589 Returns 0 on success, 1 if NAME does not exist.
1589 Returns 0 on success, 1 if NAME does not exist.
1590
1590
1591 """
1591 """
1592
1592
1593 if opts.get('edit') or opts.get('local') or opts.get('global'):
1593 if opts.get('edit') or opts.get('local') or opts.get('global'):
1594 if opts.get('local') and opts.get('global'):
1594 if opts.get('local') and opts.get('global'):
1595 raise util.Abort(_("can't use --local and --global together"))
1595 raise util.Abort(_("can't use --local and --global together"))
1596
1596
1597 if opts.get('local'):
1597 if opts.get('local'):
1598 if not repo:
1598 if not repo:
1599 raise util.Abort(_("can't use --local outside a repository"))
1599 raise util.Abort(_("can't use --local outside a repository"))
1600 paths = [repo.join('hgrc')]
1600 paths = [repo.join('hgrc')]
1601 elif opts.get('global'):
1601 elif opts.get('global'):
1602 paths = scmutil.systemrcpath()
1602 paths = scmutil.systemrcpath()
1603 else:
1603 else:
1604 paths = scmutil.userrcpath()
1604 paths = scmutil.userrcpath()
1605
1605
1606 for f in paths:
1606 for f in paths:
1607 if os.path.exists(f):
1607 if os.path.exists(f):
1608 break
1608 break
1609 else:
1609 else:
1610 if opts.get('global'):
1610 if opts.get('global'):
1611 samplehgrc = uimod.samplehgrcs['global']
1611 samplehgrc = uimod.samplehgrcs['global']
1612 elif opts.get('local'):
1612 elif opts.get('local'):
1613 samplehgrc = uimod.samplehgrcs['local']
1613 samplehgrc = uimod.samplehgrcs['local']
1614 else:
1614 else:
1615 samplehgrc = uimod.samplehgrcs['user']
1615 samplehgrc = uimod.samplehgrcs['user']
1616
1616
1617 f = paths[0]
1617 f = paths[0]
1618 fp = open(f, "w")
1618 fp = open(f, "w")
1619 fp.write(samplehgrc)
1619 fp.write(samplehgrc)
1620 fp.close()
1620 fp.close()
1621
1621
1622 editor = ui.geteditor()
1622 editor = ui.geteditor()
1623 ui.system("%s \"%s\"" % (editor, f),
1623 ui.system("%s \"%s\"" % (editor, f),
1624 onerr=util.Abort, errprefix=_("edit failed"))
1624 onerr=util.Abort, errprefix=_("edit failed"))
1625 return
1625 return
1626
1626
1627 for f in scmutil.rcpath():
1627 for f in scmutil.rcpath():
1628 ui.debug('read config from: %s\n' % f)
1628 ui.debug('read config from: %s\n' % f)
1629 untrusted = bool(opts.get('untrusted'))
1629 untrusted = bool(opts.get('untrusted'))
1630 if values:
1630 if values:
1631 sections = [v for v in values if '.' not in v]
1631 sections = [v for v in values if '.' not in v]
1632 items = [v for v in values if '.' in v]
1632 items = [v for v in values if '.' in v]
1633 if len(items) > 1 or items and sections:
1633 if len(items) > 1 or items and sections:
1634 raise util.Abort(_('only one config item permitted'))
1634 raise util.Abort(_('only one config item permitted'))
1635 matched = False
1635 matched = False
1636 for section, name, value in ui.walkconfig(untrusted=untrusted):
1636 for section, name, value in ui.walkconfig(untrusted=untrusted):
1637 value = str(value).replace('\n', '\\n')
1637 value = str(value).replace('\n', '\\n')
1638 sectname = section + '.' + name
1638 sectname = section + '.' + name
1639 if values:
1639 if values:
1640 for v in values:
1640 for v in values:
1641 if v == section:
1641 if v == section:
1642 ui.debug('%s: ' %
1642 ui.debug('%s: ' %
1643 ui.configsource(section, name, untrusted))
1643 ui.configsource(section, name, untrusted))
1644 ui.write('%s=%s\n' % (sectname, value))
1644 ui.write('%s=%s\n' % (sectname, value))
1645 matched = True
1645 matched = True
1646 elif v == sectname:
1646 elif v == sectname:
1647 ui.debug('%s: ' %
1647 ui.debug('%s: ' %
1648 ui.configsource(section, name, untrusted))
1648 ui.configsource(section, name, untrusted))
1649 ui.write(value, '\n')
1649 ui.write(value, '\n')
1650 matched = True
1650 matched = True
1651 else:
1651 else:
1652 ui.debug('%s: ' %
1652 ui.debug('%s: ' %
1653 ui.configsource(section, name, untrusted))
1653 ui.configsource(section, name, untrusted))
1654 ui.write('%s=%s\n' % (sectname, value))
1654 ui.write('%s=%s\n' % (sectname, value))
1655 matched = True
1655 matched = True
1656 if matched:
1656 if matched:
1657 return 0
1657 return 0
1658 return 1
1658 return 1
1659
1659
1660 @command('copy|cp',
1660 @command('copy|cp',
1661 [('A', 'after', None, _('record a copy that has already occurred')),
1661 [('A', 'after', None, _('record a copy that has already occurred')),
1662 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1662 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1663 ] + walkopts + dryrunopts,
1663 ] + walkopts + dryrunopts,
1664 _('[OPTION]... [SOURCE]... DEST'))
1664 _('[OPTION]... [SOURCE]... DEST'))
1665 def copy(ui, repo, *pats, **opts):
1665 def copy(ui, repo, *pats, **opts):
1666 """mark files as copied for the next commit
1666 """mark files as copied for the next commit
1667
1667
1668 Mark dest as having copies of source files. If dest is a
1668 Mark dest as having copies of source files. If dest is a
1669 directory, copies are put in that directory. If dest is a file,
1669 directory, copies are put in that directory. If dest is a file,
1670 the source must be a single file.
1670 the source must be a single file.
1671
1671
1672 By default, this command copies the contents of files as they
1672 By default, this command copies the contents of files as they
1673 exist in the working directory. If invoked with -A/--after, the
1673 exist in the working directory. If invoked with -A/--after, the
1674 operation is recorded, but no copying is performed.
1674 operation is recorded, but no copying is performed.
1675
1675
1676 This command takes effect with the next commit. To undo a copy
1676 This command takes effect with the next commit. To undo a copy
1677 before that, see :hg:`revert`.
1677 before that, see :hg:`revert`.
1678
1678
1679 Returns 0 on success, 1 if errors are encountered.
1679 Returns 0 on success, 1 if errors are encountered.
1680 """
1680 """
1681 wlock = repo.wlock(False)
1681 wlock = repo.wlock(False)
1682 try:
1682 try:
1683 return cmdutil.copy(ui, repo, pats, opts)
1683 return cmdutil.copy(ui, repo, pats, opts)
1684 finally:
1684 finally:
1685 wlock.release()
1685 wlock.release()
1686
1686
1687 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1687 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1688 def debugancestor(ui, repo, *args):
1688 def debugancestor(ui, repo, *args):
1689 """find the ancestor revision of two revisions in a given index"""
1689 """find the ancestor revision of two revisions in a given index"""
1690 if len(args) == 3:
1690 if len(args) == 3:
1691 index, rev1, rev2 = args
1691 index, rev1, rev2 = args
1692 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1692 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1693 lookup = r.lookup
1693 lookup = r.lookup
1694 elif len(args) == 2:
1694 elif len(args) == 2:
1695 if not repo:
1695 if not repo:
1696 raise util.Abort(_("there is no Mercurial repository here "
1696 raise util.Abort(_("there is no Mercurial repository here "
1697 "(.hg not found)"))
1697 "(.hg not found)"))
1698 rev1, rev2 = args
1698 rev1, rev2 = args
1699 r = repo.changelog
1699 r = repo.changelog
1700 lookup = repo.lookup
1700 lookup = repo.lookup
1701 else:
1701 else:
1702 raise util.Abort(_('either two or three arguments required'))
1702 raise util.Abort(_('either two or three arguments required'))
1703 a = r.ancestor(lookup(rev1), lookup(rev2))
1703 a = r.ancestor(lookup(rev1), lookup(rev2))
1704 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1704 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1705
1705
1706 @command('debugbuilddag',
1706 @command('debugbuilddag',
1707 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1707 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1708 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1708 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1709 ('n', 'new-file', None, _('add new file at each rev'))],
1709 ('n', 'new-file', None, _('add new file at each rev'))],
1710 _('[OPTION]... [TEXT]'))
1710 _('[OPTION]... [TEXT]'))
1711 def debugbuilddag(ui, repo, text=None,
1711 def debugbuilddag(ui, repo, text=None,
1712 mergeable_file=False,
1712 mergeable_file=False,
1713 overwritten_file=False,
1713 overwritten_file=False,
1714 new_file=False):
1714 new_file=False):
1715 """builds a repo with a given DAG from scratch in the current empty repo
1715 """builds a repo with a given DAG from scratch in the current empty repo
1716
1716
1717 The description of the DAG is read from stdin if not given on the
1717 The description of the DAG is read from stdin if not given on the
1718 command line.
1718 command line.
1719
1719
1720 Elements:
1720 Elements:
1721
1721
1722 - "+n" is a linear run of n nodes based on the current default parent
1722 - "+n" is a linear run of n nodes based on the current default parent
1723 - "." is a single node based on the current default parent
1723 - "." is a single node based on the current default parent
1724 - "$" resets the default parent to null (implied at the start);
1724 - "$" resets the default parent to null (implied at the start);
1725 otherwise the default parent is always the last node created
1725 otherwise the default parent is always the last node created
1726 - "<p" sets the default parent to the backref p
1726 - "<p" sets the default parent to the backref p
1727 - "*p" is a fork at parent p, which is a backref
1727 - "*p" is a fork at parent p, which is a backref
1728 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1728 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1729 - "/p2" is a merge of the preceding node and p2
1729 - "/p2" is a merge of the preceding node and p2
1730 - ":tag" defines a local tag for the preceding node
1730 - ":tag" defines a local tag for the preceding node
1731 - "@branch" sets the named branch for subsequent nodes
1731 - "@branch" sets the named branch for subsequent nodes
1732 - "#...\\n" is a comment up to the end of the line
1732 - "#...\\n" is a comment up to the end of the line
1733
1733
1734 Whitespace between the above elements is ignored.
1734 Whitespace between the above elements is ignored.
1735
1735
1736 A backref is either
1736 A backref is either
1737
1737
1738 - a number n, which references the node curr-n, where curr is the current
1738 - a number n, which references the node curr-n, where curr is the current
1739 node, or
1739 node, or
1740 - the name of a local tag you placed earlier using ":tag", or
1740 - the name of a local tag you placed earlier using ":tag", or
1741 - empty to denote the default parent.
1741 - empty to denote the default parent.
1742
1742
1743 All string valued-elements are either strictly alphanumeric, or must
1743 All string valued-elements are either strictly alphanumeric, or must
1744 be enclosed in double quotes ("..."), with "\\" as escape character.
1744 be enclosed in double quotes ("..."), with "\\" as escape character.
1745 """
1745 """
1746
1746
1747 if text is None:
1747 if text is None:
1748 ui.status(_("reading DAG from stdin\n"))
1748 ui.status(_("reading DAG from stdin\n"))
1749 text = ui.fin.read()
1749 text = ui.fin.read()
1750
1750
1751 cl = repo.changelog
1751 cl = repo.changelog
1752 if len(cl) > 0:
1752 if len(cl) > 0:
1753 raise util.Abort(_('repository is not empty'))
1753 raise util.Abort(_('repository is not empty'))
1754
1754
1755 # determine number of revs in DAG
1755 # determine number of revs in DAG
1756 total = 0
1756 total = 0
1757 for type, data in dagparser.parsedag(text):
1757 for type, data in dagparser.parsedag(text):
1758 if type == 'n':
1758 if type == 'n':
1759 total += 1
1759 total += 1
1760
1760
1761 if mergeable_file:
1761 if mergeable_file:
1762 linesperrev = 2
1762 linesperrev = 2
1763 # make a file with k lines per rev
1763 # make a file with k lines per rev
1764 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1764 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1765 initialmergedlines.append("")
1765 initialmergedlines.append("")
1766
1766
1767 tags = []
1767 tags = []
1768
1768
1769 lock = tr = None
1769 lock = tr = None
1770 try:
1770 try:
1771 lock = repo.lock()
1771 lock = repo.lock()
1772 tr = repo.transaction("builddag")
1772 tr = repo.transaction("builddag")
1773
1773
1774 at = -1
1774 at = -1
1775 atbranch = 'default'
1775 atbranch = 'default'
1776 nodeids = []
1776 nodeids = []
1777 id = 0
1777 id = 0
1778 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1778 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1779 for type, data in dagparser.parsedag(text):
1779 for type, data in dagparser.parsedag(text):
1780 if type == 'n':
1780 if type == 'n':
1781 ui.note(('node %s\n' % str(data)))
1781 ui.note(('node %s\n' % str(data)))
1782 id, ps = data
1782 id, ps = data
1783
1783
1784 files = []
1784 files = []
1785 fctxs = {}
1785 fctxs = {}
1786
1786
1787 p2 = None
1787 p2 = None
1788 if mergeable_file:
1788 if mergeable_file:
1789 fn = "mf"
1789 fn = "mf"
1790 p1 = repo[ps[0]]
1790 p1 = repo[ps[0]]
1791 if len(ps) > 1:
1791 if len(ps) > 1:
1792 p2 = repo[ps[1]]
1792 p2 = repo[ps[1]]
1793 pa = p1.ancestor(p2)
1793 pa = p1.ancestor(p2)
1794 base, local, other = [x[fn].data() for x in (pa, p1,
1794 base, local, other = [x[fn].data() for x in (pa, p1,
1795 p2)]
1795 p2)]
1796 m3 = simplemerge.Merge3Text(base, local, other)
1796 m3 = simplemerge.Merge3Text(base, local, other)
1797 ml = [l.strip() for l in m3.merge_lines()]
1797 ml = [l.strip() for l in m3.merge_lines()]
1798 ml.append("")
1798 ml.append("")
1799 elif at > 0:
1799 elif at > 0:
1800 ml = p1[fn].data().split("\n")
1800 ml = p1[fn].data().split("\n")
1801 else:
1801 else:
1802 ml = initialmergedlines
1802 ml = initialmergedlines
1803 ml[id * linesperrev] += " r%i" % id
1803 ml[id * linesperrev] += " r%i" % id
1804 mergedtext = "\n".join(ml)
1804 mergedtext = "\n".join(ml)
1805 files.append(fn)
1805 files.append(fn)
1806 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1806 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1807
1807
1808 if overwritten_file:
1808 if overwritten_file:
1809 fn = "of"
1809 fn = "of"
1810 files.append(fn)
1810 files.append(fn)
1811 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1811 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1812
1812
1813 if new_file:
1813 if new_file:
1814 fn = "nf%i" % id
1814 fn = "nf%i" % id
1815 files.append(fn)
1815 files.append(fn)
1816 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1816 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1817 if len(ps) > 1:
1817 if len(ps) > 1:
1818 if not p2:
1818 if not p2:
1819 p2 = repo[ps[1]]
1819 p2 = repo[ps[1]]
1820 for fn in p2:
1820 for fn in p2:
1821 if fn.startswith("nf"):
1821 if fn.startswith("nf"):
1822 files.append(fn)
1822 files.append(fn)
1823 fctxs[fn] = p2[fn]
1823 fctxs[fn] = p2[fn]
1824
1824
1825 def fctxfn(repo, cx, path):
1825 def fctxfn(repo, cx, path):
1826 return fctxs.get(path)
1826 return fctxs.get(path)
1827
1827
1828 if len(ps) == 0 or ps[0] < 0:
1828 if len(ps) == 0 or ps[0] < 0:
1829 pars = [None, None]
1829 pars = [None, None]
1830 elif len(ps) == 1:
1830 elif len(ps) == 1:
1831 pars = [nodeids[ps[0]], None]
1831 pars = [nodeids[ps[0]], None]
1832 else:
1832 else:
1833 pars = [nodeids[p] for p in ps]
1833 pars = [nodeids[p] for p in ps]
1834 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1834 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1835 date=(id, 0),
1835 date=(id, 0),
1836 user="debugbuilddag",
1836 user="debugbuilddag",
1837 extra={'branch': atbranch})
1837 extra={'branch': atbranch})
1838 nodeid = repo.commitctx(cx)
1838 nodeid = repo.commitctx(cx)
1839 nodeids.append(nodeid)
1839 nodeids.append(nodeid)
1840 at = id
1840 at = id
1841 elif type == 'l':
1841 elif type == 'l':
1842 id, name = data
1842 id, name = data
1843 ui.note(('tag %s\n' % name))
1843 ui.note(('tag %s\n' % name))
1844 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1844 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1845 elif type == 'a':
1845 elif type == 'a':
1846 ui.note(('branch %s\n' % data))
1846 ui.note(('branch %s\n' % data))
1847 atbranch = data
1847 atbranch = data
1848 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1848 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1849 tr.close()
1849 tr.close()
1850
1850
1851 if tags:
1851 if tags:
1852 repo.vfs.write("localtags", "".join(tags))
1852 repo.vfs.write("localtags", "".join(tags))
1853 finally:
1853 finally:
1854 ui.progress(_('building'), None)
1854 ui.progress(_('building'), None)
1855 release(tr, lock)
1855 release(tr, lock)
1856
1856
1857 @command('debugbundle',
1857 @command('debugbundle',
1858 [('a', 'all', None, _('show all details'))],
1858 [('a', 'all', None, _('show all details'))],
1859 _('FILE'),
1859 _('FILE'),
1860 norepo=True)
1860 norepo=True)
1861 def debugbundle(ui, bundlepath, all=None, **opts):
1861 def debugbundle(ui, bundlepath, all=None, **opts):
1862 """lists the contents of a bundle"""
1862 """lists the contents of a bundle"""
1863 f = hg.openpath(ui, bundlepath)
1863 f = hg.openpath(ui, bundlepath)
1864 try:
1864 try:
1865 gen = exchange.readbundle(ui, f, bundlepath)
1865 gen = exchange.readbundle(ui, f, bundlepath)
1866 if isinstance(gen, bundle2.unbundle20):
1866 if isinstance(gen, bundle2.unbundle20):
1867 return _debugbundle2(ui, gen, all=all, **opts)
1867 return _debugbundle2(ui, gen, all=all, **opts)
1868 if all:
1868 if all:
1869 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1869 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1870
1870
1871 def showchunks(named):
1871 def showchunks(named):
1872 ui.write("\n%s\n" % named)
1872 ui.write("\n%s\n" % named)
1873 chain = None
1873 chain = None
1874 while True:
1874 while True:
1875 chunkdata = gen.deltachunk(chain)
1875 chunkdata = gen.deltachunk(chain)
1876 if not chunkdata:
1876 if not chunkdata:
1877 break
1877 break
1878 node = chunkdata['node']
1878 node = chunkdata['node']
1879 p1 = chunkdata['p1']
1879 p1 = chunkdata['p1']
1880 p2 = chunkdata['p2']
1880 p2 = chunkdata['p2']
1881 cs = chunkdata['cs']
1881 cs = chunkdata['cs']
1882 deltabase = chunkdata['deltabase']
1882 deltabase = chunkdata['deltabase']
1883 delta = chunkdata['delta']
1883 delta = chunkdata['delta']
1884 ui.write("%s %s %s %s %s %s\n" %
1884 ui.write("%s %s %s %s %s %s\n" %
1885 (hex(node), hex(p1), hex(p2),
1885 (hex(node), hex(p1), hex(p2),
1886 hex(cs), hex(deltabase), len(delta)))
1886 hex(cs), hex(deltabase), len(delta)))
1887 chain = node
1887 chain = node
1888
1888
1889 chunkdata = gen.changelogheader()
1889 chunkdata = gen.changelogheader()
1890 showchunks("changelog")
1890 showchunks("changelog")
1891 chunkdata = gen.manifestheader()
1891 chunkdata = gen.manifestheader()
1892 showchunks("manifest")
1892 showchunks("manifest")
1893 while True:
1893 while True:
1894 chunkdata = gen.filelogheader()
1894 chunkdata = gen.filelogheader()
1895 if not chunkdata:
1895 if not chunkdata:
1896 break
1896 break
1897 fname = chunkdata['filename']
1897 fname = chunkdata['filename']
1898 showchunks(fname)
1898 showchunks(fname)
1899 else:
1899 else:
1900 if isinstance(gen, bundle2.unbundle20):
1900 if isinstance(gen, bundle2.unbundle20):
1901 raise util.Abort(_('use debugbundle2 for this file'))
1901 raise util.Abort(_('use debugbundle2 for this file'))
1902 chunkdata = gen.changelogheader()
1902 chunkdata = gen.changelogheader()
1903 chain = None
1903 chain = None
1904 while True:
1904 while True:
1905 chunkdata = gen.deltachunk(chain)
1905 chunkdata = gen.deltachunk(chain)
1906 if not chunkdata:
1906 if not chunkdata:
1907 break
1907 break
1908 node = chunkdata['node']
1908 node = chunkdata['node']
1909 ui.write("%s\n" % hex(node))
1909 ui.write("%s\n" % hex(node))
1910 chain = node
1910 chain = node
1911 finally:
1911 finally:
1912 f.close()
1912 f.close()
1913
1913
1914 def _debugbundle2(ui, gen, **opts):
1914 def _debugbundle2(ui, gen, **opts):
1915 """lists the contents of a bundle2"""
1915 """lists the contents of a bundle2"""
1916 if not isinstance(gen, bundle2.unbundle20):
1916 if not isinstance(gen, bundle2.unbundle20):
1917 raise util.Abort(_('not a bundle2 file'))
1917 raise util.Abort(_('not a bundle2 file'))
1918 ui.write(('Stream params: %s\n' % repr(gen.params)))
1918 ui.write(('Stream params: %s\n' % repr(gen.params)))
1919 for part in gen.iterparts():
1919 for part in gen.iterparts():
1920 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1920 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1921 if part.type == 'b2x:changegroup':
1921 if part.type == 'b2x:changegroup':
1922 version = part.params.get('version', '01')
1922 version = part.params.get('version', '01')
1923 cg = changegroup.packermap[version][1](part, 'UN')
1923 cg = changegroup.packermap[version][1](part, 'UN')
1924 chunkdata = cg.changelogheader()
1924 chunkdata = cg.changelogheader()
1925 chain = None
1925 chain = None
1926 while True:
1926 while True:
1927 chunkdata = cg.deltachunk(chain)
1927 chunkdata = cg.deltachunk(chain)
1928 if not chunkdata:
1928 if not chunkdata:
1929 break
1929 break
1930 node = chunkdata['node']
1930 node = chunkdata['node']
1931 ui.write(" %s\n" % hex(node))
1931 ui.write(" %s\n" % hex(node))
1932 chain = node
1932 chain = node
1933
1933
1934 @command('debugcheckstate', [], '')
1934 @command('debugcheckstate', [], '')
1935 def debugcheckstate(ui, repo):
1935 def debugcheckstate(ui, repo):
1936 """validate the correctness of the current dirstate"""
1936 """validate the correctness of the current dirstate"""
1937 parent1, parent2 = repo.dirstate.parents()
1937 parent1, parent2 = repo.dirstate.parents()
1938 m1 = repo[parent1].manifest()
1938 m1 = repo[parent1].manifest()
1939 m2 = repo[parent2].manifest()
1939 m2 = repo[parent2].manifest()
1940 errors = 0
1940 errors = 0
1941 for f in repo.dirstate:
1941 for f in repo.dirstate:
1942 state = repo.dirstate[f]
1942 state = repo.dirstate[f]
1943 if state in "nr" and f not in m1:
1943 if state in "nr" and f not in m1:
1944 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1944 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1945 errors += 1
1945 errors += 1
1946 if state in "a" and f in m1:
1946 if state in "a" and f in m1:
1947 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1947 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1948 errors += 1
1948 errors += 1
1949 if state in "m" and f not in m1 and f not in m2:
1949 if state in "m" and f not in m1 and f not in m2:
1950 ui.warn(_("%s in state %s, but not in either manifest\n") %
1950 ui.warn(_("%s in state %s, but not in either manifest\n") %
1951 (f, state))
1951 (f, state))
1952 errors += 1
1952 errors += 1
1953 for f in m1:
1953 for f in m1:
1954 state = repo.dirstate[f]
1954 state = repo.dirstate[f]
1955 if state not in "nrm":
1955 if state not in "nrm":
1956 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1956 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1957 errors += 1
1957 errors += 1
1958 if errors:
1958 if errors:
1959 error = _(".hg/dirstate inconsistent with current parent's manifest")
1959 error = _(".hg/dirstate inconsistent with current parent's manifest")
1960 raise util.Abort(error)
1960 raise util.Abort(error)
1961
1961
1962 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1962 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1963 def debugcommands(ui, cmd='', *args):
1963 def debugcommands(ui, cmd='', *args):
1964 """list all available commands and options"""
1964 """list all available commands and options"""
1965 for cmd, vals in sorted(table.iteritems()):
1965 for cmd, vals in sorted(table.iteritems()):
1966 cmd = cmd.split('|')[0].strip('^')
1966 cmd = cmd.split('|')[0].strip('^')
1967 opts = ', '.join([i[1] for i in vals[1]])
1967 opts = ', '.join([i[1] for i in vals[1]])
1968 ui.write('%s: %s\n' % (cmd, opts))
1968 ui.write('%s: %s\n' % (cmd, opts))
1969
1969
1970 @command('debugcomplete',
1970 @command('debugcomplete',
1971 [('o', 'options', None, _('show the command options'))],
1971 [('o', 'options', None, _('show the command options'))],
1972 _('[-o] CMD'),
1972 _('[-o] CMD'),
1973 norepo=True)
1973 norepo=True)
1974 def debugcomplete(ui, cmd='', **opts):
1974 def debugcomplete(ui, cmd='', **opts):
1975 """returns the completion list associated with the given command"""
1975 """returns the completion list associated with the given command"""
1976
1976
1977 if opts.get('options'):
1977 if opts.get('options'):
1978 options = []
1978 options = []
1979 otables = [globalopts]
1979 otables = [globalopts]
1980 if cmd:
1980 if cmd:
1981 aliases, entry = cmdutil.findcmd(cmd, table, False)
1981 aliases, entry = cmdutil.findcmd(cmd, table, False)
1982 otables.append(entry[1])
1982 otables.append(entry[1])
1983 for t in otables:
1983 for t in otables:
1984 for o in t:
1984 for o in t:
1985 if "(DEPRECATED)" in o[3]:
1985 if "(DEPRECATED)" in o[3]:
1986 continue
1986 continue
1987 if o[0]:
1987 if o[0]:
1988 options.append('-%s' % o[0])
1988 options.append('-%s' % o[0])
1989 options.append('--%s' % o[1])
1989 options.append('--%s' % o[1])
1990 ui.write("%s\n" % "\n".join(options))
1990 ui.write("%s\n" % "\n".join(options))
1991 return
1991 return
1992
1992
1993 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1993 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1994 if ui.verbose:
1994 if ui.verbose:
1995 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1995 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1996 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1996 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1997
1997
1998 @command('debugdag',
1998 @command('debugdag',
1999 [('t', 'tags', None, _('use tags as labels')),
1999 [('t', 'tags', None, _('use tags as labels')),
2000 ('b', 'branches', None, _('annotate with branch names')),
2000 ('b', 'branches', None, _('annotate with branch names')),
2001 ('', 'dots', None, _('use dots for runs')),
2001 ('', 'dots', None, _('use dots for runs')),
2002 ('s', 'spaces', None, _('separate elements by spaces'))],
2002 ('s', 'spaces', None, _('separate elements by spaces'))],
2003 _('[OPTION]... [FILE [REV]...]'),
2003 _('[OPTION]... [FILE [REV]...]'),
2004 optionalrepo=True)
2004 optionalrepo=True)
2005 def debugdag(ui, repo, file_=None, *revs, **opts):
2005 def debugdag(ui, repo, file_=None, *revs, **opts):
2006 """format the changelog or an index DAG as a concise textual description
2006 """format the changelog or an index DAG as a concise textual description
2007
2007
2008 If you pass a revlog index, the revlog's DAG is emitted. If you list
2008 If you pass a revlog index, the revlog's DAG is emitted. If you list
2009 revision numbers, they get labeled in the output as rN.
2009 revision numbers, they get labeled in the output as rN.
2010
2010
2011 Otherwise, the changelog DAG of the current repo is emitted.
2011 Otherwise, the changelog DAG of the current repo is emitted.
2012 """
2012 """
2013 spaces = opts.get('spaces')
2013 spaces = opts.get('spaces')
2014 dots = opts.get('dots')
2014 dots = opts.get('dots')
2015 if file_:
2015 if file_:
2016 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2016 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2017 revs = set((int(r) for r in revs))
2017 revs = set((int(r) for r in revs))
2018 def events():
2018 def events():
2019 for r in rlog:
2019 for r in rlog:
2020 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2020 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2021 if p != -1))
2021 if p != -1))
2022 if r in revs:
2022 if r in revs:
2023 yield 'l', (r, "r%i" % r)
2023 yield 'l', (r, "r%i" % r)
2024 elif repo:
2024 elif repo:
2025 cl = repo.changelog
2025 cl = repo.changelog
2026 tags = opts.get('tags')
2026 tags = opts.get('tags')
2027 branches = opts.get('branches')
2027 branches = opts.get('branches')
2028 if tags:
2028 if tags:
2029 labels = {}
2029 labels = {}
2030 for l, n in repo.tags().items():
2030 for l, n in repo.tags().items():
2031 labels.setdefault(cl.rev(n), []).append(l)
2031 labels.setdefault(cl.rev(n), []).append(l)
2032 def events():
2032 def events():
2033 b = "default"
2033 b = "default"
2034 for r in cl:
2034 for r in cl:
2035 if branches:
2035 if branches:
2036 newb = cl.read(cl.node(r))[5]['branch']
2036 newb = cl.read(cl.node(r))[5]['branch']
2037 if newb != b:
2037 if newb != b:
2038 yield 'a', newb
2038 yield 'a', newb
2039 b = newb
2039 b = newb
2040 yield 'n', (r, list(p for p in cl.parentrevs(r)
2040 yield 'n', (r, list(p for p in cl.parentrevs(r)
2041 if p != -1))
2041 if p != -1))
2042 if tags:
2042 if tags:
2043 ls = labels.get(r)
2043 ls = labels.get(r)
2044 if ls:
2044 if ls:
2045 for l in ls:
2045 for l in ls:
2046 yield 'l', (r, l)
2046 yield 'l', (r, l)
2047 else:
2047 else:
2048 raise util.Abort(_('need repo for changelog dag'))
2048 raise util.Abort(_('need repo for changelog dag'))
2049
2049
2050 for line in dagparser.dagtextlines(events(),
2050 for line in dagparser.dagtextlines(events(),
2051 addspaces=spaces,
2051 addspaces=spaces,
2052 wraplabels=True,
2052 wraplabels=True,
2053 wrapannotations=True,
2053 wrapannotations=True,
2054 wrapnonlinear=dots,
2054 wrapnonlinear=dots,
2055 usedots=dots,
2055 usedots=dots,
2056 maxlinewidth=70):
2056 maxlinewidth=70):
2057 ui.write(line)
2057 ui.write(line)
2058 ui.write("\n")
2058 ui.write("\n")
2059
2059
2060 @command('debugdata',
2060 @command('debugdata',
2061 [('c', 'changelog', False, _('open changelog')),
2061 [('c', 'changelog', False, _('open changelog')),
2062 ('m', 'manifest', False, _('open manifest'))],
2062 ('m', 'manifest', False, _('open manifest'))],
2063 _('-c|-m|FILE REV'))
2063 _('-c|-m|FILE REV'))
2064 def debugdata(ui, repo, file_, rev=None, **opts):
2064 def debugdata(ui, repo, file_, rev=None, **opts):
2065 """dump the contents of a data file revision"""
2065 """dump the contents of a data file revision"""
2066 if opts.get('changelog') or opts.get('manifest'):
2066 if opts.get('changelog') or opts.get('manifest'):
2067 file_, rev = None, file_
2067 file_, rev = None, file_
2068 elif rev is None:
2068 elif rev is None:
2069 raise error.CommandError('debugdata', _('invalid arguments'))
2069 raise error.CommandError('debugdata', _('invalid arguments'))
2070 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2070 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2071 try:
2071 try:
2072 ui.write(r.revision(r.lookup(rev)))
2072 ui.write(r.revision(r.lookup(rev)))
2073 except KeyError:
2073 except KeyError:
2074 raise util.Abort(_('invalid revision identifier %s') % rev)
2074 raise util.Abort(_('invalid revision identifier %s') % rev)
2075
2075
2076 @command('debugdate',
2076 @command('debugdate',
2077 [('e', 'extended', None, _('try extended date formats'))],
2077 [('e', 'extended', None, _('try extended date formats'))],
2078 _('[-e] DATE [RANGE]'),
2078 _('[-e] DATE [RANGE]'),
2079 norepo=True, optionalrepo=True)
2079 norepo=True, optionalrepo=True)
2080 def debugdate(ui, date, range=None, **opts):
2080 def debugdate(ui, date, range=None, **opts):
2081 """parse and display a date"""
2081 """parse and display a date"""
2082 if opts["extended"]:
2082 if opts["extended"]:
2083 d = util.parsedate(date, util.extendeddateformats)
2083 d = util.parsedate(date, util.extendeddateformats)
2084 else:
2084 else:
2085 d = util.parsedate(date)
2085 d = util.parsedate(date)
2086 ui.write(("internal: %s %s\n") % d)
2086 ui.write(("internal: %s %s\n") % d)
2087 ui.write(("standard: %s\n") % util.datestr(d))
2087 ui.write(("standard: %s\n") % util.datestr(d))
2088 if range:
2088 if range:
2089 m = util.matchdate(range)
2089 m = util.matchdate(range)
2090 ui.write(("match: %s\n") % m(d[0]))
2090 ui.write(("match: %s\n") % m(d[0]))
2091
2091
2092 @command('debugdiscovery',
2092 @command('debugdiscovery',
2093 [('', 'old', None, _('use old-style discovery')),
2093 [('', 'old', None, _('use old-style discovery')),
2094 ('', 'nonheads', None,
2094 ('', 'nonheads', None,
2095 _('use old-style discovery with non-heads included')),
2095 _('use old-style discovery with non-heads included')),
2096 ] + remoteopts,
2096 ] + remoteopts,
2097 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2097 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2098 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2098 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2099 """runs the changeset discovery protocol in isolation"""
2099 """runs the changeset discovery protocol in isolation"""
2100 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2100 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2101 opts.get('branch'))
2101 opts.get('branch'))
2102 remote = hg.peer(repo, opts, remoteurl)
2102 remote = hg.peer(repo, opts, remoteurl)
2103 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2103 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2104
2104
2105 # make sure tests are repeatable
2105 # make sure tests are repeatable
2106 random.seed(12323)
2106 random.seed(12323)
2107
2107
2108 def doit(localheads, remoteheads, remote=remote):
2108 def doit(localheads, remoteheads, remote=remote):
2109 if opts.get('old'):
2109 if opts.get('old'):
2110 if localheads:
2110 if localheads:
2111 raise util.Abort('cannot use localheads with old style '
2111 raise util.Abort('cannot use localheads with old style '
2112 'discovery')
2112 'discovery')
2113 if not util.safehasattr(remote, 'branches'):
2113 if not util.safehasattr(remote, 'branches'):
2114 # enable in-client legacy support
2114 # enable in-client legacy support
2115 remote = localrepo.locallegacypeer(remote.local())
2115 remote = localrepo.locallegacypeer(remote.local())
2116 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2116 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2117 force=True)
2117 force=True)
2118 common = set(common)
2118 common = set(common)
2119 if not opts.get('nonheads'):
2119 if not opts.get('nonheads'):
2120 ui.write(("unpruned common: %s\n") %
2120 ui.write(("unpruned common: %s\n") %
2121 " ".join(sorted(short(n) for n in common)))
2121 " ".join(sorted(short(n) for n in common)))
2122 dag = dagutil.revlogdag(repo.changelog)
2122 dag = dagutil.revlogdag(repo.changelog)
2123 all = dag.ancestorset(dag.internalizeall(common))
2123 all = dag.ancestorset(dag.internalizeall(common))
2124 common = dag.externalizeall(dag.headsetofconnecteds(all))
2124 common = dag.externalizeall(dag.headsetofconnecteds(all))
2125 else:
2125 else:
2126 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2126 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2127 common = set(common)
2127 common = set(common)
2128 rheads = set(hds)
2128 rheads = set(hds)
2129 lheads = set(repo.heads())
2129 lheads = set(repo.heads())
2130 ui.write(("common heads: %s\n") %
2130 ui.write(("common heads: %s\n") %
2131 " ".join(sorted(short(n) for n in common)))
2131 " ".join(sorted(short(n) for n in common)))
2132 if lheads <= common:
2132 if lheads <= common:
2133 ui.write(("local is subset\n"))
2133 ui.write(("local is subset\n"))
2134 elif rheads <= common:
2134 elif rheads <= common:
2135 ui.write(("remote is subset\n"))
2135 ui.write(("remote is subset\n"))
2136
2136
2137 serverlogs = opts.get('serverlog')
2137 serverlogs = opts.get('serverlog')
2138 if serverlogs:
2138 if serverlogs:
2139 for filename in serverlogs:
2139 for filename in serverlogs:
2140 logfile = open(filename, 'r')
2140 logfile = open(filename, 'r')
2141 try:
2141 try:
2142 line = logfile.readline()
2142 line = logfile.readline()
2143 while line:
2143 while line:
2144 parts = line.strip().split(';')
2144 parts = line.strip().split(';')
2145 op = parts[1]
2145 op = parts[1]
2146 if op == 'cg':
2146 if op == 'cg':
2147 pass
2147 pass
2148 elif op == 'cgss':
2148 elif op == 'cgss':
2149 doit(parts[2].split(' '), parts[3].split(' '))
2149 doit(parts[2].split(' '), parts[3].split(' '))
2150 elif op == 'unb':
2150 elif op == 'unb':
2151 doit(parts[3].split(' '), parts[2].split(' '))
2151 doit(parts[3].split(' '), parts[2].split(' '))
2152 line = logfile.readline()
2152 line = logfile.readline()
2153 finally:
2153 finally:
2154 logfile.close()
2154 logfile.close()
2155
2155
2156 else:
2156 else:
2157 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2157 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2158 opts.get('remote_head'))
2158 opts.get('remote_head'))
2159 localrevs = opts.get('local_head')
2159 localrevs = opts.get('local_head')
2160 doit(localrevs, remoterevs)
2160 doit(localrevs, remoterevs)
2161
2161
2162 @command('debugfileset',
2162 @command('debugfileset',
2163 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2163 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2164 _('[-r REV] FILESPEC'))
2164 _('[-r REV] FILESPEC'))
2165 def debugfileset(ui, repo, expr, **opts):
2165 def debugfileset(ui, repo, expr, **opts):
2166 '''parse and apply a fileset specification'''
2166 '''parse and apply a fileset specification'''
2167 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2167 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2168 if ui.verbose:
2168 if ui.verbose:
2169 tree = fileset.parse(expr)[0]
2169 tree = fileset.parse(expr)[0]
2170 ui.note(tree, "\n")
2170 ui.note(tree, "\n")
2171
2171
2172 for f in ctx.getfileset(expr):
2172 for f in ctx.getfileset(expr):
2173 ui.write("%s\n" % f)
2173 ui.write("%s\n" % f)
2174
2174
2175 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2175 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2176 def debugfsinfo(ui, path="."):
2176 def debugfsinfo(ui, path="."):
2177 """show information detected about current filesystem"""
2177 """show information detected about current filesystem"""
2178 util.writefile('.debugfsinfo', '')
2178 util.writefile('.debugfsinfo', '')
2179 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2179 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2180 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2180 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2181 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2181 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2182 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2182 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2183 and 'yes' or 'no'))
2183 and 'yes' or 'no'))
2184 os.unlink('.debugfsinfo')
2184 os.unlink('.debugfsinfo')
2185
2185
2186 @command('debuggetbundle',
2186 @command('debuggetbundle',
2187 [('H', 'head', [], _('id of head node'), _('ID')),
2187 [('H', 'head', [], _('id of head node'), _('ID')),
2188 ('C', 'common', [], _('id of common node'), _('ID')),
2188 ('C', 'common', [], _('id of common node'), _('ID')),
2189 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2189 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2190 _('REPO FILE [-H|-C ID]...'),
2190 _('REPO FILE [-H|-C ID]...'),
2191 norepo=True)
2191 norepo=True)
2192 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2192 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2193 """retrieves a bundle from a repo
2193 """retrieves a bundle from a repo
2194
2194
2195 Every ID must be a full-length hex node id string. Saves the bundle to the
2195 Every ID must be a full-length hex node id string. Saves the bundle to the
2196 given file.
2196 given file.
2197 """
2197 """
2198 repo = hg.peer(ui, opts, repopath)
2198 repo = hg.peer(ui, opts, repopath)
2199 if not repo.capable('getbundle'):
2199 if not repo.capable('getbundle'):
2200 raise util.Abort("getbundle() not supported by target repository")
2200 raise util.Abort("getbundle() not supported by target repository")
2201 args = {}
2201 args = {}
2202 if common:
2202 if common:
2203 args['common'] = [bin(s) for s in common]
2203 args['common'] = [bin(s) for s in common]
2204 if head:
2204 if head:
2205 args['heads'] = [bin(s) for s in head]
2205 args['heads'] = [bin(s) for s in head]
2206 # TODO: get desired bundlecaps from command line.
2206 # TODO: get desired bundlecaps from command line.
2207 args['bundlecaps'] = None
2207 args['bundlecaps'] = None
2208 bundle = repo.getbundle('debug', **args)
2208 bundle = repo.getbundle('debug', **args)
2209
2209
2210 bundletype = opts.get('type', 'bzip2').lower()
2210 bundletype = opts.get('type', 'bzip2').lower()
2211 btypes = {'none': 'HG10UN',
2211 btypes = {'none': 'HG10UN',
2212 'bzip2': 'HG10BZ',
2212 'bzip2': 'HG10BZ',
2213 'gzip': 'HG10GZ',
2213 'gzip': 'HG10GZ',
2214 'bundle2': 'HG2Y'}
2214 'bundle2': 'HG2Y'}
2215 bundletype = btypes.get(bundletype)
2215 bundletype = btypes.get(bundletype)
2216 if bundletype not in changegroup.bundletypes:
2216 if bundletype not in changegroup.bundletypes:
2217 raise util.Abort(_('unknown bundle type specified with --type'))
2217 raise util.Abort(_('unknown bundle type specified with --type'))
2218 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2218 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2219
2219
2220 @command('debugignore', [], '')
2220 @command('debugignore', [], '')
2221 def debugignore(ui, repo, *values, **opts):
2221 def debugignore(ui, repo, *values, **opts):
2222 """display the combined ignore pattern"""
2222 """display the combined ignore pattern"""
2223 ignore = repo.dirstate._ignore
2223 ignore = repo.dirstate._ignore
2224 includepat = getattr(ignore, 'includepat', None)
2224 includepat = getattr(ignore, 'includepat', None)
2225 if includepat is not None:
2225 if includepat is not None:
2226 ui.write("%s\n" % includepat)
2226 ui.write("%s\n" % includepat)
2227 else:
2227 else:
2228 raise util.Abort(_("no ignore patterns found"))
2228 raise util.Abort(_("no ignore patterns found"))
2229
2229
2230 @command('debugindex',
2230 @command('debugindex',
2231 [('c', 'changelog', False, _('open changelog')),
2231 [('c', 'changelog', False, _('open changelog')),
2232 ('m', 'manifest', False, _('open manifest')),
2232 ('m', 'manifest', False, _('open manifest')),
2233 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2233 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2234 _('[-f FORMAT] -c|-m|FILE'),
2234 _('[-f FORMAT] -c|-m|FILE'),
2235 optionalrepo=True)
2235 optionalrepo=True)
2236 def debugindex(ui, repo, file_=None, **opts):
2236 def debugindex(ui, repo, file_=None, **opts):
2237 """dump the contents of an index file"""
2237 """dump the contents of an index file"""
2238 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2238 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2239 format = opts.get('format', 0)
2239 format = opts.get('format', 0)
2240 if format not in (0, 1):
2240 if format not in (0, 1):
2241 raise util.Abort(_("unknown format %d") % format)
2241 raise util.Abort(_("unknown format %d") % format)
2242
2242
2243 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2243 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2244 if generaldelta:
2244 if generaldelta:
2245 basehdr = ' delta'
2245 basehdr = ' delta'
2246 else:
2246 else:
2247 basehdr = ' base'
2247 basehdr = ' base'
2248
2248
2249 if ui.debugflag:
2249 if ui.debugflag:
2250 shortfn = hex
2250 shortfn = hex
2251 else:
2251 else:
2252 shortfn = short
2252 shortfn = short
2253
2253
2254 # There might not be anything in r, so have a sane default
2254 # There might not be anything in r, so have a sane default
2255 idlen = 12
2255 idlen = 12
2256 for i in r:
2256 for i in r:
2257 idlen = len(shortfn(r.node(i)))
2257 idlen = len(shortfn(r.node(i)))
2258 break
2258 break
2259
2259
2260 if format == 0:
2260 if format == 0:
2261 ui.write(" rev offset length " + basehdr + " linkrev"
2261 ui.write(" rev offset length " + basehdr + " linkrev"
2262 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2262 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2263 elif format == 1:
2263 elif format == 1:
2264 ui.write(" rev flag offset length"
2264 ui.write(" rev flag offset length"
2265 " size " + basehdr + " link p1 p2"
2265 " size " + basehdr + " link p1 p2"
2266 " %s\n" % "nodeid".rjust(idlen))
2266 " %s\n" % "nodeid".rjust(idlen))
2267
2267
2268 for i in r:
2268 for i in r:
2269 node = r.node(i)
2269 node = r.node(i)
2270 if generaldelta:
2270 if generaldelta:
2271 base = r.deltaparent(i)
2271 base = r.deltaparent(i)
2272 else:
2272 else:
2273 base = r.chainbase(i)
2273 base = r.chainbase(i)
2274 if format == 0:
2274 if format == 0:
2275 try:
2275 try:
2276 pp = r.parents(node)
2276 pp = r.parents(node)
2277 except Exception:
2277 except Exception:
2278 pp = [nullid, nullid]
2278 pp = [nullid, nullid]
2279 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2279 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2280 i, r.start(i), r.length(i), base, r.linkrev(i),
2280 i, r.start(i), r.length(i), base, r.linkrev(i),
2281 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2281 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2282 elif format == 1:
2282 elif format == 1:
2283 pr = r.parentrevs(i)
2283 pr = r.parentrevs(i)
2284 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2284 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2285 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2285 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2286 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2286 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2287
2287
2288 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2288 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2289 def debugindexdot(ui, repo, file_):
2289 def debugindexdot(ui, repo, file_):
2290 """dump an index DAG as a graphviz dot file"""
2290 """dump an index DAG as a graphviz dot file"""
2291 r = None
2291 r = None
2292 if repo:
2292 if repo:
2293 filelog = repo.file(file_)
2293 filelog = repo.file(file_)
2294 if len(filelog):
2294 if len(filelog):
2295 r = filelog
2295 r = filelog
2296 if not r:
2296 if not r:
2297 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2297 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2298 ui.write(("digraph G {\n"))
2298 ui.write(("digraph G {\n"))
2299 for i in r:
2299 for i in r:
2300 node = r.node(i)
2300 node = r.node(i)
2301 pp = r.parents(node)
2301 pp = r.parents(node)
2302 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2302 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2303 if pp[1] != nullid:
2303 if pp[1] != nullid:
2304 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2304 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2305 ui.write("}\n")
2305 ui.write("}\n")
2306
2306
2307 @command('debuginstall', [], '', norepo=True)
2307 @command('debuginstall', [], '', norepo=True)
2308 def debuginstall(ui):
2308 def debuginstall(ui):
2309 '''test Mercurial installation
2309 '''test Mercurial installation
2310
2310
2311 Returns 0 on success.
2311 Returns 0 on success.
2312 '''
2312 '''
2313
2313
2314 def writetemp(contents):
2314 def writetemp(contents):
2315 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2315 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2316 f = os.fdopen(fd, "wb")
2316 f = os.fdopen(fd, "wb")
2317 f.write(contents)
2317 f.write(contents)
2318 f.close()
2318 f.close()
2319 return name
2319 return name
2320
2320
2321 problems = 0
2321 problems = 0
2322
2322
2323 # encoding
2323 # encoding
2324 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2324 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2325 try:
2325 try:
2326 encoding.fromlocal("test")
2326 encoding.fromlocal("test")
2327 except util.Abort, inst:
2327 except util.Abort, inst:
2328 ui.write(" %s\n" % inst)
2328 ui.write(" %s\n" % inst)
2329 ui.write(_(" (check that your locale is properly set)\n"))
2329 ui.write(_(" (check that your locale is properly set)\n"))
2330 problems += 1
2330 problems += 1
2331
2331
2332 # Python
2332 # Python
2333 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2333 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2334 ui.status(_("checking Python version (%s)\n")
2334 ui.status(_("checking Python version (%s)\n")
2335 % ("%s.%s.%s" % sys.version_info[:3]))
2335 % ("%s.%s.%s" % sys.version_info[:3]))
2336 ui.status(_("checking Python lib (%s)...\n")
2336 ui.status(_("checking Python lib (%s)...\n")
2337 % os.path.dirname(os.__file__))
2337 % os.path.dirname(os.__file__))
2338
2338
2339 # compiled modules
2339 # compiled modules
2340 ui.status(_("checking installed modules (%s)...\n")
2340 ui.status(_("checking installed modules (%s)...\n")
2341 % os.path.dirname(__file__))
2341 % os.path.dirname(__file__))
2342 try:
2342 try:
2343 import bdiff, mpatch, base85, osutil
2343 import bdiff, mpatch, base85, osutil
2344 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2344 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2345 except Exception, inst:
2345 except Exception, inst:
2346 ui.write(" %s\n" % inst)
2346 ui.write(" %s\n" % inst)
2347 ui.write(_(" One or more extensions could not be found"))
2347 ui.write(_(" One or more extensions could not be found"))
2348 ui.write(_(" (check that you compiled the extensions)\n"))
2348 ui.write(_(" (check that you compiled the extensions)\n"))
2349 problems += 1
2349 problems += 1
2350
2350
2351 # templates
2351 # templates
2352 import templater
2352 import templater
2353 p = templater.templatepaths()
2353 p = templater.templatepaths()
2354 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2354 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2355 if p:
2355 if p:
2356 m = templater.templatepath("map-cmdline.default")
2356 m = templater.templatepath("map-cmdline.default")
2357 if m:
2357 if m:
2358 # template found, check if it is working
2358 # template found, check if it is working
2359 try:
2359 try:
2360 templater.templater(m)
2360 templater.templater(m)
2361 except Exception, inst:
2361 except Exception, inst:
2362 ui.write(" %s\n" % inst)
2362 ui.write(" %s\n" % inst)
2363 p = None
2363 p = None
2364 else:
2364 else:
2365 ui.write(_(" template 'default' not found\n"))
2365 ui.write(_(" template 'default' not found\n"))
2366 p = None
2366 p = None
2367 else:
2367 else:
2368 ui.write(_(" no template directories found\n"))
2368 ui.write(_(" no template directories found\n"))
2369 if not p:
2369 if not p:
2370 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2370 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2371 problems += 1
2371 problems += 1
2372
2372
2373 # editor
2373 # editor
2374 ui.status(_("checking commit editor...\n"))
2374 ui.status(_("checking commit editor...\n"))
2375 editor = ui.geteditor()
2375 editor = ui.geteditor()
2376 cmdpath = util.findexe(shlex.split(editor)[0])
2376 cmdpath = util.findexe(shlex.split(editor)[0])
2377 if not cmdpath:
2377 if not cmdpath:
2378 if editor == 'vi':
2378 if editor == 'vi':
2379 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2379 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2380 ui.write(_(" (specify a commit editor in your configuration"
2380 ui.write(_(" (specify a commit editor in your configuration"
2381 " file)\n"))
2381 " file)\n"))
2382 else:
2382 else:
2383 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2383 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2384 ui.write(_(" (specify a commit editor in your configuration"
2384 ui.write(_(" (specify a commit editor in your configuration"
2385 " file)\n"))
2385 " file)\n"))
2386 problems += 1
2386 problems += 1
2387
2387
2388 # check username
2388 # check username
2389 ui.status(_("checking username...\n"))
2389 ui.status(_("checking username...\n"))
2390 try:
2390 try:
2391 ui.username()
2391 ui.username()
2392 except util.Abort, e:
2392 except util.Abort, e:
2393 ui.write(" %s\n" % e)
2393 ui.write(" %s\n" % e)
2394 ui.write(_(" (specify a username in your configuration file)\n"))
2394 ui.write(_(" (specify a username in your configuration file)\n"))
2395 problems += 1
2395 problems += 1
2396
2396
2397 if not problems:
2397 if not problems:
2398 ui.status(_("no problems detected\n"))
2398 ui.status(_("no problems detected\n"))
2399 else:
2399 else:
2400 ui.write(_("%s problems detected,"
2400 ui.write(_("%s problems detected,"
2401 " please check your install!\n") % problems)
2401 " please check your install!\n") % problems)
2402
2402
2403 return problems
2403 return problems
2404
2404
2405 @command('debugknown', [], _('REPO ID...'), norepo=True)
2405 @command('debugknown', [], _('REPO ID...'), norepo=True)
2406 def debugknown(ui, repopath, *ids, **opts):
2406 def debugknown(ui, repopath, *ids, **opts):
2407 """test whether node ids are known to a repo
2407 """test whether node ids are known to a repo
2408
2408
2409 Every ID must be a full-length hex node id string. Returns a list of 0s
2409 Every ID must be a full-length hex node id string. Returns a list of 0s
2410 and 1s indicating unknown/known.
2410 and 1s indicating unknown/known.
2411 """
2411 """
2412 repo = hg.peer(ui, opts, repopath)
2412 repo = hg.peer(ui, opts, repopath)
2413 if not repo.capable('known'):
2413 if not repo.capable('known'):
2414 raise util.Abort("known() not supported by target repository")
2414 raise util.Abort("known() not supported by target repository")
2415 flags = repo.known([bin(s) for s in ids])
2415 flags = repo.known([bin(s) for s in ids])
2416 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2416 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2417
2417
2418 @command('debuglabelcomplete', [], _('LABEL...'))
2418 @command('debuglabelcomplete', [], _('LABEL...'))
2419 def debuglabelcomplete(ui, repo, *args):
2419 def debuglabelcomplete(ui, repo, *args):
2420 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2420 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2421 debugnamecomplete(ui, repo, *args)
2421 debugnamecomplete(ui, repo, *args)
2422
2422
2423 @command('debugnamecomplete', [], _('NAME...'))
2423 @command('debugnamecomplete', [], _('NAME...'))
2424 def debugnamecomplete(ui, repo, *args):
2424 def debugnamecomplete(ui, repo, *args):
2425 '''complete "names" - tags, open branch names, bookmark names'''
2425 '''complete "names" - tags, open branch names, bookmark names'''
2426
2426
2427 names = set()
2427 names = set()
2428 # since we previously only listed open branches, we will handle that
2428 # since we previously only listed open branches, we will handle that
2429 # specially (after this for loop)
2429 # specially (after this for loop)
2430 for name, ns in repo.names.iteritems():
2430 for name, ns in repo.names.iteritems():
2431 if name != 'branches':
2431 if name != 'branches':
2432 names.update(ns.listnames(repo))
2432 names.update(ns.listnames(repo))
2433 names.update(tag for (tag, heads, tip, closed)
2433 names.update(tag for (tag, heads, tip, closed)
2434 in repo.branchmap().iterbranches() if not closed)
2434 in repo.branchmap().iterbranches() if not closed)
2435 completions = set()
2435 completions = set()
2436 if not args:
2436 if not args:
2437 args = ['']
2437 args = ['']
2438 for a in args:
2438 for a in args:
2439 completions.update(n for n in names if n.startswith(a))
2439 completions.update(n for n in names if n.startswith(a))
2440 ui.write('\n'.join(sorted(completions)))
2440 ui.write('\n'.join(sorted(completions)))
2441 ui.write('\n')
2441 ui.write('\n')
2442
2442
2443 @command('debuglocks',
2443 @command('debuglocks',
2444 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2444 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2445 ('W', 'force-wlock', None,
2445 ('W', 'force-wlock', None,
2446 _('free the working state lock (DANGEROUS)'))],
2446 _('free the working state lock (DANGEROUS)'))],
2447 _('[OPTION]...'))
2447 _('[OPTION]...'))
2448 def debuglocks(ui, repo, **opts):
2448 def debuglocks(ui, repo, **opts):
2449 """show or modify state of locks
2449 """show or modify state of locks
2450
2450
2451 By default, this command will show which locks are held. This
2451 By default, this command will show which locks are held. This
2452 includes the user and process holding the lock, the amount of time
2452 includes the user and process holding the lock, the amount of time
2453 the lock has been held, and the machine name where the process is
2453 the lock has been held, and the machine name where the process is
2454 running if it's not local.
2454 running if it's not local.
2455
2455
2456 Locks protect the integrity of Mercurial's data, so should be
2456 Locks protect the integrity of Mercurial's data, so should be
2457 treated with care. System crashes or other interruptions may cause
2457 treated with care. System crashes or other interruptions may cause
2458 locks to not be properly released, though Mercurial will usually
2458 locks to not be properly released, though Mercurial will usually
2459 detect and remove such stale locks automatically.
2459 detect and remove such stale locks automatically.
2460
2460
2461 However, detecting stale locks may not always be possible (for
2461 However, detecting stale locks may not always be possible (for
2462 instance, on a shared filesystem). Removing locks may also be
2462 instance, on a shared filesystem). Removing locks may also be
2463 blocked by filesystem permissions.
2463 blocked by filesystem permissions.
2464
2464
2465 Returns 0 if no locks are held.
2465 Returns 0 if no locks are held.
2466
2466
2467 """
2467 """
2468
2468
2469 if opts.get('force_lock'):
2469 if opts.get('force_lock'):
2470 repo.svfs.unlink('lock')
2470 repo.svfs.unlink('lock')
2471 if opts.get('force_wlock'):
2471 if opts.get('force_wlock'):
2472 repo.vfs.unlink('wlock')
2472 repo.vfs.unlink('wlock')
2473 if opts.get('force_lock') or opts.get('force_lock'):
2473 if opts.get('force_lock') or opts.get('force_lock'):
2474 return 0
2474 return 0
2475
2475
2476 now = time.time()
2476 now = time.time()
2477 held = 0
2477 held = 0
2478
2478
2479 def report(vfs, name, method):
2479 def report(vfs, name, method):
2480 # this causes stale locks to get reaped for more accurate reporting
2480 # this causes stale locks to get reaped for more accurate reporting
2481 try:
2481 try:
2482 l = method(False)
2482 l = method(False)
2483 except error.LockHeld:
2483 except error.LockHeld:
2484 l = None
2484 l = None
2485
2485
2486 if l:
2486 if l:
2487 l.release()
2487 l.release()
2488 else:
2488 else:
2489 try:
2489 try:
2490 stat = repo.svfs.lstat(name)
2490 stat = repo.svfs.lstat(name)
2491 age = now - stat.st_mtime
2491 age = now - stat.st_mtime
2492 user = util.username(stat.st_uid)
2492 user = util.username(stat.st_uid)
2493 locker = vfs.readlock(name)
2493 locker = vfs.readlock(name)
2494 if ":" in locker:
2494 if ":" in locker:
2495 host, pid = locker.split(':')
2495 host, pid = locker.split(':')
2496 if host == socket.gethostname():
2496 if host == socket.gethostname():
2497 locker = 'user %s, process %s' % (user, pid)
2497 locker = 'user %s, process %s' % (user, pid)
2498 else:
2498 else:
2499 locker = 'user %s, process %s, host %s' \
2499 locker = 'user %s, process %s, host %s' \
2500 % (user, pid, host)
2500 % (user, pid, host)
2501 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2501 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2502 return 1
2502 return 1
2503 except OSError, e:
2503 except OSError, e:
2504 if e.errno != errno.ENOENT:
2504 if e.errno != errno.ENOENT:
2505 raise
2505 raise
2506
2506
2507 ui.write("%-6s free\n" % (name + ":"))
2507 ui.write("%-6s free\n" % (name + ":"))
2508 return 0
2508 return 0
2509
2509
2510 held += report(repo.svfs, "lock", repo.lock)
2510 held += report(repo.svfs, "lock", repo.lock)
2511 held += report(repo.vfs, "wlock", repo.wlock)
2511 held += report(repo.vfs, "wlock", repo.wlock)
2512
2512
2513 return held
2513 return held
2514
2514
2515 @command('debugobsolete',
2515 @command('debugobsolete',
2516 [('', 'flags', 0, _('markers flag')),
2516 [('', 'flags', 0, _('markers flag')),
2517 ('', 'record-parents', False,
2517 ('', 'record-parents', False,
2518 _('record parent information for the precursor')),
2518 _('record parent information for the precursor')),
2519 ('r', 'rev', [], _('display markers relevant to REV')),
2519 ('r', 'rev', [], _('display markers relevant to REV')),
2520 ] + commitopts2,
2520 ] + commitopts2,
2521 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2521 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2522 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2522 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2523 """create arbitrary obsolete marker
2523 """create arbitrary obsolete marker
2524
2524
2525 With no arguments, displays the list of obsolescence markers."""
2525 With no arguments, displays the list of obsolescence markers."""
2526
2526
2527 def parsenodeid(s):
2527 def parsenodeid(s):
2528 try:
2528 try:
2529 # We do not use revsingle/revrange functions here to accept
2529 # We do not use revsingle/revrange functions here to accept
2530 # arbitrary node identifiers, possibly not present in the
2530 # arbitrary node identifiers, possibly not present in the
2531 # local repository.
2531 # local repository.
2532 n = bin(s)
2532 n = bin(s)
2533 if len(n) != len(nullid):
2533 if len(n) != len(nullid):
2534 raise TypeError()
2534 raise TypeError()
2535 return n
2535 return n
2536 except TypeError:
2536 except TypeError:
2537 raise util.Abort('changeset references must be full hexadecimal '
2537 raise util.Abort('changeset references must be full hexadecimal '
2538 'node identifiers')
2538 'node identifiers')
2539
2539
2540 if precursor is not None:
2540 if precursor is not None:
2541 if opts['rev']:
2541 if opts['rev']:
2542 raise util.Abort('cannot select revision when creating marker')
2542 raise util.Abort('cannot select revision when creating marker')
2543 metadata = {}
2543 metadata = {}
2544 metadata['user'] = opts['user'] or ui.username()
2544 metadata['user'] = opts['user'] or ui.username()
2545 succs = tuple(parsenodeid(succ) for succ in successors)
2545 succs = tuple(parsenodeid(succ) for succ in successors)
2546 l = repo.lock()
2546 l = repo.lock()
2547 try:
2547 try:
2548 tr = repo.transaction('debugobsolete')
2548 tr = repo.transaction('debugobsolete')
2549 try:
2549 try:
2550 try:
2550 try:
2551 date = opts.get('date')
2551 date = opts.get('date')
2552 if date:
2552 if date:
2553 date = util.parsedate(date)
2553 date = util.parsedate(date)
2554 else:
2554 else:
2555 date = None
2555 date = None
2556 prec = parsenodeid(precursor)
2556 prec = parsenodeid(precursor)
2557 parents = None
2557 parents = None
2558 if opts['record_parents']:
2558 if opts['record_parents']:
2559 if prec not in repo.unfiltered():
2559 if prec not in repo.unfiltered():
2560 raise util.Abort('cannot used --record-parents on '
2560 raise util.Abort('cannot used --record-parents on '
2561 'unknown changesets')
2561 'unknown changesets')
2562 parents = repo.unfiltered()[prec].parents()
2562 parents = repo.unfiltered()[prec].parents()
2563 parents = tuple(p.node() for p in parents)
2563 parents = tuple(p.node() for p in parents)
2564 repo.obsstore.create(tr, prec, succs, opts['flags'],
2564 repo.obsstore.create(tr, prec, succs, opts['flags'],
2565 parents=parents, date=date,
2565 parents=parents, date=date,
2566 metadata=metadata)
2566 metadata=metadata)
2567 tr.close()
2567 tr.close()
2568 except ValueError, exc:
2568 except ValueError, exc:
2569 raise util.Abort(_('bad obsmarker input: %s') % exc)
2569 raise util.Abort(_('bad obsmarker input: %s') % exc)
2570 finally:
2570 finally:
2571 tr.release()
2571 tr.release()
2572 finally:
2572 finally:
2573 l.release()
2573 l.release()
2574 else:
2574 else:
2575 if opts['rev']:
2575 if opts['rev']:
2576 revs = scmutil.revrange(repo, opts['rev'])
2576 revs = scmutil.revrange(repo, opts['rev'])
2577 nodes = [repo[r].node() for r in revs]
2577 nodes = [repo[r].node() for r in revs]
2578 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2578 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2579 markers.sort(key=lambda x: x._data)
2579 markers.sort(key=lambda x: x._data)
2580 else:
2580 else:
2581 markers = obsolete.getmarkers(repo)
2581 markers = obsolete.getmarkers(repo)
2582
2582
2583 for m in markers:
2583 for m in markers:
2584 cmdutil.showmarker(ui, m)
2584 cmdutil.showmarker(ui, m)
2585
2585
2586 @command('debugpathcomplete',
2586 @command('debugpathcomplete',
2587 [('f', 'full', None, _('complete an entire path')),
2587 [('f', 'full', None, _('complete an entire path')),
2588 ('n', 'normal', None, _('show only normal files')),
2588 ('n', 'normal', None, _('show only normal files')),
2589 ('a', 'added', None, _('show only added files')),
2589 ('a', 'added', None, _('show only added files')),
2590 ('r', 'removed', None, _('show only removed files'))],
2590 ('r', 'removed', None, _('show only removed files'))],
2591 _('FILESPEC...'))
2591 _('FILESPEC...'))
2592 def debugpathcomplete(ui, repo, *specs, **opts):
2592 def debugpathcomplete(ui, repo, *specs, **opts):
2593 '''complete part or all of a tracked path
2593 '''complete part or all of a tracked path
2594
2594
2595 This command supports shells that offer path name completion. It
2595 This command supports shells that offer path name completion. It
2596 currently completes only files already known to the dirstate.
2596 currently completes only files already known to the dirstate.
2597
2597
2598 Completion extends only to the next path segment unless
2598 Completion extends only to the next path segment unless
2599 --full is specified, in which case entire paths are used.'''
2599 --full is specified, in which case entire paths are used.'''
2600
2600
2601 def complete(path, acceptable):
2601 def complete(path, acceptable):
2602 dirstate = repo.dirstate
2602 dirstate = repo.dirstate
2603 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2603 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2604 rootdir = repo.root + os.sep
2604 rootdir = repo.root + os.sep
2605 if spec != repo.root and not spec.startswith(rootdir):
2605 if spec != repo.root and not spec.startswith(rootdir):
2606 return [], []
2606 return [], []
2607 if os.path.isdir(spec):
2607 if os.path.isdir(spec):
2608 spec += '/'
2608 spec += '/'
2609 spec = spec[len(rootdir):]
2609 spec = spec[len(rootdir):]
2610 fixpaths = os.sep != '/'
2610 fixpaths = os.sep != '/'
2611 if fixpaths:
2611 if fixpaths:
2612 spec = spec.replace(os.sep, '/')
2612 spec = spec.replace(os.sep, '/')
2613 speclen = len(spec)
2613 speclen = len(spec)
2614 fullpaths = opts['full']
2614 fullpaths = opts['full']
2615 files, dirs = set(), set()
2615 files, dirs = set(), set()
2616 adddir, addfile = dirs.add, files.add
2616 adddir, addfile = dirs.add, files.add
2617 for f, st in dirstate.iteritems():
2617 for f, st in dirstate.iteritems():
2618 if f.startswith(spec) and st[0] in acceptable:
2618 if f.startswith(spec) and st[0] in acceptable:
2619 if fixpaths:
2619 if fixpaths:
2620 f = f.replace('/', os.sep)
2620 f = f.replace('/', os.sep)
2621 if fullpaths:
2621 if fullpaths:
2622 addfile(f)
2622 addfile(f)
2623 continue
2623 continue
2624 s = f.find(os.sep, speclen)
2624 s = f.find(os.sep, speclen)
2625 if s >= 0:
2625 if s >= 0:
2626 adddir(f[:s])
2626 adddir(f[:s])
2627 else:
2627 else:
2628 addfile(f)
2628 addfile(f)
2629 return files, dirs
2629 return files, dirs
2630
2630
2631 acceptable = ''
2631 acceptable = ''
2632 if opts['normal']:
2632 if opts['normal']:
2633 acceptable += 'nm'
2633 acceptable += 'nm'
2634 if opts['added']:
2634 if opts['added']:
2635 acceptable += 'a'
2635 acceptable += 'a'
2636 if opts['removed']:
2636 if opts['removed']:
2637 acceptable += 'r'
2637 acceptable += 'r'
2638 cwd = repo.getcwd()
2638 cwd = repo.getcwd()
2639 if not specs:
2639 if not specs:
2640 specs = ['.']
2640 specs = ['.']
2641
2641
2642 files, dirs = set(), set()
2642 files, dirs = set(), set()
2643 for spec in specs:
2643 for spec in specs:
2644 f, d = complete(spec, acceptable or 'nmar')
2644 f, d = complete(spec, acceptable or 'nmar')
2645 files.update(f)
2645 files.update(f)
2646 dirs.update(d)
2646 dirs.update(d)
2647 files.update(dirs)
2647 files.update(dirs)
2648 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2648 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2649 ui.write('\n')
2649 ui.write('\n')
2650
2650
2651 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2651 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2652 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2652 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2653 '''access the pushkey key/value protocol
2653 '''access the pushkey key/value protocol
2654
2654
2655 With two args, list the keys in the given namespace.
2655 With two args, list the keys in the given namespace.
2656
2656
2657 With five args, set a key to new if it currently is set to old.
2657 With five args, set a key to new if it currently is set to old.
2658 Reports success or failure.
2658 Reports success or failure.
2659 '''
2659 '''
2660
2660
2661 target = hg.peer(ui, {}, repopath)
2661 target = hg.peer(ui, {}, repopath)
2662 if keyinfo:
2662 if keyinfo:
2663 key, old, new = keyinfo
2663 key, old, new = keyinfo
2664 r = target.pushkey(namespace, key, old, new)
2664 r = target.pushkey(namespace, key, old, new)
2665 ui.status(str(r) + '\n')
2665 ui.status(str(r) + '\n')
2666 return not r
2666 return not r
2667 else:
2667 else:
2668 for k, v in sorted(target.listkeys(namespace).iteritems()):
2668 for k, v in sorted(target.listkeys(namespace).iteritems()):
2669 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2669 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2670 v.encode('string-escape')))
2670 v.encode('string-escape')))
2671
2671
2672 @command('debugpvec', [], _('A B'))
2672 @command('debugpvec', [], _('A B'))
2673 def debugpvec(ui, repo, a, b=None):
2673 def debugpvec(ui, repo, a, b=None):
2674 ca = scmutil.revsingle(repo, a)
2674 ca = scmutil.revsingle(repo, a)
2675 cb = scmutil.revsingle(repo, b)
2675 cb = scmutil.revsingle(repo, b)
2676 pa = pvec.ctxpvec(ca)
2676 pa = pvec.ctxpvec(ca)
2677 pb = pvec.ctxpvec(cb)
2677 pb = pvec.ctxpvec(cb)
2678 if pa == pb:
2678 if pa == pb:
2679 rel = "="
2679 rel = "="
2680 elif pa > pb:
2680 elif pa > pb:
2681 rel = ">"
2681 rel = ">"
2682 elif pa < pb:
2682 elif pa < pb:
2683 rel = "<"
2683 rel = "<"
2684 elif pa | pb:
2684 elif pa | pb:
2685 rel = "|"
2685 rel = "|"
2686 ui.write(_("a: %s\n") % pa)
2686 ui.write(_("a: %s\n") % pa)
2687 ui.write(_("b: %s\n") % pb)
2687 ui.write(_("b: %s\n") % pb)
2688 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2688 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2689 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2689 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2690 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2690 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2691 pa.distance(pb), rel))
2691 pa.distance(pb), rel))
2692
2692
2693 @command('debugrebuilddirstate|debugrebuildstate',
2693 @command('debugrebuilddirstate|debugrebuildstate',
2694 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2694 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2695 _('[-r REV]'))
2695 _('[-r REV]'))
2696 def debugrebuilddirstate(ui, repo, rev):
2696 def debugrebuilddirstate(ui, repo, rev):
2697 """rebuild the dirstate as it would look like for the given revision
2697 """rebuild the dirstate as it would look like for the given revision
2698
2698
2699 If no revision is specified the first current parent will be used.
2699 If no revision is specified the first current parent will be used.
2700
2700
2701 The dirstate will be set to the files of the given revision.
2701 The dirstate will be set to the files of the given revision.
2702 The actual working directory content or existing dirstate
2702 The actual working directory content or existing dirstate
2703 information such as adds or removes is not considered.
2703 information such as adds or removes is not considered.
2704
2704
2705 One use of this command is to make the next :hg:`status` invocation
2705 One use of this command is to make the next :hg:`status` invocation
2706 check the actual file content.
2706 check the actual file content.
2707 """
2707 """
2708 ctx = scmutil.revsingle(repo, rev)
2708 ctx = scmutil.revsingle(repo, rev)
2709 wlock = repo.wlock()
2709 wlock = repo.wlock()
2710 try:
2710 try:
2711 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2711 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2712 finally:
2712 finally:
2713 wlock.release()
2713 wlock.release()
2714
2714
2715 @command('debugrename',
2715 @command('debugrename',
2716 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2716 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2717 _('[-r REV] FILE'))
2717 _('[-r REV] FILE'))
2718 def debugrename(ui, repo, file1, *pats, **opts):
2718 def debugrename(ui, repo, file1, *pats, **opts):
2719 """dump rename information"""
2719 """dump rename information"""
2720
2720
2721 ctx = scmutil.revsingle(repo, opts.get('rev'))
2721 ctx = scmutil.revsingle(repo, opts.get('rev'))
2722 m = scmutil.match(ctx, (file1,) + pats, opts)
2722 m = scmutil.match(ctx, (file1,) + pats, opts)
2723 for abs in ctx.walk(m):
2723 for abs in ctx.walk(m):
2724 fctx = ctx[abs]
2724 fctx = ctx[abs]
2725 o = fctx.filelog().renamed(fctx.filenode())
2725 o = fctx.filelog().renamed(fctx.filenode())
2726 rel = m.rel(abs)
2726 rel = m.rel(abs)
2727 if o:
2727 if o:
2728 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2728 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2729 else:
2729 else:
2730 ui.write(_("%s not renamed\n") % rel)
2730 ui.write(_("%s not renamed\n") % rel)
2731
2731
2732 @command('debugrevlog',
2732 @command('debugrevlog',
2733 [('c', 'changelog', False, _('open changelog')),
2733 [('c', 'changelog', False, _('open changelog')),
2734 ('m', 'manifest', False, _('open manifest')),
2734 ('m', 'manifest', False, _('open manifest')),
2735 ('d', 'dump', False, _('dump index data'))],
2735 ('d', 'dump', False, _('dump index data'))],
2736 _('-c|-m|FILE'),
2736 _('-c|-m|FILE'),
2737 optionalrepo=True)
2737 optionalrepo=True)
2738 def debugrevlog(ui, repo, file_=None, **opts):
2738 def debugrevlog(ui, repo, file_=None, **opts):
2739 """show data and statistics about a revlog"""
2739 """show data and statistics about a revlog"""
2740 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2740 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2741
2741
2742 if opts.get("dump"):
2742 if opts.get("dump"):
2743 numrevs = len(r)
2743 numrevs = len(r)
2744 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2744 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2745 " rawsize totalsize compression heads chainlen\n")
2745 " rawsize totalsize compression heads chainlen\n")
2746 ts = 0
2746 ts = 0
2747 heads = set()
2747 heads = set()
2748
2748
2749 for rev in xrange(numrevs):
2749 for rev in xrange(numrevs):
2750 dbase = r.deltaparent(rev)
2750 dbase = r.deltaparent(rev)
2751 if dbase == -1:
2751 if dbase == -1:
2752 dbase = rev
2752 dbase = rev
2753 cbase = r.chainbase(rev)
2753 cbase = r.chainbase(rev)
2754 clen = r.chainlen(rev)
2754 clen = r.chainlen(rev)
2755 p1, p2 = r.parentrevs(rev)
2755 p1, p2 = r.parentrevs(rev)
2756 rs = r.rawsize(rev)
2756 rs = r.rawsize(rev)
2757 ts = ts + rs
2757 ts = ts + rs
2758 heads -= set(r.parentrevs(rev))
2758 heads -= set(r.parentrevs(rev))
2759 heads.add(rev)
2759 heads.add(rev)
2760 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2760 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2761 "%11d %5d %8d\n" %
2761 "%11d %5d %8d\n" %
2762 (rev, p1, p2, r.start(rev), r.end(rev),
2762 (rev, p1, p2, r.start(rev), r.end(rev),
2763 r.start(dbase), r.start(cbase),
2763 r.start(dbase), r.start(cbase),
2764 r.start(p1), r.start(p2),
2764 r.start(p1), r.start(p2),
2765 rs, ts, ts / r.end(rev), len(heads), clen))
2765 rs, ts, ts / r.end(rev), len(heads), clen))
2766 return 0
2766 return 0
2767
2767
2768 v = r.version
2768 v = r.version
2769 format = v & 0xFFFF
2769 format = v & 0xFFFF
2770 flags = []
2770 flags = []
2771 gdelta = False
2771 gdelta = False
2772 if v & revlog.REVLOGNGINLINEDATA:
2772 if v & revlog.REVLOGNGINLINEDATA:
2773 flags.append('inline')
2773 flags.append('inline')
2774 if v & revlog.REVLOGGENERALDELTA:
2774 if v & revlog.REVLOGGENERALDELTA:
2775 gdelta = True
2775 gdelta = True
2776 flags.append('generaldelta')
2776 flags.append('generaldelta')
2777 if not flags:
2777 if not flags:
2778 flags = ['(none)']
2778 flags = ['(none)']
2779
2779
2780 nummerges = 0
2780 nummerges = 0
2781 numfull = 0
2781 numfull = 0
2782 numprev = 0
2782 numprev = 0
2783 nump1 = 0
2783 nump1 = 0
2784 nump2 = 0
2784 nump2 = 0
2785 numother = 0
2785 numother = 0
2786 nump1prev = 0
2786 nump1prev = 0
2787 nump2prev = 0
2787 nump2prev = 0
2788 chainlengths = []
2788 chainlengths = []
2789
2789
2790 datasize = [None, 0, 0L]
2790 datasize = [None, 0, 0L]
2791 fullsize = [None, 0, 0L]
2791 fullsize = [None, 0, 0L]
2792 deltasize = [None, 0, 0L]
2792 deltasize = [None, 0, 0L]
2793
2793
2794 def addsize(size, l):
2794 def addsize(size, l):
2795 if l[0] is None or size < l[0]:
2795 if l[0] is None or size < l[0]:
2796 l[0] = size
2796 l[0] = size
2797 if size > l[1]:
2797 if size > l[1]:
2798 l[1] = size
2798 l[1] = size
2799 l[2] += size
2799 l[2] += size
2800
2800
2801 numrevs = len(r)
2801 numrevs = len(r)
2802 for rev in xrange(numrevs):
2802 for rev in xrange(numrevs):
2803 p1, p2 = r.parentrevs(rev)
2803 p1, p2 = r.parentrevs(rev)
2804 delta = r.deltaparent(rev)
2804 delta = r.deltaparent(rev)
2805 if format > 0:
2805 if format > 0:
2806 addsize(r.rawsize(rev), datasize)
2806 addsize(r.rawsize(rev), datasize)
2807 if p2 != nullrev:
2807 if p2 != nullrev:
2808 nummerges += 1
2808 nummerges += 1
2809 size = r.length(rev)
2809 size = r.length(rev)
2810 if delta == nullrev:
2810 if delta == nullrev:
2811 chainlengths.append(0)
2811 chainlengths.append(0)
2812 numfull += 1
2812 numfull += 1
2813 addsize(size, fullsize)
2813 addsize(size, fullsize)
2814 else:
2814 else:
2815 chainlengths.append(chainlengths[delta] + 1)
2815 chainlengths.append(chainlengths[delta] + 1)
2816 addsize(size, deltasize)
2816 addsize(size, deltasize)
2817 if delta == rev - 1:
2817 if delta == rev - 1:
2818 numprev += 1
2818 numprev += 1
2819 if delta == p1:
2819 if delta == p1:
2820 nump1prev += 1
2820 nump1prev += 1
2821 elif delta == p2:
2821 elif delta == p2:
2822 nump2prev += 1
2822 nump2prev += 1
2823 elif delta == p1:
2823 elif delta == p1:
2824 nump1 += 1
2824 nump1 += 1
2825 elif delta == p2:
2825 elif delta == p2:
2826 nump2 += 1
2826 nump2 += 1
2827 elif delta != nullrev:
2827 elif delta != nullrev:
2828 numother += 1
2828 numother += 1
2829
2829
2830 # Adjust size min value for empty cases
2830 # Adjust size min value for empty cases
2831 for size in (datasize, fullsize, deltasize):
2831 for size in (datasize, fullsize, deltasize):
2832 if size[0] is None:
2832 if size[0] is None:
2833 size[0] = 0
2833 size[0] = 0
2834
2834
2835 numdeltas = numrevs - numfull
2835 numdeltas = numrevs - numfull
2836 numoprev = numprev - nump1prev - nump2prev
2836 numoprev = numprev - nump1prev - nump2prev
2837 totalrawsize = datasize[2]
2837 totalrawsize = datasize[2]
2838 datasize[2] /= numrevs
2838 datasize[2] /= numrevs
2839 fulltotal = fullsize[2]
2839 fulltotal = fullsize[2]
2840 fullsize[2] /= numfull
2840 fullsize[2] /= numfull
2841 deltatotal = deltasize[2]
2841 deltatotal = deltasize[2]
2842 if numrevs - numfull > 0:
2842 if numrevs - numfull > 0:
2843 deltasize[2] /= numrevs - numfull
2843 deltasize[2] /= numrevs - numfull
2844 totalsize = fulltotal + deltatotal
2844 totalsize = fulltotal + deltatotal
2845 avgchainlen = sum(chainlengths) / numrevs
2845 avgchainlen = sum(chainlengths) / numrevs
2846 maxchainlen = max(chainlengths)
2846 maxchainlen = max(chainlengths)
2847 compratio = totalrawsize / totalsize
2847 compratio = totalrawsize / totalsize
2848
2848
2849 basedfmtstr = '%%%dd\n'
2849 basedfmtstr = '%%%dd\n'
2850 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2850 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2851
2851
2852 def dfmtstr(max):
2852 def dfmtstr(max):
2853 return basedfmtstr % len(str(max))
2853 return basedfmtstr % len(str(max))
2854 def pcfmtstr(max, padding=0):
2854 def pcfmtstr(max, padding=0):
2855 return basepcfmtstr % (len(str(max)), ' ' * padding)
2855 return basepcfmtstr % (len(str(max)), ' ' * padding)
2856
2856
2857 def pcfmt(value, total):
2857 def pcfmt(value, total):
2858 return (value, 100 * float(value) / total)
2858 return (value, 100 * float(value) / total)
2859
2859
2860 ui.write(('format : %d\n') % format)
2860 ui.write(('format : %d\n') % format)
2861 ui.write(('flags : %s\n') % ', '.join(flags))
2861 ui.write(('flags : %s\n') % ', '.join(flags))
2862
2862
2863 ui.write('\n')
2863 ui.write('\n')
2864 fmt = pcfmtstr(totalsize)
2864 fmt = pcfmtstr(totalsize)
2865 fmt2 = dfmtstr(totalsize)
2865 fmt2 = dfmtstr(totalsize)
2866 ui.write(('revisions : ') + fmt2 % numrevs)
2866 ui.write(('revisions : ') + fmt2 % numrevs)
2867 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2867 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2868 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2868 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2869 ui.write(('revisions : ') + fmt2 % numrevs)
2869 ui.write(('revisions : ') + fmt2 % numrevs)
2870 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2870 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2871 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2871 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2872 ui.write(('revision size : ') + fmt2 % totalsize)
2872 ui.write(('revision size : ') + fmt2 % totalsize)
2873 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2873 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2874 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2874 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2875
2875
2876 ui.write('\n')
2876 ui.write('\n')
2877 fmt = dfmtstr(max(avgchainlen, compratio))
2877 fmt = dfmtstr(max(avgchainlen, compratio))
2878 ui.write(('avg chain length : ') + fmt % avgchainlen)
2878 ui.write(('avg chain length : ') + fmt % avgchainlen)
2879 ui.write(('max chain length : ') + fmt % maxchainlen)
2879 ui.write(('max chain length : ') + fmt % maxchainlen)
2880 ui.write(('compression ratio : ') + fmt % compratio)
2880 ui.write(('compression ratio : ') + fmt % compratio)
2881
2881
2882 if format > 0:
2882 if format > 0:
2883 ui.write('\n')
2883 ui.write('\n')
2884 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2884 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2885 % tuple(datasize))
2885 % tuple(datasize))
2886 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2886 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2887 % tuple(fullsize))
2887 % tuple(fullsize))
2888 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2888 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2889 % tuple(deltasize))
2889 % tuple(deltasize))
2890
2890
2891 if numdeltas > 0:
2891 if numdeltas > 0:
2892 ui.write('\n')
2892 ui.write('\n')
2893 fmt = pcfmtstr(numdeltas)
2893 fmt = pcfmtstr(numdeltas)
2894 fmt2 = pcfmtstr(numdeltas, 4)
2894 fmt2 = pcfmtstr(numdeltas, 4)
2895 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2895 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2896 if numprev > 0:
2896 if numprev > 0:
2897 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2897 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2898 numprev))
2898 numprev))
2899 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2899 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2900 numprev))
2900 numprev))
2901 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2901 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2902 numprev))
2902 numprev))
2903 if gdelta:
2903 if gdelta:
2904 ui.write(('deltas against p1 : ')
2904 ui.write(('deltas against p1 : ')
2905 + fmt % pcfmt(nump1, numdeltas))
2905 + fmt % pcfmt(nump1, numdeltas))
2906 ui.write(('deltas against p2 : ')
2906 ui.write(('deltas against p2 : ')
2907 + fmt % pcfmt(nump2, numdeltas))
2907 + fmt % pcfmt(nump2, numdeltas))
2908 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2908 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2909 numdeltas))
2909 numdeltas))
2910
2910
2911 @command('debugrevspec',
2911 @command('debugrevspec',
2912 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2912 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2913 ('REVSPEC'))
2913 ('REVSPEC'))
2914 def debugrevspec(ui, repo, expr, **opts):
2914 def debugrevspec(ui, repo, expr, **opts):
2915 """parse and apply a revision specification
2915 """parse and apply a revision specification
2916
2916
2917 Use --verbose to print the parsed tree before and after aliases
2917 Use --verbose to print the parsed tree before and after aliases
2918 expansion.
2918 expansion.
2919 """
2919 """
2920 if ui.verbose:
2920 if ui.verbose:
2921 tree = revset.parse(expr)[0]
2921 tree = revset.parse(expr)[0]
2922 ui.note(revset.prettyformat(tree), "\n")
2922 ui.note(revset.prettyformat(tree), "\n")
2923 newtree = revset.findaliases(ui, tree)
2923 newtree = revset.findaliases(ui, tree)
2924 if newtree != tree:
2924 if newtree != tree:
2925 ui.note(revset.prettyformat(newtree), "\n")
2925 ui.note(revset.prettyformat(newtree), "\n")
2926 tree = newtree
2926 tree = newtree
2927 newtree = revset.foldconcat(tree)
2927 newtree = revset.foldconcat(tree)
2928 if newtree != tree:
2928 if newtree != tree:
2929 ui.note(revset.prettyformat(newtree), "\n")
2929 ui.note(revset.prettyformat(newtree), "\n")
2930 if opts["optimize"]:
2930 if opts["optimize"]:
2931 weight, optimizedtree = revset.optimize(newtree, True)
2931 weight, optimizedtree = revset.optimize(newtree, True)
2932 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2932 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2933 func = revset.match(ui, expr)
2933 func = revset.match(ui, expr)
2934 revs = func(repo)
2934 revs = func(repo)
2935 if ui.verbose:
2935 if ui.verbose:
2936 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2936 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
2937 for c in revs:
2937 for c in revs:
2938 ui.write("%s\n" % c)
2938 ui.write("%s\n" % c)
2939
2939
2940 @command('debugsetparents', [], _('REV1 [REV2]'))
2940 @command('debugsetparents', [], _('REV1 [REV2]'))
2941 def debugsetparents(ui, repo, rev1, rev2=None):
2941 def debugsetparents(ui, repo, rev1, rev2=None):
2942 """manually set the parents of the current working directory
2942 """manually set the parents of the current working directory
2943
2943
2944 This is useful for writing repository conversion tools, but should
2944 This is useful for writing repository conversion tools, but should
2945 be used with care. For example, neither the working directory nor the
2945 be used with care. For example, neither the working directory nor the
2946 dirstate is updated, so file status may be incorrect after running this
2946 dirstate is updated, so file status may be incorrect after running this
2947 command.
2947 command.
2948
2948
2949 Returns 0 on success.
2949 Returns 0 on success.
2950 """
2950 """
2951
2951
2952 r1 = scmutil.revsingle(repo, rev1).node()
2952 r1 = scmutil.revsingle(repo, rev1).node()
2953 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2953 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2954
2954
2955 wlock = repo.wlock()
2955 wlock = repo.wlock()
2956 try:
2956 try:
2957 repo.dirstate.beginparentchange()
2957 repo.dirstate.beginparentchange()
2958 repo.setparents(r1, r2)
2958 repo.setparents(r1, r2)
2959 repo.dirstate.endparentchange()
2959 repo.dirstate.endparentchange()
2960 finally:
2960 finally:
2961 wlock.release()
2961 wlock.release()
2962
2962
2963 @command('debugdirstate|debugstate',
2963 @command('debugdirstate|debugstate',
2964 [('', 'nodates', None, _('do not display the saved mtime')),
2964 [('', 'nodates', None, _('do not display the saved mtime')),
2965 ('', 'datesort', None, _('sort by saved mtime'))],
2965 ('', 'datesort', None, _('sort by saved mtime'))],
2966 _('[OPTION]...'))
2966 _('[OPTION]...'))
2967 def debugstate(ui, repo, nodates=None, datesort=None):
2967 def debugstate(ui, repo, nodates=None, datesort=None):
2968 """show the contents of the current dirstate"""
2968 """show the contents of the current dirstate"""
2969 timestr = ""
2969 timestr = ""
2970 if datesort:
2970 if datesort:
2971 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2971 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2972 else:
2972 else:
2973 keyfunc = None # sort by filename
2973 keyfunc = None # sort by filename
2974 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2974 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2975 if ent[3] == -1:
2975 if ent[3] == -1:
2976 timestr = 'unset '
2976 timestr = 'unset '
2977 elif nodates:
2977 elif nodates:
2978 timestr = 'set '
2978 timestr = 'set '
2979 else:
2979 else:
2980 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2980 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2981 time.localtime(ent[3]))
2981 time.localtime(ent[3]))
2982 if ent[1] & 020000:
2982 if ent[1] & 020000:
2983 mode = 'lnk'
2983 mode = 'lnk'
2984 else:
2984 else:
2985 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2985 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2986 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2986 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2987 for f in repo.dirstate.copies():
2987 for f in repo.dirstate.copies():
2988 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2988 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2989
2989
2990 @command('debugsub',
2990 @command('debugsub',
2991 [('r', 'rev', '',
2991 [('r', 'rev', '',
2992 _('revision to check'), _('REV'))],
2992 _('revision to check'), _('REV'))],
2993 _('[-r REV] [REV]'))
2993 _('[-r REV] [REV]'))
2994 def debugsub(ui, repo, rev=None):
2994 def debugsub(ui, repo, rev=None):
2995 ctx = scmutil.revsingle(repo, rev, None)
2995 ctx = scmutil.revsingle(repo, rev, None)
2996 for k, v in sorted(ctx.substate.items()):
2996 for k, v in sorted(ctx.substate.items()):
2997 ui.write(('path %s\n') % k)
2997 ui.write(('path %s\n') % k)
2998 ui.write((' source %s\n') % v[0])
2998 ui.write((' source %s\n') % v[0])
2999 ui.write((' revision %s\n') % v[1])
2999 ui.write((' revision %s\n') % v[1])
3000
3000
3001 @command('debugsuccessorssets',
3001 @command('debugsuccessorssets',
3002 [],
3002 [],
3003 _('[REV]'))
3003 _('[REV]'))
3004 def debugsuccessorssets(ui, repo, *revs):
3004 def debugsuccessorssets(ui, repo, *revs):
3005 """show set of successors for revision
3005 """show set of successors for revision
3006
3006
3007 A successors set of changeset A is a consistent group of revisions that
3007 A successors set of changeset A is a consistent group of revisions that
3008 succeed A. It contains non-obsolete changesets only.
3008 succeed A. It contains non-obsolete changesets only.
3009
3009
3010 In most cases a changeset A has a single successors set containing a single
3010 In most cases a changeset A has a single successors set containing a single
3011 successor (changeset A replaced by A').
3011 successor (changeset A replaced by A').
3012
3012
3013 A changeset that is made obsolete with no successors are called "pruned".
3013 A changeset that is made obsolete with no successors are called "pruned".
3014 Such changesets have no successors sets at all.
3014 Such changesets have no successors sets at all.
3015
3015
3016 A changeset that has been "split" will have a successors set containing
3016 A changeset that has been "split" will have a successors set containing
3017 more than one successor.
3017 more than one successor.
3018
3018
3019 A changeset that has been rewritten in multiple different ways is called
3019 A changeset that has been rewritten in multiple different ways is called
3020 "divergent". Such changesets have multiple successor sets (each of which
3020 "divergent". Such changesets have multiple successor sets (each of which
3021 may also be split, i.e. have multiple successors).
3021 may also be split, i.e. have multiple successors).
3022
3022
3023 Results are displayed as follows::
3023 Results are displayed as follows::
3024
3024
3025 <rev1>
3025 <rev1>
3026 <successors-1A>
3026 <successors-1A>
3027 <rev2>
3027 <rev2>
3028 <successors-2A>
3028 <successors-2A>
3029 <successors-2B1> <successors-2B2> <successors-2B3>
3029 <successors-2B1> <successors-2B2> <successors-2B3>
3030
3030
3031 Here rev2 has two possible (i.e. divergent) successors sets. The first
3031 Here rev2 has two possible (i.e. divergent) successors sets. The first
3032 holds one element, whereas the second holds three (i.e. the changeset has
3032 holds one element, whereas the second holds three (i.e. the changeset has
3033 been split).
3033 been split).
3034 """
3034 """
3035 # passed to successorssets caching computation from one call to another
3035 # passed to successorssets caching computation from one call to another
3036 cache = {}
3036 cache = {}
3037 ctx2str = str
3037 ctx2str = str
3038 node2str = short
3038 node2str = short
3039 if ui.debug():
3039 if ui.debug():
3040 def ctx2str(ctx):
3040 def ctx2str(ctx):
3041 return ctx.hex()
3041 return ctx.hex()
3042 node2str = hex
3042 node2str = hex
3043 for rev in scmutil.revrange(repo, revs):
3043 for rev in scmutil.revrange(repo, revs):
3044 ctx = repo[rev]
3044 ctx = repo[rev]
3045 ui.write('%s\n'% ctx2str(ctx))
3045 ui.write('%s\n'% ctx2str(ctx))
3046 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3046 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3047 if succsset:
3047 if succsset:
3048 ui.write(' ')
3048 ui.write(' ')
3049 ui.write(node2str(succsset[0]))
3049 ui.write(node2str(succsset[0]))
3050 for node in succsset[1:]:
3050 for node in succsset[1:]:
3051 ui.write(' ')
3051 ui.write(' ')
3052 ui.write(node2str(node))
3052 ui.write(node2str(node))
3053 ui.write('\n')
3053 ui.write('\n')
3054
3054
3055 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3055 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3056 def debugwalk(ui, repo, *pats, **opts):
3056 def debugwalk(ui, repo, *pats, **opts):
3057 """show how files match on given patterns"""
3057 """show how files match on given patterns"""
3058 m = scmutil.match(repo[None], pats, opts)
3058 m = scmutil.match(repo[None], pats, opts)
3059 items = list(repo.walk(m))
3059 items = list(repo.walk(m))
3060 if not items:
3060 if not items:
3061 return
3061 return
3062 f = lambda fn: fn
3062 f = lambda fn: fn
3063 if ui.configbool('ui', 'slash') and os.sep != '/':
3063 if ui.configbool('ui', 'slash') and os.sep != '/':
3064 f = lambda fn: util.normpath(fn)
3064 f = lambda fn: util.normpath(fn)
3065 fmt = 'f %%-%ds %%-%ds %%s' % (
3065 fmt = 'f %%-%ds %%-%ds %%s' % (
3066 max([len(abs) for abs in items]),
3066 max([len(abs) for abs in items]),
3067 max([len(m.rel(abs)) for abs in items]))
3067 max([len(m.rel(abs)) for abs in items]))
3068 for abs in items:
3068 for abs in items:
3069 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3069 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3070 ui.write("%s\n" % line.rstrip())
3070 ui.write("%s\n" % line.rstrip())
3071
3071
3072 @command('debugwireargs',
3072 @command('debugwireargs',
3073 [('', 'three', '', 'three'),
3073 [('', 'three', '', 'three'),
3074 ('', 'four', '', 'four'),
3074 ('', 'four', '', 'four'),
3075 ('', 'five', '', 'five'),
3075 ('', 'five', '', 'five'),
3076 ] + remoteopts,
3076 ] + remoteopts,
3077 _('REPO [OPTIONS]... [ONE [TWO]]'),
3077 _('REPO [OPTIONS]... [ONE [TWO]]'),
3078 norepo=True)
3078 norepo=True)
3079 def debugwireargs(ui, repopath, *vals, **opts):
3079 def debugwireargs(ui, repopath, *vals, **opts):
3080 repo = hg.peer(ui, opts, repopath)
3080 repo = hg.peer(ui, opts, repopath)
3081 for opt in remoteopts:
3081 for opt in remoteopts:
3082 del opts[opt[1]]
3082 del opts[opt[1]]
3083 args = {}
3083 args = {}
3084 for k, v in opts.iteritems():
3084 for k, v in opts.iteritems():
3085 if v:
3085 if v:
3086 args[k] = v
3086 args[k] = v
3087 # run twice to check that we don't mess up the stream for the next command
3087 # run twice to check that we don't mess up the stream for the next command
3088 res1 = repo.debugwireargs(*vals, **args)
3088 res1 = repo.debugwireargs(*vals, **args)
3089 res2 = repo.debugwireargs(*vals, **args)
3089 res2 = repo.debugwireargs(*vals, **args)
3090 ui.write("%s\n" % res1)
3090 ui.write("%s\n" % res1)
3091 if res1 != res2:
3091 if res1 != res2:
3092 ui.warn("%s\n" % res2)
3092 ui.warn("%s\n" % res2)
3093
3093
3094 @command('^diff',
3094 @command('^diff',
3095 [('r', 'rev', [], _('revision'), _('REV')),
3095 [('r', 'rev', [], _('revision'), _('REV')),
3096 ('c', 'change', '', _('change made by revision'), _('REV'))
3096 ('c', 'change', '', _('change made by revision'), _('REV'))
3097 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3097 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3098 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3098 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3099 inferrepo=True)
3099 inferrepo=True)
3100 def diff(ui, repo, *pats, **opts):
3100 def diff(ui, repo, *pats, **opts):
3101 """diff repository (or selected files)
3101 """diff repository (or selected files)
3102
3102
3103 Show differences between revisions for the specified files.
3103 Show differences between revisions for the specified files.
3104
3104
3105 Differences between files are shown using the unified diff format.
3105 Differences between files are shown using the unified diff format.
3106
3106
3107 .. note::
3107 .. note::
3108
3108
3109 diff may generate unexpected results for merges, as it will
3109 diff may generate unexpected results for merges, as it will
3110 default to comparing against the working directory's first
3110 default to comparing against the working directory's first
3111 parent changeset if no revisions are specified.
3111 parent changeset if no revisions are specified.
3112
3112
3113 When two revision arguments are given, then changes are shown
3113 When two revision arguments are given, then changes are shown
3114 between those revisions. If only one revision is specified then
3114 between those revisions. If only one revision is specified then
3115 that revision is compared to the working directory, and, when no
3115 that revision is compared to the working directory, and, when no
3116 revisions are specified, the working directory files are compared
3116 revisions are specified, the working directory files are compared
3117 to its parent.
3117 to its parent.
3118
3118
3119 Alternatively you can specify -c/--change with a revision to see
3119 Alternatively you can specify -c/--change with a revision to see
3120 the changes in that changeset relative to its first parent.
3120 the changes in that changeset relative to its first parent.
3121
3121
3122 Without the -a/--text option, diff will avoid generating diffs of
3122 Without the -a/--text option, diff will avoid generating diffs of
3123 files it detects as binary. With -a, diff will generate a diff
3123 files it detects as binary. With -a, diff will generate a diff
3124 anyway, probably with undesirable results.
3124 anyway, probably with undesirable results.
3125
3125
3126 Use the -g/--git option to generate diffs in the git extended diff
3126 Use the -g/--git option to generate diffs in the git extended diff
3127 format. For more information, read :hg:`help diffs`.
3127 format. For more information, read :hg:`help diffs`.
3128
3128
3129 .. container:: verbose
3129 .. container:: verbose
3130
3130
3131 Examples:
3131 Examples:
3132
3132
3133 - compare a file in the current working directory to its parent::
3133 - compare a file in the current working directory to its parent::
3134
3134
3135 hg diff foo.c
3135 hg diff foo.c
3136
3136
3137 - compare two historical versions of a directory, with rename info::
3137 - compare two historical versions of a directory, with rename info::
3138
3138
3139 hg diff --git -r 1.0:1.2 lib/
3139 hg diff --git -r 1.0:1.2 lib/
3140
3140
3141 - get change stats relative to the last change on some date::
3141 - get change stats relative to the last change on some date::
3142
3142
3143 hg diff --stat -r "date('may 2')"
3143 hg diff --stat -r "date('may 2')"
3144
3144
3145 - diff all newly-added files that contain a keyword::
3145 - diff all newly-added files that contain a keyword::
3146
3146
3147 hg diff "set:added() and grep(GNU)"
3147 hg diff "set:added() and grep(GNU)"
3148
3148
3149 - compare a revision and its parents::
3149 - compare a revision and its parents::
3150
3150
3151 hg diff -c 9353 # compare against first parent
3151 hg diff -c 9353 # compare against first parent
3152 hg diff -r 9353^:9353 # same using revset syntax
3152 hg diff -r 9353^:9353 # same using revset syntax
3153 hg diff -r 9353^2:9353 # compare against the second parent
3153 hg diff -r 9353^2:9353 # compare against the second parent
3154
3154
3155 Returns 0 on success.
3155 Returns 0 on success.
3156 """
3156 """
3157
3157
3158 revs = opts.get('rev')
3158 revs = opts.get('rev')
3159 change = opts.get('change')
3159 change = opts.get('change')
3160 stat = opts.get('stat')
3160 stat = opts.get('stat')
3161 reverse = opts.get('reverse')
3161 reverse = opts.get('reverse')
3162
3162
3163 if revs and change:
3163 if revs and change:
3164 msg = _('cannot specify --rev and --change at the same time')
3164 msg = _('cannot specify --rev and --change at the same time')
3165 raise util.Abort(msg)
3165 raise util.Abort(msg)
3166 elif change:
3166 elif change:
3167 node2 = scmutil.revsingle(repo, change, None).node()
3167 node2 = scmutil.revsingle(repo, change, None).node()
3168 node1 = repo[node2].p1().node()
3168 node1 = repo[node2].p1().node()
3169 else:
3169 else:
3170 node1, node2 = scmutil.revpair(repo, revs)
3170 node1, node2 = scmutil.revpair(repo, revs)
3171
3171
3172 if reverse:
3172 if reverse:
3173 node1, node2 = node2, node1
3173 node1, node2 = node2, node1
3174
3174
3175 diffopts = patch.diffallopts(ui, opts)
3175 diffopts = patch.diffallopts(ui, opts)
3176 m = scmutil.match(repo[node2], pats, opts)
3176 m = scmutil.match(repo[node2], pats, opts)
3177 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3177 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3178 listsubrepos=opts.get('subrepos'),
3178 listsubrepos=opts.get('subrepos'),
3179 root=opts.get('root'))
3179 root=opts.get('root'))
3180
3180
3181 @command('^export',
3181 @command('^export',
3182 [('o', 'output', '',
3182 [('o', 'output', '',
3183 _('print output to file with formatted name'), _('FORMAT')),
3183 _('print output to file with formatted name'), _('FORMAT')),
3184 ('', 'switch-parent', None, _('diff against the second parent')),
3184 ('', 'switch-parent', None, _('diff against the second parent')),
3185 ('r', 'rev', [], _('revisions to export'), _('REV')),
3185 ('r', 'rev', [], _('revisions to export'), _('REV')),
3186 ] + diffopts,
3186 ] + diffopts,
3187 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3187 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3188 def export(ui, repo, *changesets, **opts):
3188 def export(ui, repo, *changesets, **opts):
3189 """dump the header and diffs for one or more changesets
3189 """dump the header and diffs for one or more changesets
3190
3190
3191 Print the changeset header and diffs for one or more revisions.
3191 Print the changeset header and diffs for one or more revisions.
3192 If no revision is given, the parent of the working directory is used.
3192 If no revision is given, the parent of the working directory is used.
3193
3193
3194 The information shown in the changeset header is: author, date,
3194 The information shown in the changeset header is: author, date,
3195 branch name (if non-default), changeset hash, parent(s) and commit
3195 branch name (if non-default), changeset hash, parent(s) and commit
3196 comment.
3196 comment.
3197
3197
3198 .. note::
3198 .. note::
3199
3199
3200 export may generate unexpected diff output for merge
3200 export may generate unexpected diff output for merge
3201 changesets, as it will compare the merge changeset against its
3201 changesets, as it will compare the merge changeset against its
3202 first parent only.
3202 first parent only.
3203
3203
3204 Output may be to a file, in which case the name of the file is
3204 Output may be to a file, in which case the name of the file is
3205 given using a format string. The formatting rules are as follows:
3205 given using a format string. The formatting rules are as follows:
3206
3206
3207 :``%%``: literal "%" character
3207 :``%%``: literal "%" character
3208 :``%H``: changeset hash (40 hexadecimal digits)
3208 :``%H``: changeset hash (40 hexadecimal digits)
3209 :``%N``: number of patches being generated
3209 :``%N``: number of patches being generated
3210 :``%R``: changeset revision number
3210 :``%R``: changeset revision number
3211 :``%b``: basename of the exporting repository
3211 :``%b``: basename of the exporting repository
3212 :``%h``: short-form changeset hash (12 hexadecimal digits)
3212 :``%h``: short-form changeset hash (12 hexadecimal digits)
3213 :``%m``: first line of the commit message (only alphanumeric characters)
3213 :``%m``: first line of the commit message (only alphanumeric characters)
3214 :``%n``: zero-padded sequence number, starting at 1
3214 :``%n``: zero-padded sequence number, starting at 1
3215 :``%r``: zero-padded changeset revision number
3215 :``%r``: zero-padded changeset revision number
3216
3216
3217 Without the -a/--text option, export will avoid generating diffs
3217 Without the -a/--text option, export will avoid generating diffs
3218 of files it detects as binary. With -a, export will generate a
3218 of files it detects as binary. With -a, export will generate a
3219 diff anyway, probably with undesirable results.
3219 diff anyway, probably with undesirable results.
3220
3220
3221 Use the -g/--git option to generate diffs in the git extended diff
3221 Use the -g/--git option to generate diffs in the git extended diff
3222 format. See :hg:`help diffs` for more information.
3222 format. See :hg:`help diffs` for more information.
3223
3223
3224 With the --switch-parent option, the diff will be against the
3224 With the --switch-parent option, the diff will be against the
3225 second parent. It can be useful to review a merge.
3225 second parent. It can be useful to review a merge.
3226
3226
3227 .. container:: verbose
3227 .. container:: verbose
3228
3228
3229 Examples:
3229 Examples:
3230
3230
3231 - use export and import to transplant a bugfix to the current
3231 - use export and import to transplant a bugfix to the current
3232 branch::
3232 branch::
3233
3233
3234 hg export -r 9353 | hg import -
3234 hg export -r 9353 | hg import -
3235
3235
3236 - export all the changesets between two revisions to a file with
3236 - export all the changesets between two revisions to a file with
3237 rename information::
3237 rename information::
3238
3238
3239 hg export --git -r 123:150 > changes.txt
3239 hg export --git -r 123:150 > changes.txt
3240
3240
3241 - split outgoing changes into a series of patches with
3241 - split outgoing changes into a series of patches with
3242 descriptive names::
3242 descriptive names::
3243
3243
3244 hg export -r "outgoing()" -o "%n-%m.patch"
3244 hg export -r "outgoing()" -o "%n-%m.patch"
3245
3245
3246 Returns 0 on success.
3246 Returns 0 on success.
3247 """
3247 """
3248 changesets += tuple(opts.get('rev', []))
3248 changesets += tuple(opts.get('rev', []))
3249 if not changesets:
3249 if not changesets:
3250 changesets = ['.']
3250 changesets = ['.']
3251 revs = scmutil.revrange(repo, changesets)
3251 revs = scmutil.revrange(repo, changesets)
3252 if not revs:
3252 if not revs:
3253 raise util.Abort(_("export requires at least one changeset"))
3253 raise util.Abort(_("export requires at least one changeset"))
3254 if len(revs) > 1:
3254 if len(revs) > 1:
3255 ui.note(_('exporting patches:\n'))
3255 ui.note(_('exporting patches:\n'))
3256 else:
3256 else:
3257 ui.note(_('exporting patch:\n'))
3257 ui.note(_('exporting patch:\n'))
3258 cmdutil.export(repo, revs, template=opts.get('output'),
3258 cmdutil.export(repo, revs, template=opts.get('output'),
3259 switch_parent=opts.get('switch_parent'),
3259 switch_parent=opts.get('switch_parent'),
3260 opts=patch.diffallopts(ui, opts))
3260 opts=patch.diffallopts(ui, opts))
3261
3261
3262 @command('files',
3262 @command('files',
3263 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3263 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3264 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3264 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3265 ] + walkopts + formatteropts + subrepoopts,
3265 ] + walkopts + formatteropts + subrepoopts,
3266 _('[OPTION]... [PATTERN]...'))
3266 _('[OPTION]... [PATTERN]...'))
3267 def files(ui, repo, *pats, **opts):
3267 def files(ui, repo, *pats, **opts):
3268 """list tracked files
3268 """list tracked files
3269
3269
3270 Print files under Mercurial control in the working directory or
3270 Print files under Mercurial control in the working directory or
3271 specified revision whose names match the given patterns (excluding
3271 specified revision whose names match the given patterns (excluding
3272 removed files).
3272 removed files).
3273
3273
3274 If no patterns are given to match, this command prints the names
3274 If no patterns are given to match, this command prints the names
3275 of all files under Mercurial control in the working directory.
3275 of all files under Mercurial control in the working directory.
3276
3276
3277 .. container:: verbose
3277 .. container:: verbose
3278
3278
3279 Examples:
3279 Examples:
3280
3280
3281 - list all files under the current directory::
3281 - list all files under the current directory::
3282
3282
3283 hg files .
3283 hg files .
3284
3284
3285 - shows sizes and flags for current revision::
3285 - shows sizes and flags for current revision::
3286
3286
3287 hg files -vr .
3287 hg files -vr .
3288
3288
3289 - list all files named README::
3289 - list all files named README::
3290
3290
3291 hg files -I "**/README"
3291 hg files -I "**/README"
3292
3292
3293 - list all binary files::
3293 - list all binary files::
3294
3294
3295 hg files "set:binary()"
3295 hg files "set:binary()"
3296
3296
3297 - find files containing a regular expression::
3297 - find files containing a regular expression::
3298
3298
3299 hg files "set:grep('bob')"
3299 hg files "set:grep('bob')"
3300
3300
3301 - search tracked file contents with xargs and grep::
3301 - search tracked file contents with xargs and grep::
3302
3302
3303 hg files -0 | xargs -0 grep foo
3303 hg files -0 | xargs -0 grep foo
3304
3304
3305 See :hg:`help patterns` and :hg:`help filesets` for more information
3305 See :hg:`help patterns` and :hg:`help filesets` for more information
3306 on specifying file patterns.
3306 on specifying file patterns.
3307
3307
3308 Returns 0 if a match is found, 1 otherwise.
3308 Returns 0 if a match is found, 1 otherwise.
3309
3309
3310 """
3310 """
3311 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3311 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3312
3312
3313 end = '\n'
3313 end = '\n'
3314 if opts.get('print0'):
3314 if opts.get('print0'):
3315 end = '\0'
3315 end = '\0'
3316 fm = ui.formatter('files', opts)
3316 fm = ui.formatter('files', opts)
3317 fmt = '%s' + end
3317 fmt = '%s' + end
3318
3318
3319 m = scmutil.match(ctx, pats, opts)
3319 m = scmutil.match(ctx, pats, opts)
3320 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3320 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3321
3321
3322 fm.end()
3322 fm.end()
3323
3323
3324 return ret
3324 return ret
3325
3325
3326 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3326 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3327 def forget(ui, repo, *pats, **opts):
3327 def forget(ui, repo, *pats, **opts):
3328 """forget the specified files on the next commit
3328 """forget the specified files on the next commit
3329
3329
3330 Mark the specified files so they will no longer be tracked
3330 Mark the specified files so they will no longer be tracked
3331 after the next commit.
3331 after the next commit.
3332
3332
3333 This only removes files from the current branch, not from the
3333 This only removes files from the current branch, not from the
3334 entire project history, and it does not delete them from the
3334 entire project history, and it does not delete them from the
3335 working directory.
3335 working directory.
3336
3336
3337 To undo a forget before the next commit, see :hg:`add`.
3337 To undo a forget before the next commit, see :hg:`add`.
3338
3338
3339 .. container:: verbose
3339 .. container:: verbose
3340
3340
3341 Examples:
3341 Examples:
3342
3342
3343 - forget newly-added binary files::
3343 - forget newly-added binary files::
3344
3344
3345 hg forget "set:added() and binary()"
3345 hg forget "set:added() and binary()"
3346
3346
3347 - forget files that would be excluded by .hgignore::
3347 - forget files that would be excluded by .hgignore::
3348
3348
3349 hg forget "set:hgignore()"
3349 hg forget "set:hgignore()"
3350
3350
3351 Returns 0 on success.
3351 Returns 0 on success.
3352 """
3352 """
3353
3353
3354 if not pats:
3354 if not pats:
3355 raise util.Abort(_('no files specified'))
3355 raise util.Abort(_('no files specified'))
3356
3356
3357 m = scmutil.match(repo[None], pats, opts)
3357 m = scmutil.match(repo[None], pats, opts)
3358 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3358 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3359 return rejected and 1 or 0
3359 return rejected and 1 or 0
3360
3360
3361 @command(
3361 @command(
3362 'graft',
3362 'graft',
3363 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3363 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3364 ('c', 'continue', False, _('resume interrupted graft')),
3364 ('c', 'continue', False, _('resume interrupted graft')),
3365 ('e', 'edit', False, _('invoke editor on commit messages')),
3365 ('e', 'edit', False, _('invoke editor on commit messages')),
3366 ('', 'log', None, _('append graft info to log message')),
3366 ('', 'log', None, _('append graft info to log message')),
3367 ('f', 'force', False, _('force graft')),
3367 ('f', 'force', False, _('force graft')),
3368 ('D', 'currentdate', False,
3368 ('D', 'currentdate', False,
3369 _('record the current date as commit date')),
3369 _('record the current date as commit date')),
3370 ('U', 'currentuser', False,
3370 ('U', 'currentuser', False,
3371 _('record the current user as committer'), _('DATE'))]
3371 _('record the current user as committer'), _('DATE'))]
3372 + commitopts2 + mergetoolopts + dryrunopts,
3372 + commitopts2 + mergetoolopts + dryrunopts,
3373 _('[OPTION]... [-r] REV...'))
3373 _('[OPTION]... [-r] REV...'))
3374 def graft(ui, repo, *revs, **opts):
3374 def graft(ui, repo, *revs, **opts):
3375 '''copy changes from other branches onto the current branch
3375 '''copy changes from other branches onto the current branch
3376
3376
3377 This command uses Mercurial's merge logic to copy individual
3377 This command uses Mercurial's merge logic to copy individual
3378 changes from other branches without merging branches in the
3378 changes from other branches without merging branches in the
3379 history graph. This is sometimes known as 'backporting' or
3379 history graph. This is sometimes known as 'backporting' or
3380 'cherry-picking'. By default, graft will copy user, date, and
3380 'cherry-picking'. By default, graft will copy user, date, and
3381 description from the source changesets.
3381 description from the source changesets.
3382
3382
3383 Changesets that are ancestors of the current revision, that have
3383 Changesets that are ancestors of the current revision, that have
3384 already been grafted, or that are merges will be skipped.
3384 already been grafted, or that are merges will be skipped.
3385
3385
3386 If --log is specified, log messages will have a comment appended
3386 If --log is specified, log messages will have a comment appended
3387 of the form::
3387 of the form::
3388
3388
3389 (grafted from CHANGESETHASH)
3389 (grafted from CHANGESETHASH)
3390
3390
3391 If --force is specified, revisions will be grafted even if they
3391 If --force is specified, revisions will be grafted even if they
3392 are already ancestors of or have been grafted to the destination.
3392 are already ancestors of or have been grafted to the destination.
3393 This is useful when the revisions have since been backed out.
3393 This is useful when the revisions have since been backed out.
3394
3394
3395 If a graft merge results in conflicts, the graft process is
3395 If a graft merge results in conflicts, the graft process is
3396 interrupted so that the current merge can be manually resolved.
3396 interrupted so that the current merge can be manually resolved.
3397 Once all conflicts are addressed, the graft process can be
3397 Once all conflicts are addressed, the graft process can be
3398 continued with the -c/--continue option.
3398 continued with the -c/--continue option.
3399
3399
3400 .. note::
3400 .. note::
3401
3401
3402 The -c/--continue option does not reapply earlier options, except
3402 The -c/--continue option does not reapply earlier options, except
3403 for --force.
3403 for --force.
3404
3404
3405 .. container:: verbose
3405 .. container:: verbose
3406
3406
3407 Examples:
3407 Examples:
3408
3408
3409 - copy a single change to the stable branch and edit its description::
3409 - copy a single change to the stable branch and edit its description::
3410
3410
3411 hg update stable
3411 hg update stable
3412 hg graft --edit 9393
3412 hg graft --edit 9393
3413
3413
3414 - graft a range of changesets with one exception, updating dates::
3414 - graft a range of changesets with one exception, updating dates::
3415
3415
3416 hg graft -D "2085::2093 and not 2091"
3416 hg graft -D "2085::2093 and not 2091"
3417
3417
3418 - continue a graft after resolving conflicts::
3418 - continue a graft after resolving conflicts::
3419
3419
3420 hg graft -c
3420 hg graft -c
3421
3421
3422 - show the source of a grafted changeset::
3422 - show the source of a grafted changeset::
3423
3423
3424 hg log --debug -r .
3424 hg log --debug -r .
3425
3425
3426 See :hg:`help revisions` and :hg:`help revsets` for more about
3426 See :hg:`help revisions` and :hg:`help revsets` for more about
3427 specifying revisions.
3427 specifying revisions.
3428
3428
3429 Returns 0 on successful completion.
3429 Returns 0 on successful completion.
3430 '''
3430 '''
3431
3431
3432 revs = list(revs)
3432 revs = list(revs)
3433 revs.extend(opts['rev'])
3433 revs.extend(opts['rev'])
3434
3434
3435 if not opts.get('user') and opts.get('currentuser'):
3435 if not opts.get('user') and opts.get('currentuser'):
3436 opts['user'] = ui.username()
3436 opts['user'] = ui.username()
3437 if not opts.get('date') and opts.get('currentdate'):
3437 if not opts.get('date') and opts.get('currentdate'):
3438 opts['date'] = "%d %d" % util.makedate()
3438 opts['date'] = "%d %d" % util.makedate()
3439
3439
3440 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3440 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3441
3441
3442 cont = False
3442 cont = False
3443 if opts['continue']:
3443 if opts['continue']:
3444 cont = True
3444 cont = True
3445 if revs:
3445 if revs:
3446 raise util.Abort(_("can't specify --continue and revisions"))
3446 raise util.Abort(_("can't specify --continue and revisions"))
3447 # read in unfinished revisions
3447 # read in unfinished revisions
3448 try:
3448 try:
3449 nodes = repo.vfs.read('graftstate').splitlines()
3449 nodes = repo.vfs.read('graftstate').splitlines()
3450 revs = [repo[node].rev() for node in nodes]
3450 revs = [repo[node].rev() for node in nodes]
3451 except IOError, inst:
3451 except IOError, inst:
3452 if inst.errno != errno.ENOENT:
3452 if inst.errno != errno.ENOENT:
3453 raise
3453 raise
3454 raise util.Abort(_("no graft state found, can't continue"))
3454 raise util.Abort(_("no graft state found, can't continue"))
3455 else:
3455 else:
3456 cmdutil.checkunfinished(repo)
3456 cmdutil.checkunfinished(repo)
3457 cmdutil.bailifchanged(repo)
3457 cmdutil.bailifchanged(repo)
3458 if not revs:
3458 if not revs:
3459 raise util.Abort(_('no revisions specified'))
3459 raise util.Abort(_('no revisions specified'))
3460 revs = scmutil.revrange(repo, revs)
3460 revs = scmutil.revrange(repo, revs)
3461
3461
3462 skipped = set()
3462 skipped = set()
3463 # check for merges
3463 # check for merges
3464 for rev in repo.revs('%ld and merge()', revs):
3464 for rev in repo.revs('%ld and merge()', revs):
3465 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3465 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3466 skipped.add(rev)
3466 skipped.add(rev)
3467 revs = [r for r in revs if r not in skipped]
3467 revs = [r for r in revs if r not in skipped]
3468 if not revs:
3468 if not revs:
3469 return -1
3469 return -1
3470
3470
3471 # Don't check in the --continue case, in effect retaining --force across
3471 # Don't check in the --continue case, in effect retaining --force across
3472 # --continues. That's because without --force, any revisions we decided to
3472 # --continues. That's because without --force, any revisions we decided to
3473 # skip would have been filtered out here, so they wouldn't have made their
3473 # skip would have been filtered out here, so they wouldn't have made their
3474 # way to the graftstate. With --force, any revisions we would have otherwise
3474 # way to the graftstate. With --force, any revisions we would have otherwise
3475 # skipped would not have been filtered out, and if they hadn't been applied
3475 # skipped would not have been filtered out, and if they hadn't been applied
3476 # already, they'd have been in the graftstate.
3476 # already, they'd have been in the graftstate.
3477 if not (cont or opts.get('force')):
3477 if not (cont or opts.get('force')):
3478 # check for ancestors of dest branch
3478 # check for ancestors of dest branch
3479 crev = repo['.'].rev()
3479 crev = repo['.'].rev()
3480 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3480 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3481 # Cannot use x.remove(y) on smart set, this has to be a list.
3481 # Cannot use x.remove(y) on smart set, this has to be a list.
3482 # XXX make this lazy in the future
3482 # XXX make this lazy in the future
3483 revs = list(revs)
3483 revs = list(revs)
3484 # don't mutate while iterating, create a copy
3484 # don't mutate while iterating, create a copy
3485 for rev in list(revs):
3485 for rev in list(revs):
3486 if rev in ancestors:
3486 if rev in ancestors:
3487 ui.warn(_('skipping ancestor revision %d:%s\n') %
3487 ui.warn(_('skipping ancestor revision %d:%s\n') %
3488 (rev, repo[rev]))
3488 (rev, repo[rev]))
3489 # XXX remove on list is slow
3489 # XXX remove on list is slow
3490 revs.remove(rev)
3490 revs.remove(rev)
3491 if not revs:
3491 if not revs:
3492 return -1
3492 return -1
3493
3493
3494 # analyze revs for earlier grafts
3494 # analyze revs for earlier grafts
3495 ids = {}
3495 ids = {}
3496 for ctx in repo.set("%ld", revs):
3496 for ctx in repo.set("%ld", revs):
3497 ids[ctx.hex()] = ctx.rev()
3497 ids[ctx.hex()] = ctx.rev()
3498 n = ctx.extra().get('source')
3498 n = ctx.extra().get('source')
3499 if n:
3499 if n:
3500 ids[n] = ctx.rev()
3500 ids[n] = ctx.rev()
3501
3501
3502 # check ancestors for earlier grafts
3502 # check ancestors for earlier grafts
3503 ui.debug('scanning for duplicate grafts\n')
3503 ui.debug('scanning for duplicate grafts\n')
3504
3504
3505 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3505 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3506 ctx = repo[rev]
3506 ctx = repo[rev]
3507 n = ctx.extra().get('source')
3507 n = ctx.extra().get('source')
3508 if n in ids:
3508 if n in ids:
3509 try:
3509 try:
3510 r = repo[n].rev()
3510 r = repo[n].rev()
3511 except error.RepoLookupError:
3511 except error.RepoLookupError:
3512 r = None
3512 r = None
3513 if r in revs:
3513 if r in revs:
3514 ui.warn(_('skipping revision %d:%s '
3514 ui.warn(_('skipping revision %d:%s '
3515 '(already grafted to %d:%s)\n')
3515 '(already grafted to %d:%s)\n')
3516 % (r, repo[r], rev, ctx))
3516 % (r, repo[r], rev, ctx))
3517 revs.remove(r)
3517 revs.remove(r)
3518 elif ids[n] in revs:
3518 elif ids[n] in revs:
3519 if r is None:
3519 if r is None:
3520 ui.warn(_('skipping already grafted revision %d:%s '
3520 ui.warn(_('skipping already grafted revision %d:%s '
3521 '(%d:%s also has unknown origin %s)\n')
3521 '(%d:%s also has unknown origin %s)\n')
3522 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3522 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3523 else:
3523 else:
3524 ui.warn(_('skipping already grafted revision %d:%s '
3524 ui.warn(_('skipping already grafted revision %d:%s '
3525 '(%d:%s also has origin %d:%s)\n')
3525 '(%d:%s also has origin %d:%s)\n')
3526 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3526 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3527 revs.remove(ids[n])
3527 revs.remove(ids[n])
3528 elif ctx.hex() in ids:
3528 elif ctx.hex() in ids:
3529 r = ids[ctx.hex()]
3529 r = ids[ctx.hex()]
3530 ui.warn(_('skipping already grafted revision %d:%s '
3530 ui.warn(_('skipping already grafted revision %d:%s '
3531 '(was grafted from %d:%s)\n') %
3531 '(was grafted from %d:%s)\n') %
3532 (r, repo[r], rev, ctx))
3532 (r, repo[r], rev, ctx))
3533 revs.remove(r)
3533 revs.remove(r)
3534 if not revs:
3534 if not revs:
3535 return -1
3535 return -1
3536
3536
3537 wlock = repo.wlock()
3537 wlock = repo.wlock()
3538 try:
3538 try:
3539 for pos, ctx in enumerate(repo.set("%ld", revs)):
3539 for pos, ctx in enumerate(repo.set("%ld", revs)):
3540 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3540 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3541 ctx.description().split('\n', 1)[0])
3541 ctx.description().split('\n', 1)[0])
3542 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3542 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3543 if names:
3543 if names:
3544 desc += ' (%s)' % ' '.join(names)
3544 desc += ' (%s)' % ' '.join(names)
3545 ui.status(_('grafting %s\n') % desc)
3545 ui.status(_('grafting %s\n') % desc)
3546 if opts.get('dry_run'):
3546 if opts.get('dry_run'):
3547 continue
3547 continue
3548
3548
3549 source = ctx.extra().get('source')
3549 source = ctx.extra().get('source')
3550 if not source:
3550 extra = {}
3551 source = ctx.hex()
3551 if source:
3552 extra = {'source': source}
3552 extra['source'] = source
3553 extra['intermediate-source'] = ctx.hex()
3554 else:
3555 extra['source'] = ctx.hex()
3553 user = ctx.user()
3556 user = ctx.user()
3554 if opts.get('user'):
3557 if opts.get('user'):
3555 user = opts['user']
3558 user = opts['user']
3556 date = ctx.date()
3559 date = ctx.date()
3557 if opts.get('date'):
3560 if opts.get('date'):
3558 date = opts['date']
3561 date = opts['date']
3559 message = ctx.description()
3562 message = ctx.description()
3560 if opts.get('log'):
3563 if opts.get('log'):
3561 message += '\n(grafted from %s)' % ctx.hex()
3564 message += '\n(grafted from %s)' % ctx.hex()
3562
3565
3563 # we don't merge the first commit when continuing
3566 # we don't merge the first commit when continuing
3564 if not cont:
3567 if not cont:
3565 # perform the graft merge with p1(rev) as 'ancestor'
3568 # perform the graft merge with p1(rev) as 'ancestor'
3566 try:
3569 try:
3567 # ui.forcemerge is an internal variable, do not document
3570 # ui.forcemerge is an internal variable, do not document
3568 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3571 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3569 'graft')
3572 'graft')
3570 stats = mergemod.graft(repo, ctx, ctx.p1(),
3573 stats = mergemod.graft(repo, ctx, ctx.p1(),
3571 ['local', 'graft'])
3574 ['local', 'graft'])
3572 finally:
3575 finally:
3573 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3576 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3574 # report any conflicts
3577 # report any conflicts
3575 if stats and stats[3] > 0:
3578 if stats and stats[3] > 0:
3576 # write out state for --continue
3579 # write out state for --continue
3577 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3580 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3578 repo.vfs.write('graftstate', ''.join(nodelines))
3581 repo.vfs.write('graftstate', ''.join(nodelines))
3579 raise util.Abort(
3582 raise util.Abort(
3580 _("unresolved conflicts, can't continue"),
3583 _("unresolved conflicts, can't continue"),
3581 hint=_('use hg resolve and hg graft --continue'))
3584 hint=_('use hg resolve and hg graft --continue'))
3582 else:
3585 else:
3583 cont = False
3586 cont = False
3584
3587
3585 # commit
3588 # commit
3586 node = repo.commit(text=message, user=user,
3589 node = repo.commit(text=message, user=user,
3587 date=date, extra=extra, editor=editor)
3590 date=date, extra=extra, editor=editor)
3588 if node is None:
3591 if node is None:
3589 ui.warn(
3592 ui.warn(
3590 _('note: graft of %d:%s created no changes to commit\n') %
3593 _('note: graft of %d:%s created no changes to commit\n') %
3591 (ctx.rev(), ctx))
3594 (ctx.rev(), ctx))
3592 finally:
3595 finally:
3593 wlock.release()
3596 wlock.release()
3594
3597
3595 # remove state when we complete successfully
3598 # remove state when we complete successfully
3596 if not opts.get('dry_run'):
3599 if not opts.get('dry_run'):
3597 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3600 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3598
3601
3599 return 0
3602 return 0
3600
3603
3601 @command('grep',
3604 @command('grep',
3602 [('0', 'print0', None, _('end fields with NUL')),
3605 [('0', 'print0', None, _('end fields with NUL')),
3603 ('', 'all', None, _('print all revisions that match')),
3606 ('', 'all', None, _('print all revisions that match')),
3604 ('a', 'text', None, _('treat all files as text')),
3607 ('a', 'text', None, _('treat all files as text')),
3605 ('f', 'follow', None,
3608 ('f', 'follow', None,
3606 _('follow changeset history,'
3609 _('follow changeset history,'
3607 ' or file history across copies and renames')),
3610 ' or file history across copies and renames')),
3608 ('i', 'ignore-case', None, _('ignore case when matching')),
3611 ('i', 'ignore-case', None, _('ignore case when matching')),
3609 ('l', 'files-with-matches', None,
3612 ('l', 'files-with-matches', None,
3610 _('print only filenames and revisions that match')),
3613 _('print only filenames and revisions that match')),
3611 ('n', 'line-number', None, _('print matching line numbers')),
3614 ('n', 'line-number', None, _('print matching line numbers')),
3612 ('r', 'rev', [],
3615 ('r', 'rev', [],
3613 _('only search files changed within revision range'), _('REV')),
3616 _('only search files changed within revision range'), _('REV')),
3614 ('u', 'user', None, _('list the author (long with -v)')),
3617 ('u', 'user', None, _('list the author (long with -v)')),
3615 ('d', 'date', None, _('list the date (short with -q)')),
3618 ('d', 'date', None, _('list the date (short with -q)')),
3616 ] + walkopts,
3619 ] + walkopts,
3617 _('[OPTION]... PATTERN [FILE]...'),
3620 _('[OPTION]... PATTERN [FILE]...'),
3618 inferrepo=True)
3621 inferrepo=True)
3619 def grep(ui, repo, pattern, *pats, **opts):
3622 def grep(ui, repo, pattern, *pats, **opts):
3620 """search for a pattern in specified files and revisions
3623 """search for a pattern in specified files and revisions
3621
3624
3622 Search revisions of files for a regular expression.
3625 Search revisions of files for a regular expression.
3623
3626
3624 This command behaves differently than Unix grep. It only accepts
3627 This command behaves differently than Unix grep. It only accepts
3625 Python/Perl regexps. It searches repository history, not the
3628 Python/Perl regexps. It searches repository history, not the
3626 working directory. It always prints the revision number in which a
3629 working directory. It always prints the revision number in which a
3627 match appears.
3630 match appears.
3628
3631
3629 By default, grep only prints output for the first revision of a
3632 By default, grep only prints output for the first revision of a
3630 file in which it finds a match. To get it to print every revision
3633 file in which it finds a match. To get it to print every revision
3631 that contains a change in match status ("-" for a match that
3634 that contains a change in match status ("-" for a match that
3632 becomes a non-match, or "+" for a non-match that becomes a match),
3635 becomes a non-match, or "+" for a non-match that becomes a match),
3633 use the --all flag.
3636 use the --all flag.
3634
3637
3635 Returns 0 if a match is found, 1 otherwise.
3638 Returns 0 if a match is found, 1 otherwise.
3636 """
3639 """
3637 reflags = re.M
3640 reflags = re.M
3638 if opts.get('ignore_case'):
3641 if opts.get('ignore_case'):
3639 reflags |= re.I
3642 reflags |= re.I
3640 try:
3643 try:
3641 regexp = util.re.compile(pattern, reflags)
3644 regexp = util.re.compile(pattern, reflags)
3642 except re.error, inst:
3645 except re.error, inst:
3643 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3646 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3644 return 1
3647 return 1
3645 sep, eol = ':', '\n'
3648 sep, eol = ':', '\n'
3646 if opts.get('print0'):
3649 if opts.get('print0'):
3647 sep = eol = '\0'
3650 sep = eol = '\0'
3648
3651
3649 getfile = util.lrucachefunc(repo.file)
3652 getfile = util.lrucachefunc(repo.file)
3650
3653
3651 def matchlines(body):
3654 def matchlines(body):
3652 begin = 0
3655 begin = 0
3653 linenum = 0
3656 linenum = 0
3654 while begin < len(body):
3657 while begin < len(body):
3655 match = regexp.search(body, begin)
3658 match = regexp.search(body, begin)
3656 if not match:
3659 if not match:
3657 break
3660 break
3658 mstart, mend = match.span()
3661 mstart, mend = match.span()
3659 linenum += body.count('\n', begin, mstart) + 1
3662 linenum += body.count('\n', begin, mstart) + 1
3660 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3663 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3661 begin = body.find('\n', mend) + 1 or len(body) + 1
3664 begin = body.find('\n', mend) + 1 or len(body) + 1
3662 lend = begin - 1
3665 lend = begin - 1
3663 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3666 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3664
3667
3665 class linestate(object):
3668 class linestate(object):
3666 def __init__(self, line, linenum, colstart, colend):
3669 def __init__(self, line, linenum, colstart, colend):
3667 self.line = line
3670 self.line = line
3668 self.linenum = linenum
3671 self.linenum = linenum
3669 self.colstart = colstart
3672 self.colstart = colstart
3670 self.colend = colend
3673 self.colend = colend
3671
3674
3672 def __hash__(self):
3675 def __hash__(self):
3673 return hash((self.linenum, self.line))
3676 return hash((self.linenum, self.line))
3674
3677
3675 def __eq__(self, other):
3678 def __eq__(self, other):
3676 return self.line == other.line
3679 return self.line == other.line
3677
3680
3678 def __iter__(self):
3681 def __iter__(self):
3679 yield (self.line[:self.colstart], '')
3682 yield (self.line[:self.colstart], '')
3680 yield (self.line[self.colstart:self.colend], 'grep.match')
3683 yield (self.line[self.colstart:self.colend], 'grep.match')
3681 rest = self.line[self.colend:]
3684 rest = self.line[self.colend:]
3682 while rest != '':
3685 while rest != '':
3683 match = regexp.search(rest)
3686 match = regexp.search(rest)
3684 if not match:
3687 if not match:
3685 yield (rest, '')
3688 yield (rest, '')
3686 break
3689 break
3687 mstart, mend = match.span()
3690 mstart, mend = match.span()
3688 yield (rest[:mstart], '')
3691 yield (rest[:mstart], '')
3689 yield (rest[mstart:mend], 'grep.match')
3692 yield (rest[mstart:mend], 'grep.match')
3690 rest = rest[mend:]
3693 rest = rest[mend:]
3691
3694
3692 matches = {}
3695 matches = {}
3693 copies = {}
3696 copies = {}
3694 def grepbody(fn, rev, body):
3697 def grepbody(fn, rev, body):
3695 matches[rev].setdefault(fn, [])
3698 matches[rev].setdefault(fn, [])
3696 m = matches[rev][fn]
3699 m = matches[rev][fn]
3697 for lnum, cstart, cend, line in matchlines(body):
3700 for lnum, cstart, cend, line in matchlines(body):
3698 s = linestate(line, lnum, cstart, cend)
3701 s = linestate(line, lnum, cstart, cend)
3699 m.append(s)
3702 m.append(s)
3700
3703
3701 def difflinestates(a, b):
3704 def difflinestates(a, b):
3702 sm = difflib.SequenceMatcher(None, a, b)
3705 sm = difflib.SequenceMatcher(None, a, b)
3703 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3706 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3704 if tag == 'insert':
3707 if tag == 'insert':
3705 for i in xrange(blo, bhi):
3708 for i in xrange(blo, bhi):
3706 yield ('+', b[i])
3709 yield ('+', b[i])
3707 elif tag == 'delete':
3710 elif tag == 'delete':
3708 for i in xrange(alo, ahi):
3711 for i in xrange(alo, ahi):
3709 yield ('-', a[i])
3712 yield ('-', a[i])
3710 elif tag == 'replace':
3713 elif tag == 'replace':
3711 for i in xrange(alo, ahi):
3714 for i in xrange(alo, ahi):
3712 yield ('-', a[i])
3715 yield ('-', a[i])
3713 for i in xrange(blo, bhi):
3716 for i in xrange(blo, bhi):
3714 yield ('+', b[i])
3717 yield ('+', b[i])
3715
3718
3716 def display(fn, ctx, pstates, states):
3719 def display(fn, ctx, pstates, states):
3717 rev = ctx.rev()
3720 rev = ctx.rev()
3718 if ui.quiet:
3721 if ui.quiet:
3719 datefunc = util.shortdate
3722 datefunc = util.shortdate
3720 else:
3723 else:
3721 datefunc = util.datestr
3724 datefunc = util.datestr
3722 found = False
3725 found = False
3723 @util.cachefunc
3726 @util.cachefunc
3724 def binary():
3727 def binary():
3725 flog = getfile(fn)
3728 flog = getfile(fn)
3726 return util.binary(flog.read(ctx.filenode(fn)))
3729 return util.binary(flog.read(ctx.filenode(fn)))
3727
3730
3728 if opts.get('all'):
3731 if opts.get('all'):
3729 iter = difflinestates(pstates, states)
3732 iter = difflinestates(pstates, states)
3730 else:
3733 else:
3731 iter = [('', l) for l in states]
3734 iter = [('', l) for l in states]
3732 for change, l in iter:
3735 for change, l in iter:
3733 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3736 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3734
3737
3735 if opts.get('line_number'):
3738 if opts.get('line_number'):
3736 cols.append((str(l.linenum), 'grep.linenumber'))
3739 cols.append((str(l.linenum), 'grep.linenumber'))
3737 if opts.get('all'):
3740 if opts.get('all'):
3738 cols.append((change, 'grep.change'))
3741 cols.append((change, 'grep.change'))
3739 if opts.get('user'):
3742 if opts.get('user'):
3740 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3743 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3741 if opts.get('date'):
3744 if opts.get('date'):
3742 cols.append((datefunc(ctx.date()), 'grep.date'))
3745 cols.append((datefunc(ctx.date()), 'grep.date'))
3743 for col, label in cols[:-1]:
3746 for col, label in cols[:-1]:
3744 ui.write(col, label=label)
3747 ui.write(col, label=label)
3745 ui.write(sep, label='grep.sep')
3748 ui.write(sep, label='grep.sep')
3746 ui.write(cols[-1][0], label=cols[-1][1])
3749 ui.write(cols[-1][0], label=cols[-1][1])
3747 if not opts.get('files_with_matches'):
3750 if not opts.get('files_with_matches'):
3748 ui.write(sep, label='grep.sep')
3751 ui.write(sep, label='grep.sep')
3749 if not opts.get('text') and binary():
3752 if not opts.get('text') and binary():
3750 ui.write(" Binary file matches")
3753 ui.write(" Binary file matches")
3751 else:
3754 else:
3752 for s, label in l:
3755 for s, label in l:
3753 ui.write(s, label=label)
3756 ui.write(s, label=label)
3754 ui.write(eol)
3757 ui.write(eol)
3755 found = True
3758 found = True
3756 if opts.get('files_with_matches'):
3759 if opts.get('files_with_matches'):
3757 break
3760 break
3758 return found
3761 return found
3759
3762
3760 skip = {}
3763 skip = {}
3761 revfiles = {}
3764 revfiles = {}
3762 matchfn = scmutil.match(repo[None], pats, opts)
3765 matchfn = scmutil.match(repo[None], pats, opts)
3763 found = False
3766 found = False
3764 follow = opts.get('follow')
3767 follow = opts.get('follow')
3765
3768
3766 def prep(ctx, fns):
3769 def prep(ctx, fns):
3767 rev = ctx.rev()
3770 rev = ctx.rev()
3768 pctx = ctx.p1()
3771 pctx = ctx.p1()
3769 parent = pctx.rev()
3772 parent = pctx.rev()
3770 matches.setdefault(rev, {})
3773 matches.setdefault(rev, {})
3771 matches.setdefault(parent, {})
3774 matches.setdefault(parent, {})
3772 files = revfiles.setdefault(rev, [])
3775 files = revfiles.setdefault(rev, [])
3773 for fn in fns:
3776 for fn in fns:
3774 flog = getfile(fn)
3777 flog = getfile(fn)
3775 try:
3778 try:
3776 fnode = ctx.filenode(fn)
3779 fnode = ctx.filenode(fn)
3777 except error.LookupError:
3780 except error.LookupError:
3778 continue
3781 continue
3779
3782
3780 copied = flog.renamed(fnode)
3783 copied = flog.renamed(fnode)
3781 copy = follow and copied and copied[0]
3784 copy = follow and copied and copied[0]
3782 if copy:
3785 if copy:
3783 copies.setdefault(rev, {})[fn] = copy
3786 copies.setdefault(rev, {})[fn] = copy
3784 if fn in skip:
3787 if fn in skip:
3785 if copy:
3788 if copy:
3786 skip[copy] = True
3789 skip[copy] = True
3787 continue
3790 continue
3788 files.append(fn)
3791 files.append(fn)
3789
3792
3790 if fn not in matches[rev]:
3793 if fn not in matches[rev]:
3791 grepbody(fn, rev, flog.read(fnode))
3794 grepbody(fn, rev, flog.read(fnode))
3792
3795
3793 pfn = copy or fn
3796 pfn = copy or fn
3794 if pfn not in matches[parent]:
3797 if pfn not in matches[parent]:
3795 try:
3798 try:
3796 fnode = pctx.filenode(pfn)
3799 fnode = pctx.filenode(pfn)
3797 grepbody(pfn, parent, flog.read(fnode))
3800 grepbody(pfn, parent, flog.read(fnode))
3798 except error.LookupError:
3801 except error.LookupError:
3799 pass
3802 pass
3800
3803
3801 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3804 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3802 rev = ctx.rev()
3805 rev = ctx.rev()
3803 parent = ctx.p1().rev()
3806 parent = ctx.p1().rev()
3804 for fn in sorted(revfiles.get(rev, [])):
3807 for fn in sorted(revfiles.get(rev, [])):
3805 states = matches[rev][fn]
3808 states = matches[rev][fn]
3806 copy = copies.get(rev, {}).get(fn)
3809 copy = copies.get(rev, {}).get(fn)
3807 if fn in skip:
3810 if fn in skip:
3808 if copy:
3811 if copy:
3809 skip[copy] = True
3812 skip[copy] = True
3810 continue
3813 continue
3811 pstates = matches.get(parent, {}).get(copy or fn, [])
3814 pstates = matches.get(parent, {}).get(copy or fn, [])
3812 if pstates or states:
3815 if pstates or states:
3813 r = display(fn, ctx, pstates, states)
3816 r = display(fn, ctx, pstates, states)
3814 found = found or r
3817 found = found or r
3815 if r and not opts.get('all'):
3818 if r and not opts.get('all'):
3816 skip[fn] = True
3819 skip[fn] = True
3817 if copy:
3820 if copy:
3818 skip[copy] = True
3821 skip[copy] = True
3819 del matches[rev]
3822 del matches[rev]
3820 del revfiles[rev]
3823 del revfiles[rev]
3821
3824
3822 return not found
3825 return not found
3823
3826
3824 @command('heads',
3827 @command('heads',
3825 [('r', 'rev', '',
3828 [('r', 'rev', '',
3826 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3829 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3827 ('t', 'topo', False, _('show topological heads only')),
3830 ('t', 'topo', False, _('show topological heads only')),
3828 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3831 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3829 ('c', 'closed', False, _('show normal and closed branch heads')),
3832 ('c', 'closed', False, _('show normal and closed branch heads')),
3830 ] + templateopts,
3833 ] + templateopts,
3831 _('[-ct] [-r STARTREV] [REV]...'))
3834 _('[-ct] [-r STARTREV] [REV]...'))
3832 def heads(ui, repo, *branchrevs, **opts):
3835 def heads(ui, repo, *branchrevs, **opts):
3833 """show branch heads
3836 """show branch heads
3834
3837
3835 With no arguments, show all open branch heads in the repository.
3838 With no arguments, show all open branch heads in the repository.
3836 Branch heads are changesets that have no descendants on the
3839 Branch heads are changesets that have no descendants on the
3837 same branch. They are where development generally takes place and
3840 same branch. They are where development generally takes place and
3838 are the usual targets for update and merge operations.
3841 are the usual targets for update and merge operations.
3839
3842
3840 If one or more REVs are given, only open branch heads on the
3843 If one or more REVs are given, only open branch heads on the
3841 branches associated with the specified changesets are shown. This
3844 branches associated with the specified changesets are shown. This
3842 means that you can use :hg:`heads .` to see the heads on the
3845 means that you can use :hg:`heads .` to see the heads on the
3843 currently checked-out branch.
3846 currently checked-out branch.
3844
3847
3845 If -c/--closed is specified, also show branch heads marked closed
3848 If -c/--closed is specified, also show branch heads marked closed
3846 (see :hg:`commit --close-branch`).
3849 (see :hg:`commit --close-branch`).
3847
3850
3848 If STARTREV is specified, only those heads that are descendants of
3851 If STARTREV is specified, only those heads that are descendants of
3849 STARTREV will be displayed.
3852 STARTREV will be displayed.
3850
3853
3851 If -t/--topo is specified, named branch mechanics will be ignored and only
3854 If -t/--topo is specified, named branch mechanics will be ignored and only
3852 topological heads (changesets with no children) will be shown.
3855 topological heads (changesets with no children) will be shown.
3853
3856
3854 Returns 0 if matching heads are found, 1 if not.
3857 Returns 0 if matching heads are found, 1 if not.
3855 """
3858 """
3856
3859
3857 start = None
3860 start = None
3858 if 'rev' in opts:
3861 if 'rev' in opts:
3859 start = scmutil.revsingle(repo, opts['rev'], None).node()
3862 start = scmutil.revsingle(repo, opts['rev'], None).node()
3860
3863
3861 if opts.get('topo'):
3864 if opts.get('topo'):
3862 heads = [repo[h] for h in repo.heads(start)]
3865 heads = [repo[h] for h in repo.heads(start)]
3863 else:
3866 else:
3864 heads = []
3867 heads = []
3865 for branch in repo.branchmap():
3868 for branch in repo.branchmap():
3866 heads += repo.branchheads(branch, start, opts.get('closed'))
3869 heads += repo.branchheads(branch, start, opts.get('closed'))
3867 heads = [repo[h] for h in heads]
3870 heads = [repo[h] for h in heads]
3868
3871
3869 if branchrevs:
3872 if branchrevs:
3870 branches = set(repo[br].branch() for br in branchrevs)
3873 branches = set(repo[br].branch() for br in branchrevs)
3871 heads = [h for h in heads if h.branch() in branches]
3874 heads = [h for h in heads if h.branch() in branches]
3872
3875
3873 if opts.get('active') and branchrevs:
3876 if opts.get('active') and branchrevs:
3874 dagheads = repo.heads(start)
3877 dagheads = repo.heads(start)
3875 heads = [h for h in heads if h.node() in dagheads]
3878 heads = [h for h in heads if h.node() in dagheads]
3876
3879
3877 if branchrevs:
3880 if branchrevs:
3878 haveheads = set(h.branch() for h in heads)
3881 haveheads = set(h.branch() for h in heads)
3879 if branches - haveheads:
3882 if branches - haveheads:
3880 headless = ', '.join(b for b in branches - haveheads)
3883 headless = ', '.join(b for b in branches - haveheads)
3881 msg = _('no open branch heads found on branches %s')
3884 msg = _('no open branch heads found on branches %s')
3882 if opts.get('rev'):
3885 if opts.get('rev'):
3883 msg += _(' (started at %s)') % opts['rev']
3886 msg += _(' (started at %s)') % opts['rev']
3884 ui.warn((msg + '\n') % headless)
3887 ui.warn((msg + '\n') % headless)
3885
3888
3886 if not heads:
3889 if not heads:
3887 return 1
3890 return 1
3888
3891
3889 heads = sorted(heads, key=lambda x: -x.rev())
3892 heads = sorted(heads, key=lambda x: -x.rev())
3890 displayer = cmdutil.show_changeset(ui, repo, opts)
3893 displayer = cmdutil.show_changeset(ui, repo, opts)
3891 for ctx in heads:
3894 for ctx in heads:
3892 displayer.show(ctx)
3895 displayer.show(ctx)
3893 displayer.close()
3896 displayer.close()
3894
3897
3895 @command('help',
3898 @command('help',
3896 [('e', 'extension', None, _('show only help for extensions')),
3899 [('e', 'extension', None, _('show only help for extensions')),
3897 ('c', 'command', None, _('show only help for commands')),
3900 ('c', 'command', None, _('show only help for commands')),
3898 ('k', 'keyword', '', _('show topics matching keyword')),
3901 ('k', 'keyword', '', _('show topics matching keyword')),
3899 ],
3902 ],
3900 _('[-ec] [TOPIC]'),
3903 _('[-ec] [TOPIC]'),
3901 norepo=True)
3904 norepo=True)
3902 def help_(ui, name=None, **opts):
3905 def help_(ui, name=None, **opts):
3903 """show help for a given topic or a help overview
3906 """show help for a given topic or a help overview
3904
3907
3905 With no arguments, print a list of commands with short help messages.
3908 With no arguments, print a list of commands with short help messages.
3906
3909
3907 Given a topic, extension, or command name, print help for that
3910 Given a topic, extension, or command name, print help for that
3908 topic.
3911 topic.
3909
3912
3910 Returns 0 if successful.
3913 Returns 0 if successful.
3911 """
3914 """
3912
3915
3913 textwidth = min(ui.termwidth(), 80) - 2
3916 textwidth = min(ui.termwidth(), 80) - 2
3914
3917
3915 keep = []
3918 keep = []
3916 if ui.verbose:
3919 if ui.verbose:
3917 keep.append('verbose')
3920 keep.append('verbose')
3918 if sys.platform.startswith('win'):
3921 if sys.platform.startswith('win'):
3919 keep.append('windows')
3922 keep.append('windows')
3920 elif sys.platform == 'OpenVMS':
3923 elif sys.platform == 'OpenVMS':
3921 keep.append('vms')
3924 keep.append('vms')
3922 elif sys.platform == 'plan9':
3925 elif sys.platform == 'plan9':
3923 keep.append('plan9')
3926 keep.append('plan9')
3924 else:
3927 else:
3925 keep.append('unix')
3928 keep.append('unix')
3926 keep.append(sys.platform.lower())
3929 keep.append(sys.platform.lower())
3927
3930
3928 section = None
3931 section = None
3929 if name and '.' in name:
3932 if name and '.' in name:
3930 name, section = name.split('.', 1)
3933 name, section = name.split('.', 1)
3931
3934
3932 text = help.help_(ui, name, **opts)
3935 text = help.help_(ui, name, **opts)
3933
3936
3934 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3937 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3935 section=section)
3938 section=section)
3936 if section and not formatted:
3939 if section and not formatted:
3937 raise util.Abort(_("help section not found"))
3940 raise util.Abort(_("help section not found"))
3938
3941
3939 if 'verbose' in pruned:
3942 if 'verbose' in pruned:
3940 keep.append('omitted')
3943 keep.append('omitted')
3941 else:
3944 else:
3942 keep.append('notomitted')
3945 keep.append('notomitted')
3943 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3946 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3944 section=section)
3947 section=section)
3945 ui.write(formatted)
3948 ui.write(formatted)
3946
3949
3947
3950
3948 @command('identify|id',
3951 @command('identify|id',
3949 [('r', 'rev', '',
3952 [('r', 'rev', '',
3950 _('identify the specified revision'), _('REV')),
3953 _('identify the specified revision'), _('REV')),
3951 ('n', 'num', None, _('show local revision number')),
3954 ('n', 'num', None, _('show local revision number')),
3952 ('i', 'id', None, _('show global revision id')),
3955 ('i', 'id', None, _('show global revision id')),
3953 ('b', 'branch', None, _('show branch')),
3956 ('b', 'branch', None, _('show branch')),
3954 ('t', 'tags', None, _('show tags')),
3957 ('t', 'tags', None, _('show tags')),
3955 ('B', 'bookmarks', None, _('show bookmarks')),
3958 ('B', 'bookmarks', None, _('show bookmarks')),
3956 ] + remoteopts,
3959 ] + remoteopts,
3957 _('[-nibtB] [-r REV] [SOURCE]'),
3960 _('[-nibtB] [-r REV] [SOURCE]'),
3958 optionalrepo=True)
3961 optionalrepo=True)
3959 def identify(ui, repo, source=None, rev=None,
3962 def identify(ui, repo, source=None, rev=None,
3960 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3963 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3961 """identify the working directory or specified revision
3964 """identify the working directory or specified revision
3962
3965
3963 Print a summary identifying the repository state at REV using one or
3966 Print a summary identifying the repository state at REV using one or
3964 two parent hash identifiers, followed by a "+" if the working
3967 two parent hash identifiers, followed by a "+" if the working
3965 directory has uncommitted changes, the branch name (if not default),
3968 directory has uncommitted changes, the branch name (if not default),
3966 a list of tags, and a list of bookmarks.
3969 a list of tags, and a list of bookmarks.
3967
3970
3968 When REV is not given, print a summary of the current state of the
3971 When REV is not given, print a summary of the current state of the
3969 repository.
3972 repository.
3970
3973
3971 Specifying a path to a repository root or Mercurial bundle will
3974 Specifying a path to a repository root or Mercurial bundle will
3972 cause lookup to operate on that repository/bundle.
3975 cause lookup to operate on that repository/bundle.
3973
3976
3974 .. container:: verbose
3977 .. container:: verbose
3975
3978
3976 Examples:
3979 Examples:
3977
3980
3978 - generate a build identifier for the working directory::
3981 - generate a build identifier for the working directory::
3979
3982
3980 hg id --id > build-id.dat
3983 hg id --id > build-id.dat
3981
3984
3982 - find the revision corresponding to a tag::
3985 - find the revision corresponding to a tag::
3983
3986
3984 hg id -n -r 1.3
3987 hg id -n -r 1.3
3985
3988
3986 - check the most recent revision of a remote repository::
3989 - check the most recent revision of a remote repository::
3987
3990
3988 hg id -r tip http://selenic.com/hg/
3991 hg id -r tip http://selenic.com/hg/
3989
3992
3990 Returns 0 if successful.
3993 Returns 0 if successful.
3991 """
3994 """
3992
3995
3993 if not repo and not source:
3996 if not repo and not source:
3994 raise util.Abort(_("there is no Mercurial repository here "
3997 raise util.Abort(_("there is no Mercurial repository here "
3995 "(.hg not found)"))
3998 "(.hg not found)"))
3996
3999
3997 if ui.debugflag:
4000 if ui.debugflag:
3998 hexfunc = hex
4001 hexfunc = hex
3999 else:
4002 else:
4000 hexfunc = short
4003 hexfunc = short
4001 default = not (num or id or branch or tags or bookmarks)
4004 default = not (num or id or branch or tags or bookmarks)
4002 output = []
4005 output = []
4003 revs = []
4006 revs = []
4004
4007
4005 if source:
4008 if source:
4006 source, branches = hg.parseurl(ui.expandpath(source))
4009 source, branches = hg.parseurl(ui.expandpath(source))
4007 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4010 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4008 repo = peer.local()
4011 repo = peer.local()
4009 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4012 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4010
4013
4011 if not repo:
4014 if not repo:
4012 if num or branch or tags:
4015 if num or branch or tags:
4013 raise util.Abort(
4016 raise util.Abort(
4014 _("can't query remote revision number, branch, or tags"))
4017 _("can't query remote revision number, branch, or tags"))
4015 if not rev and revs:
4018 if not rev and revs:
4016 rev = revs[0]
4019 rev = revs[0]
4017 if not rev:
4020 if not rev:
4018 rev = "tip"
4021 rev = "tip"
4019
4022
4020 remoterev = peer.lookup(rev)
4023 remoterev = peer.lookup(rev)
4021 if default or id:
4024 if default or id:
4022 output = [hexfunc(remoterev)]
4025 output = [hexfunc(remoterev)]
4023
4026
4024 def getbms():
4027 def getbms():
4025 bms = []
4028 bms = []
4026
4029
4027 if 'bookmarks' in peer.listkeys('namespaces'):
4030 if 'bookmarks' in peer.listkeys('namespaces'):
4028 hexremoterev = hex(remoterev)
4031 hexremoterev = hex(remoterev)
4029 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4032 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4030 if bmr == hexremoterev]
4033 if bmr == hexremoterev]
4031
4034
4032 return sorted(bms)
4035 return sorted(bms)
4033
4036
4034 if bookmarks:
4037 if bookmarks:
4035 output.extend(getbms())
4038 output.extend(getbms())
4036 elif default and not ui.quiet:
4039 elif default and not ui.quiet:
4037 # multiple bookmarks for a single parent separated by '/'
4040 # multiple bookmarks for a single parent separated by '/'
4038 bm = '/'.join(getbms())
4041 bm = '/'.join(getbms())
4039 if bm:
4042 if bm:
4040 output.append(bm)
4043 output.append(bm)
4041 else:
4044 else:
4042 if not rev:
4045 if not rev:
4043 ctx = repo[None]
4046 ctx = repo[None]
4044 parents = ctx.parents()
4047 parents = ctx.parents()
4045 changed = ""
4048 changed = ""
4046 if default or id or num:
4049 if default or id or num:
4047 if (util.any(repo.status())
4050 if (util.any(repo.status())
4048 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4051 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4049 changed = '+'
4052 changed = '+'
4050 if default or id:
4053 if default or id:
4051 output = ["%s%s" %
4054 output = ["%s%s" %
4052 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4055 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4053 if num:
4056 if num:
4054 output.append("%s%s" %
4057 output.append("%s%s" %
4055 ('+'.join([str(p.rev()) for p in parents]), changed))
4058 ('+'.join([str(p.rev()) for p in parents]), changed))
4056 else:
4059 else:
4057 ctx = scmutil.revsingle(repo, rev)
4060 ctx = scmutil.revsingle(repo, rev)
4058 if default or id:
4061 if default or id:
4059 output = [hexfunc(ctx.node())]
4062 output = [hexfunc(ctx.node())]
4060 if num:
4063 if num:
4061 output.append(str(ctx.rev()))
4064 output.append(str(ctx.rev()))
4062
4065
4063 if default and not ui.quiet:
4066 if default and not ui.quiet:
4064 b = ctx.branch()
4067 b = ctx.branch()
4065 if b != 'default':
4068 if b != 'default':
4066 output.append("(%s)" % b)
4069 output.append("(%s)" % b)
4067
4070
4068 # multiple tags for a single parent separated by '/'
4071 # multiple tags for a single parent separated by '/'
4069 t = '/'.join(ctx.tags())
4072 t = '/'.join(ctx.tags())
4070 if t:
4073 if t:
4071 output.append(t)
4074 output.append(t)
4072
4075
4073 # multiple bookmarks for a single parent separated by '/'
4076 # multiple bookmarks for a single parent separated by '/'
4074 bm = '/'.join(ctx.bookmarks())
4077 bm = '/'.join(ctx.bookmarks())
4075 if bm:
4078 if bm:
4076 output.append(bm)
4079 output.append(bm)
4077 else:
4080 else:
4078 if branch:
4081 if branch:
4079 output.append(ctx.branch())
4082 output.append(ctx.branch())
4080
4083
4081 if tags:
4084 if tags:
4082 output.extend(ctx.tags())
4085 output.extend(ctx.tags())
4083
4086
4084 if bookmarks:
4087 if bookmarks:
4085 output.extend(ctx.bookmarks())
4088 output.extend(ctx.bookmarks())
4086
4089
4087 ui.write("%s\n" % ' '.join(output))
4090 ui.write("%s\n" % ' '.join(output))
4088
4091
4089 @command('import|patch',
4092 @command('import|patch',
4090 [('p', 'strip', 1,
4093 [('p', 'strip', 1,
4091 _('directory strip option for patch. This has the same '
4094 _('directory strip option for patch. This has the same '
4092 'meaning as the corresponding patch option'), _('NUM')),
4095 'meaning as the corresponding patch option'), _('NUM')),
4093 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4096 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4094 ('e', 'edit', False, _('invoke editor on commit messages')),
4097 ('e', 'edit', False, _('invoke editor on commit messages')),
4095 ('f', 'force', None,
4098 ('f', 'force', None,
4096 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4099 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4097 ('', 'no-commit', None,
4100 ('', 'no-commit', None,
4098 _("don't commit, just update the working directory")),
4101 _("don't commit, just update the working directory")),
4099 ('', 'bypass', None,
4102 ('', 'bypass', None,
4100 _("apply patch without touching the working directory")),
4103 _("apply patch without touching the working directory")),
4101 ('', 'partial', None,
4104 ('', 'partial', None,
4102 _('commit even if some hunks fail')),
4105 _('commit even if some hunks fail')),
4103 ('', 'exact', None,
4106 ('', 'exact', None,
4104 _('apply patch to the nodes from which it was generated')),
4107 _('apply patch to the nodes from which it was generated')),
4105 ('', 'prefix', '',
4108 ('', 'prefix', '',
4106 _('apply patch to subdirectory'), _('DIR')),
4109 _('apply patch to subdirectory'), _('DIR')),
4107 ('', 'import-branch', None,
4110 ('', 'import-branch', None,
4108 _('use any branch information in patch (implied by --exact)'))] +
4111 _('use any branch information in patch (implied by --exact)'))] +
4109 commitopts + commitopts2 + similarityopts,
4112 commitopts + commitopts2 + similarityopts,
4110 _('[OPTION]... PATCH...'))
4113 _('[OPTION]... PATCH...'))
4111 def import_(ui, repo, patch1=None, *patches, **opts):
4114 def import_(ui, repo, patch1=None, *patches, **opts):
4112 """import an ordered set of patches
4115 """import an ordered set of patches
4113
4116
4114 Import a list of patches and commit them individually (unless
4117 Import a list of patches and commit them individually (unless
4115 --no-commit is specified).
4118 --no-commit is specified).
4116
4119
4117 Because import first applies changes to the working directory,
4120 Because import first applies changes to the working directory,
4118 import will abort if there are outstanding changes.
4121 import will abort if there are outstanding changes.
4119
4122
4120 You can import a patch straight from a mail message. Even patches
4123 You can import a patch straight from a mail message. Even patches
4121 as attachments work (to use the body part, it must have type
4124 as attachments work (to use the body part, it must have type
4122 text/plain or text/x-patch). From and Subject headers of email
4125 text/plain or text/x-patch). From and Subject headers of email
4123 message are used as default committer and commit message. All
4126 message are used as default committer and commit message. All
4124 text/plain body parts before first diff are added to commit
4127 text/plain body parts before first diff are added to commit
4125 message.
4128 message.
4126
4129
4127 If the imported patch was generated by :hg:`export`, user and
4130 If the imported patch was generated by :hg:`export`, user and
4128 description from patch override values from message headers and
4131 description from patch override values from message headers and
4129 body. Values given on command line with -m/--message and -u/--user
4132 body. Values given on command line with -m/--message and -u/--user
4130 override these.
4133 override these.
4131
4134
4132 If --exact is specified, import will set the working directory to
4135 If --exact is specified, import will set the working directory to
4133 the parent of each patch before applying it, and will abort if the
4136 the parent of each patch before applying it, and will abort if the
4134 resulting changeset has a different ID than the one recorded in
4137 resulting changeset has a different ID than the one recorded in
4135 the patch. This may happen due to character set problems or other
4138 the patch. This may happen due to character set problems or other
4136 deficiencies in the text patch format.
4139 deficiencies in the text patch format.
4137
4140
4138 Use --bypass to apply and commit patches directly to the
4141 Use --bypass to apply and commit patches directly to the
4139 repository, not touching the working directory. Without --exact,
4142 repository, not touching the working directory. Without --exact,
4140 patches will be applied on top of the working directory parent
4143 patches will be applied on top of the working directory parent
4141 revision.
4144 revision.
4142
4145
4143 With -s/--similarity, hg will attempt to discover renames and
4146 With -s/--similarity, hg will attempt to discover renames and
4144 copies in the patch in the same way as :hg:`addremove`.
4147 copies in the patch in the same way as :hg:`addremove`.
4145
4148
4146 Use --partial to ensure a changeset will be created from the patch
4149 Use --partial to ensure a changeset will be created from the patch
4147 even if some hunks fail to apply. Hunks that fail to apply will be
4150 even if some hunks fail to apply. Hunks that fail to apply will be
4148 written to a <target-file>.rej file. Conflicts can then be resolved
4151 written to a <target-file>.rej file. Conflicts can then be resolved
4149 by hand before :hg:`commit --amend` is run to update the created
4152 by hand before :hg:`commit --amend` is run to update the created
4150 changeset. This flag exists to let people import patches that
4153 changeset. This flag exists to let people import patches that
4151 partially apply without losing the associated metadata (author,
4154 partially apply without losing the associated metadata (author,
4152 date, description, ...). Note that when none of the hunk applies
4155 date, description, ...). Note that when none of the hunk applies
4153 cleanly, :hg:`import --partial` will create an empty changeset,
4156 cleanly, :hg:`import --partial` will create an empty changeset,
4154 importing only the patch metadata.
4157 importing only the patch metadata.
4155
4158
4156 To read a patch from standard input, use "-" as the patch name. If
4159 To read a patch from standard input, use "-" as the patch name. If
4157 a URL is specified, the patch will be downloaded from it.
4160 a URL is specified, the patch will be downloaded from it.
4158 See :hg:`help dates` for a list of formats valid for -d/--date.
4161 See :hg:`help dates` for a list of formats valid for -d/--date.
4159
4162
4160 .. container:: verbose
4163 .. container:: verbose
4161
4164
4162 Examples:
4165 Examples:
4163
4166
4164 - import a traditional patch from a website and detect renames::
4167 - import a traditional patch from a website and detect renames::
4165
4168
4166 hg import -s 80 http://example.com/bugfix.patch
4169 hg import -s 80 http://example.com/bugfix.patch
4167
4170
4168 - import a changeset from an hgweb server::
4171 - import a changeset from an hgweb server::
4169
4172
4170 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4173 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4171
4174
4172 - import all the patches in an Unix-style mbox::
4175 - import all the patches in an Unix-style mbox::
4173
4176
4174 hg import incoming-patches.mbox
4177 hg import incoming-patches.mbox
4175
4178
4176 - attempt to exactly restore an exported changeset (not always
4179 - attempt to exactly restore an exported changeset (not always
4177 possible)::
4180 possible)::
4178
4181
4179 hg import --exact proposed-fix.patch
4182 hg import --exact proposed-fix.patch
4180
4183
4181 Returns 0 on success, 1 on partial success (see --partial).
4184 Returns 0 on success, 1 on partial success (see --partial).
4182 """
4185 """
4183
4186
4184 if not patch1:
4187 if not patch1:
4185 raise util.Abort(_('need at least one patch to import'))
4188 raise util.Abort(_('need at least one patch to import'))
4186
4189
4187 patches = (patch1,) + patches
4190 patches = (patch1,) + patches
4188
4191
4189 date = opts.get('date')
4192 date = opts.get('date')
4190 if date:
4193 if date:
4191 opts['date'] = util.parsedate(date)
4194 opts['date'] = util.parsedate(date)
4192
4195
4193 update = not opts.get('bypass')
4196 update = not opts.get('bypass')
4194 if not update and opts.get('no_commit'):
4197 if not update and opts.get('no_commit'):
4195 raise util.Abort(_('cannot use --no-commit with --bypass'))
4198 raise util.Abort(_('cannot use --no-commit with --bypass'))
4196 try:
4199 try:
4197 sim = float(opts.get('similarity') or 0)
4200 sim = float(opts.get('similarity') or 0)
4198 except ValueError:
4201 except ValueError:
4199 raise util.Abort(_('similarity must be a number'))
4202 raise util.Abort(_('similarity must be a number'))
4200 if sim < 0 or sim > 100:
4203 if sim < 0 or sim > 100:
4201 raise util.Abort(_('similarity must be between 0 and 100'))
4204 raise util.Abort(_('similarity must be between 0 and 100'))
4202 if sim and not update:
4205 if sim and not update:
4203 raise util.Abort(_('cannot use --similarity with --bypass'))
4206 raise util.Abort(_('cannot use --similarity with --bypass'))
4204 if opts.get('exact') and opts.get('edit'):
4207 if opts.get('exact') and opts.get('edit'):
4205 raise util.Abort(_('cannot use --exact with --edit'))
4208 raise util.Abort(_('cannot use --exact with --edit'))
4206 if opts.get('exact') and opts.get('prefix'):
4209 if opts.get('exact') and opts.get('prefix'):
4207 raise util.Abort(_('cannot use --exact with --prefix'))
4210 raise util.Abort(_('cannot use --exact with --prefix'))
4208
4211
4209 if update:
4212 if update:
4210 cmdutil.checkunfinished(repo)
4213 cmdutil.checkunfinished(repo)
4211 if (opts.get('exact') or not opts.get('force')) and update:
4214 if (opts.get('exact') or not opts.get('force')) and update:
4212 cmdutil.bailifchanged(repo)
4215 cmdutil.bailifchanged(repo)
4213
4216
4214 base = opts["base"]
4217 base = opts["base"]
4215 wlock = lock = tr = None
4218 wlock = lock = tr = None
4216 msgs = []
4219 msgs = []
4217 ret = 0
4220 ret = 0
4218
4221
4219
4222
4220 try:
4223 try:
4221 try:
4224 try:
4222 wlock = repo.wlock()
4225 wlock = repo.wlock()
4223 repo.dirstate.beginparentchange()
4226 repo.dirstate.beginparentchange()
4224 if not opts.get('no_commit'):
4227 if not opts.get('no_commit'):
4225 lock = repo.lock()
4228 lock = repo.lock()
4226 tr = repo.transaction('import')
4229 tr = repo.transaction('import')
4227 parents = repo.parents()
4230 parents = repo.parents()
4228 for patchurl in patches:
4231 for patchurl in patches:
4229 if patchurl == '-':
4232 if patchurl == '-':
4230 ui.status(_('applying patch from stdin\n'))
4233 ui.status(_('applying patch from stdin\n'))
4231 patchfile = ui.fin
4234 patchfile = ui.fin
4232 patchurl = 'stdin' # for error message
4235 patchurl = 'stdin' # for error message
4233 else:
4236 else:
4234 patchurl = os.path.join(base, patchurl)
4237 patchurl = os.path.join(base, patchurl)
4235 ui.status(_('applying %s\n') % patchurl)
4238 ui.status(_('applying %s\n') % patchurl)
4236 patchfile = hg.openpath(ui, patchurl)
4239 patchfile = hg.openpath(ui, patchurl)
4237
4240
4238 haspatch = False
4241 haspatch = False
4239 for hunk in patch.split(patchfile):
4242 for hunk in patch.split(patchfile):
4240 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4243 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4241 parents, opts,
4244 parents, opts,
4242 msgs, hg.clean)
4245 msgs, hg.clean)
4243 if msg:
4246 if msg:
4244 haspatch = True
4247 haspatch = True
4245 ui.note(msg + '\n')
4248 ui.note(msg + '\n')
4246 if update or opts.get('exact'):
4249 if update or opts.get('exact'):
4247 parents = repo.parents()
4250 parents = repo.parents()
4248 else:
4251 else:
4249 parents = [repo[node]]
4252 parents = [repo[node]]
4250 if rej:
4253 if rej:
4251 ui.write_err(_("patch applied partially\n"))
4254 ui.write_err(_("patch applied partially\n"))
4252 ui.write_err(_("(fix the .rej files and run "
4255 ui.write_err(_("(fix the .rej files and run "
4253 "`hg commit --amend`)\n"))
4256 "`hg commit --amend`)\n"))
4254 ret = 1
4257 ret = 1
4255 break
4258 break
4256
4259
4257 if not haspatch:
4260 if not haspatch:
4258 raise util.Abort(_('%s: no diffs found') % patchurl)
4261 raise util.Abort(_('%s: no diffs found') % patchurl)
4259
4262
4260 if tr:
4263 if tr:
4261 tr.close()
4264 tr.close()
4262 if msgs:
4265 if msgs:
4263 repo.savecommitmessage('\n* * *\n'.join(msgs))
4266 repo.savecommitmessage('\n* * *\n'.join(msgs))
4264 repo.dirstate.endparentchange()
4267 repo.dirstate.endparentchange()
4265 return ret
4268 return ret
4266 except: # re-raises
4269 except: # re-raises
4267 # wlock.release() indirectly calls dirstate.write(): since
4270 # wlock.release() indirectly calls dirstate.write(): since
4268 # we're crashing, we do not want to change the working dir
4271 # we're crashing, we do not want to change the working dir
4269 # parent after all, so make sure it writes nothing
4272 # parent after all, so make sure it writes nothing
4270 repo.dirstate.invalidate()
4273 repo.dirstate.invalidate()
4271 raise
4274 raise
4272 finally:
4275 finally:
4273 if tr:
4276 if tr:
4274 tr.release()
4277 tr.release()
4275 release(lock, wlock)
4278 release(lock, wlock)
4276
4279
4277 @command('incoming|in',
4280 @command('incoming|in',
4278 [('f', 'force', None,
4281 [('f', 'force', None,
4279 _('run even if remote repository is unrelated')),
4282 _('run even if remote repository is unrelated')),
4280 ('n', 'newest-first', None, _('show newest record first')),
4283 ('n', 'newest-first', None, _('show newest record first')),
4281 ('', 'bundle', '',
4284 ('', 'bundle', '',
4282 _('file to store the bundles into'), _('FILE')),
4285 _('file to store the bundles into'), _('FILE')),
4283 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4286 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4284 ('B', 'bookmarks', False, _("compare bookmarks")),
4287 ('B', 'bookmarks', False, _("compare bookmarks")),
4285 ('b', 'branch', [],
4288 ('b', 'branch', [],
4286 _('a specific branch you would like to pull'), _('BRANCH')),
4289 _('a specific branch you would like to pull'), _('BRANCH')),
4287 ] + logopts + remoteopts + subrepoopts,
4290 ] + logopts + remoteopts + subrepoopts,
4288 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4291 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4289 def incoming(ui, repo, source="default", **opts):
4292 def incoming(ui, repo, source="default", **opts):
4290 """show new changesets found in source
4293 """show new changesets found in source
4291
4294
4292 Show new changesets found in the specified path/URL or the default
4295 Show new changesets found in the specified path/URL or the default
4293 pull location. These are the changesets that would have been pulled
4296 pull location. These are the changesets that would have been pulled
4294 if a pull at the time you issued this command.
4297 if a pull at the time you issued this command.
4295
4298
4296 See pull for valid source format details.
4299 See pull for valid source format details.
4297
4300
4298 .. container:: verbose
4301 .. container:: verbose
4299
4302
4300 For remote repository, using --bundle avoids downloading the
4303 For remote repository, using --bundle avoids downloading the
4301 changesets twice if the incoming is followed by a pull.
4304 changesets twice if the incoming is followed by a pull.
4302
4305
4303 Examples:
4306 Examples:
4304
4307
4305 - show incoming changes with patches and full description::
4308 - show incoming changes with patches and full description::
4306
4309
4307 hg incoming -vp
4310 hg incoming -vp
4308
4311
4309 - show incoming changes excluding merges, store a bundle::
4312 - show incoming changes excluding merges, store a bundle::
4310
4313
4311 hg in -vpM --bundle incoming.hg
4314 hg in -vpM --bundle incoming.hg
4312 hg pull incoming.hg
4315 hg pull incoming.hg
4313
4316
4314 - briefly list changes inside a bundle::
4317 - briefly list changes inside a bundle::
4315
4318
4316 hg in changes.hg -T "{desc|firstline}\\n"
4319 hg in changes.hg -T "{desc|firstline}\\n"
4317
4320
4318 Returns 0 if there are incoming changes, 1 otherwise.
4321 Returns 0 if there are incoming changes, 1 otherwise.
4319 """
4322 """
4320 if opts.get('graph'):
4323 if opts.get('graph'):
4321 cmdutil.checkunsupportedgraphflags([], opts)
4324 cmdutil.checkunsupportedgraphflags([], opts)
4322 def display(other, chlist, displayer):
4325 def display(other, chlist, displayer):
4323 revdag = cmdutil.graphrevs(other, chlist, opts)
4326 revdag = cmdutil.graphrevs(other, chlist, opts)
4324 showparents = [ctx.node() for ctx in repo[None].parents()]
4327 showparents = [ctx.node() for ctx in repo[None].parents()]
4325 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4328 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4326 graphmod.asciiedges)
4329 graphmod.asciiedges)
4327
4330
4328 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4331 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4329 return 0
4332 return 0
4330
4333
4331 if opts.get('bundle') and opts.get('subrepos'):
4334 if opts.get('bundle') and opts.get('subrepos'):
4332 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4335 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4333
4336
4334 if opts.get('bookmarks'):
4337 if opts.get('bookmarks'):
4335 source, branches = hg.parseurl(ui.expandpath(source),
4338 source, branches = hg.parseurl(ui.expandpath(source),
4336 opts.get('branch'))
4339 opts.get('branch'))
4337 other = hg.peer(repo, opts, source)
4340 other = hg.peer(repo, opts, source)
4338 if 'bookmarks' not in other.listkeys('namespaces'):
4341 if 'bookmarks' not in other.listkeys('namespaces'):
4339 ui.warn(_("remote doesn't support bookmarks\n"))
4342 ui.warn(_("remote doesn't support bookmarks\n"))
4340 return 0
4343 return 0
4341 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4344 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4342 return bookmarks.incoming(ui, repo, other)
4345 return bookmarks.incoming(ui, repo, other)
4343
4346
4344 repo._subtoppath = ui.expandpath(source)
4347 repo._subtoppath = ui.expandpath(source)
4345 try:
4348 try:
4346 return hg.incoming(ui, repo, source, opts)
4349 return hg.incoming(ui, repo, source, opts)
4347 finally:
4350 finally:
4348 del repo._subtoppath
4351 del repo._subtoppath
4349
4352
4350
4353
4351 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4354 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4352 norepo=True)
4355 norepo=True)
4353 def init(ui, dest=".", **opts):
4356 def init(ui, dest=".", **opts):
4354 """create a new repository in the given directory
4357 """create a new repository in the given directory
4355
4358
4356 Initialize a new repository in the given directory. If the given
4359 Initialize a new repository in the given directory. If the given
4357 directory does not exist, it will be created.
4360 directory does not exist, it will be created.
4358
4361
4359 If no directory is given, the current directory is used.
4362 If no directory is given, the current directory is used.
4360
4363
4361 It is possible to specify an ``ssh://`` URL as the destination.
4364 It is possible to specify an ``ssh://`` URL as the destination.
4362 See :hg:`help urls` for more information.
4365 See :hg:`help urls` for more information.
4363
4366
4364 Returns 0 on success.
4367 Returns 0 on success.
4365 """
4368 """
4366 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4369 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4367
4370
4368 @command('locate',
4371 @command('locate',
4369 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4372 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4370 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4373 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4371 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4374 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4372 ] + walkopts,
4375 ] + walkopts,
4373 _('[OPTION]... [PATTERN]...'))
4376 _('[OPTION]... [PATTERN]...'))
4374 def locate(ui, repo, *pats, **opts):
4377 def locate(ui, repo, *pats, **opts):
4375 """locate files matching specific patterns (DEPRECATED)
4378 """locate files matching specific patterns (DEPRECATED)
4376
4379
4377 Print files under Mercurial control in the working directory whose
4380 Print files under Mercurial control in the working directory whose
4378 names match the given patterns.
4381 names match the given patterns.
4379
4382
4380 By default, this command searches all directories in the working
4383 By default, this command searches all directories in the working
4381 directory. To search just the current directory and its
4384 directory. To search just the current directory and its
4382 subdirectories, use "--include .".
4385 subdirectories, use "--include .".
4383
4386
4384 If no patterns are given to match, this command prints the names
4387 If no patterns are given to match, this command prints the names
4385 of all files under Mercurial control in the working directory.
4388 of all files under Mercurial control in the working directory.
4386
4389
4387 If you want to feed the output of this command into the "xargs"
4390 If you want to feed the output of this command into the "xargs"
4388 command, use the -0 option to both this command and "xargs". This
4391 command, use the -0 option to both this command and "xargs". This
4389 will avoid the problem of "xargs" treating single filenames that
4392 will avoid the problem of "xargs" treating single filenames that
4390 contain whitespace as multiple filenames.
4393 contain whitespace as multiple filenames.
4391
4394
4392 See :hg:`help files` for a more versatile command.
4395 See :hg:`help files` for a more versatile command.
4393
4396
4394 Returns 0 if a match is found, 1 otherwise.
4397 Returns 0 if a match is found, 1 otherwise.
4395 """
4398 """
4396 if opts.get('print0'):
4399 if opts.get('print0'):
4397 end = '\0'
4400 end = '\0'
4398 else:
4401 else:
4399 end = '\n'
4402 end = '\n'
4400 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4403 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4401
4404
4402 ret = 1
4405 ret = 1
4403 ctx = repo[rev]
4406 ctx = repo[rev]
4404 m = scmutil.match(ctx, pats, opts, default='relglob')
4407 m = scmutil.match(ctx, pats, opts, default='relglob')
4405 m.bad = lambda x, y: False
4408 m.bad = lambda x, y: False
4406
4409
4407 for abs in ctx.matches(m):
4410 for abs in ctx.matches(m):
4408 if opts.get('fullpath'):
4411 if opts.get('fullpath'):
4409 ui.write(repo.wjoin(abs), end)
4412 ui.write(repo.wjoin(abs), end)
4410 else:
4413 else:
4411 ui.write(((pats and m.rel(abs)) or abs), end)
4414 ui.write(((pats and m.rel(abs)) or abs), end)
4412 ret = 0
4415 ret = 0
4413
4416
4414 return ret
4417 return ret
4415
4418
4416 @command('^log|history',
4419 @command('^log|history',
4417 [('f', 'follow', None,
4420 [('f', 'follow', None,
4418 _('follow changeset history, or file history across copies and renames')),
4421 _('follow changeset history, or file history across copies and renames')),
4419 ('', 'follow-first', None,
4422 ('', 'follow-first', None,
4420 _('only follow the first parent of merge changesets (DEPRECATED)')),
4423 _('only follow the first parent of merge changesets (DEPRECATED)')),
4421 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4424 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4422 ('C', 'copies', None, _('show copied files')),
4425 ('C', 'copies', None, _('show copied files')),
4423 ('k', 'keyword', [],
4426 ('k', 'keyword', [],
4424 _('do case-insensitive search for a given text'), _('TEXT')),
4427 _('do case-insensitive search for a given text'), _('TEXT')),
4425 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4428 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4426 ('', 'removed', None, _('include revisions where files were removed')),
4429 ('', 'removed', None, _('include revisions where files were removed')),
4427 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4430 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4428 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4431 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4429 ('', 'only-branch', [],
4432 ('', 'only-branch', [],
4430 _('show only changesets within the given named branch (DEPRECATED)'),
4433 _('show only changesets within the given named branch (DEPRECATED)'),
4431 _('BRANCH')),
4434 _('BRANCH')),
4432 ('b', 'branch', [],
4435 ('b', 'branch', [],
4433 _('show changesets within the given named branch'), _('BRANCH')),
4436 _('show changesets within the given named branch'), _('BRANCH')),
4434 ('P', 'prune', [],
4437 ('P', 'prune', [],
4435 _('do not display revision or any of its ancestors'), _('REV')),
4438 _('do not display revision or any of its ancestors'), _('REV')),
4436 ] + logopts + walkopts,
4439 ] + logopts + walkopts,
4437 _('[OPTION]... [FILE]'),
4440 _('[OPTION]... [FILE]'),
4438 inferrepo=True)
4441 inferrepo=True)
4439 def log(ui, repo, *pats, **opts):
4442 def log(ui, repo, *pats, **opts):
4440 """show revision history of entire repository or files
4443 """show revision history of entire repository or files
4441
4444
4442 Print the revision history of the specified files or the entire
4445 Print the revision history of the specified files or the entire
4443 project.
4446 project.
4444
4447
4445 If no revision range is specified, the default is ``tip:0`` unless
4448 If no revision range is specified, the default is ``tip:0`` unless
4446 --follow is set, in which case the working directory parent is
4449 --follow is set, in which case the working directory parent is
4447 used as the starting revision.
4450 used as the starting revision.
4448
4451
4449 File history is shown without following rename or copy history of
4452 File history is shown without following rename or copy history of
4450 files. Use -f/--follow with a filename to follow history across
4453 files. Use -f/--follow with a filename to follow history across
4451 renames and copies. --follow without a filename will only show
4454 renames and copies. --follow without a filename will only show
4452 ancestors or descendants of the starting revision.
4455 ancestors or descendants of the starting revision.
4453
4456
4454 By default this command prints revision number and changeset id,
4457 By default this command prints revision number and changeset id,
4455 tags, non-trivial parents, user, date and time, and a summary for
4458 tags, non-trivial parents, user, date and time, and a summary for
4456 each commit. When the -v/--verbose switch is used, the list of
4459 each commit. When the -v/--verbose switch is used, the list of
4457 changed files and full commit message are shown.
4460 changed files and full commit message are shown.
4458
4461
4459 With --graph the revisions are shown as an ASCII art DAG with the most
4462 With --graph the revisions are shown as an ASCII art DAG with the most
4460 recent changeset at the top.
4463 recent changeset at the top.
4461 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4464 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4462 and '+' represents a fork where the changeset from the lines below is a
4465 and '+' represents a fork where the changeset from the lines below is a
4463 parent of the 'o' merge on the same line.
4466 parent of the 'o' merge on the same line.
4464
4467
4465 .. note::
4468 .. note::
4466
4469
4467 log -p/--patch may generate unexpected diff output for merge
4470 log -p/--patch may generate unexpected diff output for merge
4468 changesets, as it will only compare the merge changeset against
4471 changesets, as it will only compare the merge changeset against
4469 its first parent. Also, only files different from BOTH parents
4472 its first parent. Also, only files different from BOTH parents
4470 will appear in files:.
4473 will appear in files:.
4471
4474
4472 .. note::
4475 .. note::
4473
4476
4474 for performance reasons, log FILE may omit duplicate changes
4477 for performance reasons, log FILE may omit duplicate changes
4475 made on branches and will not show removals or mode changes. To
4478 made on branches and will not show removals or mode changes. To
4476 see all such changes, use the --removed switch.
4479 see all such changes, use the --removed switch.
4477
4480
4478 .. container:: verbose
4481 .. container:: verbose
4479
4482
4480 Some examples:
4483 Some examples:
4481
4484
4482 - changesets with full descriptions and file lists::
4485 - changesets with full descriptions and file lists::
4483
4486
4484 hg log -v
4487 hg log -v
4485
4488
4486 - changesets ancestral to the working directory::
4489 - changesets ancestral to the working directory::
4487
4490
4488 hg log -f
4491 hg log -f
4489
4492
4490 - last 10 commits on the current branch::
4493 - last 10 commits on the current branch::
4491
4494
4492 hg log -l 10 -b .
4495 hg log -l 10 -b .
4493
4496
4494 - changesets showing all modifications of a file, including removals::
4497 - changesets showing all modifications of a file, including removals::
4495
4498
4496 hg log --removed file.c
4499 hg log --removed file.c
4497
4500
4498 - all changesets that touch a directory, with diffs, excluding merges::
4501 - all changesets that touch a directory, with diffs, excluding merges::
4499
4502
4500 hg log -Mp lib/
4503 hg log -Mp lib/
4501
4504
4502 - all revision numbers that match a keyword::
4505 - all revision numbers that match a keyword::
4503
4506
4504 hg log -k bug --template "{rev}\\n"
4507 hg log -k bug --template "{rev}\\n"
4505
4508
4506 - list available log templates::
4509 - list available log templates::
4507
4510
4508 hg log -T list
4511 hg log -T list
4509
4512
4510 - check if a given changeset is included in a tagged release::
4513 - check if a given changeset is included in a tagged release::
4511
4514
4512 hg log -r "a21ccf and ancestor(1.9)"
4515 hg log -r "a21ccf and ancestor(1.9)"
4513
4516
4514 - find all changesets by some user in a date range::
4517 - find all changesets by some user in a date range::
4515
4518
4516 hg log -k alice -d "may 2008 to jul 2008"
4519 hg log -k alice -d "may 2008 to jul 2008"
4517
4520
4518 - summary of all changesets after the last tag::
4521 - summary of all changesets after the last tag::
4519
4522
4520 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4523 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4521
4524
4522 See :hg:`help dates` for a list of formats valid for -d/--date.
4525 See :hg:`help dates` for a list of formats valid for -d/--date.
4523
4526
4524 See :hg:`help revisions` and :hg:`help revsets` for more about
4527 See :hg:`help revisions` and :hg:`help revsets` for more about
4525 specifying revisions.
4528 specifying revisions.
4526
4529
4527 See :hg:`help templates` for more about pre-packaged styles and
4530 See :hg:`help templates` for more about pre-packaged styles and
4528 specifying custom templates.
4531 specifying custom templates.
4529
4532
4530 Returns 0 on success.
4533 Returns 0 on success.
4531
4534
4532 """
4535 """
4533 if opts.get('follow') and opts.get('rev'):
4536 if opts.get('follow') and opts.get('rev'):
4534 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4537 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4535 del opts['follow']
4538 del opts['follow']
4536
4539
4537 if opts.get('graph'):
4540 if opts.get('graph'):
4538 return cmdutil.graphlog(ui, repo, *pats, **opts)
4541 return cmdutil.graphlog(ui, repo, *pats, **opts)
4539
4542
4540 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4543 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4541 limit = cmdutil.loglimit(opts)
4544 limit = cmdutil.loglimit(opts)
4542 count = 0
4545 count = 0
4543
4546
4544 getrenamed = None
4547 getrenamed = None
4545 if opts.get('copies'):
4548 if opts.get('copies'):
4546 endrev = None
4549 endrev = None
4547 if opts.get('rev'):
4550 if opts.get('rev'):
4548 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4551 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4549 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4552 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4550
4553
4551 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4554 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4552 for rev in revs:
4555 for rev in revs:
4553 if count == limit:
4556 if count == limit:
4554 break
4557 break
4555 ctx = repo[rev]
4558 ctx = repo[rev]
4556 copies = None
4559 copies = None
4557 if getrenamed is not None and rev:
4560 if getrenamed is not None and rev:
4558 copies = []
4561 copies = []
4559 for fn in ctx.files():
4562 for fn in ctx.files():
4560 rename = getrenamed(fn, rev)
4563 rename = getrenamed(fn, rev)
4561 if rename:
4564 if rename:
4562 copies.append((fn, rename[0]))
4565 copies.append((fn, rename[0]))
4563 if filematcher:
4566 if filematcher:
4564 revmatchfn = filematcher(ctx.rev())
4567 revmatchfn = filematcher(ctx.rev())
4565 else:
4568 else:
4566 revmatchfn = None
4569 revmatchfn = None
4567 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4570 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4568 if displayer.flush(rev):
4571 if displayer.flush(rev):
4569 count += 1
4572 count += 1
4570
4573
4571 displayer.close()
4574 displayer.close()
4572
4575
4573 @command('manifest',
4576 @command('manifest',
4574 [('r', 'rev', '', _('revision to display'), _('REV')),
4577 [('r', 'rev', '', _('revision to display'), _('REV')),
4575 ('', 'all', False, _("list files from all revisions"))]
4578 ('', 'all', False, _("list files from all revisions"))]
4576 + formatteropts,
4579 + formatteropts,
4577 _('[-r REV]'))
4580 _('[-r REV]'))
4578 def manifest(ui, repo, node=None, rev=None, **opts):
4581 def manifest(ui, repo, node=None, rev=None, **opts):
4579 """output the current or given revision of the project manifest
4582 """output the current or given revision of the project manifest
4580
4583
4581 Print a list of version controlled files for the given revision.
4584 Print a list of version controlled files for the given revision.
4582 If no revision is given, the first parent of the working directory
4585 If no revision is given, the first parent of the working directory
4583 is used, or the null revision if no revision is checked out.
4586 is used, or the null revision if no revision is checked out.
4584
4587
4585 With -v, print file permissions, symlink and executable bits.
4588 With -v, print file permissions, symlink and executable bits.
4586 With --debug, print file revision hashes.
4589 With --debug, print file revision hashes.
4587
4590
4588 If option --all is specified, the list of all files from all revisions
4591 If option --all is specified, the list of all files from all revisions
4589 is printed. This includes deleted and renamed files.
4592 is printed. This includes deleted and renamed files.
4590
4593
4591 Returns 0 on success.
4594 Returns 0 on success.
4592 """
4595 """
4593
4596
4594 fm = ui.formatter('manifest', opts)
4597 fm = ui.formatter('manifest', opts)
4595
4598
4596 if opts.get('all'):
4599 if opts.get('all'):
4597 if rev or node:
4600 if rev or node:
4598 raise util.Abort(_("can't specify a revision with --all"))
4601 raise util.Abort(_("can't specify a revision with --all"))
4599
4602
4600 res = []
4603 res = []
4601 prefix = "data/"
4604 prefix = "data/"
4602 suffix = ".i"
4605 suffix = ".i"
4603 plen = len(prefix)
4606 plen = len(prefix)
4604 slen = len(suffix)
4607 slen = len(suffix)
4605 lock = repo.lock()
4608 lock = repo.lock()
4606 try:
4609 try:
4607 for fn, b, size in repo.store.datafiles():
4610 for fn, b, size in repo.store.datafiles():
4608 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4611 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4609 res.append(fn[plen:-slen])
4612 res.append(fn[plen:-slen])
4610 finally:
4613 finally:
4611 lock.release()
4614 lock.release()
4612 for f in res:
4615 for f in res:
4613 fm.startitem()
4616 fm.startitem()
4614 fm.write("path", '%s\n', f)
4617 fm.write("path", '%s\n', f)
4615 fm.end()
4618 fm.end()
4616 return
4619 return
4617
4620
4618 if rev and node:
4621 if rev and node:
4619 raise util.Abort(_("please specify just one revision"))
4622 raise util.Abort(_("please specify just one revision"))
4620
4623
4621 if not node:
4624 if not node:
4622 node = rev
4625 node = rev
4623
4626
4624 char = {'l': '@', 'x': '*', '': ''}
4627 char = {'l': '@', 'x': '*', '': ''}
4625 mode = {'l': '644', 'x': '755', '': '644'}
4628 mode = {'l': '644', 'x': '755', '': '644'}
4626 ctx = scmutil.revsingle(repo, node)
4629 ctx = scmutil.revsingle(repo, node)
4627 mf = ctx.manifest()
4630 mf = ctx.manifest()
4628 for f in ctx:
4631 for f in ctx:
4629 fm.startitem()
4632 fm.startitem()
4630 fl = ctx[f].flags()
4633 fl = ctx[f].flags()
4631 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4634 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4632 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4635 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4633 fm.write('path', '%s\n', f)
4636 fm.write('path', '%s\n', f)
4634 fm.end()
4637 fm.end()
4635
4638
4636 @command('^merge',
4639 @command('^merge',
4637 [('f', 'force', None,
4640 [('f', 'force', None,
4638 _('force a merge including outstanding changes (DEPRECATED)')),
4641 _('force a merge including outstanding changes (DEPRECATED)')),
4639 ('r', 'rev', '', _('revision to merge'), _('REV')),
4642 ('r', 'rev', '', _('revision to merge'), _('REV')),
4640 ('P', 'preview', None,
4643 ('P', 'preview', None,
4641 _('review revisions to merge (no merge is performed)'))
4644 _('review revisions to merge (no merge is performed)'))
4642 ] + mergetoolopts,
4645 ] + mergetoolopts,
4643 _('[-P] [-f] [[-r] REV]'))
4646 _('[-P] [-f] [[-r] REV]'))
4644 def merge(ui, repo, node=None, **opts):
4647 def merge(ui, repo, node=None, **opts):
4645 """merge another revision into working directory
4648 """merge another revision into working directory
4646
4649
4647 The current working directory is updated with all changes made in
4650 The current working directory is updated with all changes made in
4648 the requested revision since the last common predecessor revision.
4651 the requested revision since the last common predecessor revision.
4649
4652
4650 Files that changed between either parent are marked as changed for
4653 Files that changed between either parent are marked as changed for
4651 the next commit and a commit must be performed before any further
4654 the next commit and a commit must be performed before any further
4652 updates to the repository are allowed. The next commit will have
4655 updates to the repository are allowed. The next commit will have
4653 two parents.
4656 two parents.
4654
4657
4655 ``--tool`` can be used to specify the merge tool used for file
4658 ``--tool`` can be used to specify the merge tool used for file
4656 merges. It overrides the HGMERGE environment variable and your
4659 merges. It overrides the HGMERGE environment variable and your
4657 configuration files. See :hg:`help merge-tools` for options.
4660 configuration files. See :hg:`help merge-tools` for options.
4658
4661
4659 If no revision is specified, the working directory's parent is a
4662 If no revision is specified, the working directory's parent is a
4660 head revision, and the current branch contains exactly one other
4663 head revision, and the current branch contains exactly one other
4661 head, the other head is merged with by default. Otherwise, an
4664 head, the other head is merged with by default. Otherwise, an
4662 explicit revision with which to merge with must be provided.
4665 explicit revision with which to merge with must be provided.
4663
4666
4664 :hg:`resolve` must be used to resolve unresolved files.
4667 :hg:`resolve` must be used to resolve unresolved files.
4665
4668
4666 To undo an uncommitted merge, use :hg:`update --clean .` which
4669 To undo an uncommitted merge, use :hg:`update --clean .` which
4667 will check out a clean copy of the original merge parent, losing
4670 will check out a clean copy of the original merge parent, losing
4668 all changes.
4671 all changes.
4669
4672
4670 Returns 0 on success, 1 if there are unresolved files.
4673 Returns 0 on success, 1 if there are unresolved files.
4671 """
4674 """
4672
4675
4673 if opts.get('rev') and node:
4676 if opts.get('rev') and node:
4674 raise util.Abort(_("please specify just one revision"))
4677 raise util.Abort(_("please specify just one revision"))
4675 if not node:
4678 if not node:
4676 node = opts.get('rev')
4679 node = opts.get('rev')
4677
4680
4678 if node:
4681 if node:
4679 node = scmutil.revsingle(repo, node).node()
4682 node = scmutil.revsingle(repo, node).node()
4680
4683
4681 if not node and repo._bookmarkcurrent:
4684 if not node and repo._bookmarkcurrent:
4682 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4685 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4683 curhead = repo[repo._bookmarkcurrent].node()
4686 curhead = repo[repo._bookmarkcurrent].node()
4684 if len(bmheads) == 2:
4687 if len(bmheads) == 2:
4685 if curhead == bmheads[0]:
4688 if curhead == bmheads[0]:
4686 node = bmheads[1]
4689 node = bmheads[1]
4687 else:
4690 else:
4688 node = bmheads[0]
4691 node = bmheads[0]
4689 elif len(bmheads) > 2:
4692 elif len(bmheads) > 2:
4690 raise util.Abort(_("multiple matching bookmarks to merge - "
4693 raise util.Abort(_("multiple matching bookmarks to merge - "
4691 "please merge with an explicit rev or bookmark"),
4694 "please merge with an explicit rev or bookmark"),
4692 hint=_("run 'hg heads' to see all heads"))
4695 hint=_("run 'hg heads' to see all heads"))
4693 elif len(bmheads) <= 1:
4696 elif len(bmheads) <= 1:
4694 raise util.Abort(_("no matching bookmark to merge - "
4697 raise util.Abort(_("no matching bookmark to merge - "
4695 "please merge with an explicit rev or bookmark"),
4698 "please merge with an explicit rev or bookmark"),
4696 hint=_("run 'hg heads' to see all heads"))
4699 hint=_("run 'hg heads' to see all heads"))
4697
4700
4698 if not node and not repo._bookmarkcurrent:
4701 if not node and not repo._bookmarkcurrent:
4699 branch = repo[None].branch()
4702 branch = repo[None].branch()
4700 bheads = repo.branchheads(branch)
4703 bheads = repo.branchheads(branch)
4701 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4704 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4702
4705
4703 if len(nbhs) > 2:
4706 if len(nbhs) > 2:
4704 raise util.Abort(_("branch '%s' has %d heads - "
4707 raise util.Abort(_("branch '%s' has %d heads - "
4705 "please merge with an explicit rev")
4708 "please merge with an explicit rev")
4706 % (branch, len(bheads)),
4709 % (branch, len(bheads)),
4707 hint=_("run 'hg heads .' to see heads"))
4710 hint=_("run 'hg heads .' to see heads"))
4708
4711
4709 parent = repo.dirstate.p1()
4712 parent = repo.dirstate.p1()
4710 if len(nbhs) <= 1:
4713 if len(nbhs) <= 1:
4711 if len(bheads) > 1:
4714 if len(bheads) > 1:
4712 raise util.Abort(_("heads are bookmarked - "
4715 raise util.Abort(_("heads are bookmarked - "
4713 "please merge with an explicit rev"),
4716 "please merge with an explicit rev"),
4714 hint=_("run 'hg heads' to see all heads"))
4717 hint=_("run 'hg heads' to see all heads"))
4715 if len(repo.heads()) > 1:
4718 if len(repo.heads()) > 1:
4716 raise util.Abort(_("branch '%s' has one head - "
4719 raise util.Abort(_("branch '%s' has one head - "
4717 "please merge with an explicit rev")
4720 "please merge with an explicit rev")
4718 % branch,
4721 % branch,
4719 hint=_("run 'hg heads' to see all heads"))
4722 hint=_("run 'hg heads' to see all heads"))
4720 msg, hint = _('nothing to merge'), None
4723 msg, hint = _('nothing to merge'), None
4721 if parent != repo.lookup(branch):
4724 if parent != repo.lookup(branch):
4722 hint = _("use 'hg update' instead")
4725 hint = _("use 'hg update' instead")
4723 raise util.Abort(msg, hint=hint)
4726 raise util.Abort(msg, hint=hint)
4724
4727
4725 if parent not in bheads:
4728 if parent not in bheads:
4726 raise util.Abort(_('working directory not at a head revision'),
4729 raise util.Abort(_('working directory not at a head revision'),
4727 hint=_("use 'hg update' or merge with an "
4730 hint=_("use 'hg update' or merge with an "
4728 "explicit revision"))
4731 "explicit revision"))
4729 if parent == nbhs[0]:
4732 if parent == nbhs[0]:
4730 node = nbhs[-1]
4733 node = nbhs[-1]
4731 else:
4734 else:
4732 node = nbhs[0]
4735 node = nbhs[0]
4733
4736
4734 if opts.get('preview'):
4737 if opts.get('preview'):
4735 # find nodes that are ancestors of p2 but not of p1
4738 # find nodes that are ancestors of p2 but not of p1
4736 p1 = repo.lookup('.')
4739 p1 = repo.lookup('.')
4737 p2 = repo.lookup(node)
4740 p2 = repo.lookup(node)
4738 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4741 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4739
4742
4740 displayer = cmdutil.show_changeset(ui, repo, opts)
4743 displayer = cmdutil.show_changeset(ui, repo, opts)
4741 for node in nodes:
4744 for node in nodes:
4742 displayer.show(repo[node])
4745 displayer.show(repo[node])
4743 displayer.close()
4746 displayer.close()
4744 return 0
4747 return 0
4745
4748
4746 try:
4749 try:
4747 # ui.forcemerge is an internal variable, do not document
4750 # ui.forcemerge is an internal variable, do not document
4748 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4751 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4749 return hg.merge(repo, node, force=opts.get('force'))
4752 return hg.merge(repo, node, force=opts.get('force'))
4750 finally:
4753 finally:
4751 ui.setconfig('ui', 'forcemerge', '', 'merge')
4754 ui.setconfig('ui', 'forcemerge', '', 'merge')
4752
4755
4753 @command('outgoing|out',
4756 @command('outgoing|out',
4754 [('f', 'force', None, _('run even when the destination is unrelated')),
4757 [('f', 'force', None, _('run even when the destination is unrelated')),
4755 ('r', 'rev', [],
4758 ('r', 'rev', [],
4756 _('a changeset intended to be included in the destination'), _('REV')),
4759 _('a changeset intended to be included in the destination'), _('REV')),
4757 ('n', 'newest-first', None, _('show newest record first')),
4760 ('n', 'newest-first', None, _('show newest record first')),
4758 ('B', 'bookmarks', False, _('compare bookmarks')),
4761 ('B', 'bookmarks', False, _('compare bookmarks')),
4759 ('b', 'branch', [], _('a specific branch you would like to push'),
4762 ('b', 'branch', [], _('a specific branch you would like to push'),
4760 _('BRANCH')),
4763 _('BRANCH')),
4761 ] + logopts + remoteopts + subrepoopts,
4764 ] + logopts + remoteopts + subrepoopts,
4762 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4765 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4763 def outgoing(ui, repo, dest=None, **opts):
4766 def outgoing(ui, repo, dest=None, **opts):
4764 """show changesets not found in the destination
4767 """show changesets not found in the destination
4765
4768
4766 Show changesets not found in the specified destination repository
4769 Show changesets not found in the specified destination repository
4767 or the default push location. These are the changesets that would
4770 or the default push location. These are the changesets that would
4768 be pushed if a push was requested.
4771 be pushed if a push was requested.
4769
4772
4770 See pull for details of valid destination formats.
4773 See pull for details of valid destination formats.
4771
4774
4772 Returns 0 if there are outgoing changes, 1 otherwise.
4775 Returns 0 if there are outgoing changes, 1 otherwise.
4773 """
4776 """
4774 if opts.get('graph'):
4777 if opts.get('graph'):
4775 cmdutil.checkunsupportedgraphflags([], opts)
4778 cmdutil.checkunsupportedgraphflags([], opts)
4776 o, other = hg._outgoing(ui, repo, dest, opts)
4779 o, other = hg._outgoing(ui, repo, dest, opts)
4777 if not o:
4780 if not o:
4778 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4781 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4779 return
4782 return
4780
4783
4781 revdag = cmdutil.graphrevs(repo, o, opts)
4784 revdag = cmdutil.graphrevs(repo, o, opts)
4782 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4785 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4783 showparents = [ctx.node() for ctx in repo[None].parents()]
4786 showparents = [ctx.node() for ctx in repo[None].parents()]
4784 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4787 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4785 graphmod.asciiedges)
4788 graphmod.asciiedges)
4786 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4789 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4787 return 0
4790 return 0
4788
4791
4789 if opts.get('bookmarks'):
4792 if opts.get('bookmarks'):
4790 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4793 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4791 dest, branches = hg.parseurl(dest, opts.get('branch'))
4794 dest, branches = hg.parseurl(dest, opts.get('branch'))
4792 other = hg.peer(repo, opts, dest)
4795 other = hg.peer(repo, opts, dest)
4793 if 'bookmarks' not in other.listkeys('namespaces'):
4796 if 'bookmarks' not in other.listkeys('namespaces'):
4794 ui.warn(_("remote doesn't support bookmarks\n"))
4797 ui.warn(_("remote doesn't support bookmarks\n"))
4795 return 0
4798 return 0
4796 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4799 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4797 return bookmarks.outgoing(ui, repo, other)
4800 return bookmarks.outgoing(ui, repo, other)
4798
4801
4799 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4802 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4800 try:
4803 try:
4801 return hg.outgoing(ui, repo, dest, opts)
4804 return hg.outgoing(ui, repo, dest, opts)
4802 finally:
4805 finally:
4803 del repo._subtoppath
4806 del repo._subtoppath
4804
4807
4805 @command('parents',
4808 @command('parents',
4806 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4809 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4807 ] + templateopts,
4810 ] + templateopts,
4808 _('[-r REV] [FILE]'),
4811 _('[-r REV] [FILE]'),
4809 inferrepo=True)
4812 inferrepo=True)
4810 def parents(ui, repo, file_=None, **opts):
4813 def parents(ui, repo, file_=None, **opts):
4811 """show the parents of the working directory or revision (DEPRECATED)
4814 """show the parents of the working directory or revision (DEPRECATED)
4812
4815
4813 Print the working directory's parent revisions. If a revision is
4816 Print the working directory's parent revisions. If a revision is
4814 given via -r/--rev, the parent of that revision will be printed.
4817 given via -r/--rev, the parent of that revision will be printed.
4815 If a file argument is given, the revision in which the file was
4818 If a file argument is given, the revision in which the file was
4816 last changed (before the working directory revision or the
4819 last changed (before the working directory revision or the
4817 argument to --rev if given) is printed.
4820 argument to --rev if given) is printed.
4818
4821
4819 See :hg:`summary` and :hg:`help revsets` for related information.
4822 See :hg:`summary` and :hg:`help revsets` for related information.
4820
4823
4821 Returns 0 on success.
4824 Returns 0 on success.
4822 """
4825 """
4823
4826
4824 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4827 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4825
4828
4826 if file_:
4829 if file_:
4827 m = scmutil.match(ctx, (file_,), opts)
4830 m = scmutil.match(ctx, (file_,), opts)
4828 if m.anypats() or len(m.files()) != 1:
4831 if m.anypats() or len(m.files()) != 1:
4829 raise util.Abort(_('can only specify an explicit filename'))
4832 raise util.Abort(_('can only specify an explicit filename'))
4830 file_ = m.files()[0]
4833 file_ = m.files()[0]
4831 filenodes = []
4834 filenodes = []
4832 for cp in ctx.parents():
4835 for cp in ctx.parents():
4833 if not cp:
4836 if not cp:
4834 continue
4837 continue
4835 try:
4838 try:
4836 filenodes.append(cp.filenode(file_))
4839 filenodes.append(cp.filenode(file_))
4837 except error.LookupError:
4840 except error.LookupError:
4838 pass
4841 pass
4839 if not filenodes:
4842 if not filenodes:
4840 raise util.Abort(_("'%s' not found in manifest!") % file_)
4843 raise util.Abort(_("'%s' not found in manifest!") % file_)
4841 p = []
4844 p = []
4842 for fn in filenodes:
4845 for fn in filenodes:
4843 fctx = repo.filectx(file_, fileid=fn)
4846 fctx = repo.filectx(file_, fileid=fn)
4844 p.append(fctx.node())
4847 p.append(fctx.node())
4845 else:
4848 else:
4846 p = [cp.node() for cp in ctx.parents()]
4849 p = [cp.node() for cp in ctx.parents()]
4847
4850
4848 displayer = cmdutil.show_changeset(ui, repo, opts)
4851 displayer = cmdutil.show_changeset(ui, repo, opts)
4849 for n in p:
4852 for n in p:
4850 if n != nullid:
4853 if n != nullid:
4851 displayer.show(repo[n])
4854 displayer.show(repo[n])
4852 displayer.close()
4855 displayer.close()
4853
4856
4854 @command('paths', [], _('[NAME]'), optionalrepo=True)
4857 @command('paths', [], _('[NAME]'), optionalrepo=True)
4855 def paths(ui, repo, search=None):
4858 def paths(ui, repo, search=None):
4856 """show aliases for remote repositories
4859 """show aliases for remote repositories
4857
4860
4858 Show definition of symbolic path name NAME. If no name is given,
4861 Show definition of symbolic path name NAME. If no name is given,
4859 show definition of all available names.
4862 show definition of all available names.
4860
4863
4861 Option -q/--quiet suppresses all output when searching for NAME
4864 Option -q/--quiet suppresses all output when searching for NAME
4862 and shows only the path names when listing all definitions.
4865 and shows only the path names when listing all definitions.
4863
4866
4864 Path names are defined in the [paths] section of your
4867 Path names are defined in the [paths] section of your
4865 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4868 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4866 repository, ``.hg/hgrc`` is used, too.
4869 repository, ``.hg/hgrc`` is used, too.
4867
4870
4868 The path names ``default`` and ``default-push`` have a special
4871 The path names ``default`` and ``default-push`` have a special
4869 meaning. When performing a push or pull operation, they are used
4872 meaning. When performing a push or pull operation, they are used
4870 as fallbacks if no location is specified on the command-line.
4873 as fallbacks if no location is specified on the command-line.
4871 When ``default-push`` is set, it will be used for push and
4874 When ``default-push`` is set, it will be used for push and
4872 ``default`` will be used for pull; otherwise ``default`` is used
4875 ``default`` will be used for pull; otherwise ``default`` is used
4873 as the fallback for both. When cloning a repository, the clone
4876 as the fallback for both. When cloning a repository, the clone
4874 source is written as ``default`` in ``.hg/hgrc``. Note that
4877 source is written as ``default`` in ``.hg/hgrc``. Note that
4875 ``default`` and ``default-push`` apply to all inbound (e.g.
4878 ``default`` and ``default-push`` apply to all inbound (e.g.
4876 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4879 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4877 :hg:`bundle`) operations.
4880 :hg:`bundle`) operations.
4878
4881
4879 See :hg:`help urls` for more information.
4882 See :hg:`help urls` for more information.
4880
4883
4881 Returns 0 on success.
4884 Returns 0 on success.
4882 """
4885 """
4883 if search:
4886 if search:
4884 for name, path in sorted(ui.paths.iteritems()):
4887 for name, path in sorted(ui.paths.iteritems()):
4885 if name == search:
4888 if name == search:
4886 ui.status("%s\n" % util.hidepassword(path.loc))
4889 ui.status("%s\n" % util.hidepassword(path.loc))
4887 return
4890 return
4888 if not ui.quiet:
4891 if not ui.quiet:
4889 ui.warn(_("not found!\n"))
4892 ui.warn(_("not found!\n"))
4890 return 1
4893 return 1
4891 else:
4894 else:
4892 for name, path in sorted(ui.paths.iteritems()):
4895 for name, path in sorted(ui.paths.iteritems()):
4893 if ui.quiet:
4896 if ui.quiet:
4894 ui.write("%s\n" % name)
4897 ui.write("%s\n" % name)
4895 else:
4898 else:
4896 ui.write("%s = %s\n" % (name,
4899 ui.write("%s = %s\n" % (name,
4897 util.hidepassword(path.loc)))
4900 util.hidepassword(path.loc)))
4898
4901
4899 @command('phase',
4902 @command('phase',
4900 [('p', 'public', False, _('set changeset phase to public')),
4903 [('p', 'public', False, _('set changeset phase to public')),
4901 ('d', 'draft', False, _('set changeset phase to draft')),
4904 ('d', 'draft', False, _('set changeset phase to draft')),
4902 ('s', 'secret', False, _('set changeset phase to secret')),
4905 ('s', 'secret', False, _('set changeset phase to secret')),
4903 ('f', 'force', False, _('allow to move boundary backward')),
4906 ('f', 'force', False, _('allow to move boundary backward')),
4904 ('r', 'rev', [], _('target revision'), _('REV')),
4907 ('r', 'rev', [], _('target revision'), _('REV')),
4905 ],
4908 ],
4906 _('[-p|-d|-s] [-f] [-r] REV...'))
4909 _('[-p|-d|-s] [-f] [-r] REV...'))
4907 def phase(ui, repo, *revs, **opts):
4910 def phase(ui, repo, *revs, **opts):
4908 """set or show the current phase name
4911 """set or show the current phase name
4909
4912
4910 With no argument, show the phase name of specified revisions.
4913 With no argument, show the phase name of specified revisions.
4911
4914
4912 With one of -p/--public, -d/--draft or -s/--secret, change the
4915 With one of -p/--public, -d/--draft or -s/--secret, change the
4913 phase value of the specified revisions.
4916 phase value of the specified revisions.
4914
4917
4915 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4918 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4916 lower phase to an higher phase. Phases are ordered as follows::
4919 lower phase to an higher phase. Phases are ordered as follows::
4917
4920
4918 public < draft < secret
4921 public < draft < secret
4919
4922
4920 Returns 0 on success, 1 if no phases were changed or some could not
4923 Returns 0 on success, 1 if no phases were changed or some could not
4921 be changed.
4924 be changed.
4922 """
4925 """
4923 # search for a unique phase argument
4926 # search for a unique phase argument
4924 targetphase = None
4927 targetphase = None
4925 for idx, name in enumerate(phases.phasenames):
4928 for idx, name in enumerate(phases.phasenames):
4926 if opts[name]:
4929 if opts[name]:
4927 if targetphase is not None:
4930 if targetphase is not None:
4928 raise util.Abort(_('only one phase can be specified'))
4931 raise util.Abort(_('only one phase can be specified'))
4929 targetphase = idx
4932 targetphase = idx
4930
4933
4931 # look for specified revision
4934 # look for specified revision
4932 revs = list(revs)
4935 revs = list(revs)
4933 revs.extend(opts['rev'])
4936 revs.extend(opts['rev'])
4934 if not revs:
4937 if not revs:
4935 raise util.Abort(_('no revisions specified'))
4938 raise util.Abort(_('no revisions specified'))
4936
4939
4937 revs = scmutil.revrange(repo, revs)
4940 revs = scmutil.revrange(repo, revs)
4938
4941
4939 lock = None
4942 lock = None
4940 ret = 0
4943 ret = 0
4941 if targetphase is None:
4944 if targetphase is None:
4942 # display
4945 # display
4943 for r in revs:
4946 for r in revs:
4944 ctx = repo[r]
4947 ctx = repo[r]
4945 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4948 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4946 else:
4949 else:
4947 tr = None
4950 tr = None
4948 lock = repo.lock()
4951 lock = repo.lock()
4949 try:
4952 try:
4950 tr = repo.transaction("phase")
4953 tr = repo.transaction("phase")
4951 # set phase
4954 # set phase
4952 if not revs:
4955 if not revs:
4953 raise util.Abort(_('empty revision set'))
4956 raise util.Abort(_('empty revision set'))
4954 nodes = [repo[r].node() for r in revs]
4957 nodes = [repo[r].node() for r in revs]
4955 # moving revision from public to draft may hide them
4958 # moving revision from public to draft may hide them
4956 # We have to check result on an unfiltered repository
4959 # We have to check result on an unfiltered repository
4957 unfi = repo.unfiltered()
4960 unfi = repo.unfiltered()
4958 getphase = unfi._phasecache.phase
4961 getphase = unfi._phasecache.phase
4959 olddata = [getphase(unfi, r) for r in unfi]
4962 olddata = [getphase(unfi, r) for r in unfi]
4960 phases.advanceboundary(repo, tr, targetphase, nodes)
4963 phases.advanceboundary(repo, tr, targetphase, nodes)
4961 if opts['force']:
4964 if opts['force']:
4962 phases.retractboundary(repo, tr, targetphase, nodes)
4965 phases.retractboundary(repo, tr, targetphase, nodes)
4963 tr.close()
4966 tr.close()
4964 finally:
4967 finally:
4965 if tr is not None:
4968 if tr is not None:
4966 tr.release()
4969 tr.release()
4967 lock.release()
4970 lock.release()
4968 getphase = unfi._phasecache.phase
4971 getphase = unfi._phasecache.phase
4969 newdata = [getphase(unfi, r) for r in unfi]
4972 newdata = [getphase(unfi, r) for r in unfi]
4970 changes = sum(newdata[r] != olddata[r] for r in unfi)
4973 changes = sum(newdata[r] != olddata[r] for r in unfi)
4971 cl = unfi.changelog
4974 cl = unfi.changelog
4972 rejected = [n for n in nodes
4975 rejected = [n for n in nodes
4973 if newdata[cl.rev(n)] < targetphase]
4976 if newdata[cl.rev(n)] < targetphase]
4974 if rejected:
4977 if rejected:
4975 ui.warn(_('cannot move %i changesets to a higher '
4978 ui.warn(_('cannot move %i changesets to a higher '
4976 'phase, use --force\n') % len(rejected))
4979 'phase, use --force\n') % len(rejected))
4977 ret = 1
4980 ret = 1
4978 if changes:
4981 if changes:
4979 msg = _('phase changed for %i changesets\n') % changes
4982 msg = _('phase changed for %i changesets\n') % changes
4980 if ret:
4983 if ret:
4981 ui.status(msg)
4984 ui.status(msg)
4982 else:
4985 else:
4983 ui.note(msg)
4986 ui.note(msg)
4984 else:
4987 else:
4985 ui.warn(_('no phases changed\n'))
4988 ui.warn(_('no phases changed\n'))
4986 ret = 1
4989 ret = 1
4987 return ret
4990 return ret
4988
4991
4989 def postincoming(ui, repo, modheads, optupdate, checkout):
4992 def postincoming(ui, repo, modheads, optupdate, checkout):
4990 if modheads == 0:
4993 if modheads == 0:
4991 return
4994 return
4992 if optupdate:
4995 if optupdate:
4993 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4996 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4994 try:
4997 try:
4995 ret = hg.update(repo, checkout)
4998 ret = hg.update(repo, checkout)
4996 except util.Abort, inst:
4999 except util.Abort, inst:
4997 ui.warn(_("not updating: %s\n") % str(inst))
5000 ui.warn(_("not updating: %s\n") % str(inst))
4998 if inst.hint:
5001 if inst.hint:
4999 ui.warn(_("(%s)\n") % inst.hint)
5002 ui.warn(_("(%s)\n") % inst.hint)
5000 return 0
5003 return 0
5001 if not ret and not checkout:
5004 if not ret and not checkout:
5002 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5005 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5003 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5006 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
5004 return ret
5007 return ret
5005 if modheads > 1:
5008 if modheads > 1:
5006 currentbranchheads = len(repo.branchheads())
5009 currentbranchheads = len(repo.branchheads())
5007 if currentbranchheads == modheads:
5010 if currentbranchheads == modheads:
5008 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5011 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5009 elif currentbranchheads > 1:
5012 elif currentbranchheads > 1:
5010 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5013 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5011 "merge)\n"))
5014 "merge)\n"))
5012 else:
5015 else:
5013 ui.status(_("(run 'hg heads' to see heads)\n"))
5016 ui.status(_("(run 'hg heads' to see heads)\n"))
5014 else:
5017 else:
5015 ui.status(_("(run 'hg update' to get a working copy)\n"))
5018 ui.status(_("(run 'hg update' to get a working copy)\n"))
5016
5019
5017 @command('^pull',
5020 @command('^pull',
5018 [('u', 'update', None,
5021 [('u', 'update', None,
5019 _('update to new branch head if changesets were pulled')),
5022 _('update to new branch head if changesets were pulled')),
5020 ('f', 'force', None, _('run even when remote repository is unrelated')),
5023 ('f', 'force', None, _('run even when remote repository is unrelated')),
5021 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5024 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5022 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5025 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5023 ('b', 'branch', [], _('a specific branch you would like to pull'),
5026 ('b', 'branch', [], _('a specific branch you would like to pull'),
5024 _('BRANCH')),
5027 _('BRANCH')),
5025 ] + remoteopts,
5028 ] + remoteopts,
5026 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5029 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5027 def pull(ui, repo, source="default", **opts):
5030 def pull(ui, repo, source="default", **opts):
5028 """pull changes from the specified source
5031 """pull changes from the specified source
5029
5032
5030 Pull changes from a remote repository to a local one.
5033 Pull changes from a remote repository to a local one.
5031
5034
5032 This finds all changes from the repository at the specified path
5035 This finds all changes from the repository at the specified path
5033 or URL and adds them to a local repository (the current one unless
5036 or URL and adds them to a local repository (the current one unless
5034 -R is specified). By default, this does not update the copy of the
5037 -R is specified). By default, this does not update the copy of the
5035 project in the working directory.
5038 project in the working directory.
5036
5039
5037 Use :hg:`incoming` if you want to see what would have been added
5040 Use :hg:`incoming` if you want to see what would have been added
5038 by a pull at the time you issued this command. If you then decide
5041 by a pull at the time you issued this command. If you then decide
5039 to add those changes to the repository, you should use :hg:`pull
5042 to add those changes to the repository, you should use :hg:`pull
5040 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5043 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5041
5044
5042 If SOURCE is omitted, the 'default' path will be used.
5045 If SOURCE is omitted, the 'default' path will be used.
5043 See :hg:`help urls` for more information.
5046 See :hg:`help urls` for more information.
5044
5047
5045 Returns 0 on success, 1 if an update had unresolved files.
5048 Returns 0 on success, 1 if an update had unresolved files.
5046 """
5049 """
5047 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5050 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5048 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5051 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5049 other = hg.peer(repo, opts, source)
5052 other = hg.peer(repo, opts, source)
5050 try:
5053 try:
5051 revs, checkout = hg.addbranchrevs(repo, other, branches,
5054 revs, checkout = hg.addbranchrevs(repo, other, branches,
5052 opts.get('rev'))
5055 opts.get('rev'))
5053
5056
5054 remotebookmarks = other.listkeys('bookmarks')
5057 remotebookmarks = other.listkeys('bookmarks')
5055
5058
5056 if opts.get('bookmark'):
5059 if opts.get('bookmark'):
5057 if not revs:
5060 if not revs:
5058 revs = []
5061 revs = []
5059 for b in opts['bookmark']:
5062 for b in opts['bookmark']:
5060 if b not in remotebookmarks:
5063 if b not in remotebookmarks:
5061 raise util.Abort(_('remote bookmark %s not found!') % b)
5064 raise util.Abort(_('remote bookmark %s not found!') % b)
5062 revs.append(remotebookmarks[b])
5065 revs.append(remotebookmarks[b])
5063
5066
5064 if revs:
5067 if revs:
5065 try:
5068 try:
5066 revs = [other.lookup(rev) for rev in revs]
5069 revs = [other.lookup(rev) for rev in revs]
5067 except error.CapabilityError:
5070 except error.CapabilityError:
5068 err = _("other repository doesn't support revision lookup, "
5071 err = _("other repository doesn't support revision lookup, "
5069 "so a rev cannot be specified.")
5072 "so a rev cannot be specified.")
5070 raise util.Abort(err)
5073 raise util.Abort(err)
5071
5074
5072 modheads = exchange.pull(repo, other, heads=revs,
5075 modheads = exchange.pull(repo, other, heads=revs,
5073 force=opts.get('force'),
5076 force=opts.get('force'),
5074 bookmarks=opts.get('bookmark', ())).cgresult
5077 bookmarks=opts.get('bookmark', ())).cgresult
5075 if checkout:
5078 if checkout:
5076 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5079 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5077 repo._subtoppath = source
5080 repo._subtoppath = source
5078 try:
5081 try:
5079 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5082 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5080
5083
5081 finally:
5084 finally:
5082 del repo._subtoppath
5085 del repo._subtoppath
5083
5086
5084 finally:
5087 finally:
5085 other.close()
5088 other.close()
5086 return ret
5089 return ret
5087
5090
5088 @command('^push',
5091 @command('^push',
5089 [('f', 'force', None, _('force push')),
5092 [('f', 'force', None, _('force push')),
5090 ('r', 'rev', [],
5093 ('r', 'rev', [],
5091 _('a changeset intended to be included in the destination'),
5094 _('a changeset intended to be included in the destination'),
5092 _('REV')),
5095 _('REV')),
5093 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5096 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5094 ('b', 'branch', [],
5097 ('b', 'branch', [],
5095 _('a specific branch you would like to push'), _('BRANCH')),
5098 _('a specific branch you would like to push'), _('BRANCH')),
5096 ('', 'new-branch', False, _('allow pushing a new branch')),
5099 ('', 'new-branch', False, _('allow pushing a new branch')),
5097 ] + remoteopts,
5100 ] + remoteopts,
5098 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5101 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5099 def push(ui, repo, dest=None, **opts):
5102 def push(ui, repo, dest=None, **opts):
5100 """push changes to the specified destination
5103 """push changes to the specified destination
5101
5104
5102 Push changesets from the local repository to the specified
5105 Push changesets from the local repository to the specified
5103 destination.
5106 destination.
5104
5107
5105 This operation is symmetrical to pull: it is identical to a pull
5108 This operation is symmetrical to pull: it is identical to a pull
5106 in the destination repository from the current one.
5109 in the destination repository from the current one.
5107
5110
5108 By default, push will not allow creation of new heads at the
5111 By default, push will not allow creation of new heads at the
5109 destination, since multiple heads would make it unclear which head
5112 destination, since multiple heads would make it unclear which head
5110 to use. In this situation, it is recommended to pull and merge
5113 to use. In this situation, it is recommended to pull and merge
5111 before pushing.
5114 before pushing.
5112
5115
5113 Use --new-branch if you want to allow push to create a new named
5116 Use --new-branch if you want to allow push to create a new named
5114 branch that is not present at the destination. This allows you to
5117 branch that is not present at the destination. This allows you to
5115 only create a new branch without forcing other changes.
5118 only create a new branch without forcing other changes.
5116
5119
5117 .. note::
5120 .. note::
5118
5121
5119 Extra care should be taken with the -f/--force option,
5122 Extra care should be taken with the -f/--force option,
5120 which will push all new heads on all branches, an action which will
5123 which will push all new heads on all branches, an action which will
5121 almost always cause confusion for collaborators.
5124 almost always cause confusion for collaborators.
5122
5125
5123 If -r/--rev is used, the specified revision and all its ancestors
5126 If -r/--rev is used, the specified revision and all its ancestors
5124 will be pushed to the remote repository.
5127 will be pushed to the remote repository.
5125
5128
5126 If -B/--bookmark is used, the specified bookmarked revision, its
5129 If -B/--bookmark is used, the specified bookmarked revision, its
5127 ancestors, and the bookmark will be pushed to the remote
5130 ancestors, and the bookmark will be pushed to the remote
5128 repository.
5131 repository.
5129
5132
5130 Please see :hg:`help urls` for important details about ``ssh://``
5133 Please see :hg:`help urls` for important details about ``ssh://``
5131 URLs. If DESTINATION is omitted, a default path will be used.
5134 URLs. If DESTINATION is omitted, a default path will be used.
5132
5135
5133 Returns 0 if push was successful, 1 if nothing to push.
5136 Returns 0 if push was successful, 1 if nothing to push.
5134 """
5137 """
5135
5138
5136 if opts.get('bookmark'):
5139 if opts.get('bookmark'):
5137 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5140 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5138 for b in opts['bookmark']:
5141 for b in opts['bookmark']:
5139 # translate -B options to -r so changesets get pushed
5142 # translate -B options to -r so changesets get pushed
5140 if b in repo._bookmarks:
5143 if b in repo._bookmarks:
5141 opts.setdefault('rev', []).append(b)
5144 opts.setdefault('rev', []).append(b)
5142 else:
5145 else:
5143 # if we try to push a deleted bookmark, translate it to null
5146 # if we try to push a deleted bookmark, translate it to null
5144 # this lets simultaneous -r, -b options continue working
5147 # this lets simultaneous -r, -b options continue working
5145 opts.setdefault('rev', []).append("null")
5148 opts.setdefault('rev', []).append("null")
5146
5149
5147 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5150 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5148 dest, branches = hg.parseurl(dest, opts.get('branch'))
5151 dest, branches = hg.parseurl(dest, opts.get('branch'))
5149 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5152 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5150 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5153 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5151 try:
5154 try:
5152 other = hg.peer(repo, opts, dest)
5155 other = hg.peer(repo, opts, dest)
5153 except error.RepoError:
5156 except error.RepoError:
5154 if dest == "default-push":
5157 if dest == "default-push":
5155 raise util.Abort(_("default repository not configured!"),
5158 raise util.Abort(_("default repository not configured!"),
5156 hint=_('see the "path" section in "hg help config"'))
5159 hint=_('see the "path" section in "hg help config"'))
5157 else:
5160 else:
5158 raise
5161 raise
5159
5162
5160 if revs:
5163 if revs:
5161 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5164 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5162 if not revs:
5165 if not revs:
5163 raise util.Abort(_("specified revisions evaluate to an empty set"),
5166 raise util.Abort(_("specified revisions evaluate to an empty set"),
5164 hint=_("use different revision arguments"))
5167 hint=_("use different revision arguments"))
5165
5168
5166 repo._subtoppath = dest
5169 repo._subtoppath = dest
5167 try:
5170 try:
5168 # push subrepos depth-first for coherent ordering
5171 # push subrepos depth-first for coherent ordering
5169 c = repo['']
5172 c = repo['']
5170 subs = c.substate # only repos that are committed
5173 subs = c.substate # only repos that are committed
5171 for s in sorted(subs):
5174 for s in sorted(subs):
5172 result = c.sub(s).push(opts)
5175 result = c.sub(s).push(opts)
5173 if result == 0:
5176 if result == 0:
5174 return not result
5177 return not result
5175 finally:
5178 finally:
5176 del repo._subtoppath
5179 del repo._subtoppath
5177 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5180 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5178 newbranch=opts.get('new_branch'),
5181 newbranch=opts.get('new_branch'),
5179 bookmarks=opts.get('bookmark', ()))
5182 bookmarks=opts.get('bookmark', ()))
5180
5183
5181 result = not pushop.cgresult
5184 result = not pushop.cgresult
5182
5185
5183 if pushop.bkresult is not None:
5186 if pushop.bkresult is not None:
5184 if pushop.bkresult == 2:
5187 if pushop.bkresult == 2:
5185 result = 2
5188 result = 2
5186 elif not result and pushop.bkresult:
5189 elif not result and pushop.bkresult:
5187 result = 2
5190 result = 2
5188
5191
5189 return result
5192 return result
5190
5193
5191 @command('recover', [])
5194 @command('recover', [])
5192 def recover(ui, repo):
5195 def recover(ui, repo):
5193 """roll back an interrupted transaction
5196 """roll back an interrupted transaction
5194
5197
5195 Recover from an interrupted commit or pull.
5198 Recover from an interrupted commit or pull.
5196
5199
5197 This command tries to fix the repository status after an
5200 This command tries to fix the repository status after an
5198 interrupted operation. It should only be necessary when Mercurial
5201 interrupted operation. It should only be necessary when Mercurial
5199 suggests it.
5202 suggests it.
5200
5203
5201 Returns 0 if successful, 1 if nothing to recover or verify fails.
5204 Returns 0 if successful, 1 if nothing to recover or verify fails.
5202 """
5205 """
5203 if repo.recover():
5206 if repo.recover():
5204 return hg.verify(repo)
5207 return hg.verify(repo)
5205 return 1
5208 return 1
5206
5209
5207 @command('^remove|rm',
5210 @command('^remove|rm',
5208 [('A', 'after', None, _('record delete for missing files')),
5211 [('A', 'after', None, _('record delete for missing files')),
5209 ('f', 'force', None,
5212 ('f', 'force', None,
5210 _('remove (and delete) file even if added or modified')),
5213 _('remove (and delete) file even if added or modified')),
5211 ] + subrepoopts + walkopts,
5214 ] + subrepoopts + walkopts,
5212 _('[OPTION]... FILE...'),
5215 _('[OPTION]... FILE...'),
5213 inferrepo=True)
5216 inferrepo=True)
5214 def remove(ui, repo, *pats, **opts):
5217 def remove(ui, repo, *pats, **opts):
5215 """remove the specified files on the next commit
5218 """remove the specified files on the next commit
5216
5219
5217 Schedule the indicated files for removal from the current branch.
5220 Schedule the indicated files for removal from the current branch.
5218
5221
5219 This command schedules the files to be removed at the next commit.
5222 This command schedules the files to be removed at the next commit.
5220 To undo a remove before that, see :hg:`revert`. To undo added
5223 To undo a remove before that, see :hg:`revert`. To undo added
5221 files, see :hg:`forget`.
5224 files, see :hg:`forget`.
5222
5225
5223 .. container:: verbose
5226 .. container:: verbose
5224
5227
5225 -A/--after can be used to remove only files that have already
5228 -A/--after can be used to remove only files that have already
5226 been deleted, -f/--force can be used to force deletion, and -Af
5229 been deleted, -f/--force can be used to force deletion, and -Af
5227 can be used to remove files from the next revision without
5230 can be used to remove files from the next revision without
5228 deleting them from the working directory.
5231 deleting them from the working directory.
5229
5232
5230 The following table details the behavior of remove for different
5233 The following table details the behavior of remove for different
5231 file states (columns) and option combinations (rows). The file
5234 file states (columns) and option combinations (rows). The file
5232 states are Added [A], Clean [C], Modified [M] and Missing [!]
5235 states are Added [A], Clean [C], Modified [M] and Missing [!]
5233 (as reported by :hg:`status`). The actions are Warn, Remove
5236 (as reported by :hg:`status`). The actions are Warn, Remove
5234 (from branch) and Delete (from disk):
5237 (from branch) and Delete (from disk):
5235
5238
5236 ========= == == == ==
5239 ========= == == == ==
5237 opt/state A C M !
5240 opt/state A C M !
5238 ========= == == == ==
5241 ========= == == == ==
5239 none W RD W R
5242 none W RD W R
5240 -f R RD RD R
5243 -f R RD RD R
5241 -A W W W R
5244 -A W W W R
5242 -Af R R R R
5245 -Af R R R R
5243 ========= == == == ==
5246 ========= == == == ==
5244
5247
5245 Note that remove never deletes files in Added [A] state from the
5248 Note that remove never deletes files in Added [A] state from the
5246 working directory, not even if option --force is specified.
5249 working directory, not even if option --force is specified.
5247
5250
5248 Returns 0 on success, 1 if any warnings encountered.
5251 Returns 0 on success, 1 if any warnings encountered.
5249 """
5252 """
5250
5253
5251 after, force = opts.get('after'), opts.get('force')
5254 after, force = opts.get('after'), opts.get('force')
5252 if not pats and not after:
5255 if not pats and not after:
5253 raise util.Abort(_('no files specified'))
5256 raise util.Abort(_('no files specified'))
5254
5257
5255 m = scmutil.match(repo[None], pats, opts)
5258 m = scmutil.match(repo[None], pats, opts)
5256 subrepos = opts.get('subrepos')
5259 subrepos = opts.get('subrepos')
5257 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5260 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5258
5261
5259 @command('rename|move|mv',
5262 @command('rename|move|mv',
5260 [('A', 'after', None, _('record a rename that has already occurred')),
5263 [('A', 'after', None, _('record a rename that has already occurred')),
5261 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5264 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5262 ] + walkopts + dryrunopts,
5265 ] + walkopts + dryrunopts,
5263 _('[OPTION]... SOURCE... DEST'))
5266 _('[OPTION]... SOURCE... DEST'))
5264 def rename(ui, repo, *pats, **opts):
5267 def rename(ui, repo, *pats, **opts):
5265 """rename files; equivalent of copy + remove
5268 """rename files; equivalent of copy + remove
5266
5269
5267 Mark dest as copies of sources; mark sources for deletion. If dest
5270 Mark dest as copies of sources; mark sources for deletion. If dest
5268 is a directory, copies are put in that directory. If dest is a
5271 is a directory, copies are put in that directory. If dest is a
5269 file, there can only be one source.
5272 file, there can only be one source.
5270
5273
5271 By default, this command copies the contents of files as they
5274 By default, this command copies the contents of files as they
5272 exist in the working directory. If invoked with -A/--after, the
5275 exist in the working directory. If invoked with -A/--after, the
5273 operation is recorded, but no copying is performed.
5276 operation is recorded, but no copying is performed.
5274
5277
5275 This command takes effect at the next commit. To undo a rename
5278 This command takes effect at the next commit. To undo a rename
5276 before that, see :hg:`revert`.
5279 before that, see :hg:`revert`.
5277
5280
5278 Returns 0 on success, 1 if errors are encountered.
5281 Returns 0 on success, 1 if errors are encountered.
5279 """
5282 """
5280 wlock = repo.wlock(False)
5283 wlock = repo.wlock(False)
5281 try:
5284 try:
5282 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5285 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5283 finally:
5286 finally:
5284 wlock.release()
5287 wlock.release()
5285
5288
5286 @command('resolve',
5289 @command('resolve',
5287 [('a', 'all', None, _('select all unresolved files')),
5290 [('a', 'all', None, _('select all unresolved files')),
5288 ('l', 'list', None, _('list state of files needing merge')),
5291 ('l', 'list', None, _('list state of files needing merge')),
5289 ('m', 'mark', None, _('mark files as resolved')),
5292 ('m', 'mark', None, _('mark files as resolved')),
5290 ('u', 'unmark', None, _('mark files as unresolved')),
5293 ('u', 'unmark', None, _('mark files as unresolved')),
5291 ('n', 'no-status', None, _('hide status prefix'))]
5294 ('n', 'no-status', None, _('hide status prefix'))]
5292 + mergetoolopts + walkopts + formatteropts,
5295 + mergetoolopts + walkopts + formatteropts,
5293 _('[OPTION]... [FILE]...'),
5296 _('[OPTION]... [FILE]...'),
5294 inferrepo=True)
5297 inferrepo=True)
5295 def resolve(ui, repo, *pats, **opts):
5298 def resolve(ui, repo, *pats, **opts):
5296 """redo merges or set/view the merge status of files
5299 """redo merges or set/view the merge status of files
5297
5300
5298 Merges with unresolved conflicts are often the result of
5301 Merges with unresolved conflicts are often the result of
5299 non-interactive merging using the ``internal:merge`` configuration
5302 non-interactive merging using the ``internal:merge`` configuration
5300 setting, or a command-line merge tool like ``diff3``. The resolve
5303 setting, or a command-line merge tool like ``diff3``. The resolve
5301 command is used to manage the files involved in a merge, after
5304 command is used to manage the files involved in a merge, after
5302 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5305 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5303 working directory must have two parents). See :hg:`help
5306 working directory must have two parents). See :hg:`help
5304 merge-tools` for information on configuring merge tools.
5307 merge-tools` for information on configuring merge tools.
5305
5308
5306 The resolve command can be used in the following ways:
5309 The resolve command can be used in the following ways:
5307
5310
5308 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5311 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5309 files, discarding any previous merge attempts. Re-merging is not
5312 files, discarding any previous merge attempts. Re-merging is not
5310 performed for files already marked as resolved. Use ``--all/-a``
5313 performed for files already marked as resolved. Use ``--all/-a``
5311 to select all unresolved files. ``--tool`` can be used to specify
5314 to select all unresolved files. ``--tool`` can be used to specify
5312 the merge tool used for the given files. It overrides the HGMERGE
5315 the merge tool used for the given files. It overrides the HGMERGE
5313 environment variable and your configuration files. Previous file
5316 environment variable and your configuration files. Previous file
5314 contents are saved with a ``.orig`` suffix.
5317 contents are saved with a ``.orig`` suffix.
5315
5318
5316 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5319 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5317 (e.g. after having manually fixed-up the files). The default is
5320 (e.g. after having manually fixed-up the files). The default is
5318 to mark all unresolved files.
5321 to mark all unresolved files.
5319
5322
5320 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5323 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5321 default is to mark all resolved files.
5324 default is to mark all resolved files.
5322
5325
5323 - :hg:`resolve -l`: list files which had or still have conflicts.
5326 - :hg:`resolve -l`: list files which had or still have conflicts.
5324 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5327 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5325
5328
5326 Note that Mercurial will not let you commit files with unresolved
5329 Note that Mercurial will not let you commit files with unresolved
5327 merge conflicts. You must use :hg:`resolve -m ...` before you can
5330 merge conflicts. You must use :hg:`resolve -m ...` before you can
5328 commit after a conflicting merge.
5331 commit after a conflicting merge.
5329
5332
5330 Returns 0 on success, 1 if any files fail a resolve attempt.
5333 Returns 0 on success, 1 if any files fail a resolve attempt.
5331 """
5334 """
5332
5335
5333 all, mark, unmark, show, nostatus = \
5336 all, mark, unmark, show, nostatus = \
5334 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5337 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5335
5338
5336 if (show and (mark or unmark)) or (mark and unmark):
5339 if (show and (mark or unmark)) or (mark and unmark):
5337 raise util.Abort(_("too many options specified"))
5340 raise util.Abort(_("too many options specified"))
5338 if pats and all:
5341 if pats and all:
5339 raise util.Abort(_("can't specify --all and patterns"))
5342 raise util.Abort(_("can't specify --all and patterns"))
5340 if not (all or pats or show or mark or unmark):
5343 if not (all or pats or show or mark or unmark):
5341 raise util.Abort(_('no files or directories specified'),
5344 raise util.Abort(_('no files or directories specified'),
5342 hint=('use --all to remerge all files'))
5345 hint=('use --all to remerge all files'))
5343
5346
5344 if show:
5347 if show:
5345 fm = ui.formatter('resolve', opts)
5348 fm = ui.formatter('resolve', opts)
5346 ms = mergemod.mergestate(repo)
5349 ms = mergemod.mergestate(repo)
5347 m = scmutil.match(repo[None], pats, opts)
5350 m = scmutil.match(repo[None], pats, opts)
5348 for f in ms:
5351 for f in ms:
5349 if not m(f):
5352 if not m(f):
5350 continue
5353 continue
5351 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5354 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5352 fm.startitem()
5355 fm.startitem()
5353 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5356 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5354 fm.write('path', '%s\n', f, label=l)
5357 fm.write('path', '%s\n', f, label=l)
5355 fm.end()
5358 fm.end()
5356 return 0
5359 return 0
5357
5360
5358 wlock = repo.wlock()
5361 wlock = repo.wlock()
5359 try:
5362 try:
5360 ms = mergemod.mergestate(repo)
5363 ms = mergemod.mergestate(repo)
5361
5364
5362 if not (ms.active() or repo.dirstate.p2() != nullid):
5365 if not (ms.active() or repo.dirstate.p2() != nullid):
5363 raise util.Abort(
5366 raise util.Abort(
5364 _('resolve command not applicable when not merging'))
5367 _('resolve command not applicable when not merging'))
5365
5368
5366 m = scmutil.match(repo[None], pats, opts)
5369 m = scmutil.match(repo[None], pats, opts)
5367 ret = 0
5370 ret = 0
5368 didwork = False
5371 didwork = False
5369
5372
5370 for f in ms:
5373 for f in ms:
5371 if not m(f):
5374 if not m(f):
5372 continue
5375 continue
5373
5376
5374 didwork = True
5377 didwork = True
5375
5378
5376 if mark:
5379 if mark:
5377 ms.mark(f, "r")
5380 ms.mark(f, "r")
5378 elif unmark:
5381 elif unmark:
5379 ms.mark(f, "u")
5382 ms.mark(f, "u")
5380 else:
5383 else:
5381 wctx = repo[None]
5384 wctx = repo[None]
5382
5385
5383 # backup pre-resolve (merge uses .orig for its own purposes)
5386 # backup pre-resolve (merge uses .orig for its own purposes)
5384 a = repo.wjoin(f)
5387 a = repo.wjoin(f)
5385 util.copyfile(a, a + ".resolve")
5388 util.copyfile(a, a + ".resolve")
5386
5389
5387 try:
5390 try:
5388 # resolve file
5391 # resolve file
5389 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5392 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5390 'resolve')
5393 'resolve')
5391 if ms.resolve(f, wctx):
5394 if ms.resolve(f, wctx):
5392 ret = 1
5395 ret = 1
5393 finally:
5396 finally:
5394 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5397 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5395 ms.commit()
5398 ms.commit()
5396
5399
5397 # replace filemerge's .orig file with our resolve file
5400 # replace filemerge's .orig file with our resolve file
5398 util.rename(a + ".resolve", a + ".orig")
5401 util.rename(a + ".resolve", a + ".orig")
5399
5402
5400 ms.commit()
5403 ms.commit()
5401
5404
5402 if not didwork and pats:
5405 if not didwork and pats:
5403 ui.warn(_("arguments do not match paths that need resolving\n"))
5406 ui.warn(_("arguments do not match paths that need resolving\n"))
5404
5407
5405 finally:
5408 finally:
5406 wlock.release()
5409 wlock.release()
5407
5410
5408 # Nudge users into finishing an unfinished operation
5411 # Nudge users into finishing an unfinished operation
5409 if not list(ms.unresolved()):
5412 if not list(ms.unresolved()):
5410 ui.status(_('(no more unresolved files)\n'))
5413 ui.status(_('(no more unresolved files)\n'))
5411
5414
5412 return ret
5415 return ret
5413
5416
5414 @command('revert',
5417 @command('revert',
5415 [('a', 'all', None, _('revert all changes when no arguments given')),
5418 [('a', 'all', None, _('revert all changes when no arguments given')),
5416 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5419 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5417 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5420 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5418 ('C', 'no-backup', None, _('do not save backup copies of files')),
5421 ('C', 'no-backup', None, _('do not save backup copies of files')),
5419 ('i', 'interactive', None, _('interactively select the changes')),
5422 ('i', 'interactive', None, _('interactively select the changes')),
5420 ] + walkopts + dryrunopts,
5423 ] + walkopts + dryrunopts,
5421 _('[OPTION]... [-r REV] [NAME]...'))
5424 _('[OPTION]... [-r REV] [NAME]...'))
5422 def revert(ui, repo, *pats, **opts):
5425 def revert(ui, repo, *pats, **opts):
5423 """restore files to their checkout state
5426 """restore files to their checkout state
5424
5427
5425 .. note::
5428 .. note::
5426
5429
5427 To check out earlier revisions, you should use :hg:`update REV`.
5430 To check out earlier revisions, you should use :hg:`update REV`.
5428 To cancel an uncommitted merge (and lose your changes),
5431 To cancel an uncommitted merge (and lose your changes),
5429 use :hg:`update --clean .`.
5432 use :hg:`update --clean .`.
5430
5433
5431 With no revision specified, revert the specified files or directories
5434 With no revision specified, revert the specified files or directories
5432 to the contents they had in the parent of the working directory.
5435 to the contents they had in the parent of the working directory.
5433 This restores the contents of files to an unmodified
5436 This restores the contents of files to an unmodified
5434 state and unschedules adds, removes, copies, and renames. If the
5437 state and unschedules adds, removes, copies, and renames. If the
5435 working directory has two parents, you must explicitly specify a
5438 working directory has two parents, you must explicitly specify a
5436 revision.
5439 revision.
5437
5440
5438 Using the -r/--rev or -d/--date options, revert the given files or
5441 Using the -r/--rev or -d/--date options, revert the given files or
5439 directories to their states as of a specific revision. Because
5442 directories to their states as of a specific revision. Because
5440 revert does not change the working directory parents, this will
5443 revert does not change the working directory parents, this will
5441 cause these files to appear modified. This can be helpful to "back
5444 cause these files to appear modified. This can be helpful to "back
5442 out" some or all of an earlier change. See :hg:`backout` for a
5445 out" some or all of an earlier change. See :hg:`backout` for a
5443 related method.
5446 related method.
5444
5447
5445 Modified files are saved with a .orig suffix before reverting.
5448 Modified files are saved with a .orig suffix before reverting.
5446 To disable these backups, use --no-backup.
5449 To disable these backups, use --no-backup.
5447
5450
5448 See :hg:`help dates` for a list of formats valid for -d/--date.
5451 See :hg:`help dates` for a list of formats valid for -d/--date.
5449
5452
5450 Returns 0 on success.
5453 Returns 0 on success.
5451 """
5454 """
5452
5455
5453 if opts.get("date"):
5456 if opts.get("date"):
5454 if opts.get("rev"):
5457 if opts.get("rev"):
5455 raise util.Abort(_("you can't specify a revision and a date"))
5458 raise util.Abort(_("you can't specify a revision and a date"))
5456 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5459 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5457
5460
5458 parent, p2 = repo.dirstate.parents()
5461 parent, p2 = repo.dirstate.parents()
5459 if not opts.get('rev') and p2 != nullid:
5462 if not opts.get('rev') and p2 != nullid:
5460 # revert after merge is a trap for new users (issue2915)
5463 # revert after merge is a trap for new users (issue2915)
5461 raise util.Abort(_('uncommitted merge with no revision specified'),
5464 raise util.Abort(_('uncommitted merge with no revision specified'),
5462 hint=_('use "hg update" or see "hg help revert"'))
5465 hint=_('use "hg update" or see "hg help revert"'))
5463
5466
5464 ctx = scmutil.revsingle(repo, opts.get('rev'))
5467 ctx = scmutil.revsingle(repo, opts.get('rev'))
5465
5468
5466 if not pats and not opts.get('all'):
5469 if not pats and not opts.get('all'):
5467 msg = _("no files or directories specified")
5470 msg = _("no files or directories specified")
5468 if p2 != nullid:
5471 if p2 != nullid:
5469 hint = _("uncommitted merge, use --all to discard all changes,"
5472 hint = _("uncommitted merge, use --all to discard all changes,"
5470 " or 'hg update -C .' to abort the merge")
5473 " or 'hg update -C .' to abort the merge")
5471 raise util.Abort(msg, hint=hint)
5474 raise util.Abort(msg, hint=hint)
5472 dirty = util.any(repo.status())
5475 dirty = util.any(repo.status())
5473 node = ctx.node()
5476 node = ctx.node()
5474 if node != parent:
5477 if node != parent:
5475 if dirty:
5478 if dirty:
5476 hint = _("uncommitted changes, use --all to discard all"
5479 hint = _("uncommitted changes, use --all to discard all"
5477 " changes, or 'hg update %s' to update") % ctx.rev()
5480 " changes, or 'hg update %s' to update") % ctx.rev()
5478 else:
5481 else:
5479 hint = _("use --all to revert all files,"
5482 hint = _("use --all to revert all files,"
5480 " or 'hg update %s' to update") % ctx.rev()
5483 " or 'hg update %s' to update") % ctx.rev()
5481 elif dirty:
5484 elif dirty:
5482 hint = _("uncommitted changes, use --all to discard all changes")
5485 hint = _("uncommitted changes, use --all to discard all changes")
5483 else:
5486 else:
5484 hint = _("use --all to revert all files")
5487 hint = _("use --all to revert all files")
5485 raise util.Abort(msg, hint=hint)
5488 raise util.Abort(msg, hint=hint)
5486
5489
5487 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5490 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5488
5491
5489 @command('rollback', dryrunopts +
5492 @command('rollback', dryrunopts +
5490 [('f', 'force', False, _('ignore safety measures'))])
5493 [('f', 'force', False, _('ignore safety measures'))])
5491 def rollback(ui, repo, **opts):
5494 def rollback(ui, repo, **opts):
5492 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5495 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5493
5496
5494 Please use :hg:`commit --amend` instead of rollback to correct
5497 Please use :hg:`commit --amend` instead of rollback to correct
5495 mistakes in the last commit.
5498 mistakes in the last commit.
5496
5499
5497 This command should be used with care. There is only one level of
5500 This command should be used with care. There is only one level of
5498 rollback, and there is no way to undo a rollback. It will also
5501 rollback, and there is no way to undo a rollback. It will also
5499 restore the dirstate at the time of the last transaction, losing
5502 restore the dirstate at the time of the last transaction, losing
5500 any dirstate changes since that time. This command does not alter
5503 any dirstate changes since that time. This command does not alter
5501 the working directory.
5504 the working directory.
5502
5505
5503 Transactions are used to encapsulate the effects of all commands
5506 Transactions are used to encapsulate the effects of all commands
5504 that create new changesets or propagate existing changesets into a
5507 that create new changesets or propagate existing changesets into a
5505 repository.
5508 repository.
5506
5509
5507 .. container:: verbose
5510 .. container:: verbose
5508
5511
5509 For example, the following commands are transactional, and their
5512 For example, the following commands are transactional, and their
5510 effects can be rolled back:
5513 effects can be rolled back:
5511
5514
5512 - commit
5515 - commit
5513 - import
5516 - import
5514 - pull
5517 - pull
5515 - push (with this repository as the destination)
5518 - push (with this repository as the destination)
5516 - unbundle
5519 - unbundle
5517
5520
5518 To avoid permanent data loss, rollback will refuse to rollback a
5521 To avoid permanent data loss, rollback will refuse to rollback a
5519 commit transaction if it isn't checked out. Use --force to
5522 commit transaction if it isn't checked out. Use --force to
5520 override this protection.
5523 override this protection.
5521
5524
5522 This command is not intended for use on public repositories. Once
5525 This command is not intended for use on public repositories. Once
5523 changes are visible for pull by other users, rolling a transaction
5526 changes are visible for pull by other users, rolling a transaction
5524 back locally is ineffective (someone else may already have pulled
5527 back locally is ineffective (someone else may already have pulled
5525 the changes). Furthermore, a race is possible with readers of the
5528 the changes). Furthermore, a race is possible with readers of the
5526 repository; for example an in-progress pull from the repository
5529 repository; for example an in-progress pull from the repository
5527 may fail if a rollback is performed.
5530 may fail if a rollback is performed.
5528
5531
5529 Returns 0 on success, 1 if no rollback data is available.
5532 Returns 0 on success, 1 if no rollback data is available.
5530 """
5533 """
5531 return repo.rollback(dryrun=opts.get('dry_run'),
5534 return repo.rollback(dryrun=opts.get('dry_run'),
5532 force=opts.get('force'))
5535 force=opts.get('force'))
5533
5536
5534 @command('root', [])
5537 @command('root', [])
5535 def root(ui, repo):
5538 def root(ui, repo):
5536 """print the root (top) of the current working directory
5539 """print the root (top) of the current working directory
5537
5540
5538 Print the root directory of the current repository.
5541 Print the root directory of the current repository.
5539
5542
5540 Returns 0 on success.
5543 Returns 0 on success.
5541 """
5544 """
5542 ui.write(repo.root + "\n")
5545 ui.write(repo.root + "\n")
5543
5546
5544 @command('^serve',
5547 @command('^serve',
5545 [('A', 'accesslog', '', _('name of access log file to write to'),
5548 [('A', 'accesslog', '', _('name of access log file to write to'),
5546 _('FILE')),
5549 _('FILE')),
5547 ('d', 'daemon', None, _('run server in background')),
5550 ('d', 'daemon', None, _('run server in background')),
5548 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5551 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5549 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5552 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5550 # use string type, then we can check if something was passed
5553 # use string type, then we can check if something was passed
5551 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5554 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5552 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5555 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5553 _('ADDR')),
5556 _('ADDR')),
5554 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5557 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5555 _('PREFIX')),
5558 _('PREFIX')),
5556 ('n', 'name', '',
5559 ('n', 'name', '',
5557 _('name to show in web pages (default: working directory)'), _('NAME')),
5560 _('name to show in web pages (default: working directory)'), _('NAME')),
5558 ('', 'web-conf', '',
5561 ('', 'web-conf', '',
5559 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5562 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5560 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5563 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5561 _('FILE')),
5564 _('FILE')),
5562 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5565 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5563 ('', 'stdio', None, _('for remote clients')),
5566 ('', 'stdio', None, _('for remote clients')),
5564 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5567 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5565 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5568 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5566 ('', 'style', '', _('template style to use'), _('STYLE')),
5569 ('', 'style', '', _('template style to use'), _('STYLE')),
5567 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5570 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5568 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5571 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5569 _('[OPTION]...'),
5572 _('[OPTION]...'),
5570 optionalrepo=True)
5573 optionalrepo=True)
5571 def serve(ui, repo, **opts):
5574 def serve(ui, repo, **opts):
5572 """start stand-alone webserver
5575 """start stand-alone webserver
5573
5576
5574 Start a local HTTP repository browser and pull server. You can use
5577 Start a local HTTP repository browser and pull server. You can use
5575 this for ad-hoc sharing and browsing of repositories. It is
5578 this for ad-hoc sharing and browsing of repositories. It is
5576 recommended to use a real web server to serve a repository for
5579 recommended to use a real web server to serve a repository for
5577 longer periods of time.
5580 longer periods of time.
5578
5581
5579 Please note that the server does not implement access control.
5582 Please note that the server does not implement access control.
5580 This means that, by default, anybody can read from the server and
5583 This means that, by default, anybody can read from the server and
5581 nobody can write to it by default. Set the ``web.allow_push``
5584 nobody can write to it by default. Set the ``web.allow_push``
5582 option to ``*`` to allow everybody to push to the server. You
5585 option to ``*`` to allow everybody to push to the server. You
5583 should use a real web server if you need to authenticate users.
5586 should use a real web server if you need to authenticate users.
5584
5587
5585 By default, the server logs accesses to stdout and errors to
5588 By default, the server logs accesses to stdout and errors to
5586 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5589 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5587 files.
5590 files.
5588
5591
5589 To have the server choose a free port number to listen on, specify
5592 To have the server choose a free port number to listen on, specify
5590 a port number of 0; in this case, the server will print the port
5593 a port number of 0; in this case, the server will print the port
5591 number it uses.
5594 number it uses.
5592
5595
5593 Returns 0 on success.
5596 Returns 0 on success.
5594 """
5597 """
5595
5598
5596 if opts["stdio"] and opts["cmdserver"]:
5599 if opts["stdio"] and opts["cmdserver"]:
5597 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5600 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5598
5601
5599 if opts["stdio"]:
5602 if opts["stdio"]:
5600 if repo is None:
5603 if repo is None:
5601 raise error.RepoError(_("there is no Mercurial repository here"
5604 raise error.RepoError(_("there is no Mercurial repository here"
5602 " (.hg not found)"))
5605 " (.hg not found)"))
5603 s = sshserver.sshserver(ui, repo)
5606 s = sshserver.sshserver(ui, repo)
5604 s.serve_forever()
5607 s.serve_forever()
5605
5608
5606 if opts["cmdserver"]:
5609 if opts["cmdserver"]:
5607 service = commandserver.createservice(ui, repo, opts)
5610 service = commandserver.createservice(ui, repo, opts)
5608 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5611 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5609
5612
5610 # this way we can check if something was given in the command-line
5613 # this way we can check if something was given in the command-line
5611 if opts.get('port'):
5614 if opts.get('port'):
5612 opts['port'] = util.getport(opts.get('port'))
5615 opts['port'] = util.getport(opts.get('port'))
5613
5616
5614 if repo:
5617 if repo:
5615 baseui = repo.baseui
5618 baseui = repo.baseui
5616 else:
5619 else:
5617 baseui = ui
5620 baseui = ui
5618 optlist = ("name templates style address port prefix ipv6"
5621 optlist = ("name templates style address port prefix ipv6"
5619 " accesslog errorlog certificate encoding")
5622 " accesslog errorlog certificate encoding")
5620 for o in optlist.split():
5623 for o in optlist.split():
5621 val = opts.get(o, '')
5624 val = opts.get(o, '')
5622 if val in (None, ''): # should check against default options instead
5625 if val in (None, ''): # should check against default options instead
5623 continue
5626 continue
5624 baseui.setconfig("web", o, val, 'serve')
5627 baseui.setconfig("web", o, val, 'serve')
5625 if repo and repo.ui != baseui:
5628 if repo and repo.ui != baseui:
5626 repo.ui.setconfig("web", o, val, 'serve')
5629 repo.ui.setconfig("web", o, val, 'serve')
5627
5630
5628 o = opts.get('web_conf') or opts.get('webdir_conf')
5631 o = opts.get('web_conf') or opts.get('webdir_conf')
5629 if not o:
5632 if not o:
5630 if not repo:
5633 if not repo:
5631 raise error.RepoError(_("there is no Mercurial repository"
5634 raise error.RepoError(_("there is no Mercurial repository"
5632 " here (.hg not found)"))
5635 " here (.hg not found)"))
5633 o = repo
5636 o = repo
5634
5637
5635 app = hgweb.hgweb(o, baseui=baseui)
5638 app = hgweb.hgweb(o, baseui=baseui)
5636 service = httpservice(ui, app, opts)
5639 service = httpservice(ui, app, opts)
5637 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5640 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5638
5641
5639 class httpservice(object):
5642 class httpservice(object):
5640 def __init__(self, ui, app, opts):
5643 def __init__(self, ui, app, opts):
5641 self.ui = ui
5644 self.ui = ui
5642 self.app = app
5645 self.app = app
5643 self.opts = opts
5646 self.opts = opts
5644
5647
5645 def init(self):
5648 def init(self):
5646 util.setsignalhandler()
5649 util.setsignalhandler()
5647 self.httpd = hgweb_server.create_server(self.ui, self.app)
5650 self.httpd = hgweb_server.create_server(self.ui, self.app)
5648
5651
5649 if self.opts['port'] and not self.ui.verbose:
5652 if self.opts['port'] and not self.ui.verbose:
5650 return
5653 return
5651
5654
5652 if self.httpd.prefix:
5655 if self.httpd.prefix:
5653 prefix = self.httpd.prefix.strip('/') + '/'
5656 prefix = self.httpd.prefix.strip('/') + '/'
5654 else:
5657 else:
5655 prefix = ''
5658 prefix = ''
5656
5659
5657 port = ':%d' % self.httpd.port
5660 port = ':%d' % self.httpd.port
5658 if port == ':80':
5661 if port == ':80':
5659 port = ''
5662 port = ''
5660
5663
5661 bindaddr = self.httpd.addr
5664 bindaddr = self.httpd.addr
5662 if bindaddr == '0.0.0.0':
5665 if bindaddr == '0.0.0.0':
5663 bindaddr = '*'
5666 bindaddr = '*'
5664 elif ':' in bindaddr: # IPv6
5667 elif ':' in bindaddr: # IPv6
5665 bindaddr = '[%s]' % bindaddr
5668 bindaddr = '[%s]' % bindaddr
5666
5669
5667 fqaddr = self.httpd.fqaddr
5670 fqaddr = self.httpd.fqaddr
5668 if ':' in fqaddr:
5671 if ':' in fqaddr:
5669 fqaddr = '[%s]' % fqaddr
5672 fqaddr = '[%s]' % fqaddr
5670 if self.opts['port']:
5673 if self.opts['port']:
5671 write = self.ui.status
5674 write = self.ui.status
5672 else:
5675 else:
5673 write = self.ui.write
5676 write = self.ui.write
5674 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5677 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5675 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5678 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5676 self.ui.flush() # avoid buffering of status message
5679 self.ui.flush() # avoid buffering of status message
5677
5680
5678 def run(self):
5681 def run(self):
5679 self.httpd.serve_forever()
5682 self.httpd.serve_forever()
5680
5683
5681
5684
5682 @command('^status|st',
5685 @command('^status|st',
5683 [('A', 'all', None, _('show status of all files')),
5686 [('A', 'all', None, _('show status of all files')),
5684 ('m', 'modified', None, _('show only modified files')),
5687 ('m', 'modified', None, _('show only modified files')),
5685 ('a', 'added', None, _('show only added files')),
5688 ('a', 'added', None, _('show only added files')),
5686 ('r', 'removed', None, _('show only removed files')),
5689 ('r', 'removed', None, _('show only removed files')),
5687 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5690 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5688 ('c', 'clean', None, _('show only files without changes')),
5691 ('c', 'clean', None, _('show only files without changes')),
5689 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5692 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5690 ('i', 'ignored', None, _('show only ignored files')),
5693 ('i', 'ignored', None, _('show only ignored files')),
5691 ('n', 'no-status', None, _('hide status prefix')),
5694 ('n', 'no-status', None, _('hide status prefix')),
5692 ('C', 'copies', None, _('show source of copied files')),
5695 ('C', 'copies', None, _('show source of copied files')),
5693 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5696 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5694 ('', 'rev', [], _('show difference from revision'), _('REV')),
5697 ('', 'rev', [], _('show difference from revision'), _('REV')),
5695 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5698 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5696 ] + walkopts + subrepoopts + formatteropts,
5699 ] + walkopts + subrepoopts + formatteropts,
5697 _('[OPTION]... [FILE]...'),
5700 _('[OPTION]... [FILE]...'),
5698 inferrepo=True)
5701 inferrepo=True)
5699 def status(ui, repo, *pats, **opts):
5702 def status(ui, repo, *pats, **opts):
5700 """show changed files in the working directory
5703 """show changed files in the working directory
5701
5704
5702 Show status of files in the repository. If names are given, only
5705 Show status of files in the repository. If names are given, only
5703 files that match are shown. Files that are clean or ignored or
5706 files that match are shown. Files that are clean or ignored or
5704 the source of a copy/move operation, are not listed unless
5707 the source of a copy/move operation, are not listed unless
5705 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5708 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5706 Unless options described with "show only ..." are given, the
5709 Unless options described with "show only ..." are given, the
5707 options -mardu are used.
5710 options -mardu are used.
5708
5711
5709 Option -q/--quiet hides untracked (unknown and ignored) files
5712 Option -q/--quiet hides untracked (unknown and ignored) files
5710 unless explicitly requested with -u/--unknown or -i/--ignored.
5713 unless explicitly requested with -u/--unknown or -i/--ignored.
5711
5714
5712 .. note::
5715 .. note::
5713
5716
5714 status may appear to disagree with diff if permissions have
5717 status may appear to disagree with diff if permissions have
5715 changed or a merge has occurred. The standard diff format does
5718 changed or a merge has occurred. The standard diff format does
5716 not report permission changes and diff only reports changes
5719 not report permission changes and diff only reports changes
5717 relative to one merge parent.
5720 relative to one merge parent.
5718
5721
5719 If one revision is given, it is used as the base revision.
5722 If one revision is given, it is used as the base revision.
5720 If two revisions are given, the differences between them are
5723 If two revisions are given, the differences between them are
5721 shown. The --change option can also be used as a shortcut to list
5724 shown. The --change option can also be used as a shortcut to list
5722 the changed files of a revision from its first parent.
5725 the changed files of a revision from its first parent.
5723
5726
5724 The codes used to show the status of files are::
5727 The codes used to show the status of files are::
5725
5728
5726 M = modified
5729 M = modified
5727 A = added
5730 A = added
5728 R = removed
5731 R = removed
5729 C = clean
5732 C = clean
5730 ! = missing (deleted by non-hg command, but still tracked)
5733 ! = missing (deleted by non-hg command, but still tracked)
5731 ? = not tracked
5734 ? = not tracked
5732 I = ignored
5735 I = ignored
5733 = origin of the previous file (with --copies)
5736 = origin of the previous file (with --copies)
5734
5737
5735 .. container:: verbose
5738 .. container:: verbose
5736
5739
5737 Examples:
5740 Examples:
5738
5741
5739 - show changes in the working directory relative to a
5742 - show changes in the working directory relative to a
5740 changeset::
5743 changeset::
5741
5744
5742 hg status --rev 9353
5745 hg status --rev 9353
5743
5746
5744 - show changes in the working directory relative to the
5747 - show changes in the working directory relative to the
5745 current directory (see :hg:`help patterns` for more information)::
5748 current directory (see :hg:`help patterns` for more information)::
5746
5749
5747 hg status re:
5750 hg status re:
5748
5751
5749 - show all changes including copies in an existing changeset::
5752 - show all changes including copies in an existing changeset::
5750
5753
5751 hg status --copies --change 9353
5754 hg status --copies --change 9353
5752
5755
5753 - get a NUL separated list of added files, suitable for xargs::
5756 - get a NUL separated list of added files, suitable for xargs::
5754
5757
5755 hg status -an0
5758 hg status -an0
5756
5759
5757 Returns 0 on success.
5760 Returns 0 on success.
5758 """
5761 """
5759
5762
5760 revs = opts.get('rev')
5763 revs = opts.get('rev')
5761 change = opts.get('change')
5764 change = opts.get('change')
5762
5765
5763 if revs and change:
5766 if revs and change:
5764 msg = _('cannot specify --rev and --change at the same time')
5767 msg = _('cannot specify --rev and --change at the same time')
5765 raise util.Abort(msg)
5768 raise util.Abort(msg)
5766 elif change:
5769 elif change:
5767 node2 = scmutil.revsingle(repo, change, None).node()
5770 node2 = scmutil.revsingle(repo, change, None).node()
5768 node1 = repo[node2].p1().node()
5771 node1 = repo[node2].p1().node()
5769 else:
5772 else:
5770 node1, node2 = scmutil.revpair(repo, revs)
5773 node1, node2 = scmutil.revpair(repo, revs)
5771
5774
5772 if pats:
5775 if pats:
5773 cwd = repo.getcwd()
5776 cwd = repo.getcwd()
5774 else:
5777 else:
5775 cwd = ''
5778 cwd = ''
5776
5779
5777 if opts.get('print0'):
5780 if opts.get('print0'):
5778 end = '\0'
5781 end = '\0'
5779 else:
5782 else:
5780 end = '\n'
5783 end = '\n'
5781 copy = {}
5784 copy = {}
5782 states = 'modified added removed deleted unknown ignored clean'.split()
5785 states = 'modified added removed deleted unknown ignored clean'.split()
5783 show = [k for k in states if opts.get(k)]
5786 show = [k for k in states if opts.get(k)]
5784 if opts.get('all'):
5787 if opts.get('all'):
5785 show += ui.quiet and (states[:4] + ['clean']) or states
5788 show += ui.quiet and (states[:4] + ['clean']) or states
5786 if not show:
5789 if not show:
5787 if ui.quiet:
5790 if ui.quiet:
5788 show = states[:4]
5791 show = states[:4]
5789 else:
5792 else:
5790 show = states[:5]
5793 show = states[:5]
5791
5794
5792 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5795 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5793 'ignored' in show, 'clean' in show, 'unknown' in show,
5796 'ignored' in show, 'clean' in show, 'unknown' in show,
5794 opts.get('subrepos'))
5797 opts.get('subrepos'))
5795 changestates = zip(states, 'MAR!?IC', stat)
5798 changestates = zip(states, 'MAR!?IC', stat)
5796
5799
5797 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5800 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5798 copy = copies.pathcopies(repo[node1], repo[node2])
5801 copy = copies.pathcopies(repo[node1], repo[node2])
5799
5802
5800 fm = ui.formatter('status', opts)
5803 fm = ui.formatter('status', opts)
5801 fmt = '%s' + end
5804 fmt = '%s' + end
5802 showchar = not opts.get('no_status')
5805 showchar = not opts.get('no_status')
5803
5806
5804 for state, char, files in changestates:
5807 for state, char, files in changestates:
5805 if state in show:
5808 if state in show:
5806 label = 'status.' + state
5809 label = 'status.' + state
5807 for f in files:
5810 for f in files:
5808 fm.startitem()
5811 fm.startitem()
5809 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5812 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5810 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5813 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5811 if f in copy:
5814 if f in copy:
5812 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5815 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5813 label='status.copied')
5816 label='status.copied')
5814 fm.end()
5817 fm.end()
5815
5818
5816 @command('^summary|sum',
5819 @command('^summary|sum',
5817 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5820 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5818 def summary(ui, repo, **opts):
5821 def summary(ui, repo, **opts):
5819 """summarize working directory state
5822 """summarize working directory state
5820
5823
5821 This generates a brief summary of the working directory state,
5824 This generates a brief summary of the working directory state,
5822 including parents, branch, commit status, and available updates.
5825 including parents, branch, commit status, and available updates.
5823
5826
5824 With the --remote option, this will check the default paths for
5827 With the --remote option, this will check the default paths for
5825 incoming and outgoing changes. This can be time-consuming.
5828 incoming and outgoing changes. This can be time-consuming.
5826
5829
5827 Returns 0 on success.
5830 Returns 0 on success.
5828 """
5831 """
5829
5832
5830 ctx = repo[None]
5833 ctx = repo[None]
5831 parents = ctx.parents()
5834 parents = ctx.parents()
5832 pnode = parents[0].node()
5835 pnode = parents[0].node()
5833 marks = []
5836 marks = []
5834
5837
5835 for p in parents:
5838 for p in parents:
5836 # label with log.changeset (instead of log.parent) since this
5839 # label with log.changeset (instead of log.parent) since this
5837 # shows a working directory parent *changeset*:
5840 # shows a working directory parent *changeset*:
5838 # i18n: column positioning for "hg summary"
5841 # i18n: column positioning for "hg summary"
5839 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5842 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5840 label='log.changeset changeset.%s' % p.phasestr())
5843 label='log.changeset changeset.%s' % p.phasestr())
5841 ui.write(' '.join(p.tags()), label='log.tag')
5844 ui.write(' '.join(p.tags()), label='log.tag')
5842 if p.bookmarks():
5845 if p.bookmarks():
5843 marks.extend(p.bookmarks())
5846 marks.extend(p.bookmarks())
5844 if p.rev() == -1:
5847 if p.rev() == -1:
5845 if not len(repo):
5848 if not len(repo):
5846 ui.write(_(' (empty repository)'))
5849 ui.write(_(' (empty repository)'))
5847 else:
5850 else:
5848 ui.write(_(' (no revision checked out)'))
5851 ui.write(_(' (no revision checked out)'))
5849 ui.write('\n')
5852 ui.write('\n')
5850 if p.description():
5853 if p.description():
5851 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5854 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5852 label='log.summary')
5855 label='log.summary')
5853
5856
5854 branch = ctx.branch()
5857 branch = ctx.branch()
5855 bheads = repo.branchheads(branch)
5858 bheads = repo.branchheads(branch)
5856 # i18n: column positioning for "hg summary"
5859 # i18n: column positioning for "hg summary"
5857 m = _('branch: %s\n') % branch
5860 m = _('branch: %s\n') % branch
5858 if branch != 'default':
5861 if branch != 'default':
5859 ui.write(m, label='log.branch')
5862 ui.write(m, label='log.branch')
5860 else:
5863 else:
5861 ui.status(m, label='log.branch')
5864 ui.status(m, label='log.branch')
5862
5865
5863 if marks:
5866 if marks:
5864 current = repo._bookmarkcurrent
5867 current = repo._bookmarkcurrent
5865 # i18n: column positioning for "hg summary"
5868 # i18n: column positioning for "hg summary"
5866 ui.write(_('bookmarks:'), label='log.bookmark')
5869 ui.write(_('bookmarks:'), label='log.bookmark')
5867 if current is not None:
5870 if current is not None:
5868 if current in marks:
5871 if current in marks:
5869 ui.write(' *' + current, label='bookmarks.current')
5872 ui.write(' *' + current, label='bookmarks.current')
5870 marks.remove(current)
5873 marks.remove(current)
5871 else:
5874 else:
5872 ui.write(' [%s]' % current, label='bookmarks.current')
5875 ui.write(' [%s]' % current, label='bookmarks.current')
5873 for m in marks:
5876 for m in marks:
5874 ui.write(' ' + m, label='log.bookmark')
5877 ui.write(' ' + m, label='log.bookmark')
5875 ui.write('\n', label='log.bookmark')
5878 ui.write('\n', label='log.bookmark')
5876
5879
5877 status = repo.status(unknown=True)
5880 status = repo.status(unknown=True)
5878
5881
5879 c = repo.dirstate.copies()
5882 c = repo.dirstate.copies()
5880 copied, renamed = [], []
5883 copied, renamed = [], []
5881 for d, s in c.iteritems():
5884 for d, s in c.iteritems():
5882 if s in status.removed:
5885 if s in status.removed:
5883 status.removed.remove(s)
5886 status.removed.remove(s)
5884 renamed.append(d)
5887 renamed.append(d)
5885 else:
5888 else:
5886 copied.append(d)
5889 copied.append(d)
5887 if d in status.added:
5890 if d in status.added:
5888 status.added.remove(d)
5891 status.added.remove(d)
5889
5892
5890 ms = mergemod.mergestate(repo)
5893 ms = mergemod.mergestate(repo)
5891 unresolved = [f for f in ms if ms[f] == 'u']
5894 unresolved = [f for f in ms if ms[f] == 'u']
5892
5895
5893 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5896 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5894
5897
5895 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5898 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5896 (ui.label(_('%d added'), 'status.added'), status.added),
5899 (ui.label(_('%d added'), 'status.added'), status.added),
5897 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5900 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5898 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5901 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5899 (ui.label(_('%d copied'), 'status.copied'), copied),
5902 (ui.label(_('%d copied'), 'status.copied'), copied),
5900 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5903 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5901 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5904 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5902 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5905 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5903 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5906 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5904 t = []
5907 t = []
5905 for l, s in labels:
5908 for l, s in labels:
5906 if s:
5909 if s:
5907 t.append(l % len(s))
5910 t.append(l % len(s))
5908
5911
5909 t = ', '.join(t)
5912 t = ', '.join(t)
5910 cleanworkdir = False
5913 cleanworkdir = False
5911
5914
5912 if repo.vfs.exists('updatestate'):
5915 if repo.vfs.exists('updatestate'):
5913 t += _(' (interrupted update)')
5916 t += _(' (interrupted update)')
5914 elif len(parents) > 1:
5917 elif len(parents) > 1:
5915 t += _(' (merge)')
5918 t += _(' (merge)')
5916 elif branch != parents[0].branch():
5919 elif branch != parents[0].branch():
5917 t += _(' (new branch)')
5920 t += _(' (new branch)')
5918 elif (parents[0].closesbranch() and
5921 elif (parents[0].closesbranch() and
5919 pnode in repo.branchheads(branch, closed=True)):
5922 pnode in repo.branchheads(branch, closed=True)):
5920 t += _(' (head closed)')
5923 t += _(' (head closed)')
5921 elif not (status.modified or status.added or status.removed or renamed or
5924 elif not (status.modified or status.added or status.removed or renamed or
5922 copied or subs):
5925 copied or subs):
5923 t += _(' (clean)')
5926 t += _(' (clean)')
5924 cleanworkdir = True
5927 cleanworkdir = True
5925 elif pnode not in bheads:
5928 elif pnode not in bheads:
5926 t += _(' (new branch head)')
5929 t += _(' (new branch head)')
5927
5930
5928 if cleanworkdir:
5931 if cleanworkdir:
5929 # i18n: column positioning for "hg summary"
5932 # i18n: column positioning for "hg summary"
5930 ui.status(_('commit: %s\n') % t.strip())
5933 ui.status(_('commit: %s\n') % t.strip())
5931 else:
5934 else:
5932 # i18n: column positioning for "hg summary"
5935 # i18n: column positioning for "hg summary"
5933 ui.write(_('commit: %s\n') % t.strip())
5936 ui.write(_('commit: %s\n') % t.strip())
5934
5937
5935 # all ancestors of branch heads - all ancestors of parent = new csets
5938 # all ancestors of branch heads - all ancestors of parent = new csets
5936 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5939 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5937 bheads))
5940 bheads))
5938
5941
5939 if new == 0:
5942 if new == 0:
5940 # i18n: column positioning for "hg summary"
5943 # i18n: column positioning for "hg summary"
5941 ui.status(_('update: (current)\n'))
5944 ui.status(_('update: (current)\n'))
5942 elif pnode not in bheads:
5945 elif pnode not in bheads:
5943 # i18n: column positioning for "hg summary"
5946 # i18n: column positioning for "hg summary"
5944 ui.write(_('update: %d new changesets (update)\n') % new)
5947 ui.write(_('update: %d new changesets (update)\n') % new)
5945 else:
5948 else:
5946 # i18n: column positioning for "hg summary"
5949 # i18n: column positioning for "hg summary"
5947 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5950 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5948 (new, len(bheads)))
5951 (new, len(bheads)))
5949
5952
5950 cmdutil.summaryhooks(ui, repo)
5953 cmdutil.summaryhooks(ui, repo)
5951
5954
5952 if opts.get('remote'):
5955 if opts.get('remote'):
5953 needsincoming, needsoutgoing = True, True
5956 needsincoming, needsoutgoing = True, True
5954 else:
5957 else:
5955 needsincoming, needsoutgoing = False, False
5958 needsincoming, needsoutgoing = False, False
5956 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5959 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5957 if i:
5960 if i:
5958 needsincoming = True
5961 needsincoming = True
5959 if o:
5962 if o:
5960 needsoutgoing = True
5963 needsoutgoing = True
5961 if not needsincoming and not needsoutgoing:
5964 if not needsincoming and not needsoutgoing:
5962 return
5965 return
5963
5966
5964 def getincoming():
5967 def getincoming():
5965 source, branches = hg.parseurl(ui.expandpath('default'))
5968 source, branches = hg.parseurl(ui.expandpath('default'))
5966 sbranch = branches[0]
5969 sbranch = branches[0]
5967 try:
5970 try:
5968 other = hg.peer(repo, {}, source)
5971 other = hg.peer(repo, {}, source)
5969 except error.RepoError:
5972 except error.RepoError:
5970 if opts.get('remote'):
5973 if opts.get('remote'):
5971 raise
5974 raise
5972 return source, sbranch, None, None, None
5975 return source, sbranch, None, None, None
5973 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5976 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5974 if revs:
5977 if revs:
5975 revs = [other.lookup(rev) for rev in revs]
5978 revs = [other.lookup(rev) for rev in revs]
5976 ui.debug('comparing with %s\n' % util.hidepassword(source))
5979 ui.debug('comparing with %s\n' % util.hidepassword(source))
5977 repo.ui.pushbuffer()
5980 repo.ui.pushbuffer()
5978 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5981 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5979 repo.ui.popbuffer()
5982 repo.ui.popbuffer()
5980 return source, sbranch, other, commoninc, commoninc[1]
5983 return source, sbranch, other, commoninc, commoninc[1]
5981
5984
5982 if needsincoming:
5985 if needsincoming:
5983 source, sbranch, sother, commoninc, incoming = getincoming()
5986 source, sbranch, sother, commoninc, incoming = getincoming()
5984 else:
5987 else:
5985 source = sbranch = sother = commoninc = incoming = None
5988 source = sbranch = sother = commoninc = incoming = None
5986
5989
5987 def getoutgoing():
5990 def getoutgoing():
5988 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5991 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5989 dbranch = branches[0]
5992 dbranch = branches[0]
5990 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5993 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5991 if source != dest:
5994 if source != dest:
5992 try:
5995 try:
5993 dother = hg.peer(repo, {}, dest)
5996 dother = hg.peer(repo, {}, dest)
5994 except error.RepoError:
5997 except error.RepoError:
5995 if opts.get('remote'):
5998 if opts.get('remote'):
5996 raise
5999 raise
5997 return dest, dbranch, None, None
6000 return dest, dbranch, None, None
5998 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6001 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5999 elif sother is None:
6002 elif sother is None:
6000 # there is no explicit destination peer, but source one is invalid
6003 # there is no explicit destination peer, but source one is invalid
6001 return dest, dbranch, None, None
6004 return dest, dbranch, None, None
6002 else:
6005 else:
6003 dother = sother
6006 dother = sother
6004 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6007 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6005 common = None
6008 common = None
6006 else:
6009 else:
6007 common = commoninc
6010 common = commoninc
6008 if revs:
6011 if revs:
6009 revs = [repo.lookup(rev) for rev in revs]
6012 revs = [repo.lookup(rev) for rev in revs]
6010 repo.ui.pushbuffer()
6013 repo.ui.pushbuffer()
6011 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6014 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6012 commoninc=common)
6015 commoninc=common)
6013 repo.ui.popbuffer()
6016 repo.ui.popbuffer()
6014 return dest, dbranch, dother, outgoing
6017 return dest, dbranch, dother, outgoing
6015
6018
6016 if needsoutgoing:
6019 if needsoutgoing:
6017 dest, dbranch, dother, outgoing = getoutgoing()
6020 dest, dbranch, dother, outgoing = getoutgoing()
6018 else:
6021 else:
6019 dest = dbranch = dother = outgoing = None
6022 dest = dbranch = dother = outgoing = None
6020
6023
6021 if opts.get('remote'):
6024 if opts.get('remote'):
6022 t = []
6025 t = []
6023 if incoming:
6026 if incoming:
6024 t.append(_('1 or more incoming'))
6027 t.append(_('1 or more incoming'))
6025 o = outgoing.missing
6028 o = outgoing.missing
6026 if o:
6029 if o:
6027 t.append(_('%d outgoing') % len(o))
6030 t.append(_('%d outgoing') % len(o))
6028 other = dother or sother
6031 other = dother or sother
6029 if 'bookmarks' in other.listkeys('namespaces'):
6032 if 'bookmarks' in other.listkeys('namespaces'):
6030 counts = bookmarks.summary(repo, other)
6033 counts = bookmarks.summary(repo, other)
6031 if counts[0] > 0:
6034 if counts[0] > 0:
6032 t.append(_('%d incoming bookmarks') % counts[0])
6035 t.append(_('%d incoming bookmarks') % counts[0])
6033 if counts[1] > 0:
6036 if counts[1] > 0:
6034 t.append(_('%d outgoing bookmarks') % counts[1])
6037 t.append(_('%d outgoing bookmarks') % counts[1])
6035
6038
6036 if t:
6039 if t:
6037 # i18n: column positioning for "hg summary"
6040 # i18n: column positioning for "hg summary"
6038 ui.write(_('remote: %s\n') % (', '.join(t)))
6041 ui.write(_('remote: %s\n') % (', '.join(t)))
6039 else:
6042 else:
6040 # i18n: column positioning for "hg summary"
6043 # i18n: column positioning for "hg summary"
6041 ui.status(_('remote: (synced)\n'))
6044 ui.status(_('remote: (synced)\n'))
6042
6045
6043 cmdutil.summaryremotehooks(ui, repo, opts,
6046 cmdutil.summaryremotehooks(ui, repo, opts,
6044 ((source, sbranch, sother, commoninc),
6047 ((source, sbranch, sother, commoninc),
6045 (dest, dbranch, dother, outgoing)))
6048 (dest, dbranch, dother, outgoing)))
6046
6049
6047 @command('tag',
6050 @command('tag',
6048 [('f', 'force', None, _('force tag')),
6051 [('f', 'force', None, _('force tag')),
6049 ('l', 'local', None, _('make the tag local')),
6052 ('l', 'local', None, _('make the tag local')),
6050 ('r', 'rev', '', _('revision to tag'), _('REV')),
6053 ('r', 'rev', '', _('revision to tag'), _('REV')),
6051 ('', 'remove', None, _('remove a tag')),
6054 ('', 'remove', None, _('remove a tag')),
6052 # -l/--local is already there, commitopts cannot be used
6055 # -l/--local is already there, commitopts cannot be used
6053 ('e', 'edit', None, _('invoke editor on commit messages')),
6056 ('e', 'edit', None, _('invoke editor on commit messages')),
6054 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6057 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6055 ] + commitopts2,
6058 ] + commitopts2,
6056 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6059 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6057 def tag(ui, repo, name1, *names, **opts):
6060 def tag(ui, repo, name1, *names, **opts):
6058 """add one or more tags for the current or given revision
6061 """add one or more tags for the current or given revision
6059
6062
6060 Name a particular revision using <name>.
6063 Name a particular revision using <name>.
6061
6064
6062 Tags are used to name particular revisions of the repository and are
6065 Tags are used to name particular revisions of the repository and are
6063 very useful to compare different revisions, to go back to significant
6066 very useful to compare different revisions, to go back to significant
6064 earlier versions or to mark branch points as releases, etc. Changing
6067 earlier versions or to mark branch points as releases, etc. Changing
6065 an existing tag is normally disallowed; use -f/--force to override.
6068 an existing tag is normally disallowed; use -f/--force to override.
6066
6069
6067 If no revision is given, the parent of the working directory is
6070 If no revision is given, the parent of the working directory is
6068 used.
6071 used.
6069
6072
6070 To facilitate version control, distribution, and merging of tags,
6073 To facilitate version control, distribution, and merging of tags,
6071 they are stored as a file named ".hgtags" which is managed similarly
6074 they are stored as a file named ".hgtags" which is managed similarly
6072 to other project files and can be hand-edited if necessary. This
6075 to other project files and can be hand-edited if necessary. This
6073 also means that tagging creates a new commit. The file
6076 also means that tagging creates a new commit. The file
6074 ".hg/localtags" is used for local tags (not shared among
6077 ".hg/localtags" is used for local tags (not shared among
6075 repositories).
6078 repositories).
6076
6079
6077 Tag commits are usually made at the head of a branch. If the parent
6080 Tag commits are usually made at the head of a branch. If the parent
6078 of the working directory is not a branch head, :hg:`tag` aborts; use
6081 of the working directory is not a branch head, :hg:`tag` aborts; use
6079 -f/--force to force the tag commit to be based on a non-head
6082 -f/--force to force the tag commit to be based on a non-head
6080 changeset.
6083 changeset.
6081
6084
6082 See :hg:`help dates` for a list of formats valid for -d/--date.
6085 See :hg:`help dates` for a list of formats valid for -d/--date.
6083
6086
6084 Since tag names have priority over branch names during revision
6087 Since tag names have priority over branch names during revision
6085 lookup, using an existing branch name as a tag name is discouraged.
6088 lookup, using an existing branch name as a tag name is discouraged.
6086
6089
6087 Returns 0 on success.
6090 Returns 0 on success.
6088 """
6091 """
6089 wlock = lock = None
6092 wlock = lock = None
6090 try:
6093 try:
6091 wlock = repo.wlock()
6094 wlock = repo.wlock()
6092 lock = repo.lock()
6095 lock = repo.lock()
6093 rev_ = "."
6096 rev_ = "."
6094 names = [t.strip() for t in (name1,) + names]
6097 names = [t.strip() for t in (name1,) + names]
6095 if len(names) != len(set(names)):
6098 if len(names) != len(set(names)):
6096 raise util.Abort(_('tag names must be unique'))
6099 raise util.Abort(_('tag names must be unique'))
6097 for n in names:
6100 for n in names:
6098 scmutil.checknewlabel(repo, n, 'tag')
6101 scmutil.checknewlabel(repo, n, 'tag')
6099 if not n:
6102 if not n:
6100 raise util.Abort(_('tag names cannot consist entirely of '
6103 raise util.Abort(_('tag names cannot consist entirely of '
6101 'whitespace'))
6104 'whitespace'))
6102 if opts.get('rev') and opts.get('remove'):
6105 if opts.get('rev') and opts.get('remove'):
6103 raise util.Abort(_("--rev and --remove are incompatible"))
6106 raise util.Abort(_("--rev and --remove are incompatible"))
6104 if opts.get('rev'):
6107 if opts.get('rev'):
6105 rev_ = opts['rev']
6108 rev_ = opts['rev']
6106 message = opts.get('message')
6109 message = opts.get('message')
6107 if opts.get('remove'):
6110 if opts.get('remove'):
6108 if opts.get('local'):
6111 if opts.get('local'):
6109 expectedtype = 'local'
6112 expectedtype = 'local'
6110 else:
6113 else:
6111 expectedtype = 'global'
6114 expectedtype = 'global'
6112
6115
6113 for n in names:
6116 for n in names:
6114 if not repo.tagtype(n):
6117 if not repo.tagtype(n):
6115 raise util.Abort(_("tag '%s' does not exist") % n)
6118 raise util.Abort(_("tag '%s' does not exist") % n)
6116 if repo.tagtype(n) != expectedtype:
6119 if repo.tagtype(n) != expectedtype:
6117 if expectedtype == 'global':
6120 if expectedtype == 'global':
6118 raise util.Abort(_("tag '%s' is not a global tag") % n)
6121 raise util.Abort(_("tag '%s' is not a global tag") % n)
6119 else:
6122 else:
6120 raise util.Abort(_("tag '%s' is not a local tag") % n)
6123 raise util.Abort(_("tag '%s' is not a local tag") % n)
6121 rev_ = nullid
6124 rev_ = nullid
6122 if not message:
6125 if not message:
6123 # we don't translate commit messages
6126 # we don't translate commit messages
6124 message = 'Removed tag %s' % ', '.join(names)
6127 message = 'Removed tag %s' % ', '.join(names)
6125 elif not opts.get('force'):
6128 elif not opts.get('force'):
6126 for n in names:
6129 for n in names:
6127 if n in repo.tags():
6130 if n in repo.tags():
6128 raise util.Abort(_("tag '%s' already exists "
6131 raise util.Abort(_("tag '%s' already exists "
6129 "(use -f to force)") % n)
6132 "(use -f to force)") % n)
6130 if not opts.get('local'):
6133 if not opts.get('local'):
6131 p1, p2 = repo.dirstate.parents()
6134 p1, p2 = repo.dirstate.parents()
6132 if p2 != nullid:
6135 if p2 != nullid:
6133 raise util.Abort(_('uncommitted merge'))
6136 raise util.Abort(_('uncommitted merge'))
6134 bheads = repo.branchheads()
6137 bheads = repo.branchheads()
6135 if not opts.get('force') and bheads and p1 not in bheads:
6138 if not opts.get('force') and bheads and p1 not in bheads:
6136 raise util.Abort(_('not at a branch head (use -f to force)'))
6139 raise util.Abort(_('not at a branch head (use -f to force)'))
6137 r = scmutil.revsingle(repo, rev_).node()
6140 r = scmutil.revsingle(repo, rev_).node()
6138
6141
6139 if not message:
6142 if not message:
6140 # we don't translate commit messages
6143 # we don't translate commit messages
6141 message = ('Added tag %s for changeset %s' %
6144 message = ('Added tag %s for changeset %s' %
6142 (', '.join(names), short(r)))
6145 (', '.join(names), short(r)))
6143
6146
6144 date = opts.get('date')
6147 date = opts.get('date')
6145 if date:
6148 if date:
6146 date = util.parsedate(date)
6149 date = util.parsedate(date)
6147
6150
6148 if opts.get('remove'):
6151 if opts.get('remove'):
6149 editform = 'tag.remove'
6152 editform = 'tag.remove'
6150 else:
6153 else:
6151 editform = 'tag.add'
6154 editform = 'tag.add'
6152 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6155 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6153
6156
6154 # don't allow tagging the null rev
6157 # don't allow tagging the null rev
6155 if (not opts.get('remove') and
6158 if (not opts.get('remove') and
6156 scmutil.revsingle(repo, rev_).rev() == nullrev):
6159 scmutil.revsingle(repo, rev_).rev() == nullrev):
6157 raise util.Abort(_("cannot tag null revision"))
6160 raise util.Abort(_("cannot tag null revision"))
6158
6161
6159 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6162 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6160 editor=editor)
6163 editor=editor)
6161 finally:
6164 finally:
6162 release(lock, wlock)
6165 release(lock, wlock)
6163
6166
6164 @command('tags', formatteropts, '')
6167 @command('tags', formatteropts, '')
6165 def tags(ui, repo, **opts):
6168 def tags(ui, repo, **opts):
6166 """list repository tags
6169 """list repository tags
6167
6170
6168 This lists both regular and local tags. When the -v/--verbose
6171 This lists both regular and local tags. When the -v/--verbose
6169 switch is used, a third column "local" is printed for local tags.
6172 switch is used, a third column "local" is printed for local tags.
6170
6173
6171 Returns 0 on success.
6174 Returns 0 on success.
6172 """
6175 """
6173
6176
6174 fm = ui.formatter('tags', opts)
6177 fm = ui.formatter('tags', opts)
6175 hexfunc = fm.hexfunc
6178 hexfunc = fm.hexfunc
6176 tagtype = ""
6179 tagtype = ""
6177
6180
6178 for t, n in reversed(repo.tagslist()):
6181 for t, n in reversed(repo.tagslist()):
6179 hn = hexfunc(n)
6182 hn = hexfunc(n)
6180 label = 'tags.normal'
6183 label = 'tags.normal'
6181 tagtype = ''
6184 tagtype = ''
6182 if repo.tagtype(t) == 'local':
6185 if repo.tagtype(t) == 'local':
6183 label = 'tags.local'
6186 label = 'tags.local'
6184 tagtype = 'local'
6187 tagtype = 'local'
6185
6188
6186 fm.startitem()
6189 fm.startitem()
6187 fm.write('tag', '%s', t, label=label)
6190 fm.write('tag', '%s', t, label=label)
6188 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6191 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6189 fm.condwrite(not ui.quiet, 'rev node', fmt,
6192 fm.condwrite(not ui.quiet, 'rev node', fmt,
6190 repo.changelog.rev(n), hn, label=label)
6193 repo.changelog.rev(n), hn, label=label)
6191 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6194 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6192 tagtype, label=label)
6195 tagtype, label=label)
6193 fm.plain('\n')
6196 fm.plain('\n')
6194 fm.end()
6197 fm.end()
6195
6198
6196 @command('tip',
6199 @command('tip',
6197 [('p', 'patch', None, _('show patch')),
6200 [('p', 'patch', None, _('show patch')),
6198 ('g', 'git', None, _('use git extended diff format')),
6201 ('g', 'git', None, _('use git extended diff format')),
6199 ] + templateopts,
6202 ] + templateopts,
6200 _('[-p] [-g]'))
6203 _('[-p] [-g]'))
6201 def tip(ui, repo, **opts):
6204 def tip(ui, repo, **opts):
6202 """show the tip revision (DEPRECATED)
6205 """show the tip revision (DEPRECATED)
6203
6206
6204 The tip revision (usually just called the tip) is the changeset
6207 The tip revision (usually just called the tip) is the changeset
6205 most recently added to the repository (and therefore the most
6208 most recently added to the repository (and therefore the most
6206 recently changed head).
6209 recently changed head).
6207
6210
6208 If you have just made a commit, that commit will be the tip. If
6211 If you have just made a commit, that commit will be the tip. If
6209 you have just pulled changes from another repository, the tip of
6212 you have just pulled changes from another repository, the tip of
6210 that repository becomes the current tip. The "tip" tag is special
6213 that repository becomes the current tip. The "tip" tag is special
6211 and cannot be renamed or assigned to a different changeset.
6214 and cannot be renamed or assigned to a different changeset.
6212
6215
6213 This command is deprecated, please use :hg:`heads` instead.
6216 This command is deprecated, please use :hg:`heads` instead.
6214
6217
6215 Returns 0 on success.
6218 Returns 0 on success.
6216 """
6219 """
6217 displayer = cmdutil.show_changeset(ui, repo, opts)
6220 displayer = cmdutil.show_changeset(ui, repo, opts)
6218 displayer.show(repo['tip'])
6221 displayer.show(repo['tip'])
6219 displayer.close()
6222 displayer.close()
6220
6223
6221 @command('unbundle',
6224 @command('unbundle',
6222 [('u', 'update', None,
6225 [('u', 'update', None,
6223 _('update to new branch head if changesets were unbundled'))],
6226 _('update to new branch head if changesets were unbundled'))],
6224 _('[-u] FILE...'))
6227 _('[-u] FILE...'))
6225 def unbundle(ui, repo, fname1, *fnames, **opts):
6228 def unbundle(ui, repo, fname1, *fnames, **opts):
6226 """apply one or more changegroup files
6229 """apply one or more changegroup files
6227
6230
6228 Apply one or more compressed changegroup files generated by the
6231 Apply one or more compressed changegroup files generated by the
6229 bundle command.
6232 bundle command.
6230
6233
6231 Returns 0 on success, 1 if an update has unresolved files.
6234 Returns 0 on success, 1 if an update has unresolved files.
6232 """
6235 """
6233 fnames = (fname1,) + fnames
6236 fnames = (fname1,) + fnames
6234
6237
6235 lock = repo.lock()
6238 lock = repo.lock()
6236 try:
6239 try:
6237 for fname in fnames:
6240 for fname in fnames:
6238 f = hg.openpath(ui, fname)
6241 f = hg.openpath(ui, fname)
6239 gen = exchange.readbundle(ui, f, fname)
6242 gen = exchange.readbundle(ui, f, fname)
6240 if isinstance(gen, bundle2.unbundle20):
6243 if isinstance(gen, bundle2.unbundle20):
6241 tr = repo.transaction('unbundle')
6244 tr = repo.transaction('unbundle')
6242 try:
6245 try:
6243 op = bundle2.processbundle(repo, gen, lambda: tr)
6246 op = bundle2.processbundle(repo, gen, lambda: tr)
6244 tr.close()
6247 tr.close()
6245 finally:
6248 finally:
6246 if tr:
6249 if tr:
6247 tr.release()
6250 tr.release()
6248 changes = [r.get('result', 0)
6251 changes = [r.get('result', 0)
6249 for r in op.records['changegroup']]
6252 for r in op.records['changegroup']]
6250 modheads = changegroup.combineresults(changes)
6253 modheads = changegroup.combineresults(changes)
6251 else:
6254 else:
6252 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6255 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6253 'bundle:' + fname)
6256 'bundle:' + fname)
6254 finally:
6257 finally:
6255 lock.release()
6258 lock.release()
6256
6259
6257 return postincoming(ui, repo, modheads, opts.get('update'), None)
6260 return postincoming(ui, repo, modheads, opts.get('update'), None)
6258
6261
6259 @command('^update|up|checkout|co',
6262 @command('^update|up|checkout|co',
6260 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6263 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6261 ('c', 'check', None,
6264 ('c', 'check', None,
6262 _('update across branches if no uncommitted changes')),
6265 _('update across branches if no uncommitted changes')),
6263 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6266 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6264 ('r', 'rev', '', _('revision'), _('REV'))
6267 ('r', 'rev', '', _('revision'), _('REV'))
6265 ] + mergetoolopts,
6268 ] + mergetoolopts,
6266 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6269 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6267 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6270 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6268 tool=None):
6271 tool=None):
6269 """update working directory (or switch revisions)
6272 """update working directory (or switch revisions)
6270
6273
6271 Update the repository's working directory to the specified
6274 Update the repository's working directory to the specified
6272 changeset. If no changeset is specified, update to the tip of the
6275 changeset. If no changeset is specified, update to the tip of the
6273 current named branch and move the current bookmark (see :hg:`help
6276 current named branch and move the current bookmark (see :hg:`help
6274 bookmarks`).
6277 bookmarks`).
6275
6278
6276 Update sets the working directory's parent revision to the specified
6279 Update sets the working directory's parent revision to the specified
6277 changeset (see :hg:`help parents`).
6280 changeset (see :hg:`help parents`).
6278
6281
6279 If the changeset is not a descendant or ancestor of the working
6282 If the changeset is not a descendant or ancestor of the working
6280 directory's parent, the update is aborted. With the -c/--check
6283 directory's parent, the update is aborted. With the -c/--check
6281 option, the working directory is checked for uncommitted changes; if
6284 option, the working directory is checked for uncommitted changes; if
6282 none are found, the working directory is updated to the specified
6285 none are found, the working directory is updated to the specified
6283 changeset.
6286 changeset.
6284
6287
6285 .. container:: verbose
6288 .. container:: verbose
6286
6289
6287 The following rules apply when the working directory contains
6290 The following rules apply when the working directory contains
6288 uncommitted changes:
6291 uncommitted changes:
6289
6292
6290 1. If neither -c/--check nor -C/--clean is specified, and if
6293 1. If neither -c/--check nor -C/--clean is specified, and if
6291 the requested changeset is an ancestor or descendant of
6294 the requested changeset is an ancestor or descendant of
6292 the working directory's parent, the uncommitted changes
6295 the working directory's parent, the uncommitted changes
6293 are merged into the requested changeset and the merged
6296 are merged into the requested changeset and the merged
6294 result is left uncommitted. If the requested changeset is
6297 result is left uncommitted. If the requested changeset is
6295 not an ancestor or descendant (that is, it is on another
6298 not an ancestor or descendant (that is, it is on another
6296 branch), the update is aborted and the uncommitted changes
6299 branch), the update is aborted and the uncommitted changes
6297 are preserved.
6300 are preserved.
6298
6301
6299 2. With the -c/--check option, the update is aborted and the
6302 2. With the -c/--check option, the update is aborted and the
6300 uncommitted changes are preserved.
6303 uncommitted changes are preserved.
6301
6304
6302 3. With the -C/--clean option, uncommitted changes are discarded and
6305 3. With the -C/--clean option, uncommitted changes are discarded and
6303 the working directory is updated to the requested changeset.
6306 the working directory is updated to the requested changeset.
6304
6307
6305 To cancel an uncommitted merge (and lose your changes), use
6308 To cancel an uncommitted merge (and lose your changes), use
6306 :hg:`update --clean .`.
6309 :hg:`update --clean .`.
6307
6310
6308 Use null as the changeset to remove the working directory (like
6311 Use null as the changeset to remove the working directory (like
6309 :hg:`clone -U`).
6312 :hg:`clone -U`).
6310
6313
6311 If you want to revert just one file to an older revision, use
6314 If you want to revert just one file to an older revision, use
6312 :hg:`revert [-r REV] NAME`.
6315 :hg:`revert [-r REV] NAME`.
6313
6316
6314 See :hg:`help dates` for a list of formats valid for -d/--date.
6317 See :hg:`help dates` for a list of formats valid for -d/--date.
6315
6318
6316 Returns 0 on success, 1 if there are unresolved files.
6319 Returns 0 on success, 1 if there are unresolved files.
6317 """
6320 """
6318 if rev and node:
6321 if rev and node:
6319 raise util.Abort(_("please specify just one revision"))
6322 raise util.Abort(_("please specify just one revision"))
6320
6323
6321 if rev is None or rev == '':
6324 if rev is None or rev == '':
6322 rev = node
6325 rev = node
6323
6326
6324 cmdutil.clearunfinished(repo)
6327 cmdutil.clearunfinished(repo)
6325
6328
6326 # with no argument, we also move the current bookmark, if any
6329 # with no argument, we also move the current bookmark, if any
6327 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6330 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6328
6331
6329 # if we defined a bookmark, we have to remember the original bookmark name
6332 # if we defined a bookmark, we have to remember the original bookmark name
6330 brev = rev
6333 brev = rev
6331 rev = scmutil.revsingle(repo, rev, rev).rev()
6334 rev = scmutil.revsingle(repo, rev, rev).rev()
6332
6335
6333 if check and clean:
6336 if check and clean:
6334 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6337 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6335
6338
6336 if date:
6339 if date:
6337 if rev is not None:
6340 if rev is not None:
6338 raise util.Abort(_("you can't specify a revision and a date"))
6341 raise util.Abort(_("you can't specify a revision and a date"))
6339 rev = cmdutil.finddate(ui, repo, date)
6342 rev = cmdutil.finddate(ui, repo, date)
6340
6343
6341 if check:
6344 if check:
6342 cmdutil.bailifchanged(repo, merge=False)
6345 cmdutil.bailifchanged(repo, merge=False)
6343 if rev is None:
6346 if rev is None:
6344 rev = repo[repo[None].branch()].rev()
6347 rev = repo[repo[None].branch()].rev()
6345
6348
6346 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6349 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6347
6350
6348 if clean:
6351 if clean:
6349 ret = hg.clean(repo, rev)
6352 ret = hg.clean(repo, rev)
6350 else:
6353 else:
6351 ret = hg.update(repo, rev)
6354 ret = hg.update(repo, rev)
6352
6355
6353 if not ret and movemarkfrom:
6356 if not ret and movemarkfrom:
6354 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6357 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6355 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6358 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6356 elif brev in repo._bookmarks:
6359 elif brev in repo._bookmarks:
6357 bookmarks.setcurrent(repo, brev)
6360 bookmarks.setcurrent(repo, brev)
6358 ui.status(_("(activating bookmark %s)\n") % brev)
6361 ui.status(_("(activating bookmark %s)\n") % brev)
6359 elif brev:
6362 elif brev:
6360 if repo._bookmarkcurrent:
6363 if repo._bookmarkcurrent:
6361 ui.status(_("(leaving bookmark %s)\n") %
6364 ui.status(_("(leaving bookmark %s)\n") %
6362 repo._bookmarkcurrent)
6365 repo._bookmarkcurrent)
6363 bookmarks.unsetcurrent(repo)
6366 bookmarks.unsetcurrent(repo)
6364
6367
6365 return ret
6368 return ret
6366
6369
6367 @command('verify', [])
6370 @command('verify', [])
6368 def verify(ui, repo):
6371 def verify(ui, repo):
6369 """verify the integrity of the repository
6372 """verify the integrity of the repository
6370
6373
6371 Verify the integrity of the current repository.
6374 Verify the integrity of the current repository.
6372
6375
6373 This will perform an extensive check of the repository's
6376 This will perform an extensive check of the repository's
6374 integrity, validating the hashes and checksums of each entry in
6377 integrity, validating the hashes and checksums of each entry in
6375 the changelog, manifest, and tracked files, as well as the
6378 the changelog, manifest, and tracked files, as well as the
6376 integrity of their crosslinks and indices.
6379 integrity of their crosslinks and indices.
6377
6380
6378 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6381 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6379 for more information about recovery from corruption of the
6382 for more information about recovery from corruption of the
6380 repository.
6383 repository.
6381
6384
6382 Returns 0 on success, 1 if errors are encountered.
6385 Returns 0 on success, 1 if errors are encountered.
6383 """
6386 """
6384 return hg.verify(repo)
6387 return hg.verify(repo)
6385
6388
6386 @command('version', [], norepo=True)
6389 @command('version', [], norepo=True)
6387 def version_(ui):
6390 def version_(ui):
6388 """output version and copyright information"""
6391 """output version and copyright information"""
6389 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6392 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6390 % util.version())
6393 % util.version())
6391 ui.status(_(
6394 ui.status(_(
6392 "(see http://mercurial.selenic.com for more information)\n"
6395 "(see http://mercurial.selenic.com for more information)\n"
6393 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6396 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6394 "This is free software; see the source for copying conditions. "
6397 "This is free software; see the source for copying conditions. "
6395 "There is NO\nwarranty; "
6398 "There is NO\nwarranty; "
6396 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6399 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6397 ))
6400 ))
6398
6401
6399 ui.note(_("\nEnabled extensions:\n\n"))
6402 ui.note(_("\nEnabled extensions:\n\n"))
6400 if ui.verbose:
6403 if ui.verbose:
6401 # format names and versions into columns
6404 # format names and versions into columns
6402 names = []
6405 names = []
6403 vers = []
6406 vers = []
6404 for name, module in extensions.extensions():
6407 for name, module in extensions.extensions():
6405 names.append(name)
6408 names.append(name)
6406 vers.append(extensions.moduleversion(module))
6409 vers.append(extensions.moduleversion(module))
6407 if names:
6410 if names:
6408 maxnamelen = max(len(n) for n in names)
6411 maxnamelen = max(len(n) for n in names)
6409 for i, name in enumerate(names):
6412 for i, name in enumerate(names):
6410 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6413 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,758 +1,773 b''
1 Create a repo with some stuff in it:
1 Create a repo with some stuff in it:
2
2
3 $ hg init a
3 $ hg init a
4 $ cd a
4 $ cd a
5 $ echo a > a
5 $ echo a > a
6 $ echo a > d
6 $ echo a > d
7 $ echo a > e
7 $ echo a > e
8 $ hg ci -qAm0
8 $ hg ci -qAm0
9 $ echo b > a
9 $ echo b > a
10 $ hg ci -m1 -u bar
10 $ hg ci -m1 -u bar
11 $ hg mv a b
11 $ hg mv a b
12 $ hg ci -m2
12 $ hg ci -m2
13 $ hg cp b c
13 $ hg cp b c
14 $ hg ci -m3 -u baz
14 $ hg ci -m3 -u baz
15 $ echo b > d
15 $ echo b > d
16 $ echo f > e
16 $ echo f > e
17 $ hg ci -m4
17 $ hg ci -m4
18 $ hg up -q 3
18 $ hg up -q 3
19 $ echo b > e
19 $ echo b > e
20 $ hg branch -q stable
20 $ hg branch -q stable
21 $ hg ci -m5
21 $ hg ci -m5
22 $ hg merge -q default --tool internal:local
22 $ hg merge -q default --tool internal:local
23 $ hg branch -q default
23 $ hg branch -q default
24 $ hg ci -m6
24 $ hg ci -m6
25 $ hg phase --public 3
25 $ hg phase --public 3
26 $ hg phase --force --secret 6
26 $ hg phase --force --secret 6
27
27
28 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
28 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
29 @ test@6.secret: 6
29 @ test@6.secret: 6
30 |\
30 |\
31 | o test@5.draft: 5
31 | o test@5.draft: 5
32 | |
32 | |
33 o | test@4.draft: 4
33 o | test@4.draft: 4
34 |/
34 |/
35 o baz@3.public: 3
35 o baz@3.public: 3
36 |
36 |
37 o test@2.public: 2
37 o test@2.public: 2
38 |
38 |
39 o bar@1.public: 1
39 o bar@1.public: 1
40 |
40 |
41 o test@0.public: 0
41 o test@0.public: 0
42
42
43
43
44 Need to specify a rev:
44 Need to specify a rev:
45
45
46 $ hg graft
46 $ hg graft
47 abort: no revisions specified
47 abort: no revisions specified
48 [255]
48 [255]
49
49
50 Can't graft ancestor:
50 Can't graft ancestor:
51
51
52 $ hg graft 1 2
52 $ hg graft 1 2
53 skipping ancestor revision 1:5d205f8b35b6
53 skipping ancestor revision 1:5d205f8b35b6
54 skipping ancestor revision 2:5c095ad7e90f
54 skipping ancestor revision 2:5c095ad7e90f
55 [255]
55 [255]
56
56
57 Specify revisions with -r:
57 Specify revisions with -r:
58
58
59 $ hg graft -r 1 -r 2
59 $ hg graft -r 1 -r 2
60 skipping ancestor revision 1:5d205f8b35b6
60 skipping ancestor revision 1:5d205f8b35b6
61 skipping ancestor revision 2:5c095ad7e90f
61 skipping ancestor revision 2:5c095ad7e90f
62 [255]
62 [255]
63
63
64 $ hg graft -r 1 2
64 $ hg graft -r 1 2
65 skipping ancestor revision 2:5c095ad7e90f
65 skipping ancestor revision 2:5c095ad7e90f
66 skipping ancestor revision 1:5d205f8b35b6
66 skipping ancestor revision 1:5d205f8b35b6
67 [255]
67 [255]
68
68
69 Can't graft with dirty wd:
69 Can't graft with dirty wd:
70
70
71 $ hg up -q 0
71 $ hg up -q 0
72 $ echo foo > a
72 $ echo foo > a
73 $ hg graft 1
73 $ hg graft 1
74 abort: uncommitted changes
74 abort: uncommitted changes
75 [255]
75 [255]
76 $ hg revert a
76 $ hg revert a
77
77
78 Graft a rename:
78 Graft a rename:
79 (this also tests that editor is invoked if '--edit' is specified)
79 (this also tests that editor is invoked if '--edit' is specified)
80
80
81 $ hg status --rev "2^1" --rev 2
81 $ hg status --rev "2^1" --rev 2
82 A b
82 A b
83 R a
83 R a
84 $ HGEDITOR=cat hg graft 2 -u foo --edit
84 $ HGEDITOR=cat hg graft 2 -u foo --edit
85 grafting 2:5c095ad7e90f "2"
85 grafting 2:5c095ad7e90f "2"
86 merging a and b to b
86 merging a and b to b
87 2
87 2
88
88
89
89
90 HG: Enter commit message. Lines beginning with 'HG:' are removed.
90 HG: Enter commit message. Lines beginning with 'HG:' are removed.
91 HG: Leave message empty to abort commit.
91 HG: Leave message empty to abort commit.
92 HG: --
92 HG: --
93 HG: user: foo
93 HG: user: foo
94 HG: branch 'default'
94 HG: branch 'default'
95 HG: added b
95 HG: added b
96 HG: removed a
96 HG: removed a
97 $ hg export tip --git
97 $ hg export tip --git
98 # HG changeset patch
98 # HG changeset patch
99 # User foo
99 # User foo
100 # Date 0 0
100 # Date 0 0
101 # Thu Jan 01 00:00:00 1970 +0000
101 # Thu Jan 01 00:00:00 1970 +0000
102 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
102 # Node ID ef0ef43d49e79e81ddafdc7997401ba0041efc82
103 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
103 # Parent 68795b066622ca79a25816a662041d8f78f3cd9e
104 2
104 2
105
105
106 diff --git a/a b/b
106 diff --git a/a b/b
107 rename from a
107 rename from a
108 rename to b
108 rename to b
109
109
110 Look for extra:source
110 Look for extra:source
111
111
112 $ hg log --debug -r tip
112 $ hg log --debug -r tip
113 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
113 changeset: 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
114 tag: tip
114 tag: tip
115 phase: draft
115 phase: draft
116 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
116 parent: 0:68795b066622ca79a25816a662041d8f78f3cd9e
117 parent: -1:0000000000000000000000000000000000000000
117 parent: -1:0000000000000000000000000000000000000000
118 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
118 manifest: 7:e59b6b228f9cbf9903d5e9abf996e083a1f533eb
119 user: foo
119 user: foo
120 date: Thu Jan 01 00:00:00 1970 +0000
120 date: Thu Jan 01 00:00:00 1970 +0000
121 files+: b
121 files+: b
122 files-: a
122 files-: a
123 extra: branch=default
123 extra: branch=default
124 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
124 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
125 description:
125 description:
126 2
126 2
127
127
128
128
129
129
130 Graft out of order, skipping a merge and a duplicate
130 Graft out of order, skipping a merge and a duplicate
131 (this also tests that editor is not invoked if '--edit' is not specified)
131 (this also tests that editor is not invoked if '--edit' is not specified)
132
132
133 $ hg graft 1 5 4 3 'merge()' 2 -n
133 $ hg graft 1 5 4 3 'merge()' 2 -n
134 skipping ungraftable merge revision 6
134 skipping ungraftable merge revision 6
135 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
135 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
136 grafting 1:5d205f8b35b6 "1"
136 grafting 1:5d205f8b35b6 "1"
137 grafting 5:97f8bfe72746 "5"
137 grafting 5:97f8bfe72746 "5"
138 grafting 4:9c233e8e184d "4"
138 grafting 4:9c233e8e184d "4"
139 grafting 3:4c60f11aa304 "3"
139 grafting 3:4c60f11aa304 "3"
140
140
141 $ HGEDITOR=cat hg graft 1 5 4 3 'merge()' 2 --debug
141 $ HGEDITOR=cat hg graft 1 5 4 3 'merge()' 2 --debug
142 skipping ungraftable merge revision 6
142 skipping ungraftable merge revision 6
143 scanning for duplicate grafts
143 scanning for duplicate grafts
144 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
144 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
145 grafting 1:5d205f8b35b6 "1"
145 grafting 1:5d205f8b35b6 "1"
146 searching for copies back to rev 1
146 searching for copies back to rev 1
147 unmatched files in local:
147 unmatched files in local:
148 b
148 b
149 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
149 all copies found (* = to merge, ! = divergent, % = renamed and deleted):
150 src: 'a' -> dst: 'b' *
150 src: 'a' -> dst: 'b' *
151 checking for directory renames
151 checking for directory renames
152 resolving manifests
152 resolving manifests
153 branchmerge: True, force: True, partial: False
153 branchmerge: True, force: True, partial: False
154 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
154 ancestor: 68795b066622, local: ef0ef43d49e7+, remote: 5d205f8b35b6
155 preserving b for resolve of b
155 preserving b for resolve of b
156 b: local copied/moved from a -> m
156 b: local copied/moved from a -> m
157 updating: b 1/1 files (100.00%)
157 updating: b 1/1 files (100.00%)
158 picked tool 'internal:merge' for b (binary False symlink False)
158 picked tool 'internal:merge' for b (binary False symlink False)
159 merging b and a to b
159 merging b and a to b
160 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
160 my b@ef0ef43d49e7+ other a@5d205f8b35b6 ancestor a@68795b066622
161 premerge successful
161 premerge successful
162 committing files:
162 committing files:
163 b
163 b
164 committing manifest
164 committing manifest
165 committing changelog
165 committing changelog
166 grafting 5:97f8bfe72746 "5"
166 grafting 5:97f8bfe72746 "5"
167 searching for copies back to rev 1
167 searching for copies back to rev 1
168 resolving manifests
168 resolving manifests
169 branchmerge: True, force: True, partial: False
169 branchmerge: True, force: True, partial: False
170 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
170 ancestor: 4c60f11aa304, local: 6b9e5368ca4e+, remote: 97f8bfe72746
171 e: remote is newer -> g
171 e: remote is newer -> g
172 getting e
172 getting e
173 updating: e 1/1 files (100.00%)
173 updating: e 1/1 files (100.00%)
174 b: remote unchanged -> k
174 b: remote unchanged -> k
175 committing files:
175 committing files:
176 e
176 e
177 committing manifest
177 committing manifest
178 committing changelog
178 committing changelog
179 grafting 4:9c233e8e184d "4"
179 grafting 4:9c233e8e184d "4"
180 searching for copies back to rev 1
180 searching for copies back to rev 1
181 resolving manifests
181 resolving manifests
182 branchmerge: True, force: True, partial: False
182 branchmerge: True, force: True, partial: False
183 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
183 ancestor: 4c60f11aa304, local: 1905859650ec+, remote: 9c233e8e184d
184 preserving e for resolve of e
184 preserving e for resolve of e
185 d: remote is newer -> g
185 d: remote is newer -> g
186 getting d
186 getting d
187 updating: d 1/2 files (50.00%)
187 updating: d 1/2 files (50.00%)
188 b: remote unchanged -> k
188 b: remote unchanged -> k
189 e: versions differ -> m
189 e: versions differ -> m
190 updating: e 2/2 files (100.00%)
190 updating: e 2/2 files (100.00%)
191 picked tool 'internal:merge' for e (binary False symlink False)
191 picked tool 'internal:merge' for e (binary False symlink False)
192 merging e
192 merging e
193 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
193 my e@1905859650ec+ other e@9c233e8e184d ancestor e@68795b066622
194 warning: conflicts during merge.
194 warning: conflicts during merge.
195 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
195 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
196 abort: unresolved conflicts, can't continue
196 abort: unresolved conflicts, can't continue
197 (use hg resolve and hg graft --continue)
197 (use hg resolve and hg graft --continue)
198 [255]
198 [255]
199
199
200 Commit while interrupted should fail:
200 Commit while interrupted should fail:
201
201
202 $ hg ci -m 'commit interrupted graft'
202 $ hg ci -m 'commit interrupted graft'
203 abort: graft in progress
203 abort: graft in progress
204 (use 'hg graft --continue' or 'hg update' to abort)
204 (use 'hg graft --continue' or 'hg update' to abort)
205 [255]
205 [255]
206
206
207 Abort the graft and try committing:
207 Abort the graft and try committing:
208
208
209 $ hg up -C .
209 $ hg up -C .
210 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
210 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
211 $ echo c >> e
211 $ echo c >> e
212 $ hg ci -mtest
212 $ hg ci -mtest
213
213
214 $ hg strip . --config extensions.strip=
214 $ hg strip . --config extensions.strip=
215 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
215 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
216 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
216 saved backup bundle to $TESTTMP/a/.hg/strip-backup/*-backup.hg (glob)
217
217
218 Graft again:
218 Graft again:
219
219
220 $ hg graft 1 5 4 3 'merge()' 2
220 $ hg graft 1 5 4 3 'merge()' 2
221 skipping ungraftable merge revision 6
221 skipping ungraftable merge revision 6
222 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
222 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
223 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
223 skipping revision 1:5d205f8b35b6 (already grafted to 8:6b9e5368ca4e)
224 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
224 skipping revision 5:97f8bfe72746 (already grafted to 9:1905859650ec)
225 grafting 4:9c233e8e184d "4"
225 grafting 4:9c233e8e184d "4"
226 merging e
226 merging e
227 warning: conflicts during merge.
227 warning: conflicts during merge.
228 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
228 merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
229 abort: unresolved conflicts, can't continue
229 abort: unresolved conflicts, can't continue
230 (use hg resolve and hg graft --continue)
230 (use hg resolve and hg graft --continue)
231 [255]
231 [255]
232
232
233 Continue without resolve should fail:
233 Continue without resolve should fail:
234
234
235 $ hg graft -c
235 $ hg graft -c
236 grafting 4:9c233e8e184d "4"
236 grafting 4:9c233e8e184d "4"
237 abort: unresolved merge conflicts (see "hg help resolve")
237 abort: unresolved merge conflicts (see "hg help resolve")
238 [255]
238 [255]
239
239
240 Fix up:
240 Fix up:
241
241
242 $ echo b > e
242 $ echo b > e
243 $ hg resolve -m e
243 $ hg resolve -m e
244 (no more unresolved files)
244 (no more unresolved files)
245
245
246 Continue with a revision should fail:
246 Continue with a revision should fail:
247
247
248 $ hg graft -c 6
248 $ hg graft -c 6
249 abort: can't specify --continue and revisions
249 abort: can't specify --continue and revisions
250 [255]
250 [255]
251
251
252 $ hg graft -c -r 6
252 $ hg graft -c -r 6
253 abort: can't specify --continue and revisions
253 abort: can't specify --continue and revisions
254 [255]
254 [255]
255
255
256 Continue for real, clobber usernames
256 Continue for real, clobber usernames
257
257
258 $ hg graft -c -U
258 $ hg graft -c -U
259 grafting 4:9c233e8e184d "4"
259 grafting 4:9c233e8e184d "4"
260 grafting 3:4c60f11aa304 "3"
260 grafting 3:4c60f11aa304 "3"
261
261
262 Compare with original:
262 Compare with original:
263
263
264 $ hg diff -r 6
264 $ hg diff -r 6
265 $ hg status --rev 0:. -C
265 $ hg status --rev 0:. -C
266 M d
266 M d
267 M e
267 M e
268 A b
268 A b
269 a
269 a
270 A c
270 A c
271 a
271 a
272 R a
272 R a
273
273
274 View graph:
274 View graph:
275
275
276 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
276 $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
277 @ test@11.draft: 3
277 @ test@11.draft: 3
278 |
278 |
279 o test@10.draft: 4
279 o test@10.draft: 4
280 |
280 |
281 o test@9.draft: 5
281 o test@9.draft: 5
282 |
282 |
283 o bar@8.draft: 1
283 o bar@8.draft: 1
284 |
284 |
285 o foo@7.draft: 2
285 o foo@7.draft: 2
286 |
286 |
287 | o test@6.secret: 6
287 | o test@6.secret: 6
288 | |\
288 | |\
289 | | o test@5.draft: 5
289 | | o test@5.draft: 5
290 | | |
290 | | |
291 | o | test@4.draft: 4
291 | o | test@4.draft: 4
292 | |/
292 | |/
293 | o baz@3.public: 3
293 | o baz@3.public: 3
294 | |
294 | |
295 | o test@2.public: 2
295 | o test@2.public: 2
296 | |
296 | |
297 | o bar@1.public: 1
297 | o bar@1.public: 1
298 |/
298 |/
299 o test@0.public: 0
299 o test@0.public: 0
300
300
301 Graft again onto another branch should preserve the original source
301 Graft again onto another branch should preserve the original source
302 $ hg up -q 0
302 $ hg up -q 0
303 $ echo 'g'>g
303 $ echo 'g'>g
304 $ hg add g
304 $ hg add g
305 $ hg ci -m 7
305 $ hg ci -m 7
306 created new head
306 created new head
307 $ hg graft 7
307 $ hg graft 7
308 grafting 7:ef0ef43d49e7 "2"
308 grafting 7:ef0ef43d49e7 "2"
309
309
310 $ hg log -r 7 --template '{rev}:{node}\n'
310 $ hg log -r 7 --template '{rev}:{node}\n'
311 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
311 7:ef0ef43d49e79e81ddafdc7997401ba0041efc82
312 $ hg log -r 2 --template '{rev}:{node}\n'
312 $ hg log -r 2 --template '{rev}:{node}\n'
313 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
313 2:5c095ad7e90f871700f02dd1fa5012cb4498a2d4
314
314
315 $ hg log --debug -r tip
315 $ hg log --debug -r tip
316 changeset: 13:9db0f28fd3747e92c57d015f53b5593aeec53c2d
316 changeset: 13:7a4785234d87ec1aa420ed6b11afe40fa73e12a9
317 tag: tip
317 tag: tip
318 phase: draft
318 phase: draft
319 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
319 parent: 12:b592ea63bb0c19a6c5c44685ee29a2284f9f1b8f
320 parent: -1:0000000000000000000000000000000000000000
320 parent: -1:0000000000000000000000000000000000000000
321 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
321 manifest: 13:dc313617b8c32457c0d589e0dbbedfe71f3cd637
322 user: foo
322 user: foo
323 date: Thu Jan 01 00:00:00 1970 +0000
323 date: Thu Jan 01 00:00:00 1970 +0000
324 files+: b
324 files+: b
325 files-: a
325 files-: a
326 extra: branch=default
326 extra: branch=default
327 extra: intermediate-source=ef0ef43d49e79e81ddafdc7997401ba0041efc82
327 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
328 extra: source=5c095ad7e90f871700f02dd1fa5012cb4498a2d4
328 description:
329 description:
329 2
330 2
330
331
331
332
332 Disallow grafting an already grafted cset onto its original branch
333 Disallow grafting an already grafted cset onto its original branch
333 $ hg up -q 6
334 $ hg up -q 6
334 $ hg graft 7
335 $ hg graft 7
335 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
336 skipping already grafted revision 7:ef0ef43d49e7 (was grafted from 2:5c095ad7e90f)
336 [255]
337 [255]
337
338
338 Disallow grafting already grafted csets with the same origin onto each other
339 Disallow grafting already grafted csets with the same origin onto each other
339 $ hg up -q 13
340 $ hg up -q 13
340 $ hg graft 2
341 $ hg graft 2
341 skipping revision 2:5c095ad7e90f (already grafted to 13:9db0f28fd374)
342 skipping revision 2:5c095ad7e90f (already grafted to 13:7a4785234d87)
342 [255]
343 [255]
343 $ hg graft 7
344 $ hg graft 7
344 skipping already grafted revision 7:ef0ef43d49e7 (13:9db0f28fd374 also has origin 2:5c095ad7e90f)
345 skipping already grafted revision 7:ef0ef43d49e7 (13:7a4785234d87 also has origin 2:5c095ad7e90f)
345 [255]
346 [255]
346
347
347 $ hg up -q 7
348 $ hg up -q 7
348 $ hg graft 2
349 $ hg graft 2
349 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
350 skipping revision 2:5c095ad7e90f (already grafted to 7:ef0ef43d49e7)
350 [255]
351 [255]
351 $ hg graft tip
352 $ hg graft tip
352 skipping already grafted revision 13:9db0f28fd374 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
353 skipping already grafted revision 13:7a4785234d87 (7:ef0ef43d49e7 also has origin 2:5c095ad7e90f)
353 [255]
354 [255]
354
355
355 Graft with --log
356 Graft with --log
356
357
357 $ hg up -Cq 1
358 $ hg up -Cq 1
358 $ hg graft 3 --log -u foo
359 $ hg graft 3 --log -u foo
359 grafting 3:4c60f11aa304 "3"
360 grafting 3:4c60f11aa304 "3"
360 warning: can't find ancestor for 'c' copied from 'b'!
361 warning: can't find ancestor for 'c' copied from 'b'!
361 $ hg log --template '{rev} {parents} {desc}\n' -r tip
362 $ hg log --template '{rev} {parents} {desc}\n' -r tip
362 14 1:5d205f8b35b6 3
363 14 1:5d205f8b35b6 3
363 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
364 (grafted from 4c60f11aa304a54ae1c199feb94e7fc771e51ed8)
364
365
365 Resolve conflicted graft
366 Resolve conflicted graft
366 $ hg up -q 0
367 $ hg up -q 0
367 $ echo b > a
368 $ echo b > a
368 $ hg ci -m 8
369 $ hg ci -m 8
369 created new head
370 created new head
370 $ echo c > a
371 $ echo c > a
371 $ hg ci -m 9
372 $ hg ci -m 9
372 $ hg graft 1 --tool internal:fail
373 $ hg graft 1 --tool internal:fail
373 grafting 1:5d205f8b35b6 "1"
374 grafting 1:5d205f8b35b6 "1"
374 abort: unresolved conflicts, can't continue
375 abort: unresolved conflicts, can't continue
375 (use hg resolve and hg graft --continue)
376 (use hg resolve and hg graft --continue)
376 [255]
377 [255]
377 $ hg resolve --all
378 $ hg resolve --all
378 merging a
379 merging a
379 warning: conflicts during merge.
380 warning: conflicts during merge.
380 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
381 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
381 [1]
382 [1]
382 $ cat a
383 $ cat a
383 <<<<<<< local: aaa4406d4f0a - test: 9
384 <<<<<<< local: aaa4406d4f0a - test: 9
384 c
385 c
385 =======
386 =======
386 b
387 b
387 >>>>>>> other: 5d205f8b35b6 - bar: 1
388 >>>>>>> other: 5d205f8b35b6 - bar: 1
388 $ echo b > a
389 $ echo b > a
389 $ hg resolve -m a
390 $ hg resolve -m a
390 (no more unresolved files)
391 (no more unresolved files)
391 $ hg graft -c
392 $ hg graft -c
392 grafting 1:5d205f8b35b6 "1"
393 grafting 1:5d205f8b35b6 "1"
393 $ hg export tip --git
394 $ hg export tip --git
394 # HG changeset patch
395 # HG changeset patch
395 # User bar
396 # User bar
396 # Date 0 0
397 # Date 0 0
397 # Thu Jan 01 00:00:00 1970 +0000
398 # Thu Jan 01 00:00:00 1970 +0000
398 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
399 # Node ID f67661df0c4804d301f064f332b57e7d5ddaf2be
399 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
400 # Parent aaa4406d4f0ae9befd6e58c82ec63706460cbca6
400 1
401 1
401
402
402 diff --git a/a b/a
403 diff --git a/a b/a
403 --- a/a
404 --- a/a
404 +++ b/a
405 +++ b/a
405 @@ -1,1 +1,1 @@
406 @@ -1,1 +1,1 @@
406 -c
407 -c
407 +b
408 +b
408
409
409 Resolve conflicted graft with rename
410 Resolve conflicted graft with rename
410 $ echo c > a
411 $ echo c > a
411 $ hg ci -m 10
412 $ hg ci -m 10
412 $ hg graft 2 --tool internal:fail
413 $ hg graft 2 --tool internal:fail
413 grafting 2:5c095ad7e90f "2"
414 grafting 2:5c095ad7e90f "2"
414 abort: unresolved conflicts, can't continue
415 abort: unresolved conflicts, can't continue
415 (use hg resolve and hg graft --continue)
416 (use hg resolve and hg graft --continue)
416 [255]
417 [255]
417 $ hg resolve --all
418 $ hg resolve --all
418 merging a and b to b
419 merging a and b to b
419 (no more unresolved files)
420 (no more unresolved files)
420 $ hg graft -c
421 $ hg graft -c
421 grafting 2:5c095ad7e90f "2"
422 grafting 2:5c095ad7e90f "2"
422 $ hg export tip --git
423 $ hg export tip --git
423 # HG changeset patch
424 # HG changeset patch
424 # User test
425 # User test
425 # Date 0 0
426 # Date 0 0
426 # Thu Jan 01 00:00:00 1970 +0000
427 # Thu Jan 01 00:00:00 1970 +0000
427 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
428 # Node ID 9627f653b421c61fc1ea4c4e366745070fa3d2bc
428 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
429 # Parent ee295f490a40b97f3d18dd4c4f1c8936c233b612
429 2
430 2
430
431
431 diff --git a/a b/b
432 diff --git a/a b/b
432 rename from a
433 rename from a
433 rename to b
434 rename to b
434
435
435 Test simple origin(), with and without args
436 Test simple origin(), with and without args
436 $ hg log -r 'origin()'
437 $ hg log -r 'origin()'
437 changeset: 1:5d205f8b35b6
438 changeset: 1:5d205f8b35b6
438 user: bar
439 user: bar
439 date: Thu Jan 01 00:00:00 1970 +0000
440 date: Thu Jan 01 00:00:00 1970 +0000
440 summary: 1
441 summary: 1
441
442
442 changeset: 2:5c095ad7e90f
443 changeset: 2:5c095ad7e90f
443 user: test
444 user: test
444 date: Thu Jan 01 00:00:00 1970 +0000
445 date: Thu Jan 01 00:00:00 1970 +0000
445 summary: 2
446 summary: 2
446
447
447 changeset: 3:4c60f11aa304
448 changeset: 3:4c60f11aa304
448 user: baz
449 user: baz
449 date: Thu Jan 01 00:00:00 1970 +0000
450 date: Thu Jan 01 00:00:00 1970 +0000
450 summary: 3
451 summary: 3
451
452
452 changeset: 4:9c233e8e184d
453 changeset: 4:9c233e8e184d
453 user: test
454 user: test
454 date: Thu Jan 01 00:00:00 1970 +0000
455 date: Thu Jan 01 00:00:00 1970 +0000
455 summary: 4
456 summary: 4
456
457
457 changeset: 5:97f8bfe72746
458 changeset: 5:97f8bfe72746
458 branch: stable
459 branch: stable
459 parent: 3:4c60f11aa304
460 parent: 3:4c60f11aa304
460 user: test
461 user: test
461 date: Thu Jan 01 00:00:00 1970 +0000
462 date: Thu Jan 01 00:00:00 1970 +0000
462 summary: 5
463 summary: 5
463
464
464 $ hg log -r 'origin(7)'
465 $ hg log -r 'origin(7)'
465 changeset: 2:5c095ad7e90f
466 changeset: 2:5c095ad7e90f
466 user: test
467 user: test
467 date: Thu Jan 01 00:00:00 1970 +0000
468 date: Thu Jan 01 00:00:00 1970 +0000
468 summary: 2
469 summary: 2
469
470
470 Now transplant a graft to test following through copies
471 Now transplant a graft to test following through copies
471 $ hg up -q 0
472 $ hg up -q 0
472 $ hg branch -q dev
473 $ hg branch -q dev
473 $ hg ci -qm "dev branch"
474 $ hg ci -qm "dev branch"
474 $ hg --config extensions.transplant= transplant -q 7
475 $ hg --config extensions.transplant= transplant -q 7
475 $ hg log -r 'origin(.)'
476 $ hg log -r 'origin(.)'
476 changeset: 2:5c095ad7e90f
477 changeset: 2:5c095ad7e90f
477 user: test
478 user: test
478 date: Thu Jan 01 00:00:00 1970 +0000
479 date: Thu Jan 01 00:00:00 1970 +0000
479 summary: 2
480 summary: 2
480
481
481 Test that the graft and transplant markers in extra are converted, allowing
482 Test that the graft and transplant markers in extra are converted, allowing
482 origin() to still work. Note that these recheck the immediately preceeding two
483 origin() to still work. Note that these recheck the immediately preceeding two
483 tests.
484 tests.
484 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
485 $ hg --quiet --config extensions.convert= --config convert.hg.saverev=True convert . ../converted
485
486
486 The graft case
487 The graft case
487 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
488 $ hg -R ../converted log -r 7 --template "{rev}: {node}\n{join(extras, '\n')}\n"
488 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
489 7: 7ae846e9111fc8f57745634250c7b9ac0a60689b
489 branch=default
490 branch=default
490 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
491 convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
491 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
492 source=e0213322b2c1a5d5d236c74e79666441bee67a7d
492 $ hg -R ../converted log -r 'origin(7)'
493 $ hg -R ../converted log -r 'origin(7)'
493 changeset: 2:e0213322b2c1
494 changeset: 2:e0213322b2c1
494 user: test
495 user: test
495 date: Thu Jan 01 00:00:00 1970 +0000
496 date: Thu Jan 01 00:00:00 1970 +0000
496 summary: 2
497 summary: 2
497
498
498 Test that template correctly expands more than one 'extra' (issue4362)
499 Test that template correctly expands more than one 'extra' (issue4362)
499 $ hg -R ../converted log -r 7 --template "{extras % ' Extra: {extra}\n'}"
500 $ hg -R ../converted log -r 7 --template "{extras % ' Extra: {extra}\n'}"
500 Extra: branch=default
501 Extra: branch=default
501 Extra: convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
502 Extra: convert_revision=ef0ef43d49e79e81ddafdc7997401ba0041efc82
502 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
503 Extra: source=e0213322b2c1a5d5d236c74e79666441bee67a7d
503
504
504 The transplant case
505 The transplant case
505 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
506 $ hg -R ../converted log -r tip --template "{rev}: {node}\n{join(extras, '\n')}\n"
506 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
507 21: fbb6c5cc81002f2b4b49c9d731404688bcae5ade
507 branch=dev
508 branch=dev
508 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
509 convert_revision=7e61b508e709a11d28194a5359bc3532d910af21
509 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
510 transplant_source=z\xe8F\xe9\x11\x1f\xc8\xf5wEcBP\xc7\xb9\xac (esc)
510 `h\x9b (esc)
511 `h\x9b (esc)
511 $ hg -R ../converted log -r 'origin(tip)'
512 $ hg -R ../converted log -r 'origin(tip)'
512 changeset: 2:e0213322b2c1
513 changeset: 2:e0213322b2c1
513 user: test
514 user: test
514 date: Thu Jan 01 00:00:00 1970 +0000
515 date: Thu Jan 01 00:00:00 1970 +0000
515 summary: 2
516 summary: 2
516
517
517
518
518 Test simple destination
519 Test simple destination
519 $ hg log -r 'destination()'
520 $ hg log -r 'destination()'
520 changeset: 7:ef0ef43d49e7
521 changeset: 7:ef0ef43d49e7
521 parent: 0:68795b066622
522 parent: 0:68795b066622
522 user: foo
523 user: foo
523 date: Thu Jan 01 00:00:00 1970 +0000
524 date: Thu Jan 01 00:00:00 1970 +0000
524 summary: 2
525 summary: 2
525
526
526 changeset: 8:6b9e5368ca4e
527 changeset: 8:6b9e5368ca4e
527 user: bar
528 user: bar
528 date: Thu Jan 01 00:00:00 1970 +0000
529 date: Thu Jan 01 00:00:00 1970 +0000
529 summary: 1
530 summary: 1
530
531
531 changeset: 9:1905859650ec
532 changeset: 9:1905859650ec
532 user: test
533 user: test
533 date: Thu Jan 01 00:00:00 1970 +0000
534 date: Thu Jan 01 00:00:00 1970 +0000
534 summary: 5
535 summary: 5
535
536
536 changeset: 10:52dc0b4c6907
537 changeset: 10:52dc0b4c6907
537 user: test
538 user: test
538 date: Thu Jan 01 00:00:00 1970 +0000
539 date: Thu Jan 01 00:00:00 1970 +0000
539 summary: 4
540 summary: 4
540
541
541 changeset: 11:882b35362a6b
542 changeset: 11:882b35362a6b
542 user: test
543 user: test
543 date: Thu Jan 01 00:00:00 1970 +0000
544 date: Thu Jan 01 00:00:00 1970 +0000
544 summary: 3
545 summary: 3
545
546
546 changeset: 13:9db0f28fd374
547 changeset: 13:7a4785234d87
547 user: foo
548 user: foo
548 date: Thu Jan 01 00:00:00 1970 +0000
549 date: Thu Jan 01 00:00:00 1970 +0000
549 summary: 2
550 summary: 2
550
551
551 changeset: 14:f64defefacee
552 changeset: 14:f64defefacee
552 parent: 1:5d205f8b35b6
553 parent: 1:5d205f8b35b6
553 user: foo
554 user: foo
554 date: Thu Jan 01 00:00:00 1970 +0000
555 date: Thu Jan 01 00:00:00 1970 +0000
555 summary: 3
556 summary: 3
556
557
557 changeset: 17:f67661df0c48
558 changeset: 17:f67661df0c48
558 user: bar
559 user: bar
559 date: Thu Jan 01 00:00:00 1970 +0000
560 date: Thu Jan 01 00:00:00 1970 +0000
560 summary: 1
561 summary: 1
561
562
562 changeset: 19:9627f653b421
563 changeset: 19:9627f653b421
563 user: test
564 user: test
564 date: Thu Jan 01 00:00:00 1970 +0000
565 date: Thu Jan 01 00:00:00 1970 +0000
565 summary: 2
566 summary: 2
566
567
567 changeset: 21:7e61b508e709
568 changeset: 21:7e61b508e709
568 branch: dev
569 branch: dev
569 tag: tip
570 tag: tip
570 user: foo
571 user: foo
571 date: Thu Jan 01 00:00:00 1970 +0000
572 date: Thu Jan 01 00:00:00 1970 +0000
572 summary: 2
573 summary: 2
573
574
574 $ hg log -r 'destination(2)'
575 $ hg log -r 'destination(2)'
575 changeset: 7:ef0ef43d49e7
576 changeset: 7:ef0ef43d49e7
576 parent: 0:68795b066622
577 parent: 0:68795b066622
577 user: foo
578 user: foo
578 date: Thu Jan 01 00:00:00 1970 +0000
579 date: Thu Jan 01 00:00:00 1970 +0000
579 summary: 2
580 summary: 2
580
581
581 changeset: 13:9db0f28fd374
582 changeset: 13:7a4785234d87
582 user: foo
583 user: foo
583 date: Thu Jan 01 00:00:00 1970 +0000
584 date: Thu Jan 01 00:00:00 1970 +0000
584 summary: 2
585 summary: 2
585
586
586 changeset: 19:9627f653b421
587 changeset: 19:9627f653b421
587 user: test
588 user: test
588 date: Thu Jan 01 00:00:00 1970 +0000
589 date: Thu Jan 01 00:00:00 1970 +0000
589 summary: 2
590 summary: 2
590
591
591 changeset: 21:7e61b508e709
592 changeset: 21:7e61b508e709
592 branch: dev
593 branch: dev
593 tag: tip
594 tag: tip
594 user: foo
595 user: foo
595 date: Thu Jan 01 00:00:00 1970 +0000
596 date: Thu Jan 01 00:00:00 1970 +0000
596 summary: 2
597 summary: 2
597
598
598 Transplants of grafts can find a destination...
599 Transplants of grafts can find a destination...
599 $ hg log -r 'destination(7)'
600 $ hg log -r 'destination(7)'
600 changeset: 21:7e61b508e709
601 changeset: 21:7e61b508e709
601 branch: dev
602 branch: dev
602 tag: tip
603 tag: tip
603 user: foo
604 user: foo
604 date: Thu Jan 01 00:00:00 1970 +0000
605 date: Thu Jan 01 00:00:00 1970 +0000
605 summary: 2
606 summary: 2
606
607
607 ... grafts of grafts unfortunately can't
608 ... grafts of grafts unfortunately can't
608 $ hg graft -q 13
609 $ hg graft -q 13
609 warning: can't find ancestor for 'b' copied from 'a'!
610 warning: can't find ancestor for 'b' copied from 'a'!
610 $ hg log -r 'destination(13)'
611 $ hg log -r 'destination(13)'
611 All copies of a cset
612 All copies of a cset
612 $ hg log -r 'origin(13) or destination(origin(13))'
613 $ hg log -r 'origin(13) or destination(origin(13))'
613 changeset: 2:5c095ad7e90f
614 changeset: 2:5c095ad7e90f
614 user: test
615 user: test
615 date: Thu Jan 01 00:00:00 1970 +0000
616 date: Thu Jan 01 00:00:00 1970 +0000
616 summary: 2
617 summary: 2
617
618
618 changeset: 7:ef0ef43d49e7
619 changeset: 7:ef0ef43d49e7
619 parent: 0:68795b066622
620 parent: 0:68795b066622
620 user: foo
621 user: foo
621 date: Thu Jan 01 00:00:00 1970 +0000
622 date: Thu Jan 01 00:00:00 1970 +0000
622 summary: 2
623 summary: 2
623
624
624 changeset: 13:9db0f28fd374
625 changeset: 13:7a4785234d87
625 user: foo
626 user: foo
626 date: Thu Jan 01 00:00:00 1970 +0000
627 date: Thu Jan 01 00:00:00 1970 +0000
627 summary: 2
628 summary: 2
628
629
629 changeset: 19:9627f653b421
630 changeset: 19:9627f653b421
630 user: test
631 user: test
631 date: Thu Jan 01 00:00:00 1970 +0000
632 date: Thu Jan 01 00:00:00 1970 +0000
632 summary: 2
633 summary: 2
633
634
634 changeset: 21:7e61b508e709
635 changeset: 21:7e61b508e709
635 branch: dev
636 branch: dev
636 user: foo
637 user: foo
637 date: Thu Jan 01 00:00:00 1970 +0000
638 date: Thu Jan 01 00:00:00 1970 +0000
638 summary: 2
639 summary: 2
639
640
640 changeset: 22:e95864da75a0
641 changeset: 22:d1cb6591fa4b
641 branch: dev
642 branch: dev
642 tag: tip
643 tag: tip
643 user: foo
644 user: foo
644 date: Thu Jan 01 00:00:00 1970 +0000
645 date: Thu Jan 01 00:00:00 1970 +0000
645 summary: 2
646 summary: 2
646
647
647
648
648 graft works on complex revset
649 graft works on complex revset
649
650
650 $ hg graft 'origin(13) or destination(origin(13))'
651 $ hg graft 'origin(13) or destination(origin(13))'
651 skipping ancestor revision 21:7e61b508e709
652 skipping ancestor revision 21:7e61b508e709
652 skipping ancestor revision 22:e95864da75a0
653 skipping ancestor revision 22:d1cb6591fa4b
653 skipping revision 2:5c095ad7e90f (already grafted to 22:e95864da75a0)
654 skipping revision 2:5c095ad7e90f (already grafted to 22:d1cb6591fa4b)
654 grafting 7:ef0ef43d49e7 "2"
655 grafting 7:ef0ef43d49e7 "2"
655 warning: can't find ancestor for 'b' copied from 'a'!
656 warning: can't find ancestor for 'b' copied from 'a'!
656 grafting 13:9db0f28fd374 "2"
657 grafting 13:7a4785234d87 "2"
657 warning: can't find ancestor for 'b' copied from 'a'!
658 warning: can't find ancestor for 'b' copied from 'a'!
658 grafting 19:9627f653b421 "2"
659 grafting 19:9627f653b421 "2"
659 merging b
660 merging b
660 warning: can't find ancestor for 'b' copied from 'a'!
661 warning: can't find ancestor for 'b' copied from 'a'!
661
662
662 graft with --force (still doesn't graft merges)
663 graft with --force (still doesn't graft merges)
663
664
664 $ hg graft 19 0 6
665 $ hg graft 19 0 6
665 skipping ungraftable merge revision 6
666 skipping ungraftable merge revision 6
666 skipping ancestor revision 0:68795b066622
667 skipping ancestor revision 0:68795b066622
667 skipping already grafted revision 19:9627f653b421 (22:e95864da75a0 also has origin 2:5c095ad7e90f)
668 skipping already grafted revision 19:9627f653b421 (22:d1cb6591fa4b also has origin 2:5c095ad7e90f)
668 [255]
669 [255]
669 $ hg graft 19 0 6 --force
670 $ hg graft 19 0 6 --force
670 skipping ungraftable merge revision 6
671 skipping ungraftable merge revision 6
671 grafting 19:9627f653b421 "2"
672 grafting 19:9627f653b421 "2"
672 merging b
673 merging b
673 warning: can't find ancestor for 'b' copied from 'a'!
674 warning: can't find ancestor for 'b' copied from 'a'!
674 grafting 0:68795b066622 "0"
675 grafting 0:68795b066622 "0"
675
676
676 graft --force after backout
677 graft --force after backout
677
678
678 $ echo abc > a
679 $ echo abc > a
679 $ hg ci -m 28
680 $ hg ci -m 28
680 $ hg backout 28
681 $ hg backout 28
681 reverting a
682 reverting a
682 changeset 29:8389853bba65 backs out changeset 28:cd42a33e1848
683 changeset 29:53177ba928f6 backs out changeset 28:50a516bb8b57
683 $ hg graft 28
684 $ hg graft 28
684 skipping ancestor revision 28:cd42a33e1848
685 skipping ancestor revision 28:50a516bb8b57
685 [255]
686 [255]
686 $ hg graft 28 --force
687 $ hg graft 28 --force
687 grafting 28:cd42a33e1848 "28"
688 grafting 28:50a516bb8b57 "28"
688 merging a
689 merging a
689 $ cat a
690 $ cat a
690 abc
691 abc
691
692
692 graft --continue after --force
693 graft --continue after --force
693
694
694 $ echo def > a
695 $ echo def > a
695 $ hg ci -m 31
696 $ hg ci -m 31
696 $ hg graft 28 --force --tool internal:fail
697 $ hg graft 28 --force --tool internal:fail
697 grafting 28:cd42a33e1848 "28"
698 grafting 28:50a516bb8b57 "28"
698 abort: unresolved conflicts, can't continue
699 abort: unresolved conflicts, can't continue
699 (use hg resolve and hg graft --continue)
700 (use hg resolve and hg graft --continue)
700 [255]
701 [255]
701 $ hg resolve --all
702 $ hg resolve --all
702 merging a
703 merging a
703 warning: conflicts during merge.
704 warning: conflicts during merge.
704 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
705 merging a incomplete! (edit conflicts, then use 'hg resolve --mark')
705 [1]
706 [1]
706 $ echo abc > a
707 $ echo abc > a
707 $ hg resolve -m a
708 $ hg resolve -m a
708 (no more unresolved files)
709 (no more unresolved files)
709 $ hg graft -c
710 $ hg graft -c
710 grafting 28:cd42a33e1848 "28"
711 grafting 28:50a516bb8b57 "28"
711 $ cat a
712 $ cat a
712 abc
713 abc
713
714
714 Continue testing same origin policy, using revision numbers from test above
715 Continue testing same origin policy, using revision numbers from test above
715 but do some destructive editing of the repo:
716 but do some destructive editing of the repo:
716
717
717 $ hg up -qC 7
718 $ hg up -qC 7
718 $ hg tag -l -r 13 tmp
719 $ hg tag -l -r 13 tmp
719 $ hg --config extensions.strip= strip 2
720 $ hg --config extensions.strip= strip 2
720 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg (glob)
721 saved backup bundle to $TESTTMP/a/.hg/strip-backup/5c095ad7e90f-d323a1e4-backup.hg (glob)
721 $ hg graft tmp
722 $ hg graft tmp
722 skipping already grafted revision 8:9db0f28fd374 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
723 skipping already grafted revision 8:7a4785234d87 (2:ef0ef43d49e7 also has unknown origin 5c095ad7e90f)
723 [255]
724 [255]
724
725
725 Empty graft
726 Empty graft
726
727
727 $ hg up -qr 26
728 $ hg up -qr 26
728 $ hg tag -f something
729 $ hg tag -f something
729 $ hg graft -qr 27
730 $ hg graft -qr 27
730 $ hg graft -f 27
731 $ hg graft -f 27
731 grafting 27:3d35c4c79e5a "28"
732 grafting 27:ed6c7e54e319 "28"
732 note: graft of 27:3d35c4c79e5a created no changes to commit
733 note: graft of 27:ed6c7e54e319 created no changes to commit
733
734
734 $ cd ..
735 $ cd ..
735
736
736 Graft to duplicate a commit
737 Graft to duplicate a commit
737
738
738 $ hg init graftsibling
739 $ hg init graftsibling
739 $ cd graftsibling
740 $ cd graftsibling
740 $ touch a
741 $ touch a
741 $ hg commit -qAm a
742 $ hg commit -qAm a
742 $ touch b
743 $ touch b
743 $ hg commit -qAm b
744 $ hg commit -qAm b
744 $ hg log -G -T '{rev}\n'
745 $ hg log -G -T '{rev}\n'
745 @ 1
746 @ 1
746 |
747 |
747 o 0
748 o 0
748
749
749 $ hg up -q 0
750 $ hg up -q 0
750 $ hg graft -r 1
751 $ hg graft -r 1
751 grafting 1:0e067c57feba "b" (tip)
752 grafting 1:0e067c57feba "b" (tip)
752 $ hg log -G -T '{rev}\n'
753 $ hg log -G -T '{rev}\n'
753 @ 2
754 @ 2
754 |
755 |
755 | o 1
756 | o 1
756 |/
757 |/
757 o 0
758 o 0
758
759
760 Graft to duplicate a commit twice
761
762 $ hg up -q 0
763 $ hg graft -r 2
764 grafting 2:044ec77f6389 "b" (tip)
765 $ hg log -G -T '{rev}\n'
766 @ 3
767 |
768 | o 2
769 |/
770 | o 1
771 |/
772 o 0
773
General Comments 0
You need to be logged in to leave comments. Login now