##// END OF EJS Templates
commands.push: abort when revisions evaluate to empty set (BC)...
Gregory Szorc -
r24429:69bd0ec2 default
parent child Browse files
Show More
@@ -1,6397 +1,6400 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 ]
151 ]
152
152
153 mergetoolopts = [
153 mergetoolopts = [
154 ('t', 'tool', '', _('specify merge tool')),
154 ('t', 'tool', '', _('specify merge tool')),
155 ]
155 ]
156
156
157 similarityopts = [
157 similarityopts = [
158 ('s', 'similarity', '',
158 ('s', 'similarity', '',
159 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
159 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
160 ]
160 ]
161
161
162 subrepoopts = [
162 subrepoopts = [
163 ('S', 'subrepos', None,
163 ('S', 'subrepos', None,
164 _('recurse into subrepositories'))
164 _('recurse into subrepositories'))
165 ]
165 ]
166
166
167 # Commands start here, listed alphabetically
167 # Commands start here, listed alphabetically
168
168
169 @command('^add',
169 @command('^add',
170 walkopts + subrepoopts + dryrunopts,
170 walkopts + subrepoopts + dryrunopts,
171 _('[OPTION]... [FILE]...'),
171 _('[OPTION]... [FILE]...'),
172 inferrepo=True)
172 inferrepo=True)
173 def add(ui, repo, *pats, **opts):
173 def add(ui, repo, *pats, **opts):
174 """add the specified files on the next commit
174 """add the specified files on the next commit
175
175
176 Schedule files to be version controlled and added to the
176 Schedule files to be version controlled and added to the
177 repository.
177 repository.
178
178
179 The files will be added to the repository at the next commit. To
179 The files will be added to the repository at the next commit. To
180 undo an add before that, see :hg:`forget`.
180 undo an add before that, see :hg:`forget`.
181
181
182 If no names are given, add all files to the repository.
182 If no names are given, add all files to the repository.
183
183
184 .. container:: verbose
184 .. container:: verbose
185
185
186 An example showing how new (unknown) files are added
186 An example showing how new (unknown) files are added
187 automatically by :hg:`add`::
187 automatically by :hg:`add`::
188
188
189 $ ls
189 $ ls
190 foo.c
190 foo.c
191 $ hg status
191 $ hg status
192 ? foo.c
192 ? foo.c
193 $ hg add
193 $ hg add
194 adding foo.c
194 adding foo.c
195 $ hg status
195 $ hg status
196 A foo.c
196 A foo.c
197
197
198 Returns 0 if all files are successfully added.
198 Returns 0 if all files are successfully added.
199 """
199 """
200
200
201 m = scmutil.match(repo[None], pats, opts)
201 m = scmutil.match(repo[None], pats, opts)
202 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
202 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
203 return rejected and 1 or 0
203 return rejected and 1 or 0
204
204
205 @command('addremove',
205 @command('addremove',
206 similarityopts + subrepoopts + walkopts + dryrunopts,
206 similarityopts + subrepoopts + walkopts + dryrunopts,
207 _('[OPTION]... [FILE]...'),
207 _('[OPTION]... [FILE]...'),
208 inferrepo=True)
208 inferrepo=True)
209 def addremove(ui, repo, *pats, **opts):
209 def addremove(ui, repo, *pats, **opts):
210 """add all new files, delete all missing files
210 """add all new files, delete all missing files
211
211
212 Add all new files and remove all missing files from the
212 Add all new files and remove all missing files from the
213 repository.
213 repository.
214
214
215 New files are ignored if they match any of the patterns in
215 New files are ignored if they match any of the patterns in
216 ``.hgignore``. As with add, these changes take effect at the next
216 ``.hgignore``. As with add, these changes take effect at the next
217 commit.
217 commit.
218
218
219 Use the -s/--similarity option to detect renamed files. This
219 Use the -s/--similarity option to detect renamed files. This
220 option takes a percentage between 0 (disabled) and 100 (files must
220 option takes a percentage between 0 (disabled) and 100 (files must
221 be identical) as its parameter. With a parameter greater than 0,
221 be identical) as its parameter. With a parameter greater than 0,
222 this compares every removed file with every added file and records
222 this compares every removed file with every added file and records
223 those similar enough as renames. Detecting renamed files this way
223 those similar enough as renames. Detecting renamed files this way
224 can be expensive. After using this option, :hg:`status -C` can be
224 can be expensive. After using this option, :hg:`status -C` can be
225 used to check which files were identified as moved or renamed. If
225 used to check which files were identified as moved or renamed. If
226 not specified, -s/--similarity defaults to 100 and only renames of
226 not specified, -s/--similarity defaults to 100 and only renames of
227 identical files are detected.
227 identical files are detected.
228
228
229 Returns 0 if all files are successfully added.
229 Returns 0 if all files are successfully added.
230 """
230 """
231 try:
231 try:
232 sim = float(opts.get('similarity') or 100)
232 sim = float(opts.get('similarity') or 100)
233 except ValueError:
233 except ValueError:
234 raise util.Abort(_('similarity must be a number'))
234 raise util.Abort(_('similarity must be a number'))
235 if sim < 0 or sim > 100:
235 if sim < 0 or sim > 100:
236 raise util.Abort(_('similarity must be between 0 and 100'))
236 raise util.Abort(_('similarity must be between 0 and 100'))
237 matcher = scmutil.match(repo[None], pats, opts)
237 matcher = scmutil.match(repo[None], pats, opts)
238 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
238 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
239
239
240 @command('^annotate|blame',
240 @command('^annotate|blame',
241 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
241 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
242 ('', 'follow', None,
242 ('', 'follow', None,
243 _('follow copies/renames and list the filename (DEPRECATED)')),
243 _('follow copies/renames and list the filename (DEPRECATED)')),
244 ('', 'no-follow', None, _("don't follow copies and renames")),
244 ('', 'no-follow', None, _("don't follow copies and renames")),
245 ('a', 'text', None, _('treat all files as text')),
245 ('a', 'text', None, _('treat all files as text')),
246 ('u', 'user', None, _('list the author (long with -v)')),
246 ('u', 'user', None, _('list the author (long with -v)')),
247 ('f', 'file', None, _('list the filename')),
247 ('f', 'file', None, _('list the filename')),
248 ('d', 'date', None, _('list the date (short with -q)')),
248 ('d', 'date', None, _('list the date (short with -q)')),
249 ('n', 'number', None, _('list the revision number (default)')),
249 ('n', 'number', None, _('list the revision number (default)')),
250 ('c', 'changeset', None, _('list the changeset')),
250 ('c', 'changeset', None, _('list the changeset')),
251 ('l', 'line-number', None, _('show line number at the first appearance'))
251 ('l', 'line-number', None, _('show line number at the first appearance'))
252 ] + diffwsopts + walkopts + formatteropts,
252 ] + diffwsopts + walkopts + formatteropts,
253 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
253 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
254 inferrepo=True)
254 inferrepo=True)
255 def annotate(ui, repo, *pats, **opts):
255 def annotate(ui, repo, *pats, **opts):
256 """show changeset information by line for each file
256 """show changeset information by line for each file
257
257
258 List changes in files, showing the revision id responsible for
258 List changes in files, showing the revision id responsible for
259 each line
259 each line
260
260
261 This command is useful for discovering when a change was made and
261 This command is useful for discovering when a change was made and
262 by whom.
262 by whom.
263
263
264 Without the -a/--text option, annotate will avoid processing files
264 Without the -a/--text option, annotate will avoid processing files
265 it detects as binary. With -a, annotate will annotate the file
265 it detects as binary. With -a, annotate will annotate the file
266 anyway, although the results will probably be neither useful
266 anyway, although the results will probably be neither useful
267 nor desirable.
267 nor desirable.
268
268
269 By default, annotate files in the parent of the working directory.
269 By default, annotate files in the parent of the working directory.
270 Use -r "wdir()" to annotate the working directory files.
270 Use -r "wdir()" to annotate the working directory files.
271
271
272 Returns 0 on success.
272 Returns 0 on success.
273 """
273 """
274 if not pats:
274 if not pats:
275 raise util.Abort(_('at least one filename or pattern is required'))
275 raise util.Abort(_('at least one filename or pattern is required'))
276
276
277 if opts.get('follow'):
277 if opts.get('follow'):
278 # --follow is deprecated and now just an alias for -f/--file
278 # --follow is deprecated and now just an alias for -f/--file
279 # to mimic the behavior of Mercurial before version 1.5
279 # to mimic the behavior of Mercurial before version 1.5
280 opts['file'] = True
280 opts['file'] = True
281
281
282 ctx = scmutil.revsingle(repo, opts.get('rev'))
282 ctx = scmutil.revsingle(repo, opts.get('rev'))
283
283
284 fm = ui.formatter('annotate', opts)
284 fm = ui.formatter('annotate', opts)
285 if ui.quiet:
285 if ui.quiet:
286 datefunc = util.shortdate
286 datefunc = util.shortdate
287 else:
287 else:
288 datefunc = util.datestr
288 datefunc = util.datestr
289 if ctx.rev() is None:
289 if ctx.rev() is None:
290 def hexfn(node):
290 def hexfn(node):
291 if node is None:
291 if node is None:
292 return None
292 return None
293 else:
293 else:
294 return fm.hexfunc(node)
294 return fm.hexfunc(node)
295 if opts.get('changeset'):
295 if opts.get('changeset'):
296 # omit "+" suffix which is appended to node hex
296 # omit "+" suffix which is appended to node hex
297 def formatrev(rev):
297 def formatrev(rev):
298 if rev is None:
298 if rev is None:
299 return '%d' % ctx.p1().rev()
299 return '%d' % ctx.p1().rev()
300 else:
300 else:
301 return '%d' % rev
301 return '%d' % rev
302 else:
302 else:
303 def formatrev(rev):
303 def formatrev(rev):
304 if rev is None:
304 if rev is None:
305 return '%d+' % ctx.p1().rev()
305 return '%d+' % ctx.p1().rev()
306 else:
306 else:
307 return '%d ' % rev
307 return '%d ' % rev
308 def formathex(hex):
308 def formathex(hex):
309 if hex is None:
309 if hex is None:
310 return '%s+' % fm.hexfunc(ctx.p1().node())
310 return '%s+' % fm.hexfunc(ctx.p1().node())
311 else:
311 else:
312 return '%s ' % hex
312 return '%s ' % hex
313 else:
313 else:
314 hexfn = fm.hexfunc
314 hexfn = fm.hexfunc
315 formatrev = formathex = str
315 formatrev = formathex = str
316
316
317 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
317 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
318 ('number', ' ', lambda x: x[0].rev(), formatrev),
318 ('number', ' ', lambda x: x[0].rev(), formatrev),
319 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
319 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
320 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
320 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
321 ('file', ' ', lambda x: x[0].path(), str),
321 ('file', ' ', lambda x: x[0].path(), str),
322 ('line_number', ':', lambda x: x[1], str),
322 ('line_number', ':', lambda x: x[1], str),
323 ]
323 ]
324 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
324 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
325
325
326 if (not opts.get('user') and not opts.get('changeset')
326 if (not opts.get('user') and not opts.get('changeset')
327 and not opts.get('date') and not opts.get('file')):
327 and not opts.get('date') and not opts.get('file')):
328 opts['number'] = True
328 opts['number'] = True
329
329
330 linenumber = opts.get('line_number') is not None
330 linenumber = opts.get('line_number') is not None
331 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
331 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
332 raise util.Abort(_('at least one of -n/-c is required for -l'))
332 raise util.Abort(_('at least one of -n/-c is required for -l'))
333
333
334 if fm:
334 if fm:
335 def makefunc(get, fmt):
335 def makefunc(get, fmt):
336 return get
336 return get
337 else:
337 else:
338 def makefunc(get, fmt):
338 def makefunc(get, fmt):
339 return lambda x: fmt(get(x))
339 return lambda x: fmt(get(x))
340 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
340 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
341 if opts.get(op)]
341 if opts.get(op)]
342 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
342 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
343 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
343 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
344 if opts.get(op))
344 if opts.get(op))
345
345
346 def bad(x, y):
346 def bad(x, y):
347 raise util.Abort("%s: %s" % (x, y))
347 raise util.Abort("%s: %s" % (x, y))
348
348
349 m = scmutil.match(ctx, pats, opts)
349 m = scmutil.match(ctx, pats, opts)
350 m.bad = bad
350 m.bad = bad
351 follow = not opts.get('no_follow')
351 follow = not opts.get('no_follow')
352 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
352 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
353 whitespace=True)
353 whitespace=True)
354 for abs in ctx.walk(m):
354 for abs in ctx.walk(m):
355 fctx = ctx[abs]
355 fctx = ctx[abs]
356 if not opts.get('text') and util.binary(fctx.data()):
356 if not opts.get('text') and util.binary(fctx.data()):
357 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
357 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
358 continue
358 continue
359
359
360 lines = fctx.annotate(follow=follow, linenumber=linenumber,
360 lines = fctx.annotate(follow=follow, linenumber=linenumber,
361 diffopts=diffopts)
361 diffopts=diffopts)
362 formats = []
362 formats = []
363 pieces = []
363 pieces = []
364
364
365 for f, sep in funcmap:
365 for f, sep in funcmap:
366 l = [f(n) for n, dummy in lines]
366 l = [f(n) for n, dummy in lines]
367 if l:
367 if l:
368 if fm:
368 if fm:
369 formats.append(['%s' for x in l])
369 formats.append(['%s' for x in l])
370 else:
370 else:
371 sizes = [encoding.colwidth(x) for x in l]
371 sizes = [encoding.colwidth(x) for x in l]
372 ml = max(sizes)
372 ml = max(sizes)
373 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
373 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
374 pieces.append(l)
374 pieces.append(l)
375
375
376 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
376 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
377 fm.startitem()
377 fm.startitem()
378 fm.write(fields, "".join(f), *p)
378 fm.write(fields, "".join(f), *p)
379 fm.write('line', ": %s", l[1])
379 fm.write('line', ": %s", l[1])
380
380
381 if lines and not lines[-1][1].endswith('\n'):
381 if lines and not lines[-1][1].endswith('\n'):
382 fm.plain('\n')
382 fm.plain('\n')
383
383
384 fm.end()
384 fm.end()
385
385
386 @command('archive',
386 @command('archive',
387 [('', 'no-decode', None, _('do not pass files through decoders')),
387 [('', 'no-decode', None, _('do not pass files through decoders')),
388 ('p', 'prefix', '', _('directory prefix for files in archive'),
388 ('p', 'prefix', '', _('directory prefix for files in archive'),
389 _('PREFIX')),
389 _('PREFIX')),
390 ('r', 'rev', '', _('revision to distribute'), _('REV')),
390 ('r', 'rev', '', _('revision to distribute'), _('REV')),
391 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
391 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
392 ] + subrepoopts + walkopts,
392 ] + subrepoopts + walkopts,
393 _('[OPTION]... DEST'))
393 _('[OPTION]... DEST'))
394 def archive(ui, repo, dest, **opts):
394 def archive(ui, repo, dest, **opts):
395 '''create an unversioned archive of a repository revision
395 '''create an unversioned archive of a repository revision
396
396
397 By default, the revision used is the parent of the working
397 By default, the revision used is the parent of the working
398 directory; use -r/--rev to specify a different revision.
398 directory; use -r/--rev to specify a different revision.
399
399
400 The archive type is automatically detected based on file
400 The archive type is automatically detected based on file
401 extension (or override using -t/--type).
401 extension (or override using -t/--type).
402
402
403 .. container:: verbose
403 .. container:: verbose
404
404
405 Examples:
405 Examples:
406
406
407 - create a zip file containing the 1.0 release::
407 - create a zip file containing the 1.0 release::
408
408
409 hg archive -r 1.0 project-1.0.zip
409 hg archive -r 1.0 project-1.0.zip
410
410
411 - create a tarball excluding .hg files::
411 - create a tarball excluding .hg files::
412
412
413 hg archive project.tar.gz -X ".hg*"
413 hg archive project.tar.gz -X ".hg*"
414
414
415 Valid types are:
415 Valid types are:
416
416
417 :``files``: a directory full of files (default)
417 :``files``: a directory full of files (default)
418 :``tar``: tar archive, uncompressed
418 :``tar``: tar archive, uncompressed
419 :``tbz2``: tar archive, compressed using bzip2
419 :``tbz2``: tar archive, compressed using bzip2
420 :``tgz``: tar archive, compressed using gzip
420 :``tgz``: tar archive, compressed using gzip
421 :``uzip``: zip archive, uncompressed
421 :``uzip``: zip archive, uncompressed
422 :``zip``: zip archive, compressed using deflate
422 :``zip``: zip archive, compressed using deflate
423
423
424 The exact name of the destination archive or directory is given
424 The exact name of the destination archive or directory is given
425 using a format string; see :hg:`help export` for details.
425 using a format string; see :hg:`help export` for details.
426
426
427 Each member added to an archive file has a directory prefix
427 Each member added to an archive file has a directory prefix
428 prepended. Use -p/--prefix to specify a format string for the
428 prepended. Use -p/--prefix to specify a format string for the
429 prefix. The default is the basename of the archive, with suffixes
429 prefix. The default is the basename of the archive, with suffixes
430 removed.
430 removed.
431
431
432 Returns 0 on success.
432 Returns 0 on success.
433 '''
433 '''
434
434
435 ctx = scmutil.revsingle(repo, opts.get('rev'))
435 ctx = scmutil.revsingle(repo, opts.get('rev'))
436 if not ctx:
436 if not ctx:
437 raise util.Abort(_('no working directory: please specify a revision'))
437 raise util.Abort(_('no working directory: please specify a revision'))
438 node = ctx.node()
438 node = ctx.node()
439 dest = cmdutil.makefilename(repo, dest, node)
439 dest = cmdutil.makefilename(repo, dest, node)
440 if os.path.realpath(dest) == repo.root:
440 if os.path.realpath(dest) == repo.root:
441 raise util.Abort(_('repository root cannot be destination'))
441 raise util.Abort(_('repository root cannot be destination'))
442
442
443 kind = opts.get('type') or archival.guesskind(dest) or 'files'
443 kind = opts.get('type') or archival.guesskind(dest) or 'files'
444 prefix = opts.get('prefix')
444 prefix = opts.get('prefix')
445
445
446 if dest == '-':
446 if dest == '-':
447 if kind == 'files':
447 if kind == 'files':
448 raise util.Abort(_('cannot archive plain files to stdout'))
448 raise util.Abort(_('cannot archive plain files to stdout'))
449 dest = cmdutil.makefileobj(repo, dest)
449 dest = cmdutil.makefileobj(repo, dest)
450 if not prefix:
450 if not prefix:
451 prefix = os.path.basename(repo.root) + '-%h'
451 prefix = os.path.basename(repo.root) + '-%h'
452
452
453 prefix = cmdutil.makefilename(repo, prefix, node)
453 prefix = cmdutil.makefilename(repo, prefix, node)
454 matchfn = scmutil.match(ctx, [], opts)
454 matchfn = scmutil.match(ctx, [], opts)
455 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
455 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
456 matchfn, prefix, subrepos=opts.get('subrepos'))
456 matchfn, prefix, subrepos=opts.get('subrepos'))
457
457
458 @command('backout',
458 @command('backout',
459 [('', 'merge', None, _('merge with old dirstate parent after backout')),
459 [('', 'merge', None, _('merge with old dirstate parent after backout')),
460 ('', 'commit', None, _('commit if no conflicts were encountered')),
460 ('', 'commit', None, _('commit if no conflicts were encountered')),
461 ('', 'parent', '',
461 ('', 'parent', '',
462 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
462 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
463 ('r', 'rev', '', _('revision to backout'), _('REV')),
463 ('r', 'rev', '', _('revision to backout'), _('REV')),
464 ('e', 'edit', False, _('invoke editor on commit messages')),
464 ('e', 'edit', False, _('invoke editor on commit messages')),
465 ] + mergetoolopts + walkopts + commitopts + commitopts2,
465 ] + mergetoolopts + walkopts + commitopts + commitopts2,
466 _('[OPTION]... [-r] REV'))
466 _('[OPTION]... [-r] REV'))
467 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
467 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
468 '''reverse effect of earlier changeset
468 '''reverse effect of earlier changeset
469
469
470 Prepare a new changeset with the effect of REV undone in the
470 Prepare a new changeset with the effect of REV undone in the
471 current working directory.
471 current working directory.
472
472
473 If REV is the parent of the working directory, then this new changeset
473 If REV is the parent of the working directory, then this new changeset
474 is committed automatically. Otherwise, hg needs to merge the
474 is committed automatically. Otherwise, hg needs to merge the
475 changes and the merged result is left uncommitted.
475 changes and the merged result is left uncommitted.
476
476
477 .. note::
477 .. note::
478
478
479 backout cannot be used to fix either an unwanted or
479 backout cannot be used to fix either an unwanted or
480 incorrect merge.
480 incorrect merge.
481
481
482 .. container:: verbose
482 .. container:: verbose
483
483
484 By default, the pending changeset will have one parent,
484 By default, the pending changeset will have one parent,
485 maintaining a linear history. With --merge, the pending
485 maintaining a linear history. With --merge, the pending
486 changeset will instead have two parents: the old parent of the
486 changeset will instead have two parents: the old parent of the
487 working directory and a new child of REV that simply undoes REV.
487 working directory and a new child of REV that simply undoes REV.
488
488
489 Before version 1.7, the behavior without --merge was equivalent
489 Before version 1.7, the behavior without --merge was equivalent
490 to specifying --merge followed by :hg:`update --clean .` to
490 to specifying --merge followed by :hg:`update --clean .` to
491 cancel the merge and leave the child of REV as a head to be
491 cancel the merge and leave the child of REV as a head to be
492 merged separately.
492 merged separately.
493
493
494 See :hg:`help dates` for a list of formats valid for -d/--date.
494 See :hg:`help dates` for a list of formats valid for -d/--date.
495
495
496 Returns 0 on success, 1 if nothing to backout or there are unresolved
496 Returns 0 on success, 1 if nothing to backout or there are unresolved
497 files.
497 files.
498 '''
498 '''
499 if rev and node:
499 if rev and node:
500 raise util.Abort(_("please specify just one revision"))
500 raise util.Abort(_("please specify just one revision"))
501
501
502 if not rev:
502 if not rev:
503 rev = node
503 rev = node
504
504
505 if not rev:
505 if not rev:
506 raise util.Abort(_("please specify a revision to backout"))
506 raise util.Abort(_("please specify a revision to backout"))
507
507
508 date = opts.get('date')
508 date = opts.get('date')
509 if date:
509 if date:
510 opts['date'] = util.parsedate(date)
510 opts['date'] = util.parsedate(date)
511
511
512 cmdutil.checkunfinished(repo)
512 cmdutil.checkunfinished(repo)
513 cmdutil.bailifchanged(repo)
513 cmdutil.bailifchanged(repo)
514 node = scmutil.revsingle(repo, rev).node()
514 node = scmutil.revsingle(repo, rev).node()
515
515
516 op1, op2 = repo.dirstate.parents()
516 op1, op2 = repo.dirstate.parents()
517 if not repo.changelog.isancestor(node, op1):
517 if not repo.changelog.isancestor(node, op1):
518 raise util.Abort(_('cannot backout change that is not an ancestor'))
518 raise util.Abort(_('cannot backout change that is not an ancestor'))
519
519
520 p1, p2 = repo.changelog.parents(node)
520 p1, p2 = repo.changelog.parents(node)
521 if p1 == nullid:
521 if p1 == nullid:
522 raise util.Abort(_('cannot backout a change with no parents'))
522 raise util.Abort(_('cannot backout a change with no parents'))
523 if p2 != nullid:
523 if p2 != nullid:
524 if not opts.get('parent'):
524 if not opts.get('parent'):
525 raise util.Abort(_('cannot backout a merge changeset'))
525 raise util.Abort(_('cannot backout a merge changeset'))
526 p = repo.lookup(opts['parent'])
526 p = repo.lookup(opts['parent'])
527 if p not in (p1, p2):
527 if p not in (p1, p2):
528 raise util.Abort(_('%s is not a parent of %s') %
528 raise util.Abort(_('%s is not a parent of %s') %
529 (short(p), short(node)))
529 (short(p), short(node)))
530 parent = p
530 parent = p
531 else:
531 else:
532 if opts.get('parent'):
532 if opts.get('parent'):
533 raise util.Abort(_('cannot use --parent on non-merge changeset'))
533 raise util.Abort(_('cannot use --parent on non-merge changeset'))
534 parent = p1
534 parent = p1
535
535
536 # the backout should appear on the same branch
536 # the backout should appear on the same branch
537 wlock = repo.wlock()
537 wlock = repo.wlock()
538 try:
538 try:
539 branch = repo.dirstate.branch()
539 branch = repo.dirstate.branch()
540 bheads = repo.branchheads(branch)
540 bheads = repo.branchheads(branch)
541 rctx = scmutil.revsingle(repo, hex(parent))
541 rctx = scmutil.revsingle(repo, hex(parent))
542 if not opts.get('merge') and op1 != node:
542 if not opts.get('merge') and op1 != node:
543 try:
543 try:
544 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
544 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
545 'backout')
545 'backout')
546 repo.dirstate.beginparentchange()
546 repo.dirstate.beginparentchange()
547 stats = mergemod.update(repo, parent, True, True, False,
547 stats = mergemod.update(repo, parent, True, True, False,
548 node, False)
548 node, False)
549 repo.setparents(op1, op2)
549 repo.setparents(op1, op2)
550 repo.dirstate.endparentchange()
550 repo.dirstate.endparentchange()
551 hg._showstats(repo, stats)
551 hg._showstats(repo, stats)
552 if stats[3]:
552 if stats[3]:
553 repo.ui.status(_("use 'hg resolve' to retry unresolved "
553 repo.ui.status(_("use 'hg resolve' to retry unresolved "
554 "file merges\n"))
554 "file merges\n"))
555 return 1
555 return 1
556 elif not commit:
556 elif not commit:
557 msg = _("changeset %s backed out, "
557 msg = _("changeset %s backed out, "
558 "don't forget to commit.\n")
558 "don't forget to commit.\n")
559 ui.status(msg % short(node))
559 ui.status(msg % short(node))
560 return 0
560 return 0
561 finally:
561 finally:
562 ui.setconfig('ui', 'forcemerge', '', '')
562 ui.setconfig('ui', 'forcemerge', '', '')
563 else:
563 else:
564 hg.clean(repo, node, show_stats=False)
564 hg.clean(repo, node, show_stats=False)
565 repo.dirstate.setbranch(branch)
565 repo.dirstate.setbranch(branch)
566 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
566 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
567
567
568
568
569 def commitfunc(ui, repo, message, match, opts):
569 def commitfunc(ui, repo, message, match, opts):
570 editform = 'backout'
570 editform = 'backout'
571 e = cmdutil.getcommiteditor(editform=editform, **opts)
571 e = cmdutil.getcommiteditor(editform=editform, **opts)
572 if not message:
572 if not message:
573 # we don't translate commit messages
573 # we don't translate commit messages
574 message = "Backed out changeset %s" % short(node)
574 message = "Backed out changeset %s" % short(node)
575 e = cmdutil.getcommiteditor(edit=True, editform=editform)
575 e = cmdutil.getcommiteditor(edit=True, editform=editform)
576 return repo.commit(message, opts.get('user'), opts.get('date'),
576 return repo.commit(message, opts.get('user'), opts.get('date'),
577 match, editor=e)
577 match, editor=e)
578 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
578 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
579 if not newnode:
579 if not newnode:
580 ui.status(_("nothing changed\n"))
580 ui.status(_("nothing changed\n"))
581 return 1
581 return 1
582 cmdutil.commitstatus(repo, newnode, branch, bheads)
582 cmdutil.commitstatus(repo, newnode, branch, bheads)
583
583
584 def nice(node):
584 def nice(node):
585 return '%d:%s' % (repo.changelog.rev(node), short(node))
585 return '%d:%s' % (repo.changelog.rev(node), short(node))
586 ui.status(_('changeset %s backs out changeset %s\n') %
586 ui.status(_('changeset %s backs out changeset %s\n') %
587 (nice(repo.changelog.tip()), nice(node)))
587 (nice(repo.changelog.tip()), nice(node)))
588 if opts.get('merge') and op1 != node:
588 if opts.get('merge') and op1 != node:
589 hg.clean(repo, op1, show_stats=False)
589 hg.clean(repo, op1, show_stats=False)
590 ui.status(_('merging with changeset %s\n')
590 ui.status(_('merging with changeset %s\n')
591 % nice(repo.changelog.tip()))
591 % nice(repo.changelog.tip()))
592 try:
592 try:
593 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
593 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
594 'backout')
594 'backout')
595 return hg.merge(repo, hex(repo.changelog.tip()))
595 return hg.merge(repo, hex(repo.changelog.tip()))
596 finally:
596 finally:
597 ui.setconfig('ui', 'forcemerge', '', '')
597 ui.setconfig('ui', 'forcemerge', '', '')
598 finally:
598 finally:
599 wlock.release()
599 wlock.release()
600 return 0
600 return 0
601
601
602 @command('bisect',
602 @command('bisect',
603 [('r', 'reset', False, _('reset bisect state')),
603 [('r', 'reset', False, _('reset bisect state')),
604 ('g', 'good', False, _('mark changeset good')),
604 ('g', 'good', False, _('mark changeset good')),
605 ('b', 'bad', False, _('mark changeset bad')),
605 ('b', 'bad', False, _('mark changeset bad')),
606 ('s', 'skip', False, _('skip testing changeset')),
606 ('s', 'skip', False, _('skip testing changeset')),
607 ('e', 'extend', False, _('extend the bisect range')),
607 ('e', 'extend', False, _('extend the bisect range')),
608 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
608 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
609 ('U', 'noupdate', False, _('do not update to target'))],
609 ('U', 'noupdate', False, _('do not update to target'))],
610 _("[-gbsr] [-U] [-c CMD] [REV]"))
610 _("[-gbsr] [-U] [-c CMD] [REV]"))
611 def bisect(ui, repo, rev=None, extra=None, command=None,
611 def bisect(ui, repo, rev=None, extra=None, command=None,
612 reset=None, good=None, bad=None, skip=None, extend=None,
612 reset=None, good=None, bad=None, skip=None, extend=None,
613 noupdate=None):
613 noupdate=None):
614 """subdivision search of changesets
614 """subdivision search of changesets
615
615
616 This command helps to find changesets which introduce problems. To
616 This command helps to find changesets which introduce problems. To
617 use, mark the earliest changeset you know exhibits the problem as
617 use, mark the earliest changeset you know exhibits the problem as
618 bad, then mark the latest changeset which is free from the problem
618 bad, then mark the latest changeset which is free from the problem
619 as good. Bisect will update your working directory to a revision
619 as good. Bisect will update your working directory to a revision
620 for testing (unless the -U/--noupdate option is specified). Once
620 for testing (unless the -U/--noupdate option is specified). Once
621 you have performed tests, mark the working directory as good or
621 you have performed tests, mark the working directory as good or
622 bad, and bisect will either update to another candidate changeset
622 bad, and bisect will either update to another candidate changeset
623 or announce that it has found the bad revision.
623 or announce that it has found the bad revision.
624
624
625 As a shortcut, you can also use the revision argument to mark a
625 As a shortcut, you can also use the revision argument to mark a
626 revision as good or bad without checking it out first.
626 revision as good or bad without checking it out first.
627
627
628 If you supply a command, it will be used for automatic bisection.
628 If you supply a command, it will be used for automatic bisection.
629 The environment variable HG_NODE will contain the ID of the
629 The environment variable HG_NODE will contain the ID of the
630 changeset being tested. The exit status of the command will be
630 changeset being tested. The exit status of the command will be
631 used to mark revisions as good or bad: status 0 means good, 125
631 used to mark revisions as good or bad: status 0 means good, 125
632 means to skip the revision, 127 (command not found) will abort the
632 means to skip the revision, 127 (command not found) will abort the
633 bisection, and any other non-zero exit status means the revision
633 bisection, and any other non-zero exit status means the revision
634 is bad.
634 is bad.
635
635
636 .. container:: verbose
636 .. container:: verbose
637
637
638 Some examples:
638 Some examples:
639
639
640 - start a bisection with known bad revision 34, and good revision 12::
640 - start a bisection with known bad revision 34, and good revision 12::
641
641
642 hg bisect --bad 34
642 hg bisect --bad 34
643 hg bisect --good 12
643 hg bisect --good 12
644
644
645 - advance the current bisection by marking current revision as good or
645 - advance the current bisection by marking current revision as good or
646 bad::
646 bad::
647
647
648 hg bisect --good
648 hg bisect --good
649 hg bisect --bad
649 hg bisect --bad
650
650
651 - mark the current revision, or a known revision, to be skipped (e.g. if
651 - mark the current revision, or a known revision, to be skipped (e.g. if
652 that revision is not usable because of another issue)::
652 that revision is not usable because of another issue)::
653
653
654 hg bisect --skip
654 hg bisect --skip
655 hg bisect --skip 23
655 hg bisect --skip 23
656
656
657 - skip all revisions that do not touch directories ``foo`` or ``bar``::
657 - skip all revisions that do not touch directories ``foo`` or ``bar``::
658
658
659 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
659 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
660
660
661 - forget the current bisection::
661 - forget the current bisection::
662
662
663 hg bisect --reset
663 hg bisect --reset
664
664
665 - use 'make && make tests' to automatically find the first broken
665 - use 'make && make tests' to automatically find the first broken
666 revision::
666 revision::
667
667
668 hg bisect --reset
668 hg bisect --reset
669 hg bisect --bad 34
669 hg bisect --bad 34
670 hg bisect --good 12
670 hg bisect --good 12
671 hg bisect --command "make && make tests"
671 hg bisect --command "make && make tests"
672
672
673 - see all changesets whose states are already known in the current
673 - see all changesets whose states are already known in the current
674 bisection::
674 bisection::
675
675
676 hg log -r "bisect(pruned)"
676 hg log -r "bisect(pruned)"
677
677
678 - see the changeset currently being bisected (especially useful
678 - see the changeset currently being bisected (especially useful
679 if running with -U/--noupdate)::
679 if running with -U/--noupdate)::
680
680
681 hg log -r "bisect(current)"
681 hg log -r "bisect(current)"
682
682
683 - see all changesets that took part in the current bisection::
683 - see all changesets that took part in the current bisection::
684
684
685 hg log -r "bisect(range)"
685 hg log -r "bisect(range)"
686
686
687 - you can even get a nice graph::
687 - you can even get a nice graph::
688
688
689 hg log --graph -r "bisect(range)"
689 hg log --graph -r "bisect(range)"
690
690
691 See :hg:`help revsets` for more about the `bisect()` keyword.
691 See :hg:`help revsets` for more about the `bisect()` keyword.
692
692
693 Returns 0 on success.
693 Returns 0 on success.
694 """
694 """
695 def extendbisectrange(nodes, good):
695 def extendbisectrange(nodes, good):
696 # bisect is incomplete when it ends on a merge node and
696 # bisect is incomplete when it ends on a merge node and
697 # one of the parent was not checked.
697 # one of the parent was not checked.
698 parents = repo[nodes[0]].parents()
698 parents = repo[nodes[0]].parents()
699 if len(parents) > 1:
699 if len(parents) > 1:
700 if good:
700 if good:
701 side = state['bad']
701 side = state['bad']
702 else:
702 else:
703 side = state['good']
703 side = state['good']
704 num = len(set(i.node() for i in parents) & set(side))
704 num = len(set(i.node() for i in parents) & set(side))
705 if num == 1:
705 if num == 1:
706 return parents[0].ancestor(parents[1])
706 return parents[0].ancestor(parents[1])
707 return None
707 return None
708
708
709 def print_result(nodes, good):
709 def print_result(nodes, good):
710 displayer = cmdutil.show_changeset(ui, repo, {})
710 displayer = cmdutil.show_changeset(ui, repo, {})
711 if len(nodes) == 1:
711 if len(nodes) == 1:
712 # narrowed it down to a single revision
712 # narrowed it down to a single revision
713 if good:
713 if good:
714 ui.write(_("The first good revision is:\n"))
714 ui.write(_("The first good revision is:\n"))
715 else:
715 else:
716 ui.write(_("The first bad revision is:\n"))
716 ui.write(_("The first bad revision is:\n"))
717 displayer.show(repo[nodes[0]])
717 displayer.show(repo[nodes[0]])
718 extendnode = extendbisectrange(nodes, good)
718 extendnode = extendbisectrange(nodes, good)
719 if extendnode is not None:
719 if extendnode is not None:
720 ui.write(_('Not all ancestors of this changeset have been'
720 ui.write(_('Not all ancestors of this changeset have been'
721 ' checked.\nUse bisect --extend to continue the '
721 ' checked.\nUse bisect --extend to continue the '
722 'bisection from\nthe common ancestor, %s.\n')
722 'bisection from\nthe common ancestor, %s.\n')
723 % extendnode)
723 % extendnode)
724 else:
724 else:
725 # multiple possible revisions
725 # multiple possible revisions
726 if good:
726 if good:
727 ui.write(_("Due to skipped revisions, the first "
727 ui.write(_("Due to skipped revisions, the first "
728 "good revision could be any of:\n"))
728 "good revision could be any of:\n"))
729 else:
729 else:
730 ui.write(_("Due to skipped revisions, the first "
730 ui.write(_("Due to skipped revisions, the first "
731 "bad revision could be any of:\n"))
731 "bad revision could be any of:\n"))
732 for n in nodes:
732 for n in nodes:
733 displayer.show(repo[n])
733 displayer.show(repo[n])
734 displayer.close()
734 displayer.close()
735
735
736 def check_state(state, interactive=True):
736 def check_state(state, interactive=True):
737 if not state['good'] or not state['bad']:
737 if not state['good'] or not state['bad']:
738 if (good or bad or skip or reset) and interactive:
738 if (good or bad or skip or reset) and interactive:
739 return
739 return
740 if not state['good']:
740 if not state['good']:
741 raise util.Abort(_('cannot bisect (no known good revisions)'))
741 raise util.Abort(_('cannot bisect (no known good revisions)'))
742 else:
742 else:
743 raise util.Abort(_('cannot bisect (no known bad revisions)'))
743 raise util.Abort(_('cannot bisect (no known bad revisions)'))
744 return True
744 return True
745
745
746 # backward compatibility
746 # backward compatibility
747 if rev in "good bad reset init".split():
747 if rev in "good bad reset init".split():
748 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
748 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
749 cmd, rev, extra = rev, extra, None
749 cmd, rev, extra = rev, extra, None
750 if cmd == "good":
750 if cmd == "good":
751 good = True
751 good = True
752 elif cmd == "bad":
752 elif cmd == "bad":
753 bad = True
753 bad = True
754 else:
754 else:
755 reset = True
755 reset = True
756 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
756 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
757 raise util.Abort(_('incompatible arguments'))
757 raise util.Abort(_('incompatible arguments'))
758
758
759 cmdutil.checkunfinished(repo)
759 cmdutil.checkunfinished(repo)
760
760
761 if reset:
761 if reset:
762 p = repo.join("bisect.state")
762 p = repo.join("bisect.state")
763 if os.path.exists(p):
763 if os.path.exists(p):
764 os.unlink(p)
764 os.unlink(p)
765 return
765 return
766
766
767 state = hbisect.load_state(repo)
767 state = hbisect.load_state(repo)
768
768
769 if command:
769 if command:
770 changesets = 1
770 changesets = 1
771 if noupdate:
771 if noupdate:
772 try:
772 try:
773 node = state['current'][0]
773 node = state['current'][0]
774 except LookupError:
774 except LookupError:
775 raise util.Abort(_('current bisect revision is unknown - '
775 raise util.Abort(_('current bisect revision is unknown - '
776 'start a new bisect to fix'))
776 'start a new bisect to fix'))
777 else:
777 else:
778 node, p2 = repo.dirstate.parents()
778 node, p2 = repo.dirstate.parents()
779 if p2 != nullid:
779 if p2 != nullid:
780 raise util.Abort(_('current bisect revision is a merge'))
780 raise util.Abort(_('current bisect revision is a merge'))
781 try:
781 try:
782 while changesets:
782 while changesets:
783 # update state
783 # update state
784 state['current'] = [node]
784 state['current'] = [node]
785 hbisect.save_state(repo, state)
785 hbisect.save_state(repo, state)
786 status = ui.system(command, environ={'HG_NODE': hex(node)})
786 status = ui.system(command, environ={'HG_NODE': hex(node)})
787 if status == 125:
787 if status == 125:
788 transition = "skip"
788 transition = "skip"
789 elif status == 0:
789 elif status == 0:
790 transition = "good"
790 transition = "good"
791 # status < 0 means process was killed
791 # status < 0 means process was killed
792 elif status == 127:
792 elif status == 127:
793 raise util.Abort(_("failed to execute %s") % command)
793 raise util.Abort(_("failed to execute %s") % command)
794 elif status < 0:
794 elif status < 0:
795 raise util.Abort(_("%s killed") % command)
795 raise util.Abort(_("%s killed") % command)
796 else:
796 else:
797 transition = "bad"
797 transition = "bad"
798 ctx = scmutil.revsingle(repo, rev, node)
798 ctx = scmutil.revsingle(repo, rev, node)
799 rev = None # clear for future iterations
799 rev = None # clear for future iterations
800 state[transition].append(ctx.node())
800 state[transition].append(ctx.node())
801 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
801 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
802 check_state(state, interactive=False)
802 check_state(state, interactive=False)
803 # bisect
803 # bisect
804 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
804 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
805 # update to next check
805 # update to next check
806 node = nodes[0]
806 node = nodes[0]
807 if not noupdate:
807 if not noupdate:
808 cmdutil.bailifchanged(repo)
808 cmdutil.bailifchanged(repo)
809 hg.clean(repo, node, show_stats=False)
809 hg.clean(repo, node, show_stats=False)
810 finally:
810 finally:
811 state['current'] = [node]
811 state['current'] = [node]
812 hbisect.save_state(repo, state)
812 hbisect.save_state(repo, state)
813 print_result(nodes, bgood)
813 print_result(nodes, bgood)
814 return
814 return
815
815
816 # update state
816 # update state
817
817
818 if rev:
818 if rev:
819 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
819 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
820 else:
820 else:
821 nodes = [repo.lookup('.')]
821 nodes = [repo.lookup('.')]
822
822
823 if good or bad or skip:
823 if good or bad or skip:
824 if good:
824 if good:
825 state['good'] += nodes
825 state['good'] += nodes
826 elif bad:
826 elif bad:
827 state['bad'] += nodes
827 state['bad'] += nodes
828 elif skip:
828 elif skip:
829 state['skip'] += nodes
829 state['skip'] += nodes
830 hbisect.save_state(repo, state)
830 hbisect.save_state(repo, state)
831
831
832 if not check_state(state):
832 if not check_state(state):
833 return
833 return
834
834
835 # actually bisect
835 # actually bisect
836 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
836 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
837 if extend:
837 if extend:
838 if not changesets:
838 if not changesets:
839 extendnode = extendbisectrange(nodes, good)
839 extendnode = extendbisectrange(nodes, good)
840 if extendnode is not None:
840 if extendnode is not None:
841 ui.write(_("Extending search to changeset %d:%s\n")
841 ui.write(_("Extending search to changeset %d:%s\n")
842 % (extendnode.rev(), extendnode))
842 % (extendnode.rev(), extendnode))
843 state['current'] = [extendnode.node()]
843 state['current'] = [extendnode.node()]
844 hbisect.save_state(repo, state)
844 hbisect.save_state(repo, state)
845 if noupdate:
845 if noupdate:
846 return
846 return
847 cmdutil.bailifchanged(repo)
847 cmdutil.bailifchanged(repo)
848 return hg.clean(repo, extendnode.node())
848 return hg.clean(repo, extendnode.node())
849 raise util.Abort(_("nothing to extend"))
849 raise util.Abort(_("nothing to extend"))
850
850
851 if changesets == 0:
851 if changesets == 0:
852 print_result(nodes, good)
852 print_result(nodes, good)
853 else:
853 else:
854 assert len(nodes) == 1 # only a single node can be tested next
854 assert len(nodes) == 1 # only a single node can be tested next
855 node = nodes[0]
855 node = nodes[0]
856 # compute the approximate number of remaining tests
856 # compute the approximate number of remaining tests
857 tests, size = 0, 2
857 tests, size = 0, 2
858 while size <= changesets:
858 while size <= changesets:
859 tests, size = tests + 1, size * 2
859 tests, size = tests + 1, size * 2
860 rev = repo.changelog.rev(node)
860 rev = repo.changelog.rev(node)
861 ui.write(_("Testing changeset %d:%s "
861 ui.write(_("Testing changeset %d:%s "
862 "(%d changesets remaining, ~%d tests)\n")
862 "(%d changesets remaining, ~%d tests)\n")
863 % (rev, short(node), changesets, tests))
863 % (rev, short(node), changesets, tests))
864 state['current'] = [node]
864 state['current'] = [node]
865 hbisect.save_state(repo, state)
865 hbisect.save_state(repo, state)
866 if not noupdate:
866 if not noupdate:
867 cmdutil.bailifchanged(repo)
867 cmdutil.bailifchanged(repo)
868 return hg.clean(repo, node)
868 return hg.clean(repo, node)
869
869
870 @command('bookmarks|bookmark',
870 @command('bookmarks|bookmark',
871 [('f', 'force', False, _('force')),
871 [('f', 'force', False, _('force')),
872 ('r', 'rev', '', _('revision'), _('REV')),
872 ('r', 'rev', '', _('revision'), _('REV')),
873 ('d', 'delete', False, _('delete a given bookmark')),
873 ('d', 'delete', False, _('delete a given bookmark')),
874 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
874 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
875 ('i', 'inactive', False, _('mark a bookmark inactive')),
875 ('i', 'inactive', False, _('mark a bookmark inactive')),
876 ] + formatteropts,
876 ] + formatteropts,
877 _('hg bookmarks [OPTIONS]... [NAME]...'))
877 _('hg bookmarks [OPTIONS]... [NAME]...'))
878 def bookmark(ui, repo, *names, **opts):
878 def bookmark(ui, repo, *names, **opts):
879 '''create a new bookmark or list existing bookmarks
879 '''create a new bookmark or list existing bookmarks
880
880
881 Bookmarks are labels on changesets to help track lines of development.
881 Bookmarks are labels on changesets to help track lines of development.
882 Bookmarks are unversioned and can be moved, renamed and deleted.
882 Bookmarks are unversioned and can be moved, renamed and deleted.
883 Deleting or moving a bookmark has no effect on the associated changesets.
883 Deleting or moving a bookmark has no effect on the associated changesets.
884
884
885 Creating or updating to a bookmark causes it to be marked as 'active'.
885 Creating or updating to a bookmark causes it to be marked as 'active'.
886 The active bookmark is indicated with a '*'.
886 The active bookmark is indicated with a '*'.
887 When a commit is made, the active bookmark will advance to the new commit.
887 When a commit is made, the active bookmark will advance to the new commit.
888 A plain :hg:`update` will also advance an active bookmark, if possible.
888 A plain :hg:`update` will also advance an active bookmark, if possible.
889 Updating away from a bookmark will cause it to be deactivated.
889 Updating away from a bookmark will cause it to be deactivated.
890
890
891 Bookmarks can be pushed and pulled between repositories (see
891 Bookmarks can be pushed and pulled between repositories (see
892 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
892 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
893 diverged, a new 'divergent bookmark' of the form 'name@path' will
893 diverged, a new 'divergent bookmark' of the form 'name@path' will
894 be created. Using :hg:`merge` will resolve the divergence.
894 be created. Using :hg:`merge` will resolve the divergence.
895
895
896 A bookmark named '@' has the special property that :hg:`clone` will
896 A bookmark named '@' has the special property that :hg:`clone` will
897 check it out by default if it exists.
897 check it out by default if it exists.
898
898
899 .. container:: verbose
899 .. container:: verbose
900
900
901 Examples:
901 Examples:
902
902
903 - create an active bookmark for a new line of development::
903 - create an active bookmark for a new line of development::
904
904
905 hg book new-feature
905 hg book new-feature
906
906
907 - create an inactive bookmark as a place marker::
907 - create an inactive bookmark as a place marker::
908
908
909 hg book -i reviewed
909 hg book -i reviewed
910
910
911 - create an inactive bookmark on another changeset::
911 - create an inactive bookmark on another changeset::
912
912
913 hg book -r .^ tested
913 hg book -r .^ tested
914
914
915 - move the '@' bookmark from another branch::
915 - move the '@' bookmark from another branch::
916
916
917 hg book -f @
917 hg book -f @
918 '''
918 '''
919 force = opts.get('force')
919 force = opts.get('force')
920 rev = opts.get('rev')
920 rev = opts.get('rev')
921 delete = opts.get('delete')
921 delete = opts.get('delete')
922 rename = opts.get('rename')
922 rename = opts.get('rename')
923 inactive = opts.get('inactive')
923 inactive = opts.get('inactive')
924
924
925 def checkformat(mark):
925 def checkformat(mark):
926 mark = mark.strip()
926 mark = mark.strip()
927 if not mark:
927 if not mark:
928 raise util.Abort(_("bookmark names cannot consist entirely of "
928 raise util.Abort(_("bookmark names cannot consist entirely of "
929 "whitespace"))
929 "whitespace"))
930 scmutil.checknewlabel(repo, mark, 'bookmark')
930 scmutil.checknewlabel(repo, mark, 'bookmark')
931 return mark
931 return mark
932
932
933 def checkconflict(repo, mark, cur, force=False, target=None):
933 def checkconflict(repo, mark, cur, force=False, target=None):
934 if mark in marks and not force:
934 if mark in marks and not force:
935 if target:
935 if target:
936 if marks[mark] == target and target == cur:
936 if marks[mark] == target and target == cur:
937 # re-activating a bookmark
937 # re-activating a bookmark
938 return
938 return
939 anc = repo.changelog.ancestors([repo[target].rev()])
939 anc = repo.changelog.ancestors([repo[target].rev()])
940 bmctx = repo[marks[mark]]
940 bmctx = repo[marks[mark]]
941 divs = [repo[b].node() for b in marks
941 divs = [repo[b].node() for b in marks
942 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
942 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
943
943
944 # allow resolving a single divergent bookmark even if moving
944 # allow resolving a single divergent bookmark even if moving
945 # the bookmark across branches when a revision is specified
945 # the bookmark across branches when a revision is specified
946 # that contains a divergent bookmark
946 # that contains a divergent bookmark
947 if bmctx.rev() not in anc and target in divs:
947 if bmctx.rev() not in anc and target in divs:
948 bookmarks.deletedivergent(repo, [target], mark)
948 bookmarks.deletedivergent(repo, [target], mark)
949 return
949 return
950
950
951 deletefrom = [b for b in divs
951 deletefrom = [b for b in divs
952 if repo[b].rev() in anc or b == target]
952 if repo[b].rev() in anc or b == target]
953 bookmarks.deletedivergent(repo, deletefrom, mark)
953 bookmarks.deletedivergent(repo, deletefrom, mark)
954 if bookmarks.validdest(repo, bmctx, repo[target]):
954 if bookmarks.validdest(repo, bmctx, repo[target]):
955 ui.status(_("moving bookmark '%s' forward from %s\n") %
955 ui.status(_("moving bookmark '%s' forward from %s\n") %
956 (mark, short(bmctx.node())))
956 (mark, short(bmctx.node())))
957 return
957 return
958 raise util.Abort(_("bookmark '%s' already exists "
958 raise util.Abort(_("bookmark '%s' already exists "
959 "(use -f to force)") % mark)
959 "(use -f to force)") % mark)
960 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
960 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
961 and not force):
961 and not force):
962 raise util.Abort(
962 raise util.Abort(
963 _("a bookmark cannot have the name of an existing branch"))
963 _("a bookmark cannot have the name of an existing branch"))
964
964
965 if delete and rename:
965 if delete and rename:
966 raise util.Abort(_("--delete and --rename are incompatible"))
966 raise util.Abort(_("--delete and --rename are incompatible"))
967 if delete and rev:
967 if delete and rev:
968 raise util.Abort(_("--rev is incompatible with --delete"))
968 raise util.Abort(_("--rev is incompatible with --delete"))
969 if rename and rev:
969 if rename and rev:
970 raise util.Abort(_("--rev is incompatible with --rename"))
970 raise util.Abort(_("--rev is incompatible with --rename"))
971 if not names and (delete or rev):
971 if not names and (delete or rev):
972 raise util.Abort(_("bookmark name required"))
972 raise util.Abort(_("bookmark name required"))
973
973
974 if delete or rename or names or inactive:
974 if delete or rename or names or inactive:
975 wlock = repo.wlock()
975 wlock = repo.wlock()
976 try:
976 try:
977 cur = repo.changectx('.').node()
977 cur = repo.changectx('.').node()
978 marks = repo._bookmarks
978 marks = repo._bookmarks
979 if delete:
979 if delete:
980 for mark in names:
980 for mark in names:
981 if mark not in marks:
981 if mark not in marks:
982 raise util.Abort(_("bookmark '%s' does not exist") %
982 raise util.Abort(_("bookmark '%s' does not exist") %
983 mark)
983 mark)
984 if mark == repo._bookmarkcurrent:
984 if mark == repo._bookmarkcurrent:
985 bookmarks.unsetcurrent(repo)
985 bookmarks.unsetcurrent(repo)
986 del marks[mark]
986 del marks[mark]
987 marks.write()
987 marks.write()
988
988
989 elif rename:
989 elif rename:
990 if not names:
990 if not names:
991 raise util.Abort(_("new bookmark name required"))
991 raise util.Abort(_("new bookmark name required"))
992 elif len(names) > 1:
992 elif len(names) > 1:
993 raise util.Abort(_("only one new bookmark name allowed"))
993 raise util.Abort(_("only one new bookmark name allowed"))
994 mark = checkformat(names[0])
994 mark = checkformat(names[0])
995 if rename not in marks:
995 if rename not in marks:
996 raise util.Abort(_("bookmark '%s' does not exist") % rename)
996 raise util.Abort(_("bookmark '%s' does not exist") % rename)
997 checkconflict(repo, mark, cur, force)
997 checkconflict(repo, mark, cur, force)
998 marks[mark] = marks[rename]
998 marks[mark] = marks[rename]
999 if repo._bookmarkcurrent == rename and not inactive:
999 if repo._bookmarkcurrent == rename and not inactive:
1000 bookmarks.setcurrent(repo, mark)
1000 bookmarks.setcurrent(repo, mark)
1001 del marks[rename]
1001 del marks[rename]
1002 marks.write()
1002 marks.write()
1003
1003
1004 elif names:
1004 elif names:
1005 newact = None
1005 newact = None
1006 for mark in names:
1006 for mark in names:
1007 mark = checkformat(mark)
1007 mark = checkformat(mark)
1008 if newact is None:
1008 if newact is None:
1009 newact = mark
1009 newact = mark
1010 if inactive and mark == repo._bookmarkcurrent:
1010 if inactive and mark == repo._bookmarkcurrent:
1011 bookmarks.unsetcurrent(repo)
1011 bookmarks.unsetcurrent(repo)
1012 return
1012 return
1013 tgt = cur
1013 tgt = cur
1014 if rev:
1014 if rev:
1015 tgt = scmutil.revsingle(repo, rev).node()
1015 tgt = scmutil.revsingle(repo, rev).node()
1016 checkconflict(repo, mark, cur, force, tgt)
1016 checkconflict(repo, mark, cur, force, tgt)
1017 marks[mark] = tgt
1017 marks[mark] = tgt
1018 if not inactive and cur == marks[newact] and not rev:
1018 if not inactive and cur == marks[newact] and not rev:
1019 bookmarks.setcurrent(repo, newact)
1019 bookmarks.setcurrent(repo, newact)
1020 elif cur != tgt and newact == repo._bookmarkcurrent:
1020 elif cur != tgt and newact == repo._bookmarkcurrent:
1021 bookmarks.unsetcurrent(repo)
1021 bookmarks.unsetcurrent(repo)
1022 marks.write()
1022 marks.write()
1023
1023
1024 elif inactive:
1024 elif inactive:
1025 if len(marks) == 0:
1025 if len(marks) == 0:
1026 ui.status(_("no bookmarks set\n"))
1026 ui.status(_("no bookmarks set\n"))
1027 elif not repo._bookmarkcurrent:
1027 elif not repo._bookmarkcurrent:
1028 ui.status(_("no active bookmark\n"))
1028 ui.status(_("no active bookmark\n"))
1029 else:
1029 else:
1030 bookmarks.unsetcurrent(repo)
1030 bookmarks.unsetcurrent(repo)
1031 finally:
1031 finally:
1032 wlock.release()
1032 wlock.release()
1033 else: # show bookmarks
1033 else: # show bookmarks
1034 fm = ui.formatter('bookmarks', opts)
1034 fm = ui.formatter('bookmarks', opts)
1035 hexfn = fm.hexfunc
1035 hexfn = fm.hexfunc
1036 marks = repo._bookmarks
1036 marks = repo._bookmarks
1037 if len(marks) == 0 and not fm:
1037 if len(marks) == 0 and not fm:
1038 ui.status(_("no bookmarks set\n"))
1038 ui.status(_("no bookmarks set\n"))
1039 for bmark, n in sorted(marks.iteritems()):
1039 for bmark, n in sorted(marks.iteritems()):
1040 current = repo._bookmarkcurrent
1040 current = repo._bookmarkcurrent
1041 if bmark == current:
1041 if bmark == current:
1042 prefix, label = '*', 'bookmarks.current'
1042 prefix, label = '*', 'bookmarks.current'
1043 else:
1043 else:
1044 prefix, label = ' ', ''
1044 prefix, label = ' ', ''
1045
1045
1046 fm.startitem()
1046 fm.startitem()
1047 if not ui.quiet:
1047 if not ui.quiet:
1048 fm.plain(' %s ' % prefix, label=label)
1048 fm.plain(' %s ' % prefix, label=label)
1049 fm.write('bookmark', '%s', bmark, label=label)
1049 fm.write('bookmark', '%s', bmark, label=label)
1050 pad = " " * (25 - encoding.colwidth(bmark))
1050 pad = " " * (25 - encoding.colwidth(bmark))
1051 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1051 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1052 repo.changelog.rev(n), hexfn(n), label=label)
1052 repo.changelog.rev(n), hexfn(n), label=label)
1053 fm.data(active=(bmark == current))
1053 fm.data(active=(bmark == current))
1054 fm.plain('\n')
1054 fm.plain('\n')
1055 fm.end()
1055 fm.end()
1056
1056
1057 @command('branch',
1057 @command('branch',
1058 [('f', 'force', None,
1058 [('f', 'force', None,
1059 _('set branch name even if it shadows an existing branch')),
1059 _('set branch name even if it shadows an existing branch')),
1060 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1060 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1061 _('[-fC] [NAME]'))
1061 _('[-fC] [NAME]'))
1062 def branch(ui, repo, label=None, **opts):
1062 def branch(ui, repo, label=None, **opts):
1063 """set or show the current branch name
1063 """set or show the current branch name
1064
1064
1065 .. note::
1065 .. note::
1066
1066
1067 Branch names are permanent and global. Use :hg:`bookmark` to create a
1067 Branch names are permanent and global. Use :hg:`bookmark` to create a
1068 light-weight bookmark instead. See :hg:`help glossary` for more
1068 light-weight bookmark instead. See :hg:`help glossary` for more
1069 information about named branches and bookmarks.
1069 information about named branches and bookmarks.
1070
1070
1071 With no argument, show the current branch name. With one argument,
1071 With no argument, show the current branch name. With one argument,
1072 set the working directory branch name (the branch will not exist
1072 set the working directory branch name (the branch will not exist
1073 in the repository until the next commit). Standard practice
1073 in the repository until the next commit). Standard practice
1074 recommends that primary development take place on the 'default'
1074 recommends that primary development take place on the 'default'
1075 branch.
1075 branch.
1076
1076
1077 Unless -f/--force is specified, branch will not let you set a
1077 Unless -f/--force is specified, branch will not let you set a
1078 branch name that already exists.
1078 branch name that already exists.
1079
1079
1080 Use -C/--clean to reset the working directory branch to that of
1080 Use -C/--clean to reset the working directory branch to that of
1081 the parent of the working directory, negating a previous branch
1081 the parent of the working directory, negating a previous branch
1082 change.
1082 change.
1083
1083
1084 Use the command :hg:`update` to switch to an existing branch. Use
1084 Use the command :hg:`update` to switch to an existing branch. Use
1085 :hg:`commit --close-branch` to mark this branch as closed.
1085 :hg:`commit --close-branch` to mark this branch as closed.
1086
1086
1087 Returns 0 on success.
1087 Returns 0 on success.
1088 """
1088 """
1089 if label:
1089 if label:
1090 label = label.strip()
1090 label = label.strip()
1091
1091
1092 if not opts.get('clean') and not label:
1092 if not opts.get('clean') and not label:
1093 ui.write("%s\n" % repo.dirstate.branch())
1093 ui.write("%s\n" % repo.dirstate.branch())
1094 return
1094 return
1095
1095
1096 wlock = repo.wlock()
1096 wlock = repo.wlock()
1097 try:
1097 try:
1098 if opts.get('clean'):
1098 if opts.get('clean'):
1099 label = repo[None].p1().branch()
1099 label = repo[None].p1().branch()
1100 repo.dirstate.setbranch(label)
1100 repo.dirstate.setbranch(label)
1101 ui.status(_('reset working directory to branch %s\n') % label)
1101 ui.status(_('reset working directory to branch %s\n') % label)
1102 elif label:
1102 elif label:
1103 if not opts.get('force') and label in repo.branchmap():
1103 if not opts.get('force') and label in repo.branchmap():
1104 if label not in [p.branch() for p in repo.parents()]:
1104 if label not in [p.branch() for p in repo.parents()]:
1105 raise util.Abort(_('a branch of the same name already'
1105 raise util.Abort(_('a branch of the same name already'
1106 ' exists'),
1106 ' exists'),
1107 # i18n: "it" refers to an existing branch
1107 # i18n: "it" refers to an existing branch
1108 hint=_("use 'hg update' to switch to it"))
1108 hint=_("use 'hg update' to switch to it"))
1109 scmutil.checknewlabel(repo, label, 'branch')
1109 scmutil.checknewlabel(repo, label, 'branch')
1110 repo.dirstate.setbranch(label)
1110 repo.dirstate.setbranch(label)
1111 ui.status(_('marked working directory as branch %s\n') % label)
1111 ui.status(_('marked working directory as branch %s\n') % label)
1112 ui.status(_('(branches are permanent and global, '
1112 ui.status(_('(branches are permanent and global, '
1113 'did you want a bookmark?)\n'))
1113 'did you want a bookmark?)\n'))
1114 finally:
1114 finally:
1115 wlock.release()
1115 wlock.release()
1116
1116
1117 @command('branches',
1117 @command('branches',
1118 [('a', 'active', False,
1118 [('a', 'active', False,
1119 _('show only branches that have unmerged heads (DEPRECATED)')),
1119 _('show only branches that have unmerged heads (DEPRECATED)')),
1120 ('c', 'closed', False, _('show normal and closed branches')),
1120 ('c', 'closed', False, _('show normal and closed branches')),
1121 ] + formatteropts,
1121 ] + formatteropts,
1122 _('[-ac]'))
1122 _('[-ac]'))
1123 def branches(ui, repo, active=False, closed=False, **opts):
1123 def branches(ui, repo, active=False, closed=False, **opts):
1124 """list repository named branches
1124 """list repository named branches
1125
1125
1126 List the repository's named branches, indicating which ones are
1126 List the repository's named branches, indicating which ones are
1127 inactive. If -c/--closed is specified, also list branches which have
1127 inactive. If -c/--closed is specified, also list branches which have
1128 been marked closed (see :hg:`commit --close-branch`).
1128 been marked closed (see :hg:`commit --close-branch`).
1129
1129
1130 Use the command :hg:`update` to switch to an existing branch.
1130 Use the command :hg:`update` to switch to an existing branch.
1131
1131
1132 Returns 0.
1132 Returns 0.
1133 """
1133 """
1134
1134
1135 fm = ui.formatter('branches', opts)
1135 fm = ui.formatter('branches', opts)
1136 hexfunc = fm.hexfunc
1136 hexfunc = fm.hexfunc
1137
1137
1138 allheads = set(repo.heads())
1138 allheads = set(repo.heads())
1139 branches = []
1139 branches = []
1140 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1140 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1141 isactive = not isclosed and bool(set(heads) & allheads)
1141 isactive = not isclosed and bool(set(heads) & allheads)
1142 branches.append((tag, repo[tip], isactive, not isclosed))
1142 branches.append((tag, repo[tip], isactive, not isclosed))
1143 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1143 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1144 reverse=True)
1144 reverse=True)
1145
1145
1146 for tag, ctx, isactive, isopen in branches:
1146 for tag, ctx, isactive, isopen in branches:
1147 if active and not isactive:
1147 if active and not isactive:
1148 continue
1148 continue
1149 if isactive:
1149 if isactive:
1150 label = 'branches.active'
1150 label = 'branches.active'
1151 notice = ''
1151 notice = ''
1152 elif not isopen:
1152 elif not isopen:
1153 if not closed:
1153 if not closed:
1154 continue
1154 continue
1155 label = 'branches.closed'
1155 label = 'branches.closed'
1156 notice = _(' (closed)')
1156 notice = _(' (closed)')
1157 else:
1157 else:
1158 label = 'branches.inactive'
1158 label = 'branches.inactive'
1159 notice = _(' (inactive)')
1159 notice = _(' (inactive)')
1160 current = (tag == repo.dirstate.branch())
1160 current = (tag == repo.dirstate.branch())
1161 if current:
1161 if current:
1162 label = 'branches.current'
1162 label = 'branches.current'
1163
1163
1164 fm.startitem()
1164 fm.startitem()
1165 fm.write('branch', '%s', tag, label=label)
1165 fm.write('branch', '%s', tag, label=label)
1166 rev = ctx.rev()
1166 rev = ctx.rev()
1167 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1167 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1168 fmt = ' ' * padsize + ' %d:%s'
1168 fmt = ' ' * padsize + ' %d:%s'
1169 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1169 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1170 label='log.changeset changeset.%s' % ctx.phasestr())
1170 label='log.changeset changeset.%s' % ctx.phasestr())
1171 fm.data(active=isactive, closed=not isopen, current=current)
1171 fm.data(active=isactive, closed=not isopen, current=current)
1172 if not ui.quiet:
1172 if not ui.quiet:
1173 fm.plain(notice)
1173 fm.plain(notice)
1174 fm.plain('\n')
1174 fm.plain('\n')
1175 fm.end()
1175 fm.end()
1176
1176
1177 @command('bundle',
1177 @command('bundle',
1178 [('f', 'force', None, _('run even when the destination is unrelated')),
1178 [('f', 'force', None, _('run even when the destination is unrelated')),
1179 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1179 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1180 _('REV')),
1180 _('REV')),
1181 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1181 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1182 _('BRANCH')),
1182 _('BRANCH')),
1183 ('', 'base', [],
1183 ('', 'base', [],
1184 _('a base changeset assumed to be available at the destination'),
1184 _('a base changeset assumed to be available at the destination'),
1185 _('REV')),
1185 _('REV')),
1186 ('a', 'all', None, _('bundle all changesets in the repository')),
1186 ('a', 'all', None, _('bundle all changesets in the repository')),
1187 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1187 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1188 ] + remoteopts,
1188 ] + remoteopts,
1189 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1189 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1190 def bundle(ui, repo, fname, dest=None, **opts):
1190 def bundle(ui, repo, fname, dest=None, **opts):
1191 """create a changegroup file
1191 """create a changegroup file
1192
1192
1193 Generate a compressed changegroup file collecting changesets not
1193 Generate a compressed changegroup file collecting changesets not
1194 known to be in another repository.
1194 known to be in another repository.
1195
1195
1196 If you omit the destination repository, then hg assumes the
1196 If you omit the destination repository, then hg assumes the
1197 destination will have all the nodes you specify with --base
1197 destination will have all the nodes you specify with --base
1198 parameters. To create a bundle containing all changesets, use
1198 parameters. To create a bundle containing all changesets, use
1199 -a/--all (or --base null).
1199 -a/--all (or --base null).
1200
1200
1201 You can change compression method with the -t/--type option.
1201 You can change compression method with the -t/--type option.
1202 The available compression methods are: none, bzip2, and
1202 The available compression methods are: none, bzip2, and
1203 gzip (by default, bundles are compressed using bzip2).
1203 gzip (by default, bundles are compressed using bzip2).
1204
1204
1205 The bundle file can then be transferred using conventional means
1205 The bundle file can then be transferred using conventional means
1206 and applied to another repository with the unbundle or pull
1206 and applied to another repository with the unbundle or pull
1207 command. This is useful when direct push and pull are not
1207 command. This is useful when direct push and pull are not
1208 available or when exporting an entire repository is undesirable.
1208 available or when exporting an entire repository is undesirable.
1209
1209
1210 Applying bundles preserves all changeset contents including
1210 Applying bundles preserves all changeset contents including
1211 permissions, copy/rename information, and revision history.
1211 permissions, copy/rename information, and revision history.
1212
1212
1213 Returns 0 on success, 1 if no changes found.
1213 Returns 0 on success, 1 if no changes found.
1214 """
1214 """
1215 revs = None
1215 revs = None
1216 if 'rev' in opts:
1216 if 'rev' in opts:
1217 revs = scmutil.revrange(repo, opts['rev'])
1217 revs = scmutil.revrange(repo, opts['rev'])
1218
1218
1219 bundletype = opts.get('type', 'bzip2').lower()
1219 bundletype = opts.get('type', 'bzip2').lower()
1220 btypes = {'none': 'HG10UN',
1220 btypes = {'none': 'HG10UN',
1221 'bzip2': 'HG10BZ',
1221 'bzip2': 'HG10BZ',
1222 'gzip': 'HG10GZ',
1222 'gzip': 'HG10GZ',
1223 'bundle2': 'HG2Y'}
1223 'bundle2': 'HG2Y'}
1224 bundletype = btypes.get(bundletype)
1224 bundletype = btypes.get(bundletype)
1225 if bundletype not in changegroup.bundletypes:
1225 if bundletype not in changegroup.bundletypes:
1226 raise util.Abort(_('unknown bundle type specified with --type'))
1226 raise util.Abort(_('unknown bundle type specified with --type'))
1227
1227
1228 if opts.get('all'):
1228 if opts.get('all'):
1229 base = ['null']
1229 base = ['null']
1230 else:
1230 else:
1231 base = scmutil.revrange(repo, opts.get('base'))
1231 base = scmutil.revrange(repo, opts.get('base'))
1232 # TODO: get desired bundlecaps from command line.
1232 # TODO: get desired bundlecaps from command line.
1233 bundlecaps = None
1233 bundlecaps = None
1234 if base:
1234 if base:
1235 if dest:
1235 if dest:
1236 raise util.Abort(_("--base is incompatible with specifying "
1236 raise util.Abort(_("--base is incompatible with specifying "
1237 "a destination"))
1237 "a destination"))
1238 common = [repo.lookup(rev) for rev in base]
1238 common = [repo.lookup(rev) for rev in base]
1239 heads = revs and map(repo.lookup, revs) or revs
1239 heads = revs and map(repo.lookup, revs) or revs
1240 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1240 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1241 common=common, bundlecaps=bundlecaps)
1241 common=common, bundlecaps=bundlecaps)
1242 outgoing = None
1242 outgoing = None
1243 else:
1243 else:
1244 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1244 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1245 dest, branches = hg.parseurl(dest, opts.get('branch'))
1245 dest, branches = hg.parseurl(dest, opts.get('branch'))
1246 other = hg.peer(repo, opts, dest)
1246 other = hg.peer(repo, opts, dest)
1247 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1247 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1248 heads = revs and map(repo.lookup, revs) or revs
1248 heads = revs and map(repo.lookup, revs) or revs
1249 outgoing = discovery.findcommonoutgoing(repo, other,
1249 outgoing = discovery.findcommonoutgoing(repo, other,
1250 onlyheads=heads,
1250 onlyheads=heads,
1251 force=opts.get('force'),
1251 force=opts.get('force'),
1252 portable=True)
1252 portable=True)
1253 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1253 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1254 bundlecaps)
1254 bundlecaps)
1255 if not cg:
1255 if not cg:
1256 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1256 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1257 return 1
1257 return 1
1258
1258
1259 changegroup.writebundle(ui, cg, fname, bundletype)
1259 changegroup.writebundle(ui, cg, fname, bundletype)
1260
1260
1261 @command('cat',
1261 @command('cat',
1262 [('o', 'output', '',
1262 [('o', 'output', '',
1263 _('print output to file with formatted name'), _('FORMAT')),
1263 _('print output to file with formatted name'), _('FORMAT')),
1264 ('r', 'rev', '', _('print the given revision'), _('REV')),
1264 ('r', 'rev', '', _('print the given revision'), _('REV')),
1265 ('', 'decode', None, _('apply any matching decode filter')),
1265 ('', 'decode', None, _('apply any matching decode filter')),
1266 ] + walkopts,
1266 ] + walkopts,
1267 _('[OPTION]... FILE...'),
1267 _('[OPTION]... FILE...'),
1268 inferrepo=True)
1268 inferrepo=True)
1269 def cat(ui, repo, file1, *pats, **opts):
1269 def cat(ui, repo, file1, *pats, **opts):
1270 """output the current or given revision of files
1270 """output the current or given revision of files
1271
1271
1272 Print the specified files as they were at the given revision. If
1272 Print the specified files as they were at the given revision. If
1273 no revision is given, the parent of the working directory is used.
1273 no revision is given, the parent of the working directory is used.
1274
1274
1275 Output may be to a file, in which case the name of the file is
1275 Output may be to a file, in which case the name of the file is
1276 given using a format string. The formatting rules as follows:
1276 given using a format string. The formatting rules as follows:
1277
1277
1278 :``%%``: literal "%" character
1278 :``%%``: literal "%" character
1279 :``%s``: basename of file being printed
1279 :``%s``: basename of file being printed
1280 :``%d``: dirname of file being printed, or '.' if in repository root
1280 :``%d``: dirname of file being printed, or '.' if in repository root
1281 :``%p``: root-relative path name of file being printed
1281 :``%p``: root-relative path name of file being printed
1282 :``%H``: changeset hash (40 hexadecimal digits)
1282 :``%H``: changeset hash (40 hexadecimal digits)
1283 :``%R``: changeset revision number
1283 :``%R``: changeset revision number
1284 :``%h``: short-form changeset hash (12 hexadecimal digits)
1284 :``%h``: short-form changeset hash (12 hexadecimal digits)
1285 :``%r``: zero-padded changeset revision number
1285 :``%r``: zero-padded changeset revision number
1286 :``%b``: basename of the exporting repository
1286 :``%b``: basename of the exporting repository
1287
1287
1288 Returns 0 on success.
1288 Returns 0 on success.
1289 """
1289 """
1290 ctx = scmutil.revsingle(repo, opts.get('rev'))
1290 ctx = scmutil.revsingle(repo, opts.get('rev'))
1291 m = scmutil.match(ctx, (file1,) + pats, opts)
1291 m = scmutil.match(ctx, (file1,) + pats, opts)
1292
1292
1293 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1293 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1294
1294
1295 @command('^clone',
1295 @command('^clone',
1296 [('U', 'noupdate', None, _('the clone will include an empty working '
1296 [('U', 'noupdate', None, _('the clone will include an empty working '
1297 'directory (only a repository)')),
1297 'directory (only a repository)')),
1298 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1298 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1299 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1299 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1300 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1300 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1301 ('', 'pull', None, _('use pull protocol to copy metadata')),
1301 ('', 'pull', None, _('use pull protocol to copy metadata')),
1302 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1302 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1303 ] + remoteopts,
1303 ] + remoteopts,
1304 _('[OPTION]... SOURCE [DEST]'),
1304 _('[OPTION]... SOURCE [DEST]'),
1305 norepo=True)
1305 norepo=True)
1306 def clone(ui, source, dest=None, **opts):
1306 def clone(ui, source, dest=None, **opts):
1307 """make a copy of an existing repository
1307 """make a copy of an existing repository
1308
1308
1309 Create a copy of an existing repository in a new directory.
1309 Create a copy of an existing repository in a new directory.
1310
1310
1311 If no destination directory name is specified, it defaults to the
1311 If no destination directory name is specified, it defaults to the
1312 basename of the source.
1312 basename of the source.
1313
1313
1314 The location of the source is added to the new repository's
1314 The location of the source is added to the new repository's
1315 ``.hg/hgrc`` file, as the default to be used for future pulls.
1315 ``.hg/hgrc`` file, as the default to be used for future pulls.
1316
1316
1317 Only local paths and ``ssh://`` URLs are supported as
1317 Only local paths and ``ssh://`` URLs are supported as
1318 destinations. For ``ssh://`` destinations, no working directory or
1318 destinations. For ``ssh://`` destinations, no working directory or
1319 ``.hg/hgrc`` will be created on the remote side.
1319 ``.hg/hgrc`` will be created on the remote side.
1320
1320
1321 To pull only a subset of changesets, specify one or more revisions
1321 To pull only a subset of changesets, specify one or more revisions
1322 identifiers with -r/--rev or branches with -b/--branch. The
1322 identifiers with -r/--rev or branches with -b/--branch. The
1323 resulting clone will contain only the specified changesets and
1323 resulting clone will contain only the specified changesets and
1324 their ancestors. These options (or 'clone src#rev dest') imply
1324 their ancestors. These options (or 'clone src#rev dest') imply
1325 --pull, even for local source repositories. Note that specifying a
1325 --pull, even for local source repositories. Note that specifying a
1326 tag will include the tagged changeset but not the changeset
1326 tag will include the tagged changeset but not the changeset
1327 containing the tag.
1327 containing the tag.
1328
1328
1329 If the source repository has a bookmark called '@' set, that
1329 If the source repository has a bookmark called '@' set, that
1330 revision will be checked out in the new repository by default.
1330 revision will be checked out in the new repository by default.
1331
1331
1332 To check out a particular version, use -u/--update, or
1332 To check out a particular version, use -u/--update, or
1333 -U/--noupdate to create a clone with no working directory.
1333 -U/--noupdate to create a clone with no working directory.
1334
1334
1335 .. container:: verbose
1335 .. container:: verbose
1336
1336
1337 For efficiency, hardlinks are used for cloning whenever the
1337 For efficiency, hardlinks are used for cloning whenever the
1338 source and destination are on the same filesystem (note this
1338 source and destination are on the same filesystem (note this
1339 applies only to the repository data, not to the working
1339 applies only to the repository data, not to the working
1340 directory). Some filesystems, such as AFS, implement hardlinking
1340 directory). Some filesystems, such as AFS, implement hardlinking
1341 incorrectly, but do not report errors. In these cases, use the
1341 incorrectly, but do not report errors. In these cases, use the
1342 --pull option to avoid hardlinking.
1342 --pull option to avoid hardlinking.
1343
1343
1344 In some cases, you can clone repositories and the working
1344 In some cases, you can clone repositories and the working
1345 directory using full hardlinks with ::
1345 directory using full hardlinks with ::
1346
1346
1347 $ cp -al REPO REPOCLONE
1347 $ cp -al REPO REPOCLONE
1348
1348
1349 This is the fastest way to clone, but it is not always safe. The
1349 This is the fastest way to clone, but it is not always safe. The
1350 operation is not atomic (making sure REPO is not modified during
1350 operation is not atomic (making sure REPO is not modified during
1351 the operation is up to you) and you have to make sure your
1351 the operation is up to you) and you have to make sure your
1352 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1352 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1353 so). Also, this is not compatible with certain extensions that
1353 so). Also, this is not compatible with certain extensions that
1354 place their metadata under the .hg directory, such as mq.
1354 place their metadata under the .hg directory, such as mq.
1355
1355
1356 Mercurial will update the working directory to the first applicable
1356 Mercurial will update the working directory to the first applicable
1357 revision from this list:
1357 revision from this list:
1358
1358
1359 a) null if -U or the source repository has no changesets
1359 a) null if -U or the source repository has no changesets
1360 b) if -u . and the source repository is local, the first parent of
1360 b) if -u . and the source repository is local, the first parent of
1361 the source repository's working directory
1361 the source repository's working directory
1362 c) the changeset specified with -u (if a branch name, this means the
1362 c) the changeset specified with -u (if a branch name, this means the
1363 latest head of that branch)
1363 latest head of that branch)
1364 d) the changeset specified with -r
1364 d) the changeset specified with -r
1365 e) the tipmost head specified with -b
1365 e) the tipmost head specified with -b
1366 f) the tipmost head specified with the url#branch source syntax
1366 f) the tipmost head specified with the url#branch source syntax
1367 g) the revision marked with the '@' bookmark, if present
1367 g) the revision marked with the '@' bookmark, if present
1368 h) the tipmost head of the default branch
1368 h) the tipmost head of the default branch
1369 i) tip
1369 i) tip
1370
1370
1371 Examples:
1371 Examples:
1372
1372
1373 - clone a remote repository to a new directory named hg/::
1373 - clone a remote repository to a new directory named hg/::
1374
1374
1375 hg clone http://selenic.com/hg
1375 hg clone http://selenic.com/hg
1376
1376
1377 - create a lightweight local clone::
1377 - create a lightweight local clone::
1378
1378
1379 hg clone project/ project-feature/
1379 hg clone project/ project-feature/
1380
1380
1381 - clone from an absolute path on an ssh server (note double-slash)::
1381 - clone from an absolute path on an ssh server (note double-slash)::
1382
1382
1383 hg clone ssh://user@server//home/projects/alpha/
1383 hg clone ssh://user@server//home/projects/alpha/
1384
1384
1385 - do a high-speed clone over a LAN while checking out a
1385 - do a high-speed clone over a LAN while checking out a
1386 specified version::
1386 specified version::
1387
1387
1388 hg clone --uncompressed http://server/repo -u 1.5
1388 hg clone --uncompressed http://server/repo -u 1.5
1389
1389
1390 - create a repository without changesets after a particular revision::
1390 - create a repository without changesets after a particular revision::
1391
1391
1392 hg clone -r 04e544 experimental/ good/
1392 hg clone -r 04e544 experimental/ good/
1393
1393
1394 - clone (and track) a particular named branch::
1394 - clone (and track) a particular named branch::
1395
1395
1396 hg clone http://selenic.com/hg#stable
1396 hg clone http://selenic.com/hg#stable
1397
1397
1398 See :hg:`help urls` for details on specifying URLs.
1398 See :hg:`help urls` for details on specifying URLs.
1399
1399
1400 Returns 0 on success.
1400 Returns 0 on success.
1401 """
1401 """
1402 if opts.get('noupdate') and opts.get('updaterev'):
1402 if opts.get('noupdate') and opts.get('updaterev'):
1403 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1403 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1404
1404
1405 r = hg.clone(ui, opts, source, dest,
1405 r = hg.clone(ui, opts, source, dest,
1406 pull=opts.get('pull'),
1406 pull=opts.get('pull'),
1407 stream=opts.get('uncompressed'),
1407 stream=opts.get('uncompressed'),
1408 rev=opts.get('rev'),
1408 rev=opts.get('rev'),
1409 update=opts.get('updaterev') or not opts.get('noupdate'),
1409 update=opts.get('updaterev') or not opts.get('noupdate'),
1410 branch=opts.get('branch'))
1410 branch=opts.get('branch'))
1411
1411
1412 return r is None
1412 return r is None
1413
1413
1414 @command('^commit|ci',
1414 @command('^commit|ci',
1415 [('A', 'addremove', None,
1415 [('A', 'addremove', None,
1416 _('mark new/missing files as added/removed before committing')),
1416 _('mark new/missing files as added/removed before committing')),
1417 ('', 'close-branch', None,
1417 ('', 'close-branch', None,
1418 _('mark a branch as closed, hiding it from the branch list')),
1418 _('mark a branch as closed, hiding it from the branch list')),
1419 ('', 'amend', None, _('amend the parent of the working directory')),
1419 ('', 'amend', None, _('amend the parent of the working directory')),
1420 ('s', 'secret', None, _('use the secret phase for committing')),
1420 ('s', 'secret', None, _('use the secret phase for committing')),
1421 ('e', 'edit', None, _('invoke editor on commit messages')),
1421 ('e', 'edit', None, _('invoke editor on commit messages')),
1422 ('i', 'interactive', None, _('use interactive mode')),
1422 ('i', 'interactive', None, _('use interactive mode')),
1423 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1423 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1424 _('[OPTION]... [FILE]...'),
1424 _('[OPTION]... [FILE]...'),
1425 inferrepo=True)
1425 inferrepo=True)
1426 def commit(ui, repo, *pats, **opts):
1426 def commit(ui, repo, *pats, **opts):
1427 """commit the specified files or all outstanding changes
1427 """commit the specified files or all outstanding changes
1428
1428
1429 Commit changes to the given files into the repository. Unlike a
1429 Commit changes to the given files into the repository. Unlike a
1430 centralized SCM, this operation is a local operation. See
1430 centralized SCM, this operation is a local operation. See
1431 :hg:`push` for a way to actively distribute your changes.
1431 :hg:`push` for a way to actively distribute your changes.
1432
1432
1433 If a list of files is omitted, all changes reported by :hg:`status`
1433 If a list of files is omitted, all changes reported by :hg:`status`
1434 will be committed.
1434 will be committed.
1435
1435
1436 If you are committing the result of a merge, do not provide any
1436 If you are committing the result of a merge, do not provide any
1437 filenames or -I/-X filters.
1437 filenames or -I/-X filters.
1438
1438
1439 If no commit message is specified, Mercurial starts your
1439 If no commit message is specified, Mercurial starts your
1440 configured editor where you can enter a message. In case your
1440 configured editor where you can enter a message. In case your
1441 commit fails, you will find a backup of your message in
1441 commit fails, you will find a backup of your message in
1442 ``.hg/last-message.txt``.
1442 ``.hg/last-message.txt``.
1443
1443
1444 The --amend flag can be used to amend the parent of the
1444 The --amend flag can be used to amend the parent of the
1445 working directory with a new commit that contains the changes
1445 working directory with a new commit that contains the changes
1446 in the parent in addition to those currently reported by :hg:`status`,
1446 in the parent in addition to those currently reported by :hg:`status`,
1447 if there are any. The old commit is stored in a backup bundle in
1447 if there are any. The old commit is stored in a backup bundle in
1448 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1448 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1449 on how to restore it).
1449 on how to restore it).
1450
1450
1451 Message, user and date are taken from the amended commit unless
1451 Message, user and date are taken from the amended commit unless
1452 specified. When a message isn't specified on the command line,
1452 specified. When a message isn't specified on the command line,
1453 the editor will open with the message of the amended commit.
1453 the editor will open with the message of the amended commit.
1454
1454
1455 It is not possible to amend public changesets (see :hg:`help phases`)
1455 It is not possible to amend public changesets (see :hg:`help phases`)
1456 or changesets that have children.
1456 or changesets that have children.
1457
1457
1458 See :hg:`help dates` for a list of formats valid for -d/--date.
1458 See :hg:`help dates` for a list of formats valid for -d/--date.
1459
1459
1460 Returns 0 on success, 1 if nothing changed.
1460 Returns 0 on success, 1 if nothing changed.
1461 """
1461 """
1462 if opts.get('interactive'):
1462 if opts.get('interactive'):
1463 opts.pop('interactive')
1463 opts.pop('interactive')
1464 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1464 cmdutil.dorecord(ui, repo, commit, 'commit', False,
1465 cmdutil.recordfilter, *pats, **opts)
1465 cmdutil.recordfilter, *pats, **opts)
1466 return
1466 return
1467
1467
1468 if opts.get('subrepos'):
1468 if opts.get('subrepos'):
1469 if opts.get('amend'):
1469 if opts.get('amend'):
1470 raise util.Abort(_('cannot amend with --subrepos'))
1470 raise util.Abort(_('cannot amend with --subrepos'))
1471 # Let --subrepos on the command line override config setting.
1471 # Let --subrepos on the command line override config setting.
1472 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1472 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1473
1473
1474 cmdutil.checkunfinished(repo, commit=True)
1474 cmdutil.checkunfinished(repo, commit=True)
1475
1475
1476 branch = repo[None].branch()
1476 branch = repo[None].branch()
1477 bheads = repo.branchheads(branch)
1477 bheads = repo.branchheads(branch)
1478
1478
1479 extra = {}
1479 extra = {}
1480 if opts.get('close_branch'):
1480 if opts.get('close_branch'):
1481 extra['close'] = 1
1481 extra['close'] = 1
1482
1482
1483 if not bheads:
1483 if not bheads:
1484 raise util.Abort(_('can only close branch heads'))
1484 raise util.Abort(_('can only close branch heads'))
1485 elif opts.get('amend'):
1485 elif opts.get('amend'):
1486 if repo.parents()[0].p1().branch() != branch and \
1486 if repo.parents()[0].p1().branch() != branch and \
1487 repo.parents()[0].p2().branch() != branch:
1487 repo.parents()[0].p2().branch() != branch:
1488 raise util.Abort(_('can only close branch heads'))
1488 raise util.Abort(_('can only close branch heads'))
1489
1489
1490 if opts.get('amend'):
1490 if opts.get('amend'):
1491 if ui.configbool('ui', 'commitsubrepos'):
1491 if ui.configbool('ui', 'commitsubrepos'):
1492 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1492 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1493
1493
1494 old = repo['.']
1494 old = repo['.']
1495 if not old.mutable():
1495 if not old.mutable():
1496 raise util.Abort(_('cannot amend public changesets'))
1496 raise util.Abort(_('cannot amend public changesets'))
1497 if len(repo[None].parents()) > 1:
1497 if len(repo[None].parents()) > 1:
1498 raise util.Abort(_('cannot amend while merging'))
1498 raise util.Abort(_('cannot amend while merging'))
1499 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1499 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1500 if not allowunstable and old.children():
1500 if not allowunstable and old.children():
1501 raise util.Abort(_('cannot amend changeset with children'))
1501 raise util.Abort(_('cannot amend changeset with children'))
1502
1502
1503 # commitfunc is used only for temporary amend commit by cmdutil.amend
1503 # commitfunc is used only for temporary amend commit by cmdutil.amend
1504 def commitfunc(ui, repo, message, match, opts):
1504 def commitfunc(ui, repo, message, match, opts):
1505 return repo.commit(message,
1505 return repo.commit(message,
1506 opts.get('user') or old.user(),
1506 opts.get('user') or old.user(),
1507 opts.get('date') or old.date(),
1507 opts.get('date') or old.date(),
1508 match,
1508 match,
1509 extra=extra)
1509 extra=extra)
1510
1510
1511 current = repo._bookmarkcurrent
1511 current = repo._bookmarkcurrent
1512 marks = old.bookmarks()
1512 marks = old.bookmarks()
1513 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1513 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1514 if node == old.node():
1514 if node == old.node():
1515 ui.status(_("nothing changed\n"))
1515 ui.status(_("nothing changed\n"))
1516 return 1
1516 return 1
1517 elif marks:
1517 elif marks:
1518 ui.debug('moving bookmarks %r from %s to %s\n' %
1518 ui.debug('moving bookmarks %r from %s to %s\n' %
1519 (marks, old.hex(), hex(node)))
1519 (marks, old.hex(), hex(node)))
1520 newmarks = repo._bookmarks
1520 newmarks = repo._bookmarks
1521 for bm in marks:
1521 for bm in marks:
1522 newmarks[bm] = node
1522 newmarks[bm] = node
1523 if bm == current:
1523 if bm == current:
1524 bookmarks.setcurrent(repo, bm)
1524 bookmarks.setcurrent(repo, bm)
1525 newmarks.write()
1525 newmarks.write()
1526 else:
1526 else:
1527 def commitfunc(ui, repo, message, match, opts):
1527 def commitfunc(ui, repo, message, match, opts):
1528 backup = ui.backupconfig('phases', 'new-commit')
1528 backup = ui.backupconfig('phases', 'new-commit')
1529 baseui = repo.baseui
1529 baseui = repo.baseui
1530 basebackup = baseui.backupconfig('phases', 'new-commit')
1530 basebackup = baseui.backupconfig('phases', 'new-commit')
1531 try:
1531 try:
1532 if opts.get('secret'):
1532 if opts.get('secret'):
1533 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1533 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1534 # Propagate to subrepos
1534 # Propagate to subrepos
1535 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1535 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1536
1536
1537 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1537 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1538 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1538 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1539 return repo.commit(message, opts.get('user'), opts.get('date'),
1539 return repo.commit(message, opts.get('user'), opts.get('date'),
1540 match,
1540 match,
1541 editor=editor,
1541 editor=editor,
1542 extra=extra)
1542 extra=extra)
1543 finally:
1543 finally:
1544 ui.restoreconfig(backup)
1544 ui.restoreconfig(backup)
1545 repo.baseui.restoreconfig(basebackup)
1545 repo.baseui.restoreconfig(basebackup)
1546
1546
1547
1547
1548 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1548 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1549
1549
1550 if not node:
1550 if not node:
1551 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1551 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1552 if stat[3]:
1552 if stat[3]:
1553 ui.status(_("nothing changed (%d missing files, see "
1553 ui.status(_("nothing changed (%d missing files, see "
1554 "'hg status')\n") % len(stat[3]))
1554 "'hg status')\n") % len(stat[3]))
1555 else:
1555 else:
1556 ui.status(_("nothing changed\n"))
1556 ui.status(_("nothing changed\n"))
1557 return 1
1557 return 1
1558
1558
1559 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1559 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1560
1560
1561 @command('config|showconfig|debugconfig',
1561 @command('config|showconfig|debugconfig',
1562 [('u', 'untrusted', None, _('show untrusted configuration options')),
1562 [('u', 'untrusted', None, _('show untrusted configuration options')),
1563 ('e', 'edit', None, _('edit user config')),
1563 ('e', 'edit', None, _('edit user config')),
1564 ('l', 'local', None, _('edit repository config')),
1564 ('l', 'local', None, _('edit repository config')),
1565 ('g', 'global', None, _('edit global config'))],
1565 ('g', 'global', None, _('edit global config'))],
1566 _('[-u] [NAME]...'),
1566 _('[-u] [NAME]...'),
1567 optionalrepo=True)
1567 optionalrepo=True)
1568 def config(ui, repo, *values, **opts):
1568 def config(ui, repo, *values, **opts):
1569 """show combined config settings from all hgrc files
1569 """show combined config settings from all hgrc files
1570
1570
1571 With no arguments, print names and values of all config items.
1571 With no arguments, print names and values of all config items.
1572
1572
1573 With one argument of the form section.name, print just the value
1573 With one argument of the form section.name, print just the value
1574 of that config item.
1574 of that config item.
1575
1575
1576 With multiple arguments, print names and values of all config
1576 With multiple arguments, print names and values of all config
1577 items with matching section names.
1577 items with matching section names.
1578
1578
1579 With --edit, start an editor on the user-level config file. With
1579 With --edit, start an editor on the user-level config file. With
1580 --global, edit the system-wide config file. With --local, edit the
1580 --global, edit the system-wide config file. With --local, edit the
1581 repository-level config file.
1581 repository-level config file.
1582
1582
1583 With --debug, the source (filename and line number) is printed
1583 With --debug, the source (filename and line number) is printed
1584 for each config item.
1584 for each config item.
1585
1585
1586 See :hg:`help config` for more information about config files.
1586 See :hg:`help config` for more information about config files.
1587
1587
1588 Returns 0 on success, 1 if NAME does not exist.
1588 Returns 0 on success, 1 if NAME does not exist.
1589
1589
1590 """
1590 """
1591
1591
1592 if opts.get('edit') or opts.get('local') or opts.get('global'):
1592 if opts.get('edit') or opts.get('local') or opts.get('global'):
1593 if opts.get('local') and opts.get('global'):
1593 if opts.get('local') and opts.get('global'):
1594 raise util.Abort(_("can't use --local and --global together"))
1594 raise util.Abort(_("can't use --local and --global together"))
1595
1595
1596 if opts.get('local'):
1596 if opts.get('local'):
1597 if not repo:
1597 if not repo:
1598 raise util.Abort(_("can't use --local outside a repository"))
1598 raise util.Abort(_("can't use --local outside a repository"))
1599 paths = [repo.join('hgrc')]
1599 paths = [repo.join('hgrc')]
1600 elif opts.get('global'):
1600 elif opts.get('global'):
1601 paths = scmutil.systemrcpath()
1601 paths = scmutil.systemrcpath()
1602 else:
1602 else:
1603 paths = scmutil.userrcpath()
1603 paths = scmutil.userrcpath()
1604
1604
1605 for f in paths:
1605 for f in paths:
1606 if os.path.exists(f):
1606 if os.path.exists(f):
1607 break
1607 break
1608 else:
1608 else:
1609 if opts.get('global'):
1609 if opts.get('global'):
1610 samplehgrc = uimod.samplehgrcs['global']
1610 samplehgrc = uimod.samplehgrcs['global']
1611 elif opts.get('local'):
1611 elif opts.get('local'):
1612 samplehgrc = uimod.samplehgrcs['local']
1612 samplehgrc = uimod.samplehgrcs['local']
1613 else:
1613 else:
1614 samplehgrc = uimod.samplehgrcs['user']
1614 samplehgrc = uimod.samplehgrcs['user']
1615
1615
1616 f = paths[0]
1616 f = paths[0]
1617 fp = open(f, "w")
1617 fp = open(f, "w")
1618 fp.write(samplehgrc)
1618 fp.write(samplehgrc)
1619 fp.close()
1619 fp.close()
1620
1620
1621 editor = ui.geteditor()
1621 editor = ui.geteditor()
1622 ui.system("%s \"%s\"" % (editor, f),
1622 ui.system("%s \"%s\"" % (editor, f),
1623 onerr=util.Abort, errprefix=_("edit failed"))
1623 onerr=util.Abort, errprefix=_("edit failed"))
1624 return
1624 return
1625
1625
1626 for f in scmutil.rcpath():
1626 for f in scmutil.rcpath():
1627 ui.debug('read config from: %s\n' % f)
1627 ui.debug('read config from: %s\n' % f)
1628 untrusted = bool(opts.get('untrusted'))
1628 untrusted = bool(opts.get('untrusted'))
1629 if values:
1629 if values:
1630 sections = [v for v in values if '.' not in v]
1630 sections = [v for v in values if '.' not in v]
1631 items = [v for v in values if '.' in v]
1631 items = [v for v in values if '.' in v]
1632 if len(items) > 1 or items and sections:
1632 if len(items) > 1 or items and sections:
1633 raise util.Abort(_('only one config item permitted'))
1633 raise util.Abort(_('only one config item permitted'))
1634 matched = False
1634 matched = False
1635 for section, name, value in ui.walkconfig(untrusted=untrusted):
1635 for section, name, value in ui.walkconfig(untrusted=untrusted):
1636 value = str(value).replace('\n', '\\n')
1636 value = str(value).replace('\n', '\\n')
1637 sectname = section + '.' + name
1637 sectname = section + '.' + name
1638 if values:
1638 if values:
1639 for v in values:
1639 for v in values:
1640 if v == section:
1640 if v == section:
1641 ui.debug('%s: ' %
1641 ui.debug('%s: ' %
1642 ui.configsource(section, name, untrusted))
1642 ui.configsource(section, name, untrusted))
1643 ui.write('%s=%s\n' % (sectname, value))
1643 ui.write('%s=%s\n' % (sectname, value))
1644 matched = True
1644 matched = True
1645 elif v == sectname:
1645 elif v == sectname:
1646 ui.debug('%s: ' %
1646 ui.debug('%s: ' %
1647 ui.configsource(section, name, untrusted))
1647 ui.configsource(section, name, untrusted))
1648 ui.write(value, '\n')
1648 ui.write(value, '\n')
1649 matched = True
1649 matched = True
1650 else:
1650 else:
1651 ui.debug('%s: ' %
1651 ui.debug('%s: ' %
1652 ui.configsource(section, name, untrusted))
1652 ui.configsource(section, name, untrusted))
1653 ui.write('%s=%s\n' % (sectname, value))
1653 ui.write('%s=%s\n' % (sectname, value))
1654 matched = True
1654 matched = True
1655 if matched:
1655 if matched:
1656 return 0
1656 return 0
1657 return 1
1657 return 1
1658
1658
1659 @command('copy|cp',
1659 @command('copy|cp',
1660 [('A', 'after', None, _('record a copy that has already occurred')),
1660 [('A', 'after', None, _('record a copy that has already occurred')),
1661 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1661 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1662 ] + walkopts + dryrunopts,
1662 ] + walkopts + dryrunopts,
1663 _('[OPTION]... [SOURCE]... DEST'))
1663 _('[OPTION]... [SOURCE]... DEST'))
1664 def copy(ui, repo, *pats, **opts):
1664 def copy(ui, repo, *pats, **opts):
1665 """mark files as copied for the next commit
1665 """mark files as copied for the next commit
1666
1666
1667 Mark dest as having copies of source files. If dest is a
1667 Mark dest as having copies of source files. If dest is a
1668 directory, copies are put in that directory. If dest is a file,
1668 directory, copies are put in that directory. If dest is a file,
1669 the source must be a single file.
1669 the source must be a single file.
1670
1670
1671 By default, this command copies the contents of files as they
1671 By default, this command copies the contents of files as they
1672 exist in the working directory. If invoked with -A/--after, the
1672 exist in the working directory. If invoked with -A/--after, the
1673 operation is recorded, but no copying is performed.
1673 operation is recorded, but no copying is performed.
1674
1674
1675 This command takes effect with the next commit. To undo a copy
1675 This command takes effect with the next commit. To undo a copy
1676 before that, see :hg:`revert`.
1676 before that, see :hg:`revert`.
1677
1677
1678 Returns 0 on success, 1 if errors are encountered.
1678 Returns 0 on success, 1 if errors are encountered.
1679 """
1679 """
1680 wlock = repo.wlock(False)
1680 wlock = repo.wlock(False)
1681 try:
1681 try:
1682 return cmdutil.copy(ui, repo, pats, opts)
1682 return cmdutil.copy(ui, repo, pats, opts)
1683 finally:
1683 finally:
1684 wlock.release()
1684 wlock.release()
1685
1685
1686 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1686 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1687 def debugancestor(ui, repo, *args):
1687 def debugancestor(ui, repo, *args):
1688 """find the ancestor revision of two revisions in a given index"""
1688 """find the ancestor revision of two revisions in a given index"""
1689 if len(args) == 3:
1689 if len(args) == 3:
1690 index, rev1, rev2 = args
1690 index, rev1, rev2 = args
1691 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1691 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1692 lookup = r.lookup
1692 lookup = r.lookup
1693 elif len(args) == 2:
1693 elif len(args) == 2:
1694 if not repo:
1694 if not repo:
1695 raise util.Abort(_("there is no Mercurial repository here "
1695 raise util.Abort(_("there is no Mercurial repository here "
1696 "(.hg not found)"))
1696 "(.hg not found)"))
1697 rev1, rev2 = args
1697 rev1, rev2 = args
1698 r = repo.changelog
1698 r = repo.changelog
1699 lookup = repo.lookup
1699 lookup = repo.lookup
1700 else:
1700 else:
1701 raise util.Abort(_('either two or three arguments required'))
1701 raise util.Abort(_('either two or three arguments required'))
1702 a = r.ancestor(lookup(rev1), lookup(rev2))
1702 a = r.ancestor(lookup(rev1), lookup(rev2))
1703 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1703 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1704
1704
1705 @command('debugbuilddag',
1705 @command('debugbuilddag',
1706 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1706 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1707 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1707 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1708 ('n', 'new-file', None, _('add new file at each rev'))],
1708 ('n', 'new-file', None, _('add new file at each rev'))],
1709 _('[OPTION]... [TEXT]'))
1709 _('[OPTION]... [TEXT]'))
1710 def debugbuilddag(ui, repo, text=None,
1710 def debugbuilddag(ui, repo, text=None,
1711 mergeable_file=False,
1711 mergeable_file=False,
1712 overwritten_file=False,
1712 overwritten_file=False,
1713 new_file=False):
1713 new_file=False):
1714 """builds a repo with a given DAG from scratch in the current empty repo
1714 """builds a repo with a given DAG from scratch in the current empty repo
1715
1715
1716 The description of the DAG is read from stdin if not given on the
1716 The description of the DAG is read from stdin if not given on the
1717 command line.
1717 command line.
1718
1718
1719 Elements:
1719 Elements:
1720
1720
1721 - "+n" is a linear run of n nodes based on the current default parent
1721 - "+n" is a linear run of n nodes based on the current default parent
1722 - "." is a single node based on the current default parent
1722 - "." is a single node based on the current default parent
1723 - "$" resets the default parent to null (implied at the start);
1723 - "$" resets the default parent to null (implied at the start);
1724 otherwise the default parent is always the last node created
1724 otherwise the default parent is always the last node created
1725 - "<p" sets the default parent to the backref p
1725 - "<p" sets the default parent to the backref p
1726 - "*p" is a fork at parent p, which is a backref
1726 - "*p" is a fork at parent p, which is a backref
1727 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1727 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1728 - "/p2" is a merge of the preceding node and p2
1728 - "/p2" is a merge of the preceding node and p2
1729 - ":tag" defines a local tag for the preceding node
1729 - ":tag" defines a local tag for the preceding node
1730 - "@branch" sets the named branch for subsequent nodes
1730 - "@branch" sets the named branch for subsequent nodes
1731 - "#...\\n" is a comment up to the end of the line
1731 - "#...\\n" is a comment up to the end of the line
1732
1732
1733 Whitespace between the above elements is ignored.
1733 Whitespace between the above elements is ignored.
1734
1734
1735 A backref is either
1735 A backref is either
1736
1736
1737 - a number n, which references the node curr-n, where curr is the current
1737 - a number n, which references the node curr-n, where curr is the current
1738 node, or
1738 node, or
1739 - the name of a local tag you placed earlier using ":tag", or
1739 - the name of a local tag you placed earlier using ":tag", or
1740 - empty to denote the default parent.
1740 - empty to denote the default parent.
1741
1741
1742 All string valued-elements are either strictly alphanumeric, or must
1742 All string valued-elements are either strictly alphanumeric, or must
1743 be enclosed in double quotes ("..."), with "\\" as escape character.
1743 be enclosed in double quotes ("..."), with "\\" as escape character.
1744 """
1744 """
1745
1745
1746 if text is None:
1746 if text is None:
1747 ui.status(_("reading DAG from stdin\n"))
1747 ui.status(_("reading DAG from stdin\n"))
1748 text = ui.fin.read()
1748 text = ui.fin.read()
1749
1749
1750 cl = repo.changelog
1750 cl = repo.changelog
1751 if len(cl) > 0:
1751 if len(cl) > 0:
1752 raise util.Abort(_('repository is not empty'))
1752 raise util.Abort(_('repository is not empty'))
1753
1753
1754 # determine number of revs in DAG
1754 # determine number of revs in DAG
1755 total = 0
1755 total = 0
1756 for type, data in dagparser.parsedag(text):
1756 for type, data in dagparser.parsedag(text):
1757 if type == 'n':
1757 if type == 'n':
1758 total += 1
1758 total += 1
1759
1759
1760 if mergeable_file:
1760 if mergeable_file:
1761 linesperrev = 2
1761 linesperrev = 2
1762 # make a file with k lines per rev
1762 # make a file with k lines per rev
1763 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1763 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1764 initialmergedlines.append("")
1764 initialmergedlines.append("")
1765
1765
1766 tags = []
1766 tags = []
1767
1767
1768 lock = tr = None
1768 lock = tr = None
1769 try:
1769 try:
1770 lock = repo.lock()
1770 lock = repo.lock()
1771 tr = repo.transaction("builddag")
1771 tr = repo.transaction("builddag")
1772
1772
1773 at = -1
1773 at = -1
1774 atbranch = 'default'
1774 atbranch = 'default'
1775 nodeids = []
1775 nodeids = []
1776 id = 0
1776 id = 0
1777 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1777 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1778 for type, data in dagparser.parsedag(text):
1778 for type, data in dagparser.parsedag(text):
1779 if type == 'n':
1779 if type == 'n':
1780 ui.note(('node %s\n' % str(data)))
1780 ui.note(('node %s\n' % str(data)))
1781 id, ps = data
1781 id, ps = data
1782
1782
1783 files = []
1783 files = []
1784 fctxs = {}
1784 fctxs = {}
1785
1785
1786 p2 = None
1786 p2 = None
1787 if mergeable_file:
1787 if mergeable_file:
1788 fn = "mf"
1788 fn = "mf"
1789 p1 = repo[ps[0]]
1789 p1 = repo[ps[0]]
1790 if len(ps) > 1:
1790 if len(ps) > 1:
1791 p2 = repo[ps[1]]
1791 p2 = repo[ps[1]]
1792 pa = p1.ancestor(p2)
1792 pa = p1.ancestor(p2)
1793 base, local, other = [x[fn].data() for x in (pa, p1,
1793 base, local, other = [x[fn].data() for x in (pa, p1,
1794 p2)]
1794 p2)]
1795 m3 = simplemerge.Merge3Text(base, local, other)
1795 m3 = simplemerge.Merge3Text(base, local, other)
1796 ml = [l.strip() for l in m3.merge_lines()]
1796 ml = [l.strip() for l in m3.merge_lines()]
1797 ml.append("")
1797 ml.append("")
1798 elif at > 0:
1798 elif at > 0:
1799 ml = p1[fn].data().split("\n")
1799 ml = p1[fn].data().split("\n")
1800 else:
1800 else:
1801 ml = initialmergedlines
1801 ml = initialmergedlines
1802 ml[id * linesperrev] += " r%i" % id
1802 ml[id * linesperrev] += " r%i" % id
1803 mergedtext = "\n".join(ml)
1803 mergedtext = "\n".join(ml)
1804 files.append(fn)
1804 files.append(fn)
1805 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1805 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1806
1806
1807 if overwritten_file:
1807 if overwritten_file:
1808 fn = "of"
1808 fn = "of"
1809 files.append(fn)
1809 files.append(fn)
1810 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1810 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1811
1811
1812 if new_file:
1812 if new_file:
1813 fn = "nf%i" % id
1813 fn = "nf%i" % id
1814 files.append(fn)
1814 files.append(fn)
1815 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1815 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1816 if len(ps) > 1:
1816 if len(ps) > 1:
1817 if not p2:
1817 if not p2:
1818 p2 = repo[ps[1]]
1818 p2 = repo[ps[1]]
1819 for fn in p2:
1819 for fn in p2:
1820 if fn.startswith("nf"):
1820 if fn.startswith("nf"):
1821 files.append(fn)
1821 files.append(fn)
1822 fctxs[fn] = p2[fn]
1822 fctxs[fn] = p2[fn]
1823
1823
1824 def fctxfn(repo, cx, path):
1824 def fctxfn(repo, cx, path):
1825 return fctxs.get(path)
1825 return fctxs.get(path)
1826
1826
1827 if len(ps) == 0 or ps[0] < 0:
1827 if len(ps) == 0 or ps[0] < 0:
1828 pars = [None, None]
1828 pars = [None, None]
1829 elif len(ps) == 1:
1829 elif len(ps) == 1:
1830 pars = [nodeids[ps[0]], None]
1830 pars = [nodeids[ps[0]], None]
1831 else:
1831 else:
1832 pars = [nodeids[p] for p in ps]
1832 pars = [nodeids[p] for p in ps]
1833 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1833 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1834 date=(id, 0),
1834 date=(id, 0),
1835 user="debugbuilddag",
1835 user="debugbuilddag",
1836 extra={'branch': atbranch})
1836 extra={'branch': atbranch})
1837 nodeid = repo.commitctx(cx)
1837 nodeid = repo.commitctx(cx)
1838 nodeids.append(nodeid)
1838 nodeids.append(nodeid)
1839 at = id
1839 at = id
1840 elif type == 'l':
1840 elif type == 'l':
1841 id, name = data
1841 id, name = data
1842 ui.note(('tag %s\n' % name))
1842 ui.note(('tag %s\n' % name))
1843 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1843 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1844 elif type == 'a':
1844 elif type == 'a':
1845 ui.note(('branch %s\n' % data))
1845 ui.note(('branch %s\n' % data))
1846 atbranch = data
1846 atbranch = data
1847 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1847 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1848 tr.close()
1848 tr.close()
1849
1849
1850 if tags:
1850 if tags:
1851 repo.vfs.write("localtags", "".join(tags))
1851 repo.vfs.write("localtags", "".join(tags))
1852 finally:
1852 finally:
1853 ui.progress(_('building'), None)
1853 ui.progress(_('building'), None)
1854 release(tr, lock)
1854 release(tr, lock)
1855
1855
1856 @command('debugbundle',
1856 @command('debugbundle',
1857 [('a', 'all', None, _('show all details'))],
1857 [('a', 'all', None, _('show all details'))],
1858 _('FILE'),
1858 _('FILE'),
1859 norepo=True)
1859 norepo=True)
1860 def debugbundle(ui, bundlepath, all=None, **opts):
1860 def debugbundle(ui, bundlepath, all=None, **opts):
1861 """lists the contents of a bundle"""
1861 """lists the contents of a bundle"""
1862 f = hg.openpath(ui, bundlepath)
1862 f = hg.openpath(ui, bundlepath)
1863 try:
1863 try:
1864 gen = exchange.readbundle(ui, f, bundlepath)
1864 gen = exchange.readbundle(ui, f, bundlepath)
1865 if isinstance(gen, bundle2.unbundle20):
1865 if isinstance(gen, bundle2.unbundle20):
1866 return _debugbundle2(ui, gen, all=all, **opts)
1866 return _debugbundle2(ui, gen, all=all, **opts)
1867 if all:
1867 if all:
1868 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1868 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1869
1869
1870 def showchunks(named):
1870 def showchunks(named):
1871 ui.write("\n%s\n" % named)
1871 ui.write("\n%s\n" % named)
1872 chain = None
1872 chain = None
1873 while True:
1873 while True:
1874 chunkdata = gen.deltachunk(chain)
1874 chunkdata = gen.deltachunk(chain)
1875 if not chunkdata:
1875 if not chunkdata:
1876 break
1876 break
1877 node = chunkdata['node']
1877 node = chunkdata['node']
1878 p1 = chunkdata['p1']
1878 p1 = chunkdata['p1']
1879 p2 = chunkdata['p2']
1879 p2 = chunkdata['p2']
1880 cs = chunkdata['cs']
1880 cs = chunkdata['cs']
1881 deltabase = chunkdata['deltabase']
1881 deltabase = chunkdata['deltabase']
1882 delta = chunkdata['delta']
1882 delta = chunkdata['delta']
1883 ui.write("%s %s %s %s %s %s\n" %
1883 ui.write("%s %s %s %s %s %s\n" %
1884 (hex(node), hex(p1), hex(p2),
1884 (hex(node), hex(p1), hex(p2),
1885 hex(cs), hex(deltabase), len(delta)))
1885 hex(cs), hex(deltabase), len(delta)))
1886 chain = node
1886 chain = node
1887
1887
1888 chunkdata = gen.changelogheader()
1888 chunkdata = gen.changelogheader()
1889 showchunks("changelog")
1889 showchunks("changelog")
1890 chunkdata = gen.manifestheader()
1890 chunkdata = gen.manifestheader()
1891 showchunks("manifest")
1891 showchunks("manifest")
1892 while True:
1892 while True:
1893 chunkdata = gen.filelogheader()
1893 chunkdata = gen.filelogheader()
1894 if not chunkdata:
1894 if not chunkdata:
1895 break
1895 break
1896 fname = chunkdata['filename']
1896 fname = chunkdata['filename']
1897 showchunks(fname)
1897 showchunks(fname)
1898 else:
1898 else:
1899 if isinstance(gen, bundle2.unbundle20):
1899 if isinstance(gen, bundle2.unbundle20):
1900 raise util.Abort(_('use debugbundle2 for this file'))
1900 raise util.Abort(_('use debugbundle2 for this file'))
1901 chunkdata = gen.changelogheader()
1901 chunkdata = gen.changelogheader()
1902 chain = None
1902 chain = None
1903 while True:
1903 while True:
1904 chunkdata = gen.deltachunk(chain)
1904 chunkdata = gen.deltachunk(chain)
1905 if not chunkdata:
1905 if not chunkdata:
1906 break
1906 break
1907 node = chunkdata['node']
1907 node = chunkdata['node']
1908 ui.write("%s\n" % hex(node))
1908 ui.write("%s\n" % hex(node))
1909 chain = node
1909 chain = node
1910 finally:
1910 finally:
1911 f.close()
1911 f.close()
1912
1912
1913 def _debugbundle2(ui, gen, **opts):
1913 def _debugbundle2(ui, gen, **opts):
1914 """lists the contents of a bundle2"""
1914 """lists the contents of a bundle2"""
1915 if not isinstance(gen, bundle2.unbundle20):
1915 if not isinstance(gen, bundle2.unbundle20):
1916 raise util.Abort(_('not a bundle2 file'))
1916 raise util.Abort(_('not a bundle2 file'))
1917 ui.write(('Stream params: %s\n' % repr(gen.params)))
1917 ui.write(('Stream params: %s\n' % repr(gen.params)))
1918 for part in gen.iterparts():
1918 for part in gen.iterparts():
1919 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1919 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1920 if part.type == 'b2x:changegroup':
1920 if part.type == 'b2x:changegroup':
1921 version = part.params.get('version', '01')
1921 version = part.params.get('version', '01')
1922 cg = changegroup.packermap[version][1](part, 'UN')
1922 cg = changegroup.packermap[version][1](part, 'UN')
1923 chunkdata = cg.changelogheader()
1923 chunkdata = cg.changelogheader()
1924 chain = None
1924 chain = None
1925 while True:
1925 while True:
1926 chunkdata = cg.deltachunk(chain)
1926 chunkdata = cg.deltachunk(chain)
1927 if not chunkdata:
1927 if not chunkdata:
1928 break
1928 break
1929 node = chunkdata['node']
1929 node = chunkdata['node']
1930 ui.write(" %s\n" % hex(node))
1930 ui.write(" %s\n" % hex(node))
1931 chain = node
1931 chain = node
1932
1932
1933 @command('debugcheckstate', [], '')
1933 @command('debugcheckstate', [], '')
1934 def debugcheckstate(ui, repo):
1934 def debugcheckstate(ui, repo):
1935 """validate the correctness of the current dirstate"""
1935 """validate the correctness of the current dirstate"""
1936 parent1, parent2 = repo.dirstate.parents()
1936 parent1, parent2 = repo.dirstate.parents()
1937 m1 = repo[parent1].manifest()
1937 m1 = repo[parent1].manifest()
1938 m2 = repo[parent2].manifest()
1938 m2 = repo[parent2].manifest()
1939 errors = 0
1939 errors = 0
1940 for f in repo.dirstate:
1940 for f in repo.dirstate:
1941 state = repo.dirstate[f]
1941 state = repo.dirstate[f]
1942 if state in "nr" and f not in m1:
1942 if state in "nr" and f not in m1:
1943 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1943 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1944 errors += 1
1944 errors += 1
1945 if state in "a" and f in m1:
1945 if state in "a" and f in m1:
1946 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1946 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1947 errors += 1
1947 errors += 1
1948 if state in "m" and f not in m1 and f not in m2:
1948 if state in "m" and f not in m1 and f not in m2:
1949 ui.warn(_("%s in state %s, but not in either manifest\n") %
1949 ui.warn(_("%s in state %s, but not in either manifest\n") %
1950 (f, state))
1950 (f, state))
1951 errors += 1
1951 errors += 1
1952 for f in m1:
1952 for f in m1:
1953 state = repo.dirstate[f]
1953 state = repo.dirstate[f]
1954 if state not in "nrm":
1954 if state not in "nrm":
1955 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1955 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1956 errors += 1
1956 errors += 1
1957 if errors:
1957 if errors:
1958 error = _(".hg/dirstate inconsistent with current parent's manifest")
1958 error = _(".hg/dirstate inconsistent with current parent's manifest")
1959 raise util.Abort(error)
1959 raise util.Abort(error)
1960
1960
1961 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1961 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1962 def debugcommands(ui, cmd='', *args):
1962 def debugcommands(ui, cmd='', *args):
1963 """list all available commands and options"""
1963 """list all available commands and options"""
1964 for cmd, vals in sorted(table.iteritems()):
1964 for cmd, vals in sorted(table.iteritems()):
1965 cmd = cmd.split('|')[0].strip('^')
1965 cmd = cmd.split('|')[0].strip('^')
1966 opts = ', '.join([i[1] for i in vals[1]])
1966 opts = ', '.join([i[1] for i in vals[1]])
1967 ui.write('%s: %s\n' % (cmd, opts))
1967 ui.write('%s: %s\n' % (cmd, opts))
1968
1968
1969 @command('debugcomplete',
1969 @command('debugcomplete',
1970 [('o', 'options', None, _('show the command options'))],
1970 [('o', 'options', None, _('show the command options'))],
1971 _('[-o] CMD'),
1971 _('[-o] CMD'),
1972 norepo=True)
1972 norepo=True)
1973 def debugcomplete(ui, cmd='', **opts):
1973 def debugcomplete(ui, cmd='', **opts):
1974 """returns the completion list associated with the given command"""
1974 """returns the completion list associated with the given command"""
1975
1975
1976 if opts.get('options'):
1976 if opts.get('options'):
1977 options = []
1977 options = []
1978 otables = [globalopts]
1978 otables = [globalopts]
1979 if cmd:
1979 if cmd:
1980 aliases, entry = cmdutil.findcmd(cmd, table, False)
1980 aliases, entry = cmdutil.findcmd(cmd, table, False)
1981 otables.append(entry[1])
1981 otables.append(entry[1])
1982 for t in otables:
1982 for t in otables:
1983 for o in t:
1983 for o in t:
1984 if "(DEPRECATED)" in o[3]:
1984 if "(DEPRECATED)" in o[3]:
1985 continue
1985 continue
1986 if o[0]:
1986 if o[0]:
1987 options.append('-%s' % o[0])
1987 options.append('-%s' % o[0])
1988 options.append('--%s' % o[1])
1988 options.append('--%s' % o[1])
1989 ui.write("%s\n" % "\n".join(options))
1989 ui.write("%s\n" % "\n".join(options))
1990 return
1990 return
1991
1991
1992 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1992 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1993 if ui.verbose:
1993 if ui.verbose:
1994 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1994 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1995 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1995 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1996
1996
1997 @command('debugdag',
1997 @command('debugdag',
1998 [('t', 'tags', None, _('use tags as labels')),
1998 [('t', 'tags', None, _('use tags as labels')),
1999 ('b', 'branches', None, _('annotate with branch names')),
1999 ('b', 'branches', None, _('annotate with branch names')),
2000 ('', 'dots', None, _('use dots for runs')),
2000 ('', 'dots', None, _('use dots for runs')),
2001 ('s', 'spaces', None, _('separate elements by spaces'))],
2001 ('s', 'spaces', None, _('separate elements by spaces'))],
2002 _('[OPTION]... [FILE [REV]...]'),
2002 _('[OPTION]... [FILE [REV]...]'),
2003 optionalrepo=True)
2003 optionalrepo=True)
2004 def debugdag(ui, repo, file_=None, *revs, **opts):
2004 def debugdag(ui, repo, file_=None, *revs, **opts):
2005 """format the changelog or an index DAG as a concise textual description
2005 """format the changelog or an index DAG as a concise textual description
2006
2006
2007 If you pass a revlog index, the revlog's DAG is emitted. If you list
2007 If you pass a revlog index, the revlog's DAG is emitted. If you list
2008 revision numbers, they get labeled in the output as rN.
2008 revision numbers, they get labeled in the output as rN.
2009
2009
2010 Otherwise, the changelog DAG of the current repo is emitted.
2010 Otherwise, the changelog DAG of the current repo is emitted.
2011 """
2011 """
2012 spaces = opts.get('spaces')
2012 spaces = opts.get('spaces')
2013 dots = opts.get('dots')
2013 dots = opts.get('dots')
2014 if file_:
2014 if file_:
2015 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2015 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2016 revs = set((int(r) for r in revs))
2016 revs = set((int(r) for r in revs))
2017 def events():
2017 def events():
2018 for r in rlog:
2018 for r in rlog:
2019 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2019 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2020 if p != -1))
2020 if p != -1))
2021 if r in revs:
2021 if r in revs:
2022 yield 'l', (r, "r%i" % r)
2022 yield 'l', (r, "r%i" % r)
2023 elif repo:
2023 elif repo:
2024 cl = repo.changelog
2024 cl = repo.changelog
2025 tags = opts.get('tags')
2025 tags = opts.get('tags')
2026 branches = opts.get('branches')
2026 branches = opts.get('branches')
2027 if tags:
2027 if tags:
2028 labels = {}
2028 labels = {}
2029 for l, n in repo.tags().items():
2029 for l, n in repo.tags().items():
2030 labels.setdefault(cl.rev(n), []).append(l)
2030 labels.setdefault(cl.rev(n), []).append(l)
2031 def events():
2031 def events():
2032 b = "default"
2032 b = "default"
2033 for r in cl:
2033 for r in cl:
2034 if branches:
2034 if branches:
2035 newb = cl.read(cl.node(r))[5]['branch']
2035 newb = cl.read(cl.node(r))[5]['branch']
2036 if newb != b:
2036 if newb != b:
2037 yield 'a', newb
2037 yield 'a', newb
2038 b = newb
2038 b = newb
2039 yield 'n', (r, list(p for p in cl.parentrevs(r)
2039 yield 'n', (r, list(p for p in cl.parentrevs(r)
2040 if p != -1))
2040 if p != -1))
2041 if tags:
2041 if tags:
2042 ls = labels.get(r)
2042 ls = labels.get(r)
2043 if ls:
2043 if ls:
2044 for l in ls:
2044 for l in ls:
2045 yield 'l', (r, l)
2045 yield 'l', (r, l)
2046 else:
2046 else:
2047 raise util.Abort(_('need repo for changelog dag'))
2047 raise util.Abort(_('need repo for changelog dag'))
2048
2048
2049 for line in dagparser.dagtextlines(events(),
2049 for line in dagparser.dagtextlines(events(),
2050 addspaces=spaces,
2050 addspaces=spaces,
2051 wraplabels=True,
2051 wraplabels=True,
2052 wrapannotations=True,
2052 wrapannotations=True,
2053 wrapnonlinear=dots,
2053 wrapnonlinear=dots,
2054 usedots=dots,
2054 usedots=dots,
2055 maxlinewidth=70):
2055 maxlinewidth=70):
2056 ui.write(line)
2056 ui.write(line)
2057 ui.write("\n")
2057 ui.write("\n")
2058
2058
2059 @command('debugdata',
2059 @command('debugdata',
2060 [('c', 'changelog', False, _('open changelog')),
2060 [('c', 'changelog', False, _('open changelog')),
2061 ('m', 'manifest', False, _('open manifest'))],
2061 ('m', 'manifest', False, _('open manifest'))],
2062 _('-c|-m|FILE REV'))
2062 _('-c|-m|FILE REV'))
2063 def debugdata(ui, repo, file_, rev=None, **opts):
2063 def debugdata(ui, repo, file_, rev=None, **opts):
2064 """dump the contents of a data file revision"""
2064 """dump the contents of a data file revision"""
2065 if opts.get('changelog') or opts.get('manifest'):
2065 if opts.get('changelog') or opts.get('manifest'):
2066 file_, rev = None, file_
2066 file_, rev = None, file_
2067 elif rev is None:
2067 elif rev is None:
2068 raise error.CommandError('debugdata', _('invalid arguments'))
2068 raise error.CommandError('debugdata', _('invalid arguments'))
2069 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2069 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2070 try:
2070 try:
2071 ui.write(r.revision(r.lookup(rev)))
2071 ui.write(r.revision(r.lookup(rev)))
2072 except KeyError:
2072 except KeyError:
2073 raise util.Abort(_('invalid revision identifier %s') % rev)
2073 raise util.Abort(_('invalid revision identifier %s') % rev)
2074
2074
2075 @command('debugdate',
2075 @command('debugdate',
2076 [('e', 'extended', None, _('try extended date formats'))],
2076 [('e', 'extended', None, _('try extended date formats'))],
2077 _('[-e] DATE [RANGE]'),
2077 _('[-e] DATE [RANGE]'),
2078 norepo=True, optionalrepo=True)
2078 norepo=True, optionalrepo=True)
2079 def debugdate(ui, date, range=None, **opts):
2079 def debugdate(ui, date, range=None, **opts):
2080 """parse and display a date"""
2080 """parse and display a date"""
2081 if opts["extended"]:
2081 if opts["extended"]:
2082 d = util.parsedate(date, util.extendeddateformats)
2082 d = util.parsedate(date, util.extendeddateformats)
2083 else:
2083 else:
2084 d = util.parsedate(date)
2084 d = util.parsedate(date)
2085 ui.write(("internal: %s %s\n") % d)
2085 ui.write(("internal: %s %s\n") % d)
2086 ui.write(("standard: %s\n") % util.datestr(d))
2086 ui.write(("standard: %s\n") % util.datestr(d))
2087 if range:
2087 if range:
2088 m = util.matchdate(range)
2088 m = util.matchdate(range)
2089 ui.write(("match: %s\n") % m(d[0]))
2089 ui.write(("match: %s\n") % m(d[0]))
2090
2090
2091 @command('debugdiscovery',
2091 @command('debugdiscovery',
2092 [('', 'old', None, _('use old-style discovery')),
2092 [('', 'old', None, _('use old-style discovery')),
2093 ('', 'nonheads', None,
2093 ('', 'nonheads', None,
2094 _('use old-style discovery with non-heads included')),
2094 _('use old-style discovery with non-heads included')),
2095 ] + remoteopts,
2095 ] + remoteopts,
2096 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2096 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2097 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2097 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2098 """runs the changeset discovery protocol in isolation"""
2098 """runs the changeset discovery protocol in isolation"""
2099 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2099 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2100 opts.get('branch'))
2100 opts.get('branch'))
2101 remote = hg.peer(repo, opts, remoteurl)
2101 remote = hg.peer(repo, opts, remoteurl)
2102 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2102 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2103
2103
2104 # make sure tests are repeatable
2104 # make sure tests are repeatable
2105 random.seed(12323)
2105 random.seed(12323)
2106
2106
2107 def doit(localheads, remoteheads, remote=remote):
2107 def doit(localheads, remoteheads, remote=remote):
2108 if opts.get('old'):
2108 if opts.get('old'):
2109 if localheads:
2109 if localheads:
2110 raise util.Abort('cannot use localheads with old style '
2110 raise util.Abort('cannot use localheads with old style '
2111 'discovery')
2111 'discovery')
2112 if not util.safehasattr(remote, 'branches'):
2112 if not util.safehasattr(remote, 'branches'):
2113 # enable in-client legacy support
2113 # enable in-client legacy support
2114 remote = localrepo.locallegacypeer(remote.local())
2114 remote = localrepo.locallegacypeer(remote.local())
2115 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2115 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2116 force=True)
2116 force=True)
2117 common = set(common)
2117 common = set(common)
2118 if not opts.get('nonheads'):
2118 if not opts.get('nonheads'):
2119 ui.write(("unpruned common: %s\n") %
2119 ui.write(("unpruned common: %s\n") %
2120 " ".join(sorted(short(n) for n in common)))
2120 " ".join(sorted(short(n) for n in common)))
2121 dag = dagutil.revlogdag(repo.changelog)
2121 dag = dagutil.revlogdag(repo.changelog)
2122 all = dag.ancestorset(dag.internalizeall(common))
2122 all = dag.ancestorset(dag.internalizeall(common))
2123 common = dag.externalizeall(dag.headsetofconnecteds(all))
2123 common = dag.externalizeall(dag.headsetofconnecteds(all))
2124 else:
2124 else:
2125 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2125 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2126 common = set(common)
2126 common = set(common)
2127 rheads = set(hds)
2127 rheads = set(hds)
2128 lheads = set(repo.heads())
2128 lheads = set(repo.heads())
2129 ui.write(("common heads: %s\n") %
2129 ui.write(("common heads: %s\n") %
2130 " ".join(sorted(short(n) for n in common)))
2130 " ".join(sorted(short(n) for n in common)))
2131 if lheads <= common:
2131 if lheads <= common:
2132 ui.write(("local is subset\n"))
2132 ui.write(("local is subset\n"))
2133 elif rheads <= common:
2133 elif rheads <= common:
2134 ui.write(("remote is subset\n"))
2134 ui.write(("remote is subset\n"))
2135
2135
2136 serverlogs = opts.get('serverlog')
2136 serverlogs = opts.get('serverlog')
2137 if serverlogs:
2137 if serverlogs:
2138 for filename in serverlogs:
2138 for filename in serverlogs:
2139 logfile = open(filename, 'r')
2139 logfile = open(filename, 'r')
2140 try:
2140 try:
2141 line = logfile.readline()
2141 line = logfile.readline()
2142 while line:
2142 while line:
2143 parts = line.strip().split(';')
2143 parts = line.strip().split(';')
2144 op = parts[1]
2144 op = parts[1]
2145 if op == 'cg':
2145 if op == 'cg':
2146 pass
2146 pass
2147 elif op == 'cgss':
2147 elif op == 'cgss':
2148 doit(parts[2].split(' '), parts[3].split(' '))
2148 doit(parts[2].split(' '), parts[3].split(' '))
2149 elif op == 'unb':
2149 elif op == 'unb':
2150 doit(parts[3].split(' '), parts[2].split(' '))
2150 doit(parts[3].split(' '), parts[2].split(' '))
2151 line = logfile.readline()
2151 line = logfile.readline()
2152 finally:
2152 finally:
2153 logfile.close()
2153 logfile.close()
2154
2154
2155 else:
2155 else:
2156 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2156 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2157 opts.get('remote_head'))
2157 opts.get('remote_head'))
2158 localrevs = opts.get('local_head')
2158 localrevs = opts.get('local_head')
2159 doit(localrevs, remoterevs)
2159 doit(localrevs, remoterevs)
2160
2160
2161 @command('debugfileset',
2161 @command('debugfileset',
2162 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2162 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2163 _('[-r REV] FILESPEC'))
2163 _('[-r REV] FILESPEC'))
2164 def debugfileset(ui, repo, expr, **opts):
2164 def debugfileset(ui, repo, expr, **opts):
2165 '''parse and apply a fileset specification'''
2165 '''parse and apply a fileset specification'''
2166 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2166 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2167 if ui.verbose:
2167 if ui.verbose:
2168 tree = fileset.parse(expr)[0]
2168 tree = fileset.parse(expr)[0]
2169 ui.note(tree, "\n")
2169 ui.note(tree, "\n")
2170
2170
2171 for f in ctx.getfileset(expr):
2171 for f in ctx.getfileset(expr):
2172 ui.write("%s\n" % f)
2172 ui.write("%s\n" % f)
2173
2173
2174 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2174 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2175 def debugfsinfo(ui, path="."):
2175 def debugfsinfo(ui, path="."):
2176 """show information detected about current filesystem"""
2176 """show information detected about current filesystem"""
2177 util.writefile('.debugfsinfo', '')
2177 util.writefile('.debugfsinfo', '')
2178 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2178 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2179 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2179 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2180 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2180 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2181 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2181 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2182 and 'yes' or 'no'))
2182 and 'yes' or 'no'))
2183 os.unlink('.debugfsinfo')
2183 os.unlink('.debugfsinfo')
2184
2184
2185 @command('debuggetbundle',
2185 @command('debuggetbundle',
2186 [('H', 'head', [], _('id of head node'), _('ID')),
2186 [('H', 'head', [], _('id of head node'), _('ID')),
2187 ('C', 'common', [], _('id of common node'), _('ID')),
2187 ('C', 'common', [], _('id of common node'), _('ID')),
2188 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2188 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2189 _('REPO FILE [-H|-C ID]...'),
2189 _('REPO FILE [-H|-C ID]...'),
2190 norepo=True)
2190 norepo=True)
2191 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2191 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2192 """retrieves a bundle from a repo
2192 """retrieves a bundle from a repo
2193
2193
2194 Every ID must be a full-length hex node id string. Saves the bundle to the
2194 Every ID must be a full-length hex node id string. Saves the bundle to the
2195 given file.
2195 given file.
2196 """
2196 """
2197 repo = hg.peer(ui, opts, repopath)
2197 repo = hg.peer(ui, opts, repopath)
2198 if not repo.capable('getbundle'):
2198 if not repo.capable('getbundle'):
2199 raise util.Abort("getbundle() not supported by target repository")
2199 raise util.Abort("getbundle() not supported by target repository")
2200 args = {}
2200 args = {}
2201 if common:
2201 if common:
2202 args['common'] = [bin(s) for s in common]
2202 args['common'] = [bin(s) for s in common]
2203 if head:
2203 if head:
2204 args['heads'] = [bin(s) for s in head]
2204 args['heads'] = [bin(s) for s in head]
2205 # TODO: get desired bundlecaps from command line.
2205 # TODO: get desired bundlecaps from command line.
2206 args['bundlecaps'] = None
2206 args['bundlecaps'] = None
2207 bundle = repo.getbundle('debug', **args)
2207 bundle = repo.getbundle('debug', **args)
2208
2208
2209 bundletype = opts.get('type', 'bzip2').lower()
2209 bundletype = opts.get('type', 'bzip2').lower()
2210 btypes = {'none': 'HG10UN',
2210 btypes = {'none': 'HG10UN',
2211 'bzip2': 'HG10BZ',
2211 'bzip2': 'HG10BZ',
2212 'gzip': 'HG10GZ',
2212 'gzip': 'HG10GZ',
2213 'bundle2': 'HG2Y'}
2213 'bundle2': 'HG2Y'}
2214 bundletype = btypes.get(bundletype)
2214 bundletype = btypes.get(bundletype)
2215 if bundletype not in changegroup.bundletypes:
2215 if bundletype not in changegroup.bundletypes:
2216 raise util.Abort(_('unknown bundle type specified with --type'))
2216 raise util.Abort(_('unknown bundle type specified with --type'))
2217 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2217 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2218
2218
2219 @command('debugignore', [], '')
2219 @command('debugignore', [], '')
2220 def debugignore(ui, repo, *values, **opts):
2220 def debugignore(ui, repo, *values, **opts):
2221 """display the combined ignore pattern"""
2221 """display the combined ignore pattern"""
2222 ignore = repo.dirstate._ignore
2222 ignore = repo.dirstate._ignore
2223 includepat = getattr(ignore, 'includepat', None)
2223 includepat = getattr(ignore, 'includepat', None)
2224 if includepat is not None:
2224 if includepat is not None:
2225 ui.write("%s\n" % includepat)
2225 ui.write("%s\n" % includepat)
2226 else:
2226 else:
2227 raise util.Abort(_("no ignore patterns found"))
2227 raise util.Abort(_("no ignore patterns found"))
2228
2228
2229 @command('debugindex',
2229 @command('debugindex',
2230 [('c', 'changelog', False, _('open changelog')),
2230 [('c', 'changelog', False, _('open changelog')),
2231 ('m', 'manifest', False, _('open manifest')),
2231 ('m', 'manifest', False, _('open manifest')),
2232 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2232 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2233 _('[-f FORMAT] -c|-m|FILE'),
2233 _('[-f FORMAT] -c|-m|FILE'),
2234 optionalrepo=True)
2234 optionalrepo=True)
2235 def debugindex(ui, repo, file_=None, **opts):
2235 def debugindex(ui, repo, file_=None, **opts):
2236 """dump the contents of an index file"""
2236 """dump the contents of an index file"""
2237 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2237 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2238 format = opts.get('format', 0)
2238 format = opts.get('format', 0)
2239 if format not in (0, 1):
2239 if format not in (0, 1):
2240 raise util.Abort(_("unknown format %d") % format)
2240 raise util.Abort(_("unknown format %d") % format)
2241
2241
2242 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2242 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2243 if generaldelta:
2243 if generaldelta:
2244 basehdr = ' delta'
2244 basehdr = ' delta'
2245 else:
2245 else:
2246 basehdr = ' base'
2246 basehdr = ' base'
2247
2247
2248 if ui.debugflag:
2248 if ui.debugflag:
2249 shortfn = hex
2249 shortfn = hex
2250 else:
2250 else:
2251 shortfn = short
2251 shortfn = short
2252
2252
2253 # There might not be anything in r, so have a sane default
2253 # There might not be anything in r, so have a sane default
2254 idlen = 12
2254 idlen = 12
2255 for i in r:
2255 for i in r:
2256 idlen = len(shortfn(r.node(i)))
2256 idlen = len(shortfn(r.node(i)))
2257 break
2257 break
2258
2258
2259 if format == 0:
2259 if format == 0:
2260 ui.write(" rev offset length " + basehdr + " linkrev"
2260 ui.write(" rev offset length " + basehdr + " linkrev"
2261 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2261 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2262 elif format == 1:
2262 elif format == 1:
2263 ui.write(" rev flag offset length"
2263 ui.write(" rev flag offset length"
2264 " size " + basehdr + " link p1 p2"
2264 " size " + basehdr + " link p1 p2"
2265 " %s\n" % "nodeid".rjust(idlen))
2265 " %s\n" % "nodeid".rjust(idlen))
2266
2266
2267 for i in r:
2267 for i in r:
2268 node = r.node(i)
2268 node = r.node(i)
2269 if generaldelta:
2269 if generaldelta:
2270 base = r.deltaparent(i)
2270 base = r.deltaparent(i)
2271 else:
2271 else:
2272 base = r.chainbase(i)
2272 base = r.chainbase(i)
2273 if format == 0:
2273 if format == 0:
2274 try:
2274 try:
2275 pp = r.parents(node)
2275 pp = r.parents(node)
2276 except Exception:
2276 except Exception:
2277 pp = [nullid, nullid]
2277 pp = [nullid, nullid]
2278 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2278 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2279 i, r.start(i), r.length(i), base, r.linkrev(i),
2279 i, r.start(i), r.length(i), base, r.linkrev(i),
2280 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2280 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2281 elif format == 1:
2281 elif format == 1:
2282 pr = r.parentrevs(i)
2282 pr = r.parentrevs(i)
2283 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2283 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2284 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2284 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2285 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2285 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2286
2286
2287 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2287 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2288 def debugindexdot(ui, repo, file_):
2288 def debugindexdot(ui, repo, file_):
2289 """dump an index DAG as a graphviz dot file"""
2289 """dump an index DAG as a graphviz dot file"""
2290 r = None
2290 r = None
2291 if repo:
2291 if repo:
2292 filelog = repo.file(file_)
2292 filelog = repo.file(file_)
2293 if len(filelog):
2293 if len(filelog):
2294 r = filelog
2294 r = filelog
2295 if not r:
2295 if not r:
2296 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2296 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2297 ui.write(("digraph G {\n"))
2297 ui.write(("digraph G {\n"))
2298 for i in r:
2298 for i in r:
2299 node = r.node(i)
2299 node = r.node(i)
2300 pp = r.parents(node)
2300 pp = r.parents(node)
2301 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2301 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2302 if pp[1] != nullid:
2302 if pp[1] != nullid:
2303 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2303 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2304 ui.write("}\n")
2304 ui.write("}\n")
2305
2305
2306 @command('debuginstall', [], '', norepo=True)
2306 @command('debuginstall', [], '', norepo=True)
2307 def debuginstall(ui):
2307 def debuginstall(ui):
2308 '''test Mercurial installation
2308 '''test Mercurial installation
2309
2309
2310 Returns 0 on success.
2310 Returns 0 on success.
2311 '''
2311 '''
2312
2312
2313 def writetemp(contents):
2313 def writetemp(contents):
2314 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2314 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2315 f = os.fdopen(fd, "wb")
2315 f = os.fdopen(fd, "wb")
2316 f.write(contents)
2316 f.write(contents)
2317 f.close()
2317 f.close()
2318 return name
2318 return name
2319
2319
2320 problems = 0
2320 problems = 0
2321
2321
2322 # encoding
2322 # encoding
2323 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2323 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2324 try:
2324 try:
2325 encoding.fromlocal("test")
2325 encoding.fromlocal("test")
2326 except util.Abort, inst:
2326 except util.Abort, inst:
2327 ui.write(" %s\n" % inst)
2327 ui.write(" %s\n" % inst)
2328 ui.write(_(" (check that your locale is properly set)\n"))
2328 ui.write(_(" (check that your locale is properly set)\n"))
2329 problems += 1
2329 problems += 1
2330
2330
2331 # Python
2331 # Python
2332 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2332 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2333 ui.status(_("checking Python version (%s)\n")
2333 ui.status(_("checking Python version (%s)\n")
2334 % ("%s.%s.%s" % sys.version_info[:3]))
2334 % ("%s.%s.%s" % sys.version_info[:3]))
2335 ui.status(_("checking Python lib (%s)...\n")
2335 ui.status(_("checking Python lib (%s)...\n")
2336 % os.path.dirname(os.__file__))
2336 % os.path.dirname(os.__file__))
2337
2337
2338 # compiled modules
2338 # compiled modules
2339 ui.status(_("checking installed modules (%s)...\n")
2339 ui.status(_("checking installed modules (%s)...\n")
2340 % os.path.dirname(__file__))
2340 % os.path.dirname(__file__))
2341 try:
2341 try:
2342 import bdiff, mpatch, base85, osutil
2342 import bdiff, mpatch, base85, osutil
2343 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2343 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2344 except Exception, inst:
2344 except Exception, inst:
2345 ui.write(" %s\n" % inst)
2345 ui.write(" %s\n" % inst)
2346 ui.write(_(" One or more extensions could not be found"))
2346 ui.write(_(" One or more extensions could not be found"))
2347 ui.write(_(" (check that you compiled the extensions)\n"))
2347 ui.write(_(" (check that you compiled the extensions)\n"))
2348 problems += 1
2348 problems += 1
2349
2349
2350 # templates
2350 # templates
2351 import templater
2351 import templater
2352 p = templater.templatepaths()
2352 p = templater.templatepaths()
2353 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2353 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2354 if p:
2354 if p:
2355 m = templater.templatepath("map-cmdline.default")
2355 m = templater.templatepath("map-cmdline.default")
2356 if m:
2356 if m:
2357 # template found, check if it is working
2357 # template found, check if it is working
2358 try:
2358 try:
2359 templater.templater(m)
2359 templater.templater(m)
2360 except Exception, inst:
2360 except Exception, inst:
2361 ui.write(" %s\n" % inst)
2361 ui.write(" %s\n" % inst)
2362 p = None
2362 p = None
2363 else:
2363 else:
2364 ui.write(_(" template 'default' not found\n"))
2364 ui.write(_(" template 'default' not found\n"))
2365 p = None
2365 p = None
2366 else:
2366 else:
2367 ui.write(_(" no template directories found\n"))
2367 ui.write(_(" no template directories found\n"))
2368 if not p:
2368 if not p:
2369 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2369 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2370 problems += 1
2370 problems += 1
2371
2371
2372 # editor
2372 # editor
2373 ui.status(_("checking commit editor...\n"))
2373 ui.status(_("checking commit editor...\n"))
2374 editor = ui.geteditor()
2374 editor = ui.geteditor()
2375 cmdpath = util.findexe(shlex.split(editor)[0])
2375 cmdpath = util.findexe(shlex.split(editor)[0])
2376 if not cmdpath:
2376 if not cmdpath:
2377 if editor == 'vi':
2377 if editor == 'vi':
2378 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2378 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2379 ui.write(_(" (specify a commit editor in your configuration"
2379 ui.write(_(" (specify a commit editor in your configuration"
2380 " file)\n"))
2380 " file)\n"))
2381 else:
2381 else:
2382 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2382 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2383 ui.write(_(" (specify a commit editor in your configuration"
2383 ui.write(_(" (specify a commit editor in your configuration"
2384 " file)\n"))
2384 " file)\n"))
2385 problems += 1
2385 problems += 1
2386
2386
2387 # check username
2387 # check username
2388 ui.status(_("checking username...\n"))
2388 ui.status(_("checking username...\n"))
2389 try:
2389 try:
2390 ui.username()
2390 ui.username()
2391 except util.Abort, e:
2391 except util.Abort, e:
2392 ui.write(" %s\n" % e)
2392 ui.write(" %s\n" % e)
2393 ui.write(_(" (specify a username in your configuration file)\n"))
2393 ui.write(_(" (specify a username in your configuration file)\n"))
2394 problems += 1
2394 problems += 1
2395
2395
2396 if not problems:
2396 if not problems:
2397 ui.status(_("no problems detected\n"))
2397 ui.status(_("no problems detected\n"))
2398 else:
2398 else:
2399 ui.write(_("%s problems detected,"
2399 ui.write(_("%s problems detected,"
2400 " please check your install!\n") % problems)
2400 " please check your install!\n") % problems)
2401
2401
2402 return problems
2402 return problems
2403
2403
2404 @command('debugknown', [], _('REPO ID...'), norepo=True)
2404 @command('debugknown', [], _('REPO ID...'), norepo=True)
2405 def debugknown(ui, repopath, *ids, **opts):
2405 def debugknown(ui, repopath, *ids, **opts):
2406 """test whether node ids are known to a repo
2406 """test whether node ids are known to a repo
2407
2407
2408 Every ID must be a full-length hex node id string. Returns a list of 0s
2408 Every ID must be a full-length hex node id string. Returns a list of 0s
2409 and 1s indicating unknown/known.
2409 and 1s indicating unknown/known.
2410 """
2410 """
2411 repo = hg.peer(ui, opts, repopath)
2411 repo = hg.peer(ui, opts, repopath)
2412 if not repo.capable('known'):
2412 if not repo.capable('known'):
2413 raise util.Abort("known() not supported by target repository")
2413 raise util.Abort("known() not supported by target repository")
2414 flags = repo.known([bin(s) for s in ids])
2414 flags = repo.known([bin(s) for s in ids])
2415 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2415 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2416
2416
2417 @command('debuglabelcomplete', [], _('LABEL...'))
2417 @command('debuglabelcomplete', [], _('LABEL...'))
2418 def debuglabelcomplete(ui, repo, *args):
2418 def debuglabelcomplete(ui, repo, *args):
2419 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2419 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2420 debugnamecomplete(ui, repo, *args)
2420 debugnamecomplete(ui, repo, *args)
2421
2421
2422 @command('debugnamecomplete', [], _('NAME...'))
2422 @command('debugnamecomplete', [], _('NAME...'))
2423 def debugnamecomplete(ui, repo, *args):
2423 def debugnamecomplete(ui, repo, *args):
2424 '''complete "names" - tags, open branch names, bookmark names'''
2424 '''complete "names" - tags, open branch names, bookmark names'''
2425
2425
2426 names = set()
2426 names = set()
2427 # since we previously only listed open branches, we will handle that
2427 # since we previously only listed open branches, we will handle that
2428 # specially (after this for loop)
2428 # specially (after this for loop)
2429 for name, ns in repo.names.iteritems():
2429 for name, ns in repo.names.iteritems():
2430 if name != 'branches':
2430 if name != 'branches':
2431 names.update(ns.listnames(repo))
2431 names.update(ns.listnames(repo))
2432 names.update(tag for (tag, heads, tip, closed)
2432 names.update(tag for (tag, heads, tip, closed)
2433 in repo.branchmap().iterbranches() if not closed)
2433 in repo.branchmap().iterbranches() if not closed)
2434 completions = set()
2434 completions = set()
2435 if not args:
2435 if not args:
2436 args = ['']
2436 args = ['']
2437 for a in args:
2437 for a in args:
2438 completions.update(n for n in names if n.startswith(a))
2438 completions.update(n for n in names if n.startswith(a))
2439 ui.write('\n'.join(sorted(completions)))
2439 ui.write('\n'.join(sorted(completions)))
2440 ui.write('\n')
2440 ui.write('\n')
2441
2441
2442 @command('debuglocks',
2442 @command('debuglocks',
2443 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2443 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2444 ('W', 'force-wlock', None,
2444 ('W', 'force-wlock', None,
2445 _('free the working state lock (DANGEROUS)'))],
2445 _('free the working state lock (DANGEROUS)'))],
2446 _('[OPTION]...'))
2446 _('[OPTION]...'))
2447 def debuglocks(ui, repo, **opts):
2447 def debuglocks(ui, repo, **opts):
2448 """show or modify state of locks
2448 """show or modify state of locks
2449
2449
2450 By default, this command will show which locks are held. This
2450 By default, this command will show which locks are held. This
2451 includes the user and process holding the lock, the amount of time
2451 includes the user and process holding the lock, the amount of time
2452 the lock has been held, and the machine name where the process is
2452 the lock has been held, and the machine name where the process is
2453 running if it's not local.
2453 running if it's not local.
2454
2454
2455 Locks protect the integrity of Mercurial's data, so should be
2455 Locks protect the integrity of Mercurial's data, so should be
2456 treated with care. System crashes or other interruptions may cause
2456 treated with care. System crashes or other interruptions may cause
2457 locks to not be properly released, though Mercurial will usually
2457 locks to not be properly released, though Mercurial will usually
2458 detect and remove such stale locks automatically.
2458 detect and remove such stale locks automatically.
2459
2459
2460 However, detecting stale locks may not always be possible (for
2460 However, detecting stale locks may not always be possible (for
2461 instance, on a shared filesystem). Removing locks may also be
2461 instance, on a shared filesystem). Removing locks may also be
2462 blocked by filesystem permissions.
2462 blocked by filesystem permissions.
2463
2463
2464 Returns 0 if no locks are held.
2464 Returns 0 if no locks are held.
2465
2465
2466 """
2466 """
2467
2467
2468 if opts.get('force_lock'):
2468 if opts.get('force_lock'):
2469 repo.svfs.unlink('lock')
2469 repo.svfs.unlink('lock')
2470 if opts.get('force_wlock'):
2470 if opts.get('force_wlock'):
2471 repo.vfs.unlink('wlock')
2471 repo.vfs.unlink('wlock')
2472 if opts.get('force_lock') or opts.get('force_lock'):
2472 if opts.get('force_lock') or opts.get('force_lock'):
2473 return 0
2473 return 0
2474
2474
2475 now = time.time()
2475 now = time.time()
2476 held = 0
2476 held = 0
2477
2477
2478 def report(vfs, name, method):
2478 def report(vfs, name, method):
2479 # this causes stale locks to get reaped for more accurate reporting
2479 # this causes stale locks to get reaped for more accurate reporting
2480 try:
2480 try:
2481 l = method(False)
2481 l = method(False)
2482 except error.LockHeld:
2482 except error.LockHeld:
2483 l = None
2483 l = None
2484
2484
2485 if l:
2485 if l:
2486 l.release()
2486 l.release()
2487 else:
2487 else:
2488 try:
2488 try:
2489 stat = repo.svfs.lstat(name)
2489 stat = repo.svfs.lstat(name)
2490 age = now - stat.st_mtime
2490 age = now - stat.st_mtime
2491 user = util.username(stat.st_uid)
2491 user = util.username(stat.st_uid)
2492 locker = vfs.readlock(name)
2492 locker = vfs.readlock(name)
2493 if ":" in locker:
2493 if ":" in locker:
2494 host, pid = locker.split(':')
2494 host, pid = locker.split(':')
2495 if host == socket.gethostname():
2495 if host == socket.gethostname():
2496 locker = 'user %s, process %s' % (user, pid)
2496 locker = 'user %s, process %s' % (user, pid)
2497 else:
2497 else:
2498 locker = 'user %s, process %s, host %s' \
2498 locker = 'user %s, process %s, host %s' \
2499 % (user, pid, host)
2499 % (user, pid, host)
2500 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2500 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2501 return 1
2501 return 1
2502 except OSError, e:
2502 except OSError, e:
2503 if e.errno != errno.ENOENT:
2503 if e.errno != errno.ENOENT:
2504 raise
2504 raise
2505
2505
2506 ui.write("%-6s free\n" % (name + ":"))
2506 ui.write("%-6s free\n" % (name + ":"))
2507 return 0
2507 return 0
2508
2508
2509 held += report(repo.svfs, "lock", repo.lock)
2509 held += report(repo.svfs, "lock", repo.lock)
2510 held += report(repo.vfs, "wlock", repo.wlock)
2510 held += report(repo.vfs, "wlock", repo.wlock)
2511
2511
2512 return held
2512 return held
2513
2513
2514 @command('debugobsolete',
2514 @command('debugobsolete',
2515 [('', 'flags', 0, _('markers flag')),
2515 [('', 'flags', 0, _('markers flag')),
2516 ('', 'record-parents', False,
2516 ('', 'record-parents', False,
2517 _('record parent information for the precursor')),
2517 _('record parent information for the precursor')),
2518 ('r', 'rev', [], _('display markers relevant to REV')),
2518 ('r', 'rev', [], _('display markers relevant to REV')),
2519 ] + commitopts2,
2519 ] + commitopts2,
2520 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2520 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2521 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2521 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2522 """create arbitrary obsolete marker
2522 """create arbitrary obsolete marker
2523
2523
2524 With no arguments, displays the list of obsolescence markers."""
2524 With no arguments, displays the list of obsolescence markers."""
2525
2525
2526 def parsenodeid(s):
2526 def parsenodeid(s):
2527 try:
2527 try:
2528 # We do not use revsingle/revrange functions here to accept
2528 # We do not use revsingle/revrange functions here to accept
2529 # arbitrary node identifiers, possibly not present in the
2529 # arbitrary node identifiers, possibly not present in the
2530 # local repository.
2530 # local repository.
2531 n = bin(s)
2531 n = bin(s)
2532 if len(n) != len(nullid):
2532 if len(n) != len(nullid):
2533 raise TypeError()
2533 raise TypeError()
2534 return n
2534 return n
2535 except TypeError:
2535 except TypeError:
2536 raise util.Abort('changeset references must be full hexadecimal '
2536 raise util.Abort('changeset references must be full hexadecimal '
2537 'node identifiers')
2537 'node identifiers')
2538
2538
2539 if precursor is not None:
2539 if precursor is not None:
2540 if opts['rev']:
2540 if opts['rev']:
2541 raise util.Abort('cannot select revision when creating marker')
2541 raise util.Abort('cannot select revision when creating marker')
2542 metadata = {}
2542 metadata = {}
2543 metadata['user'] = opts['user'] or ui.username()
2543 metadata['user'] = opts['user'] or ui.username()
2544 succs = tuple(parsenodeid(succ) for succ in successors)
2544 succs = tuple(parsenodeid(succ) for succ in successors)
2545 l = repo.lock()
2545 l = repo.lock()
2546 try:
2546 try:
2547 tr = repo.transaction('debugobsolete')
2547 tr = repo.transaction('debugobsolete')
2548 try:
2548 try:
2549 try:
2549 try:
2550 date = opts.get('date')
2550 date = opts.get('date')
2551 if date:
2551 if date:
2552 date = util.parsedate(date)
2552 date = util.parsedate(date)
2553 else:
2553 else:
2554 date = None
2554 date = None
2555 prec = parsenodeid(precursor)
2555 prec = parsenodeid(precursor)
2556 parents = None
2556 parents = None
2557 if opts['record_parents']:
2557 if opts['record_parents']:
2558 if prec not in repo.unfiltered():
2558 if prec not in repo.unfiltered():
2559 raise util.Abort('cannot used --record-parents on '
2559 raise util.Abort('cannot used --record-parents on '
2560 'unknown changesets')
2560 'unknown changesets')
2561 parents = repo.unfiltered()[prec].parents()
2561 parents = repo.unfiltered()[prec].parents()
2562 parents = tuple(p.node() for p in parents)
2562 parents = tuple(p.node() for p in parents)
2563 repo.obsstore.create(tr, prec, succs, opts['flags'],
2563 repo.obsstore.create(tr, prec, succs, opts['flags'],
2564 parents=parents, date=date,
2564 parents=parents, date=date,
2565 metadata=metadata)
2565 metadata=metadata)
2566 tr.close()
2566 tr.close()
2567 except ValueError, exc:
2567 except ValueError, exc:
2568 raise util.Abort(_('bad obsmarker input: %s') % exc)
2568 raise util.Abort(_('bad obsmarker input: %s') % exc)
2569 finally:
2569 finally:
2570 tr.release()
2570 tr.release()
2571 finally:
2571 finally:
2572 l.release()
2572 l.release()
2573 else:
2573 else:
2574 if opts['rev']:
2574 if opts['rev']:
2575 revs = scmutil.revrange(repo, opts['rev'])
2575 revs = scmutil.revrange(repo, opts['rev'])
2576 nodes = [repo[r].node() for r in revs]
2576 nodes = [repo[r].node() for r in revs]
2577 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2577 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2578 markers.sort(key=lambda x: x._data)
2578 markers.sort(key=lambda x: x._data)
2579 else:
2579 else:
2580 markers = obsolete.getmarkers(repo)
2580 markers = obsolete.getmarkers(repo)
2581
2581
2582 for m in markers:
2582 for m in markers:
2583 cmdutil.showmarker(ui, m)
2583 cmdutil.showmarker(ui, m)
2584
2584
2585 @command('debugpathcomplete',
2585 @command('debugpathcomplete',
2586 [('f', 'full', None, _('complete an entire path')),
2586 [('f', 'full', None, _('complete an entire path')),
2587 ('n', 'normal', None, _('show only normal files')),
2587 ('n', 'normal', None, _('show only normal files')),
2588 ('a', 'added', None, _('show only added files')),
2588 ('a', 'added', None, _('show only added files')),
2589 ('r', 'removed', None, _('show only removed files'))],
2589 ('r', 'removed', None, _('show only removed files'))],
2590 _('FILESPEC...'))
2590 _('FILESPEC...'))
2591 def debugpathcomplete(ui, repo, *specs, **opts):
2591 def debugpathcomplete(ui, repo, *specs, **opts):
2592 '''complete part or all of a tracked path
2592 '''complete part or all of a tracked path
2593
2593
2594 This command supports shells that offer path name completion. It
2594 This command supports shells that offer path name completion. It
2595 currently completes only files already known to the dirstate.
2595 currently completes only files already known to the dirstate.
2596
2596
2597 Completion extends only to the next path segment unless
2597 Completion extends only to the next path segment unless
2598 --full is specified, in which case entire paths are used.'''
2598 --full is specified, in which case entire paths are used.'''
2599
2599
2600 def complete(path, acceptable):
2600 def complete(path, acceptable):
2601 dirstate = repo.dirstate
2601 dirstate = repo.dirstate
2602 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2602 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2603 rootdir = repo.root + os.sep
2603 rootdir = repo.root + os.sep
2604 if spec != repo.root and not spec.startswith(rootdir):
2604 if spec != repo.root and not spec.startswith(rootdir):
2605 return [], []
2605 return [], []
2606 if os.path.isdir(spec):
2606 if os.path.isdir(spec):
2607 spec += '/'
2607 spec += '/'
2608 spec = spec[len(rootdir):]
2608 spec = spec[len(rootdir):]
2609 fixpaths = os.sep != '/'
2609 fixpaths = os.sep != '/'
2610 if fixpaths:
2610 if fixpaths:
2611 spec = spec.replace(os.sep, '/')
2611 spec = spec.replace(os.sep, '/')
2612 speclen = len(spec)
2612 speclen = len(spec)
2613 fullpaths = opts['full']
2613 fullpaths = opts['full']
2614 files, dirs = set(), set()
2614 files, dirs = set(), set()
2615 adddir, addfile = dirs.add, files.add
2615 adddir, addfile = dirs.add, files.add
2616 for f, st in dirstate.iteritems():
2616 for f, st in dirstate.iteritems():
2617 if f.startswith(spec) and st[0] in acceptable:
2617 if f.startswith(spec) and st[0] in acceptable:
2618 if fixpaths:
2618 if fixpaths:
2619 f = f.replace('/', os.sep)
2619 f = f.replace('/', os.sep)
2620 if fullpaths:
2620 if fullpaths:
2621 addfile(f)
2621 addfile(f)
2622 continue
2622 continue
2623 s = f.find(os.sep, speclen)
2623 s = f.find(os.sep, speclen)
2624 if s >= 0:
2624 if s >= 0:
2625 adddir(f[:s])
2625 adddir(f[:s])
2626 else:
2626 else:
2627 addfile(f)
2627 addfile(f)
2628 return files, dirs
2628 return files, dirs
2629
2629
2630 acceptable = ''
2630 acceptable = ''
2631 if opts['normal']:
2631 if opts['normal']:
2632 acceptable += 'nm'
2632 acceptable += 'nm'
2633 if opts['added']:
2633 if opts['added']:
2634 acceptable += 'a'
2634 acceptable += 'a'
2635 if opts['removed']:
2635 if opts['removed']:
2636 acceptable += 'r'
2636 acceptable += 'r'
2637 cwd = repo.getcwd()
2637 cwd = repo.getcwd()
2638 if not specs:
2638 if not specs:
2639 specs = ['.']
2639 specs = ['.']
2640
2640
2641 files, dirs = set(), set()
2641 files, dirs = set(), set()
2642 for spec in specs:
2642 for spec in specs:
2643 f, d = complete(spec, acceptable or 'nmar')
2643 f, d = complete(spec, acceptable or 'nmar')
2644 files.update(f)
2644 files.update(f)
2645 dirs.update(d)
2645 dirs.update(d)
2646 files.update(dirs)
2646 files.update(dirs)
2647 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2647 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2648 ui.write('\n')
2648 ui.write('\n')
2649
2649
2650 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2650 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2651 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2651 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2652 '''access the pushkey key/value protocol
2652 '''access the pushkey key/value protocol
2653
2653
2654 With two args, list the keys in the given namespace.
2654 With two args, list the keys in the given namespace.
2655
2655
2656 With five args, set a key to new if it currently is set to old.
2656 With five args, set a key to new if it currently is set to old.
2657 Reports success or failure.
2657 Reports success or failure.
2658 '''
2658 '''
2659
2659
2660 target = hg.peer(ui, {}, repopath)
2660 target = hg.peer(ui, {}, repopath)
2661 if keyinfo:
2661 if keyinfo:
2662 key, old, new = keyinfo
2662 key, old, new = keyinfo
2663 r = target.pushkey(namespace, key, old, new)
2663 r = target.pushkey(namespace, key, old, new)
2664 ui.status(str(r) + '\n')
2664 ui.status(str(r) + '\n')
2665 return not r
2665 return not r
2666 else:
2666 else:
2667 for k, v in sorted(target.listkeys(namespace).iteritems()):
2667 for k, v in sorted(target.listkeys(namespace).iteritems()):
2668 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2668 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2669 v.encode('string-escape')))
2669 v.encode('string-escape')))
2670
2670
2671 @command('debugpvec', [], _('A B'))
2671 @command('debugpvec', [], _('A B'))
2672 def debugpvec(ui, repo, a, b=None):
2672 def debugpvec(ui, repo, a, b=None):
2673 ca = scmutil.revsingle(repo, a)
2673 ca = scmutil.revsingle(repo, a)
2674 cb = scmutil.revsingle(repo, b)
2674 cb = scmutil.revsingle(repo, b)
2675 pa = pvec.ctxpvec(ca)
2675 pa = pvec.ctxpvec(ca)
2676 pb = pvec.ctxpvec(cb)
2676 pb = pvec.ctxpvec(cb)
2677 if pa == pb:
2677 if pa == pb:
2678 rel = "="
2678 rel = "="
2679 elif pa > pb:
2679 elif pa > pb:
2680 rel = ">"
2680 rel = ">"
2681 elif pa < pb:
2681 elif pa < pb:
2682 rel = "<"
2682 rel = "<"
2683 elif pa | pb:
2683 elif pa | pb:
2684 rel = "|"
2684 rel = "|"
2685 ui.write(_("a: %s\n") % pa)
2685 ui.write(_("a: %s\n") % pa)
2686 ui.write(_("b: %s\n") % pb)
2686 ui.write(_("b: %s\n") % pb)
2687 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2687 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2688 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2688 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2689 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2689 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2690 pa.distance(pb), rel))
2690 pa.distance(pb), rel))
2691
2691
2692 @command('debugrebuilddirstate|debugrebuildstate',
2692 @command('debugrebuilddirstate|debugrebuildstate',
2693 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2693 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2694 _('[-r REV]'))
2694 _('[-r REV]'))
2695 def debugrebuilddirstate(ui, repo, rev):
2695 def debugrebuilddirstate(ui, repo, rev):
2696 """rebuild the dirstate as it would look like for the given revision
2696 """rebuild the dirstate as it would look like for the given revision
2697
2697
2698 If no revision is specified the first current parent will be used.
2698 If no revision is specified the first current parent will be used.
2699
2699
2700 The dirstate will be set to the files of the given revision.
2700 The dirstate will be set to the files of the given revision.
2701 The actual working directory content or existing dirstate
2701 The actual working directory content or existing dirstate
2702 information such as adds or removes is not considered.
2702 information such as adds or removes is not considered.
2703
2703
2704 One use of this command is to make the next :hg:`status` invocation
2704 One use of this command is to make the next :hg:`status` invocation
2705 check the actual file content.
2705 check the actual file content.
2706 """
2706 """
2707 ctx = scmutil.revsingle(repo, rev)
2707 ctx = scmutil.revsingle(repo, rev)
2708 wlock = repo.wlock()
2708 wlock = repo.wlock()
2709 try:
2709 try:
2710 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2710 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2711 finally:
2711 finally:
2712 wlock.release()
2712 wlock.release()
2713
2713
2714 @command('debugrename',
2714 @command('debugrename',
2715 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2715 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2716 _('[-r REV] FILE'))
2716 _('[-r REV] FILE'))
2717 def debugrename(ui, repo, file1, *pats, **opts):
2717 def debugrename(ui, repo, file1, *pats, **opts):
2718 """dump rename information"""
2718 """dump rename information"""
2719
2719
2720 ctx = scmutil.revsingle(repo, opts.get('rev'))
2720 ctx = scmutil.revsingle(repo, opts.get('rev'))
2721 m = scmutil.match(ctx, (file1,) + pats, opts)
2721 m = scmutil.match(ctx, (file1,) + pats, opts)
2722 for abs in ctx.walk(m):
2722 for abs in ctx.walk(m):
2723 fctx = ctx[abs]
2723 fctx = ctx[abs]
2724 o = fctx.filelog().renamed(fctx.filenode())
2724 o = fctx.filelog().renamed(fctx.filenode())
2725 rel = m.rel(abs)
2725 rel = m.rel(abs)
2726 if o:
2726 if o:
2727 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2727 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2728 else:
2728 else:
2729 ui.write(_("%s not renamed\n") % rel)
2729 ui.write(_("%s not renamed\n") % rel)
2730
2730
2731 @command('debugrevlog',
2731 @command('debugrevlog',
2732 [('c', 'changelog', False, _('open changelog')),
2732 [('c', 'changelog', False, _('open changelog')),
2733 ('m', 'manifest', False, _('open manifest')),
2733 ('m', 'manifest', False, _('open manifest')),
2734 ('d', 'dump', False, _('dump index data'))],
2734 ('d', 'dump', False, _('dump index data'))],
2735 _('-c|-m|FILE'),
2735 _('-c|-m|FILE'),
2736 optionalrepo=True)
2736 optionalrepo=True)
2737 def debugrevlog(ui, repo, file_=None, **opts):
2737 def debugrevlog(ui, repo, file_=None, **opts):
2738 """show data and statistics about a revlog"""
2738 """show data and statistics about a revlog"""
2739 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2739 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2740
2740
2741 if opts.get("dump"):
2741 if opts.get("dump"):
2742 numrevs = len(r)
2742 numrevs = len(r)
2743 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2743 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2744 " rawsize totalsize compression heads chainlen\n")
2744 " rawsize totalsize compression heads chainlen\n")
2745 ts = 0
2745 ts = 0
2746 heads = set()
2746 heads = set()
2747
2747
2748 for rev in xrange(numrevs):
2748 for rev in xrange(numrevs):
2749 dbase = r.deltaparent(rev)
2749 dbase = r.deltaparent(rev)
2750 if dbase == -1:
2750 if dbase == -1:
2751 dbase = rev
2751 dbase = rev
2752 cbase = r.chainbase(rev)
2752 cbase = r.chainbase(rev)
2753 clen = r.chainlen(rev)
2753 clen = r.chainlen(rev)
2754 p1, p2 = r.parentrevs(rev)
2754 p1, p2 = r.parentrevs(rev)
2755 rs = r.rawsize(rev)
2755 rs = r.rawsize(rev)
2756 ts = ts + rs
2756 ts = ts + rs
2757 heads -= set(r.parentrevs(rev))
2757 heads -= set(r.parentrevs(rev))
2758 heads.add(rev)
2758 heads.add(rev)
2759 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2759 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2760 "%11d %5d %8d\n" %
2760 "%11d %5d %8d\n" %
2761 (rev, p1, p2, r.start(rev), r.end(rev),
2761 (rev, p1, p2, r.start(rev), r.end(rev),
2762 r.start(dbase), r.start(cbase),
2762 r.start(dbase), r.start(cbase),
2763 r.start(p1), r.start(p2),
2763 r.start(p1), r.start(p2),
2764 rs, ts, ts / r.end(rev), len(heads), clen))
2764 rs, ts, ts / r.end(rev), len(heads), clen))
2765 return 0
2765 return 0
2766
2766
2767 v = r.version
2767 v = r.version
2768 format = v & 0xFFFF
2768 format = v & 0xFFFF
2769 flags = []
2769 flags = []
2770 gdelta = False
2770 gdelta = False
2771 if v & revlog.REVLOGNGINLINEDATA:
2771 if v & revlog.REVLOGNGINLINEDATA:
2772 flags.append('inline')
2772 flags.append('inline')
2773 if v & revlog.REVLOGGENERALDELTA:
2773 if v & revlog.REVLOGGENERALDELTA:
2774 gdelta = True
2774 gdelta = True
2775 flags.append('generaldelta')
2775 flags.append('generaldelta')
2776 if not flags:
2776 if not flags:
2777 flags = ['(none)']
2777 flags = ['(none)']
2778
2778
2779 nummerges = 0
2779 nummerges = 0
2780 numfull = 0
2780 numfull = 0
2781 numprev = 0
2781 numprev = 0
2782 nump1 = 0
2782 nump1 = 0
2783 nump2 = 0
2783 nump2 = 0
2784 numother = 0
2784 numother = 0
2785 nump1prev = 0
2785 nump1prev = 0
2786 nump2prev = 0
2786 nump2prev = 0
2787 chainlengths = []
2787 chainlengths = []
2788
2788
2789 datasize = [None, 0, 0L]
2789 datasize = [None, 0, 0L]
2790 fullsize = [None, 0, 0L]
2790 fullsize = [None, 0, 0L]
2791 deltasize = [None, 0, 0L]
2791 deltasize = [None, 0, 0L]
2792
2792
2793 def addsize(size, l):
2793 def addsize(size, l):
2794 if l[0] is None or size < l[0]:
2794 if l[0] is None or size < l[0]:
2795 l[0] = size
2795 l[0] = size
2796 if size > l[1]:
2796 if size > l[1]:
2797 l[1] = size
2797 l[1] = size
2798 l[2] += size
2798 l[2] += size
2799
2799
2800 numrevs = len(r)
2800 numrevs = len(r)
2801 for rev in xrange(numrevs):
2801 for rev in xrange(numrevs):
2802 p1, p2 = r.parentrevs(rev)
2802 p1, p2 = r.parentrevs(rev)
2803 delta = r.deltaparent(rev)
2803 delta = r.deltaparent(rev)
2804 if format > 0:
2804 if format > 0:
2805 addsize(r.rawsize(rev), datasize)
2805 addsize(r.rawsize(rev), datasize)
2806 if p2 != nullrev:
2806 if p2 != nullrev:
2807 nummerges += 1
2807 nummerges += 1
2808 size = r.length(rev)
2808 size = r.length(rev)
2809 if delta == nullrev:
2809 if delta == nullrev:
2810 chainlengths.append(0)
2810 chainlengths.append(0)
2811 numfull += 1
2811 numfull += 1
2812 addsize(size, fullsize)
2812 addsize(size, fullsize)
2813 else:
2813 else:
2814 chainlengths.append(chainlengths[delta] + 1)
2814 chainlengths.append(chainlengths[delta] + 1)
2815 addsize(size, deltasize)
2815 addsize(size, deltasize)
2816 if delta == rev - 1:
2816 if delta == rev - 1:
2817 numprev += 1
2817 numprev += 1
2818 if delta == p1:
2818 if delta == p1:
2819 nump1prev += 1
2819 nump1prev += 1
2820 elif delta == p2:
2820 elif delta == p2:
2821 nump2prev += 1
2821 nump2prev += 1
2822 elif delta == p1:
2822 elif delta == p1:
2823 nump1 += 1
2823 nump1 += 1
2824 elif delta == p2:
2824 elif delta == p2:
2825 nump2 += 1
2825 nump2 += 1
2826 elif delta != nullrev:
2826 elif delta != nullrev:
2827 numother += 1
2827 numother += 1
2828
2828
2829 # Adjust size min value for empty cases
2829 # Adjust size min value for empty cases
2830 for size in (datasize, fullsize, deltasize):
2830 for size in (datasize, fullsize, deltasize):
2831 if size[0] is None:
2831 if size[0] is None:
2832 size[0] = 0
2832 size[0] = 0
2833
2833
2834 numdeltas = numrevs - numfull
2834 numdeltas = numrevs - numfull
2835 numoprev = numprev - nump1prev - nump2prev
2835 numoprev = numprev - nump1prev - nump2prev
2836 totalrawsize = datasize[2]
2836 totalrawsize = datasize[2]
2837 datasize[2] /= numrevs
2837 datasize[2] /= numrevs
2838 fulltotal = fullsize[2]
2838 fulltotal = fullsize[2]
2839 fullsize[2] /= numfull
2839 fullsize[2] /= numfull
2840 deltatotal = deltasize[2]
2840 deltatotal = deltasize[2]
2841 if numrevs - numfull > 0:
2841 if numrevs - numfull > 0:
2842 deltasize[2] /= numrevs - numfull
2842 deltasize[2] /= numrevs - numfull
2843 totalsize = fulltotal + deltatotal
2843 totalsize = fulltotal + deltatotal
2844 avgchainlen = sum(chainlengths) / numrevs
2844 avgchainlen = sum(chainlengths) / numrevs
2845 compratio = totalrawsize / totalsize
2845 compratio = totalrawsize / totalsize
2846
2846
2847 basedfmtstr = '%%%dd\n'
2847 basedfmtstr = '%%%dd\n'
2848 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2848 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2849
2849
2850 def dfmtstr(max):
2850 def dfmtstr(max):
2851 return basedfmtstr % len(str(max))
2851 return basedfmtstr % len(str(max))
2852 def pcfmtstr(max, padding=0):
2852 def pcfmtstr(max, padding=0):
2853 return basepcfmtstr % (len(str(max)), ' ' * padding)
2853 return basepcfmtstr % (len(str(max)), ' ' * padding)
2854
2854
2855 def pcfmt(value, total):
2855 def pcfmt(value, total):
2856 return (value, 100 * float(value) / total)
2856 return (value, 100 * float(value) / total)
2857
2857
2858 ui.write(('format : %d\n') % format)
2858 ui.write(('format : %d\n') % format)
2859 ui.write(('flags : %s\n') % ', '.join(flags))
2859 ui.write(('flags : %s\n') % ', '.join(flags))
2860
2860
2861 ui.write('\n')
2861 ui.write('\n')
2862 fmt = pcfmtstr(totalsize)
2862 fmt = pcfmtstr(totalsize)
2863 fmt2 = dfmtstr(totalsize)
2863 fmt2 = dfmtstr(totalsize)
2864 ui.write(('revisions : ') + fmt2 % numrevs)
2864 ui.write(('revisions : ') + fmt2 % numrevs)
2865 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2865 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2866 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2866 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2867 ui.write(('revisions : ') + fmt2 % numrevs)
2867 ui.write(('revisions : ') + fmt2 % numrevs)
2868 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2868 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2869 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2869 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2870 ui.write(('revision size : ') + fmt2 % totalsize)
2870 ui.write(('revision size : ') + fmt2 % totalsize)
2871 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2871 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2872 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2872 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2873
2873
2874 ui.write('\n')
2874 ui.write('\n')
2875 fmt = dfmtstr(max(avgchainlen, compratio))
2875 fmt = dfmtstr(max(avgchainlen, compratio))
2876 ui.write(('avg chain length : ') + fmt % avgchainlen)
2876 ui.write(('avg chain length : ') + fmt % avgchainlen)
2877 ui.write(('compression ratio : ') + fmt % compratio)
2877 ui.write(('compression ratio : ') + fmt % compratio)
2878
2878
2879 if format > 0:
2879 if format > 0:
2880 ui.write('\n')
2880 ui.write('\n')
2881 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2881 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2882 % tuple(datasize))
2882 % tuple(datasize))
2883 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2883 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2884 % tuple(fullsize))
2884 % tuple(fullsize))
2885 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2885 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2886 % tuple(deltasize))
2886 % tuple(deltasize))
2887
2887
2888 if numdeltas > 0:
2888 if numdeltas > 0:
2889 ui.write('\n')
2889 ui.write('\n')
2890 fmt = pcfmtstr(numdeltas)
2890 fmt = pcfmtstr(numdeltas)
2891 fmt2 = pcfmtstr(numdeltas, 4)
2891 fmt2 = pcfmtstr(numdeltas, 4)
2892 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2892 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2893 if numprev > 0:
2893 if numprev > 0:
2894 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2894 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2895 numprev))
2895 numprev))
2896 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2896 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2897 numprev))
2897 numprev))
2898 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2898 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2899 numprev))
2899 numprev))
2900 if gdelta:
2900 if gdelta:
2901 ui.write(('deltas against p1 : ')
2901 ui.write(('deltas against p1 : ')
2902 + fmt % pcfmt(nump1, numdeltas))
2902 + fmt % pcfmt(nump1, numdeltas))
2903 ui.write(('deltas against p2 : ')
2903 ui.write(('deltas against p2 : ')
2904 + fmt % pcfmt(nump2, numdeltas))
2904 + fmt % pcfmt(nump2, numdeltas))
2905 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2905 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2906 numdeltas))
2906 numdeltas))
2907
2907
2908 @command('debugrevspec',
2908 @command('debugrevspec',
2909 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2909 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2910 ('REVSPEC'))
2910 ('REVSPEC'))
2911 def debugrevspec(ui, repo, expr, **opts):
2911 def debugrevspec(ui, repo, expr, **opts):
2912 """parse and apply a revision specification
2912 """parse and apply a revision specification
2913
2913
2914 Use --verbose to print the parsed tree before and after aliases
2914 Use --verbose to print the parsed tree before and after aliases
2915 expansion.
2915 expansion.
2916 """
2916 """
2917 if ui.verbose:
2917 if ui.verbose:
2918 tree = revset.parse(expr)[0]
2918 tree = revset.parse(expr)[0]
2919 ui.note(revset.prettyformat(tree), "\n")
2919 ui.note(revset.prettyformat(tree), "\n")
2920 newtree = revset.findaliases(ui, tree)
2920 newtree = revset.findaliases(ui, tree)
2921 if newtree != tree:
2921 if newtree != tree:
2922 ui.note(revset.prettyformat(newtree), "\n")
2922 ui.note(revset.prettyformat(newtree), "\n")
2923 tree = newtree
2923 tree = newtree
2924 newtree = revset.foldconcat(tree)
2924 newtree = revset.foldconcat(tree)
2925 if newtree != tree:
2925 if newtree != tree:
2926 ui.note(revset.prettyformat(newtree), "\n")
2926 ui.note(revset.prettyformat(newtree), "\n")
2927 if opts["optimize"]:
2927 if opts["optimize"]:
2928 weight, optimizedtree = revset.optimize(newtree, True)
2928 weight, optimizedtree = revset.optimize(newtree, True)
2929 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2929 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2930 func = revset.match(ui, expr)
2930 func = revset.match(ui, expr)
2931 for c in func(repo):
2931 for c in func(repo):
2932 ui.write("%s\n" % c)
2932 ui.write("%s\n" % c)
2933
2933
2934 @command('debugsetparents', [], _('REV1 [REV2]'))
2934 @command('debugsetparents', [], _('REV1 [REV2]'))
2935 def debugsetparents(ui, repo, rev1, rev2=None):
2935 def debugsetparents(ui, repo, rev1, rev2=None):
2936 """manually set the parents of the current working directory
2936 """manually set the parents of the current working directory
2937
2937
2938 This is useful for writing repository conversion tools, but should
2938 This is useful for writing repository conversion tools, but should
2939 be used with care. For example, neither the working directory nor the
2939 be used with care. For example, neither the working directory nor the
2940 dirstate is updated, so file status may be incorrect after running this
2940 dirstate is updated, so file status may be incorrect after running this
2941 command.
2941 command.
2942
2942
2943 Returns 0 on success.
2943 Returns 0 on success.
2944 """
2944 """
2945
2945
2946 r1 = scmutil.revsingle(repo, rev1).node()
2946 r1 = scmutil.revsingle(repo, rev1).node()
2947 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2947 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2948
2948
2949 wlock = repo.wlock()
2949 wlock = repo.wlock()
2950 try:
2950 try:
2951 repo.dirstate.beginparentchange()
2951 repo.dirstate.beginparentchange()
2952 repo.setparents(r1, r2)
2952 repo.setparents(r1, r2)
2953 repo.dirstate.endparentchange()
2953 repo.dirstate.endparentchange()
2954 finally:
2954 finally:
2955 wlock.release()
2955 wlock.release()
2956
2956
2957 @command('debugdirstate|debugstate',
2957 @command('debugdirstate|debugstate',
2958 [('', 'nodates', None, _('do not display the saved mtime')),
2958 [('', 'nodates', None, _('do not display the saved mtime')),
2959 ('', 'datesort', None, _('sort by saved mtime'))],
2959 ('', 'datesort', None, _('sort by saved mtime'))],
2960 _('[OPTION]...'))
2960 _('[OPTION]...'))
2961 def debugstate(ui, repo, nodates=None, datesort=None):
2961 def debugstate(ui, repo, nodates=None, datesort=None):
2962 """show the contents of the current dirstate"""
2962 """show the contents of the current dirstate"""
2963 timestr = ""
2963 timestr = ""
2964 if datesort:
2964 if datesort:
2965 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2965 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2966 else:
2966 else:
2967 keyfunc = None # sort by filename
2967 keyfunc = None # sort by filename
2968 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2968 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2969 if ent[3] == -1:
2969 if ent[3] == -1:
2970 timestr = 'unset '
2970 timestr = 'unset '
2971 elif nodates:
2971 elif nodates:
2972 timestr = 'set '
2972 timestr = 'set '
2973 else:
2973 else:
2974 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2974 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2975 time.localtime(ent[3]))
2975 time.localtime(ent[3]))
2976 if ent[1] & 020000:
2976 if ent[1] & 020000:
2977 mode = 'lnk'
2977 mode = 'lnk'
2978 else:
2978 else:
2979 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2979 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2980 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2980 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2981 for f in repo.dirstate.copies():
2981 for f in repo.dirstate.copies():
2982 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2982 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2983
2983
2984 @command('debugsub',
2984 @command('debugsub',
2985 [('r', 'rev', '',
2985 [('r', 'rev', '',
2986 _('revision to check'), _('REV'))],
2986 _('revision to check'), _('REV'))],
2987 _('[-r REV] [REV]'))
2987 _('[-r REV] [REV]'))
2988 def debugsub(ui, repo, rev=None):
2988 def debugsub(ui, repo, rev=None):
2989 ctx = scmutil.revsingle(repo, rev, None)
2989 ctx = scmutil.revsingle(repo, rev, None)
2990 for k, v in sorted(ctx.substate.items()):
2990 for k, v in sorted(ctx.substate.items()):
2991 ui.write(('path %s\n') % k)
2991 ui.write(('path %s\n') % k)
2992 ui.write((' source %s\n') % v[0])
2992 ui.write((' source %s\n') % v[0])
2993 ui.write((' revision %s\n') % v[1])
2993 ui.write((' revision %s\n') % v[1])
2994
2994
2995 @command('debugsuccessorssets',
2995 @command('debugsuccessorssets',
2996 [],
2996 [],
2997 _('[REV]'))
2997 _('[REV]'))
2998 def debugsuccessorssets(ui, repo, *revs):
2998 def debugsuccessorssets(ui, repo, *revs):
2999 """show set of successors for revision
2999 """show set of successors for revision
3000
3000
3001 A successors set of changeset A is a consistent group of revisions that
3001 A successors set of changeset A is a consistent group of revisions that
3002 succeed A. It contains non-obsolete changesets only.
3002 succeed A. It contains non-obsolete changesets only.
3003
3003
3004 In most cases a changeset A has a single successors set containing a single
3004 In most cases a changeset A has a single successors set containing a single
3005 successor (changeset A replaced by A').
3005 successor (changeset A replaced by A').
3006
3006
3007 A changeset that is made obsolete with no successors are called "pruned".
3007 A changeset that is made obsolete with no successors are called "pruned".
3008 Such changesets have no successors sets at all.
3008 Such changesets have no successors sets at all.
3009
3009
3010 A changeset that has been "split" will have a successors set containing
3010 A changeset that has been "split" will have a successors set containing
3011 more than one successor.
3011 more than one successor.
3012
3012
3013 A changeset that has been rewritten in multiple different ways is called
3013 A changeset that has been rewritten in multiple different ways is called
3014 "divergent". Such changesets have multiple successor sets (each of which
3014 "divergent". Such changesets have multiple successor sets (each of which
3015 may also be split, i.e. have multiple successors).
3015 may also be split, i.e. have multiple successors).
3016
3016
3017 Results are displayed as follows::
3017 Results are displayed as follows::
3018
3018
3019 <rev1>
3019 <rev1>
3020 <successors-1A>
3020 <successors-1A>
3021 <rev2>
3021 <rev2>
3022 <successors-2A>
3022 <successors-2A>
3023 <successors-2B1> <successors-2B2> <successors-2B3>
3023 <successors-2B1> <successors-2B2> <successors-2B3>
3024
3024
3025 Here rev2 has two possible (i.e. divergent) successors sets. The first
3025 Here rev2 has two possible (i.e. divergent) successors sets. The first
3026 holds one element, whereas the second holds three (i.e. the changeset has
3026 holds one element, whereas the second holds three (i.e. the changeset has
3027 been split).
3027 been split).
3028 """
3028 """
3029 # passed to successorssets caching computation from one call to another
3029 # passed to successorssets caching computation from one call to another
3030 cache = {}
3030 cache = {}
3031 ctx2str = str
3031 ctx2str = str
3032 node2str = short
3032 node2str = short
3033 if ui.debug():
3033 if ui.debug():
3034 def ctx2str(ctx):
3034 def ctx2str(ctx):
3035 return ctx.hex()
3035 return ctx.hex()
3036 node2str = hex
3036 node2str = hex
3037 for rev in scmutil.revrange(repo, revs):
3037 for rev in scmutil.revrange(repo, revs):
3038 ctx = repo[rev]
3038 ctx = repo[rev]
3039 ui.write('%s\n'% ctx2str(ctx))
3039 ui.write('%s\n'% ctx2str(ctx))
3040 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3040 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3041 if succsset:
3041 if succsset:
3042 ui.write(' ')
3042 ui.write(' ')
3043 ui.write(node2str(succsset[0]))
3043 ui.write(node2str(succsset[0]))
3044 for node in succsset[1:]:
3044 for node in succsset[1:]:
3045 ui.write(' ')
3045 ui.write(' ')
3046 ui.write(node2str(node))
3046 ui.write(node2str(node))
3047 ui.write('\n')
3047 ui.write('\n')
3048
3048
3049 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3049 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3050 def debugwalk(ui, repo, *pats, **opts):
3050 def debugwalk(ui, repo, *pats, **opts):
3051 """show how files match on given patterns"""
3051 """show how files match on given patterns"""
3052 m = scmutil.match(repo[None], pats, opts)
3052 m = scmutil.match(repo[None], pats, opts)
3053 items = list(repo.walk(m))
3053 items = list(repo.walk(m))
3054 if not items:
3054 if not items:
3055 return
3055 return
3056 f = lambda fn: fn
3056 f = lambda fn: fn
3057 if ui.configbool('ui', 'slash') and os.sep != '/':
3057 if ui.configbool('ui', 'slash') and os.sep != '/':
3058 f = lambda fn: util.normpath(fn)
3058 f = lambda fn: util.normpath(fn)
3059 fmt = 'f %%-%ds %%-%ds %%s' % (
3059 fmt = 'f %%-%ds %%-%ds %%s' % (
3060 max([len(abs) for abs in items]),
3060 max([len(abs) for abs in items]),
3061 max([len(m.rel(abs)) for abs in items]))
3061 max([len(m.rel(abs)) for abs in items]))
3062 for abs in items:
3062 for abs in items:
3063 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3063 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3064 ui.write("%s\n" % line.rstrip())
3064 ui.write("%s\n" % line.rstrip())
3065
3065
3066 @command('debugwireargs',
3066 @command('debugwireargs',
3067 [('', 'three', '', 'three'),
3067 [('', 'three', '', 'three'),
3068 ('', 'four', '', 'four'),
3068 ('', 'four', '', 'four'),
3069 ('', 'five', '', 'five'),
3069 ('', 'five', '', 'five'),
3070 ] + remoteopts,
3070 ] + remoteopts,
3071 _('REPO [OPTIONS]... [ONE [TWO]]'),
3071 _('REPO [OPTIONS]... [ONE [TWO]]'),
3072 norepo=True)
3072 norepo=True)
3073 def debugwireargs(ui, repopath, *vals, **opts):
3073 def debugwireargs(ui, repopath, *vals, **opts):
3074 repo = hg.peer(ui, opts, repopath)
3074 repo = hg.peer(ui, opts, repopath)
3075 for opt in remoteopts:
3075 for opt in remoteopts:
3076 del opts[opt[1]]
3076 del opts[opt[1]]
3077 args = {}
3077 args = {}
3078 for k, v in opts.iteritems():
3078 for k, v in opts.iteritems():
3079 if v:
3079 if v:
3080 args[k] = v
3080 args[k] = v
3081 # run twice to check that we don't mess up the stream for the next command
3081 # run twice to check that we don't mess up the stream for the next command
3082 res1 = repo.debugwireargs(*vals, **args)
3082 res1 = repo.debugwireargs(*vals, **args)
3083 res2 = repo.debugwireargs(*vals, **args)
3083 res2 = repo.debugwireargs(*vals, **args)
3084 ui.write("%s\n" % res1)
3084 ui.write("%s\n" % res1)
3085 if res1 != res2:
3085 if res1 != res2:
3086 ui.warn("%s\n" % res2)
3086 ui.warn("%s\n" % res2)
3087
3087
3088 @command('^diff',
3088 @command('^diff',
3089 [('r', 'rev', [], _('revision'), _('REV')),
3089 [('r', 'rev', [], _('revision'), _('REV')),
3090 ('c', 'change', '', _('change made by revision'), _('REV'))
3090 ('c', 'change', '', _('change made by revision'), _('REV'))
3091 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3091 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3092 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3092 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3093 inferrepo=True)
3093 inferrepo=True)
3094 def diff(ui, repo, *pats, **opts):
3094 def diff(ui, repo, *pats, **opts):
3095 """diff repository (or selected files)
3095 """diff repository (or selected files)
3096
3096
3097 Show differences between revisions for the specified files.
3097 Show differences between revisions for the specified files.
3098
3098
3099 Differences between files are shown using the unified diff format.
3099 Differences between files are shown using the unified diff format.
3100
3100
3101 .. note::
3101 .. note::
3102
3102
3103 diff may generate unexpected results for merges, as it will
3103 diff may generate unexpected results for merges, as it will
3104 default to comparing against the working directory's first
3104 default to comparing against the working directory's first
3105 parent changeset if no revisions are specified.
3105 parent changeset if no revisions are specified.
3106
3106
3107 When two revision arguments are given, then changes are shown
3107 When two revision arguments are given, then changes are shown
3108 between those revisions. If only one revision is specified then
3108 between those revisions. If only one revision is specified then
3109 that revision is compared to the working directory, and, when no
3109 that revision is compared to the working directory, and, when no
3110 revisions are specified, the working directory files are compared
3110 revisions are specified, the working directory files are compared
3111 to its parent.
3111 to its parent.
3112
3112
3113 Alternatively you can specify -c/--change with a revision to see
3113 Alternatively you can specify -c/--change with a revision to see
3114 the changes in that changeset relative to its first parent.
3114 the changes in that changeset relative to its first parent.
3115
3115
3116 Without the -a/--text option, diff will avoid generating diffs of
3116 Without the -a/--text option, diff will avoid generating diffs of
3117 files it detects as binary. With -a, diff will generate a diff
3117 files it detects as binary. With -a, diff will generate a diff
3118 anyway, probably with undesirable results.
3118 anyway, probably with undesirable results.
3119
3119
3120 Use the -g/--git option to generate diffs in the git extended diff
3120 Use the -g/--git option to generate diffs in the git extended diff
3121 format. For more information, read :hg:`help diffs`.
3121 format. For more information, read :hg:`help diffs`.
3122
3122
3123 .. container:: verbose
3123 .. container:: verbose
3124
3124
3125 Examples:
3125 Examples:
3126
3126
3127 - compare a file in the current working directory to its parent::
3127 - compare a file in the current working directory to its parent::
3128
3128
3129 hg diff foo.c
3129 hg diff foo.c
3130
3130
3131 - compare two historical versions of a directory, with rename info::
3131 - compare two historical versions of a directory, with rename info::
3132
3132
3133 hg diff --git -r 1.0:1.2 lib/
3133 hg diff --git -r 1.0:1.2 lib/
3134
3134
3135 - get change stats relative to the last change on some date::
3135 - get change stats relative to the last change on some date::
3136
3136
3137 hg diff --stat -r "date('may 2')"
3137 hg diff --stat -r "date('may 2')"
3138
3138
3139 - diff all newly-added files that contain a keyword::
3139 - diff all newly-added files that contain a keyword::
3140
3140
3141 hg diff "set:added() and grep(GNU)"
3141 hg diff "set:added() and grep(GNU)"
3142
3142
3143 - compare a revision and its parents::
3143 - compare a revision and its parents::
3144
3144
3145 hg diff -c 9353 # compare against first parent
3145 hg diff -c 9353 # compare against first parent
3146 hg diff -r 9353^:9353 # same using revset syntax
3146 hg diff -r 9353^:9353 # same using revset syntax
3147 hg diff -r 9353^2:9353 # compare against the second parent
3147 hg diff -r 9353^2:9353 # compare against the second parent
3148
3148
3149 Returns 0 on success.
3149 Returns 0 on success.
3150 """
3150 """
3151
3151
3152 revs = opts.get('rev')
3152 revs = opts.get('rev')
3153 change = opts.get('change')
3153 change = opts.get('change')
3154 stat = opts.get('stat')
3154 stat = opts.get('stat')
3155 reverse = opts.get('reverse')
3155 reverse = opts.get('reverse')
3156
3156
3157 if revs and change:
3157 if revs and change:
3158 msg = _('cannot specify --rev and --change at the same time')
3158 msg = _('cannot specify --rev and --change at the same time')
3159 raise util.Abort(msg)
3159 raise util.Abort(msg)
3160 elif change:
3160 elif change:
3161 node2 = scmutil.revsingle(repo, change, None).node()
3161 node2 = scmutil.revsingle(repo, change, None).node()
3162 node1 = repo[node2].p1().node()
3162 node1 = repo[node2].p1().node()
3163 else:
3163 else:
3164 node1, node2 = scmutil.revpair(repo, revs)
3164 node1, node2 = scmutil.revpair(repo, revs)
3165
3165
3166 if reverse:
3166 if reverse:
3167 node1, node2 = node2, node1
3167 node1, node2 = node2, node1
3168
3168
3169 diffopts = patch.diffallopts(ui, opts)
3169 diffopts = patch.diffallopts(ui, opts)
3170 m = scmutil.match(repo[node2], pats, opts)
3170 m = scmutil.match(repo[node2], pats, opts)
3171 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3171 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3172 listsubrepos=opts.get('subrepos'))
3172 listsubrepos=opts.get('subrepos'))
3173
3173
3174 @command('^export',
3174 @command('^export',
3175 [('o', 'output', '',
3175 [('o', 'output', '',
3176 _('print output to file with formatted name'), _('FORMAT')),
3176 _('print output to file with formatted name'), _('FORMAT')),
3177 ('', 'switch-parent', None, _('diff against the second parent')),
3177 ('', 'switch-parent', None, _('diff against the second parent')),
3178 ('r', 'rev', [], _('revisions to export'), _('REV')),
3178 ('r', 'rev', [], _('revisions to export'), _('REV')),
3179 ] + diffopts,
3179 ] + diffopts,
3180 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3180 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3181 def export(ui, repo, *changesets, **opts):
3181 def export(ui, repo, *changesets, **opts):
3182 """dump the header and diffs for one or more changesets
3182 """dump the header and diffs for one or more changesets
3183
3183
3184 Print the changeset header and diffs for one or more revisions.
3184 Print the changeset header and diffs for one or more revisions.
3185 If no revision is given, the parent of the working directory is used.
3185 If no revision is given, the parent of the working directory is used.
3186
3186
3187 The information shown in the changeset header is: author, date,
3187 The information shown in the changeset header is: author, date,
3188 branch name (if non-default), changeset hash, parent(s) and commit
3188 branch name (if non-default), changeset hash, parent(s) and commit
3189 comment.
3189 comment.
3190
3190
3191 .. note::
3191 .. note::
3192
3192
3193 export may generate unexpected diff output for merge
3193 export may generate unexpected diff output for merge
3194 changesets, as it will compare the merge changeset against its
3194 changesets, as it will compare the merge changeset against its
3195 first parent only.
3195 first parent only.
3196
3196
3197 Output may be to a file, in which case the name of the file is
3197 Output may be to a file, in which case the name of the file is
3198 given using a format string. The formatting rules are as follows:
3198 given using a format string. The formatting rules are as follows:
3199
3199
3200 :``%%``: literal "%" character
3200 :``%%``: literal "%" character
3201 :``%H``: changeset hash (40 hexadecimal digits)
3201 :``%H``: changeset hash (40 hexadecimal digits)
3202 :``%N``: number of patches being generated
3202 :``%N``: number of patches being generated
3203 :``%R``: changeset revision number
3203 :``%R``: changeset revision number
3204 :``%b``: basename of the exporting repository
3204 :``%b``: basename of the exporting repository
3205 :``%h``: short-form changeset hash (12 hexadecimal digits)
3205 :``%h``: short-form changeset hash (12 hexadecimal digits)
3206 :``%m``: first line of the commit message (only alphanumeric characters)
3206 :``%m``: first line of the commit message (only alphanumeric characters)
3207 :``%n``: zero-padded sequence number, starting at 1
3207 :``%n``: zero-padded sequence number, starting at 1
3208 :``%r``: zero-padded changeset revision number
3208 :``%r``: zero-padded changeset revision number
3209
3209
3210 Without the -a/--text option, export will avoid generating diffs
3210 Without the -a/--text option, export will avoid generating diffs
3211 of files it detects as binary. With -a, export will generate a
3211 of files it detects as binary. With -a, export will generate a
3212 diff anyway, probably with undesirable results.
3212 diff anyway, probably with undesirable results.
3213
3213
3214 Use the -g/--git option to generate diffs in the git extended diff
3214 Use the -g/--git option to generate diffs in the git extended diff
3215 format. See :hg:`help diffs` for more information.
3215 format. See :hg:`help diffs` for more information.
3216
3216
3217 With the --switch-parent option, the diff will be against the
3217 With the --switch-parent option, the diff will be against the
3218 second parent. It can be useful to review a merge.
3218 second parent. It can be useful to review a merge.
3219
3219
3220 .. container:: verbose
3220 .. container:: verbose
3221
3221
3222 Examples:
3222 Examples:
3223
3223
3224 - use export and import to transplant a bugfix to the current
3224 - use export and import to transplant a bugfix to the current
3225 branch::
3225 branch::
3226
3226
3227 hg export -r 9353 | hg import -
3227 hg export -r 9353 | hg import -
3228
3228
3229 - export all the changesets between two revisions to a file with
3229 - export all the changesets between two revisions to a file with
3230 rename information::
3230 rename information::
3231
3231
3232 hg export --git -r 123:150 > changes.txt
3232 hg export --git -r 123:150 > changes.txt
3233
3233
3234 - split outgoing changes into a series of patches with
3234 - split outgoing changes into a series of patches with
3235 descriptive names::
3235 descriptive names::
3236
3236
3237 hg export -r "outgoing()" -o "%n-%m.patch"
3237 hg export -r "outgoing()" -o "%n-%m.patch"
3238
3238
3239 Returns 0 on success.
3239 Returns 0 on success.
3240 """
3240 """
3241 changesets += tuple(opts.get('rev', []))
3241 changesets += tuple(opts.get('rev', []))
3242 if not changesets:
3242 if not changesets:
3243 changesets = ['.']
3243 changesets = ['.']
3244 revs = scmutil.revrange(repo, changesets)
3244 revs = scmutil.revrange(repo, changesets)
3245 if not revs:
3245 if not revs:
3246 raise util.Abort(_("export requires at least one changeset"))
3246 raise util.Abort(_("export requires at least one changeset"))
3247 if len(revs) > 1:
3247 if len(revs) > 1:
3248 ui.note(_('exporting patches:\n'))
3248 ui.note(_('exporting patches:\n'))
3249 else:
3249 else:
3250 ui.note(_('exporting patch:\n'))
3250 ui.note(_('exporting patch:\n'))
3251 cmdutil.export(repo, revs, template=opts.get('output'),
3251 cmdutil.export(repo, revs, template=opts.get('output'),
3252 switch_parent=opts.get('switch_parent'),
3252 switch_parent=opts.get('switch_parent'),
3253 opts=patch.diffallopts(ui, opts))
3253 opts=patch.diffallopts(ui, opts))
3254
3254
3255 @command('files',
3255 @command('files',
3256 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3256 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3257 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3257 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3258 ] + walkopts + formatteropts + subrepoopts,
3258 ] + walkopts + formatteropts + subrepoopts,
3259 _('[OPTION]... [PATTERN]...'))
3259 _('[OPTION]... [PATTERN]...'))
3260 def files(ui, repo, *pats, **opts):
3260 def files(ui, repo, *pats, **opts):
3261 """list tracked files
3261 """list tracked files
3262
3262
3263 Print files under Mercurial control in the working directory or
3263 Print files under Mercurial control in the working directory or
3264 specified revision whose names match the given patterns (excluding
3264 specified revision whose names match the given patterns (excluding
3265 removed files).
3265 removed files).
3266
3266
3267 If no patterns are given to match, this command prints the names
3267 If no patterns are given to match, this command prints the names
3268 of all files under Mercurial control in the working directory.
3268 of all files under Mercurial control in the working directory.
3269
3269
3270 .. container:: verbose
3270 .. container:: verbose
3271
3271
3272 Examples:
3272 Examples:
3273
3273
3274 - list all files under the current directory::
3274 - list all files under the current directory::
3275
3275
3276 hg files .
3276 hg files .
3277
3277
3278 - shows sizes and flags for current revision::
3278 - shows sizes and flags for current revision::
3279
3279
3280 hg files -vr .
3280 hg files -vr .
3281
3281
3282 - list all files named README::
3282 - list all files named README::
3283
3283
3284 hg files -I "**/README"
3284 hg files -I "**/README"
3285
3285
3286 - list all binary files::
3286 - list all binary files::
3287
3287
3288 hg files "set:binary()"
3288 hg files "set:binary()"
3289
3289
3290 - find files containing a regular expression::
3290 - find files containing a regular expression::
3291
3291
3292 hg files "set:grep('bob')"
3292 hg files "set:grep('bob')"
3293
3293
3294 - search tracked file contents with xargs and grep::
3294 - search tracked file contents with xargs and grep::
3295
3295
3296 hg files -0 | xargs -0 grep foo
3296 hg files -0 | xargs -0 grep foo
3297
3297
3298 See :hg:`help patterns` and :hg:`help filesets` for more information
3298 See :hg:`help patterns` and :hg:`help filesets` for more information
3299 on specifying file patterns.
3299 on specifying file patterns.
3300
3300
3301 Returns 0 if a match is found, 1 otherwise.
3301 Returns 0 if a match is found, 1 otherwise.
3302
3302
3303 """
3303 """
3304 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3304 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3305
3305
3306 end = '\n'
3306 end = '\n'
3307 if opts.get('print0'):
3307 if opts.get('print0'):
3308 end = '\0'
3308 end = '\0'
3309 fm = ui.formatter('files', opts)
3309 fm = ui.formatter('files', opts)
3310 fmt = '%s' + end
3310 fmt = '%s' + end
3311
3311
3312 m = scmutil.match(ctx, pats, opts)
3312 m = scmutil.match(ctx, pats, opts)
3313 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3313 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3314
3314
3315 fm.end()
3315 fm.end()
3316
3316
3317 return ret
3317 return ret
3318
3318
3319 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3319 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3320 def forget(ui, repo, *pats, **opts):
3320 def forget(ui, repo, *pats, **opts):
3321 """forget the specified files on the next commit
3321 """forget the specified files on the next commit
3322
3322
3323 Mark the specified files so they will no longer be tracked
3323 Mark the specified files so they will no longer be tracked
3324 after the next commit.
3324 after the next commit.
3325
3325
3326 This only removes files from the current branch, not from the
3326 This only removes files from the current branch, not from the
3327 entire project history, and it does not delete them from the
3327 entire project history, and it does not delete them from the
3328 working directory.
3328 working directory.
3329
3329
3330 To undo a forget before the next commit, see :hg:`add`.
3330 To undo a forget before the next commit, see :hg:`add`.
3331
3331
3332 .. container:: verbose
3332 .. container:: verbose
3333
3333
3334 Examples:
3334 Examples:
3335
3335
3336 - forget newly-added binary files::
3336 - forget newly-added binary files::
3337
3337
3338 hg forget "set:added() and binary()"
3338 hg forget "set:added() and binary()"
3339
3339
3340 - forget files that would be excluded by .hgignore::
3340 - forget files that would be excluded by .hgignore::
3341
3341
3342 hg forget "set:hgignore()"
3342 hg forget "set:hgignore()"
3343
3343
3344 Returns 0 on success.
3344 Returns 0 on success.
3345 """
3345 """
3346
3346
3347 if not pats:
3347 if not pats:
3348 raise util.Abort(_('no files specified'))
3348 raise util.Abort(_('no files specified'))
3349
3349
3350 m = scmutil.match(repo[None], pats, opts)
3350 m = scmutil.match(repo[None], pats, opts)
3351 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3351 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3352 return rejected and 1 or 0
3352 return rejected and 1 or 0
3353
3353
3354 @command(
3354 @command(
3355 'graft',
3355 'graft',
3356 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3356 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3357 ('c', 'continue', False, _('resume interrupted graft')),
3357 ('c', 'continue', False, _('resume interrupted graft')),
3358 ('e', 'edit', False, _('invoke editor on commit messages')),
3358 ('e', 'edit', False, _('invoke editor on commit messages')),
3359 ('', 'log', None, _('append graft info to log message')),
3359 ('', 'log', None, _('append graft info to log message')),
3360 ('f', 'force', False, _('force graft')),
3360 ('f', 'force', False, _('force graft')),
3361 ('D', 'currentdate', False,
3361 ('D', 'currentdate', False,
3362 _('record the current date as commit date')),
3362 _('record the current date as commit date')),
3363 ('U', 'currentuser', False,
3363 ('U', 'currentuser', False,
3364 _('record the current user as committer'), _('DATE'))]
3364 _('record the current user as committer'), _('DATE'))]
3365 + commitopts2 + mergetoolopts + dryrunopts,
3365 + commitopts2 + mergetoolopts + dryrunopts,
3366 _('[OPTION]... [-r] REV...'))
3366 _('[OPTION]... [-r] REV...'))
3367 def graft(ui, repo, *revs, **opts):
3367 def graft(ui, repo, *revs, **opts):
3368 '''copy changes from other branches onto the current branch
3368 '''copy changes from other branches onto the current branch
3369
3369
3370 This command uses Mercurial's merge logic to copy individual
3370 This command uses Mercurial's merge logic to copy individual
3371 changes from other branches without merging branches in the
3371 changes from other branches without merging branches in the
3372 history graph. This is sometimes known as 'backporting' or
3372 history graph. This is sometimes known as 'backporting' or
3373 'cherry-picking'. By default, graft will copy user, date, and
3373 'cherry-picking'. By default, graft will copy user, date, and
3374 description from the source changesets.
3374 description from the source changesets.
3375
3375
3376 Changesets that are ancestors of the current revision, that have
3376 Changesets that are ancestors of the current revision, that have
3377 already been grafted, or that are merges will be skipped.
3377 already been grafted, or that are merges will be skipped.
3378
3378
3379 If --log is specified, log messages will have a comment appended
3379 If --log is specified, log messages will have a comment appended
3380 of the form::
3380 of the form::
3381
3381
3382 (grafted from CHANGESETHASH)
3382 (grafted from CHANGESETHASH)
3383
3383
3384 If --force is specified, revisions will be grafted even if they
3384 If --force is specified, revisions will be grafted even if they
3385 are already ancestors of or have been grafted to the destination.
3385 are already ancestors of or have been grafted to the destination.
3386 This is useful when the revisions have since been backed out.
3386 This is useful when the revisions have since been backed out.
3387
3387
3388 If a graft merge results in conflicts, the graft process is
3388 If a graft merge results in conflicts, the graft process is
3389 interrupted so that the current merge can be manually resolved.
3389 interrupted so that the current merge can be manually resolved.
3390 Once all conflicts are addressed, the graft process can be
3390 Once all conflicts are addressed, the graft process can be
3391 continued with the -c/--continue option.
3391 continued with the -c/--continue option.
3392
3392
3393 .. note::
3393 .. note::
3394
3394
3395 The -c/--continue option does not reapply earlier options, except
3395 The -c/--continue option does not reapply earlier options, except
3396 for --force.
3396 for --force.
3397
3397
3398 .. container:: verbose
3398 .. container:: verbose
3399
3399
3400 Examples:
3400 Examples:
3401
3401
3402 - copy a single change to the stable branch and edit its description::
3402 - copy a single change to the stable branch and edit its description::
3403
3403
3404 hg update stable
3404 hg update stable
3405 hg graft --edit 9393
3405 hg graft --edit 9393
3406
3406
3407 - graft a range of changesets with one exception, updating dates::
3407 - graft a range of changesets with one exception, updating dates::
3408
3408
3409 hg graft -D "2085::2093 and not 2091"
3409 hg graft -D "2085::2093 and not 2091"
3410
3410
3411 - continue a graft after resolving conflicts::
3411 - continue a graft after resolving conflicts::
3412
3412
3413 hg graft -c
3413 hg graft -c
3414
3414
3415 - show the source of a grafted changeset::
3415 - show the source of a grafted changeset::
3416
3416
3417 hg log --debug -r .
3417 hg log --debug -r .
3418
3418
3419 See :hg:`help revisions` and :hg:`help revsets` for more about
3419 See :hg:`help revisions` and :hg:`help revsets` for more about
3420 specifying revisions.
3420 specifying revisions.
3421
3421
3422 Returns 0 on successful completion.
3422 Returns 0 on successful completion.
3423 '''
3423 '''
3424
3424
3425 revs = list(revs)
3425 revs = list(revs)
3426 revs.extend(opts['rev'])
3426 revs.extend(opts['rev'])
3427
3427
3428 if not opts.get('user') and opts.get('currentuser'):
3428 if not opts.get('user') and opts.get('currentuser'):
3429 opts['user'] = ui.username()
3429 opts['user'] = ui.username()
3430 if not opts.get('date') and opts.get('currentdate'):
3430 if not opts.get('date') and opts.get('currentdate'):
3431 opts['date'] = "%d %d" % util.makedate()
3431 opts['date'] = "%d %d" % util.makedate()
3432
3432
3433 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3433 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3434
3434
3435 cont = False
3435 cont = False
3436 if opts['continue']:
3436 if opts['continue']:
3437 cont = True
3437 cont = True
3438 if revs:
3438 if revs:
3439 raise util.Abort(_("can't specify --continue and revisions"))
3439 raise util.Abort(_("can't specify --continue and revisions"))
3440 # read in unfinished revisions
3440 # read in unfinished revisions
3441 try:
3441 try:
3442 nodes = repo.vfs.read('graftstate').splitlines()
3442 nodes = repo.vfs.read('graftstate').splitlines()
3443 revs = [repo[node].rev() for node in nodes]
3443 revs = [repo[node].rev() for node in nodes]
3444 except IOError, inst:
3444 except IOError, inst:
3445 if inst.errno != errno.ENOENT:
3445 if inst.errno != errno.ENOENT:
3446 raise
3446 raise
3447 raise util.Abort(_("no graft state found, can't continue"))
3447 raise util.Abort(_("no graft state found, can't continue"))
3448 else:
3448 else:
3449 cmdutil.checkunfinished(repo)
3449 cmdutil.checkunfinished(repo)
3450 cmdutil.bailifchanged(repo)
3450 cmdutil.bailifchanged(repo)
3451 if not revs:
3451 if not revs:
3452 raise util.Abort(_('no revisions specified'))
3452 raise util.Abort(_('no revisions specified'))
3453 revs = scmutil.revrange(repo, revs)
3453 revs = scmutil.revrange(repo, revs)
3454
3454
3455 skipped = set()
3455 skipped = set()
3456 # check for merges
3456 # check for merges
3457 for rev in repo.revs('%ld and merge()', revs):
3457 for rev in repo.revs('%ld and merge()', revs):
3458 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3458 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3459 skipped.add(rev)
3459 skipped.add(rev)
3460 revs = [r for r in revs if r not in skipped]
3460 revs = [r for r in revs if r not in skipped]
3461 if not revs:
3461 if not revs:
3462 return -1
3462 return -1
3463
3463
3464 # Don't check in the --continue case, in effect retaining --force across
3464 # Don't check in the --continue case, in effect retaining --force across
3465 # --continues. That's because without --force, any revisions we decided to
3465 # --continues. That's because without --force, any revisions we decided to
3466 # skip would have been filtered out here, so they wouldn't have made their
3466 # skip would have been filtered out here, so they wouldn't have made their
3467 # way to the graftstate. With --force, any revisions we would have otherwise
3467 # way to the graftstate. With --force, any revisions we would have otherwise
3468 # skipped would not have been filtered out, and if they hadn't been applied
3468 # skipped would not have been filtered out, and if they hadn't been applied
3469 # already, they'd have been in the graftstate.
3469 # already, they'd have been in the graftstate.
3470 if not (cont or opts.get('force')):
3470 if not (cont or opts.get('force')):
3471 # check for ancestors of dest branch
3471 # check for ancestors of dest branch
3472 crev = repo['.'].rev()
3472 crev = repo['.'].rev()
3473 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3473 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3474 # Cannot use x.remove(y) on smart set, this has to be a list.
3474 # Cannot use x.remove(y) on smart set, this has to be a list.
3475 # XXX make this lazy in the future
3475 # XXX make this lazy in the future
3476 revs = list(revs)
3476 revs = list(revs)
3477 # don't mutate while iterating, create a copy
3477 # don't mutate while iterating, create a copy
3478 for rev in list(revs):
3478 for rev in list(revs):
3479 if rev in ancestors:
3479 if rev in ancestors:
3480 ui.warn(_('skipping ancestor revision %d:%s\n') %
3480 ui.warn(_('skipping ancestor revision %d:%s\n') %
3481 (rev, repo[rev]))
3481 (rev, repo[rev]))
3482 # XXX remove on list is slow
3482 # XXX remove on list is slow
3483 revs.remove(rev)
3483 revs.remove(rev)
3484 if not revs:
3484 if not revs:
3485 return -1
3485 return -1
3486
3486
3487 # analyze revs for earlier grafts
3487 # analyze revs for earlier grafts
3488 ids = {}
3488 ids = {}
3489 for ctx in repo.set("%ld", revs):
3489 for ctx in repo.set("%ld", revs):
3490 ids[ctx.hex()] = ctx.rev()
3490 ids[ctx.hex()] = ctx.rev()
3491 n = ctx.extra().get('source')
3491 n = ctx.extra().get('source')
3492 if n:
3492 if n:
3493 ids[n] = ctx.rev()
3493 ids[n] = ctx.rev()
3494
3494
3495 # check ancestors for earlier grafts
3495 # check ancestors for earlier grafts
3496 ui.debug('scanning for duplicate grafts\n')
3496 ui.debug('scanning for duplicate grafts\n')
3497
3497
3498 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3498 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3499 ctx = repo[rev]
3499 ctx = repo[rev]
3500 n = ctx.extra().get('source')
3500 n = ctx.extra().get('source')
3501 if n in ids:
3501 if n in ids:
3502 try:
3502 try:
3503 r = repo[n].rev()
3503 r = repo[n].rev()
3504 except error.RepoLookupError:
3504 except error.RepoLookupError:
3505 r = None
3505 r = None
3506 if r in revs:
3506 if r in revs:
3507 ui.warn(_('skipping revision %d:%s '
3507 ui.warn(_('skipping revision %d:%s '
3508 '(already grafted to %d:%s)\n')
3508 '(already grafted to %d:%s)\n')
3509 % (r, repo[r], rev, ctx))
3509 % (r, repo[r], rev, ctx))
3510 revs.remove(r)
3510 revs.remove(r)
3511 elif ids[n] in revs:
3511 elif ids[n] in revs:
3512 if r is None:
3512 if r is None:
3513 ui.warn(_('skipping already grafted revision %d:%s '
3513 ui.warn(_('skipping already grafted revision %d:%s '
3514 '(%d:%s also has unknown origin %s)\n')
3514 '(%d:%s also has unknown origin %s)\n')
3515 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3515 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3516 else:
3516 else:
3517 ui.warn(_('skipping already grafted revision %d:%s '
3517 ui.warn(_('skipping already grafted revision %d:%s '
3518 '(%d:%s also has origin %d:%s)\n')
3518 '(%d:%s also has origin %d:%s)\n')
3519 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3519 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3520 revs.remove(ids[n])
3520 revs.remove(ids[n])
3521 elif ctx.hex() in ids:
3521 elif ctx.hex() in ids:
3522 r = ids[ctx.hex()]
3522 r = ids[ctx.hex()]
3523 ui.warn(_('skipping already grafted revision %d:%s '
3523 ui.warn(_('skipping already grafted revision %d:%s '
3524 '(was grafted from %d:%s)\n') %
3524 '(was grafted from %d:%s)\n') %
3525 (r, repo[r], rev, ctx))
3525 (r, repo[r], rev, ctx))
3526 revs.remove(r)
3526 revs.remove(r)
3527 if not revs:
3527 if not revs:
3528 return -1
3528 return -1
3529
3529
3530 wlock = repo.wlock()
3530 wlock = repo.wlock()
3531 try:
3531 try:
3532 for pos, ctx in enumerate(repo.set("%ld", revs)):
3532 for pos, ctx in enumerate(repo.set("%ld", revs)):
3533 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3533 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3534 ctx.description().split('\n', 1)[0])
3534 ctx.description().split('\n', 1)[0])
3535 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3535 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3536 if names:
3536 if names:
3537 desc += ' (%s)' % ' '.join(names)
3537 desc += ' (%s)' % ' '.join(names)
3538 ui.status(_('grafting %s\n') % desc)
3538 ui.status(_('grafting %s\n') % desc)
3539 if opts.get('dry_run'):
3539 if opts.get('dry_run'):
3540 continue
3540 continue
3541
3541
3542 source = ctx.extra().get('source')
3542 source = ctx.extra().get('source')
3543 if not source:
3543 if not source:
3544 source = ctx.hex()
3544 source = ctx.hex()
3545 extra = {'source': source}
3545 extra = {'source': source}
3546 user = ctx.user()
3546 user = ctx.user()
3547 if opts.get('user'):
3547 if opts.get('user'):
3548 user = opts['user']
3548 user = opts['user']
3549 date = ctx.date()
3549 date = ctx.date()
3550 if opts.get('date'):
3550 if opts.get('date'):
3551 date = opts['date']
3551 date = opts['date']
3552 message = ctx.description()
3552 message = ctx.description()
3553 if opts.get('log'):
3553 if opts.get('log'):
3554 message += '\n(grafted from %s)' % ctx.hex()
3554 message += '\n(grafted from %s)' % ctx.hex()
3555
3555
3556 # we don't merge the first commit when continuing
3556 # we don't merge the first commit when continuing
3557 if not cont:
3557 if not cont:
3558 # perform the graft merge with p1(rev) as 'ancestor'
3558 # perform the graft merge with p1(rev) as 'ancestor'
3559 try:
3559 try:
3560 # ui.forcemerge is an internal variable, do not document
3560 # ui.forcemerge is an internal variable, do not document
3561 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3561 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3562 'graft')
3562 'graft')
3563 stats = mergemod.graft(repo, ctx, ctx.p1(),
3563 stats = mergemod.graft(repo, ctx, ctx.p1(),
3564 ['local', 'graft'])
3564 ['local', 'graft'])
3565 finally:
3565 finally:
3566 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3566 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3567 # report any conflicts
3567 # report any conflicts
3568 if stats and stats[3] > 0:
3568 if stats and stats[3] > 0:
3569 # write out state for --continue
3569 # write out state for --continue
3570 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3570 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3571 repo.vfs.write('graftstate', ''.join(nodelines))
3571 repo.vfs.write('graftstate', ''.join(nodelines))
3572 raise util.Abort(
3572 raise util.Abort(
3573 _("unresolved conflicts, can't continue"),
3573 _("unresolved conflicts, can't continue"),
3574 hint=_('use hg resolve and hg graft --continue'))
3574 hint=_('use hg resolve and hg graft --continue'))
3575 else:
3575 else:
3576 cont = False
3576 cont = False
3577
3577
3578 # commit
3578 # commit
3579 node = repo.commit(text=message, user=user,
3579 node = repo.commit(text=message, user=user,
3580 date=date, extra=extra, editor=editor)
3580 date=date, extra=extra, editor=editor)
3581 if node is None:
3581 if node is None:
3582 ui.warn(
3582 ui.warn(
3583 _('note: graft of %d:%s created no changes to commit\n') %
3583 _('note: graft of %d:%s created no changes to commit\n') %
3584 (ctx.rev(), ctx))
3584 (ctx.rev(), ctx))
3585 finally:
3585 finally:
3586 wlock.release()
3586 wlock.release()
3587
3587
3588 # remove state when we complete successfully
3588 # remove state when we complete successfully
3589 if not opts.get('dry_run'):
3589 if not opts.get('dry_run'):
3590 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3590 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3591
3591
3592 return 0
3592 return 0
3593
3593
3594 @command('grep',
3594 @command('grep',
3595 [('0', 'print0', None, _('end fields with NUL')),
3595 [('0', 'print0', None, _('end fields with NUL')),
3596 ('', 'all', None, _('print all revisions that match')),
3596 ('', 'all', None, _('print all revisions that match')),
3597 ('a', 'text', None, _('treat all files as text')),
3597 ('a', 'text', None, _('treat all files as text')),
3598 ('f', 'follow', None,
3598 ('f', 'follow', None,
3599 _('follow changeset history,'
3599 _('follow changeset history,'
3600 ' or file history across copies and renames')),
3600 ' or file history across copies and renames')),
3601 ('i', 'ignore-case', None, _('ignore case when matching')),
3601 ('i', 'ignore-case', None, _('ignore case when matching')),
3602 ('l', 'files-with-matches', None,
3602 ('l', 'files-with-matches', None,
3603 _('print only filenames and revisions that match')),
3603 _('print only filenames and revisions that match')),
3604 ('n', 'line-number', None, _('print matching line numbers')),
3604 ('n', 'line-number', None, _('print matching line numbers')),
3605 ('r', 'rev', [],
3605 ('r', 'rev', [],
3606 _('only search files changed within revision range'), _('REV')),
3606 _('only search files changed within revision range'), _('REV')),
3607 ('u', 'user', None, _('list the author (long with -v)')),
3607 ('u', 'user', None, _('list the author (long with -v)')),
3608 ('d', 'date', None, _('list the date (short with -q)')),
3608 ('d', 'date', None, _('list the date (short with -q)')),
3609 ] + walkopts,
3609 ] + walkopts,
3610 _('[OPTION]... PATTERN [FILE]...'),
3610 _('[OPTION]... PATTERN [FILE]...'),
3611 inferrepo=True)
3611 inferrepo=True)
3612 def grep(ui, repo, pattern, *pats, **opts):
3612 def grep(ui, repo, pattern, *pats, **opts):
3613 """search for a pattern in specified files and revisions
3613 """search for a pattern in specified files and revisions
3614
3614
3615 Search revisions of files for a regular expression.
3615 Search revisions of files for a regular expression.
3616
3616
3617 This command behaves differently than Unix grep. It only accepts
3617 This command behaves differently than Unix grep. It only accepts
3618 Python/Perl regexps. It searches repository history, not the
3618 Python/Perl regexps. It searches repository history, not the
3619 working directory. It always prints the revision number in which a
3619 working directory. It always prints the revision number in which a
3620 match appears.
3620 match appears.
3621
3621
3622 By default, grep only prints output for the first revision of a
3622 By default, grep only prints output for the first revision of a
3623 file in which it finds a match. To get it to print every revision
3623 file in which it finds a match. To get it to print every revision
3624 that contains a change in match status ("-" for a match that
3624 that contains a change in match status ("-" for a match that
3625 becomes a non-match, or "+" for a non-match that becomes a match),
3625 becomes a non-match, or "+" for a non-match that becomes a match),
3626 use the --all flag.
3626 use the --all flag.
3627
3627
3628 Returns 0 if a match is found, 1 otherwise.
3628 Returns 0 if a match is found, 1 otherwise.
3629 """
3629 """
3630 reflags = re.M
3630 reflags = re.M
3631 if opts.get('ignore_case'):
3631 if opts.get('ignore_case'):
3632 reflags |= re.I
3632 reflags |= re.I
3633 try:
3633 try:
3634 regexp = util.re.compile(pattern, reflags)
3634 regexp = util.re.compile(pattern, reflags)
3635 except re.error, inst:
3635 except re.error, inst:
3636 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3636 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3637 return 1
3637 return 1
3638 sep, eol = ':', '\n'
3638 sep, eol = ':', '\n'
3639 if opts.get('print0'):
3639 if opts.get('print0'):
3640 sep = eol = '\0'
3640 sep = eol = '\0'
3641
3641
3642 getfile = util.lrucachefunc(repo.file)
3642 getfile = util.lrucachefunc(repo.file)
3643
3643
3644 def matchlines(body):
3644 def matchlines(body):
3645 begin = 0
3645 begin = 0
3646 linenum = 0
3646 linenum = 0
3647 while begin < len(body):
3647 while begin < len(body):
3648 match = regexp.search(body, begin)
3648 match = regexp.search(body, begin)
3649 if not match:
3649 if not match:
3650 break
3650 break
3651 mstart, mend = match.span()
3651 mstart, mend = match.span()
3652 linenum += body.count('\n', begin, mstart) + 1
3652 linenum += body.count('\n', begin, mstart) + 1
3653 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3653 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3654 begin = body.find('\n', mend) + 1 or len(body) + 1
3654 begin = body.find('\n', mend) + 1 or len(body) + 1
3655 lend = begin - 1
3655 lend = begin - 1
3656 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3656 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3657
3657
3658 class linestate(object):
3658 class linestate(object):
3659 def __init__(self, line, linenum, colstart, colend):
3659 def __init__(self, line, linenum, colstart, colend):
3660 self.line = line
3660 self.line = line
3661 self.linenum = linenum
3661 self.linenum = linenum
3662 self.colstart = colstart
3662 self.colstart = colstart
3663 self.colend = colend
3663 self.colend = colend
3664
3664
3665 def __hash__(self):
3665 def __hash__(self):
3666 return hash((self.linenum, self.line))
3666 return hash((self.linenum, self.line))
3667
3667
3668 def __eq__(self, other):
3668 def __eq__(self, other):
3669 return self.line == other.line
3669 return self.line == other.line
3670
3670
3671 def __iter__(self):
3671 def __iter__(self):
3672 yield (self.line[:self.colstart], '')
3672 yield (self.line[:self.colstart], '')
3673 yield (self.line[self.colstart:self.colend], 'grep.match')
3673 yield (self.line[self.colstart:self.colend], 'grep.match')
3674 rest = self.line[self.colend:]
3674 rest = self.line[self.colend:]
3675 while rest != '':
3675 while rest != '':
3676 match = regexp.search(rest)
3676 match = regexp.search(rest)
3677 if not match:
3677 if not match:
3678 yield (rest, '')
3678 yield (rest, '')
3679 break
3679 break
3680 mstart, mend = match.span()
3680 mstart, mend = match.span()
3681 yield (rest[:mstart], '')
3681 yield (rest[:mstart], '')
3682 yield (rest[mstart:mend], 'grep.match')
3682 yield (rest[mstart:mend], 'grep.match')
3683 rest = rest[mend:]
3683 rest = rest[mend:]
3684
3684
3685 matches = {}
3685 matches = {}
3686 copies = {}
3686 copies = {}
3687 def grepbody(fn, rev, body):
3687 def grepbody(fn, rev, body):
3688 matches[rev].setdefault(fn, [])
3688 matches[rev].setdefault(fn, [])
3689 m = matches[rev][fn]
3689 m = matches[rev][fn]
3690 for lnum, cstart, cend, line in matchlines(body):
3690 for lnum, cstart, cend, line in matchlines(body):
3691 s = linestate(line, lnum, cstart, cend)
3691 s = linestate(line, lnum, cstart, cend)
3692 m.append(s)
3692 m.append(s)
3693
3693
3694 def difflinestates(a, b):
3694 def difflinestates(a, b):
3695 sm = difflib.SequenceMatcher(None, a, b)
3695 sm = difflib.SequenceMatcher(None, a, b)
3696 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3696 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3697 if tag == 'insert':
3697 if tag == 'insert':
3698 for i in xrange(blo, bhi):
3698 for i in xrange(blo, bhi):
3699 yield ('+', b[i])
3699 yield ('+', b[i])
3700 elif tag == 'delete':
3700 elif tag == 'delete':
3701 for i in xrange(alo, ahi):
3701 for i in xrange(alo, ahi):
3702 yield ('-', a[i])
3702 yield ('-', a[i])
3703 elif tag == 'replace':
3703 elif tag == 'replace':
3704 for i in xrange(alo, ahi):
3704 for i in xrange(alo, ahi):
3705 yield ('-', a[i])
3705 yield ('-', a[i])
3706 for i in xrange(blo, bhi):
3706 for i in xrange(blo, bhi):
3707 yield ('+', b[i])
3707 yield ('+', b[i])
3708
3708
3709 def display(fn, ctx, pstates, states):
3709 def display(fn, ctx, pstates, states):
3710 rev = ctx.rev()
3710 rev = ctx.rev()
3711 if ui.quiet:
3711 if ui.quiet:
3712 datefunc = util.shortdate
3712 datefunc = util.shortdate
3713 else:
3713 else:
3714 datefunc = util.datestr
3714 datefunc = util.datestr
3715 found = False
3715 found = False
3716 @util.cachefunc
3716 @util.cachefunc
3717 def binary():
3717 def binary():
3718 flog = getfile(fn)
3718 flog = getfile(fn)
3719 return util.binary(flog.read(ctx.filenode(fn)))
3719 return util.binary(flog.read(ctx.filenode(fn)))
3720
3720
3721 if opts.get('all'):
3721 if opts.get('all'):
3722 iter = difflinestates(pstates, states)
3722 iter = difflinestates(pstates, states)
3723 else:
3723 else:
3724 iter = [('', l) for l in states]
3724 iter = [('', l) for l in states]
3725 for change, l in iter:
3725 for change, l in iter:
3726 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3726 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3727
3727
3728 if opts.get('line_number'):
3728 if opts.get('line_number'):
3729 cols.append((str(l.linenum), 'grep.linenumber'))
3729 cols.append((str(l.linenum), 'grep.linenumber'))
3730 if opts.get('all'):
3730 if opts.get('all'):
3731 cols.append((change, 'grep.change'))
3731 cols.append((change, 'grep.change'))
3732 if opts.get('user'):
3732 if opts.get('user'):
3733 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3733 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3734 if opts.get('date'):
3734 if opts.get('date'):
3735 cols.append((datefunc(ctx.date()), 'grep.date'))
3735 cols.append((datefunc(ctx.date()), 'grep.date'))
3736 for col, label in cols[:-1]:
3736 for col, label in cols[:-1]:
3737 ui.write(col, label=label)
3737 ui.write(col, label=label)
3738 ui.write(sep, label='grep.sep')
3738 ui.write(sep, label='grep.sep')
3739 ui.write(cols[-1][0], label=cols[-1][1])
3739 ui.write(cols[-1][0], label=cols[-1][1])
3740 if not opts.get('files_with_matches'):
3740 if not opts.get('files_with_matches'):
3741 ui.write(sep, label='grep.sep')
3741 ui.write(sep, label='grep.sep')
3742 if not opts.get('text') and binary():
3742 if not opts.get('text') and binary():
3743 ui.write(" Binary file matches")
3743 ui.write(" Binary file matches")
3744 else:
3744 else:
3745 for s, label in l:
3745 for s, label in l:
3746 ui.write(s, label=label)
3746 ui.write(s, label=label)
3747 ui.write(eol)
3747 ui.write(eol)
3748 found = True
3748 found = True
3749 if opts.get('files_with_matches'):
3749 if opts.get('files_with_matches'):
3750 break
3750 break
3751 return found
3751 return found
3752
3752
3753 skip = {}
3753 skip = {}
3754 revfiles = {}
3754 revfiles = {}
3755 matchfn = scmutil.match(repo[None], pats, opts)
3755 matchfn = scmutil.match(repo[None], pats, opts)
3756 found = False
3756 found = False
3757 follow = opts.get('follow')
3757 follow = opts.get('follow')
3758
3758
3759 def prep(ctx, fns):
3759 def prep(ctx, fns):
3760 rev = ctx.rev()
3760 rev = ctx.rev()
3761 pctx = ctx.p1()
3761 pctx = ctx.p1()
3762 parent = pctx.rev()
3762 parent = pctx.rev()
3763 matches.setdefault(rev, {})
3763 matches.setdefault(rev, {})
3764 matches.setdefault(parent, {})
3764 matches.setdefault(parent, {})
3765 files = revfiles.setdefault(rev, [])
3765 files = revfiles.setdefault(rev, [])
3766 for fn in fns:
3766 for fn in fns:
3767 flog = getfile(fn)
3767 flog = getfile(fn)
3768 try:
3768 try:
3769 fnode = ctx.filenode(fn)
3769 fnode = ctx.filenode(fn)
3770 except error.LookupError:
3770 except error.LookupError:
3771 continue
3771 continue
3772
3772
3773 copied = flog.renamed(fnode)
3773 copied = flog.renamed(fnode)
3774 copy = follow and copied and copied[0]
3774 copy = follow and copied and copied[0]
3775 if copy:
3775 if copy:
3776 copies.setdefault(rev, {})[fn] = copy
3776 copies.setdefault(rev, {})[fn] = copy
3777 if fn in skip:
3777 if fn in skip:
3778 if copy:
3778 if copy:
3779 skip[copy] = True
3779 skip[copy] = True
3780 continue
3780 continue
3781 files.append(fn)
3781 files.append(fn)
3782
3782
3783 if fn not in matches[rev]:
3783 if fn not in matches[rev]:
3784 grepbody(fn, rev, flog.read(fnode))
3784 grepbody(fn, rev, flog.read(fnode))
3785
3785
3786 pfn = copy or fn
3786 pfn = copy or fn
3787 if pfn not in matches[parent]:
3787 if pfn not in matches[parent]:
3788 try:
3788 try:
3789 fnode = pctx.filenode(pfn)
3789 fnode = pctx.filenode(pfn)
3790 grepbody(pfn, parent, flog.read(fnode))
3790 grepbody(pfn, parent, flog.read(fnode))
3791 except error.LookupError:
3791 except error.LookupError:
3792 pass
3792 pass
3793
3793
3794 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3794 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3795 rev = ctx.rev()
3795 rev = ctx.rev()
3796 parent = ctx.p1().rev()
3796 parent = ctx.p1().rev()
3797 for fn in sorted(revfiles.get(rev, [])):
3797 for fn in sorted(revfiles.get(rev, [])):
3798 states = matches[rev][fn]
3798 states = matches[rev][fn]
3799 copy = copies.get(rev, {}).get(fn)
3799 copy = copies.get(rev, {}).get(fn)
3800 if fn in skip:
3800 if fn in skip:
3801 if copy:
3801 if copy:
3802 skip[copy] = True
3802 skip[copy] = True
3803 continue
3803 continue
3804 pstates = matches.get(parent, {}).get(copy or fn, [])
3804 pstates = matches.get(parent, {}).get(copy or fn, [])
3805 if pstates or states:
3805 if pstates or states:
3806 r = display(fn, ctx, pstates, states)
3806 r = display(fn, ctx, pstates, states)
3807 found = found or r
3807 found = found or r
3808 if r and not opts.get('all'):
3808 if r and not opts.get('all'):
3809 skip[fn] = True
3809 skip[fn] = True
3810 if copy:
3810 if copy:
3811 skip[copy] = True
3811 skip[copy] = True
3812 del matches[rev]
3812 del matches[rev]
3813 del revfiles[rev]
3813 del revfiles[rev]
3814
3814
3815 return not found
3815 return not found
3816
3816
3817 @command('heads',
3817 @command('heads',
3818 [('r', 'rev', '',
3818 [('r', 'rev', '',
3819 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3819 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3820 ('t', 'topo', False, _('show topological heads only')),
3820 ('t', 'topo', False, _('show topological heads only')),
3821 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3821 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3822 ('c', 'closed', False, _('show normal and closed branch heads')),
3822 ('c', 'closed', False, _('show normal and closed branch heads')),
3823 ] + templateopts,
3823 ] + templateopts,
3824 _('[-ct] [-r STARTREV] [REV]...'))
3824 _('[-ct] [-r STARTREV] [REV]...'))
3825 def heads(ui, repo, *branchrevs, **opts):
3825 def heads(ui, repo, *branchrevs, **opts):
3826 """show branch heads
3826 """show branch heads
3827
3827
3828 With no arguments, show all open branch heads in the repository.
3828 With no arguments, show all open branch heads in the repository.
3829 Branch heads are changesets that have no descendants on the
3829 Branch heads are changesets that have no descendants on the
3830 same branch. They are where development generally takes place and
3830 same branch. They are where development generally takes place and
3831 are the usual targets for update and merge operations.
3831 are the usual targets for update and merge operations.
3832
3832
3833 If one or more REVs are given, only open branch heads on the
3833 If one or more REVs are given, only open branch heads on the
3834 branches associated with the specified changesets are shown. This
3834 branches associated with the specified changesets are shown. This
3835 means that you can use :hg:`heads .` to see the heads on the
3835 means that you can use :hg:`heads .` to see the heads on the
3836 currently checked-out branch.
3836 currently checked-out branch.
3837
3837
3838 If -c/--closed is specified, also show branch heads marked closed
3838 If -c/--closed is specified, also show branch heads marked closed
3839 (see :hg:`commit --close-branch`).
3839 (see :hg:`commit --close-branch`).
3840
3840
3841 If STARTREV is specified, only those heads that are descendants of
3841 If STARTREV is specified, only those heads that are descendants of
3842 STARTREV will be displayed.
3842 STARTREV will be displayed.
3843
3843
3844 If -t/--topo is specified, named branch mechanics will be ignored and only
3844 If -t/--topo is specified, named branch mechanics will be ignored and only
3845 topological heads (changesets with no children) will be shown.
3845 topological heads (changesets with no children) will be shown.
3846
3846
3847 Returns 0 if matching heads are found, 1 if not.
3847 Returns 0 if matching heads are found, 1 if not.
3848 """
3848 """
3849
3849
3850 start = None
3850 start = None
3851 if 'rev' in opts:
3851 if 'rev' in opts:
3852 start = scmutil.revsingle(repo, opts['rev'], None).node()
3852 start = scmutil.revsingle(repo, opts['rev'], None).node()
3853
3853
3854 if opts.get('topo'):
3854 if opts.get('topo'):
3855 heads = [repo[h] for h in repo.heads(start)]
3855 heads = [repo[h] for h in repo.heads(start)]
3856 else:
3856 else:
3857 heads = []
3857 heads = []
3858 for branch in repo.branchmap():
3858 for branch in repo.branchmap():
3859 heads += repo.branchheads(branch, start, opts.get('closed'))
3859 heads += repo.branchheads(branch, start, opts.get('closed'))
3860 heads = [repo[h] for h in heads]
3860 heads = [repo[h] for h in heads]
3861
3861
3862 if branchrevs:
3862 if branchrevs:
3863 branches = set(repo[br].branch() for br in branchrevs)
3863 branches = set(repo[br].branch() for br in branchrevs)
3864 heads = [h for h in heads if h.branch() in branches]
3864 heads = [h for h in heads if h.branch() in branches]
3865
3865
3866 if opts.get('active') and branchrevs:
3866 if opts.get('active') and branchrevs:
3867 dagheads = repo.heads(start)
3867 dagheads = repo.heads(start)
3868 heads = [h for h in heads if h.node() in dagheads]
3868 heads = [h for h in heads if h.node() in dagheads]
3869
3869
3870 if branchrevs:
3870 if branchrevs:
3871 haveheads = set(h.branch() for h in heads)
3871 haveheads = set(h.branch() for h in heads)
3872 if branches - haveheads:
3872 if branches - haveheads:
3873 headless = ', '.join(b for b in branches - haveheads)
3873 headless = ', '.join(b for b in branches - haveheads)
3874 msg = _('no open branch heads found on branches %s')
3874 msg = _('no open branch heads found on branches %s')
3875 if opts.get('rev'):
3875 if opts.get('rev'):
3876 msg += _(' (started at %s)') % opts['rev']
3876 msg += _(' (started at %s)') % opts['rev']
3877 ui.warn((msg + '\n') % headless)
3877 ui.warn((msg + '\n') % headless)
3878
3878
3879 if not heads:
3879 if not heads:
3880 return 1
3880 return 1
3881
3881
3882 heads = sorted(heads, key=lambda x: -x.rev())
3882 heads = sorted(heads, key=lambda x: -x.rev())
3883 displayer = cmdutil.show_changeset(ui, repo, opts)
3883 displayer = cmdutil.show_changeset(ui, repo, opts)
3884 for ctx in heads:
3884 for ctx in heads:
3885 displayer.show(ctx)
3885 displayer.show(ctx)
3886 displayer.close()
3886 displayer.close()
3887
3887
3888 @command('help',
3888 @command('help',
3889 [('e', 'extension', None, _('show only help for extensions')),
3889 [('e', 'extension', None, _('show only help for extensions')),
3890 ('c', 'command', None, _('show only help for commands')),
3890 ('c', 'command', None, _('show only help for commands')),
3891 ('k', 'keyword', '', _('show topics matching keyword')),
3891 ('k', 'keyword', '', _('show topics matching keyword')),
3892 ],
3892 ],
3893 _('[-ec] [TOPIC]'),
3893 _('[-ec] [TOPIC]'),
3894 norepo=True)
3894 norepo=True)
3895 def help_(ui, name=None, **opts):
3895 def help_(ui, name=None, **opts):
3896 """show help for a given topic or a help overview
3896 """show help for a given topic or a help overview
3897
3897
3898 With no arguments, print a list of commands with short help messages.
3898 With no arguments, print a list of commands with short help messages.
3899
3899
3900 Given a topic, extension, or command name, print help for that
3900 Given a topic, extension, or command name, print help for that
3901 topic.
3901 topic.
3902
3902
3903 Returns 0 if successful.
3903 Returns 0 if successful.
3904 """
3904 """
3905
3905
3906 textwidth = min(ui.termwidth(), 80) - 2
3906 textwidth = min(ui.termwidth(), 80) - 2
3907
3907
3908 keep = []
3908 keep = []
3909 if ui.verbose:
3909 if ui.verbose:
3910 keep.append('verbose')
3910 keep.append('verbose')
3911 if sys.platform.startswith('win'):
3911 if sys.platform.startswith('win'):
3912 keep.append('windows')
3912 keep.append('windows')
3913 elif sys.platform == 'OpenVMS':
3913 elif sys.platform == 'OpenVMS':
3914 keep.append('vms')
3914 keep.append('vms')
3915 elif sys.platform == 'plan9':
3915 elif sys.platform == 'plan9':
3916 keep.append('plan9')
3916 keep.append('plan9')
3917 else:
3917 else:
3918 keep.append('unix')
3918 keep.append('unix')
3919 keep.append(sys.platform.lower())
3919 keep.append(sys.platform.lower())
3920
3920
3921 section = None
3921 section = None
3922 if name and '.' in name:
3922 if name and '.' in name:
3923 name, section = name.split('.', 1)
3923 name, section = name.split('.', 1)
3924
3924
3925 text = help.help_(ui, name, **opts)
3925 text = help.help_(ui, name, **opts)
3926
3926
3927 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3927 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3928 section=section)
3928 section=section)
3929 if section and not formatted:
3929 if section and not formatted:
3930 raise util.Abort(_("help section not found"))
3930 raise util.Abort(_("help section not found"))
3931
3931
3932 if 'verbose' in pruned:
3932 if 'verbose' in pruned:
3933 keep.append('omitted')
3933 keep.append('omitted')
3934 else:
3934 else:
3935 keep.append('notomitted')
3935 keep.append('notomitted')
3936 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3936 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3937 section=section)
3937 section=section)
3938 ui.write(formatted)
3938 ui.write(formatted)
3939
3939
3940
3940
3941 @command('identify|id',
3941 @command('identify|id',
3942 [('r', 'rev', '',
3942 [('r', 'rev', '',
3943 _('identify the specified revision'), _('REV')),
3943 _('identify the specified revision'), _('REV')),
3944 ('n', 'num', None, _('show local revision number')),
3944 ('n', 'num', None, _('show local revision number')),
3945 ('i', 'id', None, _('show global revision id')),
3945 ('i', 'id', None, _('show global revision id')),
3946 ('b', 'branch', None, _('show branch')),
3946 ('b', 'branch', None, _('show branch')),
3947 ('t', 'tags', None, _('show tags')),
3947 ('t', 'tags', None, _('show tags')),
3948 ('B', 'bookmarks', None, _('show bookmarks')),
3948 ('B', 'bookmarks', None, _('show bookmarks')),
3949 ] + remoteopts,
3949 ] + remoteopts,
3950 _('[-nibtB] [-r REV] [SOURCE]'),
3950 _('[-nibtB] [-r REV] [SOURCE]'),
3951 optionalrepo=True)
3951 optionalrepo=True)
3952 def identify(ui, repo, source=None, rev=None,
3952 def identify(ui, repo, source=None, rev=None,
3953 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3953 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3954 """identify the working directory or specified revision
3954 """identify the working directory or specified revision
3955
3955
3956 Print a summary identifying the repository state at REV using one or
3956 Print a summary identifying the repository state at REV using one or
3957 two parent hash identifiers, followed by a "+" if the working
3957 two parent hash identifiers, followed by a "+" if the working
3958 directory has uncommitted changes, the branch name (if not default),
3958 directory has uncommitted changes, the branch name (if not default),
3959 a list of tags, and a list of bookmarks.
3959 a list of tags, and a list of bookmarks.
3960
3960
3961 When REV is not given, print a summary of the current state of the
3961 When REV is not given, print a summary of the current state of the
3962 repository.
3962 repository.
3963
3963
3964 Specifying a path to a repository root or Mercurial bundle will
3964 Specifying a path to a repository root or Mercurial bundle will
3965 cause lookup to operate on that repository/bundle.
3965 cause lookup to operate on that repository/bundle.
3966
3966
3967 .. container:: verbose
3967 .. container:: verbose
3968
3968
3969 Examples:
3969 Examples:
3970
3970
3971 - generate a build identifier for the working directory::
3971 - generate a build identifier for the working directory::
3972
3972
3973 hg id --id > build-id.dat
3973 hg id --id > build-id.dat
3974
3974
3975 - find the revision corresponding to a tag::
3975 - find the revision corresponding to a tag::
3976
3976
3977 hg id -n -r 1.3
3977 hg id -n -r 1.3
3978
3978
3979 - check the most recent revision of a remote repository::
3979 - check the most recent revision of a remote repository::
3980
3980
3981 hg id -r tip http://selenic.com/hg/
3981 hg id -r tip http://selenic.com/hg/
3982
3982
3983 Returns 0 if successful.
3983 Returns 0 if successful.
3984 """
3984 """
3985
3985
3986 if not repo and not source:
3986 if not repo and not source:
3987 raise util.Abort(_("there is no Mercurial repository here "
3987 raise util.Abort(_("there is no Mercurial repository here "
3988 "(.hg not found)"))
3988 "(.hg not found)"))
3989
3989
3990 if ui.debugflag:
3990 if ui.debugflag:
3991 hexfunc = hex
3991 hexfunc = hex
3992 else:
3992 else:
3993 hexfunc = short
3993 hexfunc = short
3994 default = not (num or id or branch or tags or bookmarks)
3994 default = not (num or id or branch or tags or bookmarks)
3995 output = []
3995 output = []
3996 revs = []
3996 revs = []
3997
3997
3998 if source:
3998 if source:
3999 source, branches = hg.parseurl(ui.expandpath(source))
3999 source, branches = hg.parseurl(ui.expandpath(source))
4000 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4000 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4001 repo = peer.local()
4001 repo = peer.local()
4002 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4002 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4003
4003
4004 if not repo:
4004 if not repo:
4005 if num or branch or tags:
4005 if num or branch or tags:
4006 raise util.Abort(
4006 raise util.Abort(
4007 _("can't query remote revision number, branch, or tags"))
4007 _("can't query remote revision number, branch, or tags"))
4008 if not rev and revs:
4008 if not rev and revs:
4009 rev = revs[0]
4009 rev = revs[0]
4010 if not rev:
4010 if not rev:
4011 rev = "tip"
4011 rev = "tip"
4012
4012
4013 remoterev = peer.lookup(rev)
4013 remoterev = peer.lookup(rev)
4014 if default or id:
4014 if default or id:
4015 output = [hexfunc(remoterev)]
4015 output = [hexfunc(remoterev)]
4016
4016
4017 def getbms():
4017 def getbms():
4018 bms = []
4018 bms = []
4019
4019
4020 if 'bookmarks' in peer.listkeys('namespaces'):
4020 if 'bookmarks' in peer.listkeys('namespaces'):
4021 hexremoterev = hex(remoterev)
4021 hexremoterev = hex(remoterev)
4022 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4022 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4023 if bmr == hexremoterev]
4023 if bmr == hexremoterev]
4024
4024
4025 return sorted(bms)
4025 return sorted(bms)
4026
4026
4027 if bookmarks:
4027 if bookmarks:
4028 output.extend(getbms())
4028 output.extend(getbms())
4029 elif default and not ui.quiet:
4029 elif default and not ui.quiet:
4030 # multiple bookmarks for a single parent separated by '/'
4030 # multiple bookmarks for a single parent separated by '/'
4031 bm = '/'.join(getbms())
4031 bm = '/'.join(getbms())
4032 if bm:
4032 if bm:
4033 output.append(bm)
4033 output.append(bm)
4034 else:
4034 else:
4035 if not rev:
4035 if not rev:
4036 ctx = repo[None]
4036 ctx = repo[None]
4037 parents = ctx.parents()
4037 parents = ctx.parents()
4038 changed = ""
4038 changed = ""
4039 if default or id or num:
4039 if default or id or num:
4040 if (util.any(repo.status())
4040 if (util.any(repo.status())
4041 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4041 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4042 changed = '+'
4042 changed = '+'
4043 if default or id:
4043 if default or id:
4044 output = ["%s%s" %
4044 output = ["%s%s" %
4045 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4045 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4046 if num:
4046 if num:
4047 output.append("%s%s" %
4047 output.append("%s%s" %
4048 ('+'.join([str(p.rev()) for p in parents]), changed))
4048 ('+'.join([str(p.rev()) for p in parents]), changed))
4049 else:
4049 else:
4050 ctx = scmutil.revsingle(repo, rev)
4050 ctx = scmutil.revsingle(repo, rev)
4051 if default or id:
4051 if default or id:
4052 output = [hexfunc(ctx.node())]
4052 output = [hexfunc(ctx.node())]
4053 if num:
4053 if num:
4054 output.append(str(ctx.rev()))
4054 output.append(str(ctx.rev()))
4055
4055
4056 if default and not ui.quiet:
4056 if default and not ui.quiet:
4057 b = ctx.branch()
4057 b = ctx.branch()
4058 if b != 'default':
4058 if b != 'default':
4059 output.append("(%s)" % b)
4059 output.append("(%s)" % b)
4060
4060
4061 # multiple tags for a single parent separated by '/'
4061 # multiple tags for a single parent separated by '/'
4062 t = '/'.join(ctx.tags())
4062 t = '/'.join(ctx.tags())
4063 if t:
4063 if t:
4064 output.append(t)
4064 output.append(t)
4065
4065
4066 # multiple bookmarks for a single parent separated by '/'
4066 # multiple bookmarks for a single parent separated by '/'
4067 bm = '/'.join(ctx.bookmarks())
4067 bm = '/'.join(ctx.bookmarks())
4068 if bm:
4068 if bm:
4069 output.append(bm)
4069 output.append(bm)
4070 else:
4070 else:
4071 if branch:
4071 if branch:
4072 output.append(ctx.branch())
4072 output.append(ctx.branch())
4073
4073
4074 if tags:
4074 if tags:
4075 output.extend(ctx.tags())
4075 output.extend(ctx.tags())
4076
4076
4077 if bookmarks:
4077 if bookmarks:
4078 output.extend(ctx.bookmarks())
4078 output.extend(ctx.bookmarks())
4079
4079
4080 ui.write("%s\n" % ' '.join(output))
4080 ui.write("%s\n" % ' '.join(output))
4081
4081
4082 @command('import|patch',
4082 @command('import|patch',
4083 [('p', 'strip', 1,
4083 [('p', 'strip', 1,
4084 _('directory strip option for patch. This has the same '
4084 _('directory strip option for patch. This has the same '
4085 'meaning as the corresponding patch option'), _('NUM')),
4085 'meaning as the corresponding patch option'), _('NUM')),
4086 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4086 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4087 ('e', 'edit', False, _('invoke editor on commit messages')),
4087 ('e', 'edit', False, _('invoke editor on commit messages')),
4088 ('f', 'force', None,
4088 ('f', 'force', None,
4089 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4089 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4090 ('', 'no-commit', None,
4090 ('', 'no-commit', None,
4091 _("don't commit, just update the working directory")),
4091 _("don't commit, just update the working directory")),
4092 ('', 'bypass', None,
4092 ('', 'bypass', None,
4093 _("apply patch without touching the working directory")),
4093 _("apply patch without touching the working directory")),
4094 ('', 'partial', None,
4094 ('', 'partial', None,
4095 _('commit even if some hunks fail')),
4095 _('commit even if some hunks fail')),
4096 ('', 'exact', None,
4096 ('', 'exact', None,
4097 _('apply patch to the nodes from which it was generated')),
4097 _('apply patch to the nodes from which it was generated')),
4098 ('', 'prefix', '',
4098 ('', 'prefix', '',
4099 _('apply patch to subdirectory'), _('DIR')),
4099 _('apply patch to subdirectory'), _('DIR')),
4100 ('', 'import-branch', None,
4100 ('', 'import-branch', None,
4101 _('use any branch information in patch (implied by --exact)'))] +
4101 _('use any branch information in patch (implied by --exact)'))] +
4102 commitopts + commitopts2 + similarityopts,
4102 commitopts + commitopts2 + similarityopts,
4103 _('[OPTION]... PATCH...'))
4103 _('[OPTION]... PATCH...'))
4104 def import_(ui, repo, patch1=None, *patches, **opts):
4104 def import_(ui, repo, patch1=None, *patches, **opts):
4105 """import an ordered set of patches
4105 """import an ordered set of patches
4106
4106
4107 Import a list of patches and commit them individually (unless
4107 Import a list of patches and commit them individually (unless
4108 --no-commit is specified).
4108 --no-commit is specified).
4109
4109
4110 Because import first applies changes to the working directory,
4110 Because import first applies changes to the working directory,
4111 import will abort if there are outstanding changes.
4111 import will abort if there are outstanding changes.
4112
4112
4113 You can import a patch straight from a mail message. Even patches
4113 You can import a patch straight from a mail message. Even patches
4114 as attachments work (to use the body part, it must have type
4114 as attachments work (to use the body part, it must have type
4115 text/plain or text/x-patch). From and Subject headers of email
4115 text/plain or text/x-patch). From and Subject headers of email
4116 message are used as default committer and commit message. All
4116 message are used as default committer and commit message. All
4117 text/plain body parts before first diff are added to commit
4117 text/plain body parts before first diff are added to commit
4118 message.
4118 message.
4119
4119
4120 If the imported patch was generated by :hg:`export`, user and
4120 If the imported patch was generated by :hg:`export`, user and
4121 description from patch override values from message headers and
4121 description from patch override values from message headers and
4122 body. Values given on command line with -m/--message and -u/--user
4122 body. Values given on command line with -m/--message and -u/--user
4123 override these.
4123 override these.
4124
4124
4125 If --exact is specified, import will set the working directory to
4125 If --exact is specified, import will set the working directory to
4126 the parent of each patch before applying it, and will abort if the
4126 the parent of each patch before applying it, and will abort if the
4127 resulting changeset has a different ID than the one recorded in
4127 resulting changeset has a different ID than the one recorded in
4128 the patch. This may happen due to character set problems or other
4128 the patch. This may happen due to character set problems or other
4129 deficiencies in the text patch format.
4129 deficiencies in the text patch format.
4130
4130
4131 Use --bypass to apply and commit patches directly to the
4131 Use --bypass to apply and commit patches directly to the
4132 repository, not touching the working directory. Without --exact,
4132 repository, not touching the working directory. Without --exact,
4133 patches will be applied on top of the working directory parent
4133 patches will be applied on top of the working directory parent
4134 revision.
4134 revision.
4135
4135
4136 With -s/--similarity, hg will attempt to discover renames and
4136 With -s/--similarity, hg will attempt to discover renames and
4137 copies in the patch in the same way as :hg:`addremove`.
4137 copies in the patch in the same way as :hg:`addremove`.
4138
4138
4139 Use --partial to ensure a changeset will be created from the patch
4139 Use --partial to ensure a changeset will be created from the patch
4140 even if some hunks fail to apply. Hunks that fail to apply will be
4140 even if some hunks fail to apply. Hunks that fail to apply will be
4141 written to a <target-file>.rej file. Conflicts can then be resolved
4141 written to a <target-file>.rej file. Conflicts can then be resolved
4142 by hand before :hg:`commit --amend` is run to update the created
4142 by hand before :hg:`commit --amend` is run to update the created
4143 changeset. This flag exists to let people import patches that
4143 changeset. This flag exists to let people import patches that
4144 partially apply without losing the associated metadata (author,
4144 partially apply without losing the associated metadata (author,
4145 date, description, ...). Note that when none of the hunk applies
4145 date, description, ...). Note that when none of the hunk applies
4146 cleanly, :hg:`import --partial` will create an empty changeset,
4146 cleanly, :hg:`import --partial` will create an empty changeset,
4147 importing only the patch metadata.
4147 importing only the patch metadata.
4148
4148
4149 To read a patch from standard input, use "-" as the patch name. If
4149 To read a patch from standard input, use "-" as the patch name. If
4150 a URL is specified, the patch will be downloaded from it.
4150 a URL is specified, the patch will be downloaded from it.
4151 See :hg:`help dates` for a list of formats valid for -d/--date.
4151 See :hg:`help dates` for a list of formats valid for -d/--date.
4152
4152
4153 .. container:: verbose
4153 .. container:: verbose
4154
4154
4155 Examples:
4155 Examples:
4156
4156
4157 - import a traditional patch from a website and detect renames::
4157 - import a traditional patch from a website and detect renames::
4158
4158
4159 hg import -s 80 http://example.com/bugfix.patch
4159 hg import -s 80 http://example.com/bugfix.patch
4160
4160
4161 - import a changeset from an hgweb server::
4161 - import a changeset from an hgweb server::
4162
4162
4163 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4163 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4164
4164
4165 - import all the patches in an Unix-style mbox::
4165 - import all the patches in an Unix-style mbox::
4166
4166
4167 hg import incoming-patches.mbox
4167 hg import incoming-patches.mbox
4168
4168
4169 - attempt to exactly restore an exported changeset (not always
4169 - attempt to exactly restore an exported changeset (not always
4170 possible)::
4170 possible)::
4171
4171
4172 hg import --exact proposed-fix.patch
4172 hg import --exact proposed-fix.patch
4173
4173
4174 Returns 0 on success, 1 on partial success (see --partial).
4174 Returns 0 on success, 1 on partial success (see --partial).
4175 """
4175 """
4176
4176
4177 if not patch1:
4177 if not patch1:
4178 raise util.Abort(_('need at least one patch to import'))
4178 raise util.Abort(_('need at least one patch to import'))
4179
4179
4180 patches = (patch1,) + patches
4180 patches = (patch1,) + patches
4181
4181
4182 date = opts.get('date')
4182 date = opts.get('date')
4183 if date:
4183 if date:
4184 opts['date'] = util.parsedate(date)
4184 opts['date'] = util.parsedate(date)
4185
4185
4186 update = not opts.get('bypass')
4186 update = not opts.get('bypass')
4187 if not update and opts.get('no_commit'):
4187 if not update and opts.get('no_commit'):
4188 raise util.Abort(_('cannot use --no-commit with --bypass'))
4188 raise util.Abort(_('cannot use --no-commit with --bypass'))
4189 try:
4189 try:
4190 sim = float(opts.get('similarity') or 0)
4190 sim = float(opts.get('similarity') or 0)
4191 except ValueError:
4191 except ValueError:
4192 raise util.Abort(_('similarity must be a number'))
4192 raise util.Abort(_('similarity must be a number'))
4193 if sim < 0 or sim > 100:
4193 if sim < 0 or sim > 100:
4194 raise util.Abort(_('similarity must be between 0 and 100'))
4194 raise util.Abort(_('similarity must be between 0 and 100'))
4195 if sim and not update:
4195 if sim and not update:
4196 raise util.Abort(_('cannot use --similarity with --bypass'))
4196 raise util.Abort(_('cannot use --similarity with --bypass'))
4197 if opts.get('exact') and opts.get('edit'):
4197 if opts.get('exact') and opts.get('edit'):
4198 raise util.Abort(_('cannot use --exact with --edit'))
4198 raise util.Abort(_('cannot use --exact with --edit'))
4199 if opts.get('exact') and opts.get('prefix'):
4199 if opts.get('exact') and opts.get('prefix'):
4200 raise util.Abort(_('cannot use --exact with --prefix'))
4200 raise util.Abort(_('cannot use --exact with --prefix'))
4201
4201
4202 if update:
4202 if update:
4203 cmdutil.checkunfinished(repo)
4203 cmdutil.checkunfinished(repo)
4204 if (opts.get('exact') or not opts.get('force')) and update:
4204 if (opts.get('exact') or not opts.get('force')) and update:
4205 cmdutil.bailifchanged(repo)
4205 cmdutil.bailifchanged(repo)
4206
4206
4207 base = opts["base"]
4207 base = opts["base"]
4208 wlock = lock = tr = None
4208 wlock = lock = tr = None
4209 msgs = []
4209 msgs = []
4210 ret = 0
4210 ret = 0
4211
4211
4212
4212
4213 try:
4213 try:
4214 try:
4214 try:
4215 wlock = repo.wlock()
4215 wlock = repo.wlock()
4216 repo.dirstate.beginparentchange()
4216 repo.dirstate.beginparentchange()
4217 if not opts.get('no_commit'):
4217 if not opts.get('no_commit'):
4218 lock = repo.lock()
4218 lock = repo.lock()
4219 tr = repo.transaction('import')
4219 tr = repo.transaction('import')
4220 parents = repo.parents()
4220 parents = repo.parents()
4221 for patchurl in patches:
4221 for patchurl in patches:
4222 if patchurl == '-':
4222 if patchurl == '-':
4223 ui.status(_('applying patch from stdin\n'))
4223 ui.status(_('applying patch from stdin\n'))
4224 patchfile = ui.fin
4224 patchfile = ui.fin
4225 patchurl = 'stdin' # for error message
4225 patchurl = 'stdin' # for error message
4226 else:
4226 else:
4227 patchurl = os.path.join(base, patchurl)
4227 patchurl = os.path.join(base, patchurl)
4228 ui.status(_('applying %s\n') % patchurl)
4228 ui.status(_('applying %s\n') % patchurl)
4229 patchfile = hg.openpath(ui, patchurl)
4229 patchfile = hg.openpath(ui, patchurl)
4230
4230
4231 haspatch = False
4231 haspatch = False
4232 for hunk in patch.split(patchfile):
4232 for hunk in patch.split(patchfile):
4233 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4233 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4234 parents, opts,
4234 parents, opts,
4235 msgs, hg.clean)
4235 msgs, hg.clean)
4236 if msg:
4236 if msg:
4237 haspatch = True
4237 haspatch = True
4238 ui.note(msg + '\n')
4238 ui.note(msg + '\n')
4239 if update or opts.get('exact'):
4239 if update or opts.get('exact'):
4240 parents = repo.parents()
4240 parents = repo.parents()
4241 else:
4241 else:
4242 parents = [repo[node]]
4242 parents = [repo[node]]
4243 if rej:
4243 if rej:
4244 ui.write_err(_("patch applied partially\n"))
4244 ui.write_err(_("patch applied partially\n"))
4245 ui.write_err(_("(fix the .rej files and run "
4245 ui.write_err(_("(fix the .rej files and run "
4246 "`hg commit --amend`)\n"))
4246 "`hg commit --amend`)\n"))
4247 ret = 1
4247 ret = 1
4248 break
4248 break
4249
4249
4250 if not haspatch:
4250 if not haspatch:
4251 raise util.Abort(_('%s: no diffs found') % patchurl)
4251 raise util.Abort(_('%s: no diffs found') % patchurl)
4252
4252
4253 if tr:
4253 if tr:
4254 tr.close()
4254 tr.close()
4255 if msgs:
4255 if msgs:
4256 repo.savecommitmessage('\n* * *\n'.join(msgs))
4256 repo.savecommitmessage('\n* * *\n'.join(msgs))
4257 repo.dirstate.endparentchange()
4257 repo.dirstate.endparentchange()
4258 return ret
4258 return ret
4259 except: # re-raises
4259 except: # re-raises
4260 # wlock.release() indirectly calls dirstate.write(): since
4260 # wlock.release() indirectly calls dirstate.write(): since
4261 # we're crashing, we do not want to change the working dir
4261 # we're crashing, we do not want to change the working dir
4262 # parent after all, so make sure it writes nothing
4262 # parent after all, so make sure it writes nothing
4263 repo.dirstate.invalidate()
4263 repo.dirstate.invalidate()
4264 raise
4264 raise
4265 finally:
4265 finally:
4266 if tr:
4266 if tr:
4267 tr.release()
4267 tr.release()
4268 release(lock, wlock)
4268 release(lock, wlock)
4269
4269
4270 @command('incoming|in',
4270 @command('incoming|in',
4271 [('f', 'force', None,
4271 [('f', 'force', None,
4272 _('run even if remote repository is unrelated')),
4272 _('run even if remote repository is unrelated')),
4273 ('n', 'newest-first', None, _('show newest record first')),
4273 ('n', 'newest-first', None, _('show newest record first')),
4274 ('', 'bundle', '',
4274 ('', 'bundle', '',
4275 _('file to store the bundles into'), _('FILE')),
4275 _('file to store the bundles into'), _('FILE')),
4276 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4276 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4277 ('B', 'bookmarks', False, _("compare bookmarks")),
4277 ('B', 'bookmarks', False, _("compare bookmarks")),
4278 ('b', 'branch', [],
4278 ('b', 'branch', [],
4279 _('a specific branch you would like to pull'), _('BRANCH')),
4279 _('a specific branch you would like to pull'), _('BRANCH')),
4280 ] + logopts + remoteopts + subrepoopts,
4280 ] + logopts + remoteopts + subrepoopts,
4281 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4281 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4282 def incoming(ui, repo, source="default", **opts):
4282 def incoming(ui, repo, source="default", **opts):
4283 """show new changesets found in source
4283 """show new changesets found in source
4284
4284
4285 Show new changesets found in the specified path/URL or the default
4285 Show new changesets found in the specified path/URL or the default
4286 pull location. These are the changesets that would have been pulled
4286 pull location. These are the changesets that would have been pulled
4287 if a pull at the time you issued this command.
4287 if a pull at the time you issued this command.
4288
4288
4289 See pull for valid source format details.
4289 See pull for valid source format details.
4290
4290
4291 .. container:: verbose
4291 .. container:: verbose
4292
4292
4293 For remote repository, using --bundle avoids downloading the
4293 For remote repository, using --bundle avoids downloading the
4294 changesets twice if the incoming is followed by a pull.
4294 changesets twice if the incoming is followed by a pull.
4295
4295
4296 Examples:
4296 Examples:
4297
4297
4298 - show incoming changes with patches and full description::
4298 - show incoming changes with patches and full description::
4299
4299
4300 hg incoming -vp
4300 hg incoming -vp
4301
4301
4302 - show incoming changes excluding merges, store a bundle::
4302 - show incoming changes excluding merges, store a bundle::
4303
4303
4304 hg in -vpM --bundle incoming.hg
4304 hg in -vpM --bundle incoming.hg
4305 hg pull incoming.hg
4305 hg pull incoming.hg
4306
4306
4307 - briefly list changes inside a bundle::
4307 - briefly list changes inside a bundle::
4308
4308
4309 hg in changes.hg -T "{desc|firstline}\\n"
4309 hg in changes.hg -T "{desc|firstline}\\n"
4310
4310
4311 Returns 0 if there are incoming changes, 1 otherwise.
4311 Returns 0 if there are incoming changes, 1 otherwise.
4312 """
4312 """
4313 if opts.get('graph'):
4313 if opts.get('graph'):
4314 cmdutil.checkunsupportedgraphflags([], opts)
4314 cmdutil.checkunsupportedgraphflags([], opts)
4315 def display(other, chlist, displayer):
4315 def display(other, chlist, displayer):
4316 revdag = cmdutil.graphrevs(other, chlist, opts)
4316 revdag = cmdutil.graphrevs(other, chlist, opts)
4317 showparents = [ctx.node() for ctx in repo[None].parents()]
4317 showparents = [ctx.node() for ctx in repo[None].parents()]
4318 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4318 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4319 graphmod.asciiedges)
4319 graphmod.asciiedges)
4320
4320
4321 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4321 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4322 return 0
4322 return 0
4323
4323
4324 if opts.get('bundle') and opts.get('subrepos'):
4324 if opts.get('bundle') and opts.get('subrepos'):
4325 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4325 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4326
4326
4327 if opts.get('bookmarks'):
4327 if opts.get('bookmarks'):
4328 source, branches = hg.parseurl(ui.expandpath(source),
4328 source, branches = hg.parseurl(ui.expandpath(source),
4329 opts.get('branch'))
4329 opts.get('branch'))
4330 other = hg.peer(repo, opts, source)
4330 other = hg.peer(repo, opts, source)
4331 if 'bookmarks' not in other.listkeys('namespaces'):
4331 if 'bookmarks' not in other.listkeys('namespaces'):
4332 ui.warn(_("remote doesn't support bookmarks\n"))
4332 ui.warn(_("remote doesn't support bookmarks\n"))
4333 return 0
4333 return 0
4334 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4334 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4335 return bookmarks.incoming(ui, repo, other)
4335 return bookmarks.incoming(ui, repo, other)
4336
4336
4337 repo._subtoppath = ui.expandpath(source)
4337 repo._subtoppath = ui.expandpath(source)
4338 try:
4338 try:
4339 return hg.incoming(ui, repo, source, opts)
4339 return hg.incoming(ui, repo, source, opts)
4340 finally:
4340 finally:
4341 del repo._subtoppath
4341 del repo._subtoppath
4342
4342
4343
4343
4344 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4344 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4345 norepo=True)
4345 norepo=True)
4346 def init(ui, dest=".", **opts):
4346 def init(ui, dest=".", **opts):
4347 """create a new repository in the given directory
4347 """create a new repository in the given directory
4348
4348
4349 Initialize a new repository in the given directory. If the given
4349 Initialize a new repository in the given directory. If the given
4350 directory does not exist, it will be created.
4350 directory does not exist, it will be created.
4351
4351
4352 If no directory is given, the current directory is used.
4352 If no directory is given, the current directory is used.
4353
4353
4354 It is possible to specify an ``ssh://`` URL as the destination.
4354 It is possible to specify an ``ssh://`` URL as the destination.
4355 See :hg:`help urls` for more information.
4355 See :hg:`help urls` for more information.
4356
4356
4357 Returns 0 on success.
4357 Returns 0 on success.
4358 """
4358 """
4359 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4359 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4360
4360
4361 @command('locate',
4361 @command('locate',
4362 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4362 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4363 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4363 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4364 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4364 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4365 ] + walkopts,
4365 ] + walkopts,
4366 _('[OPTION]... [PATTERN]...'))
4366 _('[OPTION]... [PATTERN]...'))
4367 def locate(ui, repo, *pats, **opts):
4367 def locate(ui, repo, *pats, **opts):
4368 """locate files matching specific patterns (DEPRECATED)
4368 """locate files matching specific patterns (DEPRECATED)
4369
4369
4370 Print files under Mercurial control in the working directory whose
4370 Print files under Mercurial control in the working directory whose
4371 names match the given patterns.
4371 names match the given patterns.
4372
4372
4373 By default, this command searches all directories in the working
4373 By default, this command searches all directories in the working
4374 directory. To search just the current directory and its
4374 directory. To search just the current directory and its
4375 subdirectories, use "--include .".
4375 subdirectories, use "--include .".
4376
4376
4377 If no patterns are given to match, this command prints the names
4377 If no patterns are given to match, this command prints the names
4378 of all files under Mercurial control in the working directory.
4378 of all files under Mercurial control in the working directory.
4379
4379
4380 If you want to feed the output of this command into the "xargs"
4380 If you want to feed the output of this command into the "xargs"
4381 command, use the -0 option to both this command and "xargs". This
4381 command, use the -0 option to both this command and "xargs". This
4382 will avoid the problem of "xargs" treating single filenames that
4382 will avoid the problem of "xargs" treating single filenames that
4383 contain whitespace as multiple filenames.
4383 contain whitespace as multiple filenames.
4384
4384
4385 See :hg:`help files` for a more versatile command.
4385 See :hg:`help files` for a more versatile command.
4386
4386
4387 Returns 0 if a match is found, 1 otherwise.
4387 Returns 0 if a match is found, 1 otherwise.
4388 """
4388 """
4389 if opts.get('print0'):
4389 if opts.get('print0'):
4390 end = '\0'
4390 end = '\0'
4391 else:
4391 else:
4392 end = '\n'
4392 end = '\n'
4393 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4393 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4394
4394
4395 ret = 1
4395 ret = 1
4396 ctx = repo[rev]
4396 ctx = repo[rev]
4397 m = scmutil.match(ctx, pats, opts, default='relglob')
4397 m = scmutil.match(ctx, pats, opts, default='relglob')
4398 m.bad = lambda x, y: False
4398 m.bad = lambda x, y: False
4399
4399
4400 for abs in ctx.matches(m):
4400 for abs in ctx.matches(m):
4401 if opts.get('fullpath'):
4401 if opts.get('fullpath'):
4402 ui.write(repo.wjoin(abs), end)
4402 ui.write(repo.wjoin(abs), end)
4403 else:
4403 else:
4404 ui.write(((pats and m.rel(abs)) or abs), end)
4404 ui.write(((pats and m.rel(abs)) or abs), end)
4405 ret = 0
4405 ret = 0
4406
4406
4407 return ret
4407 return ret
4408
4408
4409 @command('^log|history',
4409 @command('^log|history',
4410 [('f', 'follow', None,
4410 [('f', 'follow', None,
4411 _('follow changeset history, or file history across copies and renames')),
4411 _('follow changeset history, or file history across copies and renames')),
4412 ('', 'follow-first', None,
4412 ('', 'follow-first', None,
4413 _('only follow the first parent of merge changesets (DEPRECATED)')),
4413 _('only follow the first parent of merge changesets (DEPRECATED)')),
4414 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4414 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4415 ('C', 'copies', None, _('show copied files')),
4415 ('C', 'copies', None, _('show copied files')),
4416 ('k', 'keyword', [],
4416 ('k', 'keyword', [],
4417 _('do case-insensitive search for a given text'), _('TEXT')),
4417 _('do case-insensitive search for a given text'), _('TEXT')),
4418 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4418 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4419 ('', 'removed', None, _('include revisions where files were removed')),
4419 ('', 'removed', None, _('include revisions where files were removed')),
4420 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4420 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4421 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4421 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4422 ('', 'only-branch', [],
4422 ('', 'only-branch', [],
4423 _('show only changesets within the given named branch (DEPRECATED)'),
4423 _('show only changesets within the given named branch (DEPRECATED)'),
4424 _('BRANCH')),
4424 _('BRANCH')),
4425 ('b', 'branch', [],
4425 ('b', 'branch', [],
4426 _('show changesets within the given named branch'), _('BRANCH')),
4426 _('show changesets within the given named branch'), _('BRANCH')),
4427 ('P', 'prune', [],
4427 ('P', 'prune', [],
4428 _('do not display revision or any of its ancestors'), _('REV')),
4428 _('do not display revision or any of its ancestors'), _('REV')),
4429 ] + logopts + walkopts,
4429 ] + logopts + walkopts,
4430 _('[OPTION]... [FILE]'),
4430 _('[OPTION]... [FILE]'),
4431 inferrepo=True)
4431 inferrepo=True)
4432 def log(ui, repo, *pats, **opts):
4432 def log(ui, repo, *pats, **opts):
4433 """show revision history of entire repository or files
4433 """show revision history of entire repository or files
4434
4434
4435 Print the revision history of the specified files or the entire
4435 Print the revision history of the specified files or the entire
4436 project.
4436 project.
4437
4437
4438 If no revision range is specified, the default is ``tip:0`` unless
4438 If no revision range is specified, the default is ``tip:0`` unless
4439 --follow is set, in which case the working directory parent is
4439 --follow is set, in which case the working directory parent is
4440 used as the starting revision.
4440 used as the starting revision.
4441
4441
4442 File history is shown without following rename or copy history of
4442 File history is shown without following rename or copy history of
4443 files. Use -f/--follow with a filename to follow history across
4443 files. Use -f/--follow with a filename to follow history across
4444 renames and copies. --follow without a filename will only show
4444 renames and copies. --follow without a filename will only show
4445 ancestors or descendants of the starting revision.
4445 ancestors or descendants of the starting revision.
4446
4446
4447 By default this command prints revision number and changeset id,
4447 By default this command prints revision number and changeset id,
4448 tags, non-trivial parents, user, date and time, and a summary for
4448 tags, non-trivial parents, user, date and time, and a summary for
4449 each commit. When the -v/--verbose switch is used, the list of
4449 each commit. When the -v/--verbose switch is used, the list of
4450 changed files and full commit message are shown.
4450 changed files and full commit message are shown.
4451
4451
4452 With --graph the revisions are shown as an ASCII art DAG with the most
4452 With --graph the revisions are shown as an ASCII art DAG with the most
4453 recent changeset at the top.
4453 recent changeset at the top.
4454 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4454 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4455 and '+' represents a fork where the changeset from the lines below is a
4455 and '+' represents a fork where the changeset from the lines below is a
4456 parent of the 'o' merge on the same line.
4456 parent of the 'o' merge on the same line.
4457
4457
4458 .. note::
4458 .. note::
4459
4459
4460 log -p/--patch may generate unexpected diff output for merge
4460 log -p/--patch may generate unexpected diff output for merge
4461 changesets, as it will only compare the merge changeset against
4461 changesets, as it will only compare the merge changeset against
4462 its first parent. Also, only files different from BOTH parents
4462 its first parent. Also, only files different from BOTH parents
4463 will appear in files:.
4463 will appear in files:.
4464
4464
4465 .. note::
4465 .. note::
4466
4466
4467 for performance reasons, log FILE may omit duplicate changes
4467 for performance reasons, log FILE may omit duplicate changes
4468 made on branches and will not show removals or mode changes. To
4468 made on branches and will not show removals or mode changes. To
4469 see all such changes, use the --removed switch.
4469 see all such changes, use the --removed switch.
4470
4470
4471 .. container:: verbose
4471 .. container:: verbose
4472
4472
4473 Some examples:
4473 Some examples:
4474
4474
4475 - changesets with full descriptions and file lists::
4475 - changesets with full descriptions and file lists::
4476
4476
4477 hg log -v
4477 hg log -v
4478
4478
4479 - changesets ancestral to the working directory::
4479 - changesets ancestral to the working directory::
4480
4480
4481 hg log -f
4481 hg log -f
4482
4482
4483 - last 10 commits on the current branch::
4483 - last 10 commits on the current branch::
4484
4484
4485 hg log -l 10 -b .
4485 hg log -l 10 -b .
4486
4486
4487 - changesets showing all modifications of a file, including removals::
4487 - changesets showing all modifications of a file, including removals::
4488
4488
4489 hg log --removed file.c
4489 hg log --removed file.c
4490
4490
4491 - all changesets that touch a directory, with diffs, excluding merges::
4491 - all changesets that touch a directory, with diffs, excluding merges::
4492
4492
4493 hg log -Mp lib/
4493 hg log -Mp lib/
4494
4494
4495 - all revision numbers that match a keyword::
4495 - all revision numbers that match a keyword::
4496
4496
4497 hg log -k bug --template "{rev}\\n"
4497 hg log -k bug --template "{rev}\\n"
4498
4498
4499 - list available log templates::
4499 - list available log templates::
4500
4500
4501 hg log -T list
4501 hg log -T list
4502
4502
4503 - check if a given changeset is included in a tagged release::
4503 - check if a given changeset is included in a tagged release::
4504
4504
4505 hg log -r "a21ccf and ancestor(1.9)"
4505 hg log -r "a21ccf and ancestor(1.9)"
4506
4506
4507 - find all changesets by some user in a date range::
4507 - find all changesets by some user in a date range::
4508
4508
4509 hg log -k alice -d "may 2008 to jul 2008"
4509 hg log -k alice -d "may 2008 to jul 2008"
4510
4510
4511 - summary of all changesets after the last tag::
4511 - summary of all changesets after the last tag::
4512
4512
4513 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4513 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4514
4514
4515 See :hg:`help dates` for a list of formats valid for -d/--date.
4515 See :hg:`help dates` for a list of formats valid for -d/--date.
4516
4516
4517 See :hg:`help revisions` and :hg:`help revsets` for more about
4517 See :hg:`help revisions` and :hg:`help revsets` for more about
4518 specifying revisions.
4518 specifying revisions.
4519
4519
4520 See :hg:`help templates` for more about pre-packaged styles and
4520 See :hg:`help templates` for more about pre-packaged styles and
4521 specifying custom templates.
4521 specifying custom templates.
4522
4522
4523 Returns 0 on success.
4523 Returns 0 on success.
4524
4524
4525 """
4525 """
4526 if opts.get('follow') and opts.get('rev'):
4526 if opts.get('follow') and opts.get('rev'):
4527 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4527 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4528 del opts['follow']
4528 del opts['follow']
4529
4529
4530 if opts.get('graph'):
4530 if opts.get('graph'):
4531 return cmdutil.graphlog(ui, repo, *pats, **opts)
4531 return cmdutil.graphlog(ui, repo, *pats, **opts)
4532
4532
4533 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4533 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4534 limit = cmdutil.loglimit(opts)
4534 limit = cmdutil.loglimit(opts)
4535 count = 0
4535 count = 0
4536
4536
4537 getrenamed = None
4537 getrenamed = None
4538 if opts.get('copies'):
4538 if opts.get('copies'):
4539 endrev = None
4539 endrev = None
4540 if opts.get('rev'):
4540 if opts.get('rev'):
4541 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4541 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4542 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4542 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4543
4543
4544 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4544 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4545 for rev in revs:
4545 for rev in revs:
4546 if count == limit:
4546 if count == limit:
4547 break
4547 break
4548 ctx = repo[rev]
4548 ctx = repo[rev]
4549 copies = None
4549 copies = None
4550 if getrenamed is not None and rev:
4550 if getrenamed is not None and rev:
4551 copies = []
4551 copies = []
4552 for fn in ctx.files():
4552 for fn in ctx.files():
4553 rename = getrenamed(fn, rev)
4553 rename = getrenamed(fn, rev)
4554 if rename:
4554 if rename:
4555 copies.append((fn, rename[0]))
4555 copies.append((fn, rename[0]))
4556 if filematcher:
4556 if filematcher:
4557 revmatchfn = filematcher(ctx.rev())
4557 revmatchfn = filematcher(ctx.rev())
4558 else:
4558 else:
4559 revmatchfn = None
4559 revmatchfn = None
4560 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4560 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4561 if displayer.flush(rev):
4561 if displayer.flush(rev):
4562 count += 1
4562 count += 1
4563
4563
4564 displayer.close()
4564 displayer.close()
4565
4565
4566 @command('manifest',
4566 @command('manifest',
4567 [('r', 'rev', '', _('revision to display'), _('REV')),
4567 [('r', 'rev', '', _('revision to display'), _('REV')),
4568 ('', 'all', False, _("list files from all revisions"))]
4568 ('', 'all', False, _("list files from all revisions"))]
4569 + formatteropts,
4569 + formatteropts,
4570 _('[-r REV]'))
4570 _('[-r REV]'))
4571 def manifest(ui, repo, node=None, rev=None, **opts):
4571 def manifest(ui, repo, node=None, rev=None, **opts):
4572 """output the current or given revision of the project manifest
4572 """output the current or given revision of the project manifest
4573
4573
4574 Print a list of version controlled files for the given revision.
4574 Print a list of version controlled files for the given revision.
4575 If no revision is given, the first parent of the working directory
4575 If no revision is given, the first parent of the working directory
4576 is used, or the null revision if no revision is checked out.
4576 is used, or the null revision if no revision is checked out.
4577
4577
4578 With -v, print file permissions, symlink and executable bits.
4578 With -v, print file permissions, symlink and executable bits.
4579 With --debug, print file revision hashes.
4579 With --debug, print file revision hashes.
4580
4580
4581 If option --all is specified, the list of all files from all revisions
4581 If option --all is specified, the list of all files from all revisions
4582 is printed. This includes deleted and renamed files.
4582 is printed. This includes deleted and renamed files.
4583
4583
4584 Returns 0 on success.
4584 Returns 0 on success.
4585 """
4585 """
4586
4586
4587 fm = ui.formatter('manifest', opts)
4587 fm = ui.formatter('manifest', opts)
4588
4588
4589 if opts.get('all'):
4589 if opts.get('all'):
4590 if rev or node:
4590 if rev or node:
4591 raise util.Abort(_("can't specify a revision with --all"))
4591 raise util.Abort(_("can't specify a revision with --all"))
4592
4592
4593 res = []
4593 res = []
4594 prefix = "data/"
4594 prefix = "data/"
4595 suffix = ".i"
4595 suffix = ".i"
4596 plen = len(prefix)
4596 plen = len(prefix)
4597 slen = len(suffix)
4597 slen = len(suffix)
4598 lock = repo.lock()
4598 lock = repo.lock()
4599 try:
4599 try:
4600 for fn, b, size in repo.store.datafiles():
4600 for fn, b, size in repo.store.datafiles():
4601 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4601 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4602 res.append(fn[plen:-slen])
4602 res.append(fn[plen:-slen])
4603 finally:
4603 finally:
4604 lock.release()
4604 lock.release()
4605 for f in res:
4605 for f in res:
4606 fm.startitem()
4606 fm.startitem()
4607 fm.write("path", '%s\n', f)
4607 fm.write("path", '%s\n', f)
4608 fm.end()
4608 fm.end()
4609 return
4609 return
4610
4610
4611 if rev and node:
4611 if rev and node:
4612 raise util.Abort(_("please specify just one revision"))
4612 raise util.Abort(_("please specify just one revision"))
4613
4613
4614 if not node:
4614 if not node:
4615 node = rev
4615 node = rev
4616
4616
4617 char = {'l': '@', 'x': '*', '': ''}
4617 char = {'l': '@', 'x': '*', '': ''}
4618 mode = {'l': '644', 'x': '755', '': '644'}
4618 mode = {'l': '644', 'x': '755', '': '644'}
4619 ctx = scmutil.revsingle(repo, node)
4619 ctx = scmutil.revsingle(repo, node)
4620 mf = ctx.manifest()
4620 mf = ctx.manifest()
4621 for f in ctx:
4621 for f in ctx:
4622 fm.startitem()
4622 fm.startitem()
4623 fl = ctx[f].flags()
4623 fl = ctx[f].flags()
4624 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4624 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4625 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4625 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4626 fm.write('path', '%s\n', f)
4626 fm.write('path', '%s\n', f)
4627 fm.end()
4627 fm.end()
4628
4628
4629 @command('^merge',
4629 @command('^merge',
4630 [('f', 'force', None,
4630 [('f', 'force', None,
4631 _('force a merge including outstanding changes (DEPRECATED)')),
4631 _('force a merge including outstanding changes (DEPRECATED)')),
4632 ('r', 'rev', '', _('revision to merge'), _('REV')),
4632 ('r', 'rev', '', _('revision to merge'), _('REV')),
4633 ('P', 'preview', None,
4633 ('P', 'preview', None,
4634 _('review revisions to merge (no merge is performed)'))
4634 _('review revisions to merge (no merge is performed)'))
4635 ] + mergetoolopts,
4635 ] + mergetoolopts,
4636 _('[-P] [-f] [[-r] REV]'))
4636 _('[-P] [-f] [[-r] REV]'))
4637 def merge(ui, repo, node=None, **opts):
4637 def merge(ui, repo, node=None, **opts):
4638 """merge another revision into working directory
4638 """merge another revision into working directory
4639
4639
4640 The current working directory is updated with all changes made in
4640 The current working directory is updated with all changes made in
4641 the requested revision since the last common predecessor revision.
4641 the requested revision since the last common predecessor revision.
4642
4642
4643 Files that changed between either parent are marked as changed for
4643 Files that changed between either parent are marked as changed for
4644 the next commit and a commit must be performed before any further
4644 the next commit and a commit must be performed before any further
4645 updates to the repository are allowed. The next commit will have
4645 updates to the repository are allowed. The next commit will have
4646 two parents.
4646 two parents.
4647
4647
4648 ``--tool`` can be used to specify the merge tool used for file
4648 ``--tool`` can be used to specify the merge tool used for file
4649 merges. It overrides the HGMERGE environment variable and your
4649 merges. It overrides the HGMERGE environment variable and your
4650 configuration files. See :hg:`help merge-tools` for options.
4650 configuration files. See :hg:`help merge-tools` for options.
4651
4651
4652 If no revision is specified, the working directory's parent is a
4652 If no revision is specified, the working directory's parent is a
4653 head revision, and the current branch contains exactly one other
4653 head revision, and the current branch contains exactly one other
4654 head, the other head is merged with by default. Otherwise, an
4654 head, the other head is merged with by default. Otherwise, an
4655 explicit revision with which to merge with must be provided.
4655 explicit revision with which to merge with must be provided.
4656
4656
4657 :hg:`resolve` must be used to resolve unresolved files.
4657 :hg:`resolve` must be used to resolve unresolved files.
4658
4658
4659 To undo an uncommitted merge, use :hg:`update --clean .` which
4659 To undo an uncommitted merge, use :hg:`update --clean .` which
4660 will check out a clean copy of the original merge parent, losing
4660 will check out a clean copy of the original merge parent, losing
4661 all changes.
4661 all changes.
4662
4662
4663 Returns 0 on success, 1 if there are unresolved files.
4663 Returns 0 on success, 1 if there are unresolved files.
4664 """
4664 """
4665
4665
4666 if opts.get('rev') and node:
4666 if opts.get('rev') and node:
4667 raise util.Abort(_("please specify just one revision"))
4667 raise util.Abort(_("please specify just one revision"))
4668 if not node:
4668 if not node:
4669 node = opts.get('rev')
4669 node = opts.get('rev')
4670
4670
4671 if node:
4671 if node:
4672 node = scmutil.revsingle(repo, node).node()
4672 node = scmutil.revsingle(repo, node).node()
4673
4673
4674 if not node and repo._bookmarkcurrent:
4674 if not node and repo._bookmarkcurrent:
4675 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4675 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4676 curhead = repo[repo._bookmarkcurrent].node()
4676 curhead = repo[repo._bookmarkcurrent].node()
4677 if len(bmheads) == 2:
4677 if len(bmheads) == 2:
4678 if curhead == bmheads[0]:
4678 if curhead == bmheads[0]:
4679 node = bmheads[1]
4679 node = bmheads[1]
4680 else:
4680 else:
4681 node = bmheads[0]
4681 node = bmheads[0]
4682 elif len(bmheads) > 2:
4682 elif len(bmheads) > 2:
4683 raise util.Abort(_("multiple matching bookmarks to merge - "
4683 raise util.Abort(_("multiple matching bookmarks to merge - "
4684 "please merge with an explicit rev or bookmark"),
4684 "please merge with an explicit rev or bookmark"),
4685 hint=_("run 'hg heads' to see all heads"))
4685 hint=_("run 'hg heads' to see all heads"))
4686 elif len(bmheads) <= 1:
4686 elif len(bmheads) <= 1:
4687 raise util.Abort(_("no matching bookmark to merge - "
4687 raise util.Abort(_("no matching bookmark to merge - "
4688 "please merge with an explicit rev or bookmark"),
4688 "please merge with an explicit rev or bookmark"),
4689 hint=_("run 'hg heads' to see all heads"))
4689 hint=_("run 'hg heads' to see all heads"))
4690
4690
4691 if not node and not repo._bookmarkcurrent:
4691 if not node and not repo._bookmarkcurrent:
4692 branch = repo[None].branch()
4692 branch = repo[None].branch()
4693 bheads = repo.branchheads(branch)
4693 bheads = repo.branchheads(branch)
4694 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4694 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4695
4695
4696 if len(nbhs) > 2:
4696 if len(nbhs) > 2:
4697 raise util.Abort(_("branch '%s' has %d heads - "
4697 raise util.Abort(_("branch '%s' has %d heads - "
4698 "please merge with an explicit rev")
4698 "please merge with an explicit rev")
4699 % (branch, len(bheads)),
4699 % (branch, len(bheads)),
4700 hint=_("run 'hg heads .' to see heads"))
4700 hint=_("run 'hg heads .' to see heads"))
4701
4701
4702 parent = repo.dirstate.p1()
4702 parent = repo.dirstate.p1()
4703 if len(nbhs) <= 1:
4703 if len(nbhs) <= 1:
4704 if len(bheads) > 1:
4704 if len(bheads) > 1:
4705 raise util.Abort(_("heads are bookmarked - "
4705 raise util.Abort(_("heads are bookmarked - "
4706 "please merge with an explicit rev"),
4706 "please merge with an explicit rev"),
4707 hint=_("run 'hg heads' to see all heads"))
4707 hint=_("run 'hg heads' to see all heads"))
4708 if len(repo.heads()) > 1:
4708 if len(repo.heads()) > 1:
4709 raise util.Abort(_("branch '%s' has one head - "
4709 raise util.Abort(_("branch '%s' has one head - "
4710 "please merge with an explicit rev")
4710 "please merge with an explicit rev")
4711 % branch,
4711 % branch,
4712 hint=_("run 'hg heads' to see all heads"))
4712 hint=_("run 'hg heads' to see all heads"))
4713 msg, hint = _('nothing to merge'), None
4713 msg, hint = _('nothing to merge'), None
4714 if parent != repo.lookup(branch):
4714 if parent != repo.lookup(branch):
4715 hint = _("use 'hg update' instead")
4715 hint = _("use 'hg update' instead")
4716 raise util.Abort(msg, hint=hint)
4716 raise util.Abort(msg, hint=hint)
4717
4717
4718 if parent not in bheads:
4718 if parent not in bheads:
4719 raise util.Abort(_('working directory not at a head revision'),
4719 raise util.Abort(_('working directory not at a head revision'),
4720 hint=_("use 'hg update' or merge with an "
4720 hint=_("use 'hg update' or merge with an "
4721 "explicit revision"))
4721 "explicit revision"))
4722 if parent == nbhs[0]:
4722 if parent == nbhs[0]:
4723 node = nbhs[-1]
4723 node = nbhs[-1]
4724 else:
4724 else:
4725 node = nbhs[0]
4725 node = nbhs[0]
4726
4726
4727 if opts.get('preview'):
4727 if opts.get('preview'):
4728 # find nodes that are ancestors of p2 but not of p1
4728 # find nodes that are ancestors of p2 but not of p1
4729 p1 = repo.lookup('.')
4729 p1 = repo.lookup('.')
4730 p2 = repo.lookup(node)
4730 p2 = repo.lookup(node)
4731 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4731 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4732
4732
4733 displayer = cmdutil.show_changeset(ui, repo, opts)
4733 displayer = cmdutil.show_changeset(ui, repo, opts)
4734 for node in nodes:
4734 for node in nodes:
4735 displayer.show(repo[node])
4735 displayer.show(repo[node])
4736 displayer.close()
4736 displayer.close()
4737 return 0
4737 return 0
4738
4738
4739 try:
4739 try:
4740 # ui.forcemerge is an internal variable, do not document
4740 # ui.forcemerge is an internal variable, do not document
4741 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4741 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4742 return hg.merge(repo, node, force=opts.get('force'))
4742 return hg.merge(repo, node, force=opts.get('force'))
4743 finally:
4743 finally:
4744 ui.setconfig('ui', 'forcemerge', '', 'merge')
4744 ui.setconfig('ui', 'forcemerge', '', 'merge')
4745
4745
4746 @command('outgoing|out',
4746 @command('outgoing|out',
4747 [('f', 'force', None, _('run even when the destination is unrelated')),
4747 [('f', 'force', None, _('run even when the destination is unrelated')),
4748 ('r', 'rev', [],
4748 ('r', 'rev', [],
4749 _('a changeset intended to be included in the destination'), _('REV')),
4749 _('a changeset intended to be included in the destination'), _('REV')),
4750 ('n', 'newest-first', None, _('show newest record first')),
4750 ('n', 'newest-first', None, _('show newest record first')),
4751 ('B', 'bookmarks', False, _('compare bookmarks')),
4751 ('B', 'bookmarks', False, _('compare bookmarks')),
4752 ('b', 'branch', [], _('a specific branch you would like to push'),
4752 ('b', 'branch', [], _('a specific branch you would like to push'),
4753 _('BRANCH')),
4753 _('BRANCH')),
4754 ] + logopts + remoteopts + subrepoopts,
4754 ] + logopts + remoteopts + subrepoopts,
4755 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4755 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4756 def outgoing(ui, repo, dest=None, **opts):
4756 def outgoing(ui, repo, dest=None, **opts):
4757 """show changesets not found in the destination
4757 """show changesets not found in the destination
4758
4758
4759 Show changesets not found in the specified destination repository
4759 Show changesets not found in the specified destination repository
4760 or the default push location. These are the changesets that would
4760 or the default push location. These are the changesets that would
4761 be pushed if a push was requested.
4761 be pushed if a push was requested.
4762
4762
4763 See pull for details of valid destination formats.
4763 See pull for details of valid destination formats.
4764
4764
4765 Returns 0 if there are outgoing changes, 1 otherwise.
4765 Returns 0 if there are outgoing changes, 1 otherwise.
4766 """
4766 """
4767 if opts.get('graph'):
4767 if opts.get('graph'):
4768 cmdutil.checkunsupportedgraphflags([], opts)
4768 cmdutil.checkunsupportedgraphflags([], opts)
4769 o, other = hg._outgoing(ui, repo, dest, opts)
4769 o, other = hg._outgoing(ui, repo, dest, opts)
4770 if not o:
4770 if not o:
4771 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4771 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4772 return
4772 return
4773
4773
4774 revdag = cmdutil.graphrevs(repo, o, opts)
4774 revdag = cmdutil.graphrevs(repo, o, opts)
4775 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4775 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4776 showparents = [ctx.node() for ctx in repo[None].parents()]
4776 showparents = [ctx.node() for ctx in repo[None].parents()]
4777 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4777 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4778 graphmod.asciiedges)
4778 graphmod.asciiedges)
4779 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4779 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4780 return 0
4780 return 0
4781
4781
4782 if opts.get('bookmarks'):
4782 if opts.get('bookmarks'):
4783 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4783 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4784 dest, branches = hg.parseurl(dest, opts.get('branch'))
4784 dest, branches = hg.parseurl(dest, opts.get('branch'))
4785 other = hg.peer(repo, opts, dest)
4785 other = hg.peer(repo, opts, dest)
4786 if 'bookmarks' not in other.listkeys('namespaces'):
4786 if 'bookmarks' not in other.listkeys('namespaces'):
4787 ui.warn(_("remote doesn't support bookmarks\n"))
4787 ui.warn(_("remote doesn't support bookmarks\n"))
4788 return 0
4788 return 0
4789 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4789 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4790 return bookmarks.outgoing(ui, repo, other)
4790 return bookmarks.outgoing(ui, repo, other)
4791
4791
4792 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4792 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4793 try:
4793 try:
4794 return hg.outgoing(ui, repo, dest, opts)
4794 return hg.outgoing(ui, repo, dest, opts)
4795 finally:
4795 finally:
4796 del repo._subtoppath
4796 del repo._subtoppath
4797
4797
4798 @command('parents',
4798 @command('parents',
4799 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4799 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4800 ] + templateopts,
4800 ] + templateopts,
4801 _('[-r REV] [FILE]'),
4801 _('[-r REV] [FILE]'),
4802 inferrepo=True)
4802 inferrepo=True)
4803 def parents(ui, repo, file_=None, **opts):
4803 def parents(ui, repo, file_=None, **opts):
4804 """show the parents of the working directory or revision (DEPRECATED)
4804 """show the parents of the working directory or revision (DEPRECATED)
4805
4805
4806 Print the working directory's parent revisions. If a revision is
4806 Print the working directory's parent revisions. If a revision is
4807 given via -r/--rev, the parent of that revision will be printed.
4807 given via -r/--rev, the parent of that revision will be printed.
4808 If a file argument is given, the revision in which the file was
4808 If a file argument is given, the revision in which the file was
4809 last changed (before the working directory revision or the
4809 last changed (before the working directory revision or the
4810 argument to --rev if given) is printed.
4810 argument to --rev if given) is printed.
4811
4811
4812 See :hg:`summary` and :hg:`help revsets` for related information.
4812 See :hg:`summary` and :hg:`help revsets` for related information.
4813
4813
4814 Returns 0 on success.
4814 Returns 0 on success.
4815 """
4815 """
4816
4816
4817 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4817 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4818
4818
4819 if file_:
4819 if file_:
4820 m = scmutil.match(ctx, (file_,), opts)
4820 m = scmutil.match(ctx, (file_,), opts)
4821 if m.anypats() or len(m.files()) != 1:
4821 if m.anypats() or len(m.files()) != 1:
4822 raise util.Abort(_('can only specify an explicit filename'))
4822 raise util.Abort(_('can only specify an explicit filename'))
4823 file_ = m.files()[0]
4823 file_ = m.files()[0]
4824 filenodes = []
4824 filenodes = []
4825 for cp in ctx.parents():
4825 for cp in ctx.parents():
4826 if not cp:
4826 if not cp:
4827 continue
4827 continue
4828 try:
4828 try:
4829 filenodes.append(cp.filenode(file_))
4829 filenodes.append(cp.filenode(file_))
4830 except error.LookupError:
4830 except error.LookupError:
4831 pass
4831 pass
4832 if not filenodes:
4832 if not filenodes:
4833 raise util.Abort(_("'%s' not found in manifest!") % file_)
4833 raise util.Abort(_("'%s' not found in manifest!") % file_)
4834 p = []
4834 p = []
4835 for fn in filenodes:
4835 for fn in filenodes:
4836 fctx = repo.filectx(file_, fileid=fn)
4836 fctx = repo.filectx(file_, fileid=fn)
4837 p.append(fctx.node())
4837 p.append(fctx.node())
4838 else:
4838 else:
4839 p = [cp.node() for cp in ctx.parents()]
4839 p = [cp.node() for cp in ctx.parents()]
4840
4840
4841 displayer = cmdutil.show_changeset(ui, repo, opts)
4841 displayer = cmdutil.show_changeset(ui, repo, opts)
4842 for n in p:
4842 for n in p:
4843 if n != nullid:
4843 if n != nullid:
4844 displayer.show(repo[n])
4844 displayer.show(repo[n])
4845 displayer.close()
4845 displayer.close()
4846
4846
4847 @command('paths', [], _('[NAME]'), optionalrepo=True)
4847 @command('paths', [], _('[NAME]'), optionalrepo=True)
4848 def paths(ui, repo, search=None):
4848 def paths(ui, repo, search=None):
4849 """show aliases for remote repositories
4849 """show aliases for remote repositories
4850
4850
4851 Show definition of symbolic path name NAME. If no name is given,
4851 Show definition of symbolic path name NAME. If no name is given,
4852 show definition of all available names.
4852 show definition of all available names.
4853
4853
4854 Option -q/--quiet suppresses all output when searching for NAME
4854 Option -q/--quiet suppresses all output when searching for NAME
4855 and shows only the path names when listing all definitions.
4855 and shows only the path names when listing all definitions.
4856
4856
4857 Path names are defined in the [paths] section of your
4857 Path names are defined in the [paths] section of your
4858 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4858 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4859 repository, ``.hg/hgrc`` is used, too.
4859 repository, ``.hg/hgrc`` is used, too.
4860
4860
4861 The path names ``default`` and ``default-push`` have a special
4861 The path names ``default`` and ``default-push`` have a special
4862 meaning. When performing a push or pull operation, they are used
4862 meaning. When performing a push or pull operation, they are used
4863 as fallbacks if no location is specified on the command-line.
4863 as fallbacks if no location is specified on the command-line.
4864 When ``default-push`` is set, it will be used for push and
4864 When ``default-push`` is set, it will be used for push and
4865 ``default`` will be used for pull; otherwise ``default`` is used
4865 ``default`` will be used for pull; otherwise ``default`` is used
4866 as the fallback for both. When cloning a repository, the clone
4866 as the fallback for both. When cloning a repository, the clone
4867 source is written as ``default`` in ``.hg/hgrc``. Note that
4867 source is written as ``default`` in ``.hg/hgrc``. Note that
4868 ``default`` and ``default-push`` apply to all inbound (e.g.
4868 ``default`` and ``default-push`` apply to all inbound (e.g.
4869 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4869 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4870 :hg:`bundle`) operations.
4870 :hg:`bundle`) operations.
4871
4871
4872 See :hg:`help urls` for more information.
4872 See :hg:`help urls` for more information.
4873
4873
4874 Returns 0 on success.
4874 Returns 0 on success.
4875 """
4875 """
4876 if search:
4876 if search:
4877 for name, path in sorted(ui.paths.iteritems()):
4877 for name, path in sorted(ui.paths.iteritems()):
4878 if name == search:
4878 if name == search:
4879 ui.status("%s\n" % util.hidepassword(path.loc))
4879 ui.status("%s\n" % util.hidepassword(path.loc))
4880 return
4880 return
4881 if not ui.quiet:
4881 if not ui.quiet:
4882 ui.warn(_("not found!\n"))
4882 ui.warn(_("not found!\n"))
4883 return 1
4883 return 1
4884 else:
4884 else:
4885 for name, path in sorted(ui.paths.iteritems()):
4885 for name, path in sorted(ui.paths.iteritems()):
4886 if ui.quiet:
4886 if ui.quiet:
4887 ui.write("%s\n" % name)
4887 ui.write("%s\n" % name)
4888 else:
4888 else:
4889 ui.write("%s = %s\n" % (name,
4889 ui.write("%s = %s\n" % (name,
4890 util.hidepassword(path.loc)))
4890 util.hidepassword(path.loc)))
4891
4891
4892 @command('phase',
4892 @command('phase',
4893 [('p', 'public', False, _('set changeset phase to public')),
4893 [('p', 'public', False, _('set changeset phase to public')),
4894 ('d', 'draft', False, _('set changeset phase to draft')),
4894 ('d', 'draft', False, _('set changeset phase to draft')),
4895 ('s', 'secret', False, _('set changeset phase to secret')),
4895 ('s', 'secret', False, _('set changeset phase to secret')),
4896 ('f', 'force', False, _('allow to move boundary backward')),
4896 ('f', 'force', False, _('allow to move boundary backward')),
4897 ('r', 'rev', [], _('target revision'), _('REV')),
4897 ('r', 'rev', [], _('target revision'), _('REV')),
4898 ],
4898 ],
4899 _('[-p|-d|-s] [-f] [-r] REV...'))
4899 _('[-p|-d|-s] [-f] [-r] REV...'))
4900 def phase(ui, repo, *revs, **opts):
4900 def phase(ui, repo, *revs, **opts):
4901 """set or show the current phase name
4901 """set or show the current phase name
4902
4902
4903 With no argument, show the phase name of specified revisions.
4903 With no argument, show the phase name of specified revisions.
4904
4904
4905 With one of -p/--public, -d/--draft or -s/--secret, change the
4905 With one of -p/--public, -d/--draft or -s/--secret, change the
4906 phase value of the specified revisions.
4906 phase value of the specified revisions.
4907
4907
4908 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4908 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4909 lower phase to an higher phase. Phases are ordered as follows::
4909 lower phase to an higher phase. Phases are ordered as follows::
4910
4910
4911 public < draft < secret
4911 public < draft < secret
4912
4912
4913 Returns 0 on success, 1 if no phases were changed or some could not
4913 Returns 0 on success, 1 if no phases were changed or some could not
4914 be changed.
4914 be changed.
4915 """
4915 """
4916 # search for a unique phase argument
4916 # search for a unique phase argument
4917 targetphase = None
4917 targetphase = None
4918 for idx, name in enumerate(phases.phasenames):
4918 for idx, name in enumerate(phases.phasenames):
4919 if opts[name]:
4919 if opts[name]:
4920 if targetphase is not None:
4920 if targetphase is not None:
4921 raise util.Abort(_('only one phase can be specified'))
4921 raise util.Abort(_('only one phase can be specified'))
4922 targetphase = idx
4922 targetphase = idx
4923
4923
4924 # look for specified revision
4924 # look for specified revision
4925 revs = list(revs)
4925 revs = list(revs)
4926 revs.extend(opts['rev'])
4926 revs.extend(opts['rev'])
4927 if not revs:
4927 if not revs:
4928 raise util.Abort(_('no revisions specified'))
4928 raise util.Abort(_('no revisions specified'))
4929
4929
4930 revs = scmutil.revrange(repo, revs)
4930 revs = scmutil.revrange(repo, revs)
4931
4931
4932 lock = None
4932 lock = None
4933 ret = 0
4933 ret = 0
4934 if targetphase is None:
4934 if targetphase is None:
4935 # display
4935 # display
4936 for r in revs:
4936 for r in revs:
4937 ctx = repo[r]
4937 ctx = repo[r]
4938 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4938 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4939 else:
4939 else:
4940 tr = None
4940 tr = None
4941 lock = repo.lock()
4941 lock = repo.lock()
4942 try:
4942 try:
4943 tr = repo.transaction("phase")
4943 tr = repo.transaction("phase")
4944 # set phase
4944 # set phase
4945 if not revs:
4945 if not revs:
4946 raise util.Abort(_('empty revision set'))
4946 raise util.Abort(_('empty revision set'))
4947 nodes = [repo[r].node() for r in revs]
4947 nodes = [repo[r].node() for r in revs]
4948 # moving revision from public to draft may hide them
4948 # moving revision from public to draft may hide them
4949 # We have to check result on an unfiltered repository
4949 # We have to check result on an unfiltered repository
4950 unfi = repo.unfiltered()
4950 unfi = repo.unfiltered()
4951 getphase = unfi._phasecache.phase
4951 getphase = unfi._phasecache.phase
4952 olddata = [getphase(unfi, r) for r in unfi]
4952 olddata = [getphase(unfi, r) for r in unfi]
4953 phases.advanceboundary(repo, tr, targetphase, nodes)
4953 phases.advanceboundary(repo, tr, targetphase, nodes)
4954 if opts['force']:
4954 if opts['force']:
4955 phases.retractboundary(repo, tr, targetphase, nodes)
4955 phases.retractboundary(repo, tr, targetphase, nodes)
4956 tr.close()
4956 tr.close()
4957 finally:
4957 finally:
4958 if tr is not None:
4958 if tr is not None:
4959 tr.release()
4959 tr.release()
4960 lock.release()
4960 lock.release()
4961 getphase = unfi._phasecache.phase
4961 getphase = unfi._phasecache.phase
4962 newdata = [getphase(unfi, r) for r in unfi]
4962 newdata = [getphase(unfi, r) for r in unfi]
4963 changes = sum(newdata[r] != olddata[r] for r in unfi)
4963 changes = sum(newdata[r] != olddata[r] for r in unfi)
4964 cl = unfi.changelog
4964 cl = unfi.changelog
4965 rejected = [n for n in nodes
4965 rejected = [n for n in nodes
4966 if newdata[cl.rev(n)] < targetphase]
4966 if newdata[cl.rev(n)] < targetphase]
4967 if rejected:
4967 if rejected:
4968 ui.warn(_('cannot move %i changesets to a higher '
4968 ui.warn(_('cannot move %i changesets to a higher '
4969 'phase, use --force\n') % len(rejected))
4969 'phase, use --force\n') % len(rejected))
4970 ret = 1
4970 ret = 1
4971 if changes:
4971 if changes:
4972 msg = _('phase changed for %i changesets\n') % changes
4972 msg = _('phase changed for %i changesets\n') % changes
4973 if ret:
4973 if ret:
4974 ui.status(msg)
4974 ui.status(msg)
4975 else:
4975 else:
4976 ui.note(msg)
4976 ui.note(msg)
4977 else:
4977 else:
4978 ui.warn(_('no phases changed\n'))
4978 ui.warn(_('no phases changed\n'))
4979 ret = 1
4979 ret = 1
4980 return ret
4980 return ret
4981
4981
4982 def postincoming(ui, repo, modheads, optupdate, checkout):
4982 def postincoming(ui, repo, modheads, optupdate, checkout):
4983 if modheads == 0:
4983 if modheads == 0:
4984 return
4984 return
4985 if optupdate:
4985 if optupdate:
4986 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4986 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4987 try:
4987 try:
4988 ret = hg.update(repo, checkout)
4988 ret = hg.update(repo, checkout)
4989 except util.Abort, inst:
4989 except util.Abort, inst:
4990 ui.warn(_("not updating: %s\n") % str(inst))
4990 ui.warn(_("not updating: %s\n") % str(inst))
4991 if inst.hint:
4991 if inst.hint:
4992 ui.warn(_("(%s)\n") % inst.hint)
4992 ui.warn(_("(%s)\n") % inst.hint)
4993 return 0
4993 return 0
4994 if not ret and not checkout:
4994 if not ret and not checkout:
4995 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4995 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4996 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4996 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4997 return ret
4997 return ret
4998 if modheads > 1:
4998 if modheads > 1:
4999 currentbranchheads = len(repo.branchheads())
4999 currentbranchheads = len(repo.branchheads())
5000 if currentbranchheads == modheads:
5000 if currentbranchheads == modheads:
5001 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5001 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5002 elif currentbranchheads > 1:
5002 elif currentbranchheads > 1:
5003 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5003 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5004 "merge)\n"))
5004 "merge)\n"))
5005 else:
5005 else:
5006 ui.status(_("(run 'hg heads' to see heads)\n"))
5006 ui.status(_("(run 'hg heads' to see heads)\n"))
5007 else:
5007 else:
5008 ui.status(_("(run 'hg update' to get a working copy)\n"))
5008 ui.status(_("(run 'hg update' to get a working copy)\n"))
5009
5009
5010 @command('^pull',
5010 @command('^pull',
5011 [('u', 'update', None,
5011 [('u', 'update', None,
5012 _('update to new branch head if changesets were pulled')),
5012 _('update to new branch head if changesets were pulled')),
5013 ('f', 'force', None, _('run even when remote repository is unrelated')),
5013 ('f', 'force', None, _('run even when remote repository is unrelated')),
5014 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5014 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5015 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5015 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5016 ('b', 'branch', [], _('a specific branch you would like to pull'),
5016 ('b', 'branch', [], _('a specific branch you would like to pull'),
5017 _('BRANCH')),
5017 _('BRANCH')),
5018 ] + remoteopts,
5018 ] + remoteopts,
5019 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5019 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5020 def pull(ui, repo, source="default", **opts):
5020 def pull(ui, repo, source="default", **opts):
5021 """pull changes from the specified source
5021 """pull changes from the specified source
5022
5022
5023 Pull changes from a remote repository to a local one.
5023 Pull changes from a remote repository to a local one.
5024
5024
5025 This finds all changes from the repository at the specified path
5025 This finds all changes from the repository at the specified path
5026 or URL and adds them to a local repository (the current one unless
5026 or URL and adds them to a local repository (the current one unless
5027 -R is specified). By default, this does not update the copy of the
5027 -R is specified). By default, this does not update the copy of the
5028 project in the working directory.
5028 project in the working directory.
5029
5029
5030 Use :hg:`incoming` if you want to see what would have been added
5030 Use :hg:`incoming` if you want to see what would have been added
5031 by a pull at the time you issued this command. If you then decide
5031 by a pull at the time you issued this command. If you then decide
5032 to add those changes to the repository, you should use :hg:`pull
5032 to add those changes to the repository, you should use :hg:`pull
5033 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5033 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5034
5034
5035 If SOURCE is omitted, the 'default' path will be used.
5035 If SOURCE is omitted, the 'default' path will be used.
5036 See :hg:`help urls` for more information.
5036 See :hg:`help urls` for more information.
5037
5037
5038 Returns 0 on success, 1 if an update had unresolved files.
5038 Returns 0 on success, 1 if an update had unresolved files.
5039 """
5039 """
5040 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5040 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5041 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5041 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5042 other = hg.peer(repo, opts, source)
5042 other = hg.peer(repo, opts, source)
5043 try:
5043 try:
5044 revs, checkout = hg.addbranchrevs(repo, other, branches,
5044 revs, checkout = hg.addbranchrevs(repo, other, branches,
5045 opts.get('rev'))
5045 opts.get('rev'))
5046
5046
5047 remotebookmarks = other.listkeys('bookmarks')
5047 remotebookmarks = other.listkeys('bookmarks')
5048
5048
5049 if opts.get('bookmark'):
5049 if opts.get('bookmark'):
5050 if not revs:
5050 if not revs:
5051 revs = []
5051 revs = []
5052 for b in opts['bookmark']:
5052 for b in opts['bookmark']:
5053 if b not in remotebookmarks:
5053 if b not in remotebookmarks:
5054 raise util.Abort(_('remote bookmark %s not found!') % b)
5054 raise util.Abort(_('remote bookmark %s not found!') % b)
5055 revs.append(remotebookmarks[b])
5055 revs.append(remotebookmarks[b])
5056
5056
5057 if revs:
5057 if revs:
5058 try:
5058 try:
5059 revs = [other.lookup(rev) for rev in revs]
5059 revs = [other.lookup(rev) for rev in revs]
5060 except error.CapabilityError:
5060 except error.CapabilityError:
5061 err = _("other repository doesn't support revision lookup, "
5061 err = _("other repository doesn't support revision lookup, "
5062 "so a rev cannot be specified.")
5062 "so a rev cannot be specified.")
5063 raise util.Abort(err)
5063 raise util.Abort(err)
5064
5064
5065 modheads = exchange.pull(repo, other, heads=revs,
5065 modheads = exchange.pull(repo, other, heads=revs,
5066 force=opts.get('force'),
5066 force=opts.get('force'),
5067 bookmarks=opts.get('bookmark', ())).cgresult
5067 bookmarks=opts.get('bookmark', ())).cgresult
5068 if checkout:
5068 if checkout:
5069 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5069 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5070 repo._subtoppath = source
5070 repo._subtoppath = source
5071 try:
5071 try:
5072 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5072 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5073
5073
5074 finally:
5074 finally:
5075 del repo._subtoppath
5075 del repo._subtoppath
5076
5076
5077 finally:
5077 finally:
5078 other.close()
5078 other.close()
5079 return ret
5079 return ret
5080
5080
5081 @command('^push',
5081 @command('^push',
5082 [('f', 'force', None, _('force push')),
5082 [('f', 'force', None, _('force push')),
5083 ('r', 'rev', [],
5083 ('r', 'rev', [],
5084 _('a changeset intended to be included in the destination'),
5084 _('a changeset intended to be included in the destination'),
5085 _('REV')),
5085 _('REV')),
5086 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5086 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5087 ('b', 'branch', [],
5087 ('b', 'branch', [],
5088 _('a specific branch you would like to push'), _('BRANCH')),
5088 _('a specific branch you would like to push'), _('BRANCH')),
5089 ('', 'new-branch', False, _('allow pushing a new branch')),
5089 ('', 'new-branch', False, _('allow pushing a new branch')),
5090 ] + remoteopts,
5090 ] + remoteopts,
5091 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5091 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5092 def push(ui, repo, dest=None, **opts):
5092 def push(ui, repo, dest=None, **opts):
5093 """push changes to the specified destination
5093 """push changes to the specified destination
5094
5094
5095 Push changesets from the local repository to the specified
5095 Push changesets from the local repository to the specified
5096 destination.
5096 destination.
5097
5097
5098 This operation is symmetrical to pull: it is identical to a pull
5098 This operation is symmetrical to pull: it is identical to a pull
5099 in the destination repository from the current one.
5099 in the destination repository from the current one.
5100
5100
5101 By default, push will not allow creation of new heads at the
5101 By default, push will not allow creation of new heads at the
5102 destination, since multiple heads would make it unclear which head
5102 destination, since multiple heads would make it unclear which head
5103 to use. In this situation, it is recommended to pull and merge
5103 to use. In this situation, it is recommended to pull and merge
5104 before pushing.
5104 before pushing.
5105
5105
5106 Use --new-branch if you want to allow push to create a new named
5106 Use --new-branch if you want to allow push to create a new named
5107 branch that is not present at the destination. This allows you to
5107 branch that is not present at the destination. This allows you to
5108 only create a new branch without forcing other changes.
5108 only create a new branch without forcing other changes.
5109
5109
5110 .. note::
5110 .. note::
5111
5111
5112 Extra care should be taken with the -f/--force option,
5112 Extra care should be taken with the -f/--force option,
5113 which will push all new heads on all branches, an action which will
5113 which will push all new heads on all branches, an action which will
5114 almost always cause confusion for collaborators.
5114 almost always cause confusion for collaborators.
5115
5115
5116 If -r/--rev is used, the specified revision and all its ancestors
5116 If -r/--rev is used, the specified revision and all its ancestors
5117 will be pushed to the remote repository.
5117 will be pushed to the remote repository.
5118
5118
5119 If -B/--bookmark is used, the specified bookmarked revision, its
5119 If -B/--bookmark is used, the specified bookmarked revision, its
5120 ancestors, and the bookmark will be pushed to the remote
5120 ancestors, and the bookmark will be pushed to the remote
5121 repository.
5121 repository.
5122
5122
5123 Please see :hg:`help urls` for important details about ``ssh://``
5123 Please see :hg:`help urls` for important details about ``ssh://``
5124 URLs. If DESTINATION is omitted, a default path will be used.
5124 URLs. If DESTINATION is omitted, a default path will be used.
5125
5125
5126 Returns 0 if push was successful, 1 if nothing to push.
5126 Returns 0 if push was successful, 1 if nothing to push.
5127 """
5127 """
5128
5128
5129 if opts.get('bookmark'):
5129 if opts.get('bookmark'):
5130 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5130 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5131 for b in opts['bookmark']:
5131 for b in opts['bookmark']:
5132 # translate -B options to -r so changesets get pushed
5132 # translate -B options to -r so changesets get pushed
5133 if b in repo._bookmarks:
5133 if b in repo._bookmarks:
5134 opts.setdefault('rev', []).append(b)
5134 opts.setdefault('rev', []).append(b)
5135 else:
5135 else:
5136 # if we try to push a deleted bookmark, translate it to null
5136 # if we try to push a deleted bookmark, translate it to null
5137 # this lets simultaneous -r, -b options continue working
5137 # this lets simultaneous -r, -b options continue working
5138 opts.setdefault('rev', []).append("null")
5138 opts.setdefault('rev', []).append("null")
5139
5139
5140 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5140 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5141 dest, branches = hg.parseurl(dest, opts.get('branch'))
5141 dest, branches = hg.parseurl(dest, opts.get('branch'))
5142 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5142 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5143 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5143 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5144 try:
5144 try:
5145 other = hg.peer(repo, opts, dest)
5145 other = hg.peer(repo, opts, dest)
5146 except error.RepoError:
5146 except error.RepoError:
5147 if dest == "default-push":
5147 if dest == "default-push":
5148 raise util.Abort(_("default repository not configured!"),
5148 raise util.Abort(_("default repository not configured!"),
5149 hint=_('see the "path" section in "hg help config"'))
5149 hint=_('see the "path" section in "hg help config"'))
5150 else:
5150 else:
5151 raise
5151 raise
5152
5152
5153 if revs:
5153 if revs:
5154 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5154 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5155 if not revs:
5156 raise util.Abort(_("specified revisions evaluate to an empty set"),
5157 hint=_("use different revision arguments"))
5155
5158
5156 repo._subtoppath = dest
5159 repo._subtoppath = dest
5157 try:
5160 try:
5158 # push subrepos depth-first for coherent ordering
5161 # push subrepos depth-first for coherent ordering
5159 c = repo['']
5162 c = repo['']
5160 subs = c.substate # only repos that are committed
5163 subs = c.substate # only repos that are committed
5161 for s in sorted(subs):
5164 for s in sorted(subs):
5162 result = c.sub(s).push(opts)
5165 result = c.sub(s).push(opts)
5163 if result == 0:
5166 if result == 0:
5164 return not result
5167 return not result
5165 finally:
5168 finally:
5166 del repo._subtoppath
5169 del repo._subtoppath
5167 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5170 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5168 newbranch=opts.get('new_branch'),
5171 newbranch=opts.get('new_branch'),
5169 bookmarks=opts.get('bookmark', ()))
5172 bookmarks=opts.get('bookmark', ()))
5170
5173
5171 result = not pushop.cgresult
5174 result = not pushop.cgresult
5172
5175
5173 if pushop.bkresult is not None:
5176 if pushop.bkresult is not None:
5174 if pushop.bkresult == 2:
5177 if pushop.bkresult == 2:
5175 result = 2
5178 result = 2
5176 elif not result and pushop.bkresult:
5179 elif not result and pushop.bkresult:
5177 result = 2
5180 result = 2
5178
5181
5179 return result
5182 return result
5180
5183
5181 @command('recover', [])
5184 @command('recover', [])
5182 def recover(ui, repo):
5185 def recover(ui, repo):
5183 """roll back an interrupted transaction
5186 """roll back an interrupted transaction
5184
5187
5185 Recover from an interrupted commit or pull.
5188 Recover from an interrupted commit or pull.
5186
5189
5187 This command tries to fix the repository status after an
5190 This command tries to fix the repository status after an
5188 interrupted operation. It should only be necessary when Mercurial
5191 interrupted operation. It should only be necessary when Mercurial
5189 suggests it.
5192 suggests it.
5190
5193
5191 Returns 0 if successful, 1 if nothing to recover or verify fails.
5194 Returns 0 if successful, 1 if nothing to recover or verify fails.
5192 """
5195 """
5193 if repo.recover():
5196 if repo.recover():
5194 return hg.verify(repo)
5197 return hg.verify(repo)
5195 return 1
5198 return 1
5196
5199
5197 @command('^remove|rm',
5200 @command('^remove|rm',
5198 [('A', 'after', None, _('record delete for missing files')),
5201 [('A', 'after', None, _('record delete for missing files')),
5199 ('f', 'force', None,
5202 ('f', 'force', None,
5200 _('remove (and delete) file even if added or modified')),
5203 _('remove (and delete) file even if added or modified')),
5201 ] + subrepoopts + walkopts,
5204 ] + subrepoopts + walkopts,
5202 _('[OPTION]... FILE...'),
5205 _('[OPTION]... FILE...'),
5203 inferrepo=True)
5206 inferrepo=True)
5204 def remove(ui, repo, *pats, **opts):
5207 def remove(ui, repo, *pats, **opts):
5205 """remove the specified files on the next commit
5208 """remove the specified files on the next commit
5206
5209
5207 Schedule the indicated files for removal from the current branch.
5210 Schedule the indicated files for removal from the current branch.
5208
5211
5209 This command schedules the files to be removed at the next commit.
5212 This command schedules the files to be removed at the next commit.
5210 To undo a remove before that, see :hg:`revert`. To undo added
5213 To undo a remove before that, see :hg:`revert`. To undo added
5211 files, see :hg:`forget`.
5214 files, see :hg:`forget`.
5212
5215
5213 .. container:: verbose
5216 .. container:: verbose
5214
5217
5215 -A/--after can be used to remove only files that have already
5218 -A/--after can be used to remove only files that have already
5216 been deleted, -f/--force can be used to force deletion, and -Af
5219 been deleted, -f/--force can be used to force deletion, and -Af
5217 can be used to remove files from the next revision without
5220 can be used to remove files from the next revision without
5218 deleting them from the working directory.
5221 deleting them from the working directory.
5219
5222
5220 The following table details the behavior of remove for different
5223 The following table details the behavior of remove for different
5221 file states (columns) and option combinations (rows). The file
5224 file states (columns) and option combinations (rows). The file
5222 states are Added [A], Clean [C], Modified [M] and Missing [!]
5225 states are Added [A], Clean [C], Modified [M] and Missing [!]
5223 (as reported by :hg:`status`). The actions are Warn, Remove
5226 (as reported by :hg:`status`). The actions are Warn, Remove
5224 (from branch) and Delete (from disk):
5227 (from branch) and Delete (from disk):
5225
5228
5226 ========= == == == ==
5229 ========= == == == ==
5227 opt/state A C M !
5230 opt/state A C M !
5228 ========= == == == ==
5231 ========= == == == ==
5229 none W RD W R
5232 none W RD W R
5230 -f R RD RD R
5233 -f R RD RD R
5231 -A W W W R
5234 -A W W W R
5232 -Af R R R R
5235 -Af R R R R
5233 ========= == == == ==
5236 ========= == == == ==
5234
5237
5235 Note that remove never deletes files in Added [A] state from the
5238 Note that remove never deletes files in Added [A] state from the
5236 working directory, not even if option --force is specified.
5239 working directory, not even if option --force is specified.
5237
5240
5238 Returns 0 on success, 1 if any warnings encountered.
5241 Returns 0 on success, 1 if any warnings encountered.
5239 """
5242 """
5240
5243
5241 after, force = opts.get('after'), opts.get('force')
5244 after, force = opts.get('after'), opts.get('force')
5242 if not pats and not after:
5245 if not pats and not after:
5243 raise util.Abort(_('no files specified'))
5246 raise util.Abort(_('no files specified'))
5244
5247
5245 m = scmutil.match(repo[None], pats, opts)
5248 m = scmutil.match(repo[None], pats, opts)
5246 subrepos = opts.get('subrepos')
5249 subrepos = opts.get('subrepos')
5247 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5250 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5248
5251
5249 @command('rename|move|mv',
5252 @command('rename|move|mv',
5250 [('A', 'after', None, _('record a rename that has already occurred')),
5253 [('A', 'after', None, _('record a rename that has already occurred')),
5251 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5254 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5252 ] + walkopts + dryrunopts,
5255 ] + walkopts + dryrunopts,
5253 _('[OPTION]... SOURCE... DEST'))
5256 _('[OPTION]... SOURCE... DEST'))
5254 def rename(ui, repo, *pats, **opts):
5257 def rename(ui, repo, *pats, **opts):
5255 """rename files; equivalent of copy + remove
5258 """rename files; equivalent of copy + remove
5256
5259
5257 Mark dest as copies of sources; mark sources for deletion. If dest
5260 Mark dest as copies of sources; mark sources for deletion. If dest
5258 is a directory, copies are put in that directory. If dest is a
5261 is a directory, copies are put in that directory. If dest is a
5259 file, there can only be one source.
5262 file, there can only be one source.
5260
5263
5261 By default, this command copies the contents of files as they
5264 By default, this command copies the contents of files as they
5262 exist in the working directory. If invoked with -A/--after, the
5265 exist in the working directory. If invoked with -A/--after, the
5263 operation is recorded, but no copying is performed.
5266 operation is recorded, but no copying is performed.
5264
5267
5265 This command takes effect at the next commit. To undo a rename
5268 This command takes effect at the next commit. To undo a rename
5266 before that, see :hg:`revert`.
5269 before that, see :hg:`revert`.
5267
5270
5268 Returns 0 on success, 1 if errors are encountered.
5271 Returns 0 on success, 1 if errors are encountered.
5269 """
5272 """
5270 wlock = repo.wlock(False)
5273 wlock = repo.wlock(False)
5271 try:
5274 try:
5272 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5275 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5273 finally:
5276 finally:
5274 wlock.release()
5277 wlock.release()
5275
5278
5276 @command('resolve',
5279 @command('resolve',
5277 [('a', 'all', None, _('select all unresolved files')),
5280 [('a', 'all', None, _('select all unresolved files')),
5278 ('l', 'list', None, _('list state of files needing merge')),
5281 ('l', 'list', None, _('list state of files needing merge')),
5279 ('m', 'mark', None, _('mark files as resolved')),
5282 ('m', 'mark', None, _('mark files as resolved')),
5280 ('u', 'unmark', None, _('mark files as unresolved')),
5283 ('u', 'unmark', None, _('mark files as unresolved')),
5281 ('n', 'no-status', None, _('hide status prefix'))]
5284 ('n', 'no-status', None, _('hide status prefix'))]
5282 + mergetoolopts + walkopts + formatteropts,
5285 + mergetoolopts + walkopts + formatteropts,
5283 _('[OPTION]... [FILE]...'),
5286 _('[OPTION]... [FILE]...'),
5284 inferrepo=True)
5287 inferrepo=True)
5285 def resolve(ui, repo, *pats, **opts):
5288 def resolve(ui, repo, *pats, **opts):
5286 """redo merges or set/view the merge status of files
5289 """redo merges or set/view the merge status of files
5287
5290
5288 Merges with unresolved conflicts are often the result of
5291 Merges with unresolved conflicts are often the result of
5289 non-interactive merging using the ``internal:merge`` configuration
5292 non-interactive merging using the ``internal:merge`` configuration
5290 setting, or a command-line merge tool like ``diff3``. The resolve
5293 setting, or a command-line merge tool like ``diff3``. The resolve
5291 command is used to manage the files involved in a merge, after
5294 command is used to manage the files involved in a merge, after
5292 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5295 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5293 working directory must have two parents). See :hg:`help
5296 working directory must have two parents). See :hg:`help
5294 merge-tools` for information on configuring merge tools.
5297 merge-tools` for information on configuring merge tools.
5295
5298
5296 The resolve command can be used in the following ways:
5299 The resolve command can be used in the following ways:
5297
5300
5298 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5301 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5299 files, discarding any previous merge attempts. Re-merging is not
5302 files, discarding any previous merge attempts. Re-merging is not
5300 performed for files already marked as resolved. Use ``--all/-a``
5303 performed for files already marked as resolved. Use ``--all/-a``
5301 to select all unresolved files. ``--tool`` can be used to specify
5304 to select all unresolved files. ``--tool`` can be used to specify
5302 the merge tool used for the given files. It overrides the HGMERGE
5305 the merge tool used for the given files. It overrides the HGMERGE
5303 environment variable and your configuration files. Previous file
5306 environment variable and your configuration files. Previous file
5304 contents are saved with a ``.orig`` suffix.
5307 contents are saved with a ``.orig`` suffix.
5305
5308
5306 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5309 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5307 (e.g. after having manually fixed-up the files). The default is
5310 (e.g. after having manually fixed-up the files). The default is
5308 to mark all unresolved files.
5311 to mark all unresolved files.
5309
5312
5310 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5313 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5311 default is to mark all resolved files.
5314 default is to mark all resolved files.
5312
5315
5313 - :hg:`resolve -l`: list files which had or still have conflicts.
5316 - :hg:`resolve -l`: list files which had or still have conflicts.
5314 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5317 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5315
5318
5316 Note that Mercurial will not let you commit files with unresolved
5319 Note that Mercurial will not let you commit files with unresolved
5317 merge conflicts. You must use :hg:`resolve -m ...` before you can
5320 merge conflicts. You must use :hg:`resolve -m ...` before you can
5318 commit after a conflicting merge.
5321 commit after a conflicting merge.
5319
5322
5320 Returns 0 on success, 1 if any files fail a resolve attempt.
5323 Returns 0 on success, 1 if any files fail a resolve attempt.
5321 """
5324 """
5322
5325
5323 all, mark, unmark, show, nostatus = \
5326 all, mark, unmark, show, nostatus = \
5324 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5327 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5325
5328
5326 if (show and (mark or unmark)) or (mark and unmark):
5329 if (show and (mark or unmark)) or (mark and unmark):
5327 raise util.Abort(_("too many options specified"))
5330 raise util.Abort(_("too many options specified"))
5328 if pats and all:
5331 if pats and all:
5329 raise util.Abort(_("can't specify --all and patterns"))
5332 raise util.Abort(_("can't specify --all and patterns"))
5330 if not (all or pats or show or mark or unmark):
5333 if not (all or pats or show or mark or unmark):
5331 raise util.Abort(_('no files or directories specified'),
5334 raise util.Abort(_('no files or directories specified'),
5332 hint=('use --all to remerge all files'))
5335 hint=('use --all to remerge all files'))
5333
5336
5334 if show:
5337 if show:
5335 fm = ui.formatter('resolve', opts)
5338 fm = ui.formatter('resolve', opts)
5336 ms = mergemod.mergestate(repo)
5339 ms = mergemod.mergestate(repo)
5337 m = scmutil.match(repo[None], pats, opts)
5340 m = scmutil.match(repo[None], pats, opts)
5338 for f in ms:
5341 for f in ms:
5339 if not m(f):
5342 if not m(f):
5340 continue
5343 continue
5341 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5344 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5342 fm.startitem()
5345 fm.startitem()
5343 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5346 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5344 fm.write('path', '%s\n', f, label=l)
5347 fm.write('path', '%s\n', f, label=l)
5345 fm.end()
5348 fm.end()
5346 return 0
5349 return 0
5347
5350
5348 wlock = repo.wlock()
5351 wlock = repo.wlock()
5349 try:
5352 try:
5350 ms = mergemod.mergestate(repo)
5353 ms = mergemod.mergestate(repo)
5351
5354
5352 if not (ms.active() or repo.dirstate.p2() != nullid):
5355 if not (ms.active() or repo.dirstate.p2() != nullid):
5353 raise util.Abort(
5356 raise util.Abort(
5354 _('resolve command not applicable when not merging'))
5357 _('resolve command not applicable when not merging'))
5355
5358
5356 m = scmutil.match(repo[None], pats, opts)
5359 m = scmutil.match(repo[None], pats, opts)
5357 ret = 0
5360 ret = 0
5358 didwork = False
5361 didwork = False
5359
5362
5360 for f in ms:
5363 for f in ms:
5361 if not m(f):
5364 if not m(f):
5362 continue
5365 continue
5363
5366
5364 didwork = True
5367 didwork = True
5365
5368
5366 if mark:
5369 if mark:
5367 ms.mark(f, "r")
5370 ms.mark(f, "r")
5368 elif unmark:
5371 elif unmark:
5369 ms.mark(f, "u")
5372 ms.mark(f, "u")
5370 else:
5373 else:
5371 wctx = repo[None]
5374 wctx = repo[None]
5372
5375
5373 # backup pre-resolve (merge uses .orig for its own purposes)
5376 # backup pre-resolve (merge uses .orig for its own purposes)
5374 a = repo.wjoin(f)
5377 a = repo.wjoin(f)
5375 util.copyfile(a, a + ".resolve")
5378 util.copyfile(a, a + ".resolve")
5376
5379
5377 try:
5380 try:
5378 # resolve file
5381 # resolve file
5379 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5382 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5380 'resolve')
5383 'resolve')
5381 if ms.resolve(f, wctx):
5384 if ms.resolve(f, wctx):
5382 ret = 1
5385 ret = 1
5383 finally:
5386 finally:
5384 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5387 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5385 ms.commit()
5388 ms.commit()
5386
5389
5387 # replace filemerge's .orig file with our resolve file
5390 # replace filemerge's .orig file with our resolve file
5388 util.rename(a + ".resolve", a + ".orig")
5391 util.rename(a + ".resolve", a + ".orig")
5389
5392
5390 ms.commit()
5393 ms.commit()
5391
5394
5392 if not didwork and pats:
5395 if not didwork and pats:
5393 ui.warn(_("arguments do not match paths that need resolving\n"))
5396 ui.warn(_("arguments do not match paths that need resolving\n"))
5394
5397
5395 finally:
5398 finally:
5396 wlock.release()
5399 wlock.release()
5397
5400
5398 # Nudge users into finishing an unfinished operation
5401 # Nudge users into finishing an unfinished operation
5399 if not list(ms.unresolved()):
5402 if not list(ms.unresolved()):
5400 ui.status(_('(no more unresolved files)\n'))
5403 ui.status(_('(no more unresolved files)\n'))
5401
5404
5402 return ret
5405 return ret
5403
5406
5404 @command('revert',
5407 @command('revert',
5405 [('a', 'all', None, _('revert all changes when no arguments given')),
5408 [('a', 'all', None, _('revert all changes when no arguments given')),
5406 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5409 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5407 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5410 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5408 ('C', 'no-backup', None, _('do not save backup copies of files')),
5411 ('C', 'no-backup', None, _('do not save backup copies of files')),
5409 ('i', 'interactive', None, _('interactively select the changes')),
5412 ('i', 'interactive', None, _('interactively select the changes')),
5410 ] + walkopts + dryrunopts,
5413 ] + walkopts + dryrunopts,
5411 _('[OPTION]... [-r REV] [NAME]...'))
5414 _('[OPTION]... [-r REV] [NAME]...'))
5412 def revert(ui, repo, *pats, **opts):
5415 def revert(ui, repo, *pats, **opts):
5413 """restore files to their checkout state
5416 """restore files to their checkout state
5414
5417
5415 .. note::
5418 .. note::
5416
5419
5417 To check out earlier revisions, you should use :hg:`update REV`.
5420 To check out earlier revisions, you should use :hg:`update REV`.
5418 To cancel an uncommitted merge (and lose your changes),
5421 To cancel an uncommitted merge (and lose your changes),
5419 use :hg:`update --clean .`.
5422 use :hg:`update --clean .`.
5420
5423
5421 With no revision specified, revert the specified files or directories
5424 With no revision specified, revert the specified files or directories
5422 to the contents they had in the parent of the working directory.
5425 to the contents they had in the parent of the working directory.
5423 This restores the contents of files to an unmodified
5426 This restores the contents of files to an unmodified
5424 state and unschedules adds, removes, copies, and renames. If the
5427 state and unschedules adds, removes, copies, and renames. If the
5425 working directory has two parents, you must explicitly specify a
5428 working directory has two parents, you must explicitly specify a
5426 revision.
5429 revision.
5427
5430
5428 Using the -r/--rev or -d/--date options, revert the given files or
5431 Using the -r/--rev or -d/--date options, revert the given files or
5429 directories to their states as of a specific revision. Because
5432 directories to their states as of a specific revision. Because
5430 revert does not change the working directory parents, this will
5433 revert does not change the working directory parents, this will
5431 cause these files to appear modified. This can be helpful to "back
5434 cause these files to appear modified. This can be helpful to "back
5432 out" some or all of an earlier change. See :hg:`backout` for a
5435 out" some or all of an earlier change. See :hg:`backout` for a
5433 related method.
5436 related method.
5434
5437
5435 Modified files are saved with a .orig suffix before reverting.
5438 Modified files are saved with a .orig suffix before reverting.
5436 To disable these backups, use --no-backup.
5439 To disable these backups, use --no-backup.
5437
5440
5438 See :hg:`help dates` for a list of formats valid for -d/--date.
5441 See :hg:`help dates` for a list of formats valid for -d/--date.
5439
5442
5440 Returns 0 on success.
5443 Returns 0 on success.
5441 """
5444 """
5442
5445
5443 if opts.get("date"):
5446 if opts.get("date"):
5444 if opts.get("rev"):
5447 if opts.get("rev"):
5445 raise util.Abort(_("you can't specify a revision and a date"))
5448 raise util.Abort(_("you can't specify a revision and a date"))
5446 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5449 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5447
5450
5448 parent, p2 = repo.dirstate.parents()
5451 parent, p2 = repo.dirstate.parents()
5449 if not opts.get('rev') and p2 != nullid:
5452 if not opts.get('rev') and p2 != nullid:
5450 # revert after merge is a trap for new users (issue2915)
5453 # revert after merge is a trap for new users (issue2915)
5451 raise util.Abort(_('uncommitted merge with no revision specified'),
5454 raise util.Abort(_('uncommitted merge with no revision specified'),
5452 hint=_('use "hg update" or see "hg help revert"'))
5455 hint=_('use "hg update" or see "hg help revert"'))
5453
5456
5454 ctx = scmutil.revsingle(repo, opts.get('rev'))
5457 ctx = scmutil.revsingle(repo, opts.get('rev'))
5455
5458
5456 if not pats and not opts.get('all'):
5459 if not pats and not opts.get('all'):
5457 msg = _("no files or directories specified")
5460 msg = _("no files or directories specified")
5458 if p2 != nullid:
5461 if p2 != nullid:
5459 hint = _("uncommitted merge, use --all to discard all changes,"
5462 hint = _("uncommitted merge, use --all to discard all changes,"
5460 " or 'hg update -C .' to abort the merge")
5463 " or 'hg update -C .' to abort the merge")
5461 raise util.Abort(msg, hint=hint)
5464 raise util.Abort(msg, hint=hint)
5462 dirty = util.any(repo.status())
5465 dirty = util.any(repo.status())
5463 node = ctx.node()
5466 node = ctx.node()
5464 if node != parent:
5467 if node != parent:
5465 if dirty:
5468 if dirty:
5466 hint = _("uncommitted changes, use --all to discard all"
5469 hint = _("uncommitted changes, use --all to discard all"
5467 " changes, or 'hg update %s' to update") % ctx.rev()
5470 " changes, or 'hg update %s' to update") % ctx.rev()
5468 else:
5471 else:
5469 hint = _("use --all to revert all files,"
5472 hint = _("use --all to revert all files,"
5470 " or 'hg update %s' to update") % ctx.rev()
5473 " or 'hg update %s' to update") % ctx.rev()
5471 elif dirty:
5474 elif dirty:
5472 hint = _("uncommitted changes, use --all to discard all changes")
5475 hint = _("uncommitted changes, use --all to discard all changes")
5473 else:
5476 else:
5474 hint = _("use --all to revert all files")
5477 hint = _("use --all to revert all files")
5475 raise util.Abort(msg, hint=hint)
5478 raise util.Abort(msg, hint=hint)
5476
5479
5477 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5480 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5478
5481
5479 @command('rollback', dryrunopts +
5482 @command('rollback', dryrunopts +
5480 [('f', 'force', False, _('ignore safety measures'))])
5483 [('f', 'force', False, _('ignore safety measures'))])
5481 def rollback(ui, repo, **opts):
5484 def rollback(ui, repo, **opts):
5482 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5485 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5483
5486
5484 Please use :hg:`commit --amend` instead of rollback to correct
5487 Please use :hg:`commit --amend` instead of rollback to correct
5485 mistakes in the last commit.
5488 mistakes in the last commit.
5486
5489
5487 This command should be used with care. There is only one level of
5490 This command should be used with care. There is only one level of
5488 rollback, and there is no way to undo a rollback. It will also
5491 rollback, and there is no way to undo a rollback. It will also
5489 restore the dirstate at the time of the last transaction, losing
5492 restore the dirstate at the time of the last transaction, losing
5490 any dirstate changes since that time. This command does not alter
5493 any dirstate changes since that time. This command does not alter
5491 the working directory.
5494 the working directory.
5492
5495
5493 Transactions are used to encapsulate the effects of all commands
5496 Transactions are used to encapsulate the effects of all commands
5494 that create new changesets or propagate existing changesets into a
5497 that create new changesets or propagate existing changesets into a
5495 repository.
5498 repository.
5496
5499
5497 .. container:: verbose
5500 .. container:: verbose
5498
5501
5499 For example, the following commands are transactional, and their
5502 For example, the following commands are transactional, and their
5500 effects can be rolled back:
5503 effects can be rolled back:
5501
5504
5502 - commit
5505 - commit
5503 - import
5506 - import
5504 - pull
5507 - pull
5505 - push (with this repository as the destination)
5508 - push (with this repository as the destination)
5506 - unbundle
5509 - unbundle
5507
5510
5508 To avoid permanent data loss, rollback will refuse to rollback a
5511 To avoid permanent data loss, rollback will refuse to rollback a
5509 commit transaction if it isn't checked out. Use --force to
5512 commit transaction if it isn't checked out. Use --force to
5510 override this protection.
5513 override this protection.
5511
5514
5512 This command is not intended for use on public repositories. Once
5515 This command is not intended for use on public repositories. Once
5513 changes are visible for pull by other users, rolling a transaction
5516 changes are visible for pull by other users, rolling a transaction
5514 back locally is ineffective (someone else may already have pulled
5517 back locally is ineffective (someone else may already have pulled
5515 the changes). Furthermore, a race is possible with readers of the
5518 the changes). Furthermore, a race is possible with readers of the
5516 repository; for example an in-progress pull from the repository
5519 repository; for example an in-progress pull from the repository
5517 may fail if a rollback is performed.
5520 may fail if a rollback is performed.
5518
5521
5519 Returns 0 on success, 1 if no rollback data is available.
5522 Returns 0 on success, 1 if no rollback data is available.
5520 """
5523 """
5521 return repo.rollback(dryrun=opts.get('dry_run'),
5524 return repo.rollback(dryrun=opts.get('dry_run'),
5522 force=opts.get('force'))
5525 force=opts.get('force'))
5523
5526
5524 @command('root', [])
5527 @command('root', [])
5525 def root(ui, repo):
5528 def root(ui, repo):
5526 """print the root (top) of the current working directory
5529 """print the root (top) of the current working directory
5527
5530
5528 Print the root directory of the current repository.
5531 Print the root directory of the current repository.
5529
5532
5530 Returns 0 on success.
5533 Returns 0 on success.
5531 """
5534 """
5532 ui.write(repo.root + "\n")
5535 ui.write(repo.root + "\n")
5533
5536
5534 @command('^serve',
5537 @command('^serve',
5535 [('A', 'accesslog', '', _('name of access log file to write to'),
5538 [('A', 'accesslog', '', _('name of access log file to write to'),
5536 _('FILE')),
5539 _('FILE')),
5537 ('d', 'daemon', None, _('run server in background')),
5540 ('d', 'daemon', None, _('run server in background')),
5538 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5541 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5539 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5542 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5540 # use string type, then we can check if something was passed
5543 # use string type, then we can check if something was passed
5541 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5544 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5542 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5545 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5543 _('ADDR')),
5546 _('ADDR')),
5544 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5547 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5545 _('PREFIX')),
5548 _('PREFIX')),
5546 ('n', 'name', '',
5549 ('n', 'name', '',
5547 _('name to show in web pages (default: working directory)'), _('NAME')),
5550 _('name to show in web pages (default: working directory)'), _('NAME')),
5548 ('', 'web-conf', '',
5551 ('', 'web-conf', '',
5549 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5552 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5550 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5553 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5551 _('FILE')),
5554 _('FILE')),
5552 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5555 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5553 ('', 'stdio', None, _('for remote clients')),
5556 ('', 'stdio', None, _('for remote clients')),
5554 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5557 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5555 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5558 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5556 ('', 'style', '', _('template style to use'), _('STYLE')),
5559 ('', 'style', '', _('template style to use'), _('STYLE')),
5557 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5560 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5558 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5561 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5559 _('[OPTION]...'),
5562 _('[OPTION]...'),
5560 optionalrepo=True)
5563 optionalrepo=True)
5561 def serve(ui, repo, **opts):
5564 def serve(ui, repo, **opts):
5562 """start stand-alone webserver
5565 """start stand-alone webserver
5563
5566
5564 Start a local HTTP repository browser and pull server. You can use
5567 Start a local HTTP repository browser and pull server. You can use
5565 this for ad-hoc sharing and browsing of repositories. It is
5568 this for ad-hoc sharing and browsing of repositories. It is
5566 recommended to use a real web server to serve a repository for
5569 recommended to use a real web server to serve a repository for
5567 longer periods of time.
5570 longer periods of time.
5568
5571
5569 Please note that the server does not implement access control.
5572 Please note that the server does not implement access control.
5570 This means that, by default, anybody can read from the server and
5573 This means that, by default, anybody can read from the server and
5571 nobody can write to it by default. Set the ``web.allow_push``
5574 nobody can write to it by default. Set the ``web.allow_push``
5572 option to ``*`` to allow everybody to push to the server. You
5575 option to ``*`` to allow everybody to push to the server. You
5573 should use a real web server if you need to authenticate users.
5576 should use a real web server if you need to authenticate users.
5574
5577
5575 By default, the server logs accesses to stdout and errors to
5578 By default, the server logs accesses to stdout and errors to
5576 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5579 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5577 files.
5580 files.
5578
5581
5579 To have the server choose a free port number to listen on, specify
5582 To have the server choose a free port number to listen on, specify
5580 a port number of 0; in this case, the server will print the port
5583 a port number of 0; in this case, the server will print the port
5581 number it uses.
5584 number it uses.
5582
5585
5583 Returns 0 on success.
5586 Returns 0 on success.
5584 """
5587 """
5585
5588
5586 if opts["stdio"] and opts["cmdserver"]:
5589 if opts["stdio"] and opts["cmdserver"]:
5587 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5590 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5588
5591
5589 if opts["stdio"]:
5592 if opts["stdio"]:
5590 if repo is None:
5593 if repo is None:
5591 raise error.RepoError(_("there is no Mercurial repository here"
5594 raise error.RepoError(_("there is no Mercurial repository here"
5592 " (.hg not found)"))
5595 " (.hg not found)"))
5593 s = sshserver.sshserver(ui, repo)
5596 s = sshserver.sshserver(ui, repo)
5594 s.serve_forever()
5597 s.serve_forever()
5595
5598
5596 if opts["cmdserver"]:
5599 if opts["cmdserver"]:
5597 service = commandserver.createservice(ui, repo, opts)
5600 service = commandserver.createservice(ui, repo, opts)
5598 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5601 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5599
5602
5600 # this way we can check if something was given in the command-line
5603 # this way we can check if something was given in the command-line
5601 if opts.get('port'):
5604 if opts.get('port'):
5602 opts['port'] = util.getport(opts.get('port'))
5605 opts['port'] = util.getport(opts.get('port'))
5603
5606
5604 if repo:
5607 if repo:
5605 baseui = repo.baseui
5608 baseui = repo.baseui
5606 else:
5609 else:
5607 baseui = ui
5610 baseui = ui
5608 optlist = ("name templates style address port prefix ipv6"
5611 optlist = ("name templates style address port prefix ipv6"
5609 " accesslog errorlog certificate encoding")
5612 " accesslog errorlog certificate encoding")
5610 for o in optlist.split():
5613 for o in optlist.split():
5611 val = opts.get(o, '')
5614 val = opts.get(o, '')
5612 if val in (None, ''): # should check against default options instead
5615 if val in (None, ''): # should check against default options instead
5613 continue
5616 continue
5614 baseui.setconfig("web", o, val, 'serve')
5617 baseui.setconfig("web", o, val, 'serve')
5615 if repo and repo.ui != baseui:
5618 if repo and repo.ui != baseui:
5616 repo.ui.setconfig("web", o, val, 'serve')
5619 repo.ui.setconfig("web", o, val, 'serve')
5617
5620
5618 o = opts.get('web_conf') or opts.get('webdir_conf')
5621 o = opts.get('web_conf') or opts.get('webdir_conf')
5619 if not o:
5622 if not o:
5620 if not repo:
5623 if not repo:
5621 raise error.RepoError(_("there is no Mercurial repository"
5624 raise error.RepoError(_("there is no Mercurial repository"
5622 " here (.hg not found)"))
5625 " here (.hg not found)"))
5623 o = repo
5626 o = repo
5624
5627
5625 app = hgweb.hgweb(o, baseui=baseui)
5628 app = hgweb.hgweb(o, baseui=baseui)
5626 service = httpservice(ui, app, opts)
5629 service = httpservice(ui, app, opts)
5627 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5630 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5628
5631
5629 class httpservice(object):
5632 class httpservice(object):
5630 def __init__(self, ui, app, opts):
5633 def __init__(self, ui, app, opts):
5631 self.ui = ui
5634 self.ui = ui
5632 self.app = app
5635 self.app = app
5633 self.opts = opts
5636 self.opts = opts
5634
5637
5635 def init(self):
5638 def init(self):
5636 util.setsignalhandler()
5639 util.setsignalhandler()
5637 self.httpd = hgweb_server.create_server(self.ui, self.app)
5640 self.httpd = hgweb_server.create_server(self.ui, self.app)
5638
5641
5639 if self.opts['port'] and not self.ui.verbose:
5642 if self.opts['port'] and not self.ui.verbose:
5640 return
5643 return
5641
5644
5642 if self.httpd.prefix:
5645 if self.httpd.prefix:
5643 prefix = self.httpd.prefix.strip('/') + '/'
5646 prefix = self.httpd.prefix.strip('/') + '/'
5644 else:
5647 else:
5645 prefix = ''
5648 prefix = ''
5646
5649
5647 port = ':%d' % self.httpd.port
5650 port = ':%d' % self.httpd.port
5648 if port == ':80':
5651 if port == ':80':
5649 port = ''
5652 port = ''
5650
5653
5651 bindaddr = self.httpd.addr
5654 bindaddr = self.httpd.addr
5652 if bindaddr == '0.0.0.0':
5655 if bindaddr == '0.0.0.0':
5653 bindaddr = '*'
5656 bindaddr = '*'
5654 elif ':' in bindaddr: # IPv6
5657 elif ':' in bindaddr: # IPv6
5655 bindaddr = '[%s]' % bindaddr
5658 bindaddr = '[%s]' % bindaddr
5656
5659
5657 fqaddr = self.httpd.fqaddr
5660 fqaddr = self.httpd.fqaddr
5658 if ':' in fqaddr:
5661 if ':' in fqaddr:
5659 fqaddr = '[%s]' % fqaddr
5662 fqaddr = '[%s]' % fqaddr
5660 if self.opts['port']:
5663 if self.opts['port']:
5661 write = self.ui.status
5664 write = self.ui.status
5662 else:
5665 else:
5663 write = self.ui.write
5666 write = self.ui.write
5664 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5667 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5665 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5668 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5666 self.ui.flush() # avoid buffering of status message
5669 self.ui.flush() # avoid buffering of status message
5667
5670
5668 def run(self):
5671 def run(self):
5669 self.httpd.serve_forever()
5672 self.httpd.serve_forever()
5670
5673
5671
5674
5672 @command('^status|st',
5675 @command('^status|st',
5673 [('A', 'all', None, _('show status of all files')),
5676 [('A', 'all', None, _('show status of all files')),
5674 ('m', 'modified', None, _('show only modified files')),
5677 ('m', 'modified', None, _('show only modified files')),
5675 ('a', 'added', None, _('show only added files')),
5678 ('a', 'added', None, _('show only added files')),
5676 ('r', 'removed', None, _('show only removed files')),
5679 ('r', 'removed', None, _('show only removed files')),
5677 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5680 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5678 ('c', 'clean', None, _('show only files without changes')),
5681 ('c', 'clean', None, _('show only files without changes')),
5679 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5682 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5680 ('i', 'ignored', None, _('show only ignored files')),
5683 ('i', 'ignored', None, _('show only ignored files')),
5681 ('n', 'no-status', None, _('hide status prefix')),
5684 ('n', 'no-status', None, _('hide status prefix')),
5682 ('C', 'copies', None, _('show source of copied files')),
5685 ('C', 'copies', None, _('show source of copied files')),
5683 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5686 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5684 ('', 'rev', [], _('show difference from revision'), _('REV')),
5687 ('', 'rev', [], _('show difference from revision'), _('REV')),
5685 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5688 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5686 ] + walkopts + subrepoopts + formatteropts,
5689 ] + walkopts + subrepoopts + formatteropts,
5687 _('[OPTION]... [FILE]...'),
5690 _('[OPTION]... [FILE]...'),
5688 inferrepo=True)
5691 inferrepo=True)
5689 def status(ui, repo, *pats, **opts):
5692 def status(ui, repo, *pats, **opts):
5690 """show changed files in the working directory
5693 """show changed files in the working directory
5691
5694
5692 Show status of files in the repository. If names are given, only
5695 Show status of files in the repository. If names are given, only
5693 files that match are shown. Files that are clean or ignored or
5696 files that match are shown. Files that are clean or ignored or
5694 the source of a copy/move operation, are not listed unless
5697 the source of a copy/move operation, are not listed unless
5695 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5698 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5696 Unless options described with "show only ..." are given, the
5699 Unless options described with "show only ..." are given, the
5697 options -mardu are used.
5700 options -mardu are used.
5698
5701
5699 Option -q/--quiet hides untracked (unknown and ignored) files
5702 Option -q/--quiet hides untracked (unknown and ignored) files
5700 unless explicitly requested with -u/--unknown or -i/--ignored.
5703 unless explicitly requested with -u/--unknown or -i/--ignored.
5701
5704
5702 .. note::
5705 .. note::
5703
5706
5704 status may appear to disagree with diff if permissions have
5707 status may appear to disagree with diff if permissions have
5705 changed or a merge has occurred. The standard diff format does
5708 changed or a merge has occurred. The standard diff format does
5706 not report permission changes and diff only reports changes
5709 not report permission changes and diff only reports changes
5707 relative to one merge parent.
5710 relative to one merge parent.
5708
5711
5709 If one revision is given, it is used as the base revision.
5712 If one revision is given, it is used as the base revision.
5710 If two revisions are given, the differences between them are
5713 If two revisions are given, the differences between them are
5711 shown. The --change option can also be used as a shortcut to list
5714 shown. The --change option can also be used as a shortcut to list
5712 the changed files of a revision from its first parent.
5715 the changed files of a revision from its first parent.
5713
5716
5714 The codes used to show the status of files are::
5717 The codes used to show the status of files are::
5715
5718
5716 M = modified
5719 M = modified
5717 A = added
5720 A = added
5718 R = removed
5721 R = removed
5719 C = clean
5722 C = clean
5720 ! = missing (deleted by non-hg command, but still tracked)
5723 ! = missing (deleted by non-hg command, but still tracked)
5721 ? = not tracked
5724 ? = not tracked
5722 I = ignored
5725 I = ignored
5723 = origin of the previous file (with --copies)
5726 = origin of the previous file (with --copies)
5724
5727
5725 .. container:: verbose
5728 .. container:: verbose
5726
5729
5727 Examples:
5730 Examples:
5728
5731
5729 - show changes in the working directory relative to a
5732 - show changes in the working directory relative to a
5730 changeset::
5733 changeset::
5731
5734
5732 hg status --rev 9353
5735 hg status --rev 9353
5733
5736
5734 - show all changes including copies in an existing changeset::
5737 - show all changes including copies in an existing changeset::
5735
5738
5736 hg status --copies --change 9353
5739 hg status --copies --change 9353
5737
5740
5738 - get a NUL separated list of added files, suitable for xargs::
5741 - get a NUL separated list of added files, suitable for xargs::
5739
5742
5740 hg status -an0
5743 hg status -an0
5741
5744
5742 Returns 0 on success.
5745 Returns 0 on success.
5743 """
5746 """
5744
5747
5745 revs = opts.get('rev')
5748 revs = opts.get('rev')
5746 change = opts.get('change')
5749 change = opts.get('change')
5747
5750
5748 if revs and change:
5751 if revs and change:
5749 msg = _('cannot specify --rev and --change at the same time')
5752 msg = _('cannot specify --rev and --change at the same time')
5750 raise util.Abort(msg)
5753 raise util.Abort(msg)
5751 elif change:
5754 elif change:
5752 node2 = scmutil.revsingle(repo, change, None).node()
5755 node2 = scmutil.revsingle(repo, change, None).node()
5753 node1 = repo[node2].p1().node()
5756 node1 = repo[node2].p1().node()
5754 else:
5757 else:
5755 node1, node2 = scmutil.revpair(repo, revs)
5758 node1, node2 = scmutil.revpair(repo, revs)
5756
5759
5757 if pats:
5760 if pats:
5758 cwd = repo.getcwd()
5761 cwd = repo.getcwd()
5759 else:
5762 else:
5760 cwd = ''
5763 cwd = ''
5761
5764
5762 if opts.get('print0'):
5765 if opts.get('print0'):
5763 end = '\0'
5766 end = '\0'
5764 else:
5767 else:
5765 end = '\n'
5768 end = '\n'
5766 copy = {}
5769 copy = {}
5767 states = 'modified added removed deleted unknown ignored clean'.split()
5770 states = 'modified added removed deleted unknown ignored clean'.split()
5768 show = [k for k in states if opts.get(k)]
5771 show = [k for k in states if opts.get(k)]
5769 if opts.get('all'):
5772 if opts.get('all'):
5770 show += ui.quiet and (states[:4] + ['clean']) or states
5773 show += ui.quiet and (states[:4] + ['clean']) or states
5771 if not show:
5774 if not show:
5772 if ui.quiet:
5775 if ui.quiet:
5773 show = states[:4]
5776 show = states[:4]
5774 else:
5777 else:
5775 show = states[:5]
5778 show = states[:5]
5776
5779
5777 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5780 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5778 'ignored' in show, 'clean' in show, 'unknown' in show,
5781 'ignored' in show, 'clean' in show, 'unknown' in show,
5779 opts.get('subrepos'))
5782 opts.get('subrepos'))
5780 changestates = zip(states, 'MAR!?IC', stat)
5783 changestates = zip(states, 'MAR!?IC', stat)
5781
5784
5782 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5785 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5783 copy = copies.pathcopies(repo[node1], repo[node2])
5786 copy = copies.pathcopies(repo[node1], repo[node2])
5784
5787
5785 fm = ui.formatter('status', opts)
5788 fm = ui.formatter('status', opts)
5786 fmt = '%s' + end
5789 fmt = '%s' + end
5787 showchar = not opts.get('no_status')
5790 showchar = not opts.get('no_status')
5788
5791
5789 for state, char, files in changestates:
5792 for state, char, files in changestates:
5790 if state in show:
5793 if state in show:
5791 label = 'status.' + state
5794 label = 'status.' + state
5792 for f in files:
5795 for f in files:
5793 fm.startitem()
5796 fm.startitem()
5794 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5797 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5795 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5798 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5796 if f in copy:
5799 if f in copy:
5797 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5800 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5798 label='status.copied')
5801 label='status.copied')
5799 fm.end()
5802 fm.end()
5800
5803
5801 @command('^summary|sum',
5804 @command('^summary|sum',
5802 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5805 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5803 def summary(ui, repo, **opts):
5806 def summary(ui, repo, **opts):
5804 """summarize working directory state
5807 """summarize working directory state
5805
5808
5806 This generates a brief summary of the working directory state,
5809 This generates a brief summary of the working directory state,
5807 including parents, branch, commit status, and available updates.
5810 including parents, branch, commit status, and available updates.
5808
5811
5809 With the --remote option, this will check the default paths for
5812 With the --remote option, this will check the default paths for
5810 incoming and outgoing changes. This can be time-consuming.
5813 incoming and outgoing changes. This can be time-consuming.
5811
5814
5812 Returns 0 on success.
5815 Returns 0 on success.
5813 """
5816 """
5814
5817
5815 ctx = repo[None]
5818 ctx = repo[None]
5816 parents = ctx.parents()
5819 parents = ctx.parents()
5817 pnode = parents[0].node()
5820 pnode = parents[0].node()
5818 marks = []
5821 marks = []
5819
5822
5820 for p in parents:
5823 for p in parents:
5821 # label with log.changeset (instead of log.parent) since this
5824 # label with log.changeset (instead of log.parent) since this
5822 # shows a working directory parent *changeset*:
5825 # shows a working directory parent *changeset*:
5823 # i18n: column positioning for "hg summary"
5826 # i18n: column positioning for "hg summary"
5824 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5827 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5825 label='log.changeset changeset.%s' % p.phasestr())
5828 label='log.changeset changeset.%s' % p.phasestr())
5826 ui.write(' '.join(p.tags()), label='log.tag')
5829 ui.write(' '.join(p.tags()), label='log.tag')
5827 if p.bookmarks():
5830 if p.bookmarks():
5828 marks.extend(p.bookmarks())
5831 marks.extend(p.bookmarks())
5829 if p.rev() == -1:
5832 if p.rev() == -1:
5830 if not len(repo):
5833 if not len(repo):
5831 ui.write(_(' (empty repository)'))
5834 ui.write(_(' (empty repository)'))
5832 else:
5835 else:
5833 ui.write(_(' (no revision checked out)'))
5836 ui.write(_(' (no revision checked out)'))
5834 ui.write('\n')
5837 ui.write('\n')
5835 if p.description():
5838 if p.description():
5836 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5839 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5837 label='log.summary')
5840 label='log.summary')
5838
5841
5839 branch = ctx.branch()
5842 branch = ctx.branch()
5840 bheads = repo.branchheads(branch)
5843 bheads = repo.branchheads(branch)
5841 # i18n: column positioning for "hg summary"
5844 # i18n: column positioning for "hg summary"
5842 m = _('branch: %s\n') % branch
5845 m = _('branch: %s\n') % branch
5843 if branch != 'default':
5846 if branch != 'default':
5844 ui.write(m, label='log.branch')
5847 ui.write(m, label='log.branch')
5845 else:
5848 else:
5846 ui.status(m, label='log.branch')
5849 ui.status(m, label='log.branch')
5847
5850
5848 if marks:
5851 if marks:
5849 current = repo._bookmarkcurrent
5852 current = repo._bookmarkcurrent
5850 # i18n: column positioning for "hg summary"
5853 # i18n: column positioning for "hg summary"
5851 ui.write(_('bookmarks:'), label='log.bookmark')
5854 ui.write(_('bookmarks:'), label='log.bookmark')
5852 if current is not None:
5855 if current is not None:
5853 if current in marks:
5856 if current in marks:
5854 ui.write(' *' + current, label='bookmarks.current')
5857 ui.write(' *' + current, label='bookmarks.current')
5855 marks.remove(current)
5858 marks.remove(current)
5856 else:
5859 else:
5857 ui.write(' [%s]' % current, label='bookmarks.current')
5860 ui.write(' [%s]' % current, label='bookmarks.current')
5858 for m in marks:
5861 for m in marks:
5859 ui.write(' ' + m, label='log.bookmark')
5862 ui.write(' ' + m, label='log.bookmark')
5860 ui.write('\n', label='log.bookmark')
5863 ui.write('\n', label='log.bookmark')
5861
5864
5862 status = repo.status(unknown=True)
5865 status = repo.status(unknown=True)
5863
5866
5864 c = repo.dirstate.copies()
5867 c = repo.dirstate.copies()
5865 copied, renamed = [], []
5868 copied, renamed = [], []
5866 for d, s in c.iteritems():
5869 for d, s in c.iteritems():
5867 if s in status.removed:
5870 if s in status.removed:
5868 status.removed.remove(s)
5871 status.removed.remove(s)
5869 renamed.append(d)
5872 renamed.append(d)
5870 else:
5873 else:
5871 copied.append(d)
5874 copied.append(d)
5872 if d in status.added:
5875 if d in status.added:
5873 status.added.remove(d)
5876 status.added.remove(d)
5874
5877
5875 ms = mergemod.mergestate(repo)
5878 ms = mergemod.mergestate(repo)
5876 unresolved = [f for f in ms if ms[f] == 'u']
5879 unresolved = [f for f in ms if ms[f] == 'u']
5877
5880
5878 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5881 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5879
5882
5880 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5883 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5881 (ui.label(_('%d added'), 'status.added'), status.added),
5884 (ui.label(_('%d added'), 'status.added'), status.added),
5882 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5885 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5883 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5886 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5884 (ui.label(_('%d copied'), 'status.copied'), copied),
5887 (ui.label(_('%d copied'), 'status.copied'), copied),
5885 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5888 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5886 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5889 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5887 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5890 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5888 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5891 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5889 t = []
5892 t = []
5890 for l, s in labels:
5893 for l, s in labels:
5891 if s:
5894 if s:
5892 t.append(l % len(s))
5895 t.append(l % len(s))
5893
5896
5894 t = ', '.join(t)
5897 t = ', '.join(t)
5895 cleanworkdir = False
5898 cleanworkdir = False
5896
5899
5897 if repo.vfs.exists('updatestate'):
5900 if repo.vfs.exists('updatestate'):
5898 t += _(' (interrupted update)')
5901 t += _(' (interrupted update)')
5899 elif len(parents) > 1:
5902 elif len(parents) > 1:
5900 t += _(' (merge)')
5903 t += _(' (merge)')
5901 elif branch != parents[0].branch():
5904 elif branch != parents[0].branch():
5902 t += _(' (new branch)')
5905 t += _(' (new branch)')
5903 elif (parents[0].closesbranch() and
5906 elif (parents[0].closesbranch() and
5904 pnode in repo.branchheads(branch, closed=True)):
5907 pnode in repo.branchheads(branch, closed=True)):
5905 t += _(' (head closed)')
5908 t += _(' (head closed)')
5906 elif not (status.modified or status.added or status.removed or renamed or
5909 elif not (status.modified or status.added or status.removed or renamed or
5907 copied or subs):
5910 copied or subs):
5908 t += _(' (clean)')
5911 t += _(' (clean)')
5909 cleanworkdir = True
5912 cleanworkdir = True
5910 elif pnode not in bheads:
5913 elif pnode not in bheads:
5911 t += _(' (new branch head)')
5914 t += _(' (new branch head)')
5912
5915
5913 if cleanworkdir:
5916 if cleanworkdir:
5914 # i18n: column positioning for "hg summary"
5917 # i18n: column positioning for "hg summary"
5915 ui.status(_('commit: %s\n') % t.strip())
5918 ui.status(_('commit: %s\n') % t.strip())
5916 else:
5919 else:
5917 # i18n: column positioning for "hg summary"
5920 # i18n: column positioning for "hg summary"
5918 ui.write(_('commit: %s\n') % t.strip())
5921 ui.write(_('commit: %s\n') % t.strip())
5919
5922
5920 # all ancestors of branch heads - all ancestors of parent = new csets
5923 # all ancestors of branch heads - all ancestors of parent = new csets
5921 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5924 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5922 bheads))
5925 bheads))
5923
5926
5924 if new == 0:
5927 if new == 0:
5925 # i18n: column positioning for "hg summary"
5928 # i18n: column positioning for "hg summary"
5926 ui.status(_('update: (current)\n'))
5929 ui.status(_('update: (current)\n'))
5927 elif pnode not in bheads:
5930 elif pnode not in bheads:
5928 # i18n: column positioning for "hg summary"
5931 # i18n: column positioning for "hg summary"
5929 ui.write(_('update: %d new changesets (update)\n') % new)
5932 ui.write(_('update: %d new changesets (update)\n') % new)
5930 else:
5933 else:
5931 # i18n: column positioning for "hg summary"
5934 # i18n: column positioning for "hg summary"
5932 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5935 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5933 (new, len(bheads)))
5936 (new, len(bheads)))
5934
5937
5935 cmdutil.summaryhooks(ui, repo)
5938 cmdutil.summaryhooks(ui, repo)
5936
5939
5937 if opts.get('remote'):
5940 if opts.get('remote'):
5938 needsincoming, needsoutgoing = True, True
5941 needsincoming, needsoutgoing = True, True
5939 else:
5942 else:
5940 needsincoming, needsoutgoing = False, False
5943 needsincoming, needsoutgoing = False, False
5941 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5944 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5942 if i:
5945 if i:
5943 needsincoming = True
5946 needsincoming = True
5944 if o:
5947 if o:
5945 needsoutgoing = True
5948 needsoutgoing = True
5946 if not needsincoming and not needsoutgoing:
5949 if not needsincoming and not needsoutgoing:
5947 return
5950 return
5948
5951
5949 def getincoming():
5952 def getincoming():
5950 source, branches = hg.parseurl(ui.expandpath('default'))
5953 source, branches = hg.parseurl(ui.expandpath('default'))
5951 sbranch = branches[0]
5954 sbranch = branches[0]
5952 try:
5955 try:
5953 other = hg.peer(repo, {}, source)
5956 other = hg.peer(repo, {}, source)
5954 except error.RepoError:
5957 except error.RepoError:
5955 if opts.get('remote'):
5958 if opts.get('remote'):
5956 raise
5959 raise
5957 return source, sbranch, None, None, None
5960 return source, sbranch, None, None, None
5958 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5961 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5959 if revs:
5962 if revs:
5960 revs = [other.lookup(rev) for rev in revs]
5963 revs = [other.lookup(rev) for rev in revs]
5961 ui.debug('comparing with %s\n' % util.hidepassword(source))
5964 ui.debug('comparing with %s\n' % util.hidepassword(source))
5962 repo.ui.pushbuffer()
5965 repo.ui.pushbuffer()
5963 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5966 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5964 repo.ui.popbuffer()
5967 repo.ui.popbuffer()
5965 return source, sbranch, other, commoninc, commoninc[1]
5968 return source, sbranch, other, commoninc, commoninc[1]
5966
5969
5967 if needsincoming:
5970 if needsincoming:
5968 source, sbranch, sother, commoninc, incoming = getincoming()
5971 source, sbranch, sother, commoninc, incoming = getincoming()
5969 else:
5972 else:
5970 source = sbranch = sother = commoninc = incoming = None
5973 source = sbranch = sother = commoninc = incoming = None
5971
5974
5972 def getoutgoing():
5975 def getoutgoing():
5973 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5976 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5974 dbranch = branches[0]
5977 dbranch = branches[0]
5975 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5978 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5976 if source != dest:
5979 if source != dest:
5977 try:
5980 try:
5978 dother = hg.peer(repo, {}, dest)
5981 dother = hg.peer(repo, {}, dest)
5979 except error.RepoError:
5982 except error.RepoError:
5980 if opts.get('remote'):
5983 if opts.get('remote'):
5981 raise
5984 raise
5982 return dest, dbranch, None, None
5985 return dest, dbranch, None, None
5983 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5986 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5984 elif sother is None:
5987 elif sother is None:
5985 # there is no explicit destination peer, but source one is invalid
5988 # there is no explicit destination peer, but source one is invalid
5986 return dest, dbranch, None, None
5989 return dest, dbranch, None, None
5987 else:
5990 else:
5988 dother = sother
5991 dother = sother
5989 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5992 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5990 common = None
5993 common = None
5991 else:
5994 else:
5992 common = commoninc
5995 common = commoninc
5993 if revs:
5996 if revs:
5994 revs = [repo.lookup(rev) for rev in revs]
5997 revs = [repo.lookup(rev) for rev in revs]
5995 repo.ui.pushbuffer()
5998 repo.ui.pushbuffer()
5996 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5999 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5997 commoninc=common)
6000 commoninc=common)
5998 repo.ui.popbuffer()
6001 repo.ui.popbuffer()
5999 return dest, dbranch, dother, outgoing
6002 return dest, dbranch, dother, outgoing
6000
6003
6001 if needsoutgoing:
6004 if needsoutgoing:
6002 dest, dbranch, dother, outgoing = getoutgoing()
6005 dest, dbranch, dother, outgoing = getoutgoing()
6003 else:
6006 else:
6004 dest = dbranch = dother = outgoing = None
6007 dest = dbranch = dother = outgoing = None
6005
6008
6006 if opts.get('remote'):
6009 if opts.get('remote'):
6007 t = []
6010 t = []
6008 if incoming:
6011 if incoming:
6009 t.append(_('1 or more incoming'))
6012 t.append(_('1 or more incoming'))
6010 o = outgoing.missing
6013 o = outgoing.missing
6011 if o:
6014 if o:
6012 t.append(_('%d outgoing') % len(o))
6015 t.append(_('%d outgoing') % len(o))
6013 other = dother or sother
6016 other = dother or sother
6014 if 'bookmarks' in other.listkeys('namespaces'):
6017 if 'bookmarks' in other.listkeys('namespaces'):
6015 counts = bookmarks.summary(repo, other)
6018 counts = bookmarks.summary(repo, other)
6016 if counts[0] > 0:
6019 if counts[0] > 0:
6017 t.append(_('%d incoming bookmarks') % counts[0])
6020 t.append(_('%d incoming bookmarks') % counts[0])
6018 if counts[1] > 0:
6021 if counts[1] > 0:
6019 t.append(_('%d outgoing bookmarks') % counts[1])
6022 t.append(_('%d outgoing bookmarks') % counts[1])
6020
6023
6021 if t:
6024 if t:
6022 # i18n: column positioning for "hg summary"
6025 # i18n: column positioning for "hg summary"
6023 ui.write(_('remote: %s\n') % (', '.join(t)))
6026 ui.write(_('remote: %s\n') % (', '.join(t)))
6024 else:
6027 else:
6025 # i18n: column positioning for "hg summary"
6028 # i18n: column positioning for "hg summary"
6026 ui.status(_('remote: (synced)\n'))
6029 ui.status(_('remote: (synced)\n'))
6027
6030
6028 cmdutil.summaryremotehooks(ui, repo, opts,
6031 cmdutil.summaryremotehooks(ui, repo, opts,
6029 ((source, sbranch, sother, commoninc),
6032 ((source, sbranch, sother, commoninc),
6030 (dest, dbranch, dother, outgoing)))
6033 (dest, dbranch, dother, outgoing)))
6031
6034
6032 @command('tag',
6035 @command('tag',
6033 [('f', 'force', None, _('force tag')),
6036 [('f', 'force', None, _('force tag')),
6034 ('l', 'local', None, _('make the tag local')),
6037 ('l', 'local', None, _('make the tag local')),
6035 ('r', 'rev', '', _('revision to tag'), _('REV')),
6038 ('r', 'rev', '', _('revision to tag'), _('REV')),
6036 ('', 'remove', None, _('remove a tag')),
6039 ('', 'remove', None, _('remove a tag')),
6037 # -l/--local is already there, commitopts cannot be used
6040 # -l/--local is already there, commitopts cannot be used
6038 ('e', 'edit', None, _('invoke editor on commit messages')),
6041 ('e', 'edit', None, _('invoke editor on commit messages')),
6039 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6042 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6040 ] + commitopts2,
6043 ] + commitopts2,
6041 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6044 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6042 def tag(ui, repo, name1, *names, **opts):
6045 def tag(ui, repo, name1, *names, **opts):
6043 """add one or more tags for the current or given revision
6046 """add one or more tags for the current or given revision
6044
6047
6045 Name a particular revision using <name>.
6048 Name a particular revision using <name>.
6046
6049
6047 Tags are used to name particular revisions of the repository and are
6050 Tags are used to name particular revisions of the repository and are
6048 very useful to compare different revisions, to go back to significant
6051 very useful to compare different revisions, to go back to significant
6049 earlier versions or to mark branch points as releases, etc. Changing
6052 earlier versions or to mark branch points as releases, etc. Changing
6050 an existing tag is normally disallowed; use -f/--force to override.
6053 an existing tag is normally disallowed; use -f/--force to override.
6051
6054
6052 If no revision is given, the parent of the working directory is
6055 If no revision is given, the parent of the working directory is
6053 used.
6056 used.
6054
6057
6055 To facilitate version control, distribution, and merging of tags,
6058 To facilitate version control, distribution, and merging of tags,
6056 they are stored as a file named ".hgtags" which is managed similarly
6059 they are stored as a file named ".hgtags" which is managed similarly
6057 to other project files and can be hand-edited if necessary. This
6060 to other project files and can be hand-edited if necessary. This
6058 also means that tagging creates a new commit. The file
6061 also means that tagging creates a new commit. The file
6059 ".hg/localtags" is used for local tags (not shared among
6062 ".hg/localtags" is used for local tags (not shared among
6060 repositories).
6063 repositories).
6061
6064
6062 Tag commits are usually made at the head of a branch. If the parent
6065 Tag commits are usually made at the head of a branch. If the parent
6063 of the working directory is not a branch head, :hg:`tag` aborts; use
6066 of the working directory is not a branch head, :hg:`tag` aborts; use
6064 -f/--force to force the tag commit to be based on a non-head
6067 -f/--force to force the tag commit to be based on a non-head
6065 changeset.
6068 changeset.
6066
6069
6067 See :hg:`help dates` for a list of formats valid for -d/--date.
6070 See :hg:`help dates` for a list of formats valid for -d/--date.
6068
6071
6069 Since tag names have priority over branch names during revision
6072 Since tag names have priority over branch names during revision
6070 lookup, using an existing branch name as a tag name is discouraged.
6073 lookup, using an existing branch name as a tag name is discouraged.
6071
6074
6072 Returns 0 on success.
6075 Returns 0 on success.
6073 """
6076 """
6074 wlock = lock = None
6077 wlock = lock = None
6075 try:
6078 try:
6076 wlock = repo.wlock()
6079 wlock = repo.wlock()
6077 lock = repo.lock()
6080 lock = repo.lock()
6078 rev_ = "."
6081 rev_ = "."
6079 names = [t.strip() for t in (name1,) + names]
6082 names = [t.strip() for t in (name1,) + names]
6080 if len(names) != len(set(names)):
6083 if len(names) != len(set(names)):
6081 raise util.Abort(_('tag names must be unique'))
6084 raise util.Abort(_('tag names must be unique'))
6082 for n in names:
6085 for n in names:
6083 scmutil.checknewlabel(repo, n, 'tag')
6086 scmutil.checknewlabel(repo, n, 'tag')
6084 if not n:
6087 if not n:
6085 raise util.Abort(_('tag names cannot consist entirely of '
6088 raise util.Abort(_('tag names cannot consist entirely of '
6086 'whitespace'))
6089 'whitespace'))
6087 if opts.get('rev') and opts.get('remove'):
6090 if opts.get('rev') and opts.get('remove'):
6088 raise util.Abort(_("--rev and --remove are incompatible"))
6091 raise util.Abort(_("--rev and --remove are incompatible"))
6089 if opts.get('rev'):
6092 if opts.get('rev'):
6090 rev_ = opts['rev']
6093 rev_ = opts['rev']
6091 message = opts.get('message')
6094 message = opts.get('message')
6092 if opts.get('remove'):
6095 if opts.get('remove'):
6093 if opts.get('local'):
6096 if opts.get('local'):
6094 expectedtype = 'local'
6097 expectedtype = 'local'
6095 else:
6098 else:
6096 expectedtype = 'global'
6099 expectedtype = 'global'
6097
6100
6098 for n in names:
6101 for n in names:
6099 if not repo.tagtype(n):
6102 if not repo.tagtype(n):
6100 raise util.Abort(_("tag '%s' does not exist") % n)
6103 raise util.Abort(_("tag '%s' does not exist") % n)
6101 if repo.tagtype(n) != expectedtype:
6104 if repo.tagtype(n) != expectedtype:
6102 if expectedtype == 'global':
6105 if expectedtype == 'global':
6103 raise util.Abort(_("tag '%s' is not a global tag") % n)
6106 raise util.Abort(_("tag '%s' is not a global tag") % n)
6104 else:
6107 else:
6105 raise util.Abort(_("tag '%s' is not a local tag") % n)
6108 raise util.Abort(_("tag '%s' is not a local tag") % n)
6106 rev_ = nullid
6109 rev_ = nullid
6107 if not message:
6110 if not message:
6108 # we don't translate commit messages
6111 # we don't translate commit messages
6109 message = 'Removed tag %s' % ', '.join(names)
6112 message = 'Removed tag %s' % ', '.join(names)
6110 elif not opts.get('force'):
6113 elif not opts.get('force'):
6111 for n in names:
6114 for n in names:
6112 if n in repo.tags():
6115 if n in repo.tags():
6113 raise util.Abort(_("tag '%s' already exists "
6116 raise util.Abort(_("tag '%s' already exists "
6114 "(use -f to force)") % n)
6117 "(use -f to force)") % n)
6115 if not opts.get('local'):
6118 if not opts.get('local'):
6116 p1, p2 = repo.dirstate.parents()
6119 p1, p2 = repo.dirstate.parents()
6117 if p2 != nullid:
6120 if p2 != nullid:
6118 raise util.Abort(_('uncommitted merge'))
6121 raise util.Abort(_('uncommitted merge'))
6119 bheads = repo.branchheads()
6122 bheads = repo.branchheads()
6120 if not opts.get('force') and bheads and p1 not in bheads:
6123 if not opts.get('force') and bheads and p1 not in bheads:
6121 raise util.Abort(_('not at a branch head (use -f to force)'))
6124 raise util.Abort(_('not at a branch head (use -f to force)'))
6122 r = scmutil.revsingle(repo, rev_).node()
6125 r = scmutil.revsingle(repo, rev_).node()
6123
6126
6124 if not message:
6127 if not message:
6125 # we don't translate commit messages
6128 # we don't translate commit messages
6126 message = ('Added tag %s for changeset %s' %
6129 message = ('Added tag %s for changeset %s' %
6127 (', '.join(names), short(r)))
6130 (', '.join(names), short(r)))
6128
6131
6129 date = opts.get('date')
6132 date = opts.get('date')
6130 if date:
6133 if date:
6131 date = util.parsedate(date)
6134 date = util.parsedate(date)
6132
6135
6133 if opts.get('remove'):
6136 if opts.get('remove'):
6134 editform = 'tag.remove'
6137 editform = 'tag.remove'
6135 else:
6138 else:
6136 editform = 'tag.add'
6139 editform = 'tag.add'
6137 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6140 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6138
6141
6139 # don't allow tagging the null rev
6142 # don't allow tagging the null rev
6140 if (not opts.get('remove') and
6143 if (not opts.get('remove') and
6141 scmutil.revsingle(repo, rev_).rev() == nullrev):
6144 scmutil.revsingle(repo, rev_).rev() == nullrev):
6142 raise util.Abort(_("cannot tag null revision"))
6145 raise util.Abort(_("cannot tag null revision"))
6143
6146
6144 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6147 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6145 editor=editor)
6148 editor=editor)
6146 finally:
6149 finally:
6147 release(lock, wlock)
6150 release(lock, wlock)
6148
6151
6149 @command('tags', formatteropts, '')
6152 @command('tags', formatteropts, '')
6150 def tags(ui, repo, **opts):
6153 def tags(ui, repo, **opts):
6151 """list repository tags
6154 """list repository tags
6152
6155
6153 This lists both regular and local tags. When the -v/--verbose
6156 This lists both regular and local tags. When the -v/--verbose
6154 switch is used, a third column "local" is printed for local tags.
6157 switch is used, a third column "local" is printed for local tags.
6155
6158
6156 Returns 0 on success.
6159 Returns 0 on success.
6157 """
6160 """
6158
6161
6159 fm = ui.formatter('tags', opts)
6162 fm = ui.formatter('tags', opts)
6160 hexfunc = fm.hexfunc
6163 hexfunc = fm.hexfunc
6161 tagtype = ""
6164 tagtype = ""
6162
6165
6163 for t, n in reversed(repo.tagslist()):
6166 for t, n in reversed(repo.tagslist()):
6164 hn = hexfunc(n)
6167 hn = hexfunc(n)
6165 label = 'tags.normal'
6168 label = 'tags.normal'
6166 tagtype = ''
6169 tagtype = ''
6167 if repo.tagtype(t) == 'local':
6170 if repo.tagtype(t) == 'local':
6168 label = 'tags.local'
6171 label = 'tags.local'
6169 tagtype = 'local'
6172 tagtype = 'local'
6170
6173
6171 fm.startitem()
6174 fm.startitem()
6172 fm.write('tag', '%s', t, label=label)
6175 fm.write('tag', '%s', t, label=label)
6173 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6176 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6174 fm.condwrite(not ui.quiet, 'rev node', fmt,
6177 fm.condwrite(not ui.quiet, 'rev node', fmt,
6175 repo.changelog.rev(n), hn, label=label)
6178 repo.changelog.rev(n), hn, label=label)
6176 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6179 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6177 tagtype, label=label)
6180 tagtype, label=label)
6178 fm.plain('\n')
6181 fm.plain('\n')
6179 fm.end()
6182 fm.end()
6180
6183
6181 @command('tip',
6184 @command('tip',
6182 [('p', 'patch', None, _('show patch')),
6185 [('p', 'patch', None, _('show patch')),
6183 ('g', 'git', None, _('use git extended diff format')),
6186 ('g', 'git', None, _('use git extended diff format')),
6184 ] + templateopts,
6187 ] + templateopts,
6185 _('[-p] [-g]'))
6188 _('[-p] [-g]'))
6186 def tip(ui, repo, **opts):
6189 def tip(ui, repo, **opts):
6187 """show the tip revision (DEPRECATED)
6190 """show the tip revision (DEPRECATED)
6188
6191
6189 The tip revision (usually just called the tip) is the changeset
6192 The tip revision (usually just called the tip) is the changeset
6190 most recently added to the repository (and therefore the most
6193 most recently added to the repository (and therefore the most
6191 recently changed head).
6194 recently changed head).
6192
6195
6193 If you have just made a commit, that commit will be the tip. If
6196 If you have just made a commit, that commit will be the tip. If
6194 you have just pulled changes from another repository, the tip of
6197 you have just pulled changes from another repository, the tip of
6195 that repository becomes the current tip. The "tip" tag is special
6198 that repository becomes the current tip. The "tip" tag is special
6196 and cannot be renamed or assigned to a different changeset.
6199 and cannot be renamed or assigned to a different changeset.
6197
6200
6198 This command is deprecated, please use :hg:`heads` instead.
6201 This command is deprecated, please use :hg:`heads` instead.
6199
6202
6200 Returns 0 on success.
6203 Returns 0 on success.
6201 """
6204 """
6202 displayer = cmdutil.show_changeset(ui, repo, opts)
6205 displayer = cmdutil.show_changeset(ui, repo, opts)
6203 displayer.show(repo['tip'])
6206 displayer.show(repo['tip'])
6204 displayer.close()
6207 displayer.close()
6205
6208
6206 @command('unbundle',
6209 @command('unbundle',
6207 [('u', 'update', None,
6210 [('u', 'update', None,
6208 _('update to new branch head if changesets were unbundled'))],
6211 _('update to new branch head if changesets were unbundled'))],
6209 _('[-u] FILE...'))
6212 _('[-u] FILE...'))
6210 def unbundle(ui, repo, fname1, *fnames, **opts):
6213 def unbundle(ui, repo, fname1, *fnames, **opts):
6211 """apply one or more changegroup files
6214 """apply one or more changegroup files
6212
6215
6213 Apply one or more compressed changegroup files generated by the
6216 Apply one or more compressed changegroup files generated by the
6214 bundle command.
6217 bundle command.
6215
6218
6216 Returns 0 on success, 1 if an update has unresolved files.
6219 Returns 0 on success, 1 if an update has unresolved files.
6217 """
6220 """
6218 fnames = (fname1,) + fnames
6221 fnames = (fname1,) + fnames
6219
6222
6220 lock = repo.lock()
6223 lock = repo.lock()
6221 try:
6224 try:
6222 for fname in fnames:
6225 for fname in fnames:
6223 f = hg.openpath(ui, fname)
6226 f = hg.openpath(ui, fname)
6224 gen = exchange.readbundle(ui, f, fname)
6227 gen = exchange.readbundle(ui, f, fname)
6225 if isinstance(gen, bundle2.unbundle20):
6228 if isinstance(gen, bundle2.unbundle20):
6226 tr = repo.transaction('unbundle')
6229 tr = repo.transaction('unbundle')
6227 try:
6230 try:
6228 op = bundle2.processbundle(repo, gen, lambda: tr)
6231 op = bundle2.processbundle(repo, gen, lambda: tr)
6229 tr.close()
6232 tr.close()
6230 finally:
6233 finally:
6231 if tr:
6234 if tr:
6232 tr.release()
6235 tr.release()
6233 changes = [r.get('result', 0)
6236 changes = [r.get('result', 0)
6234 for r in op.records['changegroup']]
6237 for r in op.records['changegroup']]
6235 modheads = changegroup.combineresults(changes)
6238 modheads = changegroup.combineresults(changes)
6236 else:
6239 else:
6237 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6240 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6238 'bundle:' + fname)
6241 'bundle:' + fname)
6239 finally:
6242 finally:
6240 lock.release()
6243 lock.release()
6241
6244
6242 return postincoming(ui, repo, modheads, opts.get('update'), None)
6245 return postincoming(ui, repo, modheads, opts.get('update'), None)
6243
6246
6244 @command('^update|up|checkout|co',
6247 @command('^update|up|checkout|co',
6245 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6248 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6246 ('c', 'check', None,
6249 ('c', 'check', None,
6247 _('update across branches if no uncommitted changes')),
6250 _('update across branches if no uncommitted changes')),
6248 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6251 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6249 ('r', 'rev', '', _('revision'), _('REV'))
6252 ('r', 'rev', '', _('revision'), _('REV'))
6250 ] + mergetoolopts,
6253 ] + mergetoolopts,
6251 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6254 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6252 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6255 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6253 tool=None):
6256 tool=None):
6254 """update working directory (or switch revisions)
6257 """update working directory (or switch revisions)
6255
6258
6256 Update the repository's working directory to the specified
6259 Update the repository's working directory to the specified
6257 changeset. If no changeset is specified, update to the tip of the
6260 changeset. If no changeset is specified, update to the tip of the
6258 current named branch and move the current bookmark (see :hg:`help
6261 current named branch and move the current bookmark (see :hg:`help
6259 bookmarks`).
6262 bookmarks`).
6260
6263
6261 Update sets the working directory's parent revision to the specified
6264 Update sets the working directory's parent revision to the specified
6262 changeset (see :hg:`help parents`).
6265 changeset (see :hg:`help parents`).
6263
6266
6264 If the changeset is not a descendant or ancestor of the working
6267 If the changeset is not a descendant or ancestor of the working
6265 directory's parent, the update is aborted. With the -c/--check
6268 directory's parent, the update is aborted. With the -c/--check
6266 option, the working directory is checked for uncommitted changes; if
6269 option, the working directory is checked for uncommitted changes; if
6267 none are found, the working directory is updated to the specified
6270 none are found, the working directory is updated to the specified
6268 changeset.
6271 changeset.
6269
6272
6270 .. container:: verbose
6273 .. container:: verbose
6271
6274
6272 The following rules apply when the working directory contains
6275 The following rules apply when the working directory contains
6273 uncommitted changes:
6276 uncommitted changes:
6274
6277
6275 1. If neither -c/--check nor -C/--clean is specified, and if
6278 1. If neither -c/--check nor -C/--clean is specified, and if
6276 the requested changeset is an ancestor or descendant of
6279 the requested changeset is an ancestor or descendant of
6277 the working directory's parent, the uncommitted changes
6280 the working directory's parent, the uncommitted changes
6278 are merged into the requested changeset and the merged
6281 are merged into the requested changeset and the merged
6279 result is left uncommitted. If the requested changeset is
6282 result is left uncommitted. If the requested changeset is
6280 not an ancestor or descendant (that is, it is on another
6283 not an ancestor or descendant (that is, it is on another
6281 branch), the update is aborted and the uncommitted changes
6284 branch), the update is aborted and the uncommitted changes
6282 are preserved.
6285 are preserved.
6283
6286
6284 2. With the -c/--check option, the update is aborted and the
6287 2. With the -c/--check option, the update is aborted and the
6285 uncommitted changes are preserved.
6288 uncommitted changes are preserved.
6286
6289
6287 3. With the -C/--clean option, uncommitted changes are discarded and
6290 3. With the -C/--clean option, uncommitted changes are discarded and
6288 the working directory is updated to the requested changeset.
6291 the working directory is updated to the requested changeset.
6289
6292
6290 To cancel an uncommitted merge (and lose your changes), use
6293 To cancel an uncommitted merge (and lose your changes), use
6291 :hg:`update --clean .`.
6294 :hg:`update --clean .`.
6292
6295
6293 Use null as the changeset to remove the working directory (like
6296 Use null as the changeset to remove the working directory (like
6294 :hg:`clone -U`).
6297 :hg:`clone -U`).
6295
6298
6296 If you want to revert just one file to an older revision, use
6299 If you want to revert just one file to an older revision, use
6297 :hg:`revert [-r REV] NAME`.
6300 :hg:`revert [-r REV] NAME`.
6298
6301
6299 See :hg:`help dates` for a list of formats valid for -d/--date.
6302 See :hg:`help dates` for a list of formats valid for -d/--date.
6300
6303
6301 Returns 0 on success, 1 if there are unresolved files.
6304 Returns 0 on success, 1 if there are unresolved files.
6302 """
6305 """
6303 if rev and node:
6306 if rev and node:
6304 raise util.Abort(_("please specify just one revision"))
6307 raise util.Abort(_("please specify just one revision"))
6305
6308
6306 if rev is None or rev == '':
6309 if rev is None or rev == '':
6307 rev = node
6310 rev = node
6308
6311
6309 cmdutil.clearunfinished(repo)
6312 cmdutil.clearunfinished(repo)
6310
6313
6311 # with no argument, we also move the current bookmark, if any
6314 # with no argument, we also move the current bookmark, if any
6312 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6315 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6313
6316
6314 # if we defined a bookmark, we have to remember the original bookmark name
6317 # if we defined a bookmark, we have to remember the original bookmark name
6315 brev = rev
6318 brev = rev
6316 rev = scmutil.revsingle(repo, rev, rev).rev()
6319 rev = scmutil.revsingle(repo, rev, rev).rev()
6317
6320
6318 if check and clean:
6321 if check and clean:
6319 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6322 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6320
6323
6321 if date:
6324 if date:
6322 if rev is not None:
6325 if rev is not None:
6323 raise util.Abort(_("you can't specify a revision and a date"))
6326 raise util.Abort(_("you can't specify a revision and a date"))
6324 rev = cmdutil.finddate(ui, repo, date)
6327 rev = cmdutil.finddate(ui, repo, date)
6325
6328
6326 if check:
6329 if check:
6327 c = repo[None]
6330 c = repo[None]
6328 if c.dirty(merge=False, branch=False, missing=True):
6331 if c.dirty(merge=False, branch=False, missing=True):
6329 raise util.Abort(_("uncommitted changes"))
6332 raise util.Abort(_("uncommitted changes"))
6330 if rev is None:
6333 if rev is None:
6331 rev = repo[repo[None].branch()].rev()
6334 rev = repo[repo[None].branch()].rev()
6332
6335
6333 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6336 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6334
6337
6335 if clean:
6338 if clean:
6336 ret = hg.clean(repo, rev)
6339 ret = hg.clean(repo, rev)
6337 else:
6340 else:
6338 ret = hg.update(repo, rev)
6341 ret = hg.update(repo, rev)
6339
6342
6340 if not ret and movemarkfrom:
6343 if not ret and movemarkfrom:
6341 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6344 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6342 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6345 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6343 elif brev in repo._bookmarks:
6346 elif brev in repo._bookmarks:
6344 bookmarks.setcurrent(repo, brev)
6347 bookmarks.setcurrent(repo, brev)
6345 ui.status(_("(activating bookmark %s)\n") % brev)
6348 ui.status(_("(activating bookmark %s)\n") % brev)
6346 elif brev:
6349 elif brev:
6347 if repo._bookmarkcurrent:
6350 if repo._bookmarkcurrent:
6348 ui.status(_("(leaving bookmark %s)\n") %
6351 ui.status(_("(leaving bookmark %s)\n") %
6349 repo._bookmarkcurrent)
6352 repo._bookmarkcurrent)
6350 bookmarks.unsetcurrent(repo)
6353 bookmarks.unsetcurrent(repo)
6351
6354
6352 return ret
6355 return ret
6353
6356
6354 @command('verify', [])
6357 @command('verify', [])
6355 def verify(ui, repo):
6358 def verify(ui, repo):
6356 """verify the integrity of the repository
6359 """verify the integrity of the repository
6357
6360
6358 Verify the integrity of the current repository.
6361 Verify the integrity of the current repository.
6359
6362
6360 This will perform an extensive check of the repository's
6363 This will perform an extensive check of the repository's
6361 integrity, validating the hashes and checksums of each entry in
6364 integrity, validating the hashes and checksums of each entry in
6362 the changelog, manifest, and tracked files, as well as the
6365 the changelog, manifest, and tracked files, as well as the
6363 integrity of their crosslinks and indices.
6366 integrity of their crosslinks and indices.
6364
6367
6365 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6368 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6366 for more information about recovery from corruption of the
6369 for more information about recovery from corruption of the
6367 repository.
6370 repository.
6368
6371
6369 Returns 0 on success, 1 if errors are encountered.
6372 Returns 0 on success, 1 if errors are encountered.
6370 """
6373 """
6371 return hg.verify(repo)
6374 return hg.verify(repo)
6372
6375
6373 @command('version', [], norepo=True)
6376 @command('version', [], norepo=True)
6374 def version_(ui):
6377 def version_(ui):
6375 """output version and copyright information"""
6378 """output version and copyright information"""
6376 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6379 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6377 % util.version())
6380 % util.version())
6378 ui.status(_(
6381 ui.status(_(
6379 "(see http://mercurial.selenic.com for more information)\n"
6382 "(see http://mercurial.selenic.com for more information)\n"
6380 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6383 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6381 "This is free software; see the source for copying conditions. "
6384 "This is free software; see the source for copying conditions. "
6382 "There is NO\nwarranty; "
6385 "There is NO\nwarranty; "
6383 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6386 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6384 ))
6387 ))
6385
6388
6386 ui.note(_("\nEnabled extensions:\n\n"))
6389 ui.note(_("\nEnabled extensions:\n\n"))
6387 if ui.verbose:
6390 if ui.verbose:
6388 # format names and versions into columns
6391 # format names and versions into columns
6389 names = []
6392 names = []
6390 vers = []
6393 vers = []
6391 for name, module in extensions.extensions():
6394 for name, module in extensions.extensions():
6392 names.append(name)
6395 names.append(name)
6393 vers.append(extensions.moduleversion(module))
6396 vers.append(extensions.moduleversion(module))
6394 if names:
6397 if names:
6395 maxnamelen = max(len(n) for n in names)
6398 maxnamelen = max(len(n) for n in names)
6396 for i, name in enumerate(names):
6399 for i, name in enumerate(names):
6397 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6400 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,781 +1,789 b''
1 $ hg init a
1 $ hg init a
2 $ cd a
2 $ cd a
3 $ echo foo > t1
3 $ echo foo > t1
4 $ hg add t1
4 $ hg add t1
5 $ hg commit -m "1"
5 $ hg commit -m "1"
6
6
7 $ cd ..
7 $ cd ..
8 $ hg clone a b
8 $ hg clone a b
9 updating to branch default
9 updating to branch default
10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
10 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
11
11
12 $ cd a
12 $ cd a
13 $ echo foo > t2
13 $ echo foo > t2
14 $ hg add t2
14 $ hg add t2
15 $ hg commit -m "2"
15 $ hg commit -m "2"
16
16
17 $ cd ../b
17 $ cd ../b
18 $ echo foo > t3
18 $ echo foo > t3
19 $ hg add t3
19 $ hg add t3
20 $ hg commit -m "3"
20 $ hg commit -m "3"
21
21
22 Specifying a revset that evaluates to null will abort
23
24 $ hg push -r '0 & 1' ../a
25 pushing to ../a
26 abort: specified revisions evaluate to an empty set
27 (use different revision arguments)
28 [255]
29
22 $ hg push ../a
30 $ hg push ../a
23 pushing to ../a
31 pushing to ../a
24 searching for changes
32 searching for changes
25 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
33 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
26 abort: push creates new remote head 1e108cc5548c!
34 abort: push creates new remote head 1e108cc5548c!
27 (pull and merge or see "hg help push" for details about pushing new heads)
35 (pull and merge or see "hg help push" for details about pushing new heads)
28 [255]
36 [255]
29
37
30 $ hg push --debug ../a
38 $ hg push --debug ../a
31 pushing to ../a
39 pushing to ../a
32 query 1; heads
40 query 1; heads
33 searching for changes
41 searching for changes
34 taking quick initial sample
42 taking quick initial sample
35 searching: 2 queries
43 searching: 2 queries
36 query 2; still undecided: 1, sample size is: 1
44 query 2; still undecided: 1, sample size is: 1
37 2 total queries
45 2 total queries
38 listing keys for "phases"
46 listing keys for "phases"
39 checking for updated bookmarks
47 checking for updated bookmarks
40 listing keys for "bookmarks"
48 listing keys for "bookmarks"
41 listing keys for "bookmarks"
49 listing keys for "bookmarks"
42 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
50 remote has heads on branch 'default' that are not known locally: 1c9246a22a0a
43 new remote heads on branch 'default':
51 new remote heads on branch 'default':
44 1e108cc5548c
52 1e108cc5548c
45 abort: push creates new remote head 1e108cc5548c!
53 abort: push creates new remote head 1e108cc5548c!
46 (pull and merge or see "hg help push" for details about pushing new heads)
54 (pull and merge or see "hg help push" for details about pushing new heads)
47 [255]
55 [255]
48
56
49 $ hg pull ../a
57 $ hg pull ../a
50 pulling from ../a
58 pulling from ../a
51 searching for changes
59 searching for changes
52 adding changesets
60 adding changesets
53 adding manifests
61 adding manifests
54 adding file changes
62 adding file changes
55 added 1 changesets with 1 changes to 1 files (+1 heads)
63 added 1 changesets with 1 changes to 1 files (+1 heads)
56 (run 'hg heads' to see heads, 'hg merge' to merge)
64 (run 'hg heads' to see heads, 'hg merge' to merge)
57
65
58 $ hg push ../a
66 $ hg push ../a
59 pushing to ../a
67 pushing to ../a
60 searching for changes
68 searching for changes
61 abort: push creates new remote head 1e108cc5548c!
69 abort: push creates new remote head 1e108cc5548c!
62 (merge or see "hg help push" for details about pushing new heads)
70 (merge or see "hg help push" for details about pushing new heads)
63 [255]
71 [255]
64
72
65 $ hg merge
73 $ hg merge
66 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
74 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
67 (branch merge, don't forget to commit)
75 (branch merge, don't forget to commit)
68
76
69 $ hg commit -m "4"
77 $ hg commit -m "4"
70 $ hg push ../a
78 $ hg push ../a
71 pushing to ../a
79 pushing to ../a
72 searching for changes
80 searching for changes
73 adding changesets
81 adding changesets
74 adding manifests
82 adding manifests
75 adding file changes
83 adding file changes
76 added 2 changesets with 1 changes to 1 files
84 added 2 changesets with 1 changes to 1 files
77
85
78 $ cd ..
86 $ cd ..
79
87
80 $ hg init c
88 $ hg init c
81 $ cd c
89 $ cd c
82 $ for i in 0 1 2; do
90 $ for i in 0 1 2; do
83 > echo $i >> foo
91 > echo $i >> foo
84 > hg ci -Am $i
92 > hg ci -Am $i
85 > done
93 > done
86 adding foo
94 adding foo
87 $ cd ..
95 $ cd ..
88
96
89 $ hg clone c d
97 $ hg clone c d
90 updating to branch default
98 updating to branch default
91 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
92
100
93 $ cd d
101 $ cd d
94 $ for i in 0 1; do
102 $ for i in 0 1; do
95 > hg co -C $i
103 > hg co -C $i
96 > echo d-$i >> foo
104 > echo d-$i >> foo
97 > hg ci -m d-$i
105 > hg ci -m d-$i
98 > done
106 > done
99 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
100 created new head
108 created new head
101 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
109 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
102 created new head
110 created new head
103
111
104 $ HGMERGE=true hg merge 3
112 $ HGMERGE=true hg merge 3
105 merging foo
113 merging foo
106 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
114 0 files updated, 1 files merged, 0 files removed, 0 files unresolved
107 (branch merge, don't forget to commit)
115 (branch merge, don't forget to commit)
108
116
109 $ hg ci -m c-d
117 $ hg ci -m c-d
110
118
111 $ hg push ../c
119 $ hg push ../c
112 pushing to ../c
120 pushing to ../c
113 searching for changes
121 searching for changes
114 abort: push creates new remote head 6346d66eb9f5!
122 abort: push creates new remote head 6346d66eb9f5!
115 (merge or see "hg help push" for details about pushing new heads)
123 (merge or see "hg help push" for details about pushing new heads)
116 [255]
124 [255]
117
125
118 $ hg push -r 2 ../c
126 $ hg push -r 2 ../c
119 pushing to ../c
127 pushing to ../c
120 searching for changes
128 searching for changes
121 no changes found
129 no changes found
122 [1]
130 [1]
123
131
124 $ hg push -r 3 ../c
132 $ hg push -r 3 ../c
125 pushing to ../c
133 pushing to ../c
126 searching for changes
134 searching for changes
127 abort: push creates new remote head a5dda829a167!
135 abort: push creates new remote head a5dda829a167!
128 (merge or see "hg help push" for details about pushing new heads)
136 (merge or see "hg help push" for details about pushing new heads)
129 [255]
137 [255]
130
138
131 $ hg push -v -r 3 -r 4 ../c
139 $ hg push -v -r 3 -r 4 ../c
132 pushing to ../c
140 pushing to ../c
133 searching for changes
141 searching for changes
134 new remote heads on branch 'default':
142 new remote heads on branch 'default':
135 a5dda829a167
143 a5dda829a167
136 ee8fbc7a0295
144 ee8fbc7a0295
137 abort: push creates new remote head a5dda829a167!
145 abort: push creates new remote head a5dda829a167!
138 (merge or see "hg help push" for details about pushing new heads)
146 (merge or see "hg help push" for details about pushing new heads)
139 [255]
147 [255]
140
148
141 $ hg push -v -f -r 3 -r 4 ../c
149 $ hg push -v -f -r 3 -r 4 ../c
142 pushing to ../c
150 pushing to ../c
143 searching for changes
151 searching for changes
144 2 changesets found
152 2 changesets found
145 uncompressed size of bundle content:
153 uncompressed size of bundle content:
146 308 (changelog)
154 308 (changelog)
147 286 (manifests)
155 286 (manifests)
148 213 foo
156 213 foo
149 adding changesets
157 adding changesets
150 adding manifests
158 adding manifests
151 adding file changes
159 adding file changes
152 added 2 changesets with 2 changes to 1 files (+2 heads)
160 added 2 changesets with 2 changes to 1 files (+2 heads)
153
161
154 $ hg push -r 5 ../c
162 $ hg push -r 5 ../c
155 pushing to ../c
163 pushing to ../c
156 searching for changes
164 searching for changes
157 adding changesets
165 adding changesets
158 adding manifests
166 adding manifests
159 adding file changes
167 adding file changes
160 added 1 changesets with 1 changes to 1 files (-1 heads)
168 added 1 changesets with 1 changes to 1 files (-1 heads)
161
169
162 $ hg in ../c
170 $ hg in ../c
163 comparing with ../c
171 comparing with ../c
164 searching for changes
172 searching for changes
165 no changes found
173 no changes found
166 [1]
174 [1]
167
175
168
176
169 Issue450: push -r warns about remote head creation even if no heads
177 Issue450: push -r warns about remote head creation even if no heads
170 will be created
178 will be created
171
179
172 $ hg init ../e
180 $ hg init ../e
173 $ hg push -r 0 ../e
181 $ hg push -r 0 ../e
174 pushing to ../e
182 pushing to ../e
175 searching for changes
183 searching for changes
176 adding changesets
184 adding changesets
177 adding manifests
185 adding manifests
178 adding file changes
186 adding file changes
179 added 1 changesets with 1 changes to 1 files
187 added 1 changesets with 1 changes to 1 files
180
188
181 $ hg push -r 1 ../e
189 $ hg push -r 1 ../e
182 pushing to ../e
190 pushing to ../e
183 searching for changes
191 searching for changes
184 adding changesets
192 adding changesets
185 adding manifests
193 adding manifests
186 adding file changes
194 adding file changes
187 added 1 changesets with 1 changes to 1 files
195 added 1 changesets with 1 changes to 1 files
188
196
189 $ cd ..
197 $ cd ..
190
198
191
199
192 Issue736: named branches are not considered for detection of
200 Issue736: named branches are not considered for detection of
193 unmerged heads in "hg push"
201 unmerged heads in "hg push"
194
202
195 $ hg init f
203 $ hg init f
196 $ cd f
204 $ cd f
197 $ hg -q branch a
205 $ hg -q branch a
198 $ echo 0 > foo
206 $ echo 0 > foo
199 $ hg -q ci -Am 0
207 $ hg -q ci -Am 0
200 $ echo 1 > foo
208 $ echo 1 > foo
201 $ hg -q ci -m 1
209 $ hg -q ci -m 1
202 $ hg -q up 0
210 $ hg -q up 0
203 $ echo 2 > foo
211 $ echo 2 > foo
204 $ hg -q ci -m 2
212 $ hg -q ci -m 2
205 $ hg -q up 0
213 $ hg -q up 0
206 $ hg -q branch b
214 $ hg -q branch b
207 $ echo 3 > foo
215 $ echo 3 > foo
208 $ hg -q ci -m 3
216 $ hg -q ci -m 3
209 $ cd ..
217 $ cd ..
210
218
211 $ hg -q clone f g
219 $ hg -q clone f g
212 $ cd g
220 $ cd g
213
221
214 Push on existing branch and new branch:
222 Push on existing branch and new branch:
215
223
216 $ hg -q up 1
224 $ hg -q up 1
217 $ echo 4 > foo
225 $ echo 4 > foo
218 $ hg -q ci -m 4
226 $ hg -q ci -m 4
219 $ hg -q up 0
227 $ hg -q up 0
220 $ echo 5 > foo
228 $ echo 5 > foo
221 $ hg -q branch c
229 $ hg -q branch c
222 $ hg -q ci -m 5
230 $ hg -q ci -m 5
223
231
224 $ hg push ../f
232 $ hg push ../f
225 pushing to ../f
233 pushing to ../f
226 searching for changes
234 searching for changes
227 abort: push creates new remote branches: c!
235 abort: push creates new remote branches: c!
228 (use 'hg push --new-branch' to create new remote branches)
236 (use 'hg push --new-branch' to create new remote branches)
229 [255]
237 [255]
230
238
231 $ hg push -r 4 -r 5 ../f
239 $ hg push -r 4 -r 5 ../f
232 pushing to ../f
240 pushing to ../f
233 searching for changes
241 searching for changes
234 abort: push creates new remote branches: c!
242 abort: push creates new remote branches: c!
235 (use 'hg push --new-branch' to create new remote branches)
243 (use 'hg push --new-branch' to create new remote branches)
236 [255]
244 [255]
237
245
238
246
239 Multiple new branches:
247 Multiple new branches:
240
248
241 $ hg -q branch d
249 $ hg -q branch d
242 $ echo 6 > foo
250 $ echo 6 > foo
243 $ hg -q ci -m 6
251 $ hg -q ci -m 6
244
252
245 $ hg push ../f
253 $ hg push ../f
246 pushing to ../f
254 pushing to ../f
247 searching for changes
255 searching for changes
248 abort: push creates new remote branches: c, d!
256 abort: push creates new remote branches: c, d!
249 (use 'hg push --new-branch' to create new remote branches)
257 (use 'hg push --new-branch' to create new remote branches)
250 [255]
258 [255]
251
259
252 $ hg push -r 4 -r 6 ../f
260 $ hg push -r 4 -r 6 ../f
253 pushing to ../f
261 pushing to ../f
254 searching for changes
262 searching for changes
255 abort: push creates new remote branches: c, d!
263 abort: push creates new remote branches: c, d!
256 (use 'hg push --new-branch' to create new remote branches)
264 (use 'hg push --new-branch' to create new remote branches)
257 [255]
265 [255]
258
266
259 $ cd ../g
267 $ cd ../g
260
268
261
269
262 Fail on multiple head push:
270 Fail on multiple head push:
263
271
264 $ hg -q up 1
272 $ hg -q up 1
265 $ echo 7 > foo
273 $ echo 7 > foo
266 $ hg -q ci -m 7
274 $ hg -q ci -m 7
267
275
268 $ hg push -r 4 -r 7 ../f
276 $ hg push -r 4 -r 7 ../f
269 pushing to ../f
277 pushing to ../f
270 searching for changes
278 searching for changes
271 abort: push creates new remote head 0b715ef6ff8f on branch 'a'!
279 abort: push creates new remote head 0b715ef6ff8f on branch 'a'!
272 (merge or see "hg help push" for details about pushing new heads)
280 (merge or see "hg help push" for details about pushing new heads)
273 [255]
281 [255]
274
282
275 Push replacement head on existing branches:
283 Push replacement head on existing branches:
276
284
277 $ hg -q up 3
285 $ hg -q up 3
278 $ echo 8 > foo
286 $ echo 8 > foo
279 $ hg -q ci -m 8
287 $ hg -q ci -m 8
280
288
281 $ hg push -r 7 -r 8 ../f
289 $ hg push -r 7 -r 8 ../f
282 pushing to ../f
290 pushing to ../f
283 searching for changes
291 searching for changes
284 adding changesets
292 adding changesets
285 adding manifests
293 adding manifests
286 adding file changes
294 adding file changes
287 added 2 changesets with 2 changes to 1 files
295 added 2 changesets with 2 changes to 1 files
288
296
289
297
290 Merge of branch a to other branch b followed by unrelated push
298 Merge of branch a to other branch b followed by unrelated push
291 on branch a:
299 on branch a:
292
300
293 $ hg -q up 7
301 $ hg -q up 7
294 $ HGMERGE=true hg -q merge 8
302 $ HGMERGE=true hg -q merge 8
295 $ hg -q ci -m 9
303 $ hg -q ci -m 9
296 $ hg -q up 8
304 $ hg -q up 8
297 $ echo 10 > foo
305 $ echo 10 > foo
298 $ hg -q ci -m 10
306 $ hg -q ci -m 10
299
307
300 $ hg push -r 9 ../f
308 $ hg push -r 9 ../f
301 pushing to ../f
309 pushing to ../f
302 searching for changes
310 searching for changes
303 adding changesets
311 adding changesets
304 adding manifests
312 adding manifests
305 adding file changes
313 adding file changes
306 added 1 changesets with 1 changes to 1 files (-1 heads)
314 added 1 changesets with 1 changes to 1 files (-1 heads)
307
315
308 $ hg push -r 10 ../f
316 $ hg push -r 10 ../f
309 pushing to ../f
317 pushing to ../f
310 searching for changes
318 searching for changes
311 adding changesets
319 adding changesets
312 adding manifests
320 adding manifests
313 adding file changes
321 adding file changes
314 added 1 changesets with 1 changes to 1 files (+1 heads)
322 added 1 changesets with 1 changes to 1 files (+1 heads)
315
323
316
324
317 Cheating the counting algorithm:
325 Cheating the counting algorithm:
318
326
319 $ hg -q up 9
327 $ hg -q up 9
320 $ HGMERGE=true hg -q merge 2
328 $ HGMERGE=true hg -q merge 2
321 $ hg -q ci -m 11
329 $ hg -q ci -m 11
322 $ hg -q up 1
330 $ hg -q up 1
323 $ echo 12 > foo
331 $ echo 12 > foo
324 $ hg -q ci -m 12
332 $ hg -q ci -m 12
325
333
326 $ hg push -r 11 -r 12 ../f
334 $ hg push -r 11 -r 12 ../f
327 pushing to ../f
335 pushing to ../f
328 searching for changes
336 searching for changes
329 adding changesets
337 adding changesets
330 adding manifests
338 adding manifests
331 adding file changes
339 adding file changes
332 added 2 changesets with 2 changes to 1 files
340 added 2 changesets with 2 changes to 1 files
333
341
334
342
335 Failed push of new named branch:
343 Failed push of new named branch:
336
344
337 $ echo 12 > foo
345 $ echo 12 > foo
338 $ hg -q ci -m 12a
346 $ hg -q ci -m 12a
339 [1]
347 [1]
340 $ hg -q up 11
348 $ hg -q up 11
341 $ echo 13 > foo
349 $ echo 13 > foo
342 $ hg -q branch e
350 $ hg -q branch e
343 $ hg -q ci -m 13d
351 $ hg -q ci -m 13d
344
352
345 $ hg push -r 12 -r 13 ../f
353 $ hg push -r 12 -r 13 ../f
346 pushing to ../f
354 pushing to ../f
347 searching for changes
355 searching for changes
348 abort: push creates new remote branches: e!
356 abort: push creates new remote branches: e!
349 (use 'hg push --new-branch' to create new remote branches)
357 (use 'hg push --new-branch' to create new remote branches)
350 [255]
358 [255]
351
359
352
360
353 Using --new-branch to push new named branch:
361 Using --new-branch to push new named branch:
354
362
355 $ hg push --new-branch -r 12 -r 13 ../f
363 $ hg push --new-branch -r 12 -r 13 ../f
356 pushing to ../f
364 pushing to ../f
357 searching for changes
365 searching for changes
358 adding changesets
366 adding changesets
359 adding manifests
367 adding manifests
360 adding file changes
368 adding file changes
361 added 1 changesets with 1 changes to 1 files
369 added 1 changesets with 1 changes to 1 files
362
370
363 Pushing multi headed new branch:
371 Pushing multi headed new branch:
364
372
365 $ echo 14 > foo
373 $ echo 14 > foo
366 $ hg -q branch f
374 $ hg -q branch f
367 $ hg -q ci -m 14
375 $ hg -q ci -m 14
368 $ echo 15 > foo
376 $ echo 15 > foo
369 $ hg -q ci -m 15
377 $ hg -q ci -m 15
370 $ hg -q up 14
378 $ hg -q up 14
371 $ echo 16 > foo
379 $ echo 16 > foo
372 $ hg -q ci -m 16
380 $ hg -q ci -m 16
373 $ hg push --branch f --new-branch ../f
381 $ hg push --branch f --new-branch ../f
374 pushing to ../f
382 pushing to ../f
375 searching for changes
383 searching for changes
376 abort: push creates new branch 'f' with multiple heads
384 abort: push creates new branch 'f' with multiple heads
377 (merge or see "hg help push" for details about pushing new heads)
385 (merge or see "hg help push" for details about pushing new heads)
378 [255]
386 [255]
379 $ hg push --branch f --new-branch --force ../f
387 $ hg push --branch f --new-branch --force ../f
380 pushing to ../f
388 pushing to ../f
381 searching for changes
389 searching for changes
382 adding changesets
390 adding changesets
383 adding manifests
391 adding manifests
384 adding file changes
392 adding file changes
385 added 3 changesets with 3 changes to 1 files (+1 heads)
393 added 3 changesets with 3 changes to 1 files (+1 heads)
386
394
387 Checking prepush logic does not allow silently pushing
395 Checking prepush logic does not allow silently pushing
388 multiple new heads but also doesn't report too many heads:
396 multiple new heads but also doesn't report too many heads:
389
397
390 $ cd ..
398 $ cd ..
391 $ hg init h
399 $ hg init h
392 $ echo init > h/init
400 $ echo init > h/init
393 $ hg -R h ci -Am init
401 $ hg -R h ci -Am init
394 adding init
402 adding init
395 $ echo a > h/a
403 $ echo a > h/a
396 $ hg -R h ci -Am a
404 $ hg -R h ci -Am a
397 adding a
405 adding a
398 $ hg clone h i
406 $ hg clone h i
399 updating to branch default
407 updating to branch default
400 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
408 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
401 $ hg -R h up 0
409 $ hg -R h up 0
402 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
410 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
403 $ echo b > h/b
411 $ echo b > h/b
404 $ hg -R h ci -Am b
412 $ hg -R h ci -Am b
405 adding b
413 adding b
406 created new head
414 created new head
407 $ hg -R i up 0
415 $ hg -R i up 0
408 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
416 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
409 $ echo c > i/c
417 $ echo c > i/c
410 $ hg -R i ci -Am c
418 $ hg -R i ci -Am c
411 adding c
419 adding c
412 created new head
420 created new head
413
421
414 $ for i in `python $TESTDIR/seq.py 3`; do hg -R h up -q 0; echo $i > h/b; hg -R h ci -qAm$i; done
422 $ for i in `python $TESTDIR/seq.py 3`; do hg -R h up -q 0; echo $i > h/b; hg -R h ci -qAm$i; done
415
423
416 $ hg -R i push h
424 $ hg -R i push h
417 pushing to h
425 pushing to h
418 searching for changes
426 searching for changes
419 remote has heads on branch 'default' that are not known locally: 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
427 remote has heads on branch 'default' that are not known locally: 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
420 abort: push creates new remote head 97bd0c84d346!
428 abort: push creates new remote head 97bd0c84d346!
421 (pull and merge or see "hg help push" for details about pushing new heads)
429 (pull and merge or see "hg help push" for details about pushing new heads)
422 [255]
430 [255]
423 $ hg -R h up -q 0; echo x > h/b; hg -R h ci -qAmx
431 $ hg -R h up -q 0; echo x > h/b; hg -R h ci -qAmx
424 $ hg -R i push h
432 $ hg -R i push h
425 pushing to h
433 pushing to h
426 searching for changes
434 searching for changes
427 remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 and 1 others
435 remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 and 1 others
428 abort: push creates new remote head 97bd0c84d346!
436 abort: push creates new remote head 97bd0c84d346!
429 (pull and merge or see "hg help push" for details about pushing new heads)
437 (pull and merge or see "hg help push" for details about pushing new heads)
430 [255]
438 [255]
431 $ hg -R i push h -v
439 $ hg -R i push h -v
432 pushing to h
440 pushing to h
433 searching for changes
441 searching for changes
434 remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
442 remote has heads on branch 'default' that are not known locally: 18ddb72c4590 534543e22c29 764f8ec07b96 afe7cc7679f5 ce4212fc8847
435 new remote heads on branch 'default':
443 new remote heads on branch 'default':
436 97bd0c84d346
444 97bd0c84d346
437 abort: push creates new remote head 97bd0c84d346!
445 abort: push creates new remote head 97bd0c84d346!
438 (pull and merge or see "hg help push" for details about pushing new heads)
446 (pull and merge or see "hg help push" for details about pushing new heads)
439 [255]
447 [255]
440
448
441
449
442 Check prepush logic with merged branches:
450 Check prepush logic with merged branches:
443
451
444 $ hg init j
452 $ hg init j
445 $ hg -R j branch a
453 $ hg -R j branch a
446 marked working directory as branch a
454 marked working directory as branch a
447 (branches are permanent and global, did you want a bookmark?)
455 (branches are permanent and global, did you want a bookmark?)
448 $ echo init > j/foo
456 $ echo init > j/foo
449 $ hg -R j ci -Am init
457 $ hg -R j ci -Am init
450 adding foo
458 adding foo
451 $ hg clone j k
459 $ hg clone j k
452 updating to branch a
460 updating to branch a
453 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
461 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
454 $ echo a1 > j/foo
462 $ echo a1 > j/foo
455 $ hg -R j ci -m a1
463 $ hg -R j ci -m a1
456 $ hg -R k branch b
464 $ hg -R k branch b
457 marked working directory as branch b
465 marked working directory as branch b
458 (branches are permanent and global, did you want a bookmark?)
466 (branches are permanent and global, did you want a bookmark?)
459 $ echo b > k/foo
467 $ echo b > k/foo
460 $ hg -R k ci -m b
468 $ hg -R k ci -m b
461 $ hg -R k up 0
469 $ hg -R k up 0
462 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
470 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
463
471
464 $ hg -R k merge b
472 $ hg -R k merge b
465 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
473 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
466 (branch merge, don't forget to commit)
474 (branch merge, don't forget to commit)
467
475
468 $ hg -R k ci -m merge
476 $ hg -R k ci -m merge
469
477
470 $ hg -R k push -r a j
478 $ hg -R k push -r a j
471 pushing to j
479 pushing to j
472 searching for changes
480 searching for changes
473 abort: push creates new remote branches: b!
481 abort: push creates new remote branches: b!
474 (use 'hg push --new-branch' to create new remote branches)
482 (use 'hg push --new-branch' to create new remote branches)
475 [255]
483 [255]
476
484
477
485
478 Prepush -r should not allow you to sneak in new heads:
486 Prepush -r should not allow you to sneak in new heads:
479
487
480 $ hg init l
488 $ hg init l
481 $ cd l
489 $ cd l
482 $ echo a >> foo
490 $ echo a >> foo
483 $ hg -q add foo
491 $ hg -q add foo
484 $ hg -q branch a
492 $ hg -q branch a
485 $ hg -q ci -ma
493 $ hg -q ci -ma
486 $ hg -q up null
494 $ hg -q up null
487 $ echo a >> foo
495 $ echo a >> foo
488 $ hg -q add foo
496 $ hg -q add foo
489 $ hg -q branch b
497 $ hg -q branch b
490 $ hg -q ci -mb
498 $ hg -q ci -mb
491 $ cd ..
499 $ cd ..
492 $ hg -q clone l m -u a
500 $ hg -q clone l m -u a
493 $ cd m
501 $ cd m
494 $ hg -q merge b
502 $ hg -q merge b
495 $ hg -q ci -mmb
503 $ hg -q ci -mmb
496 $ hg -q up 0
504 $ hg -q up 0
497 $ echo a >> foo
505 $ echo a >> foo
498 $ hg -q ci -ma2
506 $ hg -q ci -ma2
499 $ hg -q up 2
507 $ hg -q up 2
500 $ echo a >> foo
508 $ echo a >> foo
501 $ hg -q branch -f b
509 $ hg -q branch -f b
502 $ hg -q ci -mb2
510 $ hg -q ci -mb2
503 $ hg -q merge 3
511 $ hg -q merge 3
504 $ hg -q ci -mma
512 $ hg -q ci -mma
505
513
506 $ hg push ../l -b b
514 $ hg push ../l -b b
507 pushing to ../l
515 pushing to ../l
508 searching for changes
516 searching for changes
509 abort: push creates new remote head 451211cc22b0 on branch 'a'!
517 abort: push creates new remote head 451211cc22b0 on branch 'a'!
510 (merge or see "hg help push" for details about pushing new heads)
518 (merge or see "hg help push" for details about pushing new heads)
511 [255]
519 [255]
512
520
513 $ cd ..
521 $ cd ..
514
522
515
523
516 Check prepush with new branch head on former topo non-head:
524 Check prepush with new branch head on former topo non-head:
517
525
518 $ hg init n
526 $ hg init n
519 $ cd n
527 $ cd n
520 $ hg branch A
528 $ hg branch A
521 marked working directory as branch A
529 marked working directory as branch A
522 (branches are permanent and global, did you want a bookmark?)
530 (branches are permanent and global, did you want a bookmark?)
523 $ echo a >a
531 $ echo a >a
524 $ hg ci -Ama
532 $ hg ci -Ama
525 adding a
533 adding a
526 $ hg branch B
534 $ hg branch B
527 marked working directory as branch B
535 marked working directory as branch B
528 (branches are permanent and global, did you want a bookmark?)
536 (branches are permanent and global, did you want a bookmark?)
529 $ echo b >b
537 $ echo b >b
530 $ hg ci -Amb
538 $ hg ci -Amb
531 adding b
539 adding b
532
540
533 b is now branch head of B, and a topological head
541 b is now branch head of B, and a topological head
534 a is now branch head of A, but not a topological head
542 a is now branch head of A, but not a topological head
535
543
536 $ hg clone . inner
544 $ hg clone . inner
537 updating to branch B
545 updating to branch B
538 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
546 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
539 $ cd inner
547 $ cd inner
540 $ hg up B
548 $ hg up B
541 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
549 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
542 $ echo b1 >b1
550 $ echo b1 >b1
543 $ hg ci -Amb1
551 $ hg ci -Amb1
544 adding b1
552 adding b1
545
553
546 in the clone b1 is now the head of B
554 in the clone b1 is now the head of B
547
555
548 $ cd ..
556 $ cd ..
549 $ hg up 0
557 $ hg up 0
550 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
558 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
551 $ echo a2 >a2
559 $ echo a2 >a2
552 $ hg ci -Ama2
560 $ hg ci -Ama2
553 adding a2
561 adding a2
554
562
555 a2 is now the new branch head of A, and a new topological head
563 a2 is now the new branch head of A, and a new topological head
556 it replaces a former inner branch head, so it should at most warn about
564 it replaces a former inner branch head, so it should at most warn about
557 A, not B
565 A, not B
558
566
559 glog of local:
567 glog of local:
560
568
561 $ hg log -G --template "{rev}: {branches} {desc}\n"
569 $ hg log -G --template "{rev}: {branches} {desc}\n"
562 @ 2: A a2
570 @ 2: A a2
563 |
571 |
564 | o 1: B b
572 | o 1: B b
565 |/
573 |/
566 o 0: A a
574 o 0: A a
567
575
568 glog of remote:
576 glog of remote:
569
577
570 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
578 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
571 @ 2: B b1
579 @ 2: B b1
572 |
580 |
573 o 1: B b
581 o 1: B b
574 |
582 |
575 o 0: A a
583 o 0: A a
576
584
577 outgoing:
585 outgoing:
578
586
579 $ hg out inner --template "{rev}: {branches} {desc}\n"
587 $ hg out inner --template "{rev}: {branches} {desc}\n"
580 comparing with inner
588 comparing with inner
581 searching for changes
589 searching for changes
582 2: A a2
590 2: A a2
583
591
584 $ hg push inner
592 $ hg push inner
585 pushing to inner
593 pushing to inner
586 searching for changes
594 searching for changes
587 adding changesets
595 adding changesets
588 adding manifests
596 adding manifests
589 adding file changes
597 adding file changes
590 added 1 changesets with 1 changes to 1 files (+1 heads)
598 added 1 changesets with 1 changes to 1 files (+1 heads)
591
599
592 $ cd ..
600 $ cd ..
593
601
594
602
595 Check prepush with new branch head on former topo head:
603 Check prepush with new branch head on former topo head:
596
604
597 $ hg init o
605 $ hg init o
598 $ cd o
606 $ cd o
599 $ hg branch A
607 $ hg branch A
600 marked working directory as branch A
608 marked working directory as branch A
601 (branches are permanent and global, did you want a bookmark?)
609 (branches are permanent and global, did you want a bookmark?)
602 $ echo a >a
610 $ echo a >a
603 $ hg ci -Ama
611 $ hg ci -Ama
604 adding a
612 adding a
605 $ hg branch B
613 $ hg branch B
606 marked working directory as branch B
614 marked working directory as branch B
607 (branches are permanent and global, did you want a bookmark?)
615 (branches are permanent and global, did you want a bookmark?)
608 $ echo b >b
616 $ echo b >b
609 $ hg ci -Amb
617 $ hg ci -Amb
610 adding b
618 adding b
611
619
612 b is now branch head of B, and a topological head
620 b is now branch head of B, and a topological head
613
621
614 $ hg up 0
622 $ hg up 0
615 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
623 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
616 $ echo a1 >a1
624 $ echo a1 >a1
617 $ hg ci -Ama1
625 $ hg ci -Ama1
618 adding a1
626 adding a1
619
627
620 a1 is now branch head of A, and a topological head
628 a1 is now branch head of A, and a topological head
621
629
622 $ hg clone . inner
630 $ hg clone . inner
623 updating to branch A
631 updating to branch A
624 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
632 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
625 $ cd inner
633 $ cd inner
626 $ hg up B
634 $ hg up B
627 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
635 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
628 $ echo b1 >b1
636 $ echo b1 >b1
629 $ hg ci -Amb1
637 $ hg ci -Amb1
630 adding b1
638 adding b1
631
639
632 in the clone b1 is now the head of B
640 in the clone b1 is now the head of B
633
641
634 $ cd ..
642 $ cd ..
635 $ echo a2 >a2
643 $ echo a2 >a2
636 $ hg ci -Ama2
644 $ hg ci -Ama2
637 adding a2
645 adding a2
638
646
639 a2 is now the new branch head of A, and a topological head
647 a2 is now the new branch head of A, and a topological head
640 it replaces a former topological and branch head, so this should not warn
648 it replaces a former topological and branch head, so this should not warn
641
649
642 glog of local:
650 glog of local:
643
651
644 $ hg log -G --template "{rev}: {branches} {desc}\n"
652 $ hg log -G --template "{rev}: {branches} {desc}\n"
645 @ 3: A a2
653 @ 3: A a2
646 |
654 |
647 o 2: A a1
655 o 2: A a1
648 |
656 |
649 | o 1: B b
657 | o 1: B b
650 |/
658 |/
651 o 0: A a
659 o 0: A a
652
660
653 glog of remote:
661 glog of remote:
654
662
655 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
663 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
656 @ 3: B b1
664 @ 3: B b1
657 |
665 |
658 | o 2: A a1
666 | o 2: A a1
659 | |
667 | |
660 o | 1: B b
668 o | 1: B b
661 |/
669 |/
662 o 0: A a
670 o 0: A a
663
671
664 outgoing:
672 outgoing:
665
673
666 $ hg out inner --template "{rev}: {branches} {desc}\n"
674 $ hg out inner --template "{rev}: {branches} {desc}\n"
667 comparing with inner
675 comparing with inner
668 searching for changes
676 searching for changes
669 3: A a2
677 3: A a2
670
678
671 $ hg push inner
679 $ hg push inner
672 pushing to inner
680 pushing to inner
673 searching for changes
681 searching for changes
674 adding changesets
682 adding changesets
675 adding manifests
683 adding manifests
676 adding file changes
684 adding file changes
677 added 1 changesets with 1 changes to 1 files
685 added 1 changesets with 1 changes to 1 files
678
686
679 $ cd ..
687 $ cd ..
680
688
681
689
682 Check prepush with new branch head and new child of former branch head
690 Check prepush with new branch head and new child of former branch head
683 but child is on different branch:
691 but child is on different branch:
684
692
685 $ hg init p
693 $ hg init p
686 $ cd p
694 $ cd p
687 $ hg branch A
695 $ hg branch A
688 marked working directory as branch A
696 marked working directory as branch A
689 (branches are permanent and global, did you want a bookmark?)
697 (branches are permanent and global, did you want a bookmark?)
690 $ echo a0 >a
698 $ echo a0 >a
691 $ hg ci -Ama0
699 $ hg ci -Ama0
692 adding a
700 adding a
693 $ echo a1 >a
701 $ echo a1 >a
694 $ hg ci -ma1
702 $ hg ci -ma1
695 $ hg up null
703 $ hg up null
696 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
704 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
697 $ hg branch B
705 $ hg branch B
698 marked working directory as branch B
706 marked working directory as branch B
699 (branches are permanent and global, did you want a bookmark?)
707 (branches are permanent and global, did you want a bookmark?)
700 $ echo b0 >b
708 $ echo b0 >b
701 $ hg ci -Amb0
709 $ hg ci -Amb0
702 adding b
710 adding b
703 $ echo b1 >b
711 $ echo b1 >b
704 $ hg ci -mb1
712 $ hg ci -mb1
705
713
706 $ hg clone . inner
714 $ hg clone . inner
707 updating to branch B
715 updating to branch B
708 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
716 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
709
717
710 $ hg up A
718 $ hg up A
711 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
719 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
712 $ hg branch -f B
720 $ hg branch -f B
713 marked working directory as branch B
721 marked working directory as branch B
714 (branches are permanent and global, did you want a bookmark?)
722 (branches are permanent and global, did you want a bookmark?)
715 $ echo a3 >a
723 $ echo a3 >a
716 $ hg ci -ma3
724 $ hg ci -ma3
717 created new head
725 created new head
718 $ hg up 3
726 $ hg up 3
719 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
727 1 files updated, 0 files merged, 1 files removed, 0 files unresolved
720 $ hg branch -f A
728 $ hg branch -f A
721 marked working directory as branch A
729 marked working directory as branch A
722 (branches are permanent and global, did you want a bookmark?)
730 (branches are permanent and global, did you want a bookmark?)
723 $ echo b3 >b
731 $ echo b3 >b
724 $ hg ci -mb3
732 $ hg ci -mb3
725 created new head
733 created new head
726
734
727 glog of local:
735 glog of local:
728
736
729 $ hg log -G --template "{rev}: {branches} {desc}\n"
737 $ hg log -G --template "{rev}: {branches} {desc}\n"
730 @ 5: A b3
738 @ 5: A b3
731 |
739 |
732 | o 4: B a3
740 | o 4: B a3
733 | |
741 | |
734 o | 3: B b1
742 o | 3: B b1
735 | |
743 | |
736 o | 2: B b0
744 o | 2: B b0
737 /
745 /
738 o 1: A a1
746 o 1: A a1
739 |
747 |
740 o 0: A a0
748 o 0: A a0
741
749
742 glog of remote:
750 glog of remote:
743
751
744 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
752 $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
745 @ 3: B b1
753 @ 3: B b1
746 |
754 |
747 o 2: B b0
755 o 2: B b0
748
756
749 o 1: A a1
757 o 1: A a1
750 |
758 |
751 o 0: A a0
759 o 0: A a0
752
760
753 outgoing:
761 outgoing:
754
762
755 $ hg out inner --template "{rev}: {branches} {desc}\n"
763 $ hg out inner --template "{rev}: {branches} {desc}\n"
756 comparing with inner
764 comparing with inner
757 searching for changes
765 searching for changes
758 4: B a3
766 4: B a3
759 5: A b3
767 5: A b3
760
768
761 $ hg push inner
769 $ hg push inner
762 pushing to inner
770 pushing to inner
763 searching for changes
771 searching for changes
764 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
772 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
765 (merge or see "hg help push" for details about pushing new heads)
773 (merge or see "hg help push" for details about pushing new heads)
766 [255]
774 [255]
767
775
768 $ hg push inner -r4 -r5
776 $ hg push inner -r4 -r5
769 pushing to inner
777 pushing to inner
770 searching for changes
778 searching for changes
771 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
779 abort: push creates new remote head 7d0f4fb6cf04 on branch 'A'!
772 (merge or see "hg help push" for details about pushing new heads)
780 (merge or see "hg help push" for details about pushing new heads)
773 [255]
781 [255]
774
782
775 $ hg in inner
783 $ hg in inner
776 comparing with inner
784 comparing with inner
777 searching for changes
785 searching for changes
778 no changes found
786 no changes found
779 [1]
787 [1]
780
788
781 $ cd ..
789 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now