##// END OF EJS Templates
commands.import: accept a prefix option...
Siddharth Agarwal -
r24258:093e8a5e default
parent child Browse files
Show More
@@ -1,6334 +1,6338
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 Returns 0 on success.
269 Returns 0 on success.
270 """
270 """
271 if not pats:
271 if not pats:
272 raise util.Abort(_('at least one filename or pattern is required'))
272 raise util.Abort(_('at least one filename or pattern is required'))
273
273
274 if opts.get('follow'):
274 if opts.get('follow'):
275 # --follow is deprecated and now just an alias for -f/--file
275 # --follow is deprecated and now just an alias for -f/--file
276 # to mimic the behavior of Mercurial before version 1.5
276 # to mimic the behavior of Mercurial before version 1.5
277 opts['file'] = True
277 opts['file'] = True
278
278
279 fm = ui.formatter('annotate', opts)
279 fm = ui.formatter('annotate', opts)
280 datefunc = ui.quiet and util.shortdate or util.datestr
280 datefunc = ui.quiet and util.shortdate or util.datestr
281 hexfn = fm.hexfunc
281 hexfn = fm.hexfunc
282
282
283 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
283 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
284 ('number', ' ', lambda x: x[0].rev(), str),
284 ('number', ' ', lambda x: x[0].rev(), str),
285 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
285 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
286 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
286 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
287 ('file', ' ', lambda x: x[0].path(), str),
287 ('file', ' ', lambda x: x[0].path(), str),
288 ('line_number', ':', lambda x: x[1], str),
288 ('line_number', ':', lambda x: x[1], str),
289 ]
289 ]
290 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
290 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
291
291
292 if (not opts.get('user') and not opts.get('changeset')
292 if (not opts.get('user') and not opts.get('changeset')
293 and not opts.get('date') and not opts.get('file')):
293 and not opts.get('date') and not opts.get('file')):
294 opts['number'] = True
294 opts['number'] = True
295
295
296 linenumber = opts.get('line_number') is not None
296 linenumber = opts.get('line_number') is not None
297 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
297 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
298 raise util.Abort(_('at least one of -n/-c is required for -l'))
298 raise util.Abort(_('at least one of -n/-c is required for -l'))
299
299
300 if fm:
300 if fm:
301 def makefunc(get, fmt):
301 def makefunc(get, fmt):
302 return get
302 return get
303 else:
303 else:
304 def makefunc(get, fmt):
304 def makefunc(get, fmt):
305 return lambda x: fmt(get(x))
305 return lambda x: fmt(get(x))
306 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
306 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
307 if opts.get(op)]
307 if opts.get(op)]
308 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
308 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
309 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
309 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
310 if opts.get(op))
310 if opts.get(op))
311
311
312 def bad(x, y):
312 def bad(x, y):
313 raise util.Abort("%s: %s" % (x, y))
313 raise util.Abort("%s: %s" % (x, y))
314
314
315 ctx = scmutil.revsingle(repo, opts.get('rev'))
315 ctx = scmutil.revsingle(repo, opts.get('rev'))
316 m = scmutil.match(ctx, pats, opts)
316 m = scmutil.match(ctx, pats, opts)
317 m.bad = bad
317 m.bad = bad
318 follow = not opts.get('no_follow')
318 follow = not opts.get('no_follow')
319 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
319 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
320 whitespace=True)
320 whitespace=True)
321 for abs in ctx.walk(m):
321 for abs in ctx.walk(m):
322 fctx = ctx[abs]
322 fctx = ctx[abs]
323 if not opts.get('text') and util.binary(fctx.data()):
323 if not opts.get('text') and util.binary(fctx.data()):
324 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
324 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
325 continue
325 continue
326
326
327 lines = fctx.annotate(follow=follow, linenumber=linenumber,
327 lines = fctx.annotate(follow=follow, linenumber=linenumber,
328 diffopts=diffopts)
328 diffopts=diffopts)
329 formats = []
329 formats = []
330 pieces = []
330 pieces = []
331
331
332 for f, sep in funcmap:
332 for f, sep in funcmap:
333 l = [f(n) for n, dummy in lines]
333 l = [f(n) for n, dummy in lines]
334 if l:
334 if l:
335 if fm:
335 if fm:
336 formats.append(['%s' for x in l])
336 formats.append(['%s' for x in l])
337 else:
337 else:
338 sizes = [encoding.colwidth(x) for x in l]
338 sizes = [encoding.colwidth(x) for x in l]
339 ml = max(sizes)
339 ml = max(sizes)
340 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
340 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
341 pieces.append(l)
341 pieces.append(l)
342
342
343 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
343 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
344 fm.startitem()
344 fm.startitem()
345 fm.write(fields, "".join(f), *p)
345 fm.write(fields, "".join(f), *p)
346 fm.write('line', ": %s", l[1])
346 fm.write('line', ": %s", l[1])
347
347
348 if lines and not lines[-1][1].endswith('\n'):
348 if lines and not lines[-1][1].endswith('\n'):
349 fm.plain('\n')
349 fm.plain('\n')
350
350
351 fm.end()
351 fm.end()
352
352
353 @command('archive',
353 @command('archive',
354 [('', 'no-decode', None, _('do not pass files through decoders')),
354 [('', 'no-decode', None, _('do not pass files through decoders')),
355 ('p', 'prefix', '', _('directory prefix for files in archive'),
355 ('p', 'prefix', '', _('directory prefix for files in archive'),
356 _('PREFIX')),
356 _('PREFIX')),
357 ('r', 'rev', '', _('revision to distribute'), _('REV')),
357 ('r', 'rev', '', _('revision to distribute'), _('REV')),
358 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
358 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
359 ] + subrepoopts + walkopts,
359 ] + subrepoopts + walkopts,
360 _('[OPTION]... DEST'))
360 _('[OPTION]... DEST'))
361 def archive(ui, repo, dest, **opts):
361 def archive(ui, repo, dest, **opts):
362 '''create an unversioned archive of a repository revision
362 '''create an unversioned archive of a repository revision
363
363
364 By default, the revision used is the parent of the working
364 By default, the revision used is the parent of the working
365 directory; use -r/--rev to specify a different revision.
365 directory; use -r/--rev to specify a different revision.
366
366
367 The archive type is automatically detected based on file
367 The archive type is automatically detected based on file
368 extension (or override using -t/--type).
368 extension (or override using -t/--type).
369
369
370 .. container:: verbose
370 .. container:: verbose
371
371
372 Examples:
372 Examples:
373
373
374 - create a zip file containing the 1.0 release::
374 - create a zip file containing the 1.0 release::
375
375
376 hg archive -r 1.0 project-1.0.zip
376 hg archive -r 1.0 project-1.0.zip
377
377
378 - create a tarball excluding .hg files::
378 - create a tarball excluding .hg files::
379
379
380 hg archive project.tar.gz -X ".hg*"
380 hg archive project.tar.gz -X ".hg*"
381
381
382 Valid types are:
382 Valid types are:
383
383
384 :``files``: a directory full of files (default)
384 :``files``: a directory full of files (default)
385 :``tar``: tar archive, uncompressed
385 :``tar``: tar archive, uncompressed
386 :``tbz2``: tar archive, compressed using bzip2
386 :``tbz2``: tar archive, compressed using bzip2
387 :``tgz``: tar archive, compressed using gzip
387 :``tgz``: tar archive, compressed using gzip
388 :``uzip``: zip archive, uncompressed
388 :``uzip``: zip archive, uncompressed
389 :``zip``: zip archive, compressed using deflate
389 :``zip``: zip archive, compressed using deflate
390
390
391 The exact name of the destination archive or directory is given
391 The exact name of the destination archive or directory is given
392 using a format string; see :hg:`help export` for details.
392 using a format string; see :hg:`help export` for details.
393
393
394 Each member added to an archive file has a directory prefix
394 Each member added to an archive file has a directory prefix
395 prepended. Use -p/--prefix to specify a format string for the
395 prepended. Use -p/--prefix to specify a format string for the
396 prefix. The default is the basename of the archive, with suffixes
396 prefix. The default is the basename of the archive, with suffixes
397 removed.
397 removed.
398
398
399 Returns 0 on success.
399 Returns 0 on success.
400 '''
400 '''
401
401
402 ctx = scmutil.revsingle(repo, opts.get('rev'))
402 ctx = scmutil.revsingle(repo, opts.get('rev'))
403 if not ctx:
403 if not ctx:
404 raise util.Abort(_('no working directory: please specify a revision'))
404 raise util.Abort(_('no working directory: please specify a revision'))
405 node = ctx.node()
405 node = ctx.node()
406 dest = cmdutil.makefilename(repo, dest, node)
406 dest = cmdutil.makefilename(repo, dest, node)
407 if os.path.realpath(dest) == repo.root:
407 if os.path.realpath(dest) == repo.root:
408 raise util.Abort(_('repository root cannot be destination'))
408 raise util.Abort(_('repository root cannot be destination'))
409
409
410 kind = opts.get('type') or archival.guesskind(dest) or 'files'
410 kind = opts.get('type') or archival.guesskind(dest) or 'files'
411 prefix = opts.get('prefix')
411 prefix = opts.get('prefix')
412
412
413 if dest == '-':
413 if dest == '-':
414 if kind == 'files':
414 if kind == 'files':
415 raise util.Abort(_('cannot archive plain files to stdout'))
415 raise util.Abort(_('cannot archive plain files to stdout'))
416 dest = cmdutil.makefileobj(repo, dest)
416 dest = cmdutil.makefileobj(repo, dest)
417 if not prefix:
417 if not prefix:
418 prefix = os.path.basename(repo.root) + '-%h'
418 prefix = os.path.basename(repo.root) + '-%h'
419
419
420 prefix = cmdutil.makefilename(repo, prefix, node)
420 prefix = cmdutil.makefilename(repo, prefix, node)
421 matchfn = scmutil.match(ctx, [], opts)
421 matchfn = scmutil.match(ctx, [], opts)
422 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
422 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
423 matchfn, prefix, subrepos=opts.get('subrepos'))
423 matchfn, prefix, subrepos=opts.get('subrepos'))
424
424
425 @command('backout',
425 @command('backout',
426 [('', 'merge', None, _('merge with old dirstate parent after backout')),
426 [('', 'merge', None, _('merge with old dirstate parent after backout')),
427 ('', 'commit', None, _('commit if no conflicts were encountered')),
427 ('', 'commit', None, _('commit if no conflicts were encountered')),
428 ('', 'parent', '',
428 ('', 'parent', '',
429 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
429 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
430 ('r', 'rev', '', _('revision to backout'), _('REV')),
430 ('r', 'rev', '', _('revision to backout'), _('REV')),
431 ('e', 'edit', False, _('invoke editor on commit messages')),
431 ('e', 'edit', False, _('invoke editor on commit messages')),
432 ] + mergetoolopts + walkopts + commitopts + commitopts2,
432 ] + mergetoolopts + walkopts + commitopts + commitopts2,
433 _('[OPTION]... [-r] REV'))
433 _('[OPTION]... [-r] REV'))
434 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
434 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
435 '''reverse effect of earlier changeset
435 '''reverse effect of earlier changeset
436
436
437 Prepare a new changeset with the effect of REV undone in the
437 Prepare a new changeset with the effect of REV undone in the
438 current working directory.
438 current working directory.
439
439
440 If REV is the parent of the working directory, then this new changeset
440 If REV is the parent of the working directory, then this new changeset
441 is committed automatically. Otherwise, hg needs to merge the
441 is committed automatically. Otherwise, hg needs to merge the
442 changes and the merged result is left uncommitted.
442 changes and the merged result is left uncommitted.
443
443
444 .. note::
444 .. note::
445
445
446 backout cannot be used to fix either an unwanted or
446 backout cannot be used to fix either an unwanted or
447 incorrect merge.
447 incorrect merge.
448
448
449 .. container:: verbose
449 .. container:: verbose
450
450
451 By default, the pending changeset will have one parent,
451 By default, the pending changeset will have one parent,
452 maintaining a linear history. With --merge, the pending
452 maintaining a linear history. With --merge, the pending
453 changeset will instead have two parents: the old parent of the
453 changeset will instead have two parents: the old parent of the
454 working directory and a new child of REV that simply undoes REV.
454 working directory and a new child of REV that simply undoes REV.
455
455
456 Before version 1.7, the behavior without --merge was equivalent
456 Before version 1.7, the behavior without --merge was equivalent
457 to specifying --merge followed by :hg:`update --clean .` to
457 to specifying --merge followed by :hg:`update --clean .` to
458 cancel the merge and leave the child of REV as a head to be
458 cancel the merge and leave the child of REV as a head to be
459 merged separately.
459 merged separately.
460
460
461 See :hg:`help dates` for a list of formats valid for -d/--date.
461 See :hg:`help dates` for a list of formats valid for -d/--date.
462
462
463 Returns 0 on success, 1 if nothing to backout or there are unresolved
463 Returns 0 on success, 1 if nothing to backout or there are unresolved
464 files.
464 files.
465 '''
465 '''
466 if rev and node:
466 if rev and node:
467 raise util.Abort(_("please specify just one revision"))
467 raise util.Abort(_("please specify just one revision"))
468
468
469 if not rev:
469 if not rev:
470 rev = node
470 rev = node
471
471
472 if not rev:
472 if not rev:
473 raise util.Abort(_("please specify a revision to backout"))
473 raise util.Abort(_("please specify a revision to backout"))
474
474
475 date = opts.get('date')
475 date = opts.get('date')
476 if date:
476 if date:
477 opts['date'] = util.parsedate(date)
477 opts['date'] = util.parsedate(date)
478
478
479 cmdutil.checkunfinished(repo)
479 cmdutil.checkunfinished(repo)
480 cmdutil.bailifchanged(repo)
480 cmdutil.bailifchanged(repo)
481 node = scmutil.revsingle(repo, rev).node()
481 node = scmutil.revsingle(repo, rev).node()
482
482
483 op1, op2 = repo.dirstate.parents()
483 op1, op2 = repo.dirstate.parents()
484 if not repo.changelog.isancestor(node, op1):
484 if not repo.changelog.isancestor(node, op1):
485 raise util.Abort(_('cannot backout change that is not an ancestor'))
485 raise util.Abort(_('cannot backout change that is not an ancestor'))
486
486
487 p1, p2 = repo.changelog.parents(node)
487 p1, p2 = repo.changelog.parents(node)
488 if p1 == nullid:
488 if p1 == nullid:
489 raise util.Abort(_('cannot backout a change with no parents'))
489 raise util.Abort(_('cannot backout a change with no parents'))
490 if p2 != nullid:
490 if p2 != nullid:
491 if not opts.get('parent'):
491 if not opts.get('parent'):
492 raise util.Abort(_('cannot backout a merge changeset'))
492 raise util.Abort(_('cannot backout a merge changeset'))
493 p = repo.lookup(opts['parent'])
493 p = repo.lookup(opts['parent'])
494 if p not in (p1, p2):
494 if p not in (p1, p2):
495 raise util.Abort(_('%s is not a parent of %s') %
495 raise util.Abort(_('%s is not a parent of %s') %
496 (short(p), short(node)))
496 (short(p), short(node)))
497 parent = p
497 parent = p
498 else:
498 else:
499 if opts.get('parent'):
499 if opts.get('parent'):
500 raise util.Abort(_('cannot use --parent on non-merge changeset'))
500 raise util.Abort(_('cannot use --parent on non-merge changeset'))
501 parent = p1
501 parent = p1
502
502
503 # the backout should appear on the same branch
503 # the backout should appear on the same branch
504 wlock = repo.wlock()
504 wlock = repo.wlock()
505 try:
505 try:
506 branch = repo.dirstate.branch()
506 branch = repo.dirstate.branch()
507 bheads = repo.branchheads(branch)
507 bheads = repo.branchheads(branch)
508 rctx = scmutil.revsingle(repo, hex(parent))
508 rctx = scmutil.revsingle(repo, hex(parent))
509 if not opts.get('merge') and op1 != node:
509 if not opts.get('merge') and op1 != node:
510 try:
510 try:
511 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
511 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
512 'backout')
512 'backout')
513 repo.dirstate.beginparentchange()
513 repo.dirstate.beginparentchange()
514 stats = mergemod.update(repo, parent, True, True, False,
514 stats = mergemod.update(repo, parent, True, True, False,
515 node, False)
515 node, False)
516 repo.setparents(op1, op2)
516 repo.setparents(op1, op2)
517 repo.dirstate.endparentchange()
517 repo.dirstate.endparentchange()
518 hg._showstats(repo, stats)
518 hg._showstats(repo, stats)
519 if stats[3]:
519 if stats[3]:
520 repo.ui.status(_("use 'hg resolve' to retry unresolved "
520 repo.ui.status(_("use 'hg resolve' to retry unresolved "
521 "file merges\n"))
521 "file merges\n"))
522 return 1
522 return 1
523 elif not commit:
523 elif not commit:
524 msg = _("changeset %s backed out, "
524 msg = _("changeset %s backed out, "
525 "don't forget to commit.\n")
525 "don't forget to commit.\n")
526 ui.status(msg % short(node))
526 ui.status(msg % short(node))
527 return 0
527 return 0
528 finally:
528 finally:
529 ui.setconfig('ui', 'forcemerge', '', '')
529 ui.setconfig('ui', 'forcemerge', '', '')
530 else:
530 else:
531 hg.clean(repo, node, show_stats=False)
531 hg.clean(repo, node, show_stats=False)
532 repo.dirstate.setbranch(branch)
532 repo.dirstate.setbranch(branch)
533 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
533 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
534
534
535
535
536 def commitfunc(ui, repo, message, match, opts):
536 def commitfunc(ui, repo, message, match, opts):
537 editform = 'backout'
537 editform = 'backout'
538 e = cmdutil.getcommiteditor(editform=editform, **opts)
538 e = cmdutil.getcommiteditor(editform=editform, **opts)
539 if not message:
539 if not message:
540 # we don't translate commit messages
540 # we don't translate commit messages
541 message = "Backed out changeset %s" % short(node)
541 message = "Backed out changeset %s" % short(node)
542 e = cmdutil.getcommiteditor(edit=True, editform=editform)
542 e = cmdutil.getcommiteditor(edit=True, editform=editform)
543 return repo.commit(message, opts.get('user'), opts.get('date'),
543 return repo.commit(message, opts.get('user'), opts.get('date'),
544 match, editor=e)
544 match, editor=e)
545 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
545 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
546 if not newnode:
546 if not newnode:
547 ui.status(_("nothing changed\n"))
547 ui.status(_("nothing changed\n"))
548 return 1
548 return 1
549 cmdutil.commitstatus(repo, newnode, branch, bheads)
549 cmdutil.commitstatus(repo, newnode, branch, bheads)
550
550
551 def nice(node):
551 def nice(node):
552 return '%d:%s' % (repo.changelog.rev(node), short(node))
552 return '%d:%s' % (repo.changelog.rev(node), short(node))
553 ui.status(_('changeset %s backs out changeset %s\n') %
553 ui.status(_('changeset %s backs out changeset %s\n') %
554 (nice(repo.changelog.tip()), nice(node)))
554 (nice(repo.changelog.tip()), nice(node)))
555 if opts.get('merge') and op1 != node:
555 if opts.get('merge') and op1 != node:
556 hg.clean(repo, op1, show_stats=False)
556 hg.clean(repo, op1, show_stats=False)
557 ui.status(_('merging with changeset %s\n')
557 ui.status(_('merging with changeset %s\n')
558 % nice(repo.changelog.tip()))
558 % nice(repo.changelog.tip()))
559 try:
559 try:
560 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
560 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
561 'backout')
561 'backout')
562 return hg.merge(repo, hex(repo.changelog.tip()))
562 return hg.merge(repo, hex(repo.changelog.tip()))
563 finally:
563 finally:
564 ui.setconfig('ui', 'forcemerge', '', '')
564 ui.setconfig('ui', 'forcemerge', '', '')
565 finally:
565 finally:
566 wlock.release()
566 wlock.release()
567 return 0
567 return 0
568
568
569 @command('bisect',
569 @command('bisect',
570 [('r', 'reset', False, _('reset bisect state')),
570 [('r', 'reset', False, _('reset bisect state')),
571 ('g', 'good', False, _('mark changeset good')),
571 ('g', 'good', False, _('mark changeset good')),
572 ('b', 'bad', False, _('mark changeset bad')),
572 ('b', 'bad', False, _('mark changeset bad')),
573 ('s', 'skip', False, _('skip testing changeset')),
573 ('s', 'skip', False, _('skip testing changeset')),
574 ('e', 'extend', False, _('extend the bisect range')),
574 ('e', 'extend', False, _('extend the bisect range')),
575 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
575 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
576 ('U', 'noupdate', False, _('do not update to target'))],
576 ('U', 'noupdate', False, _('do not update to target'))],
577 _("[-gbsr] [-U] [-c CMD] [REV]"))
577 _("[-gbsr] [-U] [-c CMD] [REV]"))
578 def bisect(ui, repo, rev=None, extra=None, command=None,
578 def bisect(ui, repo, rev=None, extra=None, command=None,
579 reset=None, good=None, bad=None, skip=None, extend=None,
579 reset=None, good=None, bad=None, skip=None, extend=None,
580 noupdate=None):
580 noupdate=None):
581 """subdivision search of changesets
581 """subdivision search of changesets
582
582
583 This command helps to find changesets which introduce problems. To
583 This command helps to find changesets which introduce problems. To
584 use, mark the earliest changeset you know exhibits the problem as
584 use, mark the earliest changeset you know exhibits the problem as
585 bad, then mark the latest changeset which is free from the problem
585 bad, then mark the latest changeset which is free from the problem
586 as good. Bisect will update your working directory to a revision
586 as good. Bisect will update your working directory to a revision
587 for testing (unless the -U/--noupdate option is specified). Once
587 for testing (unless the -U/--noupdate option is specified). Once
588 you have performed tests, mark the working directory as good or
588 you have performed tests, mark the working directory as good or
589 bad, and bisect will either update to another candidate changeset
589 bad, and bisect will either update to another candidate changeset
590 or announce that it has found the bad revision.
590 or announce that it has found the bad revision.
591
591
592 As a shortcut, you can also use the revision argument to mark a
592 As a shortcut, you can also use the revision argument to mark a
593 revision as good or bad without checking it out first.
593 revision as good or bad without checking it out first.
594
594
595 If you supply a command, it will be used for automatic bisection.
595 If you supply a command, it will be used for automatic bisection.
596 The environment variable HG_NODE will contain the ID of the
596 The environment variable HG_NODE will contain the ID of the
597 changeset being tested. The exit status of the command will be
597 changeset being tested. The exit status of the command will be
598 used to mark revisions as good or bad: status 0 means good, 125
598 used to mark revisions as good or bad: status 0 means good, 125
599 means to skip the revision, 127 (command not found) will abort the
599 means to skip the revision, 127 (command not found) will abort the
600 bisection, and any other non-zero exit status means the revision
600 bisection, and any other non-zero exit status means the revision
601 is bad.
601 is bad.
602
602
603 .. container:: verbose
603 .. container:: verbose
604
604
605 Some examples:
605 Some examples:
606
606
607 - start a bisection with known bad revision 34, and good revision 12::
607 - start a bisection with known bad revision 34, and good revision 12::
608
608
609 hg bisect --bad 34
609 hg bisect --bad 34
610 hg bisect --good 12
610 hg bisect --good 12
611
611
612 - advance the current bisection by marking current revision as good or
612 - advance the current bisection by marking current revision as good or
613 bad::
613 bad::
614
614
615 hg bisect --good
615 hg bisect --good
616 hg bisect --bad
616 hg bisect --bad
617
617
618 - mark the current revision, or a known revision, to be skipped (e.g. if
618 - mark the current revision, or a known revision, to be skipped (e.g. if
619 that revision is not usable because of another issue)::
619 that revision is not usable because of another issue)::
620
620
621 hg bisect --skip
621 hg bisect --skip
622 hg bisect --skip 23
622 hg bisect --skip 23
623
623
624 - skip all revisions that do not touch directories ``foo`` or ``bar``::
624 - skip all revisions that do not touch directories ``foo`` or ``bar``::
625
625
626 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
626 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
627
627
628 - forget the current bisection::
628 - forget the current bisection::
629
629
630 hg bisect --reset
630 hg bisect --reset
631
631
632 - use 'make && make tests' to automatically find the first broken
632 - use 'make && make tests' to automatically find the first broken
633 revision::
633 revision::
634
634
635 hg bisect --reset
635 hg bisect --reset
636 hg bisect --bad 34
636 hg bisect --bad 34
637 hg bisect --good 12
637 hg bisect --good 12
638 hg bisect --command "make && make tests"
638 hg bisect --command "make && make tests"
639
639
640 - see all changesets whose states are already known in the current
640 - see all changesets whose states are already known in the current
641 bisection::
641 bisection::
642
642
643 hg log -r "bisect(pruned)"
643 hg log -r "bisect(pruned)"
644
644
645 - see the changeset currently being bisected (especially useful
645 - see the changeset currently being bisected (especially useful
646 if running with -U/--noupdate)::
646 if running with -U/--noupdate)::
647
647
648 hg log -r "bisect(current)"
648 hg log -r "bisect(current)"
649
649
650 - see all changesets that took part in the current bisection::
650 - see all changesets that took part in the current bisection::
651
651
652 hg log -r "bisect(range)"
652 hg log -r "bisect(range)"
653
653
654 - you can even get a nice graph::
654 - you can even get a nice graph::
655
655
656 hg log --graph -r "bisect(range)"
656 hg log --graph -r "bisect(range)"
657
657
658 See :hg:`help revsets` for more about the `bisect()` keyword.
658 See :hg:`help revsets` for more about the `bisect()` keyword.
659
659
660 Returns 0 on success.
660 Returns 0 on success.
661 """
661 """
662 def extendbisectrange(nodes, good):
662 def extendbisectrange(nodes, good):
663 # bisect is incomplete when it ends on a merge node and
663 # bisect is incomplete when it ends on a merge node and
664 # one of the parent was not checked.
664 # one of the parent was not checked.
665 parents = repo[nodes[0]].parents()
665 parents = repo[nodes[0]].parents()
666 if len(parents) > 1:
666 if len(parents) > 1:
667 side = good and state['bad'] or state['good']
667 side = good and state['bad'] or state['good']
668 num = len(set(i.node() for i in parents) & set(side))
668 num = len(set(i.node() for i in parents) & set(side))
669 if num == 1:
669 if num == 1:
670 return parents[0].ancestor(parents[1])
670 return parents[0].ancestor(parents[1])
671 return None
671 return None
672
672
673 def print_result(nodes, good):
673 def print_result(nodes, good):
674 displayer = cmdutil.show_changeset(ui, repo, {})
674 displayer = cmdutil.show_changeset(ui, repo, {})
675 if len(nodes) == 1:
675 if len(nodes) == 1:
676 # narrowed it down to a single revision
676 # narrowed it down to a single revision
677 if good:
677 if good:
678 ui.write(_("The first good revision is:\n"))
678 ui.write(_("The first good revision is:\n"))
679 else:
679 else:
680 ui.write(_("The first bad revision is:\n"))
680 ui.write(_("The first bad revision is:\n"))
681 displayer.show(repo[nodes[0]])
681 displayer.show(repo[nodes[0]])
682 extendnode = extendbisectrange(nodes, good)
682 extendnode = extendbisectrange(nodes, good)
683 if extendnode is not None:
683 if extendnode is not None:
684 ui.write(_('Not all ancestors of this changeset have been'
684 ui.write(_('Not all ancestors of this changeset have been'
685 ' checked.\nUse bisect --extend to continue the '
685 ' checked.\nUse bisect --extend to continue the '
686 'bisection from\nthe common ancestor, %s.\n')
686 'bisection from\nthe common ancestor, %s.\n')
687 % extendnode)
687 % extendnode)
688 else:
688 else:
689 # multiple possible revisions
689 # multiple possible revisions
690 if good:
690 if good:
691 ui.write(_("Due to skipped revisions, the first "
691 ui.write(_("Due to skipped revisions, the first "
692 "good revision could be any of:\n"))
692 "good revision could be any of:\n"))
693 else:
693 else:
694 ui.write(_("Due to skipped revisions, the first "
694 ui.write(_("Due to skipped revisions, the first "
695 "bad revision could be any of:\n"))
695 "bad revision could be any of:\n"))
696 for n in nodes:
696 for n in nodes:
697 displayer.show(repo[n])
697 displayer.show(repo[n])
698 displayer.close()
698 displayer.close()
699
699
700 def check_state(state, interactive=True):
700 def check_state(state, interactive=True):
701 if not state['good'] or not state['bad']:
701 if not state['good'] or not state['bad']:
702 if (good or bad or skip or reset) and interactive:
702 if (good or bad or skip or reset) and interactive:
703 return
703 return
704 if not state['good']:
704 if not state['good']:
705 raise util.Abort(_('cannot bisect (no known good revisions)'))
705 raise util.Abort(_('cannot bisect (no known good revisions)'))
706 else:
706 else:
707 raise util.Abort(_('cannot bisect (no known bad revisions)'))
707 raise util.Abort(_('cannot bisect (no known bad revisions)'))
708 return True
708 return True
709
709
710 # backward compatibility
710 # backward compatibility
711 if rev in "good bad reset init".split():
711 if rev in "good bad reset init".split():
712 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
712 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
713 cmd, rev, extra = rev, extra, None
713 cmd, rev, extra = rev, extra, None
714 if cmd == "good":
714 if cmd == "good":
715 good = True
715 good = True
716 elif cmd == "bad":
716 elif cmd == "bad":
717 bad = True
717 bad = True
718 else:
718 else:
719 reset = True
719 reset = True
720 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
720 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
721 raise util.Abort(_('incompatible arguments'))
721 raise util.Abort(_('incompatible arguments'))
722
722
723 cmdutil.checkunfinished(repo)
723 cmdutil.checkunfinished(repo)
724
724
725 if reset:
725 if reset:
726 p = repo.join("bisect.state")
726 p = repo.join("bisect.state")
727 if os.path.exists(p):
727 if os.path.exists(p):
728 os.unlink(p)
728 os.unlink(p)
729 return
729 return
730
730
731 state = hbisect.load_state(repo)
731 state = hbisect.load_state(repo)
732
732
733 if command:
733 if command:
734 changesets = 1
734 changesets = 1
735 if noupdate:
735 if noupdate:
736 try:
736 try:
737 node = state['current'][0]
737 node = state['current'][0]
738 except LookupError:
738 except LookupError:
739 raise util.Abort(_('current bisect revision is unknown - '
739 raise util.Abort(_('current bisect revision is unknown - '
740 'start a new bisect to fix'))
740 'start a new bisect to fix'))
741 else:
741 else:
742 node, p2 = repo.dirstate.parents()
742 node, p2 = repo.dirstate.parents()
743 if p2 != nullid:
743 if p2 != nullid:
744 raise util.Abort(_('current bisect revision is a merge'))
744 raise util.Abort(_('current bisect revision is a merge'))
745 try:
745 try:
746 while changesets:
746 while changesets:
747 # update state
747 # update state
748 state['current'] = [node]
748 state['current'] = [node]
749 hbisect.save_state(repo, state)
749 hbisect.save_state(repo, state)
750 status = ui.system(command, environ={'HG_NODE': hex(node)})
750 status = ui.system(command, environ={'HG_NODE': hex(node)})
751 if status == 125:
751 if status == 125:
752 transition = "skip"
752 transition = "skip"
753 elif status == 0:
753 elif status == 0:
754 transition = "good"
754 transition = "good"
755 # status < 0 means process was killed
755 # status < 0 means process was killed
756 elif status == 127:
756 elif status == 127:
757 raise util.Abort(_("failed to execute %s") % command)
757 raise util.Abort(_("failed to execute %s") % command)
758 elif status < 0:
758 elif status < 0:
759 raise util.Abort(_("%s killed") % command)
759 raise util.Abort(_("%s killed") % command)
760 else:
760 else:
761 transition = "bad"
761 transition = "bad"
762 ctx = scmutil.revsingle(repo, rev, node)
762 ctx = scmutil.revsingle(repo, rev, node)
763 rev = None # clear for future iterations
763 rev = None # clear for future iterations
764 state[transition].append(ctx.node())
764 state[transition].append(ctx.node())
765 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
765 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
766 check_state(state, interactive=False)
766 check_state(state, interactive=False)
767 # bisect
767 # bisect
768 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
768 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
769 # update to next check
769 # update to next check
770 node = nodes[0]
770 node = nodes[0]
771 if not noupdate:
771 if not noupdate:
772 cmdutil.bailifchanged(repo)
772 cmdutil.bailifchanged(repo)
773 hg.clean(repo, node, show_stats=False)
773 hg.clean(repo, node, show_stats=False)
774 finally:
774 finally:
775 state['current'] = [node]
775 state['current'] = [node]
776 hbisect.save_state(repo, state)
776 hbisect.save_state(repo, state)
777 print_result(nodes, bgood)
777 print_result(nodes, bgood)
778 return
778 return
779
779
780 # update state
780 # update state
781
781
782 if rev:
782 if rev:
783 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
783 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
784 else:
784 else:
785 nodes = [repo.lookup('.')]
785 nodes = [repo.lookup('.')]
786
786
787 if good or bad or skip:
787 if good or bad or skip:
788 if good:
788 if good:
789 state['good'] += nodes
789 state['good'] += nodes
790 elif bad:
790 elif bad:
791 state['bad'] += nodes
791 state['bad'] += nodes
792 elif skip:
792 elif skip:
793 state['skip'] += nodes
793 state['skip'] += nodes
794 hbisect.save_state(repo, state)
794 hbisect.save_state(repo, state)
795
795
796 if not check_state(state):
796 if not check_state(state):
797 return
797 return
798
798
799 # actually bisect
799 # actually bisect
800 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
800 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
801 if extend:
801 if extend:
802 if not changesets:
802 if not changesets:
803 extendnode = extendbisectrange(nodes, good)
803 extendnode = extendbisectrange(nodes, good)
804 if extendnode is not None:
804 if extendnode is not None:
805 ui.write(_("Extending search to changeset %d:%s\n")
805 ui.write(_("Extending search to changeset %d:%s\n")
806 % (extendnode.rev(), extendnode))
806 % (extendnode.rev(), extendnode))
807 state['current'] = [extendnode.node()]
807 state['current'] = [extendnode.node()]
808 hbisect.save_state(repo, state)
808 hbisect.save_state(repo, state)
809 if noupdate:
809 if noupdate:
810 return
810 return
811 cmdutil.bailifchanged(repo)
811 cmdutil.bailifchanged(repo)
812 return hg.clean(repo, extendnode.node())
812 return hg.clean(repo, extendnode.node())
813 raise util.Abort(_("nothing to extend"))
813 raise util.Abort(_("nothing to extend"))
814
814
815 if changesets == 0:
815 if changesets == 0:
816 print_result(nodes, good)
816 print_result(nodes, good)
817 else:
817 else:
818 assert len(nodes) == 1 # only a single node can be tested next
818 assert len(nodes) == 1 # only a single node can be tested next
819 node = nodes[0]
819 node = nodes[0]
820 # compute the approximate number of remaining tests
820 # compute the approximate number of remaining tests
821 tests, size = 0, 2
821 tests, size = 0, 2
822 while size <= changesets:
822 while size <= changesets:
823 tests, size = tests + 1, size * 2
823 tests, size = tests + 1, size * 2
824 rev = repo.changelog.rev(node)
824 rev = repo.changelog.rev(node)
825 ui.write(_("Testing changeset %d:%s "
825 ui.write(_("Testing changeset %d:%s "
826 "(%d changesets remaining, ~%d tests)\n")
826 "(%d changesets remaining, ~%d tests)\n")
827 % (rev, short(node), changesets, tests))
827 % (rev, short(node), changesets, tests))
828 state['current'] = [node]
828 state['current'] = [node]
829 hbisect.save_state(repo, state)
829 hbisect.save_state(repo, state)
830 if not noupdate:
830 if not noupdate:
831 cmdutil.bailifchanged(repo)
831 cmdutil.bailifchanged(repo)
832 return hg.clean(repo, node)
832 return hg.clean(repo, node)
833
833
834 @command('bookmarks|bookmark',
834 @command('bookmarks|bookmark',
835 [('f', 'force', False, _('force')),
835 [('f', 'force', False, _('force')),
836 ('r', 'rev', '', _('revision'), _('REV')),
836 ('r', 'rev', '', _('revision'), _('REV')),
837 ('d', 'delete', False, _('delete a given bookmark')),
837 ('d', 'delete', False, _('delete a given bookmark')),
838 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
838 ('m', 'rename', '', _('rename a given bookmark'), _('NAME')),
839 ('i', 'inactive', False, _('mark a bookmark inactive')),
839 ('i', 'inactive', False, _('mark a bookmark inactive')),
840 ] + formatteropts,
840 ] + formatteropts,
841 _('hg bookmarks [OPTIONS]... [NAME]...'))
841 _('hg bookmarks [OPTIONS]... [NAME]...'))
842 def bookmark(ui, repo, *names, **opts):
842 def bookmark(ui, repo, *names, **opts):
843 '''create a new bookmark or list existing bookmarks
843 '''create a new bookmark or list existing bookmarks
844
844
845 Bookmarks are labels on changesets to help track lines of development.
845 Bookmarks are labels on changesets to help track lines of development.
846 Bookmarks are unversioned and can be moved, renamed and deleted.
846 Bookmarks are unversioned and can be moved, renamed and deleted.
847 Deleting or moving a bookmark has no effect on the associated changesets.
847 Deleting or moving a bookmark has no effect on the associated changesets.
848
848
849 Creating or updating to a bookmark causes it to be marked as 'active'.
849 Creating or updating to a bookmark causes it to be marked as 'active'.
850 The active bookmark is indicated with a '*'.
850 The active bookmark is indicated with a '*'.
851 When a commit is made, the active bookmark will advance to the new commit.
851 When a commit is made, the active bookmark will advance to the new commit.
852 A plain :hg:`update` will also advance an active bookmark, if possible.
852 A plain :hg:`update` will also advance an active bookmark, if possible.
853 Updating away from a bookmark will cause it to be deactivated.
853 Updating away from a bookmark will cause it to be deactivated.
854
854
855 Bookmarks can be pushed and pulled between repositories (see
855 Bookmarks can be pushed and pulled between repositories (see
856 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
856 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
857 diverged, a new 'divergent bookmark' of the form 'name@path' will
857 diverged, a new 'divergent bookmark' of the form 'name@path' will
858 be created. Using :hg:`merge` will resolve the divergence.
858 be created. Using :hg:`merge` will resolve the divergence.
859
859
860 A bookmark named '@' has the special property that :hg:`clone` will
860 A bookmark named '@' has the special property that :hg:`clone` will
861 check it out by default if it exists.
861 check it out by default if it exists.
862
862
863 .. container:: verbose
863 .. container:: verbose
864
864
865 Examples:
865 Examples:
866
866
867 - create an active bookmark for a new line of development::
867 - create an active bookmark for a new line of development::
868
868
869 hg book new-feature
869 hg book new-feature
870
870
871 - create an inactive bookmark as a place marker::
871 - create an inactive bookmark as a place marker::
872
872
873 hg book -i reviewed
873 hg book -i reviewed
874
874
875 - create an inactive bookmark on another changeset::
875 - create an inactive bookmark on another changeset::
876
876
877 hg book -r .^ tested
877 hg book -r .^ tested
878
878
879 - move the '@' bookmark from another branch::
879 - move the '@' bookmark from another branch::
880
880
881 hg book -f @
881 hg book -f @
882 '''
882 '''
883 force = opts.get('force')
883 force = opts.get('force')
884 rev = opts.get('rev')
884 rev = opts.get('rev')
885 delete = opts.get('delete')
885 delete = opts.get('delete')
886 rename = opts.get('rename')
886 rename = opts.get('rename')
887 inactive = opts.get('inactive')
887 inactive = opts.get('inactive')
888
888
889 def checkformat(mark):
889 def checkformat(mark):
890 mark = mark.strip()
890 mark = mark.strip()
891 if not mark:
891 if not mark:
892 raise util.Abort(_("bookmark names cannot consist entirely of "
892 raise util.Abort(_("bookmark names cannot consist entirely of "
893 "whitespace"))
893 "whitespace"))
894 scmutil.checknewlabel(repo, mark, 'bookmark')
894 scmutil.checknewlabel(repo, mark, 'bookmark')
895 return mark
895 return mark
896
896
897 def checkconflict(repo, mark, cur, force=False, target=None):
897 def checkconflict(repo, mark, cur, force=False, target=None):
898 if mark in marks and not force:
898 if mark in marks and not force:
899 if target:
899 if target:
900 if marks[mark] == target and target == cur:
900 if marks[mark] == target and target == cur:
901 # re-activating a bookmark
901 # re-activating a bookmark
902 return
902 return
903 anc = repo.changelog.ancestors([repo[target].rev()])
903 anc = repo.changelog.ancestors([repo[target].rev()])
904 bmctx = repo[marks[mark]]
904 bmctx = repo[marks[mark]]
905 divs = [repo[b].node() for b in marks
905 divs = [repo[b].node() for b in marks
906 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
906 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
907
907
908 # allow resolving a single divergent bookmark even if moving
908 # allow resolving a single divergent bookmark even if moving
909 # the bookmark across branches when a revision is specified
909 # the bookmark across branches when a revision is specified
910 # that contains a divergent bookmark
910 # that contains a divergent bookmark
911 if bmctx.rev() not in anc and target in divs:
911 if bmctx.rev() not in anc and target in divs:
912 bookmarks.deletedivergent(repo, [target], mark)
912 bookmarks.deletedivergent(repo, [target], mark)
913 return
913 return
914
914
915 deletefrom = [b for b in divs
915 deletefrom = [b for b in divs
916 if repo[b].rev() in anc or b == target]
916 if repo[b].rev() in anc or b == target]
917 bookmarks.deletedivergent(repo, deletefrom, mark)
917 bookmarks.deletedivergent(repo, deletefrom, mark)
918 if bookmarks.validdest(repo, bmctx, repo[target]):
918 if bookmarks.validdest(repo, bmctx, repo[target]):
919 ui.status(_("moving bookmark '%s' forward from %s\n") %
919 ui.status(_("moving bookmark '%s' forward from %s\n") %
920 (mark, short(bmctx.node())))
920 (mark, short(bmctx.node())))
921 return
921 return
922 raise util.Abort(_("bookmark '%s' already exists "
922 raise util.Abort(_("bookmark '%s' already exists "
923 "(use -f to force)") % mark)
923 "(use -f to force)") % mark)
924 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
924 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
925 and not force):
925 and not force):
926 raise util.Abort(
926 raise util.Abort(
927 _("a bookmark cannot have the name of an existing branch"))
927 _("a bookmark cannot have the name of an existing branch"))
928
928
929 if delete and rename:
929 if delete and rename:
930 raise util.Abort(_("--delete and --rename are incompatible"))
930 raise util.Abort(_("--delete and --rename are incompatible"))
931 if delete and rev:
931 if delete and rev:
932 raise util.Abort(_("--rev is incompatible with --delete"))
932 raise util.Abort(_("--rev is incompatible with --delete"))
933 if rename and rev:
933 if rename and rev:
934 raise util.Abort(_("--rev is incompatible with --rename"))
934 raise util.Abort(_("--rev is incompatible with --rename"))
935 if not names and (delete or rev):
935 if not names and (delete or rev):
936 raise util.Abort(_("bookmark name required"))
936 raise util.Abort(_("bookmark name required"))
937
937
938 if delete or rename or names or inactive:
938 if delete or rename or names or inactive:
939 wlock = repo.wlock()
939 wlock = repo.wlock()
940 try:
940 try:
941 cur = repo.changectx('.').node()
941 cur = repo.changectx('.').node()
942 marks = repo._bookmarks
942 marks = repo._bookmarks
943 if delete:
943 if delete:
944 for mark in names:
944 for mark in names:
945 if mark not in marks:
945 if mark not in marks:
946 raise util.Abort(_("bookmark '%s' does not exist") %
946 raise util.Abort(_("bookmark '%s' does not exist") %
947 mark)
947 mark)
948 if mark == repo._bookmarkcurrent:
948 if mark == repo._bookmarkcurrent:
949 bookmarks.unsetcurrent(repo)
949 bookmarks.unsetcurrent(repo)
950 del marks[mark]
950 del marks[mark]
951 marks.write()
951 marks.write()
952
952
953 elif rename:
953 elif rename:
954 if not names:
954 if not names:
955 raise util.Abort(_("new bookmark name required"))
955 raise util.Abort(_("new bookmark name required"))
956 elif len(names) > 1:
956 elif len(names) > 1:
957 raise util.Abort(_("only one new bookmark name allowed"))
957 raise util.Abort(_("only one new bookmark name allowed"))
958 mark = checkformat(names[0])
958 mark = checkformat(names[0])
959 if rename not in marks:
959 if rename not in marks:
960 raise util.Abort(_("bookmark '%s' does not exist") % rename)
960 raise util.Abort(_("bookmark '%s' does not exist") % rename)
961 checkconflict(repo, mark, cur, force)
961 checkconflict(repo, mark, cur, force)
962 marks[mark] = marks[rename]
962 marks[mark] = marks[rename]
963 if repo._bookmarkcurrent == rename and not inactive:
963 if repo._bookmarkcurrent == rename and not inactive:
964 bookmarks.setcurrent(repo, mark)
964 bookmarks.setcurrent(repo, mark)
965 del marks[rename]
965 del marks[rename]
966 marks.write()
966 marks.write()
967
967
968 elif names:
968 elif names:
969 newact = None
969 newact = None
970 for mark in names:
970 for mark in names:
971 mark = checkformat(mark)
971 mark = checkformat(mark)
972 if newact is None:
972 if newact is None:
973 newact = mark
973 newact = mark
974 if inactive and mark == repo._bookmarkcurrent:
974 if inactive and mark == repo._bookmarkcurrent:
975 bookmarks.unsetcurrent(repo)
975 bookmarks.unsetcurrent(repo)
976 return
976 return
977 tgt = cur
977 tgt = cur
978 if rev:
978 if rev:
979 tgt = scmutil.revsingle(repo, rev).node()
979 tgt = scmutil.revsingle(repo, rev).node()
980 checkconflict(repo, mark, cur, force, tgt)
980 checkconflict(repo, mark, cur, force, tgt)
981 marks[mark] = tgt
981 marks[mark] = tgt
982 if not inactive and cur == marks[newact] and not rev:
982 if not inactive and cur == marks[newact] and not rev:
983 bookmarks.setcurrent(repo, newact)
983 bookmarks.setcurrent(repo, newact)
984 elif cur != tgt and newact == repo._bookmarkcurrent:
984 elif cur != tgt and newact == repo._bookmarkcurrent:
985 bookmarks.unsetcurrent(repo)
985 bookmarks.unsetcurrent(repo)
986 marks.write()
986 marks.write()
987
987
988 elif inactive:
988 elif inactive:
989 if len(marks) == 0:
989 if len(marks) == 0:
990 ui.status(_("no bookmarks set\n"))
990 ui.status(_("no bookmarks set\n"))
991 elif not repo._bookmarkcurrent:
991 elif not repo._bookmarkcurrent:
992 ui.status(_("no active bookmark\n"))
992 ui.status(_("no active bookmark\n"))
993 else:
993 else:
994 bookmarks.unsetcurrent(repo)
994 bookmarks.unsetcurrent(repo)
995 finally:
995 finally:
996 wlock.release()
996 wlock.release()
997 else: # show bookmarks
997 else: # show bookmarks
998 fm = ui.formatter('bookmarks', opts)
998 fm = ui.formatter('bookmarks', opts)
999 hexfn = fm.hexfunc
999 hexfn = fm.hexfunc
1000 marks = repo._bookmarks
1000 marks = repo._bookmarks
1001 if len(marks) == 0 and not fm:
1001 if len(marks) == 0 and not fm:
1002 ui.status(_("no bookmarks set\n"))
1002 ui.status(_("no bookmarks set\n"))
1003 for bmark, n in sorted(marks.iteritems()):
1003 for bmark, n in sorted(marks.iteritems()):
1004 current = repo._bookmarkcurrent
1004 current = repo._bookmarkcurrent
1005 if bmark == current:
1005 if bmark == current:
1006 prefix, label = '*', 'bookmarks.current'
1006 prefix, label = '*', 'bookmarks.current'
1007 else:
1007 else:
1008 prefix, label = ' ', ''
1008 prefix, label = ' ', ''
1009
1009
1010 fm.startitem()
1010 fm.startitem()
1011 if not ui.quiet:
1011 if not ui.quiet:
1012 fm.plain(' %s ' % prefix, label=label)
1012 fm.plain(' %s ' % prefix, label=label)
1013 fm.write('bookmark', '%s', bmark, label=label)
1013 fm.write('bookmark', '%s', bmark, label=label)
1014 pad = " " * (25 - encoding.colwidth(bmark))
1014 pad = " " * (25 - encoding.colwidth(bmark))
1015 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1015 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1016 repo.changelog.rev(n), hexfn(n), label=label)
1016 repo.changelog.rev(n), hexfn(n), label=label)
1017 fm.data(active=(bmark == current))
1017 fm.data(active=(bmark == current))
1018 fm.plain('\n')
1018 fm.plain('\n')
1019 fm.end()
1019 fm.end()
1020
1020
1021 @command('branch',
1021 @command('branch',
1022 [('f', 'force', None,
1022 [('f', 'force', None,
1023 _('set branch name even if it shadows an existing branch')),
1023 _('set branch name even if it shadows an existing branch')),
1024 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1024 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1025 _('[-fC] [NAME]'))
1025 _('[-fC] [NAME]'))
1026 def branch(ui, repo, label=None, **opts):
1026 def branch(ui, repo, label=None, **opts):
1027 """set or show the current branch name
1027 """set or show the current branch name
1028
1028
1029 .. note::
1029 .. note::
1030
1030
1031 Branch names are permanent and global. Use :hg:`bookmark` to create a
1031 Branch names are permanent and global. Use :hg:`bookmark` to create a
1032 light-weight bookmark instead. See :hg:`help glossary` for more
1032 light-weight bookmark instead. See :hg:`help glossary` for more
1033 information about named branches and bookmarks.
1033 information about named branches and bookmarks.
1034
1034
1035 With no argument, show the current branch name. With one argument,
1035 With no argument, show the current branch name. With one argument,
1036 set the working directory branch name (the branch will not exist
1036 set the working directory branch name (the branch will not exist
1037 in the repository until the next commit). Standard practice
1037 in the repository until the next commit). Standard practice
1038 recommends that primary development take place on the 'default'
1038 recommends that primary development take place on the 'default'
1039 branch.
1039 branch.
1040
1040
1041 Unless -f/--force is specified, branch will not let you set a
1041 Unless -f/--force is specified, branch will not let you set a
1042 branch name that already exists.
1042 branch name that already exists.
1043
1043
1044 Use -C/--clean to reset the working directory branch to that of
1044 Use -C/--clean to reset the working directory branch to that of
1045 the parent of the working directory, negating a previous branch
1045 the parent of the working directory, negating a previous branch
1046 change.
1046 change.
1047
1047
1048 Use the command :hg:`update` to switch to an existing branch. Use
1048 Use the command :hg:`update` to switch to an existing branch. Use
1049 :hg:`commit --close-branch` to mark this branch as closed.
1049 :hg:`commit --close-branch` to mark this branch as closed.
1050
1050
1051 Returns 0 on success.
1051 Returns 0 on success.
1052 """
1052 """
1053 if label:
1053 if label:
1054 label = label.strip()
1054 label = label.strip()
1055
1055
1056 if not opts.get('clean') and not label:
1056 if not opts.get('clean') and not label:
1057 ui.write("%s\n" % repo.dirstate.branch())
1057 ui.write("%s\n" % repo.dirstate.branch())
1058 return
1058 return
1059
1059
1060 wlock = repo.wlock()
1060 wlock = repo.wlock()
1061 try:
1061 try:
1062 if opts.get('clean'):
1062 if opts.get('clean'):
1063 label = repo[None].p1().branch()
1063 label = repo[None].p1().branch()
1064 repo.dirstate.setbranch(label)
1064 repo.dirstate.setbranch(label)
1065 ui.status(_('reset working directory to branch %s\n') % label)
1065 ui.status(_('reset working directory to branch %s\n') % label)
1066 elif label:
1066 elif label:
1067 if not opts.get('force') and label in repo.branchmap():
1067 if not opts.get('force') and label in repo.branchmap():
1068 if label not in [p.branch() for p in repo.parents()]:
1068 if label not in [p.branch() for p in repo.parents()]:
1069 raise util.Abort(_('a branch of the same name already'
1069 raise util.Abort(_('a branch of the same name already'
1070 ' exists'),
1070 ' exists'),
1071 # i18n: "it" refers to an existing branch
1071 # i18n: "it" refers to an existing branch
1072 hint=_("use 'hg update' to switch to it"))
1072 hint=_("use 'hg update' to switch to it"))
1073 scmutil.checknewlabel(repo, label, 'branch')
1073 scmutil.checknewlabel(repo, label, 'branch')
1074 repo.dirstate.setbranch(label)
1074 repo.dirstate.setbranch(label)
1075 ui.status(_('marked working directory as branch %s\n') % label)
1075 ui.status(_('marked working directory as branch %s\n') % label)
1076 ui.status(_('(branches are permanent and global, '
1076 ui.status(_('(branches are permanent and global, '
1077 'did you want a bookmark?)\n'))
1077 'did you want a bookmark?)\n'))
1078 finally:
1078 finally:
1079 wlock.release()
1079 wlock.release()
1080
1080
1081 @command('branches',
1081 @command('branches',
1082 [('a', 'active', False,
1082 [('a', 'active', False,
1083 _('show only branches that have unmerged heads (DEPRECATED)')),
1083 _('show only branches that have unmerged heads (DEPRECATED)')),
1084 ('c', 'closed', False, _('show normal and closed branches')),
1084 ('c', 'closed', False, _('show normal and closed branches')),
1085 ] + formatteropts,
1085 ] + formatteropts,
1086 _('[-ac]'))
1086 _('[-ac]'))
1087 def branches(ui, repo, active=False, closed=False, **opts):
1087 def branches(ui, repo, active=False, closed=False, **opts):
1088 """list repository named branches
1088 """list repository named branches
1089
1089
1090 List the repository's named branches, indicating which ones are
1090 List the repository's named branches, indicating which ones are
1091 inactive. If -c/--closed is specified, also list branches which have
1091 inactive. If -c/--closed is specified, also list branches which have
1092 been marked closed (see :hg:`commit --close-branch`).
1092 been marked closed (see :hg:`commit --close-branch`).
1093
1093
1094 Use the command :hg:`update` to switch to an existing branch.
1094 Use the command :hg:`update` to switch to an existing branch.
1095
1095
1096 Returns 0.
1096 Returns 0.
1097 """
1097 """
1098
1098
1099 fm = ui.formatter('branches', opts)
1099 fm = ui.formatter('branches', opts)
1100 hexfunc = fm.hexfunc
1100 hexfunc = fm.hexfunc
1101
1101
1102 allheads = set(repo.heads())
1102 allheads = set(repo.heads())
1103 branches = []
1103 branches = []
1104 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1104 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1105 isactive = not isclosed and bool(set(heads) & allheads)
1105 isactive = not isclosed and bool(set(heads) & allheads)
1106 branches.append((tag, repo[tip], isactive, not isclosed))
1106 branches.append((tag, repo[tip], isactive, not isclosed))
1107 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1107 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1108 reverse=True)
1108 reverse=True)
1109
1109
1110 for tag, ctx, isactive, isopen in branches:
1110 for tag, ctx, isactive, isopen in branches:
1111 if active and not isactive:
1111 if active and not isactive:
1112 continue
1112 continue
1113 if isactive:
1113 if isactive:
1114 label = 'branches.active'
1114 label = 'branches.active'
1115 notice = ''
1115 notice = ''
1116 elif not isopen:
1116 elif not isopen:
1117 if not closed:
1117 if not closed:
1118 continue
1118 continue
1119 label = 'branches.closed'
1119 label = 'branches.closed'
1120 notice = _(' (closed)')
1120 notice = _(' (closed)')
1121 else:
1121 else:
1122 label = 'branches.inactive'
1122 label = 'branches.inactive'
1123 notice = _(' (inactive)')
1123 notice = _(' (inactive)')
1124 current = (tag == repo.dirstate.branch())
1124 current = (tag == repo.dirstate.branch())
1125 if current:
1125 if current:
1126 label = 'branches.current'
1126 label = 'branches.current'
1127
1127
1128 fm.startitem()
1128 fm.startitem()
1129 fm.write('branch', '%s', tag, label=label)
1129 fm.write('branch', '%s', tag, label=label)
1130 rev = ctx.rev()
1130 rev = ctx.rev()
1131 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1131 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1132 fmt = ' ' * padsize + ' %d:%s'
1132 fmt = ' ' * padsize + ' %d:%s'
1133 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1133 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1134 label='log.changeset changeset.%s' % ctx.phasestr())
1134 label='log.changeset changeset.%s' % ctx.phasestr())
1135 fm.data(active=isactive, closed=not isopen, current=current)
1135 fm.data(active=isactive, closed=not isopen, current=current)
1136 if not ui.quiet:
1136 if not ui.quiet:
1137 fm.plain(notice)
1137 fm.plain(notice)
1138 fm.plain('\n')
1138 fm.plain('\n')
1139 fm.end()
1139 fm.end()
1140
1140
1141 @command('bundle',
1141 @command('bundle',
1142 [('f', 'force', None, _('run even when the destination is unrelated')),
1142 [('f', 'force', None, _('run even when the destination is unrelated')),
1143 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1143 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1144 _('REV')),
1144 _('REV')),
1145 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1145 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1146 _('BRANCH')),
1146 _('BRANCH')),
1147 ('', 'base', [],
1147 ('', 'base', [],
1148 _('a base changeset assumed to be available at the destination'),
1148 _('a base changeset assumed to be available at the destination'),
1149 _('REV')),
1149 _('REV')),
1150 ('a', 'all', None, _('bundle all changesets in the repository')),
1150 ('a', 'all', None, _('bundle all changesets in the repository')),
1151 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1151 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1152 ] + remoteopts,
1152 ] + remoteopts,
1153 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1153 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1154 def bundle(ui, repo, fname, dest=None, **opts):
1154 def bundle(ui, repo, fname, dest=None, **opts):
1155 """create a changegroup file
1155 """create a changegroup file
1156
1156
1157 Generate a compressed changegroup file collecting changesets not
1157 Generate a compressed changegroup file collecting changesets not
1158 known to be in another repository.
1158 known to be in another repository.
1159
1159
1160 If you omit the destination repository, then hg assumes the
1160 If you omit the destination repository, then hg assumes the
1161 destination will have all the nodes you specify with --base
1161 destination will have all the nodes you specify with --base
1162 parameters. To create a bundle containing all changesets, use
1162 parameters. To create a bundle containing all changesets, use
1163 -a/--all (or --base null).
1163 -a/--all (or --base null).
1164
1164
1165 You can change compression method with the -t/--type option.
1165 You can change compression method with the -t/--type option.
1166 The available compression methods are: none, bzip2, and
1166 The available compression methods are: none, bzip2, and
1167 gzip (by default, bundles are compressed using bzip2).
1167 gzip (by default, bundles are compressed using bzip2).
1168
1168
1169 The bundle file can then be transferred using conventional means
1169 The bundle file can then be transferred using conventional means
1170 and applied to another repository with the unbundle or pull
1170 and applied to another repository with the unbundle or pull
1171 command. This is useful when direct push and pull are not
1171 command. This is useful when direct push and pull are not
1172 available or when exporting an entire repository is undesirable.
1172 available or when exporting an entire repository is undesirable.
1173
1173
1174 Applying bundles preserves all changeset contents including
1174 Applying bundles preserves all changeset contents including
1175 permissions, copy/rename information, and revision history.
1175 permissions, copy/rename information, and revision history.
1176
1176
1177 Returns 0 on success, 1 if no changes found.
1177 Returns 0 on success, 1 if no changes found.
1178 """
1178 """
1179 revs = None
1179 revs = None
1180 if 'rev' in opts:
1180 if 'rev' in opts:
1181 revs = scmutil.revrange(repo, opts['rev'])
1181 revs = scmutil.revrange(repo, opts['rev'])
1182
1182
1183 bundletype = opts.get('type', 'bzip2').lower()
1183 bundletype = opts.get('type', 'bzip2').lower()
1184 btypes = {'none': 'HG10UN',
1184 btypes = {'none': 'HG10UN',
1185 'bzip2': 'HG10BZ',
1185 'bzip2': 'HG10BZ',
1186 'gzip': 'HG10GZ',
1186 'gzip': 'HG10GZ',
1187 'bundle2': 'HG2Y'}
1187 'bundle2': 'HG2Y'}
1188 bundletype = btypes.get(bundletype)
1188 bundletype = btypes.get(bundletype)
1189 if bundletype not in changegroup.bundletypes:
1189 if bundletype not in changegroup.bundletypes:
1190 raise util.Abort(_('unknown bundle type specified with --type'))
1190 raise util.Abort(_('unknown bundle type specified with --type'))
1191
1191
1192 if opts.get('all'):
1192 if opts.get('all'):
1193 base = ['null']
1193 base = ['null']
1194 else:
1194 else:
1195 base = scmutil.revrange(repo, opts.get('base'))
1195 base = scmutil.revrange(repo, opts.get('base'))
1196 # TODO: get desired bundlecaps from command line.
1196 # TODO: get desired bundlecaps from command line.
1197 bundlecaps = None
1197 bundlecaps = None
1198 if base:
1198 if base:
1199 if dest:
1199 if dest:
1200 raise util.Abort(_("--base is incompatible with specifying "
1200 raise util.Abort(_("--base is incompatible with specifying "
1201 "a destination"))
1201 "a destination"))
1202 common = [repo.lookup(rev) for rev in base]
1202 common = [repo.lookup(rev) for rev in base]
1203 heads = revs and map(repo.lookup, revs) or revs
1203 heads = revs and map(repo.lookup, revs) or revs
1204 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1204 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1205 common=common, bundlecaps=bundlecaps)
1205 common=common, bundlecaps=bundlecaps)
1206 outgoing = None
1206 outgoing = None
1207 else:
1207 else:
1208 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1208 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1209 dest, branches = hg.parseurl(dest, opts.get('branch'))
1209 dest, branches = hg.parseurl(dest, opts.get('branch'))
1210 other = hg.peer(repo, opts, dest)
1210 other = hg.peer(repo, opts, dest)
1211 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1211 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1212 heads = revs and map(repo.lookup, revs) or revs
1212 heads = revs and map(repo.lookup, revs) or revs
1213 outgoing = discovery.findcommonoutgoing(repo, other,
1213 outgoing = discovery.findcommonoutgoing(repo, other,
1214 onlyheads=heads,
1214 onlyheads=heads,
1215 force=opts.get('force'),
1215 force=opts.get('force'),
1216 portable=True)
1216 portable=True)
1217 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1217 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1218 bundlecaps)
1218 bundlecaps)
1219 if not cg:
1219 if not cg:
1220 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1220 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1221 return 1
1221 return 1
1222
1222
1223 changegroup.writebundle(ui, cg, fname, bundletype)
1223 changegroup.writebundle(ui, cg, fname, bundletype)
1224
1224
1225 @command('cat',
1225 @command('cat',
1226 [('o', 'output', '',
1226 [('o', 'output', '',
1227 _('print output to file with formatted name'), _('FORMAT')),
1227 _('print output to file with formatted name'), _('FORMAT')),
1228 ('r', 'rev', '', _('print the given revision'), _('REV')),
1228 ('r', 'rev', '', _('print the given revision'), _('REV')),
1229 ('', 'decode', None, _('apply any matching decode filter')),
1229 ('', 'decode', None, _('apply any matching decode filter')),
1230 ] + walkopts,
1230 ] + walkopts,
1231 _('[OPTION]... FILE...'),
1231 _('[OPTION]... FILE...'),
1232 inferrepo=True)
1232 inferrepo=True)
1233 def cat(ui, repo, file1, *pats, **opts):
1233 def cat(ui, repo, file1, *pats, **opts):
1234 """output the current or given revision of files
1234 """output the current or given revision of files
1235
1235
1236 Print the specified files as they were at the given revision. If
1236 Print the specified files as they were at the given revision. If
1237 no revision is given, the parent of the working directory is used.
1237 no revision is given, the parent of the working directory is used.
1238
1238
1239 Output may be to a file, in which case the name of the file is
1239 Output may be to a file, in which case the name of the file is
1240 given using a format string. The formatting rules as follows:
1240 given using a format string. The formatting rules as follows:
1241
1241
1242 :``%%``: literal "%" character
1242 :``%%``: literal "%" character
1243 :``%s``: basename of file being printed
1243 :``%s``: basename of file being printed
1244 :``%d``: dirname of file being printed, or '.' if in repository root
1244 :``%d``: dirname of file being printed, or '.' if in repository root
1245 :``%p``: root-relative path name of file being printed
1245 :``%p``: root-relative path name of file being printed
1246 :``%H``: changeset hash (40 hexadecimal digits)
1246 :``%H``: changeset hash (40 hexadecimal digits)
1247 :``%R``: changeset revision number
1247 :``%R``: changeset revision number
1248 :``%h``: short-form changeset hash (12 hexadecimal digits)
1248 :``%h``: short-form changeset hash (12 hexadecimal digits)
1249 :``%r``: zero-padded changeset revision number
1249 :``%r``: zero-padded changeset revision number
1250 :``%b``: basename of the exporting repository
1250 :``%b``: basename of the exporting repository
1251
1251
1252 Returns 0 on success.
1252 Returns 0 on success.
1253 """
1253 """
1254 ctx = scmutil.revsingle(repo, opts.get('rev'))
1254 ctx = scmutil.revsingle(repo, opts.get('rev'))
1255 m = scmutil.match(ctx, (file1,) + pats, opts)
1255 m = scmutil.match(ctx, (file1,) + pats, opts)
1256
1256
1257 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1257 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1258
1258
1259 @command('^clone',
1259 @command('^clone',
1260 [('U', 'noupdate', None,
1260 [('U', 'noupdate', None,
1261 _('the clone will include an empty working copy (only a repository)')),
1261 _('the clone will include an empty working copy (only a repository)')),
1262 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1262 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1263 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1263 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1264 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1264 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1265 ('', 'pull', None, _('use pull protocol to copy metadata')),
1265 ('', 'pull', None, _('use pull protocol to copy metadata')),
1266 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1266 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1267 ] + remoteopts,
1267 ] + remoteopts,
1268 _('[OPTION]... SOURCE [DEST]'),
1268 _('[OPTION]... SOURCE [DEST]'),
1269 norepo=True)
1269 norepo=True)
1270 def clone(ui, source, dest=None, **opts):
1270 def clone(ui, source, dest=None, **opts):
1271 """make a copy of an existing repository
1271 """make a copy of an existing repository
1272
1272
1273 Create a copy of an existing repository in a new directory.
1273 Create a copy of an existing repository in a new directory.
1274
1274
1275 If no destination directory name is specified, it defaults to the
1275 If no destination directory name is specified, it defaults to the
1276 basename of the source.
1276 basename of the source.
1277
1277
1278 The location of the source is added to the new repository's
1278 The location of the source is added to the new repository's
1279 ``.hg/hgrc`` file, as the default to be used for future pulls.
1279 ``.hg/hgrc`` file, as the default to be used for future pulls.
1280
1280
1281 Only local paths and ``ssh://`` URLs are supported as
1281 Only local paths and ``ssh://`` URLs are supported as
1282 destinations. For ``ssh://`` destinations, no working directory or
1282 destinations. For ``ssh://`` destinations, no working directory or
1283 ``.hg/hgrc`` will be created on the remote side.
1283 ``.hg/hgrc`` will be created on the remote side.
1284
1284
1285 To pull only a subset of changesets, specify one or more revisions
1285 To pull only a subset of changesets, specify one or more revisions
1286 identifiers with -r/--rev or branches with -b/--branch. The
1286 identifiers with -r/--rev or branches with -b/--branch. The
1287 resulting clone will contain only the specified changesets and
1287 resulting clone will contain only the specified changesets and
1288 their ancestors. These options (or 'clone src#rev dest') imply
1288 their ancestors. These options (or 'clone src#rev dest') imply
1289 --pull, even for local source repositories. Note that specifying a
1289 --pull, even for local source repositories. Note that specifying a
1290 tag will include the tagged changeset but not the changeset
1290 tag will include the tagged changeset but not the changeset
1291 containing the tag.
1291 containing the tag.
1292
1292
1293 If the source repository has a bookmark called '@' set, that
1293 If the source repository has a bookmark called '@' set, that
1294 revision will be checked out in the new repository by default.
1294 revision will be checked out in the new repository by default.
1295
1295
1296 To check out a particular version, use -u/--update, or
1296 To check out a particular version, use -u/--update, or
1297 -U/--noupdate to create a clone with no working directory.
1297 -U/--noupdate to create a clone with no working directory.
1298
1298
1299 .. container:: verbose
1299 .. container:: verbose
1300
1300
1301 For efficiency, hardlinks are used for cloning whenever the
1301 For efficiency, hardlinks are used for cloning whenever the
1302 source and destination are on the same filesystem (note this
1302 source and destination are on the same filesystem (note this
1303 applies only to the repository data, not to the working
1303 applies only to the repository data, not to the working
1304 directory). Some filesystems, such as AFS, implement hardlinking
1304 directory). Some filesystems, such as AFS, implement hardlinking
1305 incorrectly, but do not report errors. In these cases, use the
1305 incorrectly, but do not report errors. In these cases, use the
1306 --pull option to avoid hardlinking.
1306 --pull option to avoid hardlinking.
1307
1307
1308 In some cases, you can clone repositories and the working
1308 In some cases, you can clone repositories and the working
1309 directory using full hardlinks with ::
1309 directory using full hardlinks with ::
1310
1310
1311 $ cp -al REPO REPOCLONE
1311 $ cp -al REPO REPOCLONE
1312
1312
1313 This is the fastest way to clone, but it is not always safe. The
1313 This is the fastest way to clone, but it is not always safe. The
1314 operation is not atomic (making sure REPO is not modified during
1314 operation is not atomic (making sure REPO is not modified during
1315 the operation is up to you) and you have to make sure your
1315 the operation is up to you) and you have to make sure your
1316 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1316 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1317 so). Also, this is not compatible with certain extensions that
1317 so). Also, this is not compatible with certain extensions that
1318 place their metadata under the .hg directory, such as mq.
1318 place their metadata under the .hg directory, such as mq.
1319
1319
1320 Mercurial will update the working directory to the first applicable
1320 Mercurial will update the working directory to the first applicable
1321 revision from this list:
1321 revision from this list:
1322
1322
1323 a) null if -U or the source repository has no changesets
1323 a) null if -U or the source repository has no changesets
1324 b) if -u . and the source repository is local, the first parent of
1324 b) if -u . and the source repository is local, the first parent of
1325 the source repository's working directory
1325 the source repository's working directory
1326 c) the changeset specified with -u (if a branch name, this means the
1326 c) the changeset specified with -u (if a branch name, this means the
1327 latest head of that branch)
1327 latest head of that branch)
1328 d) the changeset specified with -r
1328 d) the changeset specified with -r
1329 e) the tipmost head specified with -b
1329 e) the tipmost head specified with -b
1330 f) the tipmost head specified with the url#branch source syntax
1330 f) the tipmost head specified with the url#branch source syntax
1331 g) the revision marked with the '@' bookmark, if present
1331 g) the revision marked with the '@' bookmark, if present
1332 h) the tipmost head of the default branch
1332 h) the tipmost head of the default branch
1333 i) tip
1333 i) tip
1334
1334
1335 Examples:
1335 Examples:
1336
1336
1337 - clone a remote repository to a new directory named hg/::
1337 - clone a remote repository to a new directory named hg/::
1338
1338
1339 hg clone http://selenic.com/hg
1339 hg clone http://selenic.com/hg
1340
1340
1341 - create a lightweight local clone::
1341 - create a lightweight local clone::
1342
1342
1343 hg clone project/ project-feature/
1343 hg clone project/ project-feature/
1344
1344
1345 - clone from an absolute path on an ssh server (note double-slash)::
1345 - clone from an absolute path on an ssh server (note double-slash)::
1346
1346
1347 hg clone ssh://user@server//home/projects/alpha/
1347 hg clone ssh://user@server//home/projects/alpha/
1348
1348
1349 - do a high-speed clone over a LAN while checking out a
1349 - do a high-speed clone over a LAN while checking out a
1350 specified version::
1350 specified version::
1351
1351
1352 hg clone --uncompressed http://server/repo -u 1.5
1352 hg clone --uncompressed http://server/repo -u 1.5
1353
1353
1354 - create a repository without changesets after a particular revision::
1354 - create a repository without changesets after a particular revision::
1355
1355
1356 hg clone -r 04e544 experimental/ good/
1356 hg clone -r 04e544 experimental/ good/
1357
1357
1358 - clone (and track) a particular named branch::
1358 - clone (and track) a particular named branch::
1359
1359
1360 hg clone http://selenic.com/hg#stable
1360 hg clone http://selenic.com/hg#stable
1361
1361
1362 See :hg:`help urls` for details on specifying URLs.
1362 See :hg:`help urls` for details on specifying URLs.
1363
1363
1364 Returns 0 on success.
1364 Returns 0 on success.
1365 """
1365 """
1366 if opts.get('noupdate') and opts.get('updaterev'):
1366 if opts.get('noupdate') and opts.get('updaterev'):
1367 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1367 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1368
1368
1369 r = hg.clone(ui, opts, source, dest,
1369 r = hg.clone(ui, opts, source, dest,
1370 pull=opts.get('pull'),
1370 pull=opts.get('pull'),
1371 stream=opts.get('uncompressed'),
1371 stream=opts.get('uncompressed'),
1372 rev=opts.get('rev'),
1372 rev=opts.get('rev'),
1373 update=opts.get('updaterev') or not opts.get('noupdate'),
1373 update=opts.get('updaterev') or not opts.get('noupdate'),
1374 branch=opts.get('branch'))
1374 branch=opts.get('branch'))
1375
1375
1376 return r is None
1376 return r is None
1377
1377
1378 @command('^commit|ci',
1378 @command('^commit|ci',
1379 [('A', 'addremove', None,
1379 [('A', 'addremove', None,
1380 _('mark new/missing files as added/removed before committing')),
1380 _('mark new/missing files as added/removed before committing')),
1381 ('', 'close-branch', None,
1381 ('', 'close-branch', None,
1382 _('mark a branch as closed, hiding it from the branch list')),
1382 _('mark a branch as closed, hiding it from the branch list')),
1383 ('', 'amend', None, _('amend the parent of the working dir')),
1383 ('', 'amend', None, _('amend the parent of the working dir')),
1384 ('s', 'secret', None, _('use the secret phase for committing')),
1384 ('s', 'secret', None, _('use the secret phase for committing')),
1385 ('e', 'edit', None, _('invoke editor on commit messages')),
1385 ('e', 'edit', None, _('invoke editor on commit messages')),
1386 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1386 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1387 _('[OPTION]... [FILE]...'),
1387 _('[OPTION]... [FILE]...'),
1388 inferrepo=True)
1388 inferrepo=True)
1389 def commit(ui, repo, *pats, **opts):
1389 def commit(ui, repo, *pats, **opts):
1390 """commit the specified files or all outstanding changes
1390 """commit the specified files or all outstanding changes
1391
1391
1392 Commit changes to the given files into the repository. Unlike a
1392 Commit changes to the given files into the repository. Unlike a
1393 centralized SCM, this operation is a local operation. See
1393 centralized SCM, this operation is a local operation. See
1394 :hg:`push` for a way to actively distribute your changes.
1394 :hg:`push` for a way to actively distribute your changes.
1395
1395
1396 If a list of files is omitted, all changes reported by :hg:`status`
1396 If a list of files is omitted, all changes reported by :hg:`status`
1397 will be committed.
1397 will be committed.
1398
1398
1399 If you are committing the result of a merge, do not provide any
1399 If you are committing the result of a merge, do not provide any
1400 filenames or -I/-X filters.
1400 filenames or -I/-X filters.
1401
1401
1402 If no commit message is specified, Mercurial starts your
1402 If no commit message is specified, Mercurial starts your
1403 configured editor where you can enter a message. In case your
1403 configured editor where you can enter a message. In case your
1404 commit fails, you will find a backup of your message in
1404 commit fails, you will find a backup of your message in
1405 ``.hg/last-message.txt``.
1405 ``.hg/last-message.txt``.
1406
1406
1407 The --amend flag can be used to amend the parent of the
1407 The --amend flag can be used to amend the parent of the
1408 working directory with a new commit that contains the changes
1408 working directory with a new commit that contains the changes
1409 in the parent in addition to those currently reported by :hg:`status`,
1409 in the parent in addition to those currently reported by :hg:`status`,
1410 if there are any. The old commit is stored in a backup bundle in
1410 if there are any. The old commit is stored in a backup bundle in
1411 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1411 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1412 on how to restore it).
1412 on how to restore it).
1413
1413
1414 Message, user and date are taken from the amended commit unless
1414 Message, user and date are taken from the amended commit unless
1415 specified. When a message isn't specified on the command line,
1415 specified. When a message isn't specified on the command line,
1416 the editor will open with the message of the amended commit.
1416 the editor will open with the message of the amended commit.
1417
1417
1418 It is not possible to amend public changesets (see :hg:`help phases`)
1418 It is not possible to amend public changesets (see :hg:`help phases`)
1419 or changesets that have children.
1419 or changesets that have children.
1420
1420
1421 See :hg:`help dates` for a list of formats valid for -d/--date.
1421 See :hg:`help dates` for a list of formats valid for -d/--date.
1422
1422
1423 Returns 0 on success, 1 if nothing changed.
1423 Returns 0 on success, 1 if nothing changed.
1424 """
1424 """
1425 if opts.get('subrepos'):
1425 if opts.get('subrepos'):
1426 if opts.get('amend'):
1426 if opts.get('amend'):
1427 raise util.Abort(_('cannot amend with --subrepos'))
1427 raise util.Abort(_('cannot amend with --subrepos'))
1428 # Let --subrepos on the command line override config setting.
1428 # Let --subrepos on the command line override config setting.
1429 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1429 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1430
1430
1431 cmdutil.checkunfinished(repo, commit=True)
1431 cmdutil.checkunfinished(repo, commit=True)
1432
1432
1433 branch = repo[None].branch()
1433 branch = repo[None].branch()
1434 bheads = repo.branchheads(branch)
1434 bheads = repo.branchheads(branch)
1435
1435
1436 extra = {}
1436 extra = {}
1437 if opts.get('close_branch'):
1437 if opts.get('close_branch'):
1438 extra['close'] = 1
1438 extra['close'] = 1
1439
1439
1440 if not bheads:
1440 if not bheads:
1441 raise util.Abort(_('can only close branch heads'))
1441 raise util.Abort(_('can only close branch heads'))
1442 elif opts.get('amend'):
1442 elif opts.get('amend'):
1443 if repo.parents()[0].p1().branch() != branch and \
1443 if repo.parents()[0].p1().branch() != branch and \
1444 repo.parents()[0].p2().branch() != branch:
1444 repo.parents()[0].p2().branch() != branch:
1445 raise util.Abort(_('can only close branch heads'))
1445 raise util.Abort(_('can only close branch heads'))
1446
1446
1447 if opts.get('amend'):
1447 if opts.get('amend'):
1448 if ui.configbool('ui', 'commitsubrepos'):
1448 if ui.configbool('ui', 'commitsubrepos'):
1449 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1449 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1450
1450
1451 old = repo['.']
1451 old = repo['.']
1452 if not old.mutable():
1452 if not old.mutable():
1453 raise util.Abort(_('cannot amend public changesets'))
1453 raise util.Abort(_('cannot amend public changesets'))
1454 if len(repo[None].parents()) > 1:
1454 if len(repo[None].parents()) > 1:
1455 raise util.Abort(_('cannot amend while merging'))
1455 raise util.Abort(_('cannot amend while merging'))
1456 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1456 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1457 if not allowunstable and old.children():
1457 if not allowunstable and old.children():
1458 raise util.Abort(_('cannot amend changeset with children'))
1458 raise util.Abort(_('cannot amend changeset with children'))
1459
1459
1460 # commitfunc is used only for temporary amend commit by cmdutil.amend
1460 # commitfunc is used only for temporary amend commit by cmdutil.amend
1461 def commitfunc(ui, repo, message, match, opts):
1461 def commitfunc(ui, repo, message, match, opts):
1462 return repo.commit(message,
1462 return repo.commit(message,
1463 opts.get('user') or old.user(),
1463 opts.get('user') or old.user(),
1464 opts.get('date') or old.date(),
1464 opts.get('date') or old.date(),
1465 match,
1465 match,
1466 extra=extra)
1466 extra=extra)
1467
1467
1468 current = repo._bookmarkcurrent
1468 current = repo._bookmarkcurrent
1469 marks = old.bookmarks()
1469 marks = old.bookmarks()
1470 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1470 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1471 if node == old.node():
1471 if node == old.node():
1472 ui.status(_("nothing changed\n"))
1472 ui.status(_("nothing changed\n"))
1473 return 1
1473 return 1
1474 elif marks:
1474 elif marks:
1475 ui.debug('moving bookmarks %r from %s to %s\n' %
1475 ui.debug('moving bookmarks %r from %s to %s\n' %
1476 (marks, old.hex(), hex(node)))
1476 (marks, old.hex(), hex(node)))
1477 newmarks = repo._bookmarks
1477 newmarks = repo._bookmarks
1478 for bm in marks:
1478 for bm in marks:
1479 newmarks[bm] = node
1479 newmarks[bm] = node
1480 if bm == current:
1480 if bm == current:
1481 bookmarks.setcurrent(repo, bm)
1481 bookmarks.setcurrent(repo, bm)
1482 newmarks.write()
1482 newmarks.write()
1483 else:
1483 else:
1484 def commitfunc(ui, repo, message, match, opts):
1484 def commitfunc(ui, repo, message, match, opts):
1485 backup = ui.backupconfig('phases', 'new-commit')
1485 backup = ui.backupconfig('phases', 'new-commit')
1486 baseui = repo.baseui
1486 baseui = repo.baseui
1487 basebackup = baseui.backupconfig('phases', 'new-commit')
1487 basebackup = baseui.backupconfig('phases', 'new-commit')
1488 try:
1488 try:
1489 if opts.get('secret'):
1489 if opts.get('secret'):
1490 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1490 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1491 # Propagate to subrepos
1491 # Propagate to subrepos
1492 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1492 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1493
1493
1494 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1494 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1495 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1495 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1496 return repo.commit(message, opts.get('user'), opts.get('date'),
1496 return repo.commit(message, opts.get('user'), opts.get('date'),
1497 match,
1497 match,
1498 editor=editor,
1498 editor=editor,
1499 extra=extra)
1499 extra=extra)
1500 finally:
1500 finally:
1501 ui.restoreconfig(backup)
1501 ui.restoreconfig(backup)
1502 repo.baseui.restoreconfig(basebackup)
1502 repo.baseui.restoreconfig(basebackup)
1503
1503
1504
1504
1505 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1505 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1506
1506
1507 if not node:
1507 if not node:
1508 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1508 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1509 if stat[3]:
1509 if stat[3]:
1510 ui.status(_("nothing changed (%d missing files, see "
1510 ui.status(_("nothing changed (%d missing files, see "
1511 "'hg status')\n") % len(stat[3]))
1511 "'hg status')\n") % len(stat[3]))
1512 else:
1512 else:
1513 ui.status(_("nothing changed\n"))
1513 ui.status(_("nothing changed\n"))
1514 return 1
1514 return 1
1515
1515
1516 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1516 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1517
1517
1518 @command('config|showconfig|debugconfig',
1518 @command('config|showconfig|debugconfig',
1519 [('u', 'untrusted', None, _('show untrusted configuration options')),
1519 [('u', 'untrusted', None, _('show untrusted configuration options')),
1520 ('e', 'edit', None, _('edit user config')),
1520 ('e', 'edit', None, _('edit user config')),
1521 ('l', 'local', None, _('edit repository config')),
1521 ('l', 'local', None, _('edit repository config')),
1522 ('g', 'global', None, _('edit global config'))],
1522 ('g', 'global', None, _('edit global config'))],
1523 _('[-u] [NAME]...'),
1523 _('[-u] [NAME]...'),
1524 optionalrepo=True)
1524 optionalrepo=True)
1525 def config(ui, repo, *values, **opts):
1525 def config(ui, repo, *values, **opts):
1526 """show combined config settings from all hgrc files
1526 """show combined config settings from all hgrc files
1527
1527
1528 With no arguments, print names and values of all config items.
1528 With no arguments, print names and values of all config items.
1529
1529
1530 With one argument of the form section.name, print just the value
1530 With one argument of the form section.name, print just the value
1531 of that config item.
1531 of that config item.
1532
1532
1533 With multiple arguments, print names and values of all config
1533 With multiple arguments, print names and values of all config
1534 items with matching section names.
1534 items with matching section names.
1535
1535
1536 With --edit, start an editor on the user-level config file. With
1536 With --edit, start an editor on the user-level config file. With
1537 --global, edit the system-wide config file. With --local, edit the
1537 --global, edit the system-wide config file. With --local, edit the
1538 repository-level config file.
1538 repository-level config file.
1539
1539
1540 With --debug, the source (filename and line number) is printed
1540 With --debug, the source (filename and line number) is printed
1541 for each config item.
1541 for each config item.
1542
1542
1543 See :hg:`help config` for more information about config files.
1543 See :hg:`help config` for more information about config files.
1544
1544
1545 Returns 0 on success, 1 if NAME does not exist.
1545 Returns 0 on success, 1 if NAME does not exist.
1546
1546
1547 """
1547 """
1548
1548
1549 if opts.get('edit') or opts.get('local') or opts.get('global'):
1549 if opts.get('edit') or opts.get('local') or opts.get('global'):
1550 if opts.get('local') and opts.get('global'):
1550 if opts.get('local') and opts.get('global'):
1551 raise util.Abort(_("can't use --local and --global together"))
1551 raise util.Abort(_("can't use --local and --global together"))
1552
1552
1553 if opts.get('local'):
1553 if opts.get('local'):
1554 if not repo:
1554 if not repo:
1555 raise util.Abort(_("can't use --local outside a repository"))
1555 raise util.Abort(_("can't use --local outside a repository"))
1556 paths = [repo.join('hgrc')]
1556 paths = [repo.join('hgrc')]
1557 elif opts.get('global'):
1557 elif opts.get('global'):
1558 paths = scmutil.systemrcpath()
1558 paths = scmutil.systemrcpath()
1559 else:
1559 else:
1560 paths = scmutil.userrcpath()
1560 paths = scmutil.userrcpath()
1561
1561
1562 for f in paths:
1562 for f in paths:
1563 if os.path.exists(f):
1563 if os.path.exists(f):
1564 break
1564 break
1565 else:
1565 else:
1566 if opts.get('global'):
1566 if opts.get('global'):
1567 samplehgrc = uimod.samplehgrcs['global']
1567 samplehgrc = uimod.samplehgrcs['global']
1568 elif opts.get('local'):
1568 elif opts.get('local'):
1569 samplehgrc = uimod.samplehgrcs['local']
1569 samplehgrc = uimod.samplehgrcs['local']
1570 else:
1570 else:
1571 samplehgrc = uimod.samplehgrcs['user']
1571 samplehgrc = uimod.samplehgrcs['user']
1572
1572
1573 f = paths[0]
1573 f = paths[0]
1574 fp = open(f, "w")
1574 fp = open(f, "w")
1575 fp.write(samplehgrc)
1575 fp.write(samplehgrc)
1576 fp.close()
1576 fp.close()
1577
1577
1578 editor = ui.geteditor()
1578 editor = ui.geteditor()
1579 ui.system("%s \"%s\"" % (editor, f),
1579 ui.system("%s \"%s\"" % (editor, f),
1580 onerr=util.Abort, errprefix=_("edit failed"))
1580 onerr=util.Abort, errprefix=_("edit failed"))
1581 return
1581 return
1582
1582
1583 for f in scmutil.rcpath():
1583 for f in scmutil.rcpath():
1584 ui.debug('read config from: %s\n' % f)
1584 ui.debug('read config from: %s\n' % f)
1585 untrusted = bool(opts.get('untrusted'))
1585 untrusted = bool(opts.get('untrusted'))
1586 if values:
1586 if values:
1587 sections = [v for v in values if '.' not in v]
1587 sections = [v for v in values if '.' not in v]
1588 items = [v for v in values if '.' in v]
1588 items = [v for v in values if '.' in v]
1589 if len(items) > 1 or items and sections:
1589 if len(items) > 1 or items and sections:
1590 raise util.Abort(_('only one config item permitted'))
1590 raise util.Abort(_('only one config item permitted'))
1591 matched = False
1591 matched = False
1592 for section, name, value in ui.walkconfig(untrusted=untrusted):
1592 for section, name, value in ui.walkconfig(untrusted=untrusted):
1593 value = str(value).replace('\n', '\\n')
1593 value = str(value).replace('\n', '\\n')
1594 sectname = section + '.' + name
1594 sectname = section + '.' + name
1595 if values:
1595 if values:
1596 for v in values:
1596 for v in values:
1597 if v == section:
1597 if v == section:
1598 ui.debug('%s: ' %
1598 ui.debug('%s: ' %
1599 ui.configsource(section, name, untrusted))
1599 ui.configsource(section, name, untrusted))
1600 ui.write('%s=%s\n' % (sectname, value))
1600 ui.write('%s=%s\n' % (sectname, value))
1601 matched = True
1601 matched = True
1602 elif v == sectname:
1602 elif v == sectname:
1603 ui.debug('%s: ' %
1603 ui.debug('%s: ' %
1604 ui.configsource(section, name, untrusted))
1604 ui.configsource(section, name, untrusted))
1605 ui.write(value, '\n')
1605 ui.write(value, '\n')
1606 matched = True
1606 matched = True
1607 else:
1607 else:
1608 ui.debug('%s: ' %
1608 ui.debug('%s: ' %
1609 ui.configsource(section, name, untrusted))
1609 ui.configsource(section, name, untrusted))
1610 ui.write('%s=%s\n' % (sectname, value))
1610 ui.write('%s=%s\n' % (sectname, value))
1611 matched = True
1611 matched = True
1612 if matched:
1612 if matched:
1613 return 0
1613 return 0
1614 return 1
1614 return 1
1615
1615
1616 @command('copy|cp',
1616 @command('copy|cp',
1617 [('A', 'after', None, _('record a copy that has already occurred')),
1617 [('A', 'after', None, _('record a copy that has already occurred')),
1618 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1618 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1619 ] + walkopts + dryrunopts,
1619 ] + walkopts + dryrunopts,
1620 _('[OPTION]... [SOURCE]... DEST'))
1620 _('[OPTION]... [SOURCE]... DEST'))
1621 def copy(ui, repo, *pats, **opts):
1621 def copy(ui, repo, *pats, **opts):
1622 """mark files as copied for the next commit
1622 """mark files as copied for the next commit
1623
1623
1624 Mark dest as having copies of source files. If dest is a
1624 Mark dest as having copies of source files. If dest is a
1625 directory, copies are put in that directory. If dest is a file,
1625 directory, copies are put in that directory. If dest is a file,
1626 the source must be a single file.
1626 the source must be a single file.
1627
1627
1628 By default, this command copies the contents of files as they
1628 By default, this command copies the contents of files as they
1629 exist in the working directory. If invoked with -A/--after, the
1629 exist in the working directory. If invoked with -A/--after, the
1630 operation is recorded, but no copying is performed.
1630 operation is recorded, but no copying is performed.
1631
1631
1632 This command takes effect with the next commit. To undo a copy
1632 This command takes effect with the next commit. To undo a copy
1633 before that, see :hg:`revert`.
1633 before that, see :hg:`revert`.
1634
1634
1635 Returns 0 on success, 1 if errors are encountered.
1635 Returns 0 on success, 1 if errors are encountered.
1636 """
1636 """
1637 wlock = repo.wlock(False)
1637 wlock = repo.wlock(False)
1638 try:
1638 try:
1639 return cmdutil.copy(ui, repo, pats, opts)
1639 return cmdutil.copy(ui, repo, pats, opts)
1640 finally:
1640 finally:
1641 wlock.release()
1641 wlock.release()
1642
1642
1643 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1643 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1644 def debugancestor(ui, repo, *args):
1644 def debugancestor(ui, repo, *args):
1645 """find the ancestor revision of two revisions in a given index"""
1645 """find the ancestor revision of two revisions in a given index"""
1646 if len(args) == 3:
1646 if len(args) == 3:
1647 index, rev1, rev2 = args
1647 index, rev1, rev2 = args
1648 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1648 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1649 lookup = r.lookup
1649 lookup = r.lookup
1650 elif len(args) == 2:
1650 elif len(args) == 2:
1651 if not repo:
1651 if not repo:
1652 raise util.Abort(_("there is no Mercurial repository here "
1652 raise util.Abort(_("there is no Mercurial repository here "
1653 "(.hg not found)"))
1653 "(.hg not found)"))
1654 rev1, rev2 = args
1654 rev1, rev2 = args
1655 r = repo.changelog
1655 r = repo.changelog
1656 lookup = repo.lookup
1656 lookup = repo.lookup
1657 else:
1657 else:
1658 raise util.Abort(_('either two or three arguments required'))
1658 raise util.Abort(_('either two or three arguments required'))
1659 a = r.ancestor(lookup(rev1), lookup(rev2))
1659 a = r.ancestor(lookup(rev1), lookup(rev2))
1660 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1660 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1661
1661
1662 @command('debugbuilddag',
1662 @command('debugbuilddag',
1663 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1663 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1664 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1664 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1665 ('n', 'new-file', None, _('add new file at each rev'))],
1665 ('n', 'new-file', None, _('add new file at each rev'))],
1666 _('[OPTION]... [TEXT]'))
1666 _('[OPTION]... [TEXT]'))
1667 def debugbuilddag(ui, repo, text=None,
1667 def debugbuilddag(ui, repo, text=None,
1668 mergeable_file=False,
1668 mergeable_file=False,
1669 overwritten_file=False,
1669 overwritten_file=False,
1670 new_file=False):
1670 new_file=False):
1671 """builds a repo with a given DAG from scratch in the current empty repo
1671 """builds a repo with a given DAG from scratch in the current empty repo
1672
1672
1673 The description of the DAG is read from stdin if not given on the
1673 The description of the DAG is read from stdin if not given on the
1674 command line.
1674 command line.
1675
1675
1676 Elements:
1676 Elements:
1677
1677
1678 - "+n" is a linear run of n nodes based on the current default parent
1678 - "+n" is a linear run of n nodes based on the current default parent
1679 - "." is a single node based on the current default parent
1679 - "." is a single node based on the current default parent
1680 - "$" resets the default parent to null (implied at the start);
1680 - "$" resets the default parent to null (implied at the start);
1681 otherwise the default parent is always the last node created
1681 otherwise the default parent is always the last node created
1682 - "<p" sets the default parent to the backref p
1682 - "<p" sets the default parent to the backref p
1683 - "*p" is a fork at parent p, which is a backref
1683 - "*p" is a fork at parent p, which is a backref
1684 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1684 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1685 - "/p2" is a merge of the preceding node and p2
1685 - "/p2" is a merge of the preceding node and p2
1686 - ":tag" defines a local tag for the preceding node
1686 - ":tag" defines a local tag for the preceding node
1687 - "@branch" sets the named branch for subsequent nodes
1687 - "@branch" sets the named branch for subsequent nodes
1688 - "#...\\n" is a comment up to the end of the line
1688 - "#...\\n" is a comment up to the end of the line
1689
1689
1690 Whitespace between the above elements is ignored.
1690 Whitespace between the above elements is ignored.
1691
1691
1692 A backref is either
1692 A backref is either
1693
1693
1694 - a number n, which references the node curr-n, where curr is the current
1694 - a number n, which references the node curr-n, where curr is the current
1695 node, or
1695 node, or
1696 - the name of a local tag you placed earlier using ":tag", or
1696 - the name of a local tag you placed earlier using ":tag", or
1697 - empty to denote the default parent.
1697 - empty to denote the default parent.
1698
1698
1699 All string valued-elements are either strictly alphanumeric, or must
1699 All string valued-elements are either strictly alphanumeric, or must
1700 be enclosed in double quotes ("..."), with "\\" as escape character.
1700 be enclosed in double quotes ("..."), with "\\" as escape character.
1701 """
1701 """
1702
1702
1703 if text is None:
1703 if text is None:
1704 ui.status(_("reading DAG from stdin\n"))
1704 ui.status(_("reading DAG from stdin\n"))
1705 text = ui.fin.read()
1705 text = ui.fin.read()
1706
1706
1707 cl = repo.changelog
1707 cl = repo.changelog
1708 if len(cl) > 0:
1708 if len(cl) > 0:
1709 raise util.Abort(_('repository is not empty'))
1709 raise util.Abort(_('repository is not empty'))
1710
1710
1711 # determine number of revs in DAG
1711 # determine number of revs in DAG
1712 total = 0
1712 total = 0
1713 for type, data in dagparser.parsedag(text):
1713 for type, data in dagparser.parsedag(text):
1714 if type == 'n':
1714 if type == 'n':
1715 total += 1
1715 total += 1
1716
1716
1717 if mergeable_file:
1717 if mergeable_file:
1718 linesperrev = 2
1718 linesperrev = 2
1719 # make a file with k lines per rev
1719 # make a file with k lines per rev
1720 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1720 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1721 initialmergedlines.append("")
1721 initialmergedlines.append("")
1722
1722
1723 tags = []
1723 tags = []
1724
1724
1725 lock = tr = None
1725 lock = tr = None
1726 try:
1726 try:
1727 lock = repo.lock()
1727 lock = repo.lock()
1728 tr = repo.transaction("builddag")
1728 tr = repo.transaction("builddag")
1729
1729
1730 at = -1
1730 at = -1
1731 atbranch = 'default'
1731 atbranch = 'default'
1732 nodeids = []
1732 nodeids = []
1733 id = 0
1733 id = 0
1734 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1734 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1735 for type, data in dagparser.parsedag(text):
1735 for type, data in dagparser.parsedag(text):
1736 if type == 'n':
1736 if type == 'n':
1737 ui.note(('node %s\n' % str(data)))
1737 ui.note(('node %s\n' % str(data)))
1738 id, ps = data
1738 id, ps = data
1739
1739
1740 files = []
1740 files = []
1741 fctxs = {}
1741 fctxs = {}
1742
1742
1743 p2 = None
1743 p2 = None
1744 if mergeable_file:
1744 if mergeable_file:
1745 fn = "mf"
1745 fn = "mf"
1746 p1 = repo[ps[0]]
1746 p1 = repo[ps[0]]
1747 if len(ps) > 1:
1747 if len(ps) > 1:
1748 p2 = repo[ps[1]]
1748 p2 = repo[ps[1]]
1749 pa = p1.ancestor(p2)
1749 pa = p1.ancestor(p2)
1750 base, local, other = [x[fn].data() for x in (pa, p1,
1750 base, local, other = [x[fn].data() for x in (pa, p1,
1751 p2)]
1751 p2)]
1752 m3 = simplemerge.Merge3Text(base, local, other)
1752 m3 = simplemerge.Merge3Text(base, local, other)
1753 ml = [l.strip() for l in m3.merge_lines()]
1753 ml = [l.strip() for l in m3.merge_lines()]
1754 ml.append("")
1754 ml.append("")
1755 elif at > 0:
1755 elif at > 0:
1756 ml = p1[fn].data().split("\n")
1756 ml = p1[fn].data().split("\n")
1757 else:
1757 else:
1758 ml = initialmergedlines
1758 ml = initialmergedlines
1759 ml[id * linesperrev] += " r%i" % id
1759 ml[id * linesperrev] += " r%i" % id
1760 mergedtext = "\n".join(ml)
1760 mergedtext = "\n".join(ml)
1761 files.append(fn)
1761 files.append(fn)
1762 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1762 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1763
1763
1764 if overwritten_file:
1764 if overwritten_file:
1765 fn = "of"
1765 fn = "of"
1766 files.append(fn)
1766 files.append(fn)
1767 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1767 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1768
1768
1769 if new_file:
1769 if new_file:
1770 fn = "nf%i" % id
1770 fn = "nf%i" % id
1771 files.append(fn)
1771 files.append(fn)
1772 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1772 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1773 if len(ps) > 1:
1773 if len(ps) > 1:
1774 if not p2:
1774 if not p2:
1775 p2 = repo[ps[1]]
1775 p2 = repo[ps[1]]
1776 for fn in p2:
1776 for fn in p2:
1777 if fn.startswith("nf"):
1777 if fn.startswith("nf"):
1778 files.append(fn)
1778 files.append(fn)
1779 fctxs[fn] = p2[fn]
1779 fctxs[fn] = p2[fn]
1780
1780
1781 def fctxfn(repo, cx, path):
1781 def fctxfn(repo, cx, path):
1782 return fctxs.get(path)
1782 return fctxs.get(path)
1783
1783
1784 if len(ps) == 0 or ps[0] < 0:
1784 if len(ps) == 0 or ps[0] < 0:
1785 pars = [None, None]
1785 pars = [None, None]
1786 elif len(ps) == 1:
1786 elif len(ps) == 1:
1787 pars = [nodeids[ps[0]], None]
1787 pars = [nodeids[ps[0]], None]
1788 else:
1788 else:
1789 pars = [nodeids[p] for p in ps]
1789 pars = [nodeids[p] for p in ps]
1790 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1790 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1791 date=(id, 0),
1791 date=(id, 0),
1792 user="debugbuilddag",
1792 user="debugbuilddag",
1793 extra={'branch': atbranch})
1793 extra={'branch': atbranch})
1794 nodeid = repo.commitctx(cx)
1794 nodeid = repo.commitctx(cx)
1795 nodeids.append(nodeid)
1795 nodeids.append(nodeid)
1796 at = id
1796 at = id
1797 elif type == 'l':
1797 elif type == 'l':
1798 id, name = data
1798 id, name = data
1799 ui.note(('tag %s\n' % name))
1799 ui.note(('tag %s\n' % name))
1800 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1800 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1801 elif type == 'a':
1801 elif type == 'a':
1802 ui.note(('branch %s\n' % data))
1802 ui.note(('branch %s\n' % data))
1803 atbranch = data
1803 atbranch = data
1804 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1804 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1805 tr.close()
1805 tr.close()
1806
1806
1807 if tags:
1807 if tags:
1808 repo.vfs.write("localtags", "".join(tags))
1808 repo.vfs.write("localtags", "".join(tags))
1809 finally:
1809 finally:
1810 ui.progress(_('building'), None)
1810 ui.progress(_('building'), None)
1811 release(tr, lock)
1811 release(tr, lock)
1812
1812
1813 @command('debugbundle',
1813 @command('debugbundle',
1814 [('a', 'all', None, _('show all details'))],
1814 [('a', 'all', None, _('show all details'))],
1815 _('FILE'),
1815 _('FILE'),
1816 norepo=True)
1816 norepo=True)
1817 def debugbundle(ui, bundlepath, all=None, **opts):
1817 def debugbundle(ui, bundlepath, all=None, **opts):
1818 """lists the contents of a bundle"""
1818 """lists the contents of a bundle"""
1819 f = hg.openpath(ui, bundlepath)
1819 f = hg.openpath(ui, bundlepath)
1820 try:
1820 try:
1821 gen = exchange.readbundle(ui, f, bundlepath)
1821 gen = exchange.readbundle(ui, f, bundlepath)
1822 if isinstance(gen, bundle2.unbundle20):
1822 if isinstance(gen, bundle2.unbundle20):
1823 return _debugbundle2(ui, gen, all=all, **opts)
1823 return _debugbundle2(ui, gen, all=all, **opts)
1824 if all:
1824 if all:
1825 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1825 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1826
1826
1827 def showchunks(named):
1827 def showchunks(named):
1828 ui.write("\n%s\n" % named)
1828 ui.write("\n%s\n" % named)
1829 chain = None
1829 chain = None
1830 while True:
1830 while True:
1831 chunkdata = gen.deltachunk(chain)
1831 chunkdata = gen.deltachunk(chain)
1832 if not chunkdata:
1832 if not chunkdata:
1833 break
1833 break
1834 node = chunkdata['node']
1834 node = chunkdata['node']
1835 p1 = chunkdata['p1']
1835 p1 = chunkdata['p1']
1836 p2 = chunkdata['p2']
1836 p2 = chunkdata['p2']
1837 cs = chunkdata['cs']
1837 cs = chunkdata['cs']
1838 deltabase = chunkdata['deltabase']
1838 deltabase = chunkdata['deltabase']
1839 delta = chunkdata['delta']
1839 delta = chunkdata['delta']
1840 ui.write("%s %s %s %s %s %s\n" %
1840 ui.write("%s %s %s %s %s %s\n" %
1841 (hex(node), hex(p1), hex(p2),
1841 (hex(node), hex(p1), hex(p2),
1842 hex(cs), hex(deltabase), len(delta)))
1842 hex(cs), hex(deltabase), len(delta)))
1843 chain = node
1843 chain = node
1844
1844
1845 chunkdata = gen.changelogheader()
1845 chunkdata = gen.changelogheader()
1846 showchunks("changelog")
1846 showchunks("changelog")
1847 chunkdata = gen.manifestheader()
1847 chunkdata = gen.manifestheader()
1848 showchunks("manifest")
1848 showchunks("manifest")
1849 while True:
1849 while True:
1850 chunkdata = gen.filelogheader()
1850 chunkdata = gen.filelogheader()
1851 if not chunkdata:
1851 if not chunkdata:
1852 break
1852 break
1853 fname = chunkdata['filename']
1853 fname = chunkdata['filename']
1854 showchunks(fname)
1854 showchunks(fname)
1855 else:
1855 else:
1856 if isinstance(gen, bundle2.unbundle20):
1856 if isinstance(gen, bundle2.unbundle20):
1857 raise util.Abort(_('use debugbundle2 for this file'))
1857 raise util.Abort(_('use debugbundle2 for this file'))
1858 chunkdata = gen.changelogheader()
1858 chunkdata = gen.changelogheader()
1859 chain = None
1859 chain = None
1860 while True:
1860 while True:
1861 chunkdata = gen.deltachunk(chain)
1861 chunkdata = gen.deltachunk(chain)
1862 if not chunkdata:
1862 if not chunkdata:
1863 break
1863 break
1864 node = chunkdata['node']
1864 node = chunkdata['node']
1865 ui.write("%s\n" % hex(node))
1865 ui.write("%s\n" % hex(node))
1866 chain = node
1866 chain = node
1867 finally:
1867 finally:
1868 f.close()
1868 f.close()
1869
1869
1870 def _debugbundle2(ui, gen, **opts):
1870 def _debugbundle2(ui, gen, **opts):
1871 """lists the contents of a bundle2"""
1871 """lists the contents of a bundle2"""
1872 if not isinstance(gen, bundle2.unbundle20):
1872 if not isinstance(gen, bundle2.unbundle20):
1873 raise util.Abort(_('not a bundle2 file'))
1873 raise util.Abort(_('not a bundle2 file'))
1874 ui.write(('Stream params: %s\n' % repr(gen.params)))
1874 ui.write(('Stream params: %s\n' % repr(gen.params)))
1875 for part in gen.iterparts():
1875 for part in gen.iterparts():
1876 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1876 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1877 if part.type == 'b2x:changegroup':
1877 if part.type == 'b2x:changegroup':
1878 version = part.params.get('version', '01')
1878 version = part.params.get('version', '01')
1879 cg = changegroup.packermap[version][1](part, 'UN')
1879 cg = changegroup.packermap[version][1](part, 'UN')
1880 chunkdata = cg.changelogheader()
1880 chunkdata = cg.changelogheader()
1881 chain = None
1881 chain = None
1882 while True:
1882 while True:
1883 chunkdata = cg.deltachunk(chain)
1883 chunkdata = cg.deltachunk(chain)
1884 if not chunkdata:
1884 if not chunkdata:
1885 break
1885 break
1886 node = chunkdata['node']
1886 node = chunkdata['node']
1887 ui.write(" %s\n" % hex(node))
1887 ui.write(" %s\n" % hex(node))
1888 chain = node
1888 chain = node
1889
1889
1890 @command('debugcheckstate', [], '')
1890 @command('debugcheckstate', [], '')
1891 def debugcheckstate(ui, repo):
1891 def debugcheckstate(ui, repo):
1892 """validate the correctness of the current dirstate"""
1892 """validate the correctness of the current dirstate"""
1893 parent1, parent2 = repo.dirstate.parents()
1893 parent1, parent2 = repo.dirstate.parents()
1894 m1 = repo[parent1].manifest()
1894 m1 = repo[parent1].manifest()
1895 m2 = repo[parent2].manifest()
1895 m2 = repo[parent2].manifest()
1896 errors = 0
1896 errors = 0
1897 for f in repo.dirstate:
1897 for f in repo.dirstate:
1898 state = repo.dirstate[f]
1898 state = repo.dirstate[f]
1899 if state in "nr" and f not in m1:
1899 if state in "nr" and f not in m1:
1900 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1900 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1901 errors += 1
1901 errors += 1
1902 if state in "a" and f in m1:
1902 if state in "a" and f in m1:
1903 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1903 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1904 errors += 1
1904 errors += 1
1905 if state in "m" and f not in m1 and f not in m2:
1905 if state in "m" and f not in m1 and f not in m2:
1906 ui.warn(_("%s in state %s, but not in either manifest\n") %
1906 ui.warn(_("%s in state %s, but not in either manifest\n") %
1907 (f, state))
1907 (f, state))
1908 errors += 1
1908 errors += 1
1909 for f in m1:
1909 for f in m1:
1910 state = repo.dirstate[f]
1910 state = repo.dirstate[f]
1911 if state not in "nrm":
1911 if state not in "nrm":
1912 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1912 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1913 errors += 1
1913 errors += 1
1914 if errors:
1914 if errors:
1915 error = _(".hg/dirstate inconsistent with current parent's manifest")
1915 error = _(".hg/dirstate inconsistent with current parent's manifest")
1916 raise util.Abort(error)
1916 raise util.Abort(error)
1917
1917
1918 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1918 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1919 def debugcommands(ui, cmd='', *args):
1919 def debugcommands(ui, cmd='', *args):
1920 """list all available commands and options"""
1920 """list all available commands and options"""
1921 for cmd, vals in sorted(table.iteritems()):
1921 for cmd, vals in sorted(table.iteritems()):
1922 cmd = cmd.split('|')[0].strip('^')
1922 cmd = cmd.split('|')[0].strip('^')
1923 opts = ', '.join([i[1] for i in vals[1]])
1923 opts = ', '.join([i[1] for i in vals[1]])
1924 ui.write('%s: %s\n' % (cmd, opts))
1924 ui.write('%s: %s\n' % (cmd, opts))
1925
1925
1926 @command('debugcomplete',
1926 @command('debugcomplete',
1927 [('o', 'options', None, _('show the command options'))],
1927 [('o', 'options', None, _('show the command options'))],
1928 _('[-o] CMD'),
1928 _('[-o] CMD'),
1929 norepo=True)
1929 norepo=True)
1930 def debugcomplete(ui, cmd='', **opts):
1930 def debugcomplete(ui, cmd='', **opts):
1931 """returns the completion list associated with the given command"""
1931 """returns the completion list associated with the given command"""
1932
1932
1933 if opts.get('options'):
1933 if opts.get('options'):
1934 options = []
1934 options = []
1935 otables = [globalopts]
1935 otables = [globalopts]
1936 if cmd:
1936 if cmd:
1937 aliases, entry = cmdutil.findcmd(cmd, table, False)
1937 aliases, entry = cmdutil.findcmd(cmd, table, False)
1938 otables.append(entry[1])
1938 otables.append(entry[1])
1939 for t in otables:
1939 for t in otables:
1940 for o in t:
1940 for o in t:
1941 if "(DEPRECATED)" in o[3]:
1941 if "(DEPRECATED)" in o[3]:
1942 continue
1942 continue
1943 if o[0]:
1943 if o[0]:
1944 options.append('-%s' % o[0])
1944 options.append('-%s' % o[0])
1945 options.append('--%s' % o[1])
1945 options.append('--%s' % o[1])
1946 ui.write("%s\n" % "\n".join(options))
1946 ui.write("%s\n" % "\n".join(options))
1947 return
1947 return
1948
1948
1949 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1949 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
1950 if ui.verbose:
1950 if ui.verbose:
1951 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1951 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1952 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1952 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1953
1953
1954 @command('debugdag',
1954 @command('debugdag',
1955 [('t', 'tags', None, _('use tags as labels')),
1955 [('t', 'tags', None, _('use tags as labels')),
1956 ('b', 'branches', None, _('annotate with branch names')),
1956 ('b', 'branches', None, _('annotate with branch names')),
1957 ('', 'dots', None, _('use dots for runs')),
1957 ('', 'dots', None, _('use dots for runs')),
1958 ('s', 'spaces', None, _('separate elements by spaces'))],
1958 ('s', 'spaces', None, _('separate elements by spaces'))],
1959 _('[OPTION]... [FILE [REV]...]'),
1959 _('[OPTION]... [FILE [REV]...]'),
1960 optionalrepo=True)
1960 optionalrepo=True)
1961 def debugdag(ui, repo, file_=None, *revs, **opts):
1961 def debugdag(ui, repo, file_=None, *revs, **opts):
1962 """format the changelog or an index DAG as a concise textual description
1962 """format the changelog or an index DAG as a concise textual description
1963
1963
1964 If you pass a revlog index, the revlog's DAG is emitted. If you list
1964 If you pass a revlog index, the revlog's DAG is emitted. If you list
1965 revision numbers, they get labeled in the output as rN.
1965 revision numbers, they get labeled in the output as rN.
1966
1966
1967 Otherwise, the changelog DAG of the current repo is emitted.
1967 Otherwise, the changelog DAG of the current repo is emitted.
1968 """
1968 """
1969 spaces = opts.get('spaces')
1969 spaces = opts.get('spaces')
1970 dots = opts.get('dots')
1970 dots = opts.get('dots')
1971 if file_:
1971 if file_:
1972 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1972 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1973 revs = set((int(r) for r in revs))
1973 revs = set((int(r) for r in revs))
1974 def events():
1974 def events():
1975 for r in rlog:
1975 for r in rlog:
1976 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1976 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1977 if p != -1))
1977 if p != -1))
1978 if r in revs:
1978 if r in revs:
1979 yield 'l', (r, "r%i" % r)
1979 yield 'l', (r, "r%i" % r)
1980 elif repo:
1980 elif repo:
1981 cl = repo.changelog
1981 cl = repo.changelog
1982 tags = opts.get('tags')
1982 tags = opts.get('tags')
1983 branches = opts.get('branches')
1983 branches = opts.get('branches')
1984 if tags:
1984 if tags:
1985 labels = {}
1985 labels = {}
1986 for l, n in repo.tags().items():
1986 for l, n in repo.tags().items():
1987 labels.setdefault(cl.rev(n), []).append(l)
1987 labels.setdefault(cl.rev(n), []).append(l)
1988 def events():
1988 def events():
1989 b = "default"
1989 b = "default"
1990 for r in cl:
1990 for r in cl:
1991 if branches:
1991 if branches:
1992 newb = cl.read(cl.node(r))[5]['branch']
1992 newb = cl.read(cl.node(r))[5]['branch']
1993 if newb != b:
1993 if newb != b:
1994 yield 'a', newb
1994 yield 'a', newb
1995 b = newb
1995 b = newb
1996 yield 'n', (r, list(p for p in cl.parentrevs(r)
1996 yield 'n', (r, list(p for p in cl.parentrevs(r)
1997 if p != -1))
1997 if p != -1))
1998 if tags:
1998 if tags:
1999 ls = labels.get(r)
1999 ls = labels.get(r)
2000 if ls:
2000 if ls:
2001 for l in ls:
2001 for l in ls:
2002 yield 'l', (r, l)
2002 yield 'l', (r, l)
2003 else:
2003 else:
2004 raise util.Abort(_('need repo for changelog dag'))
2004 raise util.Abort(_('need repo for changelog dag'))
2005
2005
2006 for line in dagparser.dagtextlines(events(),
2006 for line in dagparser.dagtextlines(events(),
2007 addspaces=spaces,
2007 addspaces=spaces,
2008 wraplabels=True,
2008 wraplabels=True,
2009 wrapannotations=True,
2009 wrapannotations=True,
2010 wrapnonlinear=dots,
2010 wrapnonlinear=dots,
2011 usedots=dots,
2011 usedots=dots,
2012 maxlinewidth=70):
2012 maxlinewidth=70):
2013 ui.write(line)
2013 ui.write(line)
2014 ui.write("\n")
2014 ui.write("\n")
2015
2015
2016 @command('debugdata',
2016 @command('debugdata',
2017 [('c', 'changelog', False, _('open changelog')),
2017 [('c', 'changelog', False, _('open changelog')),
2018 ('m', 'manifest', False, _('open manifest'))],
2018 ('m', 'manifest', False, _('open manifest'))],
2019 _('-c|-m|FILE REV'))
2019 _('-c|-m|FILE REV'))
2020 def debugdata(ui, repo, file_, rev=None, **opts):
2020 def debugdata(ui, repo, file_, rev=None, **opts):
2021 """dump the contents of a data file revision"""
2021 """dump the contents of a data file revision"""
2022 if opts.get('changelog') or opts.get('manifest'):
2022 if opts.get('changelog') or opts.get('manifest'):
2023 file_, rev = None, file_
2023 file_, rev = None, file_
2024 elif rev is None:
2024 elif rev is None:
2025 raise error.CommandError('debugdata', _('invalid arguments'))
2025 raise error.CommandError('debugdata', _('invalid arguments'))
2026 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2026 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2027 try:
2027 try:
2028 ui.write(r.revision(r.lookup(rev)))
2028 ui.write(r.revision(r.lookup(rev)))
2029 except KeyError:
2029 except KeyError:
2030 raise util.Abort(_('invalid revision identifier %s') % rev)
2030 raise util.Abort(_('invalid revision identifier %s') % rev)
2031
2031
2032 @command('debugdate',
2032 @command('debugdate',
2033 [('e', 'extended', None, _('try extended date formats'))],
2033 [('e', 'extended', None, _('try extended date formats'))],
2034 _('[-e] DATE [RANGE]'),
2034 _('[-e] DATE [RANGE]'),
2035 norepo=True, optionalrepo=True)
2035 norepo=True, optionalrepo=True)
2036 def debugdate(ui, date, range=None, **opts):
2036 def debugdate(ui, date, range=None, **opts):
2037 """parse and display a date"""
2037 """parse and display a date"""
2038 if opts["extended"]:
2038 if opts["extended"]:
2039 d = util.parsedate(date, util.extendeddateformats)
2039 d = util.parsedate(date, util.extendeddateformats)
2040 else:
2040 else:
2041 d = util.parsedate(date)
2041 d = util.parsedate(date)
2042 ui.write(("internal: %s %s\n") % d)
2042 ui.write(("internal: %s %s\n") % d)
2043 ui.write(("standard: %s\n") % util.datestr(d))
2043 ui.write(("standard: %s\n") % util.datestr(d))
2044 if range:
2044 if range:
2045 m = util.matchdate(range)
2045 m = util.matchdate(range)
2046 ui.write(("match: %s\n") % m(d[0]))
2046 ui.write(("match: %s\n") % m(d[0]))
2047
2047
2048 @command('debugdiscovery',
2048 @command('debugdiscovery',
2049 [('', 'old', None, _('use old-style discovery')),
2049 [('', 'old', None, _('use old-style discovery')),
2050 ('', 'nonheads', None,
2050 ('', 'nonheads', None,
2051 _('use old-style discovery with non-heads included')),
2051 _('use old-style discovery with non-heads included')),
2052 ] + remoteopts,
2052 ] + remoteopts,
2053 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2053 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2054 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2054 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2055 """runs the changeset discovery protocol in isolation"""
2055 """runs the changeset discovery protocol in isolation"""
2056 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2056 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2057 opts.get('branch'))
2057 opts.get('branch'))
2058 remote = hg.peer(repo, opts, remoteurl)
2058 remote = hg.peer(repo, opts, remoteurl)
2059 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2059 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2060
2060
2061 # make sure tests are repeatable
2061 # make sure tests are repeatable
2062 random.seed(12323)
2062 random.seed(12323)
2063
2063
2064 def doit(localheads, remoteheads, remote=remote):
2064 def doit(localheads, remoteheads, remote=remote):
2065 if opts.get('old'):
2065 if opts.get('old'):
2066 if localheads:
2066 if localheads:
2067 raise util.Abort('cannot use localheads with old style '
2067 raise util.Abort('cannot use localheads with old style '
2068 'discovery')
2068 'discovery')
2069 if not util.safehasattr(remote, 'branches'):
2069 if not util.safehasattr(remote, 'branches'):
2070 # enable in-client legacy support
2070 # enable in-client legacy support
2071 remote = localrepo.locallegacypeer(remote.local())
2071 remote = localrepo.locallegacypeer(remote.local())
2072 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2072 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2073 force=True)
2073 force=True)
2074 common = set(common)
2074 common = set(common)
2075 if not opts.get('nonheads'):
2075 if not opts.get('nonheads'):
2076 ui.write(("unpruned common: %s\n") %
2076 ui.write(("unpruned common: %s\n") %
2077 " ".join(sorted(short(n) for n in common)))
2077 " ".join(sorted(short(n) for n in common)))
2078 dag = dagutil.revlogdag(repo.changelog)
2078 dag = dagutil.revlogdag(repo.changelog)
2079 all = dag.ancestorset(dag.internalizeall(common))
2079 all = dag.ancestorset(dag.internalizeall(common))
2080 common = dag.externalizeall(dag.headsetofconnecteds(all))
2080 common = dag.externalizeall(dag.headsetofconnecteds(all))
2081 else:
2081 else:
2082 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2082 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2083 common = set(common)
2083 common = set(common)
2084 rheads = set(hds)
2084 rheads = set(hds)
2085 lheads = set(repo.heads())
2085 lheads = set(repo.heads())
2086 ui.write(("common heads: %s\n") %
2086 ui.write(("common heads: %s\n") %
2087 " ".join(sorted(short(n) for n in common)))
2087 " ".join(sorted(short(n) for n in common)))
2088 if lheads <= common:
2088 if lheads <= common:
2089 ui.write(("local is subset\n"))
2089 ui.write(("local is subset\n"))
2090 elif rheads <= common:
2090 elif rheads <= common:
2091 ui.write(("remote is subset\n"))
2091 ui.write(("remote is subset\n"))
2092
2092
2093 serverlogs = opts.get('serverlog')
2093 serverlogs = opts.get('serverlog')
2094 if serverlogs:
2094 if serverlogs:
2095 for filename in serverlogs:
2095 for filename in serverlogs:
2096 logfile = open(filename, 'r')
2096 logfile = open(filename, 'r')
2097 try:
2097 try:
2098 line = logfile.readline()
2098 line = logfile.readline()
2099 while line:
2099 while line:
2100 parts = line.strip().split(';')
2100 parts = line.strip().split(';')
2101 op = parts[1]
2101 op = parts[1]
2102 if op == 'cg':
2102 if op == 'cg':
2103 pass
2103 pass
2104 elif op == 'cgss':
2104 elif op == 'cgss':
2105 doit(parts[2].split(' '), parts[3].split(' '))
2105 doit(parts[2].split(' '), parts[3].split(' '))
2106 elif op == 'unb':
2106 elif op == 'unb':
2107 doit(parts[3].split(' '), parts[2].split(' '))
2107 doit(parts[3].split(' '), parts[2].split(' '))
2108 line = logfile.readline()
2108 line = logfile.readline()
2109 finally:
2109 finally:
2110 logfile.close()
2110 logfile.close()
2111
2111
2112 else:
2112 else:
2113 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2113 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2114 opts.get('remote_head'))
2114 opts.get('remote_head'))
2115 localrevs = opts.get('local_head')
2115 localrevs = opts.get('local_head')
2116 doit(localrevs, remoterevs)
2116 doit(localrevs, remoterevs)
2117
2117
2118 @command('debugfileset',
2118 @command('debugfileset',
2119 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2119 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2120 _('[-r REV] FILESPEC'))
2120 _('[-r REV] FILESPEC'))
2121 def debugfileset(ui, repo, expr, **opts):
2121 def debugfileset(ui, repo, expr, **opts):
2122 '''parse and apply a fileset specification'''
2122 '''parse and apply a fileset specification'''
2123 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2123 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2124 if ui.verbose:
2124 if ui.verbose:
2125 tree = fileset.parse(expr)[0]
2125 tree = fileset.parse(expr)[0]
2126 ui.note(tree, "\n")
2126 ui.note(tree, "\n")
2127
2127
2128 for f in ctx.getfileset(expr):
2128 for f in ctx.getfileset(expr):
2129 ui.write("%s\n" % f)
2129 ui.write("%s\n" % f)
2130
2130
2131 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2131 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2132 def debugfsinfo(ui, path="."):
2132 def debugfsinfo(ui, path="."):
2133 """show information detected about current filesystem"""
2133 """show information detected about current filesystem"""
2134 util.writefile('.debugfsinfo', '')
2134 util.writefile('.debugfsinfo', '')
2135 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2135 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2136 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2136 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2137 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2137 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2138 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2138 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2139 and 'yes' or 'no'))
2139 and 'yes' or 'no'))
2140 os.unlink('.debugfsinfo')
2140 os.unlink('.debugfsinfo')
2141
2141
2142 @command('debuggetbundle',
2142 @command('debuggetbundle',
2143 [('H', 'head', [], _('id of head node'), _('ID')),
2143 [('H', 'head', [], _('id of head node'), _('ID')),
2144 ('C', 'common', [], _('id of common node'), _('ID')),
2144 ('C', 'common', [], _('id of common node'), _('ID')),
2145 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2145 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2146 _('REPO FILE [-H|-C ID]...'),
2146 _('REPO FILE [-H|-C ID]...'),
2147 norepo=True)
2147 norepo=True)
2148 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2148 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2149 """retrieves a bundle from a repo
2149 """retrieves a bundle from a repo
2150
2150
2151 Every ID must be a full-length hex node id string. Saves the bundle to the
2151 Every ID must be a full-length hex node id string. Saves the bundle to the
2152 given file.
2152 given file.
2153 """
2153 """
2154 repo = hg.peer(ui, opts, repopath)
2154 repo = hg.peer(ui, opts, repopath)
2155 if not repo.capable('getbundle'):
2155 if not repo.capable('getbundle'):
2156 raise util.Abort("getbundle() not supported by target repository")
2156 raise util.Abort("getbundle() not supported by target repository")
2157 args = {}
2157 args = {}
2158 if common:
2158 if common:
2159 args['common'] = [bin(s) for s in common]
2159 args['common'] = [bin(s) for s in common]
2160 if head:
2160 if head:
2161 args['heads'] = [bin(s) for s in head]
2161 args['heads'] = [bin(s) for s in head]
2162 # TODO: get desired bundlecaps from command line.
2162 # TODO: get desired bundlecaps from command line.
2163 args['bundlecaps'] = None
2163 args['bundlecaps'] = None
2164 bundle = repo.getbundle('debug', **args)
2164 bundle = repo.getbundle('debug', **args)
2165
2165
2166 bundletype = opts.get('type', 'bzip2').lower()
2166 bundletype = opts.get('type', 'bzip2').lower()
2167 btypes = {'none': 'HG10UN',
2167 btypes = {'none': 'HG10UN',
2168 'bzip2': 'HG10BZ',
2168 'bzip2': 'HG10BZ',
2169 'gzip': 'HG10GZ',
2169 'gzip': 'HG10GZ',
2170 'bundle2': 'HG2Y'}
2170 'bundle2': 'HG2Y'}
2171 bundletype = btypes.get(bundletype)
2171 bundletype = btypes.get(bundletype)
2172 if bundletype not in changegroup.bundletypes:
2172 if bundletype not in changegroup.bundletypes:
2173 raise util.Abort(_('unknown bundle type specified with --type'))
2173 raise util.Abort(_('unknown bundle type specified with --type'))
2174 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2174 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2175
2175
2176 @command('debugignore', [], '')
2176 @command('debugignore', [], '')
2177 def debugignore(ui, repo, *values, **opts):
2177 def debugignore(ui, repo, *values, **opts):
2178 """display the combined ignore pattern"""
2178 """display the combined ignore pattern"""
2179 ignore = repo.dirstate._ignore
2179 ignore = repo.dirstate._ignore
2180 includepat = getattr(ignore, 'includepat', None)
2180 includepat = getattr(ignore, 'includepat', None)
2181 if includepat is not None:
2181 if includepat is not None:
2182 ui.write("%s\n" % includepat)
2182 ui.write("%s\n" % includepat)
2183 else:
2183 else:
2184 raise util.Abort(_("no ignore patterns found"))
2184 raise util.Abort(_("no ignore patterns found"))
2185
2185
2186 @command('debugindex',
2186 @command('debugindex',
2187 [('c', 'changelog', False, _('open changelog')),
2187 [('c', 'changelog', False, _('open changelog')),
2188 ('m', 'manifest', False, _('open manifest')),
2188 ('m', 'manifest', False, _('open manifest')),
2189 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2189 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2190 _('[-f FORMAT] -c|-m|FILE'),
2190 _('[-f FORMAT] -c|-m|FILE'),
2191 optionalrepo=True)
2191 optionalrepo=True)
2192 def debugindex(ui, repo, file_=None, **opts):
2192 def debugindex(ui, repo, file_=None, **opts):
2193 """dump the contents of an index file"""
2193 """dump the contents of an index file"""
2194 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2194 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2195 format = opts.get('format', 0)
2195 format = opts.get('format', 0)
2196 if format not in (0, 1):
2196 if format not in (0, 1):
2197 raise util.Abort(_("unknown format %d") % format)
2197 raise util.Abort(_("unknown format %d") % format)
2198
2198
2199 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2199 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2200 if generaldelta:
2200 if generaldelta:
2201 basehdr = ' delta'
2201 basehdr = ' delta'
2202 else:
2202 else:
2203 basehdr = ' base'
2203 basehdr = ' base'
2204
2204
2205 if ui.debugflag:
2205 if ui.debugflag:
2206 shortfn = hex
2206 shortfn = hex
2207 else:
2207 else:
2208 shortfn = short
2208 shortfn = short
2209
2209
2210 # There might not be anything in r, so have a sane default
2210 # There might not be anything in r, so have a sane default
2211 idlen = 12
2211 idlen = 12
2212 for i in r:
2212 for i in r:
2213 idlen = len(shortfn(r.node(i)))
2213 idlen = len(shortfn(r.node(i)))
2214 break
2214 break
2215
2215
2216 if format == 0:
2216 if format == 0:
2217 ui.write(" rev offset length " + basehdr + " linkrev"
2217 ui.write(" rev offset length " + basehdr + " linkrev"
2218 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2218 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2219 elif format == 1:
2219 elif format == 1:
2220 ui.write(" rev flag offset length"
2220 ui.write(" rev flag offset length"
2221 " size " + basehdr + " link p1 p2"
2221 " size " + basehdr + " link p1 p2"
2222 " %s\n" % "nodeid".rjust(idlen))
2222 " %s\n" % "nodeid".rjust(idlen))
2223
2223
2224 for i in r:
2224 for i in r:
2225 node = r.node(i)
2225 node = r.node(i)
2226 if generaldelta:
2226 if generaldelta:
2227 base = r.deltaparent(i)
2227 base = r.deltaparent(i)
2228 else:
2228 else:
2229 base = r.chainbase(i)
2229 base = r.chainbase(i)
2230 if format == 0:
2230 if format == 0:
2231 try:
2231 try:
2232 pp = r.parents(node)
2232 pp = r.parents(node)
2233 except Exception:
2233 except Exception:
2234 pp = [nullid, nullid]
2234 pp = [nullid, nullid]
2235 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2235 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2236 i, r.start(i), r.length(i), base, r.linkrev(i),
2236 i, r.start(i), r.length(i), base, r.linkrev(i),
2237 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2237 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2238 elif format == 1:
2238 elif format == 1:
2239 pr = r.parentrevs(i)
2239 pr = r.parentrevs(i)
2240 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2240 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2241 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2241 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2242 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2242 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2243
2243
2244 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2244 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2245 def debugindexdot(ui, repo, file_):
2245 def debugindexdot(ui, repo, file_):
2246 """dump an index DAG as a graphviz dot file"""
2246 """dump an index DAG as a graphviz dot file"""
2247 r = None
2247 r = None
2248 if repo:
2248 if repo:
2249 filelog = repo.file(file_)
2249 filelog = repo.file(file_)
2250 if len(filelog):
2250 if len(filelog):
2251 r = filelog
2251 r = filelog
2252 if not r:
2252 if not r:
2253 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2253 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2254 ui.write(("digraph G {\n"))
2254 ui.write(("digraph G {\n"))
2255 for i in r:
2255 for i in r:
2256 node = r.node(i)
2256 node = r.node(i)
2257 pp = r.parents(node)
2257 pp = r.parents(node)
2258 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2258 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2259 if pp[1] != nullid:
2259 if pp[1] != nullid:
2260 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2260 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2261 ui.write("}\n")
2261 ui.write("}\n")
2262
2262
2263 @command('debuginstall', [], '', norepo=True)
2263 @command('debuginstall', [], '', norepo=True)
2264 def debuginstall(ui):
2264 def debuginstall(ui):
2265 '''test Mercurial installation
2265 '''test Mercurial installation
2266
2266
2267 Returns 0 on success.
2267 Returns 0 on success.
2268 '''
2268 '''
2269
2269
2270 def writetemp(contents):
2270 def writetemp(contents):
2271 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2271 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2272 f = os.fdopen(fd, "wb")
2272 f = os.fdopen(fd, "wb")
2273 f.write(contents)
2273 f.write(contents)
2274 f.close()
2274 f.close()
2275 return name
2275 return name
2276
2276
2277 problems = 0
2277 problems = 0
2278
2278
2279 # encoding
2279 # encoding
2280 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2280 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2281 try:
2281 try:
2282 encoding.fromlocal("test")
2282 encoding.fromlocal("test")
2283 except util.Abort, inst:
2283 except util.Abort, inst:
2284 ui.write(" %s\n" % inst)
2284 ui.write(" %s\n" % inst)
2285 ui.write(_(" (check that your locale is properly set)\n"))
2285 ui.write(_(" (check that your locale is properly set)\n"))
2286 problems += 1
2286 problems += 1
2287
2287
2288 # Python
2288 # Python
2289 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2289 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2290 ui.status(_("checking Python version (%s)\n")
2290 ui.status(_("checking Python version (%s)\n")
2291 % ("%s.%s.%s" % sys.version_info[:3]))
2291 % ("%s.%s.%s" % sys.version_info[:3]))
2292 ui.status(_("checking Python lib (%s)...\n")
2292 ui.status(_("checking Python lib (%s)...\n")
2293 % os.path.dirname(os.__file__))
2293 % os.path.dirname(os.__file__))
2294
2294
2295 # compiled modules
2295 # compiled modules
2296 ui.status(_("checking installed modules (%s)...\n")
2296 ui.status(_("checking installed modules (%s)...\n")
2297 % os.path.dirname(__file__))
2297 % os.path.dirname(__file__))
2298 try:
2298 try:
2299 import bdiff, mpatch, base85, osutil
2299 import bdiff, mpatch, base85, osutil
2300 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2300 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2301 except Exception, inst:
2301 except Exception, inst:
2302 ui.write(" %s\n" % inst)
2302 ui.write(" %s\n" % inst)
2303 ui.write(_(" One or more extensions could not be found"))
2303 ui.write(_(" One or more extensions could not be found"))
2304 ui.write(_(" (check that you compiled the extensions)\n"))
2304 ui.write(_(" (check that you compiled the extensions)\n"))
2305 problems += 1
2305 problems += 1
2306
2306
2307 # templates
2307 # templates
2308 import templater
2308 import templater
2309 p = templater.templatepaths()
2309 p = templater.templatepaths()
2310 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2310 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2311 if p:
2311 if p:
2312 m = templater.templatepath("map-cmdline.default")
2312 m = templater.templatepath("map-cmdline.default")
2313 if m:
2313 if m:
2314 # template found, check if it is working
2314 # template found, check if it is working
2315 try:
2315 try:
2316 templater.templater(m)
2316 templater.templater(m)
2317 except Exception, inst:
2317 except Exception, inst:
2318 ui.write(" %s\n" % inst)
2318 ui.write(" %s\n" % inst)
2319 p = None
2319 p = None
2320 else:
2320 else:
2321 ui.write(_(" template 'default' not found\n"))
2321 ui.write(_(" template 'default' not found\n"))
2322 p = None
2322 p = None
2323 else:
2323 else:
2324 ui.write(_(" no template directories found\n"))
2324 ui.write(_(" no template directories found\n"))
2325 if not p:
2325 if not p:
2326 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2326 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2327 problems += 1
2327 problems += 1
2328
2328
2329 # editor
2329 # editor
2330 ui.status(_("checking commit editor...\n"))
2330 ui.status(_("checking commit editor...\n"))
2331 editor = ui.geteditor()
2331 editor = ui.geteditor()
2332 cmdpath = util.findexe(shlex.split(editor)[0])
2332 cmdpath = util.findexe(shlex.split(editor)[0])
2333 if not cmdpath:
2333 if not cmdpath:
2334 if editor == 'vi':
2334 if editor == 'vi':
2335 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2335 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2336 ui.write(_(" (specify a commit editor in your configuration"
2336 ui.write(_(" (specify a commit editor in your configuration"
2337 " file)\n"))
2337 " file)\n"))
2338 else:
2338 else:
2339 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2339 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2340 ui.write(_(" (specify a commit editor in your configuration"
2340 ui.write(_(" (specify a commit editor in your configuration"
2341 " file)\n"))
2341 " file)\n"))
2342 problems += 1
2342 problems += 1
2343
2343
2344 # check username
2344 # check username
2345 ui.status(_("checking username...\n"))
2345 ui.status(_("checking username...\n"))
2346 try:
2346 try:
2347 ui.username()
2347 ui.username()
2348 except util.Abort, e:
2348 except util.Abort, e:
2349 ui.write(" %s\n" % e)
2349 ui.write(" %s\n" % e)
2350 ui.write(_(" (specify a username in your configuration file)\n"))
2350 ui.write(_(" (specify a username in your configuration file)\n"))
2351 problems += 1
2351 problems += 1
2352
2352
2353 if not problems:
2353 if not problems:
2354 ui.status(_("no problems detected\n"))
2354 ui.status(_("no problems detected\n"))
2355 else:
2355 else:
2356 ui.write(_("%s problems detected,"
2356 ui.write(_("%s problems detected,"
2357 " please check your install!\n") % problems)
2357 " please check your install!\n") % problems)
2358
2358
2359 return problems
2359 return problems
2360
2360
2361 @command('debugknown', [], _('REPO ID...'), norepo=True)
2361 @command('debugknown', [], _('REPO ID...'), norepo=True)
2362 def debugknown(ui, repopath, *ids, **opts):
2362 def debugknown(ui, repopath, *ids, **opts):
2363 """test whether node ids are known to a repo
2363 """test whether node ids are known to a repo
2364
2364
2365 Every ID must be a full-length hex node id string. Returns a list of 0s
2365 Every ID must be a full-length hex node id string. Returns a list of 0s
2366 and 1s indicating unknown/known.
2366 and 1s indicating unknown/known.
2367 """
2367 """
2368 repo = hg.peer(ui, opts, repopath)
2368 repo = hg.peer(ui, opts, repopath)
2369 if not repo.capable('known'):
2369 if not repo.capable('known'):
2370 raise util.Abort("known() not supported by target repository")
2370 raise util.Abort("known() not supported by target repository")
2371 flags = repo.known([bin(s) for s in ids])
2371 flags = repo.known([bin(s) for s in ids])
2372 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2372 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2373
2373
2374 @command('debuglabelcomplete', [], _('LABEL...'))
2374 @command('debuglabelcomplete', [], _('LABEL...'))
2375 def debuglabelcomplete(ui, repo, *args):
2375 def debuglabelcomplete(ui, repo, *args):
2376 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2376 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2377 debugnamecomplete(ui, repo, *args)
2377 debugnamecomplete(ui, repo, *args)
2378
2378
2379 @command('debugnamecomplete', [], _('NAME...'))
2379 @command('debugnamecomplete', [], _('NAME...'))
2380 def debugnamecomplete(ui, repo, *args):
2380 def debugnamecomplete(ui, repo, *args):
2381 '''complete "names" - tags, open branch names, bookmark names'''
2381 '''complete "names" - tags, open branch names, bookmark names'''
2382
2382
2383 names = set()
2383 names = set()
2384 # since we previously only listed open branches, we will handle that
2384 # since we previously only listed open branches, we will handle that
2385 # specially (after this for loop)
2385 # specially (after this for loop)
2386 for name, ns in repo.names.iteritems():
2386 for name, ns in repo.names.iteritems():
2387 if name != 'branches':
2387 if name != 'branches':
2388 names.update(ns.listnames(repo))
2388 names.update(ns.listnames(repo))
2389 names.update(tag for (tag, heads, tip, closed)
2389 names.update(tag for (tag, heads, tip, closed)
2390 in repo.branchmap().iterbranches() if not closed)
2390 in repo.branchmap().iterbranches() if not closed)
2391 completions = set()
2391 completions = set()
2392 if not args:
2392 if not args:
2393 args = ['']
2393 args = ['']
2394 for a in args:
2394 for a in args:
2395 completions.update(n for n in names if n.startswith(a))
2395 completions.update(n for n in names if n.startswith(a))
2396 ui.write('\n'.join(sorted(completions)))
2396 ui.write('\n'.join(sorted(completions)))
2397 ui.write('\n')
2397 ui.write('\n')
2398
2398
2399 @command('debuglocks',
2399 @command('debuglocks',
2400 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2400 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2401 ('W', 'force-wlock', None,
2401 ('W', 'force-wlock', None,
2402 _('free the working state lock (DANGEROUS)'))],
2402 _('free the working state lock (DANGEROUS)'))],
2403 _('[OPTION]...'))
2403 _('[OPTION]...'))
2404 def debuglocks(ui, repo, **opts):
2404 def debuglocks(ui, repo, **opts):
2405 """show or modify state of locks
2405 """show or modify state of locks
2406
2406
2407 By default, this command will show which locks are held. This
2407 By default, this command will show which locks are held. This
2408 includes the user and process holding the lock, the amount of time
2408 includes the user and process holding the lock, the amount of time
2409 the lock has been held, and the machine name where the process is
2409 the lock has been held, and the machine name where the process is
2410 running if it's not local.
2410 running if it's not local.
2411
2411
2412 Locks protect the integrity of Mercurial's data, so should be
2412 Locks protect the integrity of Mercurial's data, so should be
2413 treated with care. System crashes or other interruptions may cause
2413 treated with care. System crashes or other interruptions may cause
2414 locks to not be properly released, though Mercurial will usually
2414 locks to not be properly released, though Mercurial will usually
2415 detect and remove such stale locks automatically.
2415 detect and remove such stale locks automatically.
2416
2416
2417 However, detecting stale locks may not always be possible (for
2417 However, detecting stale locks may not always be possible (for
2418 instance, on a shared filesystem). Removing locks may also be
2418 instance, on a shared filesystem). Removing locks may also be
2419 blocked by filesystem permissions.
2419 blocked by filesystem permissions.
2420
2420
2421 Returns 0 if no locks are held.
2421 Returns 0 if no locks are held.
2422
2422
2423 """
2423 """
2424
2424
2425 if opts.get('force_lock'):
2425 if opts.get('force_lock'):
2426 repo.svfs.unlink('lock')
2426 repo.svfs.unlink('lock')
2427 if opts.get('force_wlock'):
2427 if opts.get('force_wlock'):
2428 repo.vfs.unlink('wlock')
2428 repo.vfs.unlink('wlock')
2429 if opts.get('force_lock') or opts.get('force_lock'):
2429 if opts.get('force_lock') or opts.get('force_lock'):
2430 return 0
2430 return 0
2431
2431
2432 now = time.time()
2432 now = time.time()
2433 held = 0
2433 held = 0
2434
2434
2435 def report(vfs, name, method):
2435 def report(vfs, name, method):
2436 # this causes stale locks to get reaped for more accurate reporting
2436 # this causes stale locks to get reaped for more accurate reporting
2437 try:
2437 try:
2438 l = method(False)
2438 l = method(False)
2439 except error.LockHeld:
2439 except error.LockHeld:
2440 l = None
2440 l = None
2441
2441
2442 if l:
2442 if l:
2443 l.release()
2443 l.release()
2444 else:
2444 else:
2445 try:
2445 try:
2446 stat = repo.svfs.lstat(name)
2446 stat = repo.svfs.lstat(name)
2447 age = now - stat.st_mtime
2447 age = now - stat.st_mtime
2448 user = util.username(stat.st_uid)
2448 user = util.username(stat.st_uid)
2449 locker = vfs.readlock(name)
2449 locker = vfs.readlock(name)
2450 if ":" in locker:
2450 if ":" in locker:
2451 host, pid = locker.split(':')
2451 host, pid = locker.split(':')
2452 if host == socket.gethostname():
2452 if host == socket.gethostname():
2453 locker = 'user %s, process %s' % (user, pid)
2453 locker = 'user %s, process %s' % (user, pid)
2454 else:
2454 else:
2455 locker = 'user %s, process %s, host %s' \
2455 locker = 'user %s, process %s, host %s' \
2456 % (user, pid, host)
2456 % (user, pid, host)
2457 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2457 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2458 return 1
2458 return 1
2459 except OSError, e:
2459 except OSError, e:
2460 if e.errno != errno.ENOENT:
2460 if e.errno != errno.ENOENT:
2461 raise
2461 raise
2462
2462
2463 ui.write("%-6s free\n" % (name + ":"))
2463 ui.write("%-6s free\n" % (name + ":"))
2464 return 0
2464 return 0
2465
2465
2466 held += report(repo.svfs, "lock", repo.lock)
2466 held += report(repo.svfs, "lock", repo.lock)
2467 held += report(repo.vfs, "wlock", repo.wlock)
2467 held += report(repo.vfs, "wlock", repo.wlock)
2468
2468
2469 return held
2469 return held
2470
2470
2471 @command('debugobsolete',
2471 @command('debugobsolete',
2472 [('', 'flags', 0, _('markers flag')),
2472 [('', 'flags', 0, _('markers flag')),
2473 ('', 'record-parents', False,
2473 ('', 'record-parents', False,
2474 _('record parent information for the precursor')),
2474 _('record parent information for the precursor')),
2475 ('r', 'rev', [], _('display markers relevant to REV')),
2475 ('r', 'rev', [], _('display markers relevant to REV')),
2476 ] + commitopts2,
2476 ] + commitopts2,
2477 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2477 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2478 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2478 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2479 """create arbitrary obsolete marker
2479 """create arbitrary obsolete marker
2480
2480
2481 With no arguments, displays the list of obsolescence markers."""
2481 With no arguments, displays the list of obsolescence markers."""
2482
2482
2483 def parsenodeid(s):
2483 def parsenodeid(s):
2484 try:
2484 try:
2485 # We do not use revsingle/revrange functions here to accept
2485 # We do not use revsingle/revrange functions here to accept
2486 # arbitrary node identifiers, possibly not present in the
2486 # arbitrary node identifiers, possibly not present in the
2487 # local repository.
2487 # local repository.
2488 n = bin(s)
2488 n = bin(s)
2489 if len(n) != len(nullid):
2489 if len(n) != len(nullid):
2490 raise TypeError()
2490 raise TypeError()
2491 return n
2491 return n
2492 except TypeError:
2492 except TypeError:
2493 raise util.Abort('changeset references must be full hexadecimal '
2493 raise util.Abort('changeset references must be full hexadecimal '
2494 'node identifiers')
2494 'node identifiers')
2495
2495
2496 if precursor is not None:
2496 if precursor is not None:
2497 if opts['rev']:
2497 if opts['rev']:
2498 raise util.Abort('cannot select revision when creating marker')
2498 raise util.Abort('cannot select revision when creating marker')
2499 metadata = {}
2499 metadata = {}
2500 metadata['user'] = opts['user'] or ui.username()
2500 metadata['user'] = opts['user'] or ui.username()
2501 succs = tuple(parsenodeid(succ) for succ in successors)
2501 succs = tuple(parsenodeid(succ) for succ in successors)
2502 l = repo.lock()
2502 l = repo.lock()
2503 try:
2503 try:
2504 tr = repo.transaction('debugobsolete')
2504 tr = repo.transaction('debugobsolete')
2505 try:
2505 try:
2506 try:
2506 try:
2507 date = opts.get('date')
2507 date = opts.get('date')
2508 if date:
2508 if date:
2509 date = util.parsedate(date)
2509 date = util.parsedate(date)
2510 else:
2510 else:
2511 date = None
2511 date = None
2512 prec = parsenodeid(precursor)
2512 prec = parsenodeid(precursor)
2513 parents = None
2513 parents = None
2514 if opts['record_parents']:
2514 if opts['record_parents']:
2515 if prec not in repo.unfiltered():
2515 if prec not in repo.unfiltered():
2516 raise util.Abort('cannot used --record-parents on '
2516 raise util.Abort('cannot used --record-parents on '
2517 'unknown changesets')
2517 'unknown changesets')
2518 parents = repo.unfiltered()[prec].parents()
2518 parents = repo.unfiltered()[prec].parents()
2519 parents = tuple(p.node() for p in parents)
2519 parents = tuple(p.node() for p in parents)
2520 repo.obsstore.create(tr, prec, succs, opts['flags'],
2520 repo.obsstore.create(tr, prec, succs, opts['flags'],
2521 parents=parents, date=date,
2521 parents=parents, date=date,
2522 metadata=metadata)
2522 metadata=metadata)
2523 tr.close()
2523 tr.close()
2524 except ValueError, exc:
2524 except ValueError, exc:
2525 raise util.Abort(_('bad obsmarker input: %s') % exc)
2525 raise util.Abort(_('bad obsmarker input: %s') % exc)
2526 finally:
2526 finally:
2527 tr.release()
2527 tr.release()
2528 finally:
2528 finally:
2529 l.release()
2529 l.release()
2530 else:
2530 else:
2531 if opts['rev']:
2531 if opts['rev']:
2532 revs = scmutil.revrange(repo, opts['rev'])
2532 revs = scmutil.revrange(repo, opts['rev'])
2533 nodes = [repo[r].node() for r in revs]
2533 nodes = [repo[r].node() for r in revs]
2534 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2534 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2535 markers.sort(key=lambda x: x._data)
2535 markers.sort(key=lambda x: x._data)
2536 else:
2536 else:
2537 markers = obsolete.getmarkers(repo)
2537 markers = obsolete.getmarkers(repo)
2538
2538
2539 for m in markers:
2539 for m in markers:
2540 cmdutil.showmarker(ui, m)
2540 cmdutil.showmarker(ui, m)
2541
2541
2542 @command('debugpathcomplete',
2542 @command('debugpathcomplete',
2543 [('f', 'full', None, _('complete an entire path')),
2543 [('f', 'full', None, _('complete an entire path')),
2544 ('n', 'normal', None, _('show only normal files')),
2544 ('n', 'normal', None, _('show only normal files')),
2545 ('a', 'added', None, _('show only added files')),
2545 ('a', 'added', None, _('show only added files')),
2546 ('r', 'removed', None, _('show only removed files'))],
2546 ('r', 'removed', None, _('show only removed files'))],
2547 _('FILESPEC...'))
2547 _('FILESPEC...'))
2548 def debugpathcomplete(ui, repo, *specs, **opts):
2548 def debugpathcomplete(ui, repo, *specs, **opts):
2549 '''complete part or all of a tracked path
2549 '''complete part or all of a tracked path
2550
2550
2551 This command supports shells that offer path name completion. It
2551 This command supports shells that offer path name completion. It
2552 currently completes only files already known to the dirstate.
2552 currently completes only files already known to the dirstate.
2553
2553
2554 Completion extends only to the next path segment unless
2554 Completion extends only to the next path segment unless
2555 --full is specified, in which case entire paths are used.'''
2555 --full is specified, in which case entire paths are used.'''
2556
2556
2557 def complete(path, acceptable):
2557 def complete(path, acceptable):
2558 dirstate = repo.dirstate
2558 dirstate = repo.dirstate
2559 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2559 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2560 rootdir = repo.root + os.sep
2560 rootdir = repo.root + os.sep
2561 if spec != repo.root and not spec.startswith(rootdir):
2561 if spec != repo.root and not spec.startswith(rootdir):
2562 return [], []
2562 return [], []
2563 if os.path.isdir(spec):
2563 if os.path.isdir(spec):
2564 spec += '/'
2564 spec += '/'
2565 spec = spec[len(rootdir):]
2565 spec = spec[len(rootdir):]
2566 fixpaths = os.sep != '/'
2566 fixpaths = os.sep != '/'
2567 if fixpaths:
2567 if fixpaths:
2568 spec = spec.replace(os.sep, '/')
2568 spec = spec.replace(os.sep, '/')
2569 speclen = len(spec)
2569 speclen = len(spec)
2570 fullpaths = opts['full']
2570 fullpaths = opts['full']
2571 files, dirs = set(), set()
2571 files, dirs = set(), set()
2572 adddir, addfile = dirs.add, files.add
2572 adddir, addfile = dirs.add, files.add
2573 for f, st in dirstate.iteritems():
2573 for f, st in dirstate.iteritems():
2574 if f.startswith(spec) and st[0] in acceptable:
2574 if f.startswith(spec) and st[0] in acceptable:
2575 if fixpaths:
2575 if fixpaths:
2576 f = f.replace('/', os.sep)
2576 f = f.replace('/', os.sep)
2577 if fullpaths:
2577 if fullpaths:
2578 addfile(f)
2578 addfile(f)
2579 continue
2579 continue
2580 s = f.find(os.sep, speclen)
2580 s = f.find(os.sep, speclen)
2581 if s >= 0:
2581 if s >= 0:
2582 adddir(f[:s])
2582 adddir(f[:s])
2583 else:
2583 else:
2584 addfile(f)
2584 addfile(f)
2585 return files, dirs
2585 return files, dirs
2586
2586
2587 acceptable = ''
2587 acceptable = ''
2588 if opts['normal']:
2588 if opts['normal']:
2589 acceptable += 'nm'
2589 acceptable += 'nm'
2590 if opts['added']:
2590 if opts['added']:
2591 acceptable += 'a'
2591 acceptable += 'a'
2592 if opts['removed']:
2592 if opts['removed']:
2593 acceptable += 'r'
2593 acceptable += 'r'
2594 cwd = repo.getcwd()
2594 cwd = repo.getcwd()
2595 if not specs:
2595 if not specs:
2596 specs = ['.']
2596 specs = ['.']
2597
2597
2598 files, dirs = set(), set()
2598 files, dirs = set(), set()
2599 for spec in specs:
2599 for spec in specs:
2600 f, d = complete(spec, acceptable or 'nmar')
2600 f, d = complete(spec, acceptable or 'nmar')
2601 files.update(f)
2601 files.update(f)
2602 dirs.update(d)
2602 dirs.update(d)
2603 files.update(dirs)
2603 files.update(dirs)
2604 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2604 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2605 ui.write('\n')
2605 ui.write('\n')
2606
2606
2607 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2607 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2608 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2608 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2609 '''access the pushkey key/value protocol
2609 '''access the pushkey key/value protocol
2610
2610
2611 With two args, list the keys in the given namespace.
2611 With two args, list the keys in the given namespace.
2612
2612
2613 With five args, set a key to new if it currently is set to old.
2613 With five args, set a key to new if it currently is set to old.
2614 Reports success or failure.
2614 Reports success or failure.
2615 '''
2615 '''
2616
2616
2617 target = hg.peer(ui, {}, repopath)
2617 target = hg.peer(ui, {}, repopath)
2618 if keyinfo:
2618 if keyinfo:
2619 key, old, new = keyinfo
2619 key, old, new = keyinfo
2620 r = target.pushkey(namespace, key, old, new)
2620 r = target.pushkey(namespace, key, old, new)
2621 ui.status(str(r) + '\n')
2621 ui.status(str(r) + '\n')
2622 return not r
2622 return not r
2623 else:
2623 else:
2624 for k, v in sorted(target.listkeys(namespace).iteritems()):
2624 for k, v in sorted(target.listkeys(namespace).iteritems()):
2625 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2625 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2626 v.encode('string-escape')))
2626 v.encode('string-escape')))
2627
2627
2628 @command('debugpvec', [], _('A B'))
2628 @command('debugpvec', [], _('A B'))
2629 def debugpvec(ui, repo, a, b=None):
2629 def debugpvec(ui, repo, a, b=None):
2630 ca = scmutil.revsingle(repo, a)
2630 ca = scmutil.revsingle(repo, a)
2631 cb = scmutil.revsingle(repo, b)
2631 cb = scmutil.revsingle(repo, b)
2632 pa = pvec.ctxpvec(ca)
2632 pa = pvec.ctxpvec(ca)
2633 pb = pvec.ctxpvec(cb)
2633 pb = pvec.ctxpvec(cb)
2634 if pa == pb:
2634 if pa == pb:
2635 rel = "="
2635 rel = "="
2636 elif pa > pb:
2636 elif pa > pb:
2637 rel = ">"
2637 rel = ">"
2638 elif pa < pb:
2638 elif pa < pb:
2639 rel = "<"
2639 rel = "<"
2640 elif pa | pb:
2640 elif pa | pb:
2641 rel = "|"
2641 rel = "|"
2642 ui.write(_("a: %s\n") % pa)
2642 ui.write(_("a: %s\n") % pa)
2643 ui.write(_("b: %s\n") % pb)
2643 ui.write(_("b: %s\n") % pb)
2644 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2644 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2645 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2645 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2646 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2646 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2647 pa.distance(pb), rel))
2647 pa.distance(pb), rel))
2648
2648
2649 @command('debugrebuilddirstate|debugrebuildstate',
2649 @command('debugrebuilddirstate|debugrebuildstate',
2650 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2650 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2651 _('[-r REV]'))
2651 _('[-r REV]'))
2652 def debugrebuilddirstate(ui, repo, rev):
2652 def debugrebuilddirstate(ui, repo, rev):
2653 """rebuild the dirstate as it would look like for the given revision
2653 """rebuild the dirstate as it would look like for the given revision
2654
2654
2655 If no revision is specified the first current parent will be used.
2655 If no revision is specified the first current parent will be used.
2656
2656
2657 The dirstate will be set to the files of the given revision.
2657 The dirstate will be set to the files of the given revision.
2658 The actual working directory content or existing dirstate
2658 The actual working directory content or existing dirstate
2659 information such as adds or removes is not considered.
2659 information such as adds or removes is not considered.
2660
2660
2661 One use of this command is to make the next :hg:`status` invocation
2661 One use of this command is to make the next :hg:`status` invocation
2662 check the actual file content.
2662 check the actual file content.
2663 """
2663 """
2664 ctx = scmutil.revsingle(repo, rev)
2664 ctx = scmutil.revsingle(repo, rev)
2665 wlock = repo.wlock()
2665 wlock = repo.wlock()
2666 try:
2666 try:
2667 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2667 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2668 finally:
2668 finally:
2669 wlock.release()
2669 wlock.release()
2670
2670
2671 @command('debugrename',
2671 @command('debugrename',
2672 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2672 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2673 _('[-r REV] FILE'))
2673 _('[-r REV] FILE'))
2674 def debugrename(ui, repo, file1, *pats, **opts):
2674 def debugrename(ui, repo, file1, *pats, **opts):
2675 """dump rename information"""
2675 """dump rename information"""
2676
2676
2677 ctx = scmutil.revsingle(repo, opts.get('rev'))
2677 ctx = scmutil.revsingle(repo, opts.get('rev'))
2678 m = scmutil.match(ctx, (file1,) + pats, opts)
2678 m = scmutil.match(ctx, (file1,) + pats, opts)
2679 for abs in ctx.walk(m):
2679 for abs in ctx.walk(m):
2680 fctx = ctx[abs]
2680 fctx = ctx[abs]
2681 o = fctx.filelog().renamed(fctx.filenode())
2681 o = fctx.filelog().renamed(fctx.filenode())
2682 rel = m.rel(abs)
2682 rel = m.rel(abs)
2683 if o:
2683 if o:
2684 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2684 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2685 else:
2685 else:
2686 ui.write(_("%s not renamed\n") % rel)
2686 ui.write(_("%s not renamed\n") % rel)
2687
2687
2688 @command('debugrevlog',
2688 @command('debugrevlog',
2689 [('c', 'changelog', False, _('open changelog')),
2689 [('c', 'changelog', False, _('open changelog')),
2690 ('m', 'manifest', False, _('open manifest')),
2690 ('m', 'manifest', False, _('open manifest')),
2691 ('d', 'dump', False, _('dump index data'))],
2691 ('d', 'dump', False, _('dump index data'))],
2692 _('-c|-m|FILE'),
2692 _('-c|-m|FILE'),
2693 optionalrepo=True)
2693 optionalrepo=True)
2694 def debugrevlog(ui, repo, file_=None, **opts):
2694 def debugrevlog(ui, repo, file_=None, **opts):
2695 """show data and statistics about a revlog"""
2695 """show data and statistics about a revlog"""
2696 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2696 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2697
2697
2698 if opts.get("dump"):
2698 if opts.get("dump"):
2699 numrevs = len(r)
2699 numrevs = len(r)
2700 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2700 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2701 " rawsize totalsize compression heads chainlen\n")
2701 " rawsize totalsize compression heads chainlen\n")
2702 ts = 0
2702 ts = 0
2703 heads = set()
2703 heads = set()
2704
2704
2705 for rev in xrange(numrevs):
2705 for rev in xrange(numrevs):
2706 dbase = r.deltaparent(rev)
2706 dbase = r.deltaparent(rev)
2707 if dbase == -1:
2707 if dbase == -1:
2708 dbase = rev
2708 dbase = rev
2709 cbase = r.chainbase(rev)
2709 cbase = r.chainbase(rev)
2710 clen = r.chainlen(rev)
2710 clen = r.chainlen(rev)
2711 p1, p2 = r.parentrevs(rev)
2711 p1, p2 = r.parentrevs(rev)
2712 rs = r.rawsize(rev)
2712 rs = r.rawsize(rev)
2713 ts = ts + rs
2713 ts = ts + rs
2714 heads -= set(r.parentrevs(rev))
2714 heads -= set(r.parentrevs(rev))
2715 heads.add(rev)
2715 heads.add(rev)
2716 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2716 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2717 "%11d %5d %8d\n" %
2717 "%11d %5d %8d\n" %
2718 (rev, p1, p2, r.start(rev), r.end(rev),
2718 (rev, p1, p2, r.start(rev), r.end(rev),
2719 r.start(dbase), r.start(cbase),
2719 r.start(dbase), r.start(cbase),
2720 r.start(p1), r.start(p2),
2720 r.start(p1), r.start(p2),
2721 rs, ts, ts / r.end(rev), len(heads), clen))
2721 rs, ts, ts / r.end(rev), len(heads), clen))
2722 return 0
2722 return 0
2723
2723
2724 v = r.version
2724 v = r.version
2725 format = v & 0xFFFF
2725 format = v & 0xFFFF
2726 flags = []
2726 flags = []
2727 gdelta = False
2727 gdelta = False
2728 if v & revlog.REVLOGNGINLINEDATA:
2728 if v & revlog.REVLOGNGINLINEDATA:
2729 flags.append('inline')
2729 flags.append('inline')
2730 if v & revlog.REVLOGGENERALDELTA:
2730 if v & revlog.REVLOGGENERALDELTA:
2731 gdelta = True
2731 gdelta = True
2732 flags.append('generaldelta')
2732 flags.append('generaldelta')
2733 if not flags:
2733 if not flags:
2734 flags = ['(none)']
2734 flags = ['(none)']
2735
2735
2736 nummerges = 0
2736 nummerges = 0
2737 numfull = 0
2737 numfull = 0
2738 numprev = 0
2738 numprev = 0
2739 nump1 = 0
2739 nump1 = 0
2740 nump2 = 0
2740 nump2 = 0
2741 numother = 0
2741 numother = 0
2742 nump1prev = 0
2742 nump1prev = 0
2743 nump2prev = 0
2743 nump2prev = 0
2744 chainlengths = []
2744 chainlengths = []
2745
2745
2746 datasize = [None, 0, 0L]
2746 datasize = [None, 0, 0L]
2747 fullsize = [None, 0, 0L]
2747 fullsize = [None, 0, 0L]
2748 deltasize = [None, 0, 0L]
2748 deltasize = [None, 0, 0L]
2749
2749
2750 def addsize(size, l):
2750 def addsize(size, l):
2751 if l[0] is None or size < l[0]:
2751 if l[0] is None or size < l[0]:
2752 l[0] = size
2752 l[0] = size
2753 if size > l[1]:
2753 if size > l[1]:
2754 l[1] = size
2754 l[1] = size
2755 l[2] += size
2755 l[2] += size
2756
2756
2757 numrevs = len(r)
2757 numrevs = len(r)
2758 for rev in xrange(numrevs):
2758 for rev in xrange(numrevs):
2759 p1, p2 = r.parentrevs(rev)
2759 p1, p2 = r.parentrevs(rev)
2760 delta = r.deltaparent(rev)
2760 delta = r.deltaparent(rev)
2761 if format > 0:
2761 if format > 0:
2762 addsize(r.rawsize(rev), datasize)
2762 addsize(r.rawsize(rev), datasize)
2763 if p2 != nullrev:
2763 if p2 != nullrev:
2764 nummerges += 1
2764 nummerges += 1
2765 size = r.length(rev)
2765 size = r.length(rev)
2766 if delta == nullrev:
2766 if delta == nullrev:
2767 chainlengths.append(0)
2767 chainlengths.append(0)
2768 numfull += 1
2768 numfull += 1
2769 addsize(size, fullsize)
2769 addsize(size, fullsize)
2770 else:
2770 else:
2771 chainlengths.append(chainlengths[delta] + 1)
2771 chainlengths.append(chainlengths[delta] + 1)
2772 addsize(size, deltasize)
2772 addsize(size, deltasize)
2773 if delta == rev - 1:
2773 if delta == rev - 1:
2774 numprev += 1
2774 numprev += 1
2775 if delta == p1:
2775 if delta == p1:
2776 nump1prev += 1
2776 nump1prev += 1
2777 elif delta == p2:
2777 elif delta == p2:
2778 nump2prev += 1
2778 nump2prev += 1
2779 elif delta == p1:
2779 elif delta == p1:
2780 nump1 += 1
2780 nump1 += 1
2781 elif delta == p2:
2781 elif delta == p2:
2782 nump2 += 1
2782 nump2 += 1
2783 elif delta != nullrev:
2783 elif delta != nullrev:
2784 numother += 1
2784 numother += 1
2785
2785
2786 # Adjust size min value for empty cases
2786 # Adjust size min value for empty cases
2787 for size in (datasize, fullsize, deltasize):
2787 for size in (datasize, fullsize, deltasize):
2788 if size[0] is None:
2788 if size[0] is None:
2789 size[0] = 0
2789 size[0] = 0
2790
2790
2791 numdeltas = numrevs - numfull
2791 numdeltas = numrevs - numfull
2792 numoprev = numprev - nump1prev - nump2prev
2792 numoprev = numprev - nump1prev - nump2prev
2793 totalrawsize = datasize[2]
2793 totalrawsize = datasize[2]
2794 datasize[2] /= numrevs
2794 datasize[2] /= numrevs
2795 fulltotal = fullsize[2]
2795 fulltotal = fullsize[2]
2796 fullsize[2] /= numfull
2796 fullsize[2] /= numfull
2797 deltatotal = deltasize[2]
2797 deltatotal = deltasize[2]
2798 if numrevs - numfull > 0:
2798 if numrevs - numfull > 0:
2799 deltasize[2] /= numrevs - numfull
2799 deltasize[2] /= numrevs - numfull
2800 totalsize = fulltotal + deltatotal
2800 totalsize = fulltotal + deltatotal
2801 avgchainlen = sum(chainlengths) / numrevs
2801 avgchainlen = sum(chainlengths) / numrevs
2802 compratio = totalrawsize / totalsize
2802 compratio = totalrawsize / totalsize
2803
2803
2804 basedfmtstr = '%%%dd\n'
2804 basedfmtstr = '%%%dd\n'
2805 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2805 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2806
2806
2807 def dfmtstr(max):
2807 def dfmtstr(max):
2808 return basedfmtstr % len(str(max))
2808 return basedfmtstr % len(str(max))
2809 def pcfmtstr(max, padding=0):
2809 def pcfmtstr(max, padding=0):
2810 return basepcfmtstr % (len(str(max)), ' ' * padding)
2810 return basepcfmtstr % (len(str(max)), ' ' * padding)
2811
2811
2812 def pcfmt(value, total):
2812 def pcfmt(value, total):
2813 return (value, 100 * float(value) / total)
2813 return (value, 100 * float(value) / total)
2814
2814
2815 ui.write(('format : %d\n') % format)
2815 ui.write(('format : %d\n') % format)
2816 ui.write(('flags : %s\n') % ', '.join(flags))
2816 ui.write(('flags : %s\n') % ', '.join(flags))
2817
2817
2818 ui.write('\n')
2818 ui.write('\n')
2819 fmt = pcfmtstr(totalsize)
2819 fmt = pcfmtstr(totalsize)
2820 fmt2 = dfmtstr(totalsize)
2820 fmt2 = dfmtstr(totalsize)
2821 ui.write(('revisions : ') + fmt2 % numrevs)
2821 ui.write(('revisions : ') + fmt2 % numrevs)
2822 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2822 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2823 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2823 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2824 ui.write(('revisions : ') + fmt2 % numrevs)
2824 ui.write(('revisions : ') + fmt2 % numrevs)
2825 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2825 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2826 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2826 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2827 ui.write(('revision size : ') + fmt2 % totalsize)
2827 ui.write(('revision size : ') + fmt2 % totalsize)
2828 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2828 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2829 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2829 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2830
2830
2831 ui.write('\n')
2831 ui.write('\n')
2832 fmt = dfmtstr(max(avgchainlen, compratio))
2832 fmt = dfmtstr(max(avgchainlen, compratio))
2833 ui.write(('avg chain length : ') + fmt % avgchainlen)
2833 ui.write(('avg chain length : ') + fmt % avgchainlen)
2834 ui.write(('compression ratio : ') + fmt % compratio)
2834 ui.write(('compression ratio : ') + fmt % compratio)
2835
2835
2836 if format > 0:
2836 if format > 0:
2837 ui.write('\n')
2837 ui.write('\n')
2838 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2838 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2839 % tuple(datasize))
2839 % tuple(datasize))
2840 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2840 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2841 % tuple(fullsize))
2841 % tuple(fullsize))
2842 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2842 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2843 % tuple(deltasize))
2843 % tuple(deltasize))
2844
2844
2845 if numdeltas > 0:
2845 if numdeltas > 0:
2846 ui.write('\n')
2846 ui.write('\n')
2847 fmt = pcfmtstr(numdeltas)
2847 fmt = pcfmtstr(numdeltas)
2848 fmt2 = pcfmtstr(numdeltas, 4)
2848 fmt2 = pcfmtstr(numdeltas, 4)
2849 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2849 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2850 if numprev > 0:
2850 if numprev > 0:
2851 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2851 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2852 numprev))
2852 numprev))
2853 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2853 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2854 numprev))
2854 numprev))
2855 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2855 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2856 numprev))
2856 numprev))
2857 if gdelta:
2857 if gdelta:
2858 ui.write(('deltas against p1 : ')
2858 ui.write(('deltas against p1 : ')
2859 + fmt % pcfmt(nump1, numdeltas))
2859 + fmt % pcfmt(nump1, numdeltas))
2860 ui.write(('deltas against p2 : ')
2860 ui.write(('deltas against p2 : ')
2861 + fmt % pcfmt(nump2, numdeltas))
2861 + fmt % pcfmt(nump2, numdeltas))
2862 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2862 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2863 numdeltas))
2863 numdeltas))
2864
2864
2865 @command('debugrevspec',
2865 @command('debugrevspec',
2866 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2866 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2867 ('REVSPEC'))
2867 ('REVSPEC'))
2868 def debugrevspec(ui, repo, expr, **opts):
2868 def debugrevspec(ui, repo, expr, **opts):
2869 """parse and apply a revision specification
2869 """parse and apply a revision specification
2870
2870
2871 Use --verbose to print the parsed tree before and after aliases
2871 Use --verbose to print the parsed tree before and after aliases
2872 expansion.
2872 expansion.
2873 """
2873 """
2874 if ui.verbose:
2874 if ui.verbose:
2875 tree = revset.parse(expr)[0]
2875 tree = revset.parse(expr)[0]
2876 ui.note(revset.prettyformat(tree), "\n")
2876 ui.note(revset.prettyformat(tree), "\n")
2877 newtree = revset.findaliases(ui, tree)
2877 newtree = revset.findaliases(ui, tree)
2878 if newtree != tree:
2878 if newtree != tree:
2879 ui.note(revset.prettyformat(newtree), "\n")
2879 ui.note(revset.prettyformat(newtree), "\n")
2880 tree = newtree
2880 tree = newtree
2881 newtree = revset.foldconcat(tree)
2881 newtree = revset.foldconcat(tree)
2882 if newtree != tree:
2882 if newtree != tree:
2883 ui.note(revset.prettyformat(newtree), "\n")
2883 ui.note(revset.prettyformat(newtree), "\n")
2884 if opts["optimize"]:
2884 if opts["optimize"]:
2885 weight, optimizedtree = revset.optimize(newtree, True)
2885 weight, optimizedtree = revset.optimize(newtree, True)
2886 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2886 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2887 func = revset.match(ui, expr)
2887 func = revset.match(ui, expr)
2888 for c in func(repo):
2888 for c in func(repo):
2889 ui.write("%s\n" % c)
2889 ui.write("%s\n" % c)
2890
2890
2891 @command('debugsetparents', [], _('REV1 [REV2]'))
2891 @command('debugsetparents', [], _('REV1 [REV2]'))
2892 def debugsetparents(ui, repo, rev1, rev2=None):
2892 def debugsetparents(ui, repo, rev1, rev2=None):
2893 """manually set the parents of the current working directory
2893 """manually set the parents of the current working directory
2894
2894
2895 This is useful for writing repository conversion tools, but should
2895 This is useful for writing repository conversion tools, but should
2896 be used with care. For example, neither the working copy nor the dirstate
2896 be used with care. For example, neither the working copy nor the dirstate
2897 is updated, so file status may be incorrect after running this command.
2897 is updated, so file status may be incorrect after running this command.
2898
2898
2899 Returns 0 on success.
2899 Returns 0 on success.
2900 """
2900 """
2901
2901
2902 r1 = scmutil.revsingle(repo, rev1).node()
2902 r1 = scmutil.revsingle(repo, rev1).node()
2903 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2903 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2904
2904
2905 wlock = repo.wlock()
2905 wlock = repo.wlock()
2906 try:
2906 try:
2907 repo.dirstate.beginparentchange()
2907 repo.dirstate.beginparentchange()
2908 repo.setparents(r1, r2)
2908 repo.setparents(r1, r2)
2909 repo.dirstate.endparentchange()
2909 repo.dirstate.endparentchange()
2910 finally:
2910 finally:
2911 wlock.release()
2911 wlock.release()
2912
2912
2913 @command('debugdirstate|debugstate',
2913 @command('debugdirstate|debugstate',
2914 [('', 'nodates', None, _('do not display the saved mtime')),
2914 [('', 'nodates', None, _('do not display the saved mtime')),
2915 ('', 'datesort', None, _('sort by saved mtime'))],
2915 ('', 'datesort', None, _('sort by saved mtime'))],
2916 _('[OPTION]...'))
2916 _('[OPTION]...'))
2917 def debugstate(ui, repo, nodates=None, datesort=None):
2917 def debugstate(ui, repo, nodates=None, datesort=None):
2918 """show the contents of the current dirstate"""
2918 """show the contents of the current dirstate"""
2919 timestr = ""
2919 timestr = ""
2920 if datesort:
2920 if datesort:
2921 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2921 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2922 else:
2922 else:
2923 keyfunc = None # sort by filename
2923 keyfunc = None # sort by filename
2924 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2924 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2925 if ent[3] == -1:
2925 if ent[3] == -1:
2926 timestr = 'unset '
2926 timestr = 'unset '
2927 elif nodates:
2927 elif nodates:
2928 timestr = 'set '
2928 timestr = 'set '
2929 else:
2929 else:
2930 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2930 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2931 time.localtime(ent[3]))
2931 time.localtime(ent[3]))
2932 if ent[1] & 020000:
2932 if ent[1] & 020000:
2933 mode = 'lnk'
2933 mode = 'lnk'
2934 else:
2934 else:
2935 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2935 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2936 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2936 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2937 for f in repo.dirstate.copies():
2937 for f in repo.dirstate.copies():
2938 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2938 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2939
2939
2940 @command('debugsub',
2940 @command('debugsub',
2941 [('r', 'rev', '',
2941 [('r', 'rev', '',
2942 _('revision to check'), _('REV'))],
2942 _('revision to check'), _('REV'))],
2943 _('[-r REV] [REV]'))
2943 _('[-r REV] [REV]'))
2944 def debugsub(ui, repo, rev=None):
2944 def debugsub(ui, repo, rev=None):
2945 ctx = scmutil.revsingle(repo, rev, None)
2945 ctx = scmutil.revsingle(repo, rev, None)
2946 for k, v in sorted(ctx.substate.items()):
2946 for k, v in sorted(ctx.substate.items()):
2947 ui.write(('path %s\n') % k)
2947 ui.write(('path %s\n') % k)
2948 ui.write((' source %s\n') % v[0])
2948 ui.write((' source %s\n') % v[0])
2949 ui.write((' revision %s\n') % v[1])
2949 ui.write((' revision %s\n') % v[1])
2950
2950
2951 @command('debugsuccessorssets',
2951 @command('debugsuccessorssets',
2952 [],
2952 [],
2953 _('[REV]'))
2953 _('[REV]'))
2954 def debugsuccessorssets(ui, repo, *revs):
2954 def debugsuccessorssets(ui, repo, *revs):
2955 """show set of successors for revision
2955 """show set of successors for revision
2956
2956
2957 A successors set of changeset A is a consistent group of revisions that
2957 A successors set of changeset A is a consistent group of revisions that
2958 succeed A. It contains non-obsolete changesets only.
2958 succeed A. It contains non-obsolete changesets only.
2959
2959
2960 In most cases a changeset A has a single successors set containing a single
2960 In most cases a changeset A has a single successors set containing a single
2961 successor (changeset A replaced by A').
2961 successor (changeset A replaced by A').
2962
2962
2963 A changeset that is made obsolete with no successors are called "pruned".
2963 A changeset that is made obsolete with no successors are called "pruned".
2964 Such changesets have no successors sets at all.
2964 Such changesets have no successors sets at all.
2965
2965
2966 A changeset that has been "split" will have a successors set containing
2966 A changeset that has been "split" will have a successors set containing
2967 more than one successor.
2967 more than one successor.
2968
2968
2969 A changeset that has been rewritten in multiple different ways is called
2969 A changeset that has been rewritten in multiple different ways is called
2970 "divergent". Such changesets have multiple successor sets (each of which
2970 "divergent". Such changesets have multiple successor sets (each of which
2971 may also be split, i.e. have multiple successors).
2971 may also be split, i.e. have multiple successors).
2972
2972
2973 Results are displayed as follows::
2973 Results are displayed as follows::
2974
2974
2975 <rev1>
2975 <rev1>
2976 <successors-1A>
2976 <successors-1A>
2977 <rev2>
2977 <rev2>
2978 <successors-2A>
2978 <successors-2A>
2979 <successors-2B1> <successors-2B2> <successors-2B3>
2979 <successors-2B1> <successors-2B2> <successors-2B3>
2980
2980
2981 Here rev2 has two possible (i.e. divergent) successors sets. The first
2981 Here rev2 has two possible (i.e. divergent) successors sets. The first
2982 holds one element, whereas the second holds three (i.e. the changeset has
2982 holds one element, whereas the second holds three (i.e. the changeset has
2983 been split).
2983 been split).
2984 """
2984 """
2985 # passed to successorssets caching computation from one call to another
2985 # passed to successorssets caching computation from one call to another
2986 cache = {}
2986 cache = {}
2987 ctx2str = str
2987 ctx2str = str
2988 node2str = short
2988 node2str = short
2989 if ui.debug():
2989 if ui.debug():
2990 def ctx2str(ctx):
2990 def ctx2str(ctx):
2991 return ctx.hex()
2991 return ctx.hex()
2992 node2str = hex
2992 node2str = hex
2993 for rev in scmutil.revrange(repo, revs):
2993 for rev in scmutil.revrange(repo, revs):
2994 ctx = repo[rev]
2994 ctx = repo[rev]
2995 ui.write('%s\n'% ctx2str(ctx))
2995 ui.write('%s\n'% ctx2str(ctx))
2996 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2996 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2997 if succsset:
2997 if succsset:
2998 ui.write(' ')
2998 ui.write(' ')
2999 ui.write(node2str(succsset[0]))
2999 ui.write(node2str(succsset[0]))
3000 for node in succsset[1:]:
3000 for node in succsset[1:]:
3001 ui.write(' ')
3001 ui.write(' ')
3002 ui.write(node2str(node))
3002 ui.write(node2str(node))
3003 ui.write('\n')
3003 ui.write('\n')
3004
3004
3005 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3005 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3006 def debugwalk(ui, repo, *pats, **opts):
3006 def debugwalk(ui, repo, *pats, **opts):
3007 """show how files match on given patterns"""
3007 """show how files match on given patterns"""
3008 m = scmutil.match(repo[None], pats, opts)
3008 m = scmutil.match(repo[None], pats, opts)
3009 items = list(repo.walk(m))
3009 items = list(repo.walk(m))
3010 if not items:
3010 if not items:
3011 return
3011 return
3012 f = lambda fn: fn
3012 f = lambda fn: fn
3013 if ui.configbool('ui', 'slash') and os.sep != '/':
3013 if ui.configbool('ui', 'slash') and os.sep != '/':
3014 f = lambda fn: util.normpath(fn)
3014 f = lambda fn: util.normpath(fn)
3015 fmt = 'f %%-%ds %%-%ds %%s' % (
3015 fmt = 'f %%-%ds %%-%ds %%s' % (
3016 max([len(abs) for abs in items]),
3016 max([len(abs) for abs in items]),
3017 max([len(m.rel(abs)) for abs in items]))
3017 max([len(m.rel(abs)) for abs in items]))
3018 for abs in items:
3018 for abs in items:
3019 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3019 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3020 ui.write("%s\n" % line.rstrip())
3020 ui.write("%s\n" % line.rstrip())
3021
3021
3022 @command('debugwireargs',
3022 @command('debugwireargs',
3023 [('', 'three', '', 'three'),
3023 [('', 'three', '', 'three'),
3024 ('', 'four', '', 'four'),
3024 ('', 'four', '', 'four'),
3025 ('', 'five', '', 'five'),
3025 ('', 'five', '', 'five'),
3026 ] + remoteopts,
3026 ] + remoteopts,
3027 _('REPO [OPTIONS]... [ONE [TWO]]'),
3027 _('REPO [OPTIONS]... [ONE [TWO]]'),
3028 norepo=True)
3028 norepo=True)
3029 def debugwireargs(ui, repopath, *vals, **opts):
3029 def debugwireargs(ui, repopath, *vals, **opts):
3030 repo = hg.peer(ui, opts, repopath)
3030 repo = hg.peer(ui, opts, repopath)
3031 for opt in remoteopts:
3031 for opt in remoteopts:
3032 del opts[opt[1]]
3032 del opts[opt[1]]
3033 args = {}
3033 args = {}
3034 for k, v in opts.iteritems():
3034 for k, v in opts.iteritems():
3035 if v:
3035 if v:
3036 args[k] = v
3036 args[k] = v
3037 # run twice to check that we don't mess up the stream for the next command
3037 # run twice to check that we don't mess up the stream for the next command
3038 res1 = repo.debugwireargs(*vals, **args)
3038 res1 = repo.debugwireargs(*vals, **args)
3039 res2 = repo.debugwireargs(*vals, **args)
3039 res2 = repo.debugwireargs(*vals, **args)
3040 ui.write("%s\n" % res1)
3040 ui.write("%s\n" % res1)
3041 if res1 != res2:
3041 if res1 != res2:
3042 ui.warn("%s\n" % res2)
3042 ui.warn("%s\n" % res2)
3043
3043
3044 @command('^diff',
3044 @command('^diff',
3045 [('r', 'rev', [], _('revision'), _('REV')),
3045 [('r', 'rev', [], _('revision'), _('REV')),
3046 ('c', 'change', '', _('change made by revision'), _('REV'))
3046 ('c', 'change', '', _('change made by revision'), _('REV'))
3047 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3047 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3048 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3048 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3049 inferrepo=True)
3049 inferrepo=True)
3050 def diff(ui, repo, *pats, **opts):
3050 def diff(ui, repo, *pats, **opts):
3051 """diff repository (or selected files)
3051 """diff repository (or selected files)
3052
3052
3053 Show differences between revisions for the specified files.
3053 Show differences between revisions for the specified files.
3054
3054
3055 Differences between files are shown using the unified diff format.
3055 Differences between files are shown using the unified diff format.
3056
3056
3057 .. note::
3057 .. note::
3058
3058
3059 diff may generate unexpected results for merges, as it will
3059 diff may generate unexpected results for merges, as it will
3060 default to comparing against the working directory's first
3060 default to comparing against the working directory's first
3061 parent changeset if no revisions are specified.
3061 parent changeset if no revisions are specified.
3062
3062
3063 When two revision arguments are given, then changes are shown
3063 When two revision arguments are given, then changes are shown
3064 between those revisions. If only one revision is specified then
3064 between those revisions. If only one revision is specified then
3065 that revision is compared to the working directory, and, when no
3065 that revision is compared to the working directory, and, when no
3066 revisions are specified, the working directory files are compared
3066 revisions are specified, the working directory files are compared
3067 to its parent.
3067 to its parent.
3068
3068
3069 Alternatively you can specify -c/--change with a revision to see
3069 Alternatively you can specify -c/--change with a revision to see
3070 the changes in that changeset relative to its first parent.
3070 the changes in that changeset relative to its first parent.
3071
3071
3072 Without the -a/--text option, diff will avoid generating diffs of
3072 Without the -a/--text option, diff will avoid generating diffs of
3073 files it detects as binary. With -a, diff will generate a diff
3073 files it detects as binary. With -a, diff will generate a diff
3074 anyway, probably with undesirable results.
3074 anyway, probably with undesirable results.
3075
3075
3076 Use the -g/--git option to generate diffs in the git extended diff
3076 Use the -g/--git option to generate diffs in the git extended diff
3077 format. For more information, read :hg:`help diffs`.
3077 format. For more information, read :hg:`help diffs`.
3078
3078
3079 .. container:: verbose
3079 .. container:: verbose
3080
3080
3081 Examples:
3081 Examples:
3082
3082
3083 - compare a file in the current working directory to its parent::
3083 - compare a file in the current working directory to its parent::
3084
3084
3085 hg diff foo.c
3085 hg diff foo.c
3086
3086
3087 - compare two historical versions of a directory, with rename info::
3087 - compare two historical versions of a directory, with rename info::
3088
3088
3089 hg diff --git -r 1.0:1.2 lib/
3089 hg diff --git -r 1.0:1.2 lib/
3090
3090
3091 - get change stats relative to the last change on some date::
3091 - get change stats relative to the last change on some date::
3092
3092
3093 hg diff --stat -r "date('may 2')"
3093 hg diff --stat -r "date('may 2')"
3094
3094
3095 - diff all newly-added files that contain a keyword::
3095 - diff all newly-added files that contain a keyword::
3096
3096
3097 hg diff "set:added() and grep(GNU)"
3097 hg diff "set:added() and grep(GNU)"
3098
3098
3099 - compare a revision and its parents::
3099 - compare a revision and its parents::
3100
3100
3101 hg diff -c 9353 # compare against first parent
3101 hg diff -c 9353 # compare against first parent
3102 hg diff -r 9353^:9353 # same using revset syntax
3102 hg diff -r 9353^:9353 # same using revset syntax
3103 hg diff -r 9353^2:9353 # compare against the second parent
3103 hg diff -r 9353^2:9353 # compare against the second parent
3104
3104
3105 Returns 0 on success.
3105 Returns 0 on success.
3106 """
3106 """
3107
3107
3108 revs = opts.get('rev')
3108 revs = opts.get('rev')
3109 change = opts.get('change')
3109 change = opts.get('change')
3110 stat = opts.get('stat')
3110 stat = opts.get('stat')
3111 reverse = opts.get('reverse')
3111 reverse = opts.get('reverse')
3112
3112
3113 if revs and change:
3113 if revs and change:
3114 msg = _('cannot specify --rev and --change at the same time')
3114 msg = _('cannot specify --rev and --change at the same time')
3115 raise util.Abort(msg)
3115 raise util.Abort(msg)
3116 elif change:
3116 elif change:
3117 node2 = scmutil.revsingle(repo, change, None).node()
3117 node2 = scmutil.revsingle(repo, change, None).node()
3118 node1 = repo[node2].p1().node()
3118 node1 = repo[node2].p1().node()
3119 else:
3119 else:
3120 node1, node2 = scmutil.revpair(repo, revs)
3120 node1, node2 = scmutil.revpair(repo, revs)
3121
3121
3122 if reverse:
3122 if reverse:
3123 node1, node2 = node2, node1
3123 node1, node2 = node2, node1
3124
3124
3125 diffopts = patch.diffallopts(ui, opts)
3125 diffopts = patch.diffallopts(ui, opts)
3126 m = scmutil.match(repo[node2], pats, opts)
3126 m = scmutil.match(repo[node2], pats, opts)
3127 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3127 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3128 listsubrepos=opts.get('subrepos'))
3128 listsubrepos=opts.get('subrepos'))
3129
3129
3130 @command('^export',
3130 @command('^export',
3131 [('o', 'output', '',
3131 [('o', 'output', '',
3132 _('print output to file with formatted name'), _('FORMAT')),
3132 _('print output to file with formatted name'), _('FORMAT')),
3133 ('', 'switch-parent', None, _('diff against the second parent')),
3133 ('', 'switch-parent', None, _('diff against the second parent')),
3134 ('r', 'rev', [], _('revisions to export'), _('REV')),
3134 ('r', 'rev', [], _('revisions to export'), _('REV')),
3135 ] + diffopts,
3135 ] + diffopts,
3136 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3136 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3137 def export(ui, repo, *changesets, **opts):
3137 def export(ui, repo, *changesets, **opts):
3138 """dump the header and diffs for one or more changesets
3138 """dump the header and diffs for one or more changesets
3139
3139
3140 Print the changeset header and diffs for one or more revisions.
3140 Print the changeset header and diffs for one or more revisions.
3141 If no revision is given, the parent of the working directory is used.
3141 If no revision is given, the parent of the working directory is used.
3142
3142
3143 The information shown in the changeset header is: author, date,
3143 The information shown in the changeset header is: author, date,
3144 branch name (if non-default), changeset hash, parent(s) and commit
3144 branch name (if non-default), changeset hash, parent(s) and commit
3145 comment.
3145 comment.
3146
3146
3147 .. note::
3147 .. note::
3148
3148
3149 export may generate unexpected diff output for merge
3149 export may generate unexpected diff output for merge
3150 changesets, as it will compare the merge changeset against its
3150 changesets, as it will compare the merge changeset against its
3151 first parent only.
3151 first parent only.
3152
3152
3153 Output may be to a file, in which case the name of the file is
3153 Output may be to a file, in which case the name of the file is
3154 given using a format string. The formatting rules are as follows:
3154 given using a format string. The formatting rules are as follows:
3155
3155
3156 :``%%``: literal "%" character
3156 :``%%``: literal "%" character
3157 :``%H``: changeset hash (40 hexadecimal digits)
3157 :``%H``: changeset hash (40 hexadecimal digits)
3158 :``%N``: number of patches being generated
3158 :``%N``: number of patches being generated
3159 :``%R``: changeset revision number
3159 :``%R``: changeset revision number
3160 :``%b``: basename of the exporting repository
3160 :``%b``: basename of the exporting repository
3161 :``%h``: short-form changeset hash (12 hexadecimal digits)
3161 :``%h``: short-form changeset hash (12 hexadecimal digits)
3162 :``%m``: first line of the commit message (only alphanumeric characters)
3162 :``%m``: first line of the commit message (only alphanumeric characters)
3163 :``%n``: zero-padded sequence number, starting at 1
3163 :``%n``: zero-padded sequence number, starting at 1
3164 :``%r``: zero-padded changeset revision number
3164 :``%r``: zero-padded changeset revision number
3165
3165
3166 Without the -a/--text option, export will avoid generating diffs
3166 Without the -a/--text option, export will avoid generating diffs
3167 of files it detects as binary. With -a, export will generate a
3167 of files it detects as binary. With -a, export will generate a
3168 diff anyway, probably with undesirable results.
3168 diff anyway, probably with undesirable results.
3169
3169
3170 Use the -g/--git option to generate diffs in the git extended diff
3170 Use the -g/--git option to generate diffs in the git extended diff
3171 format. See :hg:`help diffs` for more information.
3171 format. See :hg:`help diffs` for more information.
3172
3172
3173 With the --switch-parent option, the diff will be against the
3173 With the --switch-parent option, the diff will be against the
3174 second parent. It can be useful to review a merge.
3174 second parent. It can be useful to review a merge.
3175
3175
3176 .. container:: verbose
3176 .. container:: verbose
3177
3177
3178 Examples:
3178 Examples:
3179
3179
3180 - use export and import to transplant a bugfix to the current
3180 - use export and import to transplant a bugfix to the current
3181 branch::
3181 branch::
3182
3182
3183 hg export -r 9353 | hg import -
3183 hg export -r 9353 | hg import -
3184
3184
3185 - export all the changesets between two revisions to a file with
3185 - export all the changesets between two revisions to a file with
3186 rename information::
3186 rename information::
3187
3187
3188 hg export --git -r 123:150 > changes.txt
3188 hg export --git -r 123:150 > changes.txt
3189
3189
3190 - split outgoing changes into a series of patches with
3190 - split outgoing changes into a series of patches with
3191 descriptive names::
3191 descriptive names::
3192
3192
3193 hg export -r "outgoing()" -o "%n-%m.patch"
3193 hg export -r "outgoing()" -o "%n-%m.patch"
3194
3194
3195 Returns 0 on success.
3195 Returns 0 on success.
3196 """
3196 """
3197 changesets += tuple(opts.get('rev', []))
3197 changesets += tuple(opts.get('rev', []))
3198 if not changesets:
3198 if not changesets:
3199 changesets = ['.']
3199 changesets = ['.']
3200 revs = scmutil.revrange(repo, changesets)
3200 revs = scmutil.revrange(repo, changesets)
3201 if not revs:
3201 if not revs:
3202 raise util.Abort(_("export requires at least one changeset"))
3202 raise util.Abort(_("export requires at least one changeset"))
3203 if len(revs) > 1:
3203 if len(revs) > 1:
3204 ui.note(_('exporting patches:\n'))
3204 ui.note(_('exporting patches:\n'))
3205 else:
3205 else:
3206 ui.note(_('exporting patch:\n'))
3206 ui.note(_('exporting patch:\n'))
3207 cmdutil.export(repo, revs, template=opts.get('output'),
3207 cmdutil.export(repo, revs, template=opts.get('output'),
3208 switch_parent=opts.get('switch_parent'),
3208 switch_parent=opts.get('switch_parent'),
3209 opts=patch.diffallopts(ui, opts))
3209 opts=patch.diffallopts(ui, opts))
3210
3210
3211 @command('files',
3211 @command('files',
3212 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3212 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3213 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3213 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3214 ] + walkopts + formatteropts,
3214 ] + walkopts + formatteropts,
3215 _('[OPTION]... [PATTERN]...'))
3215 _('[OPTION]... [PATTERN]...'))
3216 def files(ui, repo, *pats, **opts):
3216 def files(ui, repo, *pats, **opts):
3217 """list tracked files
3217 """list tracked files
3218
3218
3219 Print files under Mercurial control in the working directory or
3219 Print files under Mercurial control in the working directory or
3220 specified revision whose names match the given patterns (excluding
3220 specified revision whose names match the given patterns (excluding
3221 removed files).
3221 removed files).
3222
3222
3223 If no patterns are given to match, this command prints the names
3223 If no patterns are given to match, this command prints the names
3224 of all files under Mercurial control in the working copy.
3224 of all files under Mercurial control in the working copy.
3225
3225
3226 .. container:: verbose
3226 .. container:: verbose
3227
3227
3228 Examples:
3228 Examples:
3229
3229
3230 - list all files under the current directory::
3230 - list all files under the current directory::
3231
3231
3232 hg files .
3232 hg files .
3233
3233
3234 - shows sizes and flags for current revision::
3234 - shows sizes and flags for current revision::
3235
3235
3236 hg files -vr .
3236 hg files -vr .
3237
3237
3238 - list all files named README::
3238 - list all files named README::
3239
3239
3240 hg files -I "**/README"
3240 hg files -I "**/README"
3241
3241
3242 - list all binary files::
3242 - list all binary files::
3243
3243
3244 hg files "set:binary()"
3244 hg files "set:binary()"
3245
3245
3246 - find files containing a regular expression::
3246 - find files containing a regular expression::
3247
3247
3248 hg files "set:grep('bob')"
3248 hg files "set:grep('bob')"
3249
3249
3250 - search tracked file contents with xargs and grep::
3250 - search tracked file contents with xargs and grep::
3251
3251
3252 hg files -0 | xargs -0 grep foo
3252 hg files -0 | xargs -0 grep foo
3253
3253
3254 See :hg:`help patterns` and :hg:`help filesets` for more information
3254 See :hg:`help patterns` and :hg:`help filesets` for more information
3255 on specifying file patterns.
3255 on specifying file patterns.
3256
3256
3257 Returns 0 if a match is found, 1 otherwise.
3257 Returns 0 if a match is found, 1 otherwise.
3258
3258
3259 """
3259 """
3260 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3260 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3261 rev = ctx.rev()
3261 rev = ctx.rev()
3262 ret = 1
3262 ret = 1
3263
3263
3264 end = '\n'
3264 end = '\n'
3265 if opts.get('print0'):
3265 if opts.get('print0'):
3266 end = '\0'
3266 end = '\0'
3267 fm = ui.formatter('files', opts)
3267 fm = ui.formatter('files', opts)
3268 fmt = '%s' + end
3268 fmt = '%s' + end
3269
3269
3270 m = scmutil.match(ctx, pats, opts)
3270 m = scmutil.match(ctx, pats, opts)
3271 ds = repo.dirstate
3271 ds = repo.dirstate
3272 for f in ctx.matches(m):
3272 for f in ctx.matches(m):
3273 if rev is None and ds[f] == 'r':
3273 if rev is None and ds[f] == 'r':
3274 continue
3274 continue
3275 fm.startitem()
3275 fm.startitem()
3276 if ui.verbose:
3276 if ui.verbose:
3277 fc = ctx[f]
3277 fc = ctx[f]
3278 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3278 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3279 fm.data(abspath=f)
3279 fm.data(abspath=f)
3280 fm.write('path', fmt, m.rel(f))
3280 fm.write('path', fmt, m.rel(f))
3281 ret = 0
3281 ret = 0
3282
3282
3283 fm.end()
3283 fm.end()
3284
3284
3285 return ret
3285 return ret
3286
3286
3287 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3287 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3288 def forget(ui, repo, *pats, **opts):
3288 def forget(ui, repo, *pats, **opts):
3289 """forget the specified files on the next commit
3289 """forget the specified files on the next commit
3290
3290
3291 Mark the specified files so they will no longer be tracked
3291 Mark the specified files so they will no longer be tracked
3292 after the next commit.
3292 after the next commit.
3293
3293
3294 This only removes files from the current branch, not from the
3294 This only removes files from the current branch, not from the
3295 entire project history, and it does not delete them from the
3295 entire project history, and it does not delete them from the
3296 working directory.
3296 working directory.
3297
3297
3298 To undo a forget before the next commit, see :hg:`add`.
3298 To undo a forget before the next commit, see :hg:`add`.
3299
3299
3300 .. container:: verbose
3300 .. container:: verbose
3301
3301
3302 Examples:
3302 Examples:
3303
3303
3304 - forget newly-added binary files::
3304 - forget newly-added binary files::
3305
3305
3306 hg forget "set:added() and binary()"
3306 hg forget "set:added() and binary()"
3307
3307
3308 - forget files that would be excluded by .hgignore::
3308 - forget files that would be excluded by .hgignore::
3309
3309
3310 hg forget "set:hgignore()"
3310 hg forget "set:hgignore()"
3311
3311
3312 Returns 0 on success.
3312 Returns 0 on success.
3313 """
3313 """
3314
3314
3315 if not pats:
3315 if not pats:
3316 raise util.Abort(_('no files specified'))
3316 raise util.Abort(_('no files specified'))
3317
3317
3318 m = scmutil.match(repo[None], pats, opts)
3318 m = scmutil.match(repo[None], pats, opts)
3319 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3319 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3320 return rejected and 1 or 0
3320 return rejected and 1 or 0
3321
3321
3322 @command(
3322 @command(
3323 'graft',
3323 'graft',
3324 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3324 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3325 ('c', 'continue', False, _('resume interrupted graft')),
3325 ('c', 'continue', False, _('resume interrupted graft')),
3326 ('e', 'edit', False, _('invoke editor on commit messages')),
3326 ('e', 'edit', False, _('invoke editor on commit messages')),
3327 ('', 'log', None, _('append graft info to log message')),
3327 ('', 'log', None, _('append graft info to log message')),
3328 ('f', 'force', False, _('force graft')),
3328 ('f', 'force', False, _('force graft')),
3329 ('D', 'currentdate', False,
3329 ('D', 'currentdate', False,
3330 _('record the current date as commit date')),
3330 _('record the current date as commit date')),
3331 ('U', 'currentuser', False,
3331 ('U', 'currentuser', False,
3332 _('record the current user as committer'), _('DATE'))]
3332 _('record the current user as committer'), _('DATE'))]
3333 + commitopts2 + mergetoolopts + dryrunopts,
3333 + commitopts2 + mergetoolopts + dryrunopts,
3334 _('[OPTION]... [-r] REV...'))
3334 _('[OPTION]... [-r] REV...'))
3335 def graft(ui, repo, *revs, **opts):
3335 def graft(ui, repo, *revs, **opts):
3336 '''copy changes from other branches onto the current branch
3336 '''copy changes from other branches onto the current branch
3337
3337
3338 This command uses Mercurial's merge logic to copy individual
3338 This command uses Mercurial's merge logic to copy individual
3339 changes from other branches without merging branches in the
3339 changes from other branches without merging branches in the
3340 history graph. This is sometimes known as 'backporting' or
3340 history graph. This is sometimes known as 'backporting' or
3341 'cherry-picking'. By default, graft will copy user, date, and
3341 'cherry-picking'. By default, graft will copy user, date, and
3342 description from the source changesets.
3342 description from the source changesets.
3343
3343
3344 Changesets that are ancestors of the current revision, that have
3344 Changesets that are ancestors of the current revision, that have
3345 already been grafted, or that are merges will be skipped.
3345 already been grafted, or that are merges will be skipped.
3346
3346
3347 If --log is specified, log messages will have a comment appended
3347 If --log is specified, log messages will have a comment appended
3348 of the form::
3348 of the form::
3349
3349
3350 (grafted from CHANGESETHASH)
3350 (grafted from CHANGESETHASH)
3351
3351
3352 If --force is specified, revisions will be grafted even if they
3352 If --force is specified, revisions will be grafted even if they
3353 are already ancestors of or have been grafted to the destination.
3353 are already ancestors of or have been grafted to the destination.
3354 This is useful when the revisions have since been backed out.
3354 This is useful when the revisions have since been backed out.
3355
3355
3356 If a graft merge results in conflicts, the graft process is
3356 If a graft merge results in conflicts, the graft process is
3357 interrupted so that the current merge can be manually resolved.
3357 interrupted so that the current merge can be manually resolved.
3358 Once all conflicts are addressed, the graft process can be
3358 Once all conflicts are addressed, the graft process can be
3359 continued with the -c/--continue option.
3359 continued with the -c/--continue option.
3360
3360
3361 .. note::
3361 .. note::
3362
3362
3363 The -c/--continue option does not reapply earlier options, except
3363 The -c/--continue option does not reapply earlier options, except
3364 for --force.
3364 for --force.
3365
3365
3366 .. container:: verbose
3366 .. container:: verbose
3367
3367
3368 Examples:
3368 Examples:
3369
3369
3370 - copy a single change to the stable branch and edit its description::
3370 - copy a single change to the stable branch and edit its description::
3371
3371
3372 hg update stable
3372 hg update stable
3373 hg graft --edit 9393
3373 hg graft --edit 9393
3374
3374
3375 - graft a range of changesets with one exception, updating dates::
3375 - graft a range of changesets with one exception, updating dates::
3376
3376
3377 hg graft -D "2085::2093 and not 2091"
3377 hg graft -D "2085::2093 and not 2091"
3378
3378
3379 - continue a graft after resolving conflicts::
3379 - continue a graft after resolving conflicts::
3380
3380
3381 hg graft -c
3381 hg graft -c
3382
3382
3383 - show the source of a grafted changeset::
3383 - show the source of a grafted changeset::
3384
3384
3385 hg log --debug -r .
3385 hg log --debug -r .
3386
3386
3387 See :hg:`help revisions` and :hg:`help revsets` for more about
3387 See :hg:`help revisions` and :hg:`help revsets` for more about
3388 specifying revisions.
3388 specifying revisions.
3389
3389
3390 Returns 0 on successful completion.
3390 Returns 0 on successful completion.
3391 '''
3391 '''
3392
3392
3393 revs = list(revs)
3393 revs = list(revs)
3394 revs.extend(opts['rev'])
3394 revs.extend(opts['rev'])
3395
3395
3396 if not opts.get('user') and opts.get('currentuser'):
3396 if not opts.get('user') and opts.get('currentuser'):
3397 opts['user'] = ui.username()
3397 opts['user'] = ui.username()
3398 if not opts.get('date') and opts.get('currentdate'):
3398 if not opts.get('date') and opts.get('currentdate'):
3399 opts['date'] = "%d %d" % util.makedate()
3399 opts['date'] = "%d %d" % util.makedate()
3400
3400
3401 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3401 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3402
3402
3403 cont = False
3403 cont = False
3404 if opts['continue']:
3404 if opts['continue']:
3405 cont = True
3405 cont = True
3406 if revs:
3406 if revs:
3407 raise util.Abort(_("can't specify --continue and revisions"))
3407 raise util.Abort(_("can't specify --continue and revisions"))
3408 # read in unfinished revisions
3408 # read in unfinished revisions
3409 try:
3409 try:
3410 nodes = repo.vfs.read('graftstate').splitlines()
3410 nodes = repo.vfs.read('graftstate').splitlines()
3411 revs = [repo[node].rev() for node in nodes]
3411 revs = [repo[node].rev() for node in nodes]
3412 except IOError, inst:
3412 except IOError, inst:
3413 if inst.errno != errno.ENOENT:
3413 if inst.errno != errno.ENOENT:
3414 raise
3414 raise
3415 raise util.Abort(_("no graft state found, can't continue"))
3415 raise util.Abort(_("no graft state found, can't continue"))
3416 else:
3416 else:
3417 cmdutil.checkunfinished(repo)
3417 cmdutil.checkunfinished(repo)
3418 cmdutil.bailifchanged(repo)
3418 cmdutil.bailifchanged(repo)
3419 if not revs:
3419 if not revs:
3420 raise util.Abort(_('no revisions specified'))
3420 raise util.Abort(_('no revisions specified'))
3421 revs = scmutil.revrange(repo, revs)
3421 revs = scmutil.revrange(repo, revs)
3422
3422
3423 skipped = set()
3423 skipped = set()
3424 # check for merges
3424 # check for merges
3425 for rev in repo.revs('%ld and merge()', revs):
3425 for rev in repo.revs('%ld and merge()', revs):
3426 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3426 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3427 skipped.add(rev)
3427 skipped.add(rev)
3428 revs = [r for r in revs if r not in skipped]
3428 revs = [r for r in revs if r not in skipped]
3429 if not revs:
3429 if not revs:
3430 return -1
3430 return -1
3431
3431
3432 # Don't check in the --continue case, in effect retaining --force across
3432 # Don't check in the --continue case, in effect retaining --force across
3433 # --continues. That's because without --force, any revisions we decided to
3433 # --continues. That's because without --force, any revisions we decided to
3434 # skip would have been filtered out here, so they wouldn't have made their
3434 # skip would have been filtered out here, so they wouldn't have made their
3435 # way to the graftstate. With --force, any revisions we would have otherwise
3435 # way to the graftstate. With --force, any revisions we would have otherwise
3436 # skipped would not have been filtered out, and if they hadn't been applied
3436 # skipped would not have been filtered out, and if they hadn't been applied
3437 # already, they'd have been in the graftstate.
3437 # already, they'd have been in the graftstate.
3438 if not (cont or opts.get('force')):
3438 if not (cont or opts.get('force')):
3439 # check for ancestors of dest branch
3439 # check for ancestors of dest branch
3440 crev = repo['.'].rev()
3440 crev = repo['.'].rev()
3441 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3441 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3442 # Cannot use x.remove(y) on smart set, this has to be a list.
3442 # Cannot use x.remove(y) on smart set, this has to be a list.
3443 # XXX make this lazy in the future
3443 # XXX make this lazy in the future
3444 revs = list(revs)
3444 revs = list(revs)
3445 # don't mutate while iterating, create a copy
3445 # don't mutate while iterating, create a copy
3446 for rev in list(revs):
3446 for rev in list(revs):
3447 if rev in ancestors:
3447 if rev in ancestors:
3448 ui.warn(_('skipping ancestor revision %d:%s\n') %
3448 ui.warn(_('skipping ancestor revision %d:%s\n') %
3449 (rev, repo[rev]))
3449 (rev, repo[rev]))
3450 # XXX remove on list is slow
3450 # XXX remove on list is slow
3451 revs.remove(rev)
3451 revs.remove(rev)
3452 if not revs:
3452 if not revs:
3453 return -1
3453 return -1
3454
3454
3455 # analyze revs for earlier grafts
3455 # analyze revs for earlier grafts
3456 ids = {}
3456 ids = {}
3457 for ctx in repo.set("%ld", revs):
3457 for ctx in repo.set("%ld", revs):
3458 ids[ctx.hex()] = ctx.rev()
3458 ids[ctx.hex()] = ctx.rev()
3459 n = ctx.extra().get('source')
3459 n = ctx.extra().get('source')
3460 if n:
3460 if n:
3461 ids[n] = ctx.rev()
3461 ids[n] = ctx.rev()
3462
3462
3463 # check ancestors for earlier grafts
3463 # check ancestors for earlier grafts
3464 ui.debug('scanning for duplicate grafts\n')
3464 ui.debug('scanning for duplicate grafts\n')
3465
3465
3466 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3466 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3467 ctx = repo[rev]
3467 ctx = repo[rev]
3468 n = ctx.extra().get('source')
3468 n = ctx.extra().get('source')
3469 if n in ids:
3469 if n in ids:
3470 try:
3470 try:
3471 r = repo[n].rev()
3471 r = repo[n].rev()
3472 except error.RepoLookupError:
3472 except error.RepoLookupError:
3473 r = None
3473 r = None
3474 if r in revs:
3474 if r in revs:
3475 ui.warn(_('skipping revision %d:%s '
3475 ui.warn(_('skipping revision %d:%s '
3476 '(already grafted to %d:%s)\n')
3476 '(already grafted to %d:%s)\n')
3477 % (r, repo[r], rev, ctx))
3477 % (r, repo[r], rev, ctx))
3478 revs.remove(r)
3478 revs.remove(r)
3479 elif ids[n] in revs:
3479 elif ids[n] in revs:
3480 if r is None:
3480 if r is None:
3481 ui.warn(_('skipping already grafted revision %d:%s '
3481 ui.warn(_('skipping already grafted revision %d:%s '
3482 '(%d:%s also has unknown origin %s)\n')
3482 '(%d:%s also has unknown origin %s)\n')
3483 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3483 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3484 else:
3484 else:
3485 ui.warn(_('skipping already grafted revision %d:%s '
3485 ui.warn(_('skipping already grafted revision %d:%s '
3486 '(%d:%s also has origin %d:%s)\n')
3486 '(%d:%s also has origin %d:%s)\n')
3487 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3487 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3488 revs.remove(ids[n])
3488 revs.remove(ids[n])
3489 elif ctx.hex() in ids:
3489 elif ctx.hex() in ids:
3490 r = ids[ctx.hex()]
3490 r = ids[ctx.hex()]
3491 ui.warn(_('skipping already grafted revision %d:%s '
3491 ui.warn(_('skipping already grafted revision %d:%s '
3492 '(was grafted from %d:%s)\n') %
3492 '(was grafted from %d:%s)\n') %
3493 (r, repo[r], rev, ctx))
3493 (r, repo[r], rev, ctx))
3494 revs.remove(r)
3494 revs.remove(r)
3495 if not revs:
3495 if not revs:
3496 return -1
3496 return -1
3497
3497
3498 wlock = repo.wlock()
3498 wlock = repo.wlock()
3499 try:
3499 try:
3500 for pos, ctx in enumerate(repo.set("%ld", revs)):
3500 for pos, ctx in enumerate(repo.set("%ld", revs)):
3501 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3501 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3502 ctx.description().split('\n', 1)[0])
3502 ctx.description().split('\n', 1)[0])
3503 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3503 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3504 if names:
3504 if names:
3505 desc += ' (%s)' % ' '.join(names)
3505 desc += ' (%s)' % ' '.join(names)
3506 ui.status(_('grafting %s\n') % desc)
3506 ui.status(_('grafting %s\n') % desc)
3507 if opts.get('dry_run'):
3507 if opts.get('dry_run'):
3508 continue
3508 continue
3509
3509
3510 source = ctx.extra().get('source')
3510 source = ctx.extra().get('source')
3511 if not source:
3511 if not source:
3512 source = ctx.hex()
3512 source = ctx.hex()
3513 extra = {'source': source}
3513 extra = {'source': source}
3514 user = ctx.user()
3514 user = ctx.user()
3515 if opts.get('user'):
3515 if opts.get('user'):
3516 user = opts['user']
3516 user = opts['user']
3517 date = ctx.date()
3517 date = ctx.date()
3518 if opts.get('date'):
3518 if opts.get('date'):
3519 date = opts['date']
3519 date = opts['date']
3520 message = ctx.description()
3520 message = ctx.description()
3521 if opts.get('log'):
3521 if opts.get('log'):
3522 message += '\n(grafted from %s)' % ctx.hex()
3522 message += '\n(grafted from %s)' % ctx.hex()
3523
3523
3524 # we don't merge the first commit when continuing
3524 # we don't merge the first commit when continuing
3525 if not cont:
3525 if not cont:
3526 # perform the graft merge with p1(rev) as 'ancestor'
3526 # perform the graft merge with p1(rev) as 'ancestor'
3527 try:
3527 try:
3528 # ui.forcemerge is an internal variable, do not document
3528 # ui.forcemerge is an internal variable, do not document
3529 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3529 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3530 'graft')
3530 'graft')
3531 stats = mergemod.graft(repo, ctx, ctx.p1(),
3531 stats = mergemod.graft(repo, ctx, ctx.p1(),
3532 ['local', 'graft'])
3532 ['local', 'graft'])
3533 finally:
3533 finally:
3534 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3534 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3535 # report any conflicts
3535 # report any conflicts
3536 if stats and stats[3] > 0:
3536 if stats and stats[3] > 0:
3537 # write out state for --continue
3537 # write out state for --continue
3538 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3538 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3539 repo.vfs.write('graftstate', ''.join(nodelines))
3539 repo.vfs.write('graftstate', ''.join(nodelines))
3540 raise util.Abort(
3540 raise util.Abort(
3541 _("unresolved conflicts, can't continue"),
3541 _("unresolved conflicts, can't continue"),
3542 hint=_('use hg resolve and hg graft --continue'))
3542 hint=_('use hg resolve and hg graft --continue'))
3543 else:
3543 else:
3544 cont = False
3544 cont = False
3545
3545
3546 # commit
3546 # commit
3547 node = repo.commit(text=message, user=user,
3547 node = repo.commit(text=message, user=user,
3548 date=date, extra=extra, editor=editor)
3548 date=date, extra=extra, editor=editor)
3549 if node is None:
3549 if node is None:
3550 ui.warn(
3550 ui.warn(
3551 _('note: graft of %d:%s created no changes to commit\n') %
3551 _('note: graft of %d:%s created no changes to commit\n') %
3552 (ctx.rev(), ctx))
3552 (ctx.rev(), ctx))
3553 finally:
3553 finally:
3554 wlock.release()
3554 wlock.release()
3555
3555
3556 # remove state when we complete successfully
3556 # remove state when we complete successfully
3557 if not opts.get('dry_run'):
3557 if not opts.get('dry_run'):
3558 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3558 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3559
3559
3560 return 0
3560 return 0
3561
3561
3562 @command('grep',
3562 @command('grep',
3563 [('0', 'print0', None, _('end fields with NUL')),
3563 [('0', 'print0', None, _('end fields with NUL')),
3564 ('', 'all', None, _('print all revisions that match')),
3564 ('', 'all', None, _('print all revisions that match')),
3565 ('a', 'text', None, _('treat all files as text')),
3565 ('a', 'text', None, _('treat all files as text')),
3566 ('f', 'follow', None,
3566 ('f', 'follow', None,
3567 _('follow changeset history,'
3567 _('follow changeset history,'
3568 ' or file history across copies and renames')),
3568 ' or file history across copies and renames')),
3569 ('i', 'ignore-case', None, _('ignore case when matching')),
3569 ('i', 'ignore-case', None, _('ignore case when matching')),
3570 ('l', 'files-with-matches', None,
3570 ('l', 'files-with-matches', None,
3571 _('print only filenames and revisions that match')),
3571 _('print only filenames and revisions that match')),
3572 ('n', 'line-number', None, _('print matching line numbers')),
3572 ('n', 'line-number', None, _('print matching line numbers')),
3573 ('r', 'rev', [],
3573 ('r', 'rev', [],
3574 _('only search files changed within revision range'), _('REV')),
3574 _('only search files changed within revision range'), _('REV')),
3575 ('u', 'user', None, _('list the author (long with -v)')),
3575 ('u', 'user', None, _('list the author (long with -v)')),
3576 ('d', 'date', None, _('list the date (short with -q)')),
3576 ('d', 'date', None, _('list the date (short with -q)')),
3577 ] + walkopts,
3577 ] + walkopts,
3578 _('[OPTION]... PATTERN [FILE]...'),
3578 _('[OPTION]... PATTERN [FILE]...'),
3579 inferrepo=True)
3579 inferrepo=True)
3580 def grep(ui, repo, pattern, *pats, **opts):
3580 def grep(ui, repo, pattern, *pats, **opts):
3581 """search for a pattern in specified files and revisions
3581 """search for a pattern in specified files and revisions
3582
3582
3583 Search revisions of files for a regular expression.
3583 Search revisions of files for a regular expression.
3584
3584
3585 This command behaves differently than Unix grep. It only accepts
3585 This command behaves differently than Unix grep. It only accepts
3586 Python/Perl regexps. It searches repository history, not the
3586 Python/Perl regexps. It searches repository history, not the
3587 working directory. It always prints the revision number in which a
3587 working directory. It always prints the revision number in which a
3588 match appears.
3588 match appears.
3589
3589
3590 By default, grep only prints output for the first revision of a
3590 By default, grep only prints output for the first revision of a
3591 file in which it finds a match. To get it to print every revision
3591 file in which it finds a match. To get it to print every revision
3592 that contains a change in match status ("-" for a match that
3592 that contains a change in match status ("-" for a match that
3593 becomes a non-match, or "+" for a non-match that becomes a match),
3593 becomes a non-match, or "+" for a non-match that becomes a match),
3594 use the --all flag.
3594 use the --all flag.
3595
3595
3596 Returns 0 if a match is found, 1 otherwise.
3596 Returns 0 if a match is found, 1 otherwise.
3597 """
3597 """
3598 reflags = re.M
3598 reflags = re.M
3599 if opts.get('ignore_case'):
3599 if opts.get('ignore_case'):
3600 reflags |= re.I
3600 reflags |= re.I
3601 try:
3601 try:
3602 regexp = util.re.compile(pattern, reflags)
3602 regexp = util.re.compile(pattern, reflags)
3603 except re.error, inst:
3603 except re.error, inst:
3604 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3604 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3605 return 1
3605 return 1
3606 sep, eol = ':', '\n'
3606 sep, eol = ':', '\n'
3607 if opts.get('print0'):
3607 if opts.get('print0'):
3608 sep = eol = '\0'
3608 sep = eol = '\0'
3609
3609
3610 getfile = util.lrucachefunc(repo.file)
3610 getfile = util.lrucachefunc(repo.file)
3611
3611
3612 def matchlines(body):
3612 def matchlines(body):
3613 begin = 0
3613 begin = 0
3614 linenum = 0
3614 linenum = 0
3615 while begin < len(body):
3615 while begin < len(body):
3616 match = regexp.search(body, begin)
3616 match = regexp.search(body, begin)
3617 if not match:
3617 if not match:
3618 break
3618 break
3619 mstart, mend = match.span()
3619 mstart, mend = match.span()
3620 linenum += body.count('\n', begin, mstart) + 1
3620 linenum += body.count('\n', begin, mstart) + 1
3621 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3621 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3622 begin = body.find('\n', mend) + 1 or len(body) + 1
3622 begin = body.find('\n', mend) + 1 or len(body) + 1
3623 lend = begin - 1
3623 lend = begin - 1
3624 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3624 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3625
3625
3626 class linestate(object):
3626 class linestate(object):
3627 def __init__(self, line, linenum, colstart, colend):
3627 def __init__(self, line, linenum, colstart, colend):
3628 self.line = line
3628 self.line = line
3629 self.linenum = linenum
3629 self.linenum = linenum
3630 self.colstart = colstart
3630 self.colstart = colstart
3631 self.colend = colend
3631 self.colend = colend
3632
3632
3633 def __hash__(self):
3633 def __hash__(self):
3634 return hash((self.linenum, self.line))
3634 return hash((self.linenum, self.line))
3635
3635
3636 def __eq__(self, other):
3636 def __eq__(self, other):
3637 return self.line == other.line
3637 return self.line == other.line
3638
3638
3639 def __iter__(self):
3639 def __iter__(self):
3640 yield (self.line[:self.colstart], '')
3640 yield (self.line[:self.colstart], '')
3641 yield (self.line[self.colstart:self.colend], 'grep.match')
3641 yield (self.line[self.colstart:self.colend], 'grep.match')
3642 rest = self.line[self.colend:]
3642 rest = self.line[self.colend:]
3643 while rest != '':
3643 while rest != '':
3644 match = regexp.search(rest)
3644 match = regexp.search(rest)
3645 if not match:
3645 if not match:
3646 yield (rest, '')
3646 yield (rest, '')
3647 break
3647 break
3648 mstart, mend = match.span()
3648 mstart, mend = match.span()
3649 yield (rest[:mstart], '')
3649 yield (rest[:mstart], '')
3650 yield (rest[mstart:mend], 'grep.match')
3650 yield (rest[mstart:mend], 'grep.match')
3651 rest = rest[mend:]
3651 rest = rest[mend:]
3652
3652
3653 matches = {}
3653 matches = {}
3654 copies = {}
3654 copies = {}
3655 def grepbody(fn, rev, body):
3655 def grepbody(fn, rev, body):
3656 matches[rev].setdefault(fn, [])
3656 matches[rev].setdefault(fn, [])
3657 m = matches[rev][fn]
3657 m = matches[rev][fn]
3658 for lnum, cstart, cend, line in matchlines(body):
3658 for lnum, cstart, cend, line in matchlines(body):
3659 s = linestate(line, lnum, cstart, cend)
3659 s = linestate(line, lnum, cstart, cend)
3660 m.append(s)
3660 m.append(s)
3661
3661
3662 def difflinestates(a, b):
3662 def difflinestates(a, b):
3663 sm = difflib.SequenceMatcher(None, a, b)
3663 sm = difflib.SequenceMatcher(None, a, b)
3664 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3664 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3665 if tag == 'insert':
3665 if tag == 'insert':
3666 for i in xrange(blo, bhi):
3666 for i in xrange(blo, bhi):
3667 yield ('+', b[i])
3667 yield ('+', b[i])
3668 elif tag == 'delete':
3668 elif tag == 'delete':
3669 for i in xrange(alo, ahi):
3669 for i in xrange(alo, ahi):
3670 yield ('-', a[i])
3670 yield ('-', a[i])
3671 elif tag == 'replace':
3671 elif tag == 'replace':
3672 for i in xrange(alo, ahi):
3672 for i in xrange(alo, ahi):
3673 yield ('-', a[i])
3673 yield ('-', a[i])
3674 for i in xrange(blo, bhi):
3674 for i in xrange(blo, bhi):
3675 yield ('+', b[i])
3675 yield ('+', b[i])
3676
3676
3677 def display(fn, ctx, pstates, states):
3677 def display(fn, ctx, pstates, states):
3678 rev = ctx.rev()
3678 rev = ctx.rev()
3679 datefunc = ui.quiet and util.shortdate or util.datestr
3679 datefunc = ui.quiet and util.shortdate or util.datestr
3680 found = False
3680 found = False
3681 @util.cachefunc
3681 @util.cachefunc
3682 def binary():
3682 def binary():
3683 flog = getfile(fn)
3683 flog = getfile(fn)
3684 return util.binary(flog.read(ctx.filenode(fn)))
3684 return util.binary(flog.read(ctx.filenode(fn)))
3685
3685
3686 if opts.get('all'):
3686 if opts.get('all'):
3687 iter = difflinestates(pstates, states)
3687 iter = difflinestates(pstates, states)
3688 else:
3688 else:
3689 iter = [('', l) for l in states]
3689 iter = [('', l) for l in states]
3690 for change, l in iter:
3690 for change, l in iter:
3691 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3691 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3692
3692
3693 if opts.get('line_number'):
3693 if opts.get('line_number'):
3694 cols.append((str(l.linenum), 'grep.linenumber'))
3694 cols.append((str(l.linenum), 'grep.linenumber'))
3695 if opts.get('all'):
3695 if opts.get('all'):
3696 cols.append((change, 'grep.change'))
3696 cols.append((change, 'grep.change'))
3697 if opts.get('user'):
3697 if opts.get('user'):
3698 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3698 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3699 if opts.get('date'):
3699 if opts.get('date'):
3700 cols.append((datefunc(ctx.date()), 'grep.date'))
3700 cols.append((datefunc(ctx.date()), 'grep.date'))
3701 for col, label in cols[:-1]:
3701 for col, label in cols[:-1]:
3702 ui.write(col, label=label)
3702 ui.write(col, label=label)
3703 ui.write(sep, label='grep.sep')
3703 ui.write(sep, label='grep.sep')
3704 ui.write(cols[-1][0], label=cols[-1][1])
3704 ui.write(cols[-1][0], label=cols[-1][1])
3705 if not opts.get('files_with_matches'):
3705 if not opts.get('files_with_matches'):
3706 ui.write(sep, label='grep.sep')
3706 ui.write(sep, label='grep.sep')
3707 if not opts.get('text') and binary():
3707 if not opts.get('text') and binary():
3708 ui.write(" Binary file matches")
3708 ui.write(" Binary file matches")
3709 else:
3709 else:
3710 for s, label in l:
3710 for s, label in l:
3711 ui.write(s, label=label)
3711 ui.write(s, label=label)
3712 ui.write(eol)
3712 ui.write(eol)
3713 found = True
3713 found = True
3714 if opts.get('files_with_matches'):
3714 if opts.get('files_with_matches'):
3715 break
3715 break
3716 return found
3716 return found
3717
3717
3718 skip = {}
3718 skip = {}
3719 revfiles = {}
3719 revfiles = {}
3720 matchfn = scmutil.match(repo[None], pats, opts)
3720 matchfn = scmutil.match(repo[None], pats, opts)
3721 found = False
3721 found = False
3722 follow = opts.get('follow')
3722 follow = opts.get('follow')
3723
3723
3724 def prep(ctx, fns):
3724 def prep(ctx, fns):
3725 rev = ctx.rev()
3725 rev = ctx.rev()
3726 pctx = ctx.p1()
3726 pctx = ctx.p1()
3727 parent = pctx.rev()
3727 parent = pctx.rev()
3728 matches.setdefault(rev, {})
3728 matches.setdefault(rev, {})
3729 matches.setdefault(parent, {})
3729 matches.setdefault(parent, {})
3730 files = revfiles.setdefault(rev, [])
3730 files = revfiles.setdefault(rev, [])
3731 for fn in fns:
3731 for fn in fns:
3732 flog = getfile(fn)
3732 flog = getfile(fn)
3733 try:
3733 try:
3734 fnode = ctx.filenode(fn)
3734 fnode = ctx.filenode(fn)
3735 except error.LookupError:
3735 except error.LookupError:
3736 continue
3736 continue
3737
3737
3738 copied = flog.renamed(fnode)
3738 copied = flog.renamed(fnode)
3739 copy = follow and copied and copied[0]
3739 copy = follow and copied and copied[0]
3740 if copy:
3740 if copy:
3741 copies.setdefault(rev, {})[fn] = copy
3741 copies.setdefault(rev, {})[fn] = copy
3742 if fn in skip:
3742 if fn in skip:
3743 if copy:
3743 if copy:
3744 skip[copy] = True
3744 skip[copy] = True
3745 continue
3745 continue
3746 files.append(fn)
3746 files.append(fn)
3747
3747
3748 if fn not in matches[rev]:
3748 if fn not in matches[rev]:
3749 grepbody(fn, rev, flog.read(fnode))
3749 grepbody(fn, rev, flog.read(fnode))
3750
3750
3751 pfn = copy or fn
3751 pfn = copy or fn
3752 if pfn not in matches[parent]:
3752 if pfn not in matches[parent]:
3753 try:
3753 try:
3754 fnode = pctx.filenode(pfn)
3754 fnode = pctx.filenode(pfn)
3755 grepbody(pfn, parent, flog.read(fnode))
3755 grepbody(pfn, parent, flog.read(fnode))
3756 except error.LookupError:
3756 except error.LookupError:
3757 pass
3757 pass
3758
3758
3759 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3759 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3760 rev = ctx.rev()
3760 rev = ctx.rev()
3761 parent = ctx.p1().rev()
3761 parent = ctx.p1().rev()
3762 for fn in sorted(revfiles.get(rev, [])):
3762 for fn in sorted(revfiles.get(rev, [])):
3763 states = matches[rev][fn]
3763 states = matches[rev][fn]
3764 copy = copies.get(rev, {}).get(fn)
3764 copy = copies.get(rev, {}).get(fn)
3765 if fn in skip:
3765 if fn in skip:
3766 if copy:
3766 if copy:
3767 skip[copy] = True
3767 skip[copy] = True
3768 continue
3768 continue
3769 pstates = matches.get(parent, {}).get(copy or fn, [])
3769 pstates = matches.get(parent, {}).get(copy or fn, [])
3770 if pstates or states:
3770 if pstates or states:
3771 r = display(fn, ctx, pstates, states)
3771 r = display(fn, ctx, pstates, states)
3772 found = found or r
3772 found = found or r
3773 if r and not opts.get('all'):
3773 if r and not opts.get('all'):
3774 skip[fn] = True
3774 skip[fn] = True
3775 if copy:
3775 if copy:
3776 skip[copy] = True
3776 skip[copy] = True
3777 del matches[rev]
3777 del matches[rev]
3778 del revfiles[rev]
3778 del revfiles[rev]
3779
3779
3780 return not found
3780 return not found
3781
3781
3782 @command('heads',
3782 @command('heads',
3783 [('r', 'rev', '',
3783 [('r', 'rev', '',
3784 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3784 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3785 ('t', 'topo', False, _('show topological heads only')),
3785 ('t', 'topo', False, _('show topological heads only')),
3786 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3786 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3787 ('c', 'closed', False, _('show normal and closed branch heads')),
3787 ('c', 'closed', False, _('show normal and closed branch heads')),
3788 ] + templateopts,
3788 ] + templateopts,
3789 _('[-ct] [-r STARTREV] [REV]...'))
3789 _('[-ct] [-r STARTREV] [REV]...'))
3790 def heads(ui, repo, *branchrevs, **opts):
3790 def heads(ui, repo, *branchrevs, **opts):
3791 """show branch heads
3791 """show branch heads
3792
3792
3793 With no arguments, show all open branch heads in the repository.
3793 With no arguments, show all open branch heads in the repository.
3794 Branch heads are changesets that have no descendants on the
3794 Branch heads are changesets that have no descendants on the
3795 same branch. They are where development generally takes place and
3795 same branch. They are where development generally takes place and
3796 are the usual targets for update and merge operations.
3796 are the usual targets for update and merge operations.
3797
3797
3798 If one or more REVs are given, only open branch heads on the
3798 If one or more REVs are given, only open branch heads on the
3799 branches associated with the specified changesets are shown. This
3799 branches associated with the specified changesets are shown. This
3800 means that you can use :hg:`heads .` to see the heads on the
3800 means that you can use :hg:`heads .` to see the heads on the
3801 currently checked-out branch.
3801 currently checked-out branch.
3802
3802
3803 If -c/--closed is specified, also show branch heads marked closed
3803 If -c/--closed is specified, also show branch heads marked closed
3804 (see :hg:`commit --close-branch`).
3804 (see :hg:`commit --close-branch`).
3805
3805
3806 If STARTREV is specified, only those heads that are descendants of
3806 If STARTREV is specified, only those heads that are descendants of
3807 STARTREV will be displayed.
3807 STARTREV will be displayed.
3808
3808
3809 If -t/--topo is specified, named branch mechanics will be ignored and only
3809 If -t/--topo is specified, named branch mechanics will be ignored and only
3810 topological heads (changesets with no children) will be shown.
3810 topological heads (changesets with no children) will be shown.
3811
3811
3812 Returns 0 if matching heads are found, 1 if not.
3812 Returns 0 if matching heads are found, 1 if not.
3813 """
3813 """
3814
3814
3815 start = None
3815 start = None
3816 if 'rev' in opts:
3816 if 'rev' in opts:
3817 start = scmutil.revsingle(repo, opts['rev'], None).node()
3817 start = scmutil.revsingle(repo, opts['rev'], None).node()
3818
3818
3819 if opts.get('topo'):
3819 if opts.get('topo'):
3820 heads = [repo[h] for h in repo.heads(start)]
3820 heads = [repo[h] for h in repo.heads(start)]
3821 else:
3821 else:
3822 heads = []
3822 heads = []
3823 for branch in repo.branchmap():
3823 for branch in repo.branchmap():
3824 heads += repo.branchheads(branch, start, opts.get('closed'))
3824 heads += repo.branchheads(branch, start, opts.get('closed'))
3825 heads = [repo[h] for h in heads]
3825 heads = [repo[h] for h in heads]
3826
3826
3827 if branchrevs:
3827 if branchrevs:
3828 branches = set(repo[br].branch() for br in branchrevs)
3828 branches = set(repo[br].branch() for br in branchrevs)
3829 heads = [h for h in heads if h.branch() in branches]
3829 heads = [h for h in heads if h.branch() in branches]
3830
3830
3831 if opts.get('active') and branchrevs:
3831 if opts.get('active') and branchrevs:
3832 dagheads = repo.heads(start)
3832 dagheads = repo.heads(start)
3833 heads = [h for h in heads if h.node() in dagheads]
3833 heads = [h for h in heads if h.node() in dagheads]
3834
3834
3835 if branchrevs:
3835 if branchrevs:
3836 haveheads = set(h.branch() for h in heads)
3836 haveheads = set(h.branch() for h in heads)
3837 if branches - haveheads:
3837 if branches - haveheads:
3838 headless = ', '.join(b for b in branches - haveheads)
3838 headless = ', '.join(b for b in branches - haveheads)
3839 msg = _('no open branch heads found on branches %s')
3839 msg = _('no open branch heads found on branches %s')
3840 if opts.get('rev'):
3840 if opts.get('rev'):
3841 msg += _(' (started at %s)') % opts['rev']
3841 msg += _(' (started at %s)') % opts['rev']
3842 ui.warn((msg + '\n') % headless)
3842 ui.warn((msg + '\n') % headless)
3843
3843
3844 if not heads:
3844 if not heads:
3845 return 1
3845 return 1
3846
3846
3847 heads = sorted(heads, key=lambda x: -x.rev())
3847 heads = sorted(heads, key=lambda x: -x.rev())
3848 displayer = cmdutil.show_changeset(ui, repo, opts)
3848 displayer = cmdutil.show_changeset(ui, repo, opts)
3849 for ctx in heads:
3849 for ctx in heads:
3850 displayer.show(ctx)
3850 displayer.show(ctx)
3851 displayer.close()
3851 displayer.close()
3852
3852
3853 @command('help',
3853 @command('help',
3854 [('e', 'extension', None, _('show only help for extensions')),
3854 [('e', 'extension', None, _('show only help for extensions')),
3855 ('c', 'command', None, _('show only help for commands')),
3855 ('c', 'command', None, _('show only help for commands')),
3856 ('k', 'keyword', '', _('show topics matching keyword')),
3856 ('k', 'keyword', '', _('show topics matching keyword')),
3857 ],
3857 ],
3858 _('[-ec] [TOPIC]'),
3858 _('[-ec] [TOPIC]'),
3859 norepo=True)
3859 norepo=True)
3860 def help_(ui, name=None, **opts):
3860 def help_(ui, name=None, **opts):
3861 """show help for a given topic or a help overview
3861 """show help for a given topic or a help overview
3862
3862
3863 With no arguments, print a list of commands with short help messages.
3863 With no arguments, print a list of commands with short help messages.
3864
3864
3865 Given a topic, extension, or command name, print help for that
3865 Given a topic, extension, or command name, print help for that
3866 topic.
3866 topic.
3867
3867
3868 Returns 0 if successful.
3868 Returns 0 if successful.
3869 """
3869 """
3870
3870
3871 textwidth = min(ui.termwidth(), 80) - 2
3871 textwidth = min(ui.termwidth(), 80) - 2
3872
3872
3873 keep = []
3873 keep = []
3874 if ui.verbose:
3874 if ui.verbose:
3875 keep.append('verbose')
3875 keep.append('verbose')
3876 if sys.platform.startswith('win'):
3876 if sys.platform.startswith('win'):
3877 keep.append('windows')
3877 keep.append('windows')
3878 elif sys.platform == 'OpenVMS':
3878 elif sys.platform == 'OpenVMS':
3879 keep.append('vms')
3879 keep.append('vms')
3880 elif sys.platform == 'plan9':
3880 elif sys.platform == 'plan9':
3881 keep.append('plan9')
3881 keep.append('plan9')
3882 else:
3882 else:
3883 keep.append('unix')
3883 keep.append('unix')
3884 keep.append(sys.platform.lower())
3884 keep.append(sys.platform.lower())
3885
3885
3886 section = None
3886 section = None
3887 if name and '.' in name:
3887 if name and '.' in name:
3888 name, section = name.split('.', 1)
3888 name, section = name.split('.', 1)
3889
3889
3890 text = help.help_(ui, name, **opts)
3890 text = help.help_(ui, name, **opts)
3891
3891
3892 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3892 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3893 section=section)
3893 section=section)
3894 if section and not formatted:
3894 if section and not formatted:
3895 raise util.Abort(_("help section not found"))
3895 raise util.Abort(_("help section not found"))
3896
3896
3897 if 'verbose' in pruned:
3897 if 'verbose' in pruned:
3898 keep.append('omitted')
3898 keep.append('omitted')
3899 else:
3899 else:
3900 keep.append('notomitted')
3900 keep.append('notomitted')
3901 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3901 formatted, pruned = minirst.format(text, textwidth, keep=keep,
3902 section=section)
3902 section=section)
3903 ui.write(formatted)
3903 ui.write(formatted)
3904
3904
3905
3905
3906 @command('identify|id',
3906 @command('identify|id',
3907 [('r', 'rev', '',
3907 [('r', 'rev', '',
3908 _('identify the specified revision'), _('REV')),
3908 _('identify the specified revision'), _('REV')),
3909 ('n', 'num', None, _('show local revision number')),
3909 ('n', 'num', None, _('show local revision number')),
3910 ('i', 'id', None, _('show global revision id')),
3910 ('i', 'id', None, _('show global revision id')),
3911 ('b', 'branch', None, _('show branch')),
3911 ('b', 'branch', None, _('show branch')),
3912 ('t', 'tags', None, _('show tags')),
3912 ('t', 'tags', None, _('show tags')),
3913 ('B', 'bookmarks', None, _('show bookmarks')),
3913 ('B', 'bookmarks', None, _('show bookmarks')),
3914 ] + remoteopts,
3914 ] + remoteopts,
3915 _('[-nibtB] [-r REV] [SOURCE]'),
3915 _('[-nibtB] [-r REV] [SOURCE]'),
3916 optionalrepo=True)
3916 optionalrepo=True)
3917 def identify(ui, repo, source=None, rev=None,
3917 def identify(ui, repo, source=None, rev=None,
3918 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3918 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3919 """identify the working copy or specified revision
3919 """identify the working copy or specified revision
3920
3920
3921 Print a summary identifying the repository state at REV using one or
3921 Print a summary identifying the repository state at REV using one or
3922 two parent hash identifiers, followed by a "+" if the working
3922 two parent hash identifiers, followed by a "+" if the working
3923 directory has uncommitted changes, the branch name (if not default),
3923 directory has uncommitted changes, the branch name (if not default),
3924 a list of tags, and a list of bookmarks.
3924 a list of tags, and a list of bookmarks.
3925
3925
3926 When REV is not given, print a summary of the current state of the
3926 When REV is not given, print a summary of the current state of the
3927 repository.
3927 repository.
3928
3928
3929 Specifying a path to a repository root or Mercurial bundle will
3929 Specifying a path to a repository root or Mercurial bundle will
3930 cause lookup to operate on that repository/bundle.
3930 cause lookup to operate on that repository/bundle.
3931
3931
3932 .. container:: verbose
3932 .. container:: verbose
3933
3933
3934 Examples:
3934 Examples:
3935
3935
3936 - generate a build identifier for the working directory::
3936 - generate a build identifier for the working directory::
3937
3937
3938 hg id --id > build-id.dat
3938 hg id --id > build-id.dat
3939
3939
3940 - find the revision corresponding to a tag::
3940 - find the revision corresponding to a tag::
3941
3941
3942 hg id -n -r 1.3
3942 hg id -n -r 1.3
3943
3943
3944 - check the most recent revision of a remote repository::
3944 - check the most recent revision of a remote repository::
3945
3945
3946 hg id -r tip http://selenic.com/hg/
3946 hg id -r tip http://selenic.com/hg/
3947
3947
3948 Returns 0 if successful.
3948 Returns 0 if successful.
3949 """
3949 """
3950
3950
3951 if not repo and not source:
3951 if not repo and not source:
3952 raise util.Abort(_("there is no Mercurial repository here "
3952 raise util.Abort(_("there is no Mercurial repository here "
3953 "(.hg not found)"))
3953 "(.hg not found)"))
3954
3954
3955 hexfunc = ui.debugflag and hex or short
3955 hexfunc = ui.debugflag and hex or short
3956 default = not (num or id or branch or tags or bookmarks)
3956 default = not (num or id or branch or tags or bookmarks)
3957 output = []
3957 output = []
3958 revs = []
3958 revs = []
3959
3959
3960 if source:
3960 if source:
3961 source, branches = hg.parseurl(ui.expandpath(source))
3961 source, branches = hg.parseurl(ui.expandpath(source))
3962 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3962 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3963 repo = peer.local()
3963 repo = peer.local()
3964 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3964 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3965
3965
3966 if not repo:
3966 if not repo:
3967 if num or branch or tags:
3967 if num or branch or tags:
3968 raise util.Abort(
3968 raise util.Abort(
3969 _("can't query remote revision number, branch, or tags"))
3969 _("can't query remote revision number, branch, or tags"))
3970 if not rev and revs:
3970 if not rev and revs:
3971 rev = revs[0]
3971 rev = revs[0]
3972 if not rev:
3972 if not rev:
3973 rev = "tip"
3973 rev = "tip"
3974
3974
3975 remoterev = peer.lookup(rev)
3975 remoterev = peer.lookup(rev)
3976 if default or id:
3976 if default or id:
3977 output = [hexfunc(remoterev)]
3977 output = [hexfunc(remoterev)]
3978
3978
3979 def getbms():
3979 def getbms():
3980 bms = []
3980 bms = []
3981
3981
3982 if 'bookmarks' in peer.listkeys('namespaces'):
3982 if 'bookmarks' in peer.listkeys('namespaces'):
3983 hexremoterev = hex(remoterev)
3983 hexremoterev = hex(remoterev)
3984 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3984 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3985 if bmr == hexremoterev]
3985 if bmr == hexremoterev]
3986
3986
3987 return sorted(bms)
3987 return sorted(bms)
3988
3988
3989 if bookmarks:
3989 if bookmarks:
3990 output.extend(getbms())
3990 output.extend(getbms())
3991 elif default and not ui.quiet:
3991 elif default and not ui.quiet:
3992 # multiple bookmarks for a single parent separated by '/'
3992 # multiple bookmarks for a single parent separated by '/'
3993 bm = '/'.join(getbms())
3993 bm = '/'.join(getbms())
3994 if bm:
3994 if bm:
3995 output.append(bm)
3995 output.append(bm)
3996 else:
3996 else:
3997 if not rev:
3997 if not rev:
3998 ctx = repo[None]
3998 ctx = repo[None]
3999 parents = ctx.parents()
3999 parents = ctx.parents()
4000 changed = ""
4000 changed = ""
4001 if default or id or num:
4001 if default or id or num:
4002 if (util.any(repo.status())
4002 if (util.any(repo.status())
4003 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4003 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
4004 changed = '+'
4004 changed = '+'
4005 if default or id:
4005 if default or id:
4006 output = ["%s%s" %
4006 output = ["%s%s" %
4007 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4007 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4008 if num:
4008 if num:
4009 output.append("%s%s" %
4009 output.append("%s%s" %
4010 ('+'.join([str(p.rev()) for p in parents]), changed))
4010 ('+'.join([str(p.rev()) for p in parents]), changed))
4011 else:
4011 else:
4012 ctx = scmutil.revsingle(repo, rev)
4012 ctx = scmutil.revsingle(repo, rev)
4013 if default or id:
4013 if default or id:
4014 output = [hexfunc(ctx.node())]
4014 output = [hexfunc(ctx.node())]
4015 if num:
4015 if num:
4016 output.append(str(ctx.rev()))
4016 output.append(str(ctx.rev()))
4017
4017
4018 if default and not ui.quiet:
4018 if default and not ui.quiet:
4019 b = ctx.branch()
4019 b = ctx.branch()
4020 if b != 'default':
4020 if b != 'default':
4021 output.append("(%s)" % b)
4021 output.append("(%s)" % b)
4022
4022
4023 # multiple tags for a single parent separated by '/'
4023 # multiple tags for a single parent separated by '/'
4024 t = '/'.join(ctx.tags())
4024 t = '/'.join(ctx.tags())
4025 if t:
4025 if t:
4026 output.append(t)
4026 output.append(t)
4027
4027
4028 # multiple bookmarks for a single parent separated by '/'
4028 # multiple bookmarks for a single parent separated by '/'
4029 bm = '/'.join(ctx.bookmarks())
4029 bm = '/'.join(ctx.bookmarks())
4030 if bm:
4030 if bm:
4031 output.append(bm)
4031 output.append(bm)
4032 else:
4032 else:
4033 if branch:
4033 if branch:
4034 output.append(ctx.branch())
4034 output.append(ctx.branch())
4035
4035
4036 if tags:
4036 if tags:
4037 output.extend(ctx.tags())
4037 output.extend(ctx.tags())
4038
4038
4039 if bookmarks:
4039 if bookmarks:
4040 output.extend(ctx.bookmarks())
4040 output.extend(ctx.bookmarks())
4041
4041
4042 ui.write("%s\n" % ' '.join(output))
4042 ui.write("%s\n" % ' '.join(output))
4043
4043
4044 @command('import|patch',
4044 @command('import|patch',
4045 [('p', 'strip', 1,
4045 [('p', 'strip', 1,
4046 _('directory strip option for patch. This has the same '
4046 _('directory strip option for patch. This has the same '
4047 'meaning as the corresponding patch option'), _('NUM')),
4047 'meaning as the corresponding patch option'), _('NUM')),
4048 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4048 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4049 ('e', 'edit', False, _('invoke editor on commit messages')),
4049 ('e', 'edit', False, _('invoke editor on commit messages')),
4050 ('f', 'force', None,
4050 ('f', 'force', None,
4051 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4051 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4052 ('', 'no-commit', None,
4052 ('', 'no-commit', None,
4053 _("don't commit, just update the working directory")),
4053 _("don't commit, just update the working directory")),
4054 ('', 'bypass', None,
4054 ('', 'bypass', None,
4055 _("apply patch without touching the working directory")),
4055 _("apply patch without touching the working directory")),
4056 ('', 'partial', None,
4056 ('', 'partial', None,
4057 _('commit even if some hunks fail')),
4057 _('commit even if some hunks fail')),
4058 ('', 'exact', None,
4058 ('', 'exact', None,
4059 _('apply patch to the nodes from which it was generated')),
4059 _('apply patch to the nodes from which it was generated')),
4060 ('', 'prefix', '',
4061 _('apply patch to directory relative to the root'), _('DIR')),
4060 ('', 'import-branch', None,
4062 ('', 'import-branch', None,
4061 _('use any branch information in patch (implied by --exact)'))] +
4063 _('use any branch information in patch (implied by --exact)'))] +
4062 commitopts + commitopts2 + similarityopts,
4064 commitopts + commitopts2 + similarityopts,
4063 _('[OPTION]... PATCH...'))
4065 _('[OPTION]... PATCH...'))
4064 def import_(ui, repo, patch1=None, *patches, **opts):
4066 def import_(ui, repo, patch1=None, *patches, **opts):
4065 """import an ordered set of patches
4067 """import an ordered set of patches
4066
4068
4067 Import a list of patches and commit them individually (unless
4069 Import a list of patches and commit them individually (unless
4068 --no-commit is specified).
4070 --no-commit is specified).
4069
4071
4070 Because import first applies changes to the working directory,
4072 Because import first applies changes to the working directory,
4071 import will abort if there are outstanding changes.
4073 import will abort if there are outstanding changes.
4072
4074
4073 You can import a patch straight from a mail message. Even patches
4075 You can import a patch straight from a mail message. Even patches
4074 as attachments work (to use the body part, it must have type
4076 as attachments work (to use the body part, it must have type
4075 text/plain or text/x-patch). From and Subject headers of email
4077 text/plain or text/x-patch). From and Subject headers of email
4076 message are used as default committer and commit message. All
4078 message are used as default committer and commit message. All
4077 text/plain body parts before first diff are added to commit
4079 text/plain body parts before first diff are added to commit
4078 message.
4080 message.
4079
4081
4080 If the imported patch was generated by :hg:`export`, user and
4082 If the imported patch was generated by :hg:`export`, user and
4081 description from patch override values from message headers and
4083 description from patch override values from message headers and
4082 body. Values given on command line with -m/--message and -u/--user
4084 body. Values given on command line with -m/--message and -u/--user
4083 override these.
4085 override these.
4084
4086
4085 If --exact is specified, import will set the working directory to
4087 If --exact is specified, import will set the working directory to
4086 the parent of each patch before applying it, and will abort if the
4088 the parent of each patch before applying it, and will abort if the
4087 resulting changeset has a different ID than the one recorded in
4089 resulting changeset has a different ID than the one recorded in
4088 the patch. This may happen due to character set problems or other
4090 the patch. This may happen due to character set problems or other
4089 deficiencies in the text patch format.
4091 deficiencies in the text patch format.
4090
4092
4091 Use --bypass to apply and commit patches directly to the
4093 Use --bypass to apply and commit patches directly to the
4092 repository, not touching the working directory. Without --exact,
4094 repository, not touching the working directory. Without --exact,
4093 patches will be applied on top of the working directory parent
4095 patches will be applied on top of the working directory parent
4094 revision.
4096 revision.
4095
4097
4096 With -s/--similarity, hg will attempt to discover renames and
4098 With -s/--similarity, hg will attempt to discover renames and
4097 copies in the patch in the same way as :hg:`addremove`.
4099 copies in the patch in the same way as :hg:`addremove`.
4098
4100
4099 Use --partial to ensure a changeset will be created from the patch
4101 Use --partial to ensure a changeset will be created from the patch
4100 even if some hunks fail to apply. Hunks that fail to apply will be
4102 even if some hunks fail to apply. Hunks that fail to apply will be
4101 written to a <target-file>.rej file. Conflicts can then be resolved
4103 written to a <target-file>.rej file. Conflicts can then be resolved
4102 by hand before :hg:`commit --amend` is run to update the created
4104 by hand before :hg:`commit --amend` is run to update the created
4103 changeset. This flag exists to let people import patches that
4105 changeset. This flag exists to let people import patches that
4104 partially apply without losing the associated metadata (author,
4106 partially apply without losing the associated metadata (author,
4105 date, description, ...). Note that when none of the hunk applies
4107 date, description, ...). Note that when none of the hunk applies
4106 cleanly, :hg:`import --partial` will create an empty changeset,
4108 cleanly, :hg:`import --partial` will create an empty changeset,
4107 importing only the patch metadata.
4109 importing only the patch metadata.
4108
4110
4109 To read a patch from standard input, use "-" as the patch name. If
4111 To read a patch from standard input, use "-" as the patch name. If
4110 a URL is specified, the patch will be downloaded from it.
4112 a URL is specified, the patch will be downloaded from it.
4111 See :hg:`help dates` for a list of formats valid for -d/--date.
4113 See :hg:`help dates` for a list of formats valid for -d/--date.
4112
4114
4113 .. container:: verbose
4115 .. container:: verbose
4114
4116
4115 Examples:
4117 Examples:
4116
4118
4117 - import a traditional patch from a website and detect renames::
4119 - import a traditional patch from a website and detect renames::
4118
4120
4119 hg import -s 80 http://example.com/bugfix.patch
4121 hg import -s 80 http://example.com/bugfix.patch
4120
4122
4121 - import a changeset from an hgweb server::
4123 - import a changeset from an hgweb server::
4122
4124
4123 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4125 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4124
4126
4125 - import all the patches in an Unix-style mbox::
4127 - import all the patches in an Unix-style mbox::
4126
4128
4127 hg import incoming-patches.mbox
4129 hg import incoming-patches.mbox
4128
4130
4129 - attempt to exactly restore an exported changeset (not always
4131 - attempt to exactly restore an exported changeset (not always
4130 possible)::
4132 possible)::
4131
4133
4132 hg import --exact proposed-fix.patch
4134 hg import --exact proposed-fix.patch
4133
4135
4134 Returns 0 on success, 1 on partial success (see --partial).
4136 Returns 0 on success, 1 on partial success (see --partial).
4135 """
4137 """
4136
4138
4137 if not patch1:
4139 if not patch1:
4138 raise util.Abort(_('need at least one patch to import'))
4140 raise util.Abort(_('need at least one patch to import'))
4139
4141
4140 patches = (patch1,) + patches
4142 patches = (patch1,) + patches
4141
4143
4142 date = opts.get('date')
4144 date = opts.get('date')
4143 if date:
4145 if date:
4144 opts['date'] = util.parsedate(date)
4146 opts['date'] = util.parsedate(date)
4145
4147
4146 update = not opts.get('bypass')
4148 update = not opts.get('bypass')
4147 if not update and opts.get('no_commit'):
4149 if not update and opts.get('no_commit'):
4148 raise util.Abort(_('cannot use --no-commit with --bypass'))
4150 raise util.Abort(_('cannot use --no-commit with --bypass'))
4149 try:
4151 try:
4150 sim = float(opts.get('similarity') or 0)
4152 sim = float(opts.get('similarity') or 0)
4151 except ValueError:
4153 except ValueError:
4152 raise util.Abort(_('similarity must be a number'))
4154 raise util.Abort(_('similarity must be a number'))
4153 if sim < 0 or sim > 100:
4155 if sim < 0 or sim > 100:
4154 raise util.Abort(_('similarity must be between 0 and 100'))
4156 raise util.Abort(_('similarity must be between 0 and 100'))
4155 if sim and not update:
4157 if sim and not update:
4156 raise util.Abort(_('cannot use --similarity with --bypass'))
4158 raise util.Abort(_('cannot use --similarity with --bypass'))
4157 if opts.get('exact') and opts.get('edit'):
4159 if opts.get('exact') and opts.get('edit'):
4158 raise util.Abort(_('cannot use --exact with --edit'))
4160 raise util.Abort(_('cannot use --exact with --edit'))
4161 if opts.get('exact') and opts.get('prefix'):
4162 raise util.Abort(_('cannot use --exact with --prefix'))
4159
4163
4160 if update:
4164 if update:
4161 cmdutil.checkunfinished(repo)
4165 cmdutil.checkunfinished(repo)
4162 if (opts.get('exact') or not opts.get('force')) and update:
4166 if (opts.get('exact') or not opts.get('force')) and update:
4163 cmdutil.bailifchanged(repo)
4167 cmdutil.bailifchanged(repo)
4164
4168
4165 base = opts["base"]
4169 base = opts["base"]
4166 wlock = lock = tr = None
4170 wlock = lock = tr = None
4167 msgs = []
4171 msgs = []
4168 ret = 0
4172 ret = 0
4169
4173
4170
4174
4171 try:
4175 try:
4172 try:
4176 try:
4173 wlock = repo.wlock()
4177 wlock = repo.wlock()
4174 repo.dirstate.beginparentchange()
4178 repo.dirstate.beginparentchange()
4175 if not opts.get('no_commit'):
4179 if not opts.get('no_commit'):
4176 lock = repo.lock()
4180 lock = repo.lock()
4177 tr = repo.transaction('import')
4181 tr = repo.transaction('import')
4178 parents = repo.parents()
4182 parents = repo.parents()
4179 for patchurl in patches:
4183 for patchurl in patches:
4180 if patchurl == '-':
4184 if patchurl == '-':
4181 ui.status(_('applying patch from stdin\n'))
4185 ui.status(_('applying patch from stdin\n'))
4182 patchfile = ui.fin
4186 patchfile = ui.fin
4183 patchurl = 'stdin' # for error message
4187 patchurl = 'stdin' # for error message
4184 else:
4188 else:
4185 patchurl = os.path.join(base, patchurl)
4189 patchurl = os.path.join(base, patchurl)
4186 ui.status(_('applying %s\n') % patchurl)
4190 ui.status(_('applying %s\n') % patchurl)
4187 patchfile = hg.openpath(ui, patchurl)
4191 patchfile = hg.openpath(ui, patchurl)
4188
4192
4189 haspatch = False
4193 haspatch = False
4190 for hunk in patch.split(patchfile):
4194 for hunk in patch.split(patchfile):
4191 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4195 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4192 parents, opts,
4196 parents, opts,
4193 msgs, hg.clean)
4197 msgs, hg.clean)
4194 if msg:
4198 if msg:
4195 haspatch = True
4199 haspatch = True
4196 ui.note(msg + '\n')
4200 ui.note(msg + '\n')
4197 if update or opts.get('exact'):
4201 if update or opts.get('exact'):
4198 parents = repo.parents()
4202 parents = repo.parents()
4199 else:
4203 else:
4200 parents = [repo[node]]
4204 parents = [repo[node]]
4201 if rej:
4205 if rej:
4202 ui.write_err(_("patch applied partially\n"))
4206 ui.write_err(_("patch applied partially\n"))
4203 ui.write_err(_("(fix the .rej files and run "
4207 ui.write_err(_("(fix the .rej files and run "
4204 "`hg commit --amend`)\n"))
4208 "`hg commit --amend`)\n"))
4205 ret = 1
4209 ret = 1
4206 break
4210 break
4207
4211
4208 if not haspatch:
4212 if not haspatch:
4209 raise util.Abort(_('%s: no diffs found') % patchurl)
4213 raise util.Abort(_('%s: no diffs found') % patchurl)
4210
4214
4211 if tr:
4215 if tr:
4212 tr.close()
4216 tr.close()
4213 if msgs:
4217 if msgs:
4214 repo.savecommitmessage('\n* * *\n'.join(msgs))
4218 repo.savecommitmessage('\n* * *\n'.join(msgs))
4215 repo.dirstate.endparentchange()
4219 repo.dirstate.endparentchange()
4216 return ret
4220 return ret
4217 except: # re-raises
4221 except: # re-raises
4218 # wlock.release() indirectly calls dirstate.write(): since
4222 # wlock.release() indirectly calls dirstate.write(): since
4219 # we're crashing, we do not want to change the working dir
4223 # we're crashing, we do not want to change the working dir
4220 # parent after all, so make sure it writes nothing
4224 # parent after all, so make sure it writes nothing
4221 repo.dirstate.invalidate()
4225 repo.dirstate.invalidate()
4222 raise
4226 raise
4223 finally:
4227 finally:
4224 if tr:
4228 if tr:
4225 tr.release()
4229 tr.release()
4226 release(lock, wlock)
4230 release(lock, wlock)
4227
4231
4228 @command('incoming|in',
4232 @command('incoming|in',
4229 [('f', 'force', None,
4233 [('f', 'force', None,
4230 _('run even if remote repository is unrelated')),
4234 _('run even if remote repository is unrelated')),
4231 ('n', 'newest-first', None, _('show newest record first')),
4235 ('n', 'newest-first', None, _('show newest record first')),
4232 ('', 'bundle', '',
4236 ('', 'bundle', '',
4233 _('file to store the bundles into'), _('FILE')),
4237 _('file to store the bundles into'), _('FILE')),
4234 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4238 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4235 ('B', 'bookmarks', False, _("compare bookmarks")),
4239 ('B', 'bookmarks', False, _("compare bookmarks")),
4236 ('b', 'branch', [],
4240 ('b', 'branch', [],
4237 _('a specific branch you would like to pull'), _('BRANCH')),
4241 _('a specific branch you would like to pull'), _('BRANCH')),
4238 ] + logopts + remoteopts + subrepoopts,
4242 ] + logopts + remoteopts + subrepoopts,
4239 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4243 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4240 def incoming(ui, repo, source="default", **opts):
4244 def incoming(ui, repo, source="default", **opts):
4241 """show new changesets found in source
4245 """show new changesets found in source
4242
4246
4243 Show new changesets found in the specified path/URL or the default
4247 Show new changesets found in the specified path/URL or the default
4244 pull location. These are the changesets that would have been pulled
4248 pull location. These are the changesets that would have been pulled
4245 if a pull at the time you issued this command.
4249 if a pull at the time you issued this command.
4246
4250
4247 See pull for valid source format details.
4251 See pull for valid source format details.
4248
4252
4249 .. container:: verbose
4253 .. container:: verbose
4250
4254
4251 For remote repository, using --bundle avoids downloading the
4255 For remote repository, using --bundle avoids downloading the
4252 changesets twice if the incoming is followed by a pull.
4256 changesets twice if the incoming is followed by a pull.
4253
4257
4254 Examples:
4258 Examples:
4255
4259
4256 - show incoming changes with patches and full description::
4260 - show incoming changes with patches and full description::
4257
4261
4258 hg incoming -vp
4262 hg incoming -vp
4259
4263
4260 - show incoming changes excluding merges, store a bundle::
4264 - show incoming changes excluding merges, store a bundle::
4261
4265
4262 hg in -vpM --bundle incoming.hg
4266 hg in -vpM --bundle incoming.hg
4263 hg pull incoming.hg
4267 hg pull incoming.hg
4264
4268
4265 - briefly list changes inside a bundle::
4269 - briefly list changes inside a bundle::
4266
4270
4267 hg in changes.hg -T "{desc|firstline}\\n"
4271 hg in changes.hg -T "{desc|firstline}\\n"
4268
4272
4269 Returns 0 if there are incoming changes, 1 otherwise.
4273 Returns 0 if there are incoming changes, 1 otherwise.
4270 """
4274 """
4271 if opts.get('graph'):
4275 if opts.get('graph'):
4272 cmdutil.checkunsupportedgraphflags([], opts)
4276 cmdutil.checkunsupportedgraphflags([], opts)
4273 def display(other, chlist, displayer):
4277 def display(other, chlist, displayer):
4274 revdag = cmdutil.graphrevs(other, chlist, opts)
4278 revdag = cmdutil.graphrevs(other, chlist, opts)
4275 showparents = [ctx.node() for ctx in repo[None].parents()]
4279 showparents = [ctx.node() for ctx in repo[None].parents()]
4276 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4280 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4277 graphmod.asciiedges)
4281 graphmod.asciiedges)
4278
4282
4279 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4283 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4280 return 0
4284 return 0
4281
4285
4282 if opts.get('bundle') and opts.get('subrepos'):
4286 if opts.get('bundle') and opts.get('subrepos'):
4283 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4287 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4284
4288
4285 if opts.get('bookmarks'):
4289 if opts.get('bookmarks'):
4286 source, branches = hg.parseurl(ui.expandpath(source),
4290 source, branches = hg.parseurl(ui.expandpath(source),
4287 opts.get('branch'))
4291 opts.get('branch'))
4288 other = hg.peer(repo, opts, source)
4292 other = hg.peer(repo, opts, source)
4289 if 'bookmarks' not in other.listkeys('namespaces'):
4293 if 'bookmarks' not in other.listkeys('namespaces'):
4290 ui.warn(_("remote doesn't support bookmarks\n"))
4294 ui.warn(_("remote doesn't support bookmarks\n"))
4291 return 0
4295 return 0
4292 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4296 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4293 return bookmarks.diff(ui, repo, other)
4297 return bookmarks.diff(ui, repo, other)
4294
4298
4295 repo._subtoppath = ui.expandpath(source)
4299 repo._subtoppath = ui.expandpath(source)
4296 try:
4300 try:
4297 return hg.incoming(ui, repo, source, opts)
4301 return hg.incoming(ui, repo, source, opts)
4298 finally:
4302 finally:
4299 del repo._subtoppath
4303 del repo._subtoppath
4300
4304
4301
4305
4302 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4306 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4303 norepo=True)
4307 norepo=True)
4304 def init(ui, dest=".", **opts):
4308 def init(ui, dest=".", **opts):
4305 """create a new repository in the given directory
4309 """create a new repository in the given directory
4306
4310
4307 Initialize a new repository in the given directory. If the given
4311 Initialize a new repository in the given directory. If the given
4308 directory does not exist, it will be created.
4312 directory does not exist, it will be created.
4309
4313
4310 If no directory is given, the current directory is used.
4314 If no directory is given, the current directory is used.
4311
4315
4312 It is possible to specify an ``ssh://`` URL as the destination.
4316 It is possible to specify an ``ssh://`` URL as the destination.
4313 See :hg:`help urls` for more information.
4317 See :hg:`help urls` for more information.
4314
4318
4315 Returns 0 on success.
4319 Returns 0 on success.
4316 """
4320 """
4317 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4321 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4318
4322
4319 @command('locate',
4323 @command('locate',
4320 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4324 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4321 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4325 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4322 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4326 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4323 ] + walkopts,
4327 ] + walkopts,
4324 _('[OPTION]... [PATTERN]...'))
4328 _('[OPTION]... [PATTERN]...'))
4325 def locate(ui, repo, *pats, **opts):
4329 def locate(ui, repo, *pats, **opts):
4326 """locate files matching specific patterns (DEPRECATED)
4330 """locate files matching specific patterns (DEPRECATED)
4327
4331
4328 Print files under Mercurial control in the working directory whose
4332 Print files under Mercurial control in the working directory whose
4329 names match the given patterns.
4333 names match the given patterns.
4330
4334
4331 By default, this command searches all directories in the working
4335 By default, this command searches all directories in the working
4332 directory. To search just the current directory and its
4336 directory. To search just the current directory and its
4333 subdirectories, use "--include .".
4337 subdirectories, use "--include .".
4334
4338
4335 If no patterns are given to match, this command prints the names
4339 If no patterns are given to match, this command prints the names
4336 of all files under Mercurial control in the working directory.
4340 of all files under Mercurial control in the working directory.
4337
4341
4338 If you want to feed the output of this command into the "xargs"
4342 If you want to feed the output of this command into the "xargs"
4339 command, use the -0 option to both this command and "xargs". This
4343 command, use the -0 option to both this command and "xargs". This
4340 will avoid the problem of "xargs" treating single filenames that
4344 will avoid the problem of "xargs" treating single filenames that
4341 contain whitespace as multiple filenames.
4345 contain whitespace as multiple filenames.
4342
4346
4343 See :hg:`help files` for a more versatile command.
4347 See :hg:`help files` for a more versatile command.
4344
4348
4345 Returns 0 if a match is found, 1 otherwise.
4349 Returns 0 if a match is found, 1 otherwise.
4346 """
4350 """
4347 end = opts.get('print0') and '\0' or '\n'
4351 end = opts.get('print0') and '\0' or '\n'
4348 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4352 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4349
4353
4350 ret = 1
4354 ret = 1
4351 ctx = repo[rev]
4355 ctx = repo[rev]
4352 m = scmutil.match(ctx, pats, opts, default='relglob')
4356 m = scmutil.match(ctx, pats, opts, default='relglob')
4353 m.bad = lambda x, y: False
4357 m.bad = lambda x, y: False
4354
4358
4355 for abs in ctx.matches(m):
4359 for abs in ctx.matches(m):
4356 if opts.get('fullpath'):
4360 if opts.get('fullpath'):
4357 ui.write(repo.wjoin(abs), end)
4361 ui.write(repo.wjoin(abs), end)
4358 else:
4362 else:
4359 ui.write(((pats and m.rel(abs)) or abs), end)
4363 ui.write(((pats and m.rel(abs)) or abs), end)
4360 ret = 0
4364 ret = 0
4361
4365
4362 return ret
4366 return ret
4363
4367
4364 @command('^log|history',
4368 @command('^log|history',
4365 [('f', 'follow', None,
4369 [('f', 'follow', None,
4366 _('follow changeset history, or file history across copies and renames')),
4370 _('follow changeset history, or file history across copies and renames')),
4367 ('', 'follow-first', None,
4371 ('', 'follow-first', None,
4368 _('only follow the first parent of merge changesets (DEPRECATED)')),
4372 _('only follow the first parent of merge changesets (DEPRECATED)')),
4369 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4373 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4370 ('C', 'copies', None, _('show copied files')),
4374 ('C', 'copies', None, _('show copied files')),
4371 ('k', 'keyword', [],
4375 ('k', 'keyword', [],
4372 _('do case-insensitive search for a given text'), _('TEXT')),
4376 _('do case-insensitive search for a given text'), _('TEXT')),
4373 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4377 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4374 ('', 'removed', None, _('include revisions where files were removed')),
4378 ('', 'removed', None, _('include revisions where files were removed')),
4375 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4379 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4376 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4380 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4377 ('', 'only-branch', [],
4381 ('', 'only-branch', [],
4378 _('show only changesets within the given named branch (DEPRECATED)'),
4382 _('show only changesets within the given named branch (DEPRECATED)'),
4379 _('BRANCH')),
4383 _('BRANCH')),
4380 ('b', 'branch', [],
4384 ('b', 'branch', [],
4381 _('show changesets within the given named branch'), _('BRANCH')),
4385 _('show changesets within the given named branch'), _('BRANCH')),
4382 ('P', 'prune', [],
4386 ('P', 'prune', [],
4383 _('do not display revision or any of its ancestors'), _('REV')),
4387 _('do not display revision or any of its ancestors'), _('REV')),
4384 ] + logopts + walkopts,
4388 ] + logopts + walkopts,
4385 _('[OPTION]... [FILE]'),
4389 _('[OPTION]... [FILE]'),
4386 inferrepo=True)
4390 inferrepo=True)
4387 def log(ui, repo, *pats, **opts):
4391 def log(ui, repo, *pats, **opts):
4388 """show revision history of entire repository or files
4392 """show revision history of entire repository or files
4389
4393
4390 Print the revision history of the specified files or the entire
4394 Print the revision history of the specified files or the entire
4391 project.
4395 project.
4392
4396
4393 If no revision range is specified, the default is ``tip:0`` unless
4397 If no revision range is specified, the default is ``tip:0`` unless
4394 --follow is set, in which case the working directory parent is
4398 --follow is set, in which case the working directory parent is
4395 used as the starting revision.
4399 used as the starting revision.
4396
4400
4397 File history is shown without following rename or copy history of
4401 File history is shown without following rename or copy history of
4398 files. Use -f/--follow with a filename to follow history across
4402 files. Use -f/--follow with a filename to follow history across
4399 renames and copies. --follow without a filename will only show
4403 renames and copies. --follow without a filename will only show
4400 ancestors or descendants of the starting revision.
4404 ancestors or descendants of the starting revision.
4401
4405
4402 By default this command prints revision number and changeset id,
4406 By default this command prints revision number and changeset id,
4403 tags, non-trivial parents, user, date and time, and a summary for
4407 tags, non-trivial parents, user, date and time, and a summary for
4404 each commit. When the -v/--verbose switch is used, the list of
4408 each commit. When the -v/--verbose switch is used, the list of
4405 changed files and full commit message are shown.
4409 changed files and full commit message are shown.
4406
4410
4407 With --graph the revisions are shown as an ASCII art DAG with the most
4411 With --graph the revisions are shown as an ASCII art DAG with the most
4408 recent changeset at the top.
4412 recent changeset at the top.
4409 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4413 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4410 and '+' represents a fork where the changeset from the lines below is a
4414 and '+' represents a fork where the changeset from the lines below is a
4411 parent of the 'o' merge on the same line.
4415 parent of the 'o' merge on the same line.
4412
4416
4413 .. note::
4417 .. note::
4414
4418
4415 log -p/--patch may generate unexpected diff output for merge
4419 log -p/--patch may generate unexpected diff output for merge
4416 changesets, as it will only compare the merge changeset against
4420 changesets, as it will only compare the merge changeset against
4417 its first parent. Also, only files different from BOTH parents
4421 its first parent. Also, only files different from BOTH parents
4418 will appear in files:.
4422 will appear in files:.
4419
4423
4420 .. note::
4424 .. note::
4421
4425
4422 for performance reasons, log FILE may omit duplicate changes
4426 for performance reasons, log FILE may omit duplicate changes
4423 made on branches and will not show removals or mode changes. To
4427 made on branches and will not show removals or mode changes. To
4424 see all such changes, use the --removed switch.
4428 see all such changes, use the --removed switch.
4425
4429
4426 .. container:: verbose
4430 .. container:: verbose
4427
4431
4428 Some examples:
4432 Some examples:
4429
4433
4430 - changesets with full descriptions and file lists::
4434 - changesets with full descriptions and file lists::
4431
4435
4432 hg log -v
4436 hg log -v
4433
4437
4434 - changesets ancestral to the working directory::
4438 - changesets ancestral to the working directory::
4435
4439
4436 hg log -f
4440 hg log -f
4437
4441
4438 - last 10 commits on the current branch::
4442 - last 10 commits on the current branch::
4439
4443
4440 hg log -l 10 -b .
4444 hg log -l 10 -b .
4441
4445
4442 - changesets showing all modifications of a file, including removals::
4446 - changesets showing all modifications of a file, including removals::
4443
4447
4444 hg log --removed file.c
4448 hg log --removed file.c
4445
4449
4446 - all changesets that touch a directory, with diffs, excluding merges::
4450 - all changesets that touch a directory, with diffs, excluding merges::
4447
4451
4448 hg log -Mp lib/
4452 hg log -Mp lib/
4449
4453
4450 - all revision numbers that match a keyword::
4454 - all revision numbers that match a keyword::
4451
4455
4452 hg log -k bug --template "{rev}\\n"
4456 hg log -k bug --template "{rev}\\n"
4453
4457
4454 - list available log templates::
4458 - list available log templates::
4455
4459
4456 hg log -T list
4460 hg log -T list
4457
4461
4458 - check if a given changeset is included in a tagged release::
4462 - check if a given changeset is included in a tagged release::
4459
4463
4460 hg log -r "a21ccf and ancestor(1.9)"
4464 hg log -r "a21ccf and ancestor(1.9)"
4461
4465
4462 - find all changesets by some user in a date range::
4466 - find all changesets by some user in a date range::
4463
4467
4464 hg log -k alice -d "may 2008 to jul 2008"
4468 hg log -k alice -d "may 2008 to jul 2008"
4465
4469
4466 - summary of all changesets after the last tag::
4470 - summary of all changesets after the last tag::
4467
4471
4468 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4472 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4469
4473
4470 See :hg:`help dates` for a list of formats valid for -d/--date.
4474 See :hg:`help dates` for a list of formats valid for -d/--date.
4471
4475
4472 See :hg:`help revisions` and :hg:`help revsets` for more about
4476 See :hg:`help revisions` and :hg:`help revsets` for more about
4473 specifying revisions.
4477 specifying revisions.
4474
4478
4475 See :hg:`help templates` for more about pre-packaged styles and
4479 See :hg:`help templates` for more about pre-packaged styles and
4476 specifying custom templates.
4480 specifying custom templates.
4477
4481
4478 Returns 0 on success.
4482 Returns 0 on success.
4479
4483
4480 """
4484 """
4481 if opts.get('follow') and opts.get('rev'):
4485 if opts.get('follow') and opts.get('rev'):
4482 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4486 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4483 del opts['follow']
4487 del opts['follow']
4484
4488
4485 if opts.get('graph'):
4489 if opts.get('graph'):
4486 return cmdutil.graphlog(ui, repo, *pats, **opts)
4490 return cmdutil.graphlog(ui, repo, *pats, **opts)
4487
4491
4488 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4492 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4489 limit = cmdutil.loglimit(opts)
4493 limit = cmdutil.loglimit(opts)
4490 count = 0
4494 count = 0
4491
4495
4492 getrenamed = None
4496 getrenamed = None
4493 if opts.get('copies'):
4497 if opts.get('copies'):
4494 endrev = None
4498 endrev = None
4495 if opts.get('rev'):
4499 if opts.get('rev'):
4496 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4500 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4497 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4501 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4498
4502
4499 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4503 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4500 for rev in revs:
4504 for rev in revs:
4501 if count == limit:
4505 if count == limit:
4502 break
4506 break
4503 ctx = repo[rev]
4507 ctx = repo[rev]
4504 copies = None
4508 copies = None
4505 if getrenamed is not None and rev:
4509 if getrenamed is not None and rev:
4506 copies = []
4510 copies = []
4507 for fn in ctx.files():
4511 for fn in ctx.files():
4508 rename = getrenamed(fn, rev)
4512 rename = getrenamed(fn, rev)
4509 if rename:
4513 if rename:
4510 copies.append((fn, rename[0]))
4514 copies.append((fn, rename[0]))
4511 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4515 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4512 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4516 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4513 if displayer.flush(rev):
4517 if displayer.flush(rev):
4514 count += 1
4518 count += 1
4515
4519
4516 displayer.close()
4520 displayer.close()
4517
4521
4518 @command('manifest',
4522 @command('manifest',
4519 [('r', 'rev', '', _('revision to display'), _('REV')),
4523 [('r', 'rev', '', _('revision to display'), _('REV')),
4520 ('', 'all', False, _("list files from all revisions"))]
4524 ('', 'all', False, _("list files from all revisions"))]
4521 + formatteropts,
4525 + formatteropts,
4522 _('[-r REV]'))
4526 _('[-r REV]'))
4523 def manifest(ui, repo, node=None, rev=None, **opts):
4527 def manifest(ui, repo, node=None, rev=None, **opts):
4524 """output the current or given revision of the project manifest
4528 """output the current or given revision of the project manifest
4525
4529
4526 Print a list of version controlled files for the given revision.
4530 Print a list of version controlled files for the given revision.
4527 If no revision is given, the first parent of the working directory
4531 If no revision is given, the first parent of the working directory
4528 is used, or the null revision if no revision is checked out.
4532 is used, or the null revision if no revision is checked out.
4529
4533
4530 With -v, print file permissions, symlink and executable bits.
4534 With -v, print file permissions, symlink and executable bits.
4531 With --debug, print file revision hashes.
4535 With --debug, print file revision hashes.
4532
4536
4533 If option --all is specified, the list of all files from all revisions
4537 If option --all is specified, the list of all files from all revisions
4534 is printed. This includes deleted and renamed files.
4538 is printed. This includes deleted and renamed files.
4535
4539
4536 Returns 0 on success.
4540 Returns 0 on success.
4537 """
4541 """
4538
4542
4539 fm = ui.formatter('manifest', opts)
4543 fm = ui.formatter('manifest', opts)
4540
4544
4541 if opts.get('all'):
4545 if opts.get('all'):
4542 if rev or node:
4546 if rev or node:
4543 raise util.Abort(_("can't specify a revision with --all"))
4547 raise util.Abort(_("can't specify a revision with --all"))
4544
4548
4545 res = []
4549 res = []
4546 prefix = "data/"
4550 prefix = "data/"
4547 suffix = ".i"
4551 suffix = ".i"
4548 plen = len(prefix)
4552 plen = len(prefix)
4549 slen = len(suffix)
4553 slen = len(suffix)
4550 lock = repo.lock()
4554 lock = repo.lock()
4551 try:
4555 try:
4552 for fn, b, size in repo.store.datafiles():
4556 for fn, b, size in repo.store.datafiles():
4553 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4557 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4554 res.append(fn[plen:-slen])
4558 res.append(fn[plen:-slen])
4555 finally:
4559 finally:
4556 lock.release()
4560 lock.release()
4557 for f in res:
4561 for f in res:
4558 fm.startitem()
4562 fm.startitem()
4559 fm.write("path", '%s\n', f)
4563 fm.write("path", '%s\n', f)
4560 fm.end()
4564 fm.end()
4561 return
4565 return
4562
4566
4563 if rev and node:
4567 if rev and node:
4564 raise util.Abort(_("please specify just one revision"))
4568 raise util.Abort(_("please specify just one revision"))
4565
4569
4566 if not node:
4570 if not node:
4567 node = rev
4571 node = rev
4568
4572
4569 char = {'l': '@', 'x': '*', '': ''}
4573 char = {'l': '@', 'x': '*', '': ''}
4570 mode = {'l': '644', 'x': '755', '': '644'}
4574 mode = {'l': '644', 'x': '755', '': '644'}
4571 ctx = scmutil.revsingle(repo, node)
4575 ctx = scmutil.revsingle(repo, node)
4572 mf = ctx.manifest()
4576 mf = ctx.manifest()
4573 for f in ctx:
4577 for f in ctx:
4574 fm.startitem()
4578 fm.startitem()
4575 fl = ctx[f].flags()
4579 fl = ctx[f].flags()
4576 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4580 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4577 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4581 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4578 fm.write('path', '%s\n', f)
4582 fm.write('path', '%s\n', f)
4579 fm.end()
4583 fm.end()
4580
4584
4581 @command('^merge',
4585 @command('^merge',
4582 [('f', 'force', None,
4586 [('f', 'force', None,
4583 _('force a merge including outstanding changes (DEPRECATED)')),
4587 _('force a merge including outstanding changes (DEPRECATED)')),
4584 ('r', 'rev', '', _('revision to merge'), _('REV')),
4588 ('r', 'rev', '', _('revision to merge'), _('REV')),
4585 ('P', 'preview', None,
4589 ('P', 'preview', None,
4586 _('review revisions to merge (no merge is performed)'))
4590 _('review revisions to merge (no merge is performed)'))
4587 ] + mergetoolopts,
4591 ] + mergetoolopts,
4588 _('[-P] [-f] [[-r] REV]'))
4592 _('[-P] [-f] [[-r] REV]'))
4589 def merge(ui, repo, node=None, **opts):
4593 def merge(ui, repo, node=None, **opts):
4590 """merge another revision into working directory
4594 """merge another revision into working directory
4591
4595
4592 The current working directory is updated with all changes made in
4596 The current working directory is updated with all changes made in
4593 the requested revision since the last common predecessor revision.
4597 the requested revision since the last common predecessor revision.
4594
4598
4595 Files that changed between either parent are marked as changed for
4599 Files that changed between either parent are marked as changed for
4596 the next commit and a commit must be performed before any further
4600 the next commit and a commit must be performed before any further
4597 updates to the repository are allowed. The next commit will have
4601 updates to the repository are allowed. The next commit will have
4598 two parents.
4602 two parents.
4599
4603
4600 ``--tool`` can be used to specify the merge tool used for file
4604 ``--tool`` can be used to specify the merge tool used for file
4601 merges. It overrides the HGMERGE environment variable and your
4605 merges. It overrides the HGMERGE environment variable and your
4602 configuration files. See :hg:`help merge-tools` for options.
4606 configuration files. See :hg:`help merge-tools` for options.
4603
4607
4604 If no revision is specified, the working directory's parent is a
4608 If no revision is specified, the working directory's parent is a
4605 head revision, and the current branch contains exactly one other
4609 head revision, and the current branch contains exactly one other
4606 head, the other head is merged with by default. Otherwise, an
4610 head, the other head is merged with by default. Otherwise, an
4607 explicit revision with which to merge with must be provided.
4611 explicit revision with which to merge with must be provided.
4608
4612
4609 :hg:`resolve` must be used to resolve unresolved files.
4613 :hg:`resolve` must be used to resolve unresolved files.
4610
4614
4611 To undo an uncommitted merge, use :hg:`update --clean .` which
4615 To undo an uncommitted merge, use :hg:`update --clean .` which
4612 will check out a clean copy of the original merge parent, losing
4616 will check out a clean copy of the original merge parent, losing
4613 all changes.
4617 all changes.
4614
4618
4615 Returns 0 on success, 1 if there are unresolved files.
4619 Returns 0 on success, 1 if there are unresolved files.
4616 """
4620 """
4617
4621
4618 if opts.get('rev') and node:
4622 if opts.get('rev') and node:
4619 raise util.Abort(_("please specify just one revision"))
4623 raise util.Abort(_("please specify just one revision"))
4620 if not node:
4624 if not node:
4621 node = opts.get('rev')
4625 node = opts.get('rev')
4622
4626
4623 if node:
4627 if node:
4624 node = scmutil.revsingle(repo, node).node()
4628 node = scmutil.revsingle(repo, node).node()
4625
4629
4626 if not node and repo._bookmarkcurrent:
4630 if not node and repo._bookmarkcurrent:
4627 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4631 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4628 curhead = repo[repo._bookmarkcurrent].node()
4632 curhead = repo[repo._bookmarkcurrent].node()
4629 if len(bmheads) == 2:
4633 if len(bmheads) == 2:
4630 if curhead == bmheads[0]:
4634 if curhead == bmheads[0]:
4631 node = bmheads[1]
4635 node = bmheads[1]
4632 else:
4636 else:
4633 node = bmheads[0]
4637 node = bmheads[0]
4634 elif len(bmheads) > 2:
4638 elif len(bmheads) > 2:
4635 raise util.Abort(_("multiple matching bookmarks to merge - "
4639 raise util.Abort(_("multiple matching bookmarks to merge - "
4636 "please merge with an explicit rev or bookmark"),
4640 "please merge with an explicit rev or bookmark"),
4637 hint=_("run 'hg heads' to see all heads"))
4641 hint=_("run 'hg heads' to see all heads"))
4638 elif len(bmheads) <= 1:
4642 elif len(bmheads) <= 1:
4639 raise util.Abort(_("no matching bookmark to merge - "
4643 raise util.Abort(_("no matching bookmark to merge - "
4640 "please merge with an explicit rev or bookmark"),
4644 "please merge with an explicit rev or bookmark"),
4641 hint=_("run 'hg heads' to see all heads"))
4645 hint=_("run 'hg heads' to see all heads"))
4642
4646
4643 if not node and not repo._bookmarkcurrent:
4647 if not node and not repo._bookmarkcurrent:
4644 branch = repo[None].branch()
4648 branch = repo[None].branch()
4645 bheads = repo.branchheads(branch)
4649 bheads = repo.branchheads(branch)
4646 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4650 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4647
4651
4648 if len(nbhs) > 2:
4652 if len(nbhs) > 2:
4649 raise util.Abort(_("branch '%s' has %d heads - "
4653 raise util.Abort(_("branch '%s' has %d heads - "
4650 "please merge with an explicit rev")
4654 "please merge with an explicit rev")
4651 % (branch, len(bheads)),
4655 % (branch, len(bheads)),
4652 hint=_("run 'hg heads .' to see heads"))
4656 hint=_("run 'hg heads .' to see heads"))
4653
4657
4654 parent = repo.dirstate.p1()
4658 parent = repo.dirstate.p1()
4655 if len(nbhs) <= 1:
4659 if len(nbhs) <= 1:
4656 if len(bheads) > 1:
4660 if len(bheads) > 1:
4657 raise util.Abort(_("heads are bookmarked - "
4661 raise util.Abort(_("heads are bookmarked - "
4658 "please merge with an explicit rev"),
4662 "please merge with an explicit rev"),
4659 hint=_("run 'hg heads' to see all heads"))
4663 hint=_("run 'hg heads' to see all heads"))
4660 if len(repo.heads()) > 1:
4664 if len(repo.heads()) > 1:
4661 raise util.Abort(_("branch '%s' has one head - "
4665 raise util.Abort(_("branch '%s' has one head - "
4662 "please merge with an explicit rev")
4666 "please merge with an explicit rev")
4663 % branch,
4667 % branch,
4664 hint=_("run 'hg heads' to see all heads"))
4668 hint=_("run 'hg heads' to see all heads"))
4665 msg, hint = _('nothing to merge'), None
4669 msg, hint = _('nothing to merge'), None
4666 if parent != repo.lookup(branch):
4670 if parent != repo.lookup(branch):
4667 hint = _("use 'hg update' instead")
4671 hint = _("use 'hg update' instead")
4668 raise util.Abort(msg, hint=hint)
4672 raise util.Abort(msg, hint=hint)
4669
4673
4670 if parent not in bheads:
4674 if parent not in bheads:
4671 raise util.Abort(_('working directory not at a head revision'),
4675 raise util.Abort(_('working directory not at a head revision'),
4672 hint=_("use 'hg update' or merge with an "
4676 hint=_("use 'hg update' or merge with an "
4673 "explicit revision"))
4677 "explicit revision"))
4674 if parent == nbhs[0]:
4678 if parent == nbhs[0]:
4675 node = nbhs[-1]
4679 node = nbhs[-1]
4676 else:
4680 else:
4677 node = nbhs[0]
4681 node = nbhs[0]
4678
4682
4679 if opts.get('preview'):
4683 if opts.get('preview'):
4680 # find nodes that are ancestors of p2 but not of p1
4684 # find nodes that are ancestors of p2 but not of p1
4681 p1 = repo.lookup('.')
4685 p1 = repo.lookup('.')
4682 p2 = repo.lookup(node)
4686 p2 = repo.lookup(node)
4683 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4687 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4684
4688
4685 displayer = cmdutil.show_changeset(ui, repo, opts)
4689 displayer = cmdutil.show_changeset(ui, repo, opts)
4686 for node in nodes:
4690 for node in nodes:
4687 displayer.show(repo[node])
4691 displayer.show(repo[node])
4688 displayer.close()
4692 displayer.close()
4689 return 0
4693 return 0
4690
4694
4691 try:
4695 try:
4692 # ui.forcemerge is an internal variable, do not document
4696 # ui.forcemerge is an internal variable, do not document
4693 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4697 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4694 return hg.merge(repo, node, force=opts.get('force'))
4698 return hg.merge(repo, node, force=opts.get('force'))
4695 finally:
4699 finally:
4696 ui.setconfig('ui', 'forcemerge', '', 'merge')
4700 ui.setconfig('ui', 'forcemerge', '', 'merge')
4697
4701
4698 @command('outgoing|out',
4702 @command('outgoing|out',
4699 [('f', 'force', None, _('run even when the destination is unrelated')),
4703 [('f', 'force', None, _('run even when the destination is unrelated')),
4700 ('r', 'rev', [],
4704 ('r', 'rev', [],
4701 _('a changeset intended to be included in the destination'), _('REV')),
4705 _('a changeset intended to be included in the destination'), _('REV')),
4702 ('n', 'newest-first', None, _('show newest record first')),
4706 ('n', 'newest-first', None, _('show newest record first')),
4703 ('B', 'bookmarks', False, _('compare bookmarks')),
4707 ('B', 'bookmarks', False, _('compare bookmarks')),
4704 ('b', 'branch', [], _('a specific branch you would like to push'),
4708 ('b', 'branch', [], _('a specific branch you would like to push'),
4705 _('BRANCH')),
4709 _('BRANCH')),
4706 ] + logopts + remoteopts + subrepoopts,
4710 ] + logopts + remoteopts + subrepoopts,
4707 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4711 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4708 def outgoing(ui, repo, dest=None, **opts):
4712 def outgoing(ui, repo, dest=None, **opts):
4709 """show changesets not found in the destination
4713 """show changesets not found in the destination
4710
4714
4711 Show changesets not found in the specified destination repository
4715 Show changesets not found in the specified destination repository
4712 or the default push location. These are the changesets that would
4716 or the default push location. These are the changesets that would
4713 be pushed if a push was requested.
4717 be pushed if a push was requested.
4714
4718
4715 See pull for details of valid destination formats.
4719 See pull for details of valid destination formats.
4716
4720
4717 Returns 0 if there are outgoing changes, 1 otherwise.
4721 Returns 0 if there are outgoing changes, 1 otherwise.
4718 """
4722 """
4719 if opts.get('graph'):
4723 if opts.get('graph'):
4720 cmdutil.checkunsupportedgraphflags([], opts)
4724 cmdutil.checkunsupportedgraphflags([], opts)
4721 o, other = hg._outgoing(ui, repo, dest, opts)
4725 o, other = hg._outgoing(ui, repo, dest, opts)
4722 if not o:
4726 if not o:
4723 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4727 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4724 return
4728 return
4725
4729
4726 revdag = cmdutil.graphrevs(repo, o, opts)
4730 revdag = cmdutil.graphrevs(repo, o, opts)
4727 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4731 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4728 showparents = [ctx.node() for ctx in repo[None].parents()]
4732 showparents = [ctx.node() for ctx in repo[None].parents()]
4729 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4733 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4730 graphmod.asciiedges)
4734 graphmod.asciiedges)
4731 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4735 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4732 return 0
4736 return 0
4733
4737
4734 if opts.get('bookmarks'):
4738 if opts.get('bookmarks'):
4735 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4739 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4736 dest, branches = hg.parseurl(dest, opts.get('branch'))
4740 dest, branches = hg.parseurl(dest, opts.get('branch'))
4737 other = hg.peer(repo, opts, dest)
4741 other = hg.peer(repo, opts, dest)
4738 if 'bookmarks' not in other.listkeys('namespaces'):
4742 if 'bookmarks' not in other.listkeys('namespaces'):
4739 ui.warn(_("remote doesn't support bookmarks\n"))
4743 ui.warn(_("remote doesn't support bookmarks\n"))
4740 return 0
4744 return 0
4741 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4745 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4742 return bookmarks.diff(ui, other, repo)
4746 return bookmarks.diff(ui, other, repo)
4743
4747
4744 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4748 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4745 try:
4749 try:
4746 return hg.outgoing(ui, repo, dest, opts)
4750 return hg.outgoing(ui, repo, dest, opts)
4747 finally:
4751 finally:
4748 del repo._subtoppath
4752 del repo._subtoppath
4749
4753
4750 @command('parents',
4754 @command('parents',
4751 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4755 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4752 ] + templateopts,
4756 ] + templateopts,
4753 _('[-r REV] [FILE]'),
4757 _('[-r REV] [FILE]'),
4754 inferrepo=True)
4758 inferrepo=True)
4755 def parents(ui, repo, file_=None, **opts):
4759 def parents(ui, repo, file_=None, **opts):
4756 """show the parents of the working directory or revision (DEPRECATED)
4760 """show the parents of the working directory or revision (DEPRECATED)
4757
4761
4758 Print the working directory's parent revisions. If a revision is
4762 Print the working directory's parent revisions. If a revision is
4759 given via -r/--rev, the parent of that revision will be printed.
4763 given via -r/--rev, the parent of that revision will be printed.
4760 If a file argument is given, the revision in which the file was
4764 If a file argument is given, the revision in which the file was
4761 last changed (before the working directory revision or the
4765 last changed (before the working directory revision or the
4762 argument to --rev if given) is printed.
4766 argument to --rev if given) is printed.
4763
4767
4764 See :hg:`summary` and :hg:`help revsets` for related information.
4768 See :hg:`summary` and :hg:`help revsets` for related information.
4765
4769
4766 Returns 0 on success.
4770 Returns 0 on success.
4767 """
4771 """
4768
4772
4769 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4773 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4770
4774
4771 if file_:
4775 if file_:
4772 m = scmutil.match(ctx, (file_,), opts)
4776 m = scmutil.match(ctx, (file_,), opts)
4773 if m.anypats() or len(m.files()) != 1:
4777 if m.anypats() or len(m.files()) != 1:
4774 raise util.Abort(_('can only specify an explicit filename'))
4778 raise util.Abort(_('can only specify an explicit filename'))
4775 file_ = m.files()[0]
4779 file_ = m.files()[0]
4776 filenodes = []
4780 filenodes = []
4777 for cp in ctx.parents():
4781 for cp in ctx.parents():
4778 if not cp:
4782 if not cp:
4779 continue
4783 continue
4780 try:
4784 try:
4781 filenodes.append(cp.filenode(file_))
4785 filenodes.append(cp.filenode(file_))
4782 except error.LookupError:
4786 except error.LookupError:
4783 pass
4787 pass
4784 if not filenodes:
4788 if not filenodes:
4785 raise util.Abort(_("'%s' not found in manifest!") % file_)
4789 raise util.Abort(_("'%s' not found in manifest!") % file_)
4786 p = []
4790 p = []
4787 for fn in filenodes:
4791 for fn in filenodes:
4788 fctx = repo.filectx(file_, fileid=fn)
4792 fctx = repo.filectx(file_, fileid=fn)
4789 p.append(fctx.node())
4793 p.append(fctx.node())
4790 else:
4794 else:
4791 p = [cp.node() for cp in ctx.parents()]
4795 p = [cp.node() for cp in ctx.parents()]
4792
4796
4793 displayer = cmdutil.show_changeset(ui, repo, opts)
4797 displayer = cmdutil.show_changeset(ui, repo, opts)
4794 for n in p:
4798 for n in p:
4795 if n != nullid:
4799 if n != nullid:
4796 displayer.show(repo[n])
4800 displayer.show(repo[n])
4797 displayer.close()
4801 displayer.close()
4798
4802
4799 @command('paths', [], _('[NAME]'), optionalrepo=True)
4803 @command('paths', [], _('[NAME]'), optionalrepo=True)
4800 def paths(ui, repo, search=None):
4804 def paths(ui, repo, search=None):
4801 """show aliases for remote repositories
4805 """show aliases for remote repositories
4802
4806
4803 Show definition of symbolic path name NAME. If no name is given,
4807 Show definition of symbolic path name NAME. If no name is given,
4804 show definition of all available names.
4808 show definition of all available names.
4805
4809
4806 Option -q/--quiet suppresses all output when searching for NAME
4810 Option -q/--quiet suppresses all output when searching for NAME
4807 and shows only the path names when listing all definitions.
4811 and shows only the path names when listing all definitions.
4808
4812
4809 Path names are defined in the [paths] section of your
4813 Path names are defined in the [paths] section of your
4810 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4814 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4811 repository, ``.hg/hgrc`` is used, too.
4815 repository, ``.hg/hgrc`` is used, too.
4812
4816
4813 The path names ``default`` and ``default-push`` have a special
4817 The path names ``default`` and ``default-push`` have a special
4814 meaning. When performing a push or pull operation, they are used
4818 meaning. When performing a push or pull operation, they are used
4815 as fallbacks if no location is specified on the command-line.
4819 as fallbacks if no location is specified on the command-line.
4816 When ``default-push`` is set, it will be used for push and
4820 When ``default-push`` is set, it will be used for push and
4817 ``default`` will be used for pull; otherwise ``default`` is used
4821 ``default`` will be used for pull; otherwise ``default`` is used
4818 as the fallback for both. When cloning a repository, the clone
4822 as the fallback for both. When cloning a repository, the clone
4819 source is written as ``default`` in ``.hg/hgrc``. Note that
4823 source is written as ``default`` in ``.hg/hgrc``. Note that
4820 ``default`` and ``default-push`` apply to all inbound (e.g.
4824 ``default`` and ``default-push`` apply to all inbound (e.g.
4821 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4825 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4822 :hg:`bundle`) operations.
4826 :hg:`bundle`) operations.
4823
4827
4824 See :hg:`help urls` for more information.
4828 See :hg:`help urls` for more information.
4825
4829
4826 Returns 0 on success.
4830 Returns 0 on success.
4827 """
4831 """
4828 if search:
4832 if search:
4829 for name, path in sorted(ui.paths.iteritems()):
4833 for name, path in sorted(ui.paths.iteritems()):
4830 if name == search:
4834 if name == search:
4831 ui.status("%s\n" % util.hidepassword(path.loc))
4835 ui.status("%s\n" % util.hidepassword(path.loc))
4832 return
4836 return
4833 if not ui.quiet:
4837 if not ui.quiet:
4834 ui.warn(_("not found!\n"))
4838 ui.warn(_("not found!\n"))
4835 return 1
4839 return 1
4836 else:
4840 else:
4837 for name, path in sorted(ui.paths.iteritems()):
4841 for name, path in sorted(ui.paths.iteritems()):
4838 if ui.quiet:
4842 if ui.quiet:
4839 ui.write("%s\n" % name)
4843 ui.write("%s\n" % name)
4840 else:
4844 else:
4841 ui.write("%s = %s\n" % (name,
4845 ui.write("%s = %s\n" % (name,
4842 util.hidepassword(path.loc)))
4846 util.hidepassword(path.loc)))
4843
4847
4844 @command('phase',
4848 @command('phase',
4845 [('p', 'public', False, _('set changeset phase to public')),
4849 [('p', 'public', False, _('set changeset phase to public')),
4846 ('d', 'draft', False, _('set changeset phase to draft')),
4850 ('d', 'draft', False, _('set changeset phase to draft')),
4847 ('s', 'secret', False, _('set changeset phase to secret')),
4851 ('s', 'secret', False, _('set changeset phase to secret')),
4848 ('f', 'force', False, _('allow to move boundary backward')),
4852 ('f', 'force', False, _('allow to move boundary backward')),
4849 ('r', 'rev', [], _('target revision'), _('REV')),
4853 ('r', 'rev', [], _('target revision'), _('REV')),
4850 ],
4854 ],
4851 _('[-p|-d|-s] [-f] [-r] REV...'))
4855 _('[-p|-d|-s] [-f] [-r] REV...'))
4852 def phase(ui, repo, *revs, **opts):
4856 def phase(ui, repo, *revs, **opts):
4853 """set or show the current phase name
4857 """set or show the current phase name
4854
4858
4855 With no argument, show the phase name of specified revisions.
4859 With no argument, show the phase name of specified revisions.
4856
4860
4857 With one of -p/--public, -d/--draft or -s/--secret, change the
4861 With one of -p/--public, -d/--draft or -s/--secret, change the
4858 phase value of the specified revisions.
4862 phase value of the specified revisions.
4859
4863
4860 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4864 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4861 lower phase to an higher phase. Phases are ordered as follows::
4865 lower phase to an higher phase. Phases are ordered as follows::
4862
4866
4863 public < draft < secret
4867 public < draft < secret
4864
4868
4865 Returns 0 on success, 1 if no phases were changed or some could not
4869 Returns 0 on success, 1 if no phases were changed or some could not
4866 be changed.
4870 be changed.
4867 """
4871 """
4868 # search for a unique phase argument
4872 # search for a unique phase argument
4869 targetphase = None
4873 targetphase = None
4870 for idx, name in enumerate(phases.phasenames):
4874 for idx, name in enumerate(phases.phasenames):
4871 if opts[name]:
4875 if opts[name]:
4872 if targetphase is not None:
4876 if targetphase is not None:
4873 raise util.Abort(_('only one phase can be specified'))
4877 raise util.Abort(_('only one phase can be specified'))
4874 targetphase = idx
4878 targetphase = idx
4875
4879
4876 # look for specified revision
4880 # look for specified revision
4877 revs = list(revs)
4881 revs = list(revs)
4878 revs.extend(opts['rev'])
4882 revs.extend(opts['rev'])
4879 if not revs:
4883 if not revs:
4880 raise util.Abort(_('no revisions specified'))
4884 raise util.Abort(_('no revisions specified'))
4881
4885
4882 revs = scmutil.revrange(repo, revs)
4886 revs = scmutil.revrange(repo, revs)
4883
4887
4884 lock = None
4888 lock = None
4885 ret = 0
4889 ret = 0
4886 if targetphase is None:
4890 if targetphase is None:
4887 # display
4891 # display
4888 for r in revs:
4892 for r in revs:
4889 ctx = repo[r]
4893 ctx = repo[r]
4890 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4894 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4891 else:
4895 else:
4892 tr = None
4896 tr = None
4893 lock = repo.lock()
4897 lock = repo.lock()
4894 try:
4898 try:
4895 tr = repo.transaction("phase")
4899 tr = repo.transaction("phase")
4896 # set phase
4900 # set phase
4897 if not revs:
4901 if not revs:
4898 raise util.Abort(_('empty revision set'))
4902 raise util.Abort(_('empty revision set'))
4899 nodes = [repo[r].node() for r in revs]
4903 nodes = [repo[r].node() for r in revs]
4900 # moving revision from public to draft may hide them
4904 # moving revision from public to draft may hide them
4901 # We have to check result on an unfiltered repository
4905 # We have to check result on an unfiltered repository
4902 unfi = repo.unfiltered()
4906 unfi = repo.unfiltered()
4903 getphase = unfi._phasecache.phase
4907 getphase = unfi._phasecache.phase
4904 olddata = [getphase(unfi, r) for r in unfi]
4908 olddata = [getphase(unfi, r) for r in unfi]
4905 phases.advanceboundary(repo, tr, targetphase, nodes)
4909 phases.advanceboundary(repo, tr, targetphase, nodes)
4906 if opts['force']:
4910 if opts['force']:
4907 phases.retractboundary(repo, tr, targetphase, nodes)
4911 phases.retractboundary(repo, tr, targetphase, nodes)
4908 tr.close()
4912 tr.close()
4909 finally:
4913 finally:
4910 if tr is not None:
4914 if tr is not None:
4911 tr.release()
4915 tr.release()
4912 lock.release()
4916 lock.release()
4913 getphase = unfi._phasecache.phase
4917 getphase = unfi._phasecache.phase
4914 newdata = [getphase(unfi, r) for r in unfi]
4918 newdata = [getphase(unfi, r) for r in unfi]
4915 changes = sum(newdata[r] != olddata[r] for r in unfi)
4919 changes = sum(newdata[r] != olddata[r] for r in unfi)
4916 cl = unfi.changelog
4920 cl = unfi.changelog
4917 rejected = [n for n in nodes
4921 rejected = [n for n in nodes
4918 if newdata[cl.rev(n)] < targetphase]
4922 if newdata[cl.rev(n)] < targetphase]
4919 if rejected:
4923 if rejected:
4920 ui.warn(_('cannot move %i changesets to a higher '
4924 ui.warn(_('cannot move %i changesets to a higher '
4921 'phase, use --force\n') % len(rejected))
4925 'phase, use --force\n') % len(rejected))
4922 ret = 1
4926 ret = 1
4923 if changes:
4927 if changes:
4924 msg = _('phase changed for %i changesets\n') % changes
4928 msg = _('phase changed for %i changesets\n') % changes
4925 if ret:
4929 if ret:
4926 ui.status(msg)
4930 ui.status(msg)
4927 else:
4931 else:
4928 ui.note(msg)
4932 ui.note(msg)
4929 else:
4933 else:
4930 ui.warn(_('no phases changed\n'))
4934 ui.warn(_('no phases changed\n'))
4931 ret = 1
4935 ret = 1
4932 return ret
4936 return ret
4933
4937
4934 def postincoming(ui, repo, modheads, optupdate, checkout):
4938 def postincoming(ui, repo, modheads, optupdate, checkout):
4935 if modheads == 0:
4939 if modheads == 0:
4936 return
4940 return
4937 if optupdate:
4941 if optupdate:
4938 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4942 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4939 try:
4943 try:
4940 ret = hg.update(repo, checkout)
4944 ret = hg.update(repo, checkout)
4941 except util.Abort, inst:
4945 except util.Abort, inst:
4942 ui.warn(_("not updating: %s\n") % str(inst))
4946 ui.warn(_("not updating: %s\n") % str(inst))
4943 if inst.hint:
4947 if inst.hint:
4944 ui.warn(_("(%s)\n") % inst.hint)
4948 ui.warn(_("(%s)\n") % inst.hint)
4945 return 0
4949 return 0
4946 if not ret and not checkout:
4950 if not ret and not checkout:
4947 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4951 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4948 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4952 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4949 return ret
4953 return ret
4950 if modheads > 1:
4954 if modheads > 1:
4951 currentbranchheads = len(repo.branchheads())
4955 currentbranchheads = len(repo.branchheads())
4952 if currentbranchheads == modheads:
4956 if currentbranchheads == modheads:
4953 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4957 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4954 elif currentbranchheads > 1:
4958 elif currentbranchheads > 1:
4955 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4959 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4956 "merge)\n"))
4960 "merge)\n"))
4957 else:
4961 else:
4958 ui.status(_("(run 'hg heads' to see heads)\n"))
4962 ui.status(_("(run 'hg heads' to see heads)\n"))
4959 else:
4963 else:
4960 ui.status(_("(run 'hg update' to get a working copy)\n"))
4964 ui.status(_("(run 'hg update' to get a working copy)\n"))
4961
4965
4962 @command('^pull',
4966 @command('^pull',
4963 [('u', 'update', None,
4967 [('u', 'update', None,
4964 _('update to new branch head if changesets were pulled')),
4968 _('update to new branch head if changesets were pulled')),
4965 ('f', 'force', None, _('run even when remote repository is unrelated')),
4969 ('f', 'force', None, _('run even when remote repository is unrelated')),
4966 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4970 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4967 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4971 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4968 ('b', 'branch', [], _('a specific branch you would like to pull'),
4972 ('b', 'branch', [], _('a specific branch you would like to pull'),
4969 _('BRANCH')),
4973 _('BRANCH')),
4970 ] + remoteopts,
4974 ] + remoteopts,
4971 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4975 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4972 def pull(ui, repo, source="default", **opts):
4976 def pull(ui, repo, source="default", **opts):
4973 """pull changes from the specified source
4977 """pull changes from the specified source
4974
4978
4975 Pull changes from a remote repository to a local one.
4979 Pull changes from a remote repository to a local one.
4976
4980
4977 This finds all changes from the repository at the specified path
4981 This finds all changes from the repository at the specified path
4978 or URL and adds them to a local repository (the current one unless
4982 or URL and adds them to a local repository (the current one unless
4979 -R is specified). By default, this does not update the copy of the
4983 -R is specified). By default, this does not update the copy of the
4980 project in the working directory.
4984 project in the working directory.
4981
4985
4982 Use :hg:`incoming` if you want to see what would have been added
4986 Use :hg:`incoming` if you want to see what would have been added
4983 by a pull at the time you issued this command. If you then decide
4987 by a pull at the time you issued this command. If you then decide
4984 to add those changes to the repository, you should use :hg:`pull
4988 to add those changes to the repository, you should use :hg:`pull
4985 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4989 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4986
4990
4987 If SOURCE is omitted, the 'default' path will be used.
4991 If SOURCE is omitted, the 'default' path will be used.
4988 See :hg:`help urls` for more information.
4992 See :hg:`help urls` for more information.
4989
4993
4990 Returns 0 on success, 1 if an update had unresolved files.
4994 Returns 0 on success, 1 if an update had unresolved files.
4991 """
4995 """
4992 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4996 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4993 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4997 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4994 other = hg.peer(repo, opts, source)
4998 other = hg.peer(repo, opts, source)
4995 try:
4999 try:
4996 revs, checkout = hg.addbranchrevs(repo, other, branches,
5000 revs, checkout = hg.addbranchrevs(repo, other, branches,
4997 opts.get('rev'))
5001 opts.get('rev'))
4998
5002
4999 remotebookmarks = other.listkeys('bookmarks')
5003 remotebookmarks = other.listkeys('bookmarks')
5000
5004
5001 if opts.get('bookmark'):
5005 if opts.get('bookmark'):
5002 if not revs:
5006 if not revs:
5003 revs = []
5007 revs = []
5004 for b in opts['bookmark']:
5008 for b in opts['bookmark']:
5005 if b not in remotebookmarks:
5009 if b not in remotebookmarks:
5006 raise util.Abort(_('remote bookmark %s not found!') % b)
5010 raise util.Abort(_('remote bookmark %s not found!') % b)
5007 revs.append(remotebookmarks[b])
5011 revs.append(remotebookmarks[b])
5008
5012
5009 if revs:
5013 if revs:
5010 try:
5014 try:
5011 revs = [other.lookup(rev) for rev in revs]
5015 revs = [other.lookup(rev) for rev in revs]
5012 except error.CapabilityError:
5016 except error.CapabilityError:
5013 err = _("other repository doesn't support revision lookup, "
5017 err = _("other repository doesn't support revision lookup, "
5014 "so a rev cannot be specified.")
5018 "so a rev cannot be specified.")
5015 raise util.Abort(err)
5019 raise util.Abort(err)
5016
5020
5017 modheads = exchange.pull(repo, other, heads=revs,
5021 modheads = exchange.pull(repo, other, heads=revs,
5018 force=opts.get('force'),
5022 force=opts.get('force'),
5019 bookmarks=opts.get('bookmark', ())).cgresult
5023 bookmarks=opts.get('bookmark', ())).cgresult
5020 if checkout:
5024 if checkout:
5021 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5025 checkout = str(repo.changelog.rev(other.lookup(checkout)))
5022 repo._subtoppath = source
5026 repo._subtoppath = source
5023 try:
5027 try:
5024 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5028 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5025
5029
5026 finally:
5030 finally:
5027 del repo._subtoppath
5031 del repo._subtoppath
5028
5032
5029 finally:
5033 finally:
5030 other.close()
5034 other.close()
5031 return ret
5035 return ret
5032
5036
5033 @command('^push',
5037 @command('^push',
5034 [('f', 'force', None, _('force push')),
5038 [('f', 'force', None, _('force push')),
5035 ('r', 'rev', [],
5039 ('r', 'rev', [],
5036 _('a changeset intended to be included in the destination'),
5040 _('a changeset intended to be included in the destination'),
5037 _('REV')),
5041 _('REV')),
5038 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5042 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5039 ('b', 'branch', [],
5043 ('b', 'branch', [],
5040 _('a specific branch you would like to push'), _('BRANCH')),
5044 _('a specific branch you would like to push'), _('BRANCH')),
5041 ('', 'new-branch', False, _('allow pushing a new branch')),
5045 ('', 'new-branch', False, _('allow pushing a new branch')),
5042 ] + remoteopts,
5046 ] + remoteopts,
5043 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5047 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5044 def push(ui, repo, dest=None, **opts):
5048 def push(ui, repo, dest=None, **opts):
5045 """push changes to the specified destination
5049 """push changes to the specified destination
5046
5050
5047 Push changesets from the local repository to the specified
5051 Push changesets from the local repository to the specified
5048 destination.
5052 destination.
5049
5053
5050 This operation is symmetrical to pull: it is identical to a pull
5054 This operation is symmetrical to pull: it is identical to a pull
5051 in the destination repository from the current one.
5055 in the destination repository from the current one.
5052
5056
5053 By default, push will not allow creation of new heads at the
5057 By default, push will not allow creation of new heads at the
5054 destination, since multiple heads would make it unclear which head
5058 destination, since multiple heads would make it unclear which head
5055 to use. In this situation, it is recommended to pull and merge
5059 to use. In this situation, it is recommended to pull and merge
5056 before pushing.
5060 before pushing.
5057
5061
5058 Use --new-branch if you want to allow push to create a new named
5062 Use --new-branch if you want to allow push to create a new named
5059 branch that is not present at the destination. This allows you to
5063 branch that is not present at the destination. This allows you to
5060 only create a new branch without forcing other changes.
5064 only create a new branch without forcing other changes.
5061
5065
5062 .. note::
5066 .. note::
5063
5067
5064 Extra care should be taken with the -f/--force option,
5068 Extra care should be taken with the -f/--force option,
5065 which will push all new heads on all branches, an action which will
5069 which will push all new heads on all branches, an action which will
5066 almost always cause confusion for collaborators.
5070 almost always cause confusion for collaborators.
5067
5071
5068 If -r/--rev is used, the specified revision and all its ancestors
5072 If -r/--rev is used, the specified revision and all its ancestors
5069 will be pushed to the remote repository.
5073 will be pushed to the remote repository.
5070
5074
5071 If -B/--bookmark is used, the specified bookmarked revision, its
5075 If -B/--bookmark is used, the specified bookmarked revision, its
5072 ancestors, and the bookmark will be pushed to the remote
5076 ancestors, and the bookmark will be pushed to the remote
5073 repository.
5077 repository.
5074
5078
5075 Please see :hg:`help urls` for important details about ``ssh://``
5079 Please see :hg:`help urls` for important details about ``ssh://``
5076 URLs. If DESTINATION is omitted, a default path will be used.
5080 URLs. If DESTINATION is omitted, a default path will be used.
5077
5081
5078 Returns 0 if push was successful, 1 if nothing to push.
5082 Returns 0 if push was successful, 1 if nothing to push.
5079 """
5083 """
5080
5084
5081 if opts.get('bookmark'):
5085 if opts.get('bookmark'):
5082 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5086 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5083 for b in opts['bookmark']:
5087 for b in opts['bookmark']:
5084 # translate -B options to -r so changesets get pushed
5088 # translate -B options to -r so changesets get pushed
5085 if b in repo._bookmarks:
5089 if b in repo._bookmarks:
5086 opts.setdefault('rev', []).append(b)
5090 opts.setdefault('rev', []).append(b)
5087 else:
5091 else:
5088 # if we try to push a deleted bookmark, translate it to null
5092 # if we try to push a deleted bookmark, translate it to null
5089 # this lets simultaneous -r, -b options continue working
5093 # this lets simultaneous -r, -b options continue working
5090 opts.setdefault('rev', []).append("null")
5094 opts.setdefault('rev', []).append("null")
5091
5095
5092 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5096 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5093 dest, branches = hg.parseurl(dest, opts.get('branch'))
5097 dest, branches = hg.parseurl(dest, opts.get('branch'))
5094 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5098 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5095 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5099 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5096 try:
5100 try:
5097 other = hg.peer(repo, opts, dest)
5101 other = hg.peer(repo, opts, dest)
5098 except error.RepoError:
5102 except error.RepoError:
5099 if dest == "default-push":
5103 if dest == "default-push":
5100 raise util.Abort(_("default repository not configured!"),
5104 raise util.Abort(_("default repository not configured!"),
5101 hint=_('see the "path" section in "hg help config"'))
5105 hint=_('see the "path" section in "hg help config"'))
5102 else:
5106 else:
5103 raise
5107 raise
5104
5108
5105 if revs:
5109 if revs:
5106 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5110 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5107
5111
5108 repo._subtoppath = dest
5112 repo._subtoppath = dest
5109 try:
5113 try:
5110 # push subrepos depth-first for coherent ordering
5114 # push subrepos depth-first for coherent ordering
5111 c = repo['']
5115 c = repo['']
5112 subs = c.substate # only repos that are committed
5116 subs = c.substate # only repos that are committed
5113 for s in sorted(subs):
5117 for s in sorted(subs):
5114 result = c.sub(s).push(opts)
5118 result = c.sub(s).push(opts)
5115 if result == 0:
5119 if result == 0:
5116 return not result
5120 return not result
5117 finally:
5121 finally:
5118 del repo._subtoppath
5122 del repo._subtoppath
5119 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5123 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5120 newbranch=opts.get('new_branch'),
5124 newbranch=opts.get('new_branch'),
5121 bookmarks=opts.get('bookmark', ()))
5125 bookmarks=opts.get('bookmark', ()))
5122
5126
5123 result = not pushop.cgresult
5127 result = not pushop.cgresult
5124
5128
5125 if pushop.bkresult is not None:
5129 if pushop.bkresult is not None:
5126 if pushop.bkresult == 2:
5130 if pushop.bkresult == 2:
5127 result = 2
5131 result = 2
5128 elif not result and pushop.bkresult:
5132 elif not result and pushop.bkresult:
5129 result = 2
5133 result = 2
5130
5134
5131 return result
5135 return result
5132
5136
5133 @command('recover', [])
5137 @command('recover', [])
5134 def recover(ui, repo):
5138 def recover(ui, repo):
5135 """roll back an interrupted transaction
5139 """roll back an interrupted transaction
5136
5140
5137 Recover from an interrupted commit or pull.
5141 Recover from an interrupted commit or pull.
5138
5142
5139 This command tries to fix the repository status after an
5143 This command tries to fix the repository status after an
5140 interrupted operation. It should only be necessary when Mercurial
5144 interrupted operation. It should only be necessary when Mercurial
5141 suggests it.
5145 suggests it.
5142
5146
5143 Returns 0 if successful, 1 if nothing to recover or verify fails.
5147 Returns 0 if successful, 1 if nothing to recover or verify fails.
5144 """
5148 """
5145 if repo.recover():
5149 if repo.recover():
5146 return hg.verify(repo)
5150 return hg.verify(repo)
5147 return 1
5151 return 1
5148
5152
5149 @command('^remove|rm',
5153 @command('^remove|rm',
5150 [('A', 'after', None, _('record delete for missing files')),
5154 [('A', 'after', None, _('record delete for missing files')),
5151 ('f', 'force', None,
5155 ('f', 'force', None,
5152 _('remove (and delete) file even if added or modified')),
5156 _('remove (and delete) file even if added or modified')),
5153 ] + subrepoopts + walkopts,
5157 ] + subrepoopts + walkopts,
5154 _('[OPTION]... FILE...'),
5158 _('[OPTION]... FILE...'),
5155 inferrepo=True)
5159 inferrepo=True)
5156 def remove(ui, repo, *pats, **opts):
5160 def remove(ui, repo, *pats, **opts):
5157 """remove the specified files on the next commit
5161 """remove the specified files on the next commit
5158
5162
5159 Schedule the indicated files for removal from the current branch.
5163 Schedule the indicated files for removal from the current branch.
5160
5164
5161 This command schedules the files to be removed at the next commit.
5165 This command schedules the files to be removed at the next commit.
5162 To undo a remove before that, see :hg:`revert`. To undo added
5166 To undo a remove before that, see :hg:`revert`. To undo added
5163 files, see :hg:`forget`.
5167 files, see :hg:`forget`.
5164
5168
5165 .. container:: verbose
5169 .. container:: verbose
5166
5170
5167 -A/--after can be used to remove only files that have already
5171 -A/--after can be used to remove only files that have already
5168 been deleted, -f/--force can be used to force deletion, and -Af
5172 been deleted, -f/--force can be used to force deletion, and -Af
5169 can be used to remove files from the next revision without
5173 can be used to remove files from the next revision without
5170 deleting them from the working directory.
5174 deleting them from the working directory.
5171
5175
5172 The following table details the behavior of remove for different
5176 The following table details the behavior of remove for different
5173 file states (columns) and option combinations (rows). The file
5177 file states (columns) and option combinations (rows). The file
5174 states are Added [A], Clean [C], Modified [M] and Missing [!]
5178 states are Added [A], Clean [C], Modified [M] and Missing [!]
5175 (as reported by :hg:`status`). The actions are Warn, Remove
5179 (as reported by :hg:`status`). The actions are Warn, Remove
5176 (from branch) and Delete (from disk):
5180 (from branch) and Delete (from disk):
5177
5181
5178 ========= == == == ==
5182 ========= == == == ==
5179 opt/state A C M !
5183 opt/state A C M !
5180 ========= == == == ==
5184 ========= == == == ==
5181 none W RD W R
5185 none W RD W R
5182 -f R RD RD R
5186 -f R RD RD R
5183 -A W W W R
5187 -A W W W R
5184 -Af R R R R
5188 -Af R R R R
5185 ========= == == == ==
5189 ========= == == == ==
5186
5190
5187 Note that remove never deletes files in Added [A] state from the
5191 Note that remove never deletes files in Added [A] state from the
5188 working directory, not even if option --force is specified.
5192 working directory, not even if option --force is specified.
5189
5193
5190 Returns 0 on success, 1 if any warnings encountered.
5194 Returns 0 on success, 1 if any warnings encountered.
5191 """
5195 """
5192
5196
5193 after, force = opts.get('after'), opts.get('force')
5197 after, force = opts.get('after'), opts.get('force')
5194 if not pats and not after:
5198 if not pats and not after:
5195 raise util.Abort(_('no files specified'))
5199 raise util.Abort(_('no files specified'))
5196
5200
5197 m = scmutil.match(repo[None], pats, opts)
5201 m = scmutil.match(repo[None], pats, opts)
5198 subrepos = opts.get('subrepos')
5202 subrepos = opts.get('subrepos')
5199 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5203 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5200
5204
5201 @command('rename|move|mv',
5205 @command('rename|move|mv',
5202 [('A', 'after', None, _('record a rename that has already occurred')),
5206 [('A', 'after', None, _('record a rename that has already occurred')),
5203 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5207 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5204 ] + walkopts + dryrunopts,
5208 ] + walkopts + dryrunopts,
5205 _('[OPTION]... SOURCE... DEST'))
5209 _('[OPTION]... SOURCE... DEST'))
5206 def rename(ui, repo, *pats, **opts):
5210 def rename(ui, repo, *pats, **opts):
5207 """rename files; equivalent of copy + remove
5211 """rename files; equivalent of copy + remove
5208
5212
5209 Mark dest as copies of sources; mark sources for deletion. If dest
5213 Mark dest as copies of sources; mark sources for deletion. If dest
5210 is a directory, copies are put in that directory. If dest is a
5214 is a directory, copies are put in that directory. If dest is a
5211 file, there can only be one source.
5215 file, there can only be one source.
5212
5216
5213 By default, this command copies the contents of files as they
5217 By default, this command copies the contents of files as they
5214 exist in the working directory. If invoked with -A/--after, the
5218 exist in the working directory. If invoked with -A/--after, the
5215 operation is recorded, but no copying is performed.
5219 operation is recorded, but no copying is performed.
5216
5220
5217 This command takes effect at the next commit. To undo a rename
5221 This command takes effect at the next commit. To undo a rename
5218 before that, see :hg:`revert`.
5222 before that, see :hg:`revert`.
5219
5223
5220 Returns 0 on success, 1 if errors are encountered.
5224 Returns 0 on success, 1 if errors are encountered.
5221 """
5225 """
5222 wlock = repo.wlock(False)
5226 wlock = repo.wlock(False)
5223 try:
5227 try:
5224 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5228 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5225 finally:
5229 finally:
5226 wlock.release()
5230 wlock.release()
5227
5231
5228 @command('resolve',
5232 @command('resolve',
5229 [('a', 'all', None, _('select all unresolved files')),
5233 [('a', 'all', None, _('select all unresolved files')),
5230 ('l', 'list', None, _('list state of files needing merge')),
5234 ('l', 'list', None, _('list state of files needing merge')),
5231 ('m', 'mark', None, _('mark files as resolved')),
5235 ('m', 'mark', None, _('mark files as resolved')),
5232 ('u', 'unmark', None, _('mark files as unresolved')),
5236 ('u', 'unmark', None, _('mark files as unresolved')),
5233 ('n', 'no-status', None, _('hide status prefix'))]
5237 ('n', 'no-status', None, _('hide status prefix'))]
5234 + mergetoolopts + walkopts + formatteropts,
5238 + mergetoolopts + walkopts + formatteropts,
5235 _('[OPTION]... [FILE]...'),
5239 _('[OPTION]... [FILE]...'),
5236 inferrepo=True)
5240 inferrepo=True)
5237 def resolve(ui, repo, *pats, **opts):
5241 def resolve(ui, repo, *pats, **opts):
5238 """redo merges or set/view the merge status of files
5242 """redo merges or set/view the merge status of files
5239
5243
5240 Merges with unresolved conflicts are often the result of
5244 Merges with unresolved conflicts are often the result of
5241 non-interactive merging using the ``internal:merge`` configuration
5245 non-interactive merging using the ``internal:merge`` configuration
5242 setting, or a command-line merge tool like ``diff3``. The resolve
5246 setting, or a command-line merge tool like ``diff3``. The resolve
5243 command is used to manage the files involved in a merge, after
5247 command is used to manage the files involved in a merge, after
5244 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5248 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5245 working directory must have two parents). See :hg:`help
5249 working directory must have two parents). See :hg:`help
5246 merge-tools` for information on configuring merge tools.
5250 merge-tools` for information on configuring merge tools.
5247
5251
5248 The resolve command can be used in the following ways:
5252 The resolve command can be used in the following ways:
5249
5253
5250 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5254 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5251 files, discarding any previous merge attempts. Re-merging is not
5255 files, discarding any previous merge attempts. Re-merging is not
5252 performed for files already marked as resolved. Use ``--all/-a``
5256 performed for files already marked as resolved. Use ``--all/-a``
5253 to select all unresolved files. ``--tool`` can be used to specify
5257 to select all unresolved files. ``--tool`` can be used to specify
5254 the merge tool used for the given files. It overrides the HGMERGE
5258 the merge tool used for the given files. It overrides the HGMERGE
5255 environment variable and your configuration files. Previous file
5259 environment variable and your configuration files. Previous file
5256 contents are saved with a ``.orig`` suffix.
5260 contents are saved with a ``.orig`` suffix.
5257
5261
5258 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5262 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5259 (e.g. after having manually fixed-up the files). The default is
5263 (e.g. after having manually fixed-up the files). The default is
5260 to mark all unresolved files.
5264 to mark all unresolved files.
5261
5265
5262 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5266 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5263 default is to mark all resolved files.
5267 default is to mark all resolved files.
5264
5268
5265 - :hg:`resolve -l`: list files which had or still have conflicts.
5269 - :hg:`resolve -l`: list files which had or still have conflicts.
5266 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5270 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5267
5271
5268 Note that Mercurial will not let you commit files with unresolved
5272 Note that Mercurial will not let you commit files with unresolved
5269 merge conflicts. You must use :hg:`resolve -m ...` before you can
5273 merge conflicts. You must use :hg:`resolve -m ...` before you can
5270 commit after a conflicting merge.
5274 commit after a conflicting merge.
5271
5275
5272 Returns 0 on success, 1 if any files fail a resolve attempt.
5276 Returns 0 on success, 1 if any files fail a resolve attempt.
5273 """
5277 """
5274
5278
5275 all, mark, unmark, show, nostatus = \
5279 all, mark, unmark, show, nostatus = \
5276 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5280 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5277
5281
5278 if (show and (mark or unmark)) or (mark and unmark):
5282 if (show and (mark or unmark)) or (mark and unmark):
5279 raise util.Abort(_("too many options specified"))
5283 raise util.Abort(_("too many options specified"))
5280 if pats and all:
5284 if pats and all:
5281 raise util.Abort(_("can't specify --all and patterns"))
5285 raise util.Abort(_("can't specify --all and patterns"))
5282 if not (all or pats or show or mark or unmark):
5286 if not (all or pats or show or mark or unmark):
5283 raise util.Abort(_('no files or directories specified'),
5287 raise util.Abort(_('no files or directories specified'),
5284 hint=('use --all to remerge all files'))
5288 hint=('use --all to remerge all files'))
5285
5289
5286 if show:
5290 if show:
5287 fm = ui.formatter('resolve', opts)
5291 fm = ui.formatter('resolve', opts)
5288 ms = mergemod.mergestate(repo)
5292 ms = mergemod.mergestate(repo)
5289 m = scmutil.match(repo[None], pats, opts)
5293 m = scmutil.match(repo[None], pats, opts)
5290 for f in ms:
5294 for f in ms:
5291 if not m(f):
5295 if not m(f):
5292 continue
5296 continue
5293 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5297 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved'}[ms[f]]
5294 fm.startitem()
5298 fm.startitem()
5295 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5299 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5296 fm.write('path', '%s\n', f, label=l)
5300 fm.write('path', '%s\n', f, label=l)
5297 fm.end()
5301 fm.end()
5298 return 0
5302 return 0
5299
5303
5300 wlock = repo.wlock()
5304 wlock = repo.wlock()
5301 try:
5305 try:
5302 ms = mergemod.mergestate(repo)
5306 ms = mergemod.mergestate(repo)
5303
5307
5304 if not (ms.active() or repo.dirstate.p2() != nullid):
5308 if not (ms.active() or repo.dirstate.p2() != nullid):
5305 raise util.Abort(
5309 raise util.Abort(
5306 _('resolve command not applicable when not merging'))
5310 _('resolve command not applicable when not merging'))
5307
5311
5308 m = scmutil.match(repo[None], pats, opts)
5312 m = scmutil.match(repo[None], pats, opts)
5309 ret = 0
5313 ret = 0
5310 didwork = False
5314 didwork = False
5311
5315
5312 for f in ms:
5316 for f in ms:
5313 if not m(f):
5317 if not m(f):
5314 continue
5318 continue
5315
5319
5316 didwork = True
5320 didwork = True
5317
5321
5318 if mark:
5322 if mark:
5319 ms.mark(f, "r")
5323 ms.mark(f, "r")
5320 elif unmark:
5324 elif unmark:
5321 ms.mark(f, "u")
5325 ms.mark(f, "u")
5322 else:
5326 else:
5323 wctx = repo[None]
5327 wctx = repo[None]
5324
5328
5325 # backup pre-resolve (merge uses .orig for its own purposes)
5329 # backup pre-resolve (merge uses .orig for its own purposes)
5326 a = repo.wjoin(f)
5330 a = repo.wjoin(f)
5327 util.copyfile(a, a + ".resolve")
5331 util.copyfile(a, a + ".resolve")
5328
5332
5329 try:
5333 try:
5330 # resolve file
5334 # resolve file
5331 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5335 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5332 'resolve')
5336 'resolve')
5333 if ms.resolve(f, wctx):
5337 if ms.resolve(f, wctx):
5334 ret = 1
5338 ret = 1
5335 finally:
5339 finally:
5336 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5340 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5337 ms.commit()
5341 ms.commit()
5338
5342
5339 # replace filemerge's .orig file with our resolve file
5343 # replace filemerge's .orig file with our resolve file
5340 util.rename(a + ".resolve", a + ".orig")
5344 util.rename(a + ".resolve", a + ".orig")
5341
5345
5342 ms.commit()
5346 ms.commit()
5343
5347
5344 if not didwork and pats:
5348 if not didwork and pats:
5345 ui.warn(_("arguments do not match paths that need resolving\n"))
5349 ui.warn(_("arguments do not match paths that need resolving\n"))
5346
5350
5347 finally:
5351 finally:
5348 wlock.release()
5352 wlock.release()
5349
5353
5350 # Nudge users into finishing an unfinished operation
5354 # Nudge users into finishing an unfinished operation
5351 if not list(ms.unresolved()):
5355 if not list(ms.unresolved()):
5352 ui.status(_('(no more unresolved files)\n'))
5356 ui.status(_('(no more unresolved files)\n'))
5353
5357
5354 return ret
5358 return ret
5355
5359
5356 @command('revert',
5360 @command('revert',
5357 [('a', 'all', None, _('revert all changes when no arguments given')),
5361 [('a', 'all', None, _('revert all changes when no arguments given')),
5358 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5362 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5359 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5363 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5360 ('C', 'no-backup', None, _('do not save backup copies of files')),
5364 ('C', 'no-backup', None, _('do not save backup copies of files')),
5361 ] + walkopts + dryrunopts,
5365 ] + walkopts + dryrunopts,
5362 _('[OPTION]... [-r REV] [NAME]...'))
5366 _('[OPTION]... [-r REV] [NAME]...'))
5363 def revert(ui, repo, *pats, **opts):
5367 def revert(ui, repo, *pats, **opts):
5364 """restore files to their checkout state
5368 """restore files to their checkout state
5365
5369
5366 .. note::
5370 .. note::
5367
5371
5368 To check out earlier revisions, you should use :hg:`update REV`.
5372 To check out earlier revisions, you should use :hg:`update REV`.
5369 To cancel an uncommitted merge (and lose your changes),
5373 To cancel an uncommitted merge (and lose your changes),
5370 use :hg:`update --clean .`.
5374 use :hg:`update --clean .`.
5371
5375
5372 With no revision specified, revert the specified files or directories
5376 With no revision specified, revert the specified files or directories
5373 to the contents they had in the parent of the working directory.
5377 to the contents they had in the parent of the working directory.
5374 This restores the contents of files to an unmodified
5378 This restores the contents of files to an unmodified
5375 state and unschedules adds, removes, copies, and renames. If the
5379 state and unschedules adds, removes, copies, and renames. If the
5376 working directory has two parents, you must explicitly specify a
5380 working directory has two parents, you must explicitly specify a
5377 revision.
5381 revision.
5378
5382
5379 Using the -r/--rev or -d/--date options, revert the given files or
5383 Using the -r/--rev or -d/--date options, revert the given files or
5380 directories to their states as of a specific revision. Because
5384 directories to their states as of a specific revision. Because
5381 revert does not change the working directory parents, this will
5385 revert does not change the working directory parents, this will
5382 cause these files to appear modified. This can be helpful to "back
5386 cause these files to appear modified. This can be helpful to "back
5383 out" some or all of an earlier change. See :hg:`backout` for a
5387 out" some or all of an earlier change. See :hg:`backout` for a
5384 related method.
5388 related method.
5385
5389
5386 Modified files are saved with a .orig suffix before reverting.
5390 Modified files are saved with a .orig suffix before reverting.
5387 To disable these backups, use --no-backup.
5391 To disable these backups, use --no-backup.
5388
5392
5389 See :hg:`help dates` for a list of formats valid for -d/--date.
5393 See :hg:`help dates` for a list of formats valid for -d/--date.
5390
5394
5391 Returns 0 on success.
5395 Returns 0 on success.
5392 """
5396 """
5393
5397
5394 if opts.get("date"):
5398 if opts.get("date"):
5395 if opts.get("rev"):
5399 if opts.get("rev"):
5396 raise util.Abort(_("you can't specify a revision and a date"))
5400 raise util.Abort(_("you can't specify a revision and a date"))
5397 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5401 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5398
5402
5399 parent, p2 = repo.dirstate.parents()
5403 parent, p2 = repo.dirstate.parents()
5400 if not opts.get('rev') and p2 != nullid:
5404 if not opts.get('rev') and p2 != nullid:
5401 # revert after merge is a trap for new users (issue2915)
5405 # revert after merge is a trap for new users (issue2915)
5402 raise util.Abort(_('uncommitted merge with no revision specified'),
5406 raise util.Abort(_('uncommitted merge with no revision specified'),
5403 hint=_('use "hg update" or see "hg help revert"'))
5407 hint=_('use "hg update" or see "hg help revert"'))
5404
5408
5405 ctx = scmutil.revsingle(repo, opts.get('rev'))
5409 ctx = scmutil.revsingle(repo, opts.get('rev'))
5406
5410
5407 if not pats and not opts.get('all'):
5411 if not pats and not opts.get('all'):
5408 msg = _("no files or directories specified")
5412 msg = _("no files or directories specified")
5409 if p2 != nullid:
5413 if p2 != nullid:
5410 hint = _("uncommitted merge, use --all to discard all changes,"
5414 hint = _("uncommitted merge, use --all to discard all changes,"
5411 " or 'hg update -C .' to abort the merge")
5415 " or 'hg update -C .' to abort the merge")
5412 raise util.Abort(msg, hint=hint)
5416 raise util.Abort(msg, hint=hint)
5413 dirty = util.any(repo.status())
5417 dirty = util.any(repo.status())
5414 node = ctx.node()
5418 node = ctx.node()
5415 if node != parent:
5419 if node != parent:
5416 if dirty:
5420 if dirty:
5417 hint = _("uncommitted changes, use --all to discard all"
5421 hint = _("uncommitted changes, use --all to discard all"
5418 " changes, or 'hg update %s' to update") % ctx.rev()
5422 " changes, or 'hg update %s' to update") % ctx.rev()
5419 else:
5423 else:
5420 hint = _("use --all to revert all files,"
5424 hint = _("use --all to revert all files,"
5421 " or 'hg update %s' to update") % ctx.rev()
5425 " or 'hg update %s' to update") % ctx.rev()
5422 elif dirty:
5426 elif dirty:
5423 hint = _("uncommitted changes, use --all to discard all changes")
5427 hint = _("uncommitted changes, use --all to discard all changes")
5424 else:
5428 else:
5425 hint = _("use --all to revert all files")
5429 hint = _("use --all to revert all files")
5426 raise util.Abort(msg, hint=hint)
5430 raise util.Abort(msg, hint=hint)
5427
5431
5428 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5432 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5429
5433
5430 @command('rollback', dryrunopts +
5434 @command('rollback', dryrunopts +
5431 [('f', 'force', False, _('ignore safety measures'))])
5435 [('f', 'force', False, _('ignore safety measures'))])
5432 def rollback(ui, repo, **opts):
5436 def rollback(ui, repo, **opts):
5433 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5437 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5434
5438
5435 Please use :hg:`commit --amend` instead of rollback to correct
5439 Please use :hg:`commit --amend` instead of rollback to correct
5436 mistakes in the last commit.
5440 mistakes in the last commit.
5437
5441
5438 This command should be used with care. There is only one level of
5442 This command should be used with care. There is only one level of
5439 rollback, and there is no way to undo a rollback. It will also
5443 rollback, and there is no way to undo a rollback. It will also
5440 restore the dirstate at the time of the last transaction, losing
5444 restore the dirstate at the time of the last transaction, losing
5441 any dirstate changes since that time. This command does not alter
5445 any dirstate changes since that time. This command does not alter
5442 the working directory.
5446 the working directory.
5443
5447
5444 Transactions are used to encapsulate the effects of all commands
5448 Transactions are used to encapsulate the effects of all commands
5445 that create new changesets or propagate existing changesets into a
5449 that create new changesets or propagate existing changesets into a
5446 repository.
5450 repository.
5447
5451
5448 .. container:: verbose
5452 .. container:: verbose
5449
5453
5450 For example, the following commands are transactional, and their
5454 For example, the following commands are transactional, and their
5451 effects can be rolled back:
5455 effects can be rolled back:
5452
5456
5453 - commit
5457 - commit
5454 - import
5458 - import
5455 - pull
5459 - pull
5456 - push (with this repository as the destination)
5460 - push (with this repository as the destination)
5457 - unbundle
5461 - unbundle
5458
5462
5459 To avoid permanent data loss, rollback will refuse to rollback a
5463 To avoid permanent data loss, rollback will refuse to rollback a
5460 commit transaction if it isn't checked out. Use --force to
5464 commit transaction if it isn't checked out. Use --force to
5461 override this protection.
5465 override this protection.
5462
5466
5463 This command is not intended for use on public repositories. Once
5467 This command is not intended for use on public repositories. Once
5464 changes are visible for pull by other users, rolling a transaction
5468 changes are visible for pull by other users, rolling a transaction
5465 back locally is ineffective (someone else may already have pulled
5469 back locally is ineffective (someone else may already have pulled
5466 the changes). Furthermore, a race is possible with readers of the
5470 the changes). Furthermore, a race is possible with readers of the
5467 repository; for example an in-progress pull from the repository
5471 repository; for example an in-progress pull from the repository
5468 may fail if a rollback is performed.
5472 may fail if a rollback is performed.
5469
5473
5470 Returns 0 on success, 1 if no rollback data is available.
5474 Returns 0 on success, 1 if no rollback data is available.
5471 """
5475 """
5472 return repo.rollback(dryrun=opts.get('dry_run'),
5476 return repo.rollback(dryrun=opts.get('dry_run'),
5473 force=opts.get('force'))
5477 force=opts.get('force'))
5474
5478
5475 @command('root', [])
5479 @command('root', [])
5476 def root(ui, repo):
5480 def root(ui, repo):
5477 """print the root (top) of the current working directory
5481 """print the root (top) of the current working directory
5478
5482
5479 Print the root directory of the current repository.
5483 Print the root directory of the current repository.
5480
5484
5481 Returns 0 on success.
5485 Returns 0 on success.
5482 """
5486 """
5483 ui.write(repo.root + "\n")
5487 ui.write(repo.root + "\n")
5484
5488
5485 @command('^serve',
5489 @command('^serve',
5486 [('A', 'accesslog', '', _('name of access log file to write to'),
5490 [('A', 'accesslog', '', _('name of access log file to write to'),
5487 _('FILE')),
5491 _('FILE')),
5488 ('d', 'daemon', None, _('run server in background')),
5492 ('d', 'daemon', None, _('run server in background')),
5489 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5493 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5490 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5494 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5491 # use string type, then we can check if something was passed
5495 # use string type, then we can check if something was passed
5492 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5496 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5493 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5497 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5494 _('ADDR')),
5498 _('ADDR')),
5495 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5499 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5496 _('PREFIX')),
5500 _('PREFIX')),
5497 ('n', 'name', '',
5501 ('n', 'name', '',
5498 _('name to show in web pages (default: working directory)'), _('NAME')),
5502 _('name to show in web pages (default: working directory)'), _('NAME')),
5499 ('', 'web-conf', '',
5503 ('', 'web-conf', '',
5500 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5504 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5501 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5505 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5502 _('FILE')),
5506 _('FILE')),
5503 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5507 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5504 ('', 'stdio', None, _('for remote clients')),
5508 ('', 'stdio', None, _('for remote clients')),
5505 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5509 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5506 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5510 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5507 ('', 'style', '', _('template style to use'), _('STYLE')),
5511 ('', 'style', '', _('template style to use'), _('STYLE')),
5508 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5512 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5509 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5513 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5510 _('[OPTION]...'),
5514 _('[OPTION]...'),
5511 optionalrepo=True)
5515 optionalrepo=True)
5512 def serve(ui, repo, **opts):
5516 def serve(ui, repo, **opts):
5513 """start stand-alone webserver
5517 """start stand-alone webserver
5514
5518
5515 Start a local HTTP repository browser and pull server. You can use
5519 Start a local HTTP repository browser and pull server. You can use
5516 this for ad-hoc sharing and browsing of repositories. It is
5520 this for ad-hoc sharing and browsing of repositories. It is
5517 recommended to use a real web server to serve a repository for
5521 recommended to use a real web server to serve a repository for
5518 longer periods of time.
5522 longer periods of time.
5519
5523
5520 Please note that the server does not implement access control.
5524 Please note that the server does not implement access control.
5521 This means that, by default, anybody can read from the server and
5525 This means that, by default, anybody can read from the server and
5522 nobody can write to it by default. Set the ``web.allow_push``
5526 nobody can write to it by default. Set the ``web.allow_push``
5523 option to ``*`` to allow everybody to push to the server. You
5527 option to ``*`` to allow everybody to push to the server. You
5524 should use a real web server if you need to authenticate users.
5528 should use a real web server if you need to authenticate users.
5525
5529
5526 By default, the server logs accesses to stdout and errors to
5530 By default, the server logs accesses to stdout and errors to
5527 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5531 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5528 files.
5532 files.
5529
5533
5530 To have the server choose a free port number to listen on, specify
5534 To have the server choose a free port number to listen on, specify
5531 a port number of 0; in this case, the server will print the port
5535 a port number of 0; in this case, the server will print the port
5532 number it uses.
5536 number it uses.
5533
5537
5534 Returns 0 on success.
5538 Returns 0 on success.
5535 """
5539 """
5536
5540
5537 if opts["stdio"] and opts["cmdserver"]:
5541 if opts["stdio"] and opts["cmdserver"]:
5538 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5542 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5539
5543
5540 if opts["stdio"]:
5544 if opts["stdio"]:
5541 if repo is None:
5545 if repo is None:
5542 raise error.RepoError(_("there is no Mercurial repository here"
5546 raise error.RepoError(_("there is no Mercurial repository here"
5543 " (.hg not found)"))
5547 " (.hg not found)"))
5544 s = sshserver.sshserver(ui, repo)
5548 s = sshserver.sshserver(ui, repo)
5545 s.serve_forever()
5549 s.serve_forever()
5546
5550
5547 if opts["cmdserver"]:
5551 if opts["cmdserver"]:
5548 service = commandserver.createservice(ui, repo, opts)
5552 service = commandserver.createservice(ui, repo, opts)
5549 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5553 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5550
5554
5551 # this way we can check if something was given in the command-line
5555 # this way we can check if something was given in the command-line
5552 if opts.get('port'):
5556 if opts.get('port'):
5553 opts['port'] = util.getport(opts.get('port'))
5557 opts['port'] = util.getport(opts.get('port'))
5554
5558
5555 baseui = repo and repo.baseui or ui
5559 baseui = repo and repo.baseui or ui
5556 optlist = ("name templates style address port prefix ipv6"
5560 optlist = ("name templates style address port prefix ipv6"
5557 " accesslog errorlog certificate encoding")
5561 " accesslog errorlog certificate encoding")
5558 for o in optlist.split():
5562 for o in optlist.split():
5559 val = opts.get(o, '')
5563 val = opts.get(o, '')
5560 if val in (None, ''): # should check against default options instead
5564 if val in (None, ''): # should check against default options instead
5561 continue
5565 continue
5562 baseui.setconfig("web", o, val, 'serve')
5566 baseui.setconfig("web", o, val, 'serve')
5563 if repo and repo.ui != baseui:
5567 if repo and repo.ui != baseui:
5564 repo.ui.setconfig("web", o, val, 'serve')
5568 repo.ui.setconfig("web", o, val, 'serve')
5565
5569
5566 o = opts.get('web_conf') or opts.get('webdir_conf')
5570 o = opts.get('web_conf') or opts.get('webdir_conf')
5567 if not o:
5571 if not o:
5568 if not repo:
5572 if not repo:
5569 raise error.RepoError(_("there is no Mercurial repository"
5573 raise error.RepoError(_("there is no Mercurial repository"
5570 " here (.hg not found)"))
5574 " here (.hg not found)"))
5571 o = repo
5575 o = repo
5572
5576
5573 app = hgweb.hgweb(o, baseui=baseui)
5577 app = hgweb.hgweb(o, baseui=baseui)
5574 service = httpservice(ui, app, opts)
5578 service = httpservice(ui, app, opts)
5575 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5579 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5576
5580
5577 class httpservice(object):
5581 class httpservice(object):
5578 def __init__(self, ui, app, opts):
5582 def __init__(self, ui, app, opts):
5579 self.ui = ui
5583 self.ui = ui
5580 self.app = app
5584 self.app = app
5581 self.opts = opts
5585 self.opts = opts
5582
5586
5583 def init(self):
5587 def init(self):
5584 util.setsignalhandler()
5588 util.setsignalhandler()
5585 self.httpd = hgweb_server.create_server(self.ui, self.app)
5589 self.httpd = hgweb_server.create_server(self.ui, self.app)
5586
5590
5587 if self.opts['port'] and not self.ui.verbose:
5591 if self.opts['port'] and not self.ui.verbose:
5588 return
5592 return
5589
5593
5590 if self.httpd.prefix:
5594 if self.httpd.prefix:
5591 prefix = self.httpd.prefix.strip('/') + '/'
5595 prefix = self.httpd.prefix.strip('/') + '/'
5592 else:
5596 else:
5593 prefix = ''
5597 prefix = ''
5594
5598
5595 port = ':%d' % self.httpd.port
5599 port = ':%d' % self.httpd.port
5596 if port == ':80':
5600 if port == ':80':
5597 port = ''
5601 port = ''
5598
5602
5599 bindaddr = self.httpd.addr
5603 bindaddr = self.httpd.addr
5600 if bindaddr == '0.0.0.0':
5604 if bindaddr == '0.0.0.0':
5601 bindaddr = '*'
5605 bindaddr = '*'
5602 elif ':' in bindaddr: # IPv6
5606 elif ':' in bindaddr: # IPv6
5603 bindaddr = '[%s]' % bindaddr
5607 bindaddr = '[%s]' % bindaddr
5604
5608
5605 fqaddr = self.httpd.fqaddr
5609 fqaddr = self.httpd.fqaddr
5606 if ':' in fqaddr:
5610 if ':' in fqaddr:
5607 fqaddr = '[%s]' % fqaddr
5611 fqaddr = '[%s]' % fqaddr
5608 if self.opts['port']:
5612 if self.opts['port']:
5609 write = self.ui.status
5613 write = self.ui.status
5610 else:
5614 else:
5611 write = self.ui.write
5615 write = self.ui.write
5612 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5616 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5613 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5617 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5614 self.ui.flush() # avoid buffering of status message
5618 self.ui.flush() # avoid buffering of status message
5615
5619
5616 def run(self):
5620 def run(self):
5617 self.httpd.serve_forever()
5621 self.httpd.serve_forever()
5618
5622
5619
5623
5620 @command('^status|st',
5624 @command('^status|st',
5621 [('A', 'all', None, _('show status of all files')),
5625 [('A', 'all', None, _('show status of all files')),
5622 ('m', 'modified', None, _('show only modified files')),
5626 ('m', 'modified', None, _('show only modified files')),
5623 ('a', 'added', None, _('show only added files')),
5627 ('a', 'added', None, _('show only added files')),
5624 ('r', 'removed', None, _('show only removed files')),
5628 ('r', 'removed', None, _('show only removed files')),
5625 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5629 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5626 ('c', 'clean', None, _('show only files without changes')),
5630 ('c', 'clean', None, _('show only files without changes')),
5627 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5631 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5628 ('i', 'ignored', None, _('show only ignored files')),
5632 ('i', 'ignored', None, _('show only ignored files')),
5629 ('n', 'no-status', None, _('hide status prefix')),
5633 ('n', 'no-status', None, _('hide status prefix')),
5630 ('C', 'copies', None, _('show source of copied files')),
5634 ('C', 'copies', None, _('show source of copied files')),
5631 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5635 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5632 ('', 'rev', [], _('show difference from revision'), _('REV')),
5636 ('', 'rev', [], _('show difference from revision'), _('REV')),
5633 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5637 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5634 ] + walkopts + subrepoopts + formatteropts,
5638 ] + walkopts + subrepoopts + formatteropts,
5635 _('[OPTION]... [FILE]...'),
5639 _('[OPTION]... [FILE]...'),
5636 inferrepo=True)
5640 inferrepo=True)
5637 def status(ui, repo, *pats, **opts):
5641 def status(ui, repo, *pats, **opts):
5638 """show changed files in the working directory
5642 """show changed files in the working directory
5639
5643
5640 Show status of files in the repository. If names are given, only
5644 Show status of files in the repository. If names are given, only
5641 files that match are shown. Files that are clean or ignored or
5645 files that match are shown. Files that are clean or ignored or
5642 the source of a copy/move operation, are not listed unless
5646 the source of a copy/move operation, are not listed unless
5643 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5647 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5644 Unless options described with "show only ..." are given, the
5648 Unless options described with "show only ..." are given, the
5645 options -mardu are used.
5649 options -mardu are used.
5646
5650
5647 Option -q/--quiet hides untracked (unknown and ignored) files
5651 Option -q/--quiet hides untracked (unknown and ignored) files
5648 unless explicitly requested with -u/--unknown or -i/--ignored.
5652 unless explicitly requested with -u/--unknown or -i/--ignored.
5649
5653
5650 .. note::
5654 .. note::
5651
5655
5652 status may appear to disagree with diff if permissions have
5656 status may appear to disagree with diff if permissions have
5653 changed or a merge has occurred. The standard diff format does
5657 changed or a merge has occurred. The standard diff format does
5654 not report permission changes and diff only reports changes
5658 not report permission changes and diff only reports changes
5655 relative to one merge parent.
5659 relative to one merge parent.
5656
5660
5657 If one revision is given, it is used as the base revision.
5661 If one revision is given, it is used as the base revision.
5658 If two revisions are given, the differences between them are
5662 If two revisions are given, the differences between them are
5659 shown. The --change option can also be used as a shortcut to list
5663 shown. The --change option can also be used as a shortcut to list
5660 the changed files of a revision from its first parent.
5664 the changed files of a revision from its first parent.
5661
5665
5662 The codes used to show the status of files are::
5666 The codes used to show the status of files are::
5663
5667
5664 M = modified
5668 M = modified
5665 A = added
5669 A = added
5666 R = removed
5670 R = removed
5667 C = clean
5671 C = clean
5668 ! = missing (deleted by non-hg command, but still tracked)
5672 ! = missing (deleted by non-hg command, but still tracked)
5669 ? = not tracked
5673 ? = not tracked
5670 I = ignored
5674 I = ignored
5671 = origin of the previous file (with --copies)
5675 = origin of the previous file (with --copies)
5672
5676
5673 .. container:: verbose
5677 .. container:: verbose
5674
5678
5675 Examples:
5679 Examples:
5676
5680
5677 - show changes in the working directory relative to a
5681 - show changes in the working directory relative to a
5678 changeset::
5682 changeset::
5679
5683
5680 hg status --rev 9353
5684 hg status --rev 9353
5681
5685
5682 - show all changes including copies in an existing changeset::
5686 - show all changes including copies in an existing changeset::
5683
5687
5684 hg status --copies --change 9353
5688 hg status --copies --change 9353
5685
5689
5686 - get a NUL separated list of added files, suitable for xargs::
5690 - get a NUL separated list of added files, suitable for xargs::
5687
5691
5688 hg status -an0
5692 hg status -an0
5689
5693
5690 Returns 0 on success.
5694 Returns 0 on success.
5691 """
5695 """
5692
5696
5693 revs = opts.get('rev')
5697 revs = opts.get('rev')
5694 change = opts.get('change')
5698 change = opts.get('change')
5695
5699
5696 if revs and change:
5700 if revs and change:
5697 msg = _('cannot specify --rev and --change at the same time')
5701 msg = _('cannot specify --rev and --change at the same time')
5698 raise util.Abort(msg)
5702 raise util.Abort(msg)
5699 elif change:
5703 elif change:
5700 node2 = scmutil.revsingle(repo, change, None).node()
5704 node2 = scmutil.revsingle(repo, change, None).node()
5701 node1 = repo[node2].p1().node()
5705 node1 = repo[node2].p1().node()
5702 else:
5706 else:
5703 node1, node2 = scmutil.revpair(repo, revs)
5707 node1, node2 = scmutil.revpair(repo, revs)
5704
5708
5705 cwd = (pats and repo.getcwd()) or ''
5709 cwd = (pats and repo.getcwd()) or ''
5706 end = opts.get('print0') and '\0' or '\n'
5710 end = opts.get('print0') and '\0' or '\n'
5707 copy = {}
5711 copy = {}
5708 states = 'modified added removed deleted unknown ignored clean'.split()
5712 states = 'modified added removed deleted unknown ignored clean'.split()
5709 show = [k for k in states if opts.get(k)]
5713 show = [k for k in states if opts.get(k)]
5710 if opts.get('all'):
5714 if opts.get('all'):
5711 show += ui.quiet and (states[:4] + ['clean']) or states
5715 show += ui.quiet and (states[:4] + ['clean']) or states
5712 if not show:
5716 if not show:
5713 show = ui.quiet and states[:4] or states[:5]
5717 show = ui.quiet and states[:4] or states[:5]
5714
5718
5715 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5719 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5716 'ignored' in show, 'clean' in show, 'unknown' in show,
5720 'ignored' in show, 'clean' in show, 'unknown' in show,
5717 opts.get('subrepos'))
5721 opts.get('subrepos'))
5718 changestates = zip(states, 'MAR!?IC', stat)
5722 changestates = zip(states, 'MAR!?IC', stat)
5719
5723
5720 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5724 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5721 copy = copies.pathcopies(repo[node1], repo[node2])
5725 copy = copies.pathcopies(repo[node1], repo[node2])
5722
5726
5723 fm = ui.formatter('status', opts)
5727 fm = ui.formatter('status', opts)
5724 fmt = '%s' + end
5728 fmt = '%s' + end
5725 showchar = not opts.get('no_status')
5729 showchar = not opts.get('no_status')
5726
5730
5727 for state, char, files in changestates:
5731 for state, char, files in changestates:
5728 if state in show:
5732 if state in show:
5729 label = 'status.' + state
5733 label = 'status.' + state
5730 for f in files:
5734 for f in files:
5731 fm.startitem()
5735 fm.startitem()
5732 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5736 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5733 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5737 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5734 if f in copy:
5738 if f in copy:
5735 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5739 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5736 label='status.copied')
5740 label='status.copied')
5737 fm.end()
5741 fm.end()
5738
5742
5739 @command('^summary|sum',
5743 @command('^summary|sum',
5740 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5744 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5741 def summary(ui, repo, **opts):
5745 def summary(ui, repo, **opts):
5742 """summarize working directory state
5746 """summarize working directory state
5743
5747
5744 This generates a brief summary of the working directory state,
5748 This generates a brief summary of the working directory state,
5745 including parents, branch, commit status, and available updates.
5749 including parents, branch, commit status, and available updates.
5746
5750
5747 With the --remote option, this will check the default paths for
5751 With the --remote option, this will check the default paths for
5748 incoming and outgoing changes. This can be time-consuming.
5752 incoming and outgoing changes. This can be time-consuming.
5749
5753
5750 Returns 0 on success.
5754 Returns 0 on success.
5751 """
5755 """
5752
5756
5753 ctx = repo[None]
5757 ctx = repo[None]
5754 parents = ctx.parents()
5758 parents = ctx.parents()
5755 pnode = parents[0].node()
5759 pnode = parents[0].node()
5756 marks = []
5760 marks = []
5757
5761
5758 for p in parents:
5762 for p in parents:
5759 # label with log.changeset (instead of log.parent) since this
5763 # label with log.changeset (instead of log.parent) since this
5760 # shows a working directory parent *changeset*:
5764 # shows a working directory parent *changeset*:
5761 # i18n: column positioning for "hg summary"
5765 # i18n: column positioning for "hg summary"
5762 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5766 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5763 label='log.changeset changeset.%s' % p.phasestr())
5767 label='log.changeset changeset.%s' % p.phasestr())
5764 ui.write(' '.join(p.tags()), label='log.tag')
5768 ui.write(' '.join(p.tags()), label='log.tag')
5765 if p.bookmarks():
5769 if p.bookmarks():
5766 marks.extend(p.bookmarks())
5770 marks.extend(p.bookmarks())
5767 if p.rev() == -1:
5771 if p.rev() == -1:
5768 if not len(repo):
5772 if not len(repo):
5769 ui.write(_(' (empty repository)'))
5773 ui.write(_(' (empty repository)'))
5770 else:
5774 else:
5771 ui.write(_(' (no revision checked out)'))
5775 ui.write(_(' (no revision checked out)'))
5772 ui.write('\n')
5776 ui.write('\n')
5773 if p.description():
5777 if p.description():
5774 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5778 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5775 label='log.summary')
5779 label='log.summary')
5776
5780
5777 branch = ctx.branch()
5781 branch = ctx.branch()
5778 bheads = repo.branchheads(branch)
5782 bheads = repo.branchheads(branch)
5779 # i18n: column positioning for "hg summary"
5783 # i18n: column positioning for "hg summary"
5780 m = _('branch: %s\n') % branch
5784 m = _('branch: %s\n') % branch
5781 if branch != 'default':
5785 if branch != 'default':
5782 ui.write(m, label='log.branch')
5786 ui.write(m, label='log.branch')
5783 else:
5787 else:
5784 ui.status(m, label='log.branch')
5788 ui.status(m, label='log.branch')
5785
5789
5786 if marks:
5790 if marks:
5787 current = repo._bookmarkcurrent
5791 current = repo._bookmarkcurrent
5788 # i18n: column positioning for "hg summary"
5792 # i18n: column positioning for "hg summary"
5789 ui.write(_('bookmarks:'), label='log.bookmark')
5793 ui.write(_('bookmarks:'), label='log.bookmark')
5790 if current is not None:
5794 if current is not None:
5791 if current in marks:
5795 if current in marks:
5792 ui.write(' *' + current, label='bookmarks.current')
5796 ui.write(' *' + current, label='bookmarks.current')
5793 marks.remove(current)
5797 marks.remove(current)
5794 else:
5798 else:
5795 ui.write(' [%s]' % current, label='bookmarks.current')
5799 ui.write(' [%s]' % current, label='bookmarks.current')
5796 for m in marks:
5800 for m in marks:
5797 ui.write(' ' + m, label='log.bookmark')
5801 ui.write(' ' + m, label='log.bookmark')
5798 ui.write('\n', label='log.bookmark')
5802 ui.write('\n', label='log.bookmark')
5799
5803
5800 status = repo.status(unknown=True)
5804 status = repo.status(unknown=True)
5801
5805
5802 c = repo.dirstate.copies()
5806 c = repo.dirstate.copies()
5803 copied, renamed = [], []
5807 copied, renamed = [], []
5804 for d, s in c.iteritems():
5808 for d, s in c.iteritems():
5805 if s in status.removed:
5809 if s in status.removed:
5806 status.removed.remove(s)
5810 status.removed.remove(s)
5807 renamed.append(d)
5811 renamed.append(d)
5808 else:
5812 else:
5809 copied.append(d)
5813 copied.append(d)
5810 if d in status.added:
5814 if d in status.added:
5811 status.added.remove(d)
5815 status.added.remove(d)
5812
5816
5813 ms = mergemod.mergestate(repo)
5817 ms = mergemod.mergestate(repo)
5814 unresolved = [f for f in ms if ms[f] == 'u']
5818 unresolved = [f for f in ms if ms[f] == 'u']
5815
5819
5816 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5820 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5817
5821
5818 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5822 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
5819 (ui.label(_('%d added'), 'status.added'), status.added),
5823 (ui.label(_('%d added'), 'status.added'), status.added),
5820 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5824 (ui.label(_('%d removed'), 'status.removed'), status.removed),
5821 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5825 (ui.label(_('%d renamed'), 'status.copied'), renamed),
5822 (ui.label(_('%d copied'), 'status.copied'), copied),
5826 (ui.label(_('%d copied'), 'status.copied'), copied),
5823 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5827 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
5824 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5828 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
5825 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5829 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
5826 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5830 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
5827 t = []
5831 t = []
5828 for l, s in labels:
5832 for l, s in labels:
5829 if s:
5833 if s:
5830 t.append(l % len(s))
5834 t.append(l % len(s))
5831
5835
5832 t = ', '.join(t)
5836 t = ', '.join(t)
5833 cleanworkdir = False
5837 cleanworkdir = False
5834
5838
5835 if repo.vfs.exists('updatestate'):
5839 if repo.vfs.exists('updatestate'):
5836 t += _(' (interrupted update)')
5840 t += _(' (interrupted update)')
5837 elif len(parents) > 1:
5841 elif len(parents) > 1:
5838 t += _(' (merge)')
5842 t += _(' (merge)')
5839 elif branch != parents[0].branch():
5843 elif branch != parents[0].branch():
5840 t += _(' (new branch)')
5844 t += _(' (new branch)')
5841 elif (parents[0].closesbranch() and
5845 elif (parents[0].closesbranch() and
5842 pnode in repo.branchheads(branch, closed=True)):
5846 pnode in repo.branchheads(branch, closed=True)):
5843 t += _(' (head closed)')
5847 t += _(' (head closed)')
5844 elif not (status.modified or status.added or status.removed or renamed or
5848 elif not (status.modified or status.added or status.removed or renamed or
5845 copied or subs):
5849 copied or subs):
5846 t += _(' (clean)')
5850 t += _(' (clean)')
5847 cleanworkdir = True
5851 cleanworkdir = True
5848 elif pnode not in bheads:
5852 elif pnode not in bheads:
5849 t += _(' (new branch head)')
5853 t += _(' (new branch head)')
5850
5854
5851 if cleanworkdir:
5855 if cleanworkdir:
5852 # i18n: column positioning for "hg summary"
5856 # i18n: column positioning for "hg summary"
5853 ui.status(_('commit: %s\n') % t.strip())
5857 ui.status(_('commit: %s\n') % t.strip())
5854 else:
5858 else:
5855 # i18n: column positioning for "hg summary"
5859 # i18n: column positioning for "hg summary"
5856 ui.write(_('commit: %s\n') % t.strip())
5860 ui.write(_('commit: %s\n') % t.strip())
5857
5861
5858 # all ancestors of branch heads - all ancestors of parent = new csets
5862 # all ancestors of branch heads - all ancestors of parent = new csets
5859 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5863 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5860 bheads))
5864 bheads))
5861
5865
5862 if new == 0:
5866 if new == 0:
5863 # i18n: column positioning for "hg summary"
5867 # i18n: column positioning for "hg summary"
5864 ui.status(_('update: (current)\n'))
5868 ui.status(_('update: (current)\n'))
5865 elif pnode not in bheads:
5869 elif pnode not in bheads:
5866 # i18n: column positioning for "hg summary"
5870 # i18n: column positioning for "hg summary"
5867 ui.write(_('update: %d new changesets (update)\n') % new)
5871 ui.write(_('update: %d new changesets (update)\n') % new)
5868 else:
5872 else:
5869 # i18n: column positioning for "hg summary"
5873 # i18n: column positioning for "hg summary"
5870 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5874 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5871 (new, len(bheads)))
5875 (new, len(bheads)))
5872
5876
5873 cmdutil.summaryhooks(ui, repo)
5877 cmdutil.summaryhooks(ui, repo)
5874
5878
5875 if opts.get('remote'):
5879 if opts.get('remote'):
5876 needsincoming, needsoutgoing = True, True
5880 needsincoming, needsoutgoing = True, True
5877 else:
5881 else:
5878 needsincoming, needsoutgoing = False, False
5882 needsincoming, needsoutgoing = False, False
5879 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5883 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5880 if i:
5884 if i:
5881 needsincoming = True
5885 needsincoming = True
5882 if o:
5886 if o:
5883 needsoutgoing = True
5887 needsoutgoing = True
5884 if not needsincoming and not needsoutgoing:
5888 if not needsincoming and not needsoutgoing:
5885 return
5889 return
5886
5890
5887 def getincoming():
5891 def getincoming():
5888 source, branches = hg.parseurl(ui.expandpath('default'))
5892 source, branches = hg.parseurl(ui.expandpath('default'))
5889 sbranch = branches[0]
5893 sbranch = branches[0]
5890 try:
5894 try:
5891 other = hg.peer(repo, {}, source)
5895 other = hg.peer(repo, {}, source)
5892 except error.RepoError:
5896 except error.RepoError:
5893 if opts.get('remote'):
5897 if opts.get('remote'):
5894 raise
5898 raise
5895 return source, sbranch, None, None, None
5899 return source, sbranch, None, None, None
5896 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5900 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5897 if revs:
5901 if revs:
5898 revs = [other.lookup(rev) for rev in revs]
5902 revs = [other.lookup(rev) for rev in revs]
5899 ui.debug('comparing with %s\n' % util.hidepassword(source))
5903 ui.debug('comparing with %s\n' % util.hidepassword(source))
5900 repo.ui.pushbuffer()
5904 repo.ui.pushbuffer()
5901 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5905 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5902 repo.ui.popbuffer()
5906 repo.ui.popbuffer()
5903 return source, sbranch, other, commoninc, commoninc[1]
5907 return source, sbranch, other, commoninc, commoninc[1]
5904
5908
5905 if needsincoming:
5909 if needsincoming:
5906 source, sbranch, sother, commoninc, incoming = getincoming()
5910 source, sbranch, sother, commoninc, incoming = getincoming()
5907 else:
5911 else:
5908 source = sbranch = sother = commoninc = incoming = None
5912 source = sbranch = sother = commoninc = incoming = None
5909
5913
5910 def getoutgoing():
5914 def getoutgoing():
5911 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5915 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5912 dbranch = branches[0]
5916 dbranch = branches[0]
5913 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5917 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5914 if source != dest:
5918 if source != dest:
5915 try:
5919 try:
5916 dother = hg.peer(repo, {}, dest)
5920 dother = hg.peer(repo, {}, dest)
5917 except error.RepoError:
5921 except error.RepoError:
5918 if opts.get('remote'):
5922 if opts.get('remote'):
5919 raise
5923 raise
5920 return dest, dbranch, None, None
5924 return dest, dbranch, None, None
5921 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5925 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5922 elif sother is None:
5926 elif sother is None:
5923 # there is no explicit destination peer, but source one is invalid
5927 # there is no explicit destination peer, but source one is invalid
5924 return dest, dbranch, None, None
5928 return dest, dbranch, None, None
5925 else:
5929 else:
5926 dother = sother
5930 dother = sother
5927 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5931 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5928 common = None
5932 common = None
5929 else:
5933 else:
5930 common = commoninc
5934 common = commoninc
5931 if revs:
5935 if revs:
5932 revs = [repo.lookup(rev) for rev in revs]
5936 revs = [repo.lookup(rev) for rev in revs]
5933 repo.ui.pushbuffer()
5937 repo.ui.pushbuffer()
5934 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5938 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5935 commoninc=common)
5939 commoninc=common)
5936 repo.ui.popbuffer()
5940 repo.ui.popbuffer()
5937 return dest, dbranch, dother, outgoing
5941 return dest, dbranch, dother, outgoing
5938
5942
5939 if needsoutgoing:
5943 if needsoutgoing:
5940 dest, dbranch, dother, outgoing = getoutgoing()
5944 dest, dbranch, dother, outgoing = getoutgoing()
5941 else:
5945 else:
5942 dest = dbranch = dother = outgoing = None
5946 dest = dbranch = dother = outgoing = None
5943
5947
5944 if opts.get('remote'):
5948 if opts.get('remote'):
5945 t = []
5949 t = []
5946 if incoming:
5950 if incoming:
5947 t.append(_('1 or more incoming'))
5951 t.append(_('1 or more incoming'))
5948 o = outgoing.missing
5952 o = outgoing.missing
5949 if o:
5953 if o:
5950 t.append(_('%d outgoing') % len(o))
5954 t.append(_('%d outgoing') % len(o))
5951 other = dother or sother
5955 other = dother or sother
5952 if 'bookmarks' in other.listkeys('namespaces'):
5956 if 'bookmarks' in other.listkeys('namespaces'):
5953 lmarks = repo.listkeys('bookmarks')
5957 lmarks = repo.listkeys('bookmarks')
5954 rmarks = other.listkeys('bookmarks')
5958 rmarks = other.listkeys('bookmarks')
5955 diff = set(rmarks) - set(lmarks)
5959 diff = set(rmarks) - set(lmarks)
5956 if len(diff) > 0:
5960 if len(diff) > 0:
5957 t.append(_('%d incoming bookmarks') % len(diff))
5961 t.append(_('%d incoming bookmarks') % len(diff))
5958 diff = set(lmarks) - set(rmarks)
5962 diff = set(lmarks) - set(rmarks)
5959 if len(diff) > 0:
5963 if len(diff) > 0:
5960 t.append(_('%d outgoing bookmarks') % len(diff))
5964 t.append(_('%d outgoing bookmarks') % len(diff))
5961
5965
5962 if t:
5966 if t:
5963 # i18n: column positioning for "hg summary"
5967 # i18n: column positioning for "hg summary"
5964 ui.write(_('remote: %s\n') % (', '.join(t)))
5968 ui.write(_('remote: %s\n') % (', '.join(t)))
5965 else:
5969 else:
5966 # i18n: column positioning for "hg summary"
5970 # i18n: column positioning for "hg summary"
5967 ui.status(_('remote: (synced)\n'))
5971 ui.status(_('remote: (synced)\n'))
5968
5972
5969 cmdutil.summaryremotehooks(ui, repo, opts,
5973 cmdutil.summaryremotehooks(ui, repo, opts,
5970 ((source, sbranch, sother, commoninc),
5974 ((source, sbranch, sother, commoninc),
5971 (dest, dbranch, dother, outgoing)))
5975 (dest, dbranch, dother, outgoing)))
5972
5976
5973 @command('tag',
5977 @command('tag',
5974 [('f', 'force', None, _('force tag')),
5978 [('f', 'force', None, _('force tag')),
5975 ('l', 'local', None, _('make the tag local')),
5979 ('l', 'local', None, _('make the tag local')),
5976 ('r', 'rev', '', _('revision to tag'), _('REV')),
5980 ('r', 'rev', '', _('revision to tag'), _('REV')),
5977 ('', 'remove', None, _('remove a tag')),
5981 ('', 'remove', None, _('remove a tag')),
5978 # -l/--local is already there, commitopts cannot be used
5982 # -l/--local is already there, commitopts cannot be used
5979 ('e', 'edit', None, _('invoke editor on commit messages')),
5983 ('e', 'edit', None, _('invoke editor on commit messages')),
5980 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5984 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5981 ] + commitopts2,
5985 ] + commitopts2,
5982 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5986 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5983 def tag(ui, repo, name1, *names, **opts):
5987 def tag(ui, repo, name1, *names, **opts):
5984 """add one or more tags for the current or given revision
5988 """add one or more tags for the current or given revision
5985
5989
5986 Name a particular revision using <name>.
5990 Name a particular revision using <name>.
5987
5991
5988 Tags are used to name particular revisions of the repository and are
5992 Tags are used to name particular revisions of the repository and are
5989 very useful to compare different revisions, to go back to significant
5993 very useful to compare different revisions, to go back to significant
5990 earlier versions or to mark branch points as releases, etc. Changing
5994 earlier versions or to mark branch points as releases, etc. Changing
5991 an existing tag is normally disallowed; use -f/--force to override.
5995 an existing tag is normally disallowed; use -f/--force to override.
5992
5996
5993 If no revision is given, the parent of the working directory is
5997 If no revision is given, the parent of the working directory is
5994 used.
5998 used.
5995
5999
5996 To facilitate version control, distribution, and merging of tags,
6000 To facilitate version control, distribution, and merging of tags,
5997 they are stored as a file named ".hgtags" which is managed similarly
6001 they are stored as a file named ".hgtags" which is managed similarly
5998 to other project files and can be hand-edited if necessary. This
6002 to other project files and can be hand-edited if necessary. This
5999 also means that tagging creates a new commit. The file
6003 also means that tagging creates a new commit. The file
6000 ".hg/localtags" is used for local tags (not shared among
6004 ".hg/localtags" is used for local tags (not shared among
6001 repositories).
6005 repositories).
6002
6006
6003 Tag commits are usually made at the head of a branch. If the parent
6007 Tag commits are usually made at the head of a branch. If the parent
6004 of the working directory is not a branch head, :hg:`tag` aborts; use
6008 of the working directory is not a branch head, :hg:`tag` aborts; use
6005 -f/--force to force the tag commit to be based on a non-head
6009 -f/--force to force the tag commit to be based on a non-head
6006 changeset.
6010 changeset.
6007
6011
6008 See :hg:`help dates` for a list of formats valid for -d/--date.
6012 See :hg:`help dates` for a list of formats valid for -d/--date.
6009
6013
6010 Since tag names have priority over branch names during revision
6014 Since tag names have priority over branch names during revision
6011 lookup, using an existing branch name as a tag name is discouraged.
6015 lookup, using an existing branch name as a tag name is discouraged.
6012
6016
6013 Returns 0 on success.
6017 Returns 0 on success.
6014 """
6018 """
6015 wlock = lock = None
6019 wlock = lock = None
6016 try:
6020 try:
6017 wlock = repo.wlock()
6021 wlock = repo.wlock()
6018 lock = repo.lock()
6022 lock = repo.lock()
6019 rev_ = "."
6023 rev_ = "."
6020 names = [t.strip() for t in (name1,) + names]
6024 names = [t.strip() for t in (name1,) + names]
6021 if len(names) != len(set(names)):
6025 if len(names) != len(set(names)):
6022 raise util.Abort(_('tag names must be unique'))
6026 raise util.Abort(_('tag names must be unique'))
6023 for n in names:
6027 for n in names:
6024 scmutil.checknewlabel(repo, n, 'tag')
6028 scmutil.checknewlabel(repo, n, 'tag')
6025 if not n:
6029 if not n:
6026 raise util.Abort(_('tag names cannot consist entirely of '
6030 raise util.Abort(_('tag names cannot consist entirely of '
6027 'whitespace'))
6031 'whitespace'))
6028 if opts.get('rev') and opts.get('remove'):
6032 if opts.get('rev') and opts.get('remove'):
6029 raise util.Abort(_("--rev and --remove are incompatible"))
6033 raise util.Abort(_("--rev and --remove are incompatible"))
6030 if opts.get('rev'):
6034 if opts.get('rev'):
6031 rev_ = opts['rev']
6035 rev_ = opts['rev']
6032 message = opts.get('message')
6036 message = opts.get('message')
6033 if opts.get('remove'):
6037 if opts.get('remove'):
6034 expectedtype = opts.get('local') and 'local' or 'global'
6038 expectedtype = opts.get('local') and 'local' or 'global'
6035 for n in names:
6039 for n in names:
6036 if not repo.tagtype(n):
6040 if not repo.tagtype(n):
6037 raise util.Abort(_("tag '%s' does not exist") % n)
6041 raise util.Abort(_("tag '%s' does not exist") % n)
6038 if repo.tagtype(n) != expectedtype:
6042 if repo.tagtype(n) != expectedtype:
6039 if expectedtype == 'global':
6043 if expectedtype == 'global':
6040 raise util.Abort(_("tag '%s' is not a global tag") % n)
6044 raise util.Abort(_("tag '%s' is not a global tag") % n)
6041 else:
6045 else:
6042 raise util.Abort(_("tag '%s' is not a local tag") % n)
6046 raise util.Abort(_("tag '%s' is not a local tag") % n)
6043 rev_ = nullid
6047 rev_ = nullid
6044 if not message:
6048 if not message:
6045 # we don't translate commit messages
6049 # we don't translate commit messages
6046 message = 'Removed tag %s' % ', '.join(names)
6050 message = 'Removed tag %s' % ', '.join(names)
6047 elif not opts.get('force'):
6051 elif not opts.get('force'):
6048 for n in names:
6052 for n in names:
6049 if n in repo.tags():
6053 if n in repo.tags():
6050 raise util.Abort(_("tag '%s' already exists "
6054 raise util.Abort(_("tag '%s' already exists "
6051 "(use -f to force)") % n)
6055 "(use -f to force)") % n)
6052 if not opts.get('local'):
6056 if not opts.get('local'):
6053 p1, p2 = repo.dirstate.parents()
6057 p1, p2 = repo.dirstate.parents()
6054 if p2 != nullid:
6058 if p2 != nullid:
6055 raise util.Abort(_('uncommitted merge'))
6059 raise util.Abort(_('uncommitted merge'))
6056 bheads = repo.branchheads()
6060 bheads = repo.branchheads()
6057 if not opts.get('force') and bheads and p1 not in bheads:
6061 if not opts.get('force') and bheads and p1 not in bheads:
6058 raise util.Abort(_('not at a branch head (use -f to force)'))
6062 raise util.Abort(_('not at a branch head (use -f to force)'))
6059 r = scmutil.revsingle(repo, rev_).node()
6063 r = scmutil.revsingle(repo, rev_).node()
6060
6064
6061 if not message:
6065 if not message:
6062 # we don't translate commit messages
6066 # we don't translate commit messages
6063 message = ('Added tag %s for changeset %s' %
6067 message = ('Added tag %s for changeset %s' %
6064 (', '.join(names), short(r)))
6068 (', '.join(names), short(r)))
6065
6069
6066 date = opts.get('date')
6070 date = opts.get('date')
6067 if date:
6071 if date:
6068 date = util.parsedate(date)
6072 date = util.parsedate(date)
6069
6073
6070 if opts.get('remove'):
6074 if opts.get('remove'):
6071 editform = 'tag.remove'
6075 editform = 'tag.remove'
6072 else:
6076 else:
6073 editform = 'tag.add'
6077 editform = 'tag.add'
6074 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6078 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6075
6079
6076 # don't allow tagging the null rev
6080 # don't allow tagging the null rev
6077 if (not opts.get('remove') and
6081 if (not opts.get('remove') and
6078 scmutil.revsingle(repo, rev_).rev() == nullrev):
6082 scmutil.revsingle(repo, rev_).rev() == nullrev):
6079 raise util.Abort(_("cannot tag null revision"))
6083 raise util.Abort(_("cannot tag null revision"))
6080
6084
6081 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6085 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6082 editor=editor)
6086 editor=editor)
6083 finally:
6087 finally:
6084 release(lock, wlock)
6088 release(lock, wlock)
6085
6089
6086 @command('tags', formatteropts, '')
6090 @command('tags', formatteropts, '')
6087 def tags(ui, repo, **opts):
6091 def tags(ui, repo, **opts):
6088 """list repository tags
6092 """list repository tags
6089
6093
6090 This lists both regular and local tags. When the -v/--verbose
6094 This lists both regular and local tags. When the -v/--verbose
6091 switch is used, a third column "local" is printed for local tags.
6095 switch is used, a third column "local" is printed for local tags.
6092
6096
6093 Returns 0 on success.
6097 Returns 0 on success.
6094 """
6098 """
6095
6099
6096 fm = ui.formatter('tags', opts)
6100 fm = ui.formatter('tags', opts)
6097 hexfunc = fm.hexfunc
6101 hexfunc = fm.hexfunc
6098 tagtype = ""
6102 tagtype = ""
6099
6103
6100 for t, n in reversed(repo.tagslist()):
6104 for t, n in reversed(repo.tagslist()):
6101 hn = hexfunc(n)
6105 hn = hexfunc(n)
6102 label = 'tags.normal'
6106 label = 'tags.normal'
6103 tagtype = ''
6107 tagtype = ''
6104 if repo.tagtype(t) == 'local':
6108 if repo.tagtype(t) == 'local':
6105 label = 'tags.local'
6109 label = 'tags.local'
6106 tagtype = 'local'
6110 tagtype = 'local'
6107
6111
6108 fm.startitem()
6112 fm.startitem()
6109 fm.write('tag', '%s', t, label=label)
6113 fm.write('tag', '%s', t, label=label)
6110 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6114 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6111 fm.condwrite(not ui.quiet, 'rev node', fmt,
6115 fm.condwrite(not ui.quiet, 'rev node', fmt,
6112 repo.changelog.rev(n), hn, label=label)
6116 repo.changelog.rev(n), hn, label=label)
6113 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6117 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6114 tagtype, label=label)
6118 tagtype, label=label)
6115 fm.plain('\n')
6119 fm.plain('\n')
6116 fm.end()
6120 fm.end()
6117
6121
6118 @command('tip',
6122 @command('tip',
6119 [('p', 'patch', None, _('show patch')),
6123 [('p', 'patch', None, _('show patch')),
6120 ('g', 'git', None, _('use git extended diff format')),
6124 ('g', 'git', None, _('use git extended diff format')),
6121 ] + templateopts,
6125 ] + templateopts,
6122 _('[-p] [-g]'))
6126 _('[-p] [-g]'))
6123 def tip(ui, repo, **opts):
6127 def tip(ui, repo, **opts):
6124 """show the tip revision (DEPRECATED)
6128 """show the tip revision (DEPRECATED)
6125
6129
6126 The tip revision (usually just called the tip) is the changeset
6130 The tip revision (usually just called the tip) is the changeset
6127 most recently added to the repository (and therefore the most
6131 most recently added to the repository (and therefore the most
6128 recently changed head).
6132 recently changed head).
6129
6133
6130 If you have just made a commit, that commit will be the tip. If
6134 If you have just made a commit, that commit will be the tip. If
6131 you have just pulled changes from another repository, the tip of
6135 you have just pulled changes from another repository, the tip of
6132 that repository becomes the current tip. The "tip" tag is special
6136 that repository becomes the current tip. The "tip" tag is special
6133 and cannot be renamed or assigned to a different changeset.
6137 and cannot be renamed or assigned to a different changeset.
6134
6138
6135 This command is deprecated, please use :hg:`heads` instead.
6139 This command is deprecated, please use :hg:`heads` instead.
6136
6140
6137 Returns 0 on success.
6141 Returns 0 on success.
6138 """
6142 """
6139 displayer = cmdutil.show_changeset(ui, repo, opts)
6143 displayer = cmdutil.show_changeset(ui, repo, opts)
6140 displayer.show(repo['tip'])
6144 displayer.show(repo['tip'])
6141 displayer.close()
6145 displayer.close()
6142
6146
6143 @command('unbundle',
6147 @command('unbundle',
6144 [('u', 'update', None,
6148 [('u', 'update', None,
6145 _('update to new branch head if changesets were unbundled'))],
6149 _('update to new branch head if changesets were unbundled'))],
6146 _('[-u] FILE...'))
6150 _('[-u] FILE...'))
6147 def unbundle(ui, repo, fname1, *fnames, **opts):
6151 def unbundle(ui, repo, fname1, *fnames, **opts):
6148 """apply one or more changegroup files
6152 """apply one or more changegroup files
6149
6153
6150 Apply one or more compressed changegroup files generated by the
6154 Apply one or more compressed changegroup files generated by the
6151 bundle command.
6155 bundle command.
6152
6156
6153 Returns 0 on success, 1 if an update has unresolved files.
6157 Returns 0 on success, 1 if an update has unresolved files.
6154 """
6158 """
6155 fnames = (fname1,) + fnames
6159 fnames = (fname1,) + fnames
6156
6160
6157 lock = repo.lock()
6161 lock = repo.lock()
6158 try:
6162 try:
6159 for fname in fnames:
6163 for fname in fnames:
6160 f = hg.openpath(ui, fname)
6164 f = hg.openpath(ui, fname)
6161 gen = exchange.readbundle(ui, f, fname)
6165 gen = exchange.readbundle(ui, f, fname)
6162 if isinstance(gen, bundle2.unbundle20):
6166 if isinstance(gen, bundle2.unbundle20):
6163 tr = repo.transaction('unbundle')
6167 tr = repo.transaction('unbundle')
6164 try:
6168 try:
6165 op = bundle2.processbundle(repo, gen, lambda: tr)
6169 op = bundle2.processbundle(repo, gen, lambda: tr)
6166 tr.close()
6170 tr.close()
6167 finally:
6171 finally:
6168 if tr:
6172 if tr:
6169 tr.release()
6173 tr.release()
6170 changes = [r.get('result', 0)
6174 changes = [r.get('result', 0)
6171 for r in op.records['changegroup']]
6175 for r in op.records['changegroup']]
6172 modheads = changegroup.combineresults(changes)
6176 modheads = changegroup.combineresults(changes)
6173 else:
6177 else:
6174 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6178 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6175 'bundle:' + fname)
6179 'bundle:' + fname)
6176 finally:
6180 finally:
6177 lock.release()
6181 lock.release()
6178
6182
6179 return postincoming(ui, repo, modheads, opts.get('update'), None)
6183 return postincoming(ui, repo, modheads, opts.get('update'), None)
6180
6184
6181 @command('^update|up|checkout|co',
6185 @command('^update|up|checkout|co',
6182 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6186 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6183 ('c', 'check', None,
6187 ('c', 'check', None,
6184 _('update across branches if no uncommitted changes')),
6188 _('update across branches if no uncommitted changes')),
6185 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6189 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6186 ('r', 'rev', '', _('revision'), _('REV'))
6190 ('r', 'rev', '', _('revision'), _('REV'))
6187 ] + mergetoolopts,
6191 ] + mergetoolopts,
6188 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6192 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6189 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6193 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6190 tool=None):
6194 tool=None):
6191 """update working directory (or switch revisions)
6195 """update working directory (or switch revisions)
6192
6196
6193 Update the repository's working directory to the specified
6197 Update the repository's working directory to the specified
6194 changeset. If no changeset is specified, update to the tip of the
6198 changeset. If no changeset is specified, update to the tip of the
6195 current named branch and move the current bookmark (see :hg:`help
6199 current named branch and move the current bookmark (see :hg:`help
6196 bookmarks`).
6200 bookmarks`).
6197
6201
6198 Update sets the working directory's parent revision to the specified
6202 Update sets the working directory's parent revision to the specified
6199 changeset (see :hg:`help parents`).
6203 changeset (see :hg:`help parents`).
6200
6204
6201 If the changeset is not a descendant or ancestor of the working
6205 If the changeset is not a descendant or ancestor of the working
6202 directory's parent, the update is aborted. With the -c/--check
6206 directory's parent, the update is aborted. With the -c/--check
6203 option, the working directory is checked for uncommitted changes; if
6207 option, the working directory is checked for uncommitted changes; if
6204 none are found, the working directory is updated to the specified
6208 none are found, the working directory is updated to the specified
6205 changeset.
6209 changeset.
6206
6210
6207 .. container:: verbose
6211 .. container:: verbose
6208
6212
6209 The following rules apply when the working directory contains
6213 The following rules apply when the working directory contains
6210 uncommitted changes:
6214 uncommitted changes:
6211
6215
6212 1. If neither -c/--check nor -C/--clean is specified, and if
6216 1. If neither -c/--check nor -C/--clean is specified, and if
6213 the requested changeset is an ancestor or descendant of
6217 the requested changeset is an ancestor or descendant of
6214 the working directory's parent, the uncommitted changes
6218 the working directory's parent, the uncommitted changes
6215 are merged into the requested changeset and the merged
6219 are merged into the requested changeset and the merged
6216 result is left uncommitted. If the requested changeset is
6220 result is left uncommitted. If the requested changeset is
6217 not an ancestor or descendant (that is, it is on another
6221 not an ancestor or descendant (that is, it is on another
6218 branch), the update is aborted and the uncommitted changes
6222 branch), the update is aborted and the uncommitted changes
6219 are preserved.
6223 are preserved.
6220
6224
6221 2. With the -c/--check option, the update is aborted and the
6225 2. With the -c/--check option, the update is aborted and the
6222 uncommitted changes are preserved.
6226 uncommitted changes are preserved.
6223
6227
6224 3. With the -C/--clean option, uncommitted changes are discarded and
6228 3. With the -C/--clean option, uncommitted changes are discarded and
6225 the working directory is updated to the requested changeset.
6229 the working directory is updated to the requested changeset.
6226
6230
6227 To cancel an uncommitted merge (and lose your changes), use
6231 To cancel an uncommitted merge (and lose your changes), use
6228 :hg:`update --clean .`.
6232 :hg:`update --clean .`.
6229
6233
6230 Use null as the changeset to remove the working directory (like
6234 Use null as the changeset to remove the working directory (like
6231 :hg:`clone -U`).
6235 :hg:`clone -U`).
6232
6236
6233 If you want to revert just one file to an older revision, use
6237 If you want to revert just one file to an older revision, use
6234 :hg:`revert [-r REV] NAME`.
6238 :hg:`revert [-r REV] NAME`.
6235
6239
6236 See :hg:`help dates` for a list of formats valid for -d/--date.
6240 See :hg:`help dates` for a list of formats valid for -d/--date.
6237
6241
6238 Returns 0 on success, 1 if there are unresolved files.
6242 Returns 0 on success, 1 if there are unresolved files.
6239 """
6243 """
6240 if rev and node:
6244 if rev and node:
6241 raise util.Abort(_("please specify just one revision"))
6245 raise util.Abort(_("please specify just one revision"))
6242
6246
6243 if rev is None or rev == '':
6247 if rev is None or rev == '':
6244 rev = node
6248 rev = node
6245
6249
6246 cmdutil.clearunfinished(repo)
6250 cmdutil.clearunfinished(repo)
6247
6251
6248 # with no argument, we also move the current bookmark, if any
6252 # with no argument, we also move the current bookmark, if any
6249 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6253 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6250
6254
6251 # if we defined a bookmark, we have to remember the original bookmark name
6255 # if we defined a bookmark, we have to remember the original bookmark name
6252 brev = rev
6256 brev = rev
6253 rev = scmutil.revsingle(repo, rev, rev).rev()
6257 rev = scmutil.revsingle(repo, rev, rev).rev()
6254
6258
6255 if check and clean:
6259 if check and clean:
6256 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6260 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6257
6261
6258 if date:
6262 if date:
6259 if rev is not None:
6263 if rev is not None:
6260 raise util.Abort(_("you can't specify a revision and a date"))
6264 raise util.Abort(_("you can't specify a revision and a date"))
6261 rev = cmdutil.finddate(ui, repo, date)
6265 rev = cmdutil.finddate(ui, repo, date)
6262
6266
6263 if check:
6267 if check:
6264 c = repo[None]
6268 c = repo[None]
6265 if c.dirty(merge=False, branch=False, missing=True):
6269 if c.dirty(merge=False, branch=False, missing=True):
6266 raise util.Abort(_("uncommitted changes"))
6270 raise util.Abort(_("uncommitted changes"))
6267 if rev is None:
6271 if rev is None:
6268 rev = repo[repo[None].branch()].rev()
6272 rev = repo[repo[None].branch()].rev()
6269
6273
6270 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6274 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6271
6275
6272 if clean:
6276 if clean:
6273 ret = hg.clean(repo, rev)
6277 ret = hg.clean(repo, rev)
6274 else:
6278 else:
6275 ret = hg.update(repo, rev)
6279 ret = hg.update(repo, rev)
6276
6280
6277 if not ret and movemarkfrom:
6281 if not ret and movemarkfrom:
6278 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6282 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6279 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6283 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6280 elif brev in repo._bookmarks:
6284 elif brev in repo._bookmarks:
6281 bookmarks.setcurrent(repo, brev)
6285 bookmarks.setcurrent(repo, brev)
6282 ui.status(_("(activating bookmark %s)\n") % brev)
6286 ui.status(_("(activating bookmark %s)\n") % brev)
6283 elif brev:
6287 elif brev:
6284 if repo._bookmarkcurrent:
6288 if repo._bookmarkcurrent:
6285 ui.status(_("(leaving bookmark %s)\n") %
6289 ui.status(_("(leaving bookmark %s)\n") %
6286 repo._bookmarkcurrent)
6290 repo._bookmarkcurrent)
6287 bookmarks.unsetcurrent(repo)
6291 bookmarks.unsetcurrent(repo)
6288
6292
6289 return ret
6293 return ret
6290
6294
6291 @command('verify', [])
6295 @command('verify', [])
6292 def verify(ui, repo):
6296 def verify(ui, repo):
6293 """verify the integrity of the repository
6297 """verify the integrity of the repository
6294
6298
6295 Verify the integrity of the current repository.
6299 Verify the integrity of the current repository.
6296
6300
6297 This will perform an extensive check of the repository's
6301 This will perform an extensive check of the repository's
6298 integrity, validating the hashes and checksums of each entry in
6302 integrity, validating the hashes and checksums of each entry in
6299 the changelog, manifest, and tracked files, as well as the
6303 the changelog, manifest, and tracked files, as well as the
6300 integrity of their crosslinks and indices.
6304 integrity of their crosslinks and indices.
6301
6305
6302 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6306 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6303 for more information about recovery from corruption of the
6307 for more information about recovery from corruption of the
6304 repository.
6308 repository.
6305
6309
6306 Returns 0 on success, 1 if errors are encountered.
6310 Returns 0 on success, 1 if errors are encountered.
6307 """
6311 """
6308 return hg.verify(repo)
6312 return hg.verify(repo)
6309
6313
6310 @command('version', [], norepo=True)
6314 @command('version', [], norepo=True)
6311 def version_(ui):
6315 def version_(ui):
6312 """output version and copyright information"""
6316 """output version and copyright information"""
6313 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6317 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6314 % util.version())
6318 % util.version())
6315 ui.status(_(
6319 ui.status(_(
6316 "(see http://mercurial.selenic.com for more information)\n"
6320 "(see http://mercurial.selenic.com for more information)\n"
6317 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6321 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6318 "This is free software; see the source for copying conditions. "
6322 "This is free software; see the source for copying conditions. "
6319 "There is NO\nwarranty; "
6323 "There is NO\nwarranty; "
6320 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6324 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6321 ))
6325 ))
6322
6326
6323 ui.note(_("\nEnabled extensions:\n\n"))
6327 ui.note(_("\nEnabled extensions:\n\n"))
6324 if ui.verbose:
6328 if ui.verbose:
6325 # format names and versions into columns
6329 # format names and versions into columns
6326 names = []
6330 names = []
6327 vers = []
6331 vers = []
6328 for name, module in extensions.extensions():
6332 for name, module in extensions.extensions():
6329 names.append(name)
6333 names.append(name)
6330 vers.append(extensions.moduleversion(module))
6334 vers.append(extensions.moduleversion(module))
6331 if names:
6335 if names:
6332 maxnamelen = max(len(n) for n in names)
6336 maxnamelen = max(len(n) for n in names)
6333 for i, name in enumerate(names):
6337 for i, name in enumerate(names):
6334 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6338 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,338 +1,338
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 config
16 config
17 copy
17 copy
18 diff
18 diff
19 export
19 export
20 files
20 files
21 forget
21 forget
22 graft
22 graft
23 grep
23 grep
24 heads
24 heads
25 help
25 help
26 identify
26 identify
27 import
27 import
28 incoming
28 incoming
29 init
29 init
30 locate
30 locate
31 log
31 log
32 manifest
32 manifest
33 merge
33 merge
34 outgoing
34 outgoing
35 parents
35 parents
36 paths
36 paths
37 phase
37 phase
38 pull
38 pull
39 push
39 push
40 recover
40 recover
41 remove
41 remove
42 rename
42 rename
43 resolve
43 resolve
44 revert
44 revert
45 rollback
45 rollback
46 root
46 root
47 serve
47 serve
48 status
48 status
49 summary
49 summary
50 tag
50 tag
51 tags
51 tags
52 tip
52 tip
53 unbundle
53 unbundle
54 update
54 update
55 verify
55 verify
56 version
56 version
57
57
58 Show all commands that start with "a"
58 Show all commands that start with "a"
59 $ hg debugcomplete a
59 $ hg debugcomplete a
60 add
60 add
61 addremove
61 addremove
62 annotate
62 annotate
63 archive
63 archive
64
64
65 Do not show debug commands if there are other candidates
65 Do not show debug commands if there are other candidates
66 $ hg debugcomplete d
66 $ hg debugcomplete d
67 diff
67 diff
68
68
69 Show debug commands if there are no other candidates
69 Show debug commands if there are no other candidates
70 $ hg debugcomplete debug
70 $ hg debugcomplete debug
71 debugancestor
71 debugancestor
72 debugbuilddag
72 debugbuilddag
73 debugbundle
73 debugbundle
74 debugcheckstate
74 debugcheckstate
75 debugcommands
75 debugcommands
76 debugcomplete
76 debugcomplete
77 debugconfig
77 debugconfig
78 debugdag
78 debugdag
79 debugdata
79 debugdata
80 debugdate
80 debugdate
81 debugdirstate
81 debugdirstate
82 debugdiscovery
82 debugdiscovery
83 debugfileset
83 debugfileset
84 debugfsinfo
84 debugfsinfo
85 debuggetbundle
85 debuggetbundle
86 debugignore
86 debugignore
87 debugindex
87 debugindex
88 debugindexdot
88 debugindexdot
89 debuginstall
89 debuginstall
90 debugknown
90 debugknown
91 debuglabelcomplete
91 debuglabelcomplete
92 debuglocks
92 debuglocks
93 debugnamecomplete
93 debugnamecomplete
94 debugobsolete
94 debugobsolete
95 debugpathcomplete
95 debugpathcomplete
96 debugpushkey
96 debugpushkey
97 debugpvec
97 debugpvec
98 debugrebuilddirstate
98 debugrebuilddirstate
99 debugrename
99 debugrename
100 debugrevlog
100 debugrevlog
101 debugrevspec
101 debugrevspec
102 debugsetparents
102 debugsetparents
103 debugsub
103 debugsub
104 debugsuccessorssets
104 debugsuccessorssets
105 debugwalk
105 debugwalk
106 debugwireargs
106 debugwireargs
107
107
108 Do not show the alias of a debug command if there are other candidates
108 Do not show the alias of a debug command if there are other candidates
109 (this should hide rawcommit)
109 (this should hide rawcommit)
110 $ hg debugcomplete r
110 $ hg debugcomplete r
111 recover
111 recover
112 remove
112 remove
113 rename
113 rename
114 resolve
114 resolve
115 revert
115 revert
116 rollback
116 rollback
117 root
117 root
118 Show the alias of a debug command if there are no other candidates
118 Show the alias of a debug command if there are no other candidates
119 $ hg debugcomplete rawc
119 $ hg debugcomplete rawc
120
120
121
121
122 Show the global options
122 Show the global options
123 $ hg debugcomplete --options | sort
123 $ hg debugcomplete --options | sort
124 --config
124 --config
125 --cwd
125 --cwd
126 --debug
126 --debug
127 --debugger
127 --debugger
128 --encoding
128 --encoding
129 --encodingmode
129 --encodingmode
130 --help
130 --help
131 --hidden
131 --hidden
132 --noninteractive
132 --noninteractive
133 --profile
133 --profile
134 --quiet
134 --quiet
135 --repository
135 --repository
136 --time
136 --time
137 --traceback
137 --traceback
138 --verbose
138 --verbose
139 --version
139 --version
140 -R
140 -R
141 -h
141 -h
142 -q
142 -q
143 -v
143 -v
144 -y
144 -y
145
145
146 Show the options for the "serve" command
146 Show the options for the "serve" command
147 $ hg debugcomplete --options serve | sort
147 $ hg debugcomplete --options serve | sort
148 --accesslog
148 --accesslog
149 --address
149 --address
150 --certificate
150 --certificate
151 --cmdserver
151 --cmdserver
152 --config
152 --config
153 --cwd
153 --cwd
154 --daemon
154 --daemon
155 --daemon-pipefds
155 --daemon-pipefds
156 --debug
156 --debug
157 --debugger
157 --debugger
158 --encoding
158 --encoding
159 --encodingmode
159 --encodingmode
160 --errorlog
160 --errorlog
161 --help
161 --help
162 --hidden
162 --hidden
163 --ipv6
163 --ipv6
164 --name
164 --name
165 --noninteractive
165 --noninteractive
166 --pid-file
166 --pid-file
167 --port
167 --port
168 --prefix
168 --prefix
169 --profile
169 --profile
170 --quiet
170 --quiet
171 --repository
171 --repository
172 --stdio
172 --stdio
173 --style
173 --style
174 --templates
174 --templates
175 --time
175 --time
176 --traceback
176 --traceback
177 --verbose
177 --verbose
178 --version
178 --version
179 --web-conf
179 --web-conf
180 -6
180 -6
181 -A
181 -A
182 -E
182 -E
183 -R
183 -R
184 -a
184 -a
185 -d
185 -d
186 -h
186 -h
187 -n
187 -n
188 -p
188 -p
189 -q
189 -q
190 -t
190 -t
191 -v
191 -v
192 -y
192 -y
193
193
194 Show an error if we use --options with an ambiguous abbreviation
194 Show an error if we use --options with an ambiguous abbreviation
195 $ hg debugcomplete --options s
195 $ hg debugcomplete --options s
196 hg: command 's' is ambiguous:
196 hg: command 's' is ambiguous:
197 serve showconfig status summary
197 serve showconfig status summary
198 [255]
198 [255]
199
199
200 Show all commands + options
200 Show all commands + options
201 $ hg debugcommands
201 $ hg debugcommands
202 add: include, exclude, subrepos, dry-run
202 add: include, exclude, subrepos, dry-run
203 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
203 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
204 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
204 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
205 commit: addremove, close-branch, amend, secret, edit, include, exclude, message, logfile, date, user, subrepos
205 commit: addremove, close-branch, amend, secret, edit, include, exclude, message, logfile, date, user, subrepos
206 diff: rev, change, text, git, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
206 diff: rev, change, text, git, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, include, exclude, subrepos
207 export: output, switch-parent, rev, text, git, nodates
207 export: output, switch-parent, rev, text, git, nodates
208 forget: include, exclude
208 forget: include, exclude
209 init: ssh, remotecmd, insecure
209 init: ssh, remotecmd, insecure
210 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
210 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
211 merge: force, rev, preview, tool
211 merge: force, rev, preview, tool
212 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
212 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
213 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
213 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
214 remove: after, force, subrepos, include, exclude
214 remove: after, force, subrepos, include, exclude
215 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
215 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
216 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
216 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
217 summary: remote
217 summary: remote
218 update: clean, check, date, rev, tool
218 update: clean, check, date, rev, tool
219 addremove: similarity, subrepos, include, exclude, dry-run
219 addremove: similarity, subrepos, include, exclude, dry-run
220 archive: no-decode, prefix, rev, type, subrepos, include, exclude
220 archive: no-decode, prefix, rev, type, subrepos, include, exclude
221 backout: merge, commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
221 backout: merge, commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
222 bisect: reset, good, bad, skip, extend, command, noupdate
222 bisect: reset, good, bad, skip, extend, command, noupdate
223 bookmarks: force, rev, delete, rename, inactive, template
223 bookmarks: force, rev, delete, rename, inactive, template
224 branch: force, clean
224 branch: force, clean
225 branches: active, closed, template
225 branches: active, closed, template
226 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
226 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
227 cat: output, rev, decode, include, exclude
227 cat: output, rev, decode, include, exclude
228 config: untrusted, edit, local, global
228 config: untrusted, edit, local, global
229 copy: after, force, include, exclude, dry-run
229 copy: after, force, include, exclude, dry-run
230 debugancestor:
230 debugancestor:
231 debugbuilddag: mergeable-file, overwritten-file, new-file
231 debugbuilddag: mergeable-file, overwritten-file, new-file
232 debugbundle: all
232 debugbundle: all
233 debugcheckstate:
233 debugcheckstate:
234 debugcommands:
234 debugcommands:
235 debugcomplete: options
235 debugcomplete: options
236 debugdag: tags, branches, dots, spaces
236 debugdag: tags, branches, dots, spaces
237 debugdata: changelog, manifest
237 debugdata: changelog, manifest
238 debugdate: extended
238 debugdate: extended
239 debugdirstate: nodates, datesort
239 debugdirstate: nodates, datesort
240 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
240 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
241 debugfileset: rev
241 debugfileset: rev
242 debugfsinfo:
242 debugfsinfo:
243 debuggetbundle: head, common, type
243 debuggetbundle: head, common, type
244 debugignore:
244 debugignore:
245 debugindex: changelog, manifest, format
245 debugindex: changelog, manifest, format
246 debugindexdot:
246 debugindexdot:
247 debuginstall:
247 debuginstall:
248 debugknown:
248 debugknown:
249 debuglabelcomplete:
249 debuglabelcomplete:
250 debuglocks: force-lock, force-wlock
250 debuglocks: force-lock, force-wlock
251 debugnamecomplete:
251 debugnamecomplete:
252 debugobsolete: flags, record-parents, rev, date, user
252 debugobsolete: flags, record-parents, rev, date, user
253 debugpathcomplete: full, normal, added, removed
253 debugpathcomplete: full, normal, added, removed
254 debugpushkey:
254 debugpushkey:
255 debugpvec:
255 debugpvec:
256 debugrebuilddirstate: rev
256 debugrebuilddirstate: rev
257 debugrename: rev
257 debugrename: rev
258 debugrevlog: changelog, manifest, dump
258 debugrevlog: changelog, manifest, dump
259 debugrevspec: optimize
259 debugrevspec: optimize
260 debugsetparents:
260 debugsetparents:
261 debugsub: rev
261 debugsub: rev
262 debugsuccessorssets:
262 debugsuccessorssets:
263 debugwalk: include, exclude
263 debugwalk: include, exclude
264 debugwireargs: three, four, five, ssh, remotecmd, insecure
264 debugwireargs: three, four, five, ssh, remotecmd, insecure
265 files: rev, print0, include, exclude, template
265 files: rev, print0, include, exclude, template
266 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
266 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
267 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
267 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
268 heads: rev, topo, active, closed, style, template
268 heads: rev, topo, active, closed, style, template
269 help: extension, command, keyword
269 help: extension, command, keyword
270 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
270 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
271 import: strip, base, edit, force, no-commit, bypass, partial, exact, import-branch, message, logfile, date, user, similarity
271 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
272 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
272 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
273 locate: rev, print0, fullpath, include, exclude
273 locate: rev, print0, fullpath, include, exclude
274 manifest: rev, all, template
274 manifest: rev, all, template
275 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
275 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
276 parents: rev, style, template
276 parents: rev, style, template
277 paths:
277 paths:
278 phase: public, draft, secret, force, rev
278 phase: public, draft, secret, force, rev
279 recover:
279 recover:
280 rename: after, force, include, exclude, dry-run
280 rename: after, force, include, exclude, dry-run
281 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
281 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
282 revert: all, date, rev, no-backup, include, exclude, dry-run
282 revert: all, date, rev, no-backup, include, exclude, dry-run
283 rollback: dry-run, force
283 rollback: dry-run, force
284 root:
284 root:
285 tag: force, local, rev, remove, edit, message, date, user
285 tag: force, local, rev, remove, edit, message, date, user
286 tags: template
286 tags: template
287 tip: patch, git, style, template
287 tip: patch, git, style, template
288 unbundle: update
288 unbundle: update
289 verify:
289 verify:
290 version:
290 version:
291
291
292 $ hg init a
292 $ hg init a
293 $ cd a
293 $ cd a
294 $ echo fee > fee
294 $ echo fee > fee
295 $ hg ci -q -Amfee
295 $ hg ci -q -Amfee
296 $ hg tag fee
296 $ hg tag fee
297 $ mkdir fie
297 $ mkdir fie
298 $ echo dead > fie/dead
298 $ echo dead > fie/dead
299 $ echo live > fie/live
299 $ echo live > fie/live
300 $ hg bookmark fo
300 $ hg bookmark fo
301 $ hg branch -q fie
301 $ hg branch -q fie
302 $ hg ci -q -Amfie
302 $ hg ci -q -Amfie
303 $ echo fo > fo
303 $ echo fo > fo
304 $ hg branch -qf default
304 $ hg branch -qf default
305 $ hg ci -q -Amfo
305 $ hg ci -q -Amfo
306 $ echo Fum > Fum
306 $ echo Fum > Fum
307 $ hg ci -q -AmFum
307 $ hg ci -q -AmFum
308 $ hg bookmark Fum
308 $ hg bookmark Fum
309
309
310 Test debugpathcomplete
310 Test debugpathcomplete
311
311
312 $ hg debugpathcomplete f
312 $ hg debugpathcomplete f
313 fee
313 fee
314 fie
314 fie
315 fo
315 fo
316 $ hg debugpathcomplete -f f
316 $ hg debugpathcomplete -f f
317 fee
317 fee
318 fie/dead
318 fie/dead
319 fie/live
319 fie/live
320 fo
320 fo
321
321
322 $ hg rm Fum
322 $ hg rm Fum
323 $ hg debugpathcomplete -r F
323 $ hg debugpathcomplete -r F
324 Fum
324 Fum
325
325
326 Test debugnamecomplete
326 Test debugnamecomplete
327
327
328 $ hg debugnamecomplete
328 $ hg debugnamecomplete
329 Fum
329 Fum
330 default
330 default
331 fee
331 fee
332 fie
332 fie
333 fo
333 fo
334 tip
334 tip
335 $ hg debugnamecomplete f
335 $ hg debugnamecomplete f
336 fee
336 fee
337 fie
337 fie
338 fo
338 fo
@@ -1,299 +1,302
1 $ echo "[extensions]" >> $HGRCPATH
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "purge=" >> $HGRCPATH
2 $ echo "purge=" >> $HGRCPATH
3
3
4 $ shortlog() {
4 $ shortlog() {
5 > hg log -G --template '{rev}:{node|short} {author} {date|hgdate} - {branch} - {desc|firstline}\n'
5 > hg log -G --template '{rev}:{node|short} {author} {date|hgdate} - {branch} - {desc|firstline}\n'
6 > }
6 > }
7
7
8 Test --bypass with other options
8 Test --bypass with other options
9
9
10 $ hg init repo-options
10 $ hg init repo-options
11 $ cd repo-options
11 $ cd repo-options
12 $ echo a > a
12 $ echo a > a
13 $ hg ci -Am adda
13 $ hg ci -Am adda
14 adding a
14 adding a
15 $ echo a >> a
15 $ echo a >> a
16 $ hg branch foo
16 $ hg branch foo
17 marked working directory as branch foo
17 marked working directory as branch foo
18 (branches are permanent and global, did you want a bookmark?)
18 (branches are permanent and global, did you want a bookmark?)
19 $ hg ci -Am changea
19 $ hg ci -Am changea
20 $ hg export . > ../test.diff
20 $ hg export . > ../test.diff
21 $ hg up null
21 $ hg up null
22 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
22 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
23
23
24 Test importing an existing revision
24 Test importing an existing revision
25 (this also tests that "hg import" disallows combination of '--exact'
25 (this also tests that "hg import" disallows combination of '--exact'
26 and '--edit')
26 and '--edit')
27
27
28 $ hg import --bypass --exact --edit ../test.diff
28 $ hg import --bypass --exact --edit ../test.diff
29 abort: cannot use --exact with --edit
29 abort: cannot use --exact with --edit
30 [255]
30 [255]
31 $ hg import --bypass --exact ../test.diff
31 $ hg import --bypass --exact ../test.diff
32 applying ../test.diff
32 applying ../test.diff
33 $ shortlog
33 $ shortlog
34 o 1:4e322f7ce8e3 test 0 0 - foo - changea
34 o 1:4e322f7ce8e3 test 0 0 - foo - changea
35 |
35 |
36 o 0:07f494440405 test 0 0 - default - adda
36 o 0:07f494440405 test 0 0 - default - adda
37
37
38
38
39 Test failure without --exact
39 Test failure without --exact
40
40
41 $ hg import --bypass ../test.diff
41 $ hg import --bypass ../test.diff
42 applying ../test.diff
42 applying ../test.diff
43 unable to find 'a' for patching
43 unable to find 'a' for patching
44 abort: patch failed to apply
44 abort: patch failed to apply
45 [255]
45 [255]
46 $ hg st
46 $ hg st
47 $ shortlog
47 $ shortlog
48 o 1:4e322f7ce8e3 test 0 0 - foo - changea
48 o 1:4e322f7ce8e3 test 0 0 - foo - changea
49 |
49 |
50 o 0:07f494440405 test 0 0 - default - adda
50 o 0:07f494440405 test 0 0 - default - adda
51
51
52
52
53 Test --user, --date and --message
53 Test --user, --date and --message
54
54
55 $ hg up 0
55 $ hg up 0
56 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
56 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
57 $ hg import --bypass --u test2 -d '1 0' -m patch2 ../test.diff
57 $ hg import --bypass --u test2 -d '1 0' -m patch2 ../test.diff
58 applying ../test.diff
58 applying ../test.diff
59 $ cat .hg/last-message.txt
59 $ cat .hg/last-message.txt
60 patch2 (no-eol)
60 patch2 (no-eol)
61 $ shortlog
61 $ shortlog
62 o 2:2e127d1da504 test2 1 0 - default - patch2
62 o 2:2e127d1da504 test2 1 0 - default - patch2
63 |
63 |
64 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
64 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
65 |/
65 |/
66 @ 0:07f494440405 test 0 0 - default - adda
66 @ 0:07f494440405 test 0 0 - default - adda
67
67
68 $ hg rollback
68 $ hg rollback
69 repository tip rolled back to revision 1 (undo import)
69 repository tip rolled back to revision 1 (undo import)
70
70
71 Test --import-branch
71 Test --import-branch
72 (this also tests that editor is not invoked for '--bypass', if the
72 (this also tests that editor is not invoked for '--bypass', if the
73 patch contains the commit message, regardless of '--edit')
73 patch contains the commit message, regardless of '--edit')
74
74
75 $ HGEDITOR=cat hg import --bypass --import-branch --edit ../test.diff
75 $ HGEDITOR=cat hg import --bypass --import-branch --edit ../test.diff
76 applying ../test.diff
76 applying ../test.diff
77 $ shortlog
77 $ shortlog
78 o 1:4e322f7ce8e3 test 0 0 - foo - changea
78 o 1:4e322f7ce8e3 test 0 0 - foo - changea
79 |
79 |
80 @ 0:07f494440405 test 0 0 - default - adda
80 @ 0:07f494440405 test 0 0 - default - adda
81
81
82 $ hg rollback
82 $ hg rollback
83 repository tip rolled back to revision 1 (undo import)
83 repository tip rolled back to revision 1 (undo import)
84
84
85 Test --strip
85 Test --strip
86
86
87 $ hg import --bypass --strip 0 - <<EOF
87 $ hg import --bypass --strip 0 - <<EOF
88 > # HG changeset patch
88 > # HG changeset patch
89 > # User test
89 > # User test
90 > # Date 0 0
90 > # Date 0 0
91 > # Branch foo
91 > # Branch foo
92 > # Node ID 4e322f7ce8e3e4203950eac9ece27bf7e45ffa6c
92 > # Node ID 4e322f7ce8e3e4203950eac9ece27bf7e45ffa6c
93 > # Parent 07f4944404050f47db2e5c5071e0e84e7a27bba9
93 > # Parent 07f4944404050f47db2e5c5071e0e84e7a27bba9
94 > changea
94 > changea
95 >
95 >
96 > diff -r 07f494440405 -r 4e322f7ce8e3 a
96 > diff -r 07f494440405 -r 4e322f7ce8e3 a
97 > --- a Thu Jan 01 00:00:00 1970 +0000
97 > --- a Thu Jan 01 00:00:00 1970 +0000
98 > +++ a Thu Jan 01 00:00:00 1970 +0000
98 > +++ a Thu Jan 01 00:00:00 1970 +0000
99 > @@ -1,1 +1,2 @@
99 > @@ -1,1 +1,2 @@
100 > a
100 > a
101 > +a
101 > +a
102 > EOF
102 > EOF
103 applying patch from stdin
103 applying patch from stdin
104 $ hg rollback
104 $ hg rollback
105 repository tip rolled back to revision 1 (undo import)
105 repository tip rolled back to revision 1 (undo import)
106
106
107 Test unsupported combinations
107 Test unsupported combinations
108
108
109 $ hg import --bypass --no-commit ../test.diff
109 $ hg import --bypass --no-commit ../test.diff
110 abort: cannot use --no-commit with --bypass
110 abort: cannot use --no-commit with --bypass
111 [255]
111 [255]
112 $ hg import --bypass --similarity 50 ../test.diff
112 $ hg import --bypass --similarity 50 ../test.diff
113 abort: cannot use --similarity with --bypass
113 abort: cannot use --similarity with --bypass
114 [255]
114 [255]
115 $ hg import --exact --prefix dir/ ../test.diff
116 abort: cannot use --exact with --prefix
117 [255]
115
118
116 Test commit editor
119 Test commit editor
117 (this also tests that editor is invoked, if the patch doesn't contain
120 (this also tests that editor is invoked, if the patch doesn't contain
118 the commit message, regardless of '--edit')
121 the commit message, regardless of '--edit')
119
122
120 $ cat > ../test.diff <<EOF
123 $ cat > ../test.diff <<EOF
121 > diff -r 07f494440405 -r 4e322f7ce8e3 a
124 > diff -r 07f494440405 -r 4e322f7ce8e3 a
122 > --- a/a Thu Jan 01 00:00:00 1970 +0000
125 > --- a/a Thu Jan 01 00:00:00 1970 +0000
123 > +++ b/a Thu Jan 01 00:00:00 1970 +0000
126 > +++ b/a Thu Jan 01 00:00:00 1970 +0000
124 > @@ -1,1 +1,2 @@
127 > @@ -1,1 +1,2 @@
125 > -a
128 > -a
126 > +b
129 > +b
127 > +c
130 > +c
128 > EOF
131 > EOF
129 $ HGEDITOR=cat hg import --bypass ../test.diff
132 $ HGEDITOR=cat hg import --bypass ../test.diff
130 applying ../test.diff
133 applying ../test.diff
131
134
132
135
133 HG: Enter commit message. Lines beginning with 'HG:' are removed.
136 HG: Enter commit message. Lines beginning with 'HG:' are removed.
134 HG: Leave message empty to abort commit.
137 HG: Leave message empty to abort commit.
135 HG: --
138 HG: --
136 HG: user: test
139 HG: user: test
137 HG: branch 'default'
140 HG: branch 'default'
138 HG: changed a
141 HG: changed a
139 abort: empty commit message
142 abort: empty commit message
140 [255]
143 [255]
141
144
142 Test patch.eol is handled
145 Test patch.eol is handled
143 (this also tests that editor is not invoked for '--bypass', if the
146 (this also tests that editor is not invoked for '--bypass', if the
144 commit message is explicitly specified, regardless of '--edit')
147 commit message is explicitly specified, regardless of '--edit')
145
148
146 $ $PYTHON -c 'file("a", "wb").write("a\r\n")'
149 $ $PYTHON -c 'file("a", "wb").write("a\r\n")'
147 $ hg ci -m makeacrlf
150 $ hg ci -m makeacrlf
148 $ HGEDITOR=cat hg import -m 'should fail because of eol' --edit --bypass ../test.diff
151 $ HGEDITOR=cat hg import -m 'should fail because of eol' --edit --bypass ../test.diff
149 applying ../test.diff
152 applying ../test.diff
150 patching file a
153 patching file a
151 Hunk #1 FAILED at 0
154 Hunk #1 FAILED at 0
152 abort: patch failed to apply
155 abort: patch failed to apply
153 [255]
156 [255]
154 $ hg --config patch.eol=auto import -d '0 0' -m 'test patch.eol' --bypass ../test.diff
157 $ hg --config patch.eol=auto import -d '0 0' -m 'test patch.eol' --bypass ../test.diff
155 applying ../test.diff
158 applying ../test.diff
156 $ shortlog
159 $ shortlog
157 o 3:c606edafba99 test 0 0 - default - test patch.eol
160 o 3:c606edafba99 test 0 0 - default - test patch.eol
158 |
161 |
159 @ 2:872023de769d test 0 0 - default - makeacrlf
162 @ 2:872023de769d test 0 0 - default - makeacrlf
160 |
163 |
161 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
164 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
162 |/
165 |/
163 o 0:07f494440405 test 0 0 - default - adda
166 o 0:07f494440405 test 0 0 - default - adda
164
167
165
168
166 Test applying multiple patches
169 Test applying multiple patches
167
170
168 $ hg up -qC 0
171 $ hg up -qC 0
169 $ echo e > e
172 $ echo e > e
170 $ hg ci -Am adde
173 $ hg ci -Am adde
171 adding e
174 adding e
172 created new head
175 created new head
173 $ hg export . > ../patch1.diff
176 $ hg export . > ../patch1.diff
174 $ hg up -qC 1
177 $ hg up -qC 1
175 $ echo f > f
178 $ echo f > f
176 $ hg ci -Am addf
179 $ hg ci -Am addf
177 adding f
180 adding f
178 $ hg export . > ../patch2.diff
181 $ hg export . > ../patch2.diff
179 $ cd ..
182 $ cd ..
180 $ hg clone -r1 repo-options repo-multi1
183 $ hg clone -r1 repo-options repo-multi1
181 adding changesets
184 adding changesets
182 adding manifests
185 adding manifests
183 adding file changes
186 adding file changes
184 added 2 changesets with 2 changes to 1 files
187 added 2 changesets with 2 changes to 1 files
185 updating to branch foo
188 updating to branch foo
186 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
189 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
187 $ cd repo-multi1
190 $ cd repo-multi1
188 $ hg up 0
191 $ hg up 0
189 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
192 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
190 $ hg import --bypass ../patch1.diff ../patch2.diff
193 $ hg import --bypass ../patch1.diff ../patch2.diff
191 applying ../patch1.diff
194 applying ../patch1.diff
192 applying ../patch2.diff
195 applying ../patch2.diff
193 $ shortlog
196 $ shortlog
194 o 3:bc8ca3f8a7c4 test 0 0 - default - addf
197 o 3:bc8ca3f8a7c4 test 0 0 - default - addf
195 |
198 |
196 o 2:16581080145e test 0 0 - default - adde
199 o 2:16581080145e test 0 0 - default - adde
197 |
200 |
198 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
201 | o 1:4e322f7ce8e3 test 0 0 - foo - changea
199 |/
202 |/
200 @ 0:07f494440405 test 0 0 - default - adda
203 @ 0:07f494440405 test 0 0 - default - adda
201
204
202
205
203 Test applying multiple patches with --exact
206 Test applying multiple patches with --exact
204
207
205 $ cd ..
208 $ cd ..
206 $ hg clone -r1 repo-options repo-multi2
209 $ hg clone -r1 repo-options repo-multi2
207 adding changesets
210 adding changesets
208 adding manifests
211 adding manifests
209 adding file changes
212 adding file changes
210 added 2 changesets with 2 changes to 1 files
213 added 2 changesets with 2 changes to 1 files
211 updating to branch foo
214 updating to branch foo
212 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
215 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
213 $ cd repo-multi2
216 $ cd repo-multi2
214 $ hg import --bypass --exact ../patch1.diff ../patch2.diff
217 $ hg import --bypass --exact ../patch1.diff ../patch2.diff
215 applying ../patch1.diff
218 applying ../patch1.diff
216 applying ../patch2.diff
219 applying ../patch2.diff
217 $ shortlog
220 $ shortlog
218 o 3:d60cb8989666 test 0 0 - foo - addf
221 o 3:d60cb8989666 test 0 0 - foo - addf
219 |
222 |
220 | o 2:16581080145e test 0 0 - default - adde
223 | o 2:16581080145e test 0 0 - default - adde
221 | |
224 | |
222 @ | 1:4e322f7ce8e3 test 0 0 - foo - changea
225 @ | 1:4e322f7ce8e3 test 0 0 - foo - changea
223 |/
226 |/
224 o 0:07f494440405 test 0 0 - default - adda
227 o 0:07f494440405 test 0 0 - default - adda
225
228
226
229
227 $ cd ..
230 $ cd ..
228
231
229 Test avoiding editor invocation at applying the patch with --exact
232 Test avoiding editor invocation at applying the patch with --exact
230 even if commit message is empty
233 even if commit message is empty
231
234
232 $ cd repo-options
235 $ cd repo-options
233
236
234 $ echo a >> a
237 $ echo a >> a
235 $ hg commit -m ' '
238 $ hg commit -m ' '
236 $ hg tip -T "{node}\n"
239 $ hg tip -T "{node}\n"
237 1b77bc7d1db9f0e7f1716d515b630516ab386c89
240 1b77bc7d1db9f0e7f1716d515b630516ab386c89
238 $ hg export -o ../empty-log.diff .
241 $ hg export -o ../empty-log.diff .
239 $ hg update -q -C ".^1"
242 $ hg update -q -C ".^1"
240 $ hg --config extensions.strip= strip -q tip
243 $ hg --config extensions.strip= strip -q tip
241 $ HGEDITOR=cat hg import --exact --bypass ../empty-log.diff
244 $ HGEDITOR=cat hg import --exact --bypass ../empty-log.diff
242 applying ../empty-log.diff
245 applying ../empty-log.diff
243 $ hg tip -T "{node}\n"
246 $ hg tip -T "{node}\n"
244 1b77bc7d1db9f0e7f1716d515b630516ab386c89
247 1b77bc7d1db9f0e7f1716d515b630516ab386c89
245
248
246 $ cd ..
249 $ cd ..
247
250
248 #if symlink execbit
251 #if symlink execbit
249
252
250 Test complicated patch with --exact
253 Test complicated patch with --exact
251
254
252 $ hg init repo-exact
255 $ hg init repo-exact
253 $ cd repo-exact
256 $ cd repo-exact
254 $ echo a > a
257 $ echo a > a
255 $ echo c > c
258 $ echo c > c
256 $ echo d > d
259 $ echo d > d
257 $ echo e > e
260 $ echo e > e
258 $ echo f > f
261 $ echo f > f
259 $ chmod +x f
262 $ chmod +x f
260 $ ln -s c linkc
263 $ ln -s c linkc
261 $ hg ci -Am t
264 $ hg ci -Am t
262 adding a
265 adding a
263 adding c
266 adding c
264 adding d
267 adding d
265 adding e
268 adding e
266 adding f
269 adding f
267 adding linkc
270 adding linkc
268 $ hg cp a aa1
271 $ hg cp a aa1
269 $ echo b >> a
272 $ echo b >> a
270 $ echo b > b
273 $ echo b > b
271 $ hg add b
274 $ hg add b
272 $ hg cp a aa2
275 $ hg cp a aa2
273 $ echo aa >> aa2
276 $ echo aa >> aa2
274 $ chmod +x e
277 $ chmod +x e
275 $ chmod -x f
278 $ chmod -x f
276 $ ln -s a linka
279 $ ln -s a linka
277 $ hg rm d
280 $ hg rm d
278 $ hg rm linkc
281 $ hg rm linkc
279 $ hg mv c cc
282 $ hg mv c cc
280 $ hg ci -m patch
283 $ hg ci -m patch
281 $ hg export --git . > ../test.diff
284 $ hg export --git . > ../test.diff
282 $ hg up -C null
285 $ hg up -C null
283 0 files updated, 0 files merged, 7 files removed, 0 files unresolved
286 0 files updated, 0 files merged, 7 files removed, 0 files unresolved
284 $ hg purge
287 $ hg purge
285 $ hg st
288 $ hg st
286 $ hg import --bypass --exact ../test.diff
289 $ hg import --bypass --exact ../test.diff
287 applying ../test.diff
290 applying ../test.diff
288
291
289 The patch should have matched the exported revision and generated no additional
292 The patch should have matched the exported revision and generated no additional
290 data. If not, diff both heads to debug it.
293 data. If not, diff both heads to debug it.
291
294
292 $ shortlog
295 $ shortlog
293 o 1:2978fd5c8aa4 test 0 0 - default - patch
296 o 1:2978fd5c8aa4 test 0 0 - default - patch
294 |
297 |
295 o 0:a0e19e636a43 test 0 0 - default - t
298 o 0:a0e19e636a43 test 0 0 - default - t
296
299
297 #endif
300 #endif
298
301
299 $ cd ..
302 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now