##// END OF EJS Templates
tags: change field name of formatter output to be the same as log command...
Yuya Nishihara -
r22553:67b6b82a default
parent child Browse files
Show More
@@ -1,6228 +1,6228 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno, shlex
11 import os, re, difflib, time, tempfile, errno, shlex
12 import sys
12 import sys
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
21 import dagparser, context, simplemerge, graphmod
22 import random
22 import random
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo
24 import phases, obsolete, exchange
24 import phases, obsolete, exchange
25
25
26 table = {}
26 table = {}
27
27
28 command = cmdutil.command(table)
28 command = cmdutil.command(table)
29
29
30 # Space delimited list of commands that don't require local repositories.
30 # Space delimited list of commands that don't require local repositories.
31 # This should be populated by passing norepo=True into the @command decorator.
31 # This should be populated by passing norepo=True into the @command decorator.
32 norepo = ''
32 norepo = ''
33 # Space delimited list of commands that optionally require local repositories.
33 # Space delimited list of commands that optionally require local repositories.
34 # This should be populated by passing optionalrepo=True into the @command
34 # This should be populated by passing optionalrepo=True into the @command
35 # decorator.
35 # decorator.
36 optionalrepo = ''
36 optionalrepo = ''
37 # Space delimited list of commands that will examine arguments looking for
37 # Space delimited list of commands that will examine arguments looking for
38 # a repository. This should be populated by passing inferrepo=True into the
38 # a repository. This should be populated by passing inferrepo=True into the
39 # @command decorator.
39 # @command decorator.
40 inferrepo = ''
40 inferrepo = ''
41
41
42 # common command options
42 # common command options
43
43
44 globalopts = [
44 globalopts = [
45 ('R', 'repository', '',
45 ('R', 'repository', '',
46 _('repository root directory or name of overlay bundle file'),
46 _('repository root directory or name of overlay bundle file'),
47 _('REPO')),
47 _('REPO')),
48 ('', 'cwd', '',
48 ('', 'cwd', '',
49 _('change working directory'), _('DIR')),
49 _('change working directory'), _('DIR')),
50 ('y', 'noninteractive', None,
50 ('y', 'noninteractive', None,
51 _('do not prompt, automatically pick the first choice for all prompts')),
51 _('do not prompt, automatically pick the first choice for all prompts')),
52 ('q', 'quiet', None, _('suppress output')),
52 ('q', 'quiet', None, _('suppress output')),
53 ('v', 'verbose', None, _('enable additional output')),
53 ('v', 'verbose', None, _('enable additional output')),
54 ('', 'config', [],
54 ('', 'config', [],
55 _('set/override config option (use \'section.name=value\')'),
55 _('set/override config option (use \'section.name=value\')'),
56 _('CONFIG')),
56 _('CONFIG')),
57 ('', 'debug', None, _('enable debugging output')),
57 ('', 'debug', None, _('enable debugging output')),
58 ('', 'debugger', None, _('start debugger')),
58 ('', 'debugger', None, _('start debugger')),
59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
59 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
60 _('ENCODE')),
60 _('ENCODE')),
61 ('', 'encodingmode', encoding.encodingmode,
61 ('', 'encodingmode', encoding.encodingmode,
62 _('set the charset encoding mode'), _('MODE')),
62 _('set the charset encoding mode'), _('MODE')),
63 ('', 'traceback', None, _('always print a traceback on exception')),
63 ('', 'traceback', None, _('always print a traceback on exception')),
64 ('', 'time', None, _('time how long the command takes')),
64 ('', 'time', None, _('time how long the command takes')),
65 ('', 'profile', None, _('print command execution profile')),
65 ('', 'profile', None, _('print command execution profile')),
66 ('', 'version', None, _('output version information and exit')),
66 ('', 'version', None, _('output version information and exit')),
67 ('h', 'help', None, _('display help and exit')),
67 ('h', 'help', None, _('display help and exit')),
68 ('', 'hidden', False, _('consider hidden changesets')),
68 ('', 'hidden', False, _('consider hidden changesets')),
69 ]
69 ]
70
70
71 dryrunopts = [('n', 'dry-run', None,
71 dryrunopts = [('n', 'dry-run', None,
72 _('do not perform actions, just print output'))]
72 _('do not perform actions, just print output'))]
73
73
74 remoteopts = [
74 remoteopts = [
75 ('e', 'ssh', '',
75 ('e', 'ssh', '',
76 _('specify ssh command to use'), _('CMD')),
76 _('specify ssh command to use'), _('CMD')),
77 ('', 'remotecmd', '',
77 ('', 'remotecmd', '',
78 _('specify hg command to run on the remote side'), _('CMD')),
78 _('specify hg command to run on the remote side'), _('CMD')),
79 ('', 'insecure', None,
79 ('', 'insecure', None,
80 _('do not verify server certificate (ignoring web.cacerts config)')),
80 _('do not verify server certificate (ignoring web.cacerts config)')),
81 ]
81 ]
82
82
83 walkopts = [
83 walkopts = [
84 ('I', 'include', [],
84 ('I', 'include', [],
85 _('include names matching the given patterns'), _('PATTERN')),
85 _('include names matching the given patterns'), _('PATTERN')),
86 ('X', 'exclude', [],
86 ('X', 'exclude', [],
87 _('exclude names matching the given patterns'), _('PATTERN')),
87 _('exclude names matching the given patterns'), _('PATTERN')),
88 ]
88 ]
89
89
90 commitopts = [
90 commitopts = [
91 ('m', 'message', '',
91 ('m', 'message', '',
92 _('use text as commit message'), _('TEXT')),
92 _('use text as commit message'), _('TEXT')),
93 ('l', 'logfile', '',
93 ('l', 'logfile', '',
94 _('read commit message from file'), _('FILE')),
94 _('read commit message from file'), _('FILE')),
95 ]
95 ]
96
96
97 commitopts2 = [
97 commitopts2 = [
98 ('d', 'date', '',
98 ('d', 'date', '',
99 _('record the specified date as commit date'), _('DATE')),
99 _('record the specified date as commit date'), _('DATE')),
100 ('u', 'user', '',
100 ('u', 'user', '',
101 _('record the specified user as committer'), _('USER')),
101 _('record the specified user as committer'), _('USER')),
102 ]
102 ]
103
103
104 # hidden for now
104 # hidden for now
105 formatteropts = [
105 formatteropts = [
106 ('T', 'template', '',
106 ('T', 'template', '',
107 _('display with template (DEPRECATED)'), _('TEMPLATE')),
107 _('display with template (DEPRECATED)'), _('TEMPLATE')),
108 ]
108 ]
109
109
110 templateopts = [
110 templateopts = [
111 ('', 'style', '',
111 ('', 'style', '',
112 _('display using template map file (DEPRECATED)'), _('STYLE')),
112 _('display using template map file (DEPRECATED)'), _('STYLE')),
113 ('T', 'template', '',
113 ('T', 'template', '',
114 _('display with template'), _('TEMPLATE')),
114 _('display with template'), _('TEMPLATE')),
115 ]
115 ]
116
116
117 logopts = [
117 logopts = [
118 ('p', 'patch', None, _('show patch')),
118 ('p', 'patch', None, _('show patch')),
119 ('g', 'git', None, _('use git extended diff format')),
119 ('g', 'git', None, _('use git extended diff format')),
120 ('l', 'limit', '',
120 ('l', 'limit', '',
121 _('limit number of changes displayed'), _('NUM')),
121 _('limit number of changes displayed'), _('NUM')),
122 ('M', 'no-merges', None, _('do not show merges')),
122 ('M', 'no-merges', None, _('do not show merges')),
123 ('', 'stat', None, _('output diffstat-style summary of changes')),
123 ('', 'stat', None, _('output diffstat-style summary of changes')),
124 ('G', 'graph', None, _("show the revision DAG")),
124 ('G', 'graph', None, _("show the revision DAG")),
125 ] + templateopts
125 ] + templateopts
126
126
127 diffopts = [
127 diffopts = [
128 ('a', 'text', None, _('treat all files as text')),
128 ('a', 'text', None, _('treat all files as text')),
129 ('g', 'git', None, _('use git extended diff format')),
129 ('g', 'git', None, _('use git extended diff format')),
130 ('', 'nodates', None, _('omit dates from diff headers'))
130 ('', 'nodates', None, _('omit dates from diff headers'))
131 ]
131 ]
132
132
133 diffwsopts = [
133 diffwsopts = [
134 ('w', 'ignore-all-space', None,
134 ('w', 'ignore-all-space', None,
135 _('ignore white space when comparing lines')),
135 _('ignore white space when comparing lines')),
136 ('b', 'ignore-space-change', None,
136 ('b', 'ignore-space-change', None,
137 _('ignore changes in the amount of white space')),
137 _('ignore changes in the amount of white space')),
138 ('B', 'ignore-blank-lines', None,
138 ('B', 'ignore-blank-lines', None,
139 _('ignore changes whose lines are all blank')),
139 _('ignore changes whose lines are all blank')),
140 ]
140 ]
141
141
142 diffopts2 = [
142 diffopts2 = [
143 ('p', 'show-function', None, _('show which function each change is in')),
143 ('p', 'show-function', None, _('show which function each change is in')),
144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
144 ('', 'reverse', None, _('produce a diff that undoes the changes')),
145 ] + diffwsopts + [
145 ] + diffwsopts + [
146 ('U', 'unified', '',
146 ('U', 'unified', '',
147 _('number of lines of context to show'), _('NUM')),
147 _('number of lines of context to show'), _('NUM')),
148 ('', 'stat', None, _('output diffstat-style summary of changes')),
148 ('', 'stat', None, _('output diffstat-style summary of changes')),
149 ]
149 ]
150
150
151 mergetoolopts = [
151 mergetoolopts = [
152 ('t', 'tool', '', _('specify merge tool')),
152 ('t', 'tool', '', _('specify merge tool')),
153 ]
153 ]
154
154
155 similarityopts = [
155 similarityopts = [
156 ('s', 'similarity', '',
156 ('s', 'similarity', '',
157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
157 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
158 ]
158 ]
159
159
160 subrepoopts = [
160 subrepoopts = [
161 ('S', 'subrepos', None,
161 ('S', 'subrepos', None,
162 _('recurse into subrepositories'))
162 _('recurse into subrepositories'))
163 ]
163 ]
164
164
165 # Commands start here, listed alphabetically
165 # Commands start here, listed alphabetically
166
166
167 @command('^add',
167 @command('^add',
168 walkopts + subrepoopts + dryrunopts,
168 walkopts + subrepoopts + dryrunopts,
169 _('[OPTION]... [FILE]...'),
169 _('[OPTION]... [FILE]...'),
170 inferrepo=True)
170 inferrepo=True)
171 def add(ui, repo, *pats, **opts):
171 def add(ui, repo, *pats, **opts):
172 """add the specified files on the next commit
172 """add the specified files on the next commit
173
173
174 Schedule files to be version controlled and added to the
174 Schedule files to be version controlled and added to the
175 repository.
175 repository.
176
176
177 The files will be added to the repository at the next commit. To
177 The files will be added to the repository at the next commit. To
178 undo an add before that, see :hg:`forget`.
178 undo an add before that, see :hg:`forget`.
179
179
180 If no names are given, add all files to the repository.
180 If no names are given, add all files to the repository.
181
181
182 .. container:: verbose
182 .. container:: verbose
183
183
184 An example showing how new (unknown) files are added
184 An example showing how new (unknown) files are added
185 automatically by :hg:`add`::
185 automatically by :hg:`add`::
186
186
187 $ ls
187 $ ls
188 foo.c
188 foo.c
189 $ hg status
189 $ hg status
190 ? foo.c
190 ? foo.c
191 $ hg add
191 $ hg add
192 adding foo.c
192 adding foo.c
193 $ hg status
193 $ hg status
194 A foo.c
194 A foo.c
195
195
196 Returns 0 if all files are successfully added.
196 Returns 0 if all files are successfully added.
197 """
197 """
198
198
199 m = scmutil.match(repo[None], pats, opts)
199 m = scmutil.match(repo[None], pats, opts)
200 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
200 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
201 opts.get('subrepos'), prefix="", explicitonly=False)
201 opts.get('subrepos'), prefix="", explicitonly=False)
202 return rejected and 1 or 0
202 return rejected and 1 or 0
203
203
204 @command('addremove',
204 @command('addremove',
205 similarityopts + walkopts + dryrunopts,
205 similarityopts + walkopts + dryrunopts,
206 _('[OPTION]... [FILE]...'),
206 _('[OPTION]... [FILE]...'),
207 inferrepo=True)
207 inferrepo=True)
208 def addremove(ui, repo, *pats, **opts):
208 def addremove(ui, repo, *pats, **opts):
209 """add all new files, delete all missing files
209 """add all new files, delete all missing files
210
210
211 Add all new files and remove all missing files from the
211 Add all new files and remove all missing files from the
212 repository.
212 repository.
213
213
214 New files are ignored if they match any of the patterns in
214 New files are ignored if they match any of the patterns in
215 ``.hgignore``. As with add, these changes take effect at the next
215 ``.hgignore``. As with add, these changes take effect at the next
216 commit.
216 commit.
217
217
218 Use the -s/--similarity option to detect renamed files. This
218 Use the -s/--similarity option to detect renamed files. This
219 option takes a percentage between 0 (disabled) and 100 (files must
219 option takes a percentage between 0 (disabled) and 100 (files must
220 be identical) as its parameter. With a parameter greater than 0,
220 be identical) as its parameter. With a parameter greater than 0,
221 this compares every removed file with every added file and records
221 this compares every removed file with every added file and records
222 those similar enough as renames. Detecting renamed files this way
222 those similar enough as renames. Detecting renamed files this way
223 can be expensive. After using this option, :hg:`status -C` can be
223 can be expensive. After using this option, :hg:`status -C` can be
224 used to check which files were identified as moved or renamed. If
224 used to check which files were identified as moved or renamed. If
225 not specified, -s/--similarity defaults to 100 and only renames of
225 not specified, -s/--similarity defaults to 100 and only renames of
226 identical files are detected.
226 identical files are detected.
227
227
228 Returns 0 if all files are successfully added.
228 Returns 0 if all files are successfully added.
229 """
229 """
230 try:
230 try:
231 sim = float(opts.get('similarity') or 100)
231 sim = float(opts.get('similarity') or 100)
232 except ValueError:
232 except ValueError:
233 raise util.Abort(_('similarity must be a number'))
233 raise util.Abort(_('similarity must be a number'))
234 if sim < 0 or sim > 100:
234 if sim < 0 or sim > 100:
235 raise util.Abort(_('similarity must be between 0 and 100'))
235 raise util.Abort(_('similarity must be between 0 and 100'))
236 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
236 return scmutil.addremove(repo, pats, opts, similarity=sim / 100.0)
237
237
238 @command('^annotate|blame',
238 @command('^annotate|blame',
239 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
239 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
240 ('', 'follow', None,
240 ('', 'follow', None,
241 _('follow copies/renames and list the filename (DEPRECATED)')),
241 _('follow copies/renames and list the filename (DEPRECATED)')),
242 ('', 'no-follow', None, _("don't follow copies and renames")),
242 ('', 'no-follow', None, _("don't follow copies and renames")),
243 ('a', 'text', None, _('treat all files as text')),
243 ('a', 'text', None, _('treat all files as text')),
244 ('u', 'user', None, _('list the author (long with -v)')),
244 ('u', 'user', None, _('list the author (long with -v)')),
245 ('f', 'file', None, _('list the filename')),
245 ('f', 'file', None, _('list the filename')),
246 ('d', 'date', None, _('list the date (short with -q)')),
246 ('d', 'date', None, _('list the date (short with -q)')),
247 ('n', 'number', None, _('list the revision number (default)')),
247 ('n', 'number', None, _('list the revision number (default)')),
248 ('c', 'changeset', None, _('list the changeset')),
248 ('c', 'changeset', None, _('list the changeset')),
249 ('l', 'line-number', None, _('show line number at the first appearance'))
249 ('l', 'line-number', None, _('show line number at the first appearance'))
250 ] + diffwsopts + walkopts + formatteropts,
250 ] + diffwsopts + walkopts + formatteropts,
251 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
251 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
252 inferrepo=True)
252 inferrepo=True)
253 def annotate(ui, repo, *pats, **opts):
253 def annotate(ui, repo, *pats, **opts):
254 """show changeset information by line for each file
254 """show changeset information by line for each file
255
255
256 List changes in files, showing the revision id responsible for
256 List changes in files, showing the revision id responsible for
257 each line
257 each line
258
258
259 This command is useful for discovering when a change was made and
259 This command is useful for discovering when a change was made and
260 by whom.
260 by whom.
261
261
262 Without the -a/--text option, annotate will avoid processing files
262 Without the -a/--text option, annotate will avoid processing files
263 it detects as binary. With -a, annotate will annotate the file
263 it detects as binary. With -a, annotate will annotate the file
264 anyway, although the results will probably be neither useful
264 anyway, although the results will probably be neither useful
265 nor desirable.
265 nor desirable.
266
266
267 Returns 0 on success.
267 Returns 0 on success.
268 """
268 """
269 if not pats:
269 if not pats:
270 raise util.Abort(_('at least one filename or pattern is required'))
270 raise util.Abort(_('at least one filename or pattern is required'))
271
271
272 if opts.get('follow'):
272 if opts.get('follow'):
273 # --follow is deprecated and now just an alias for -f/--file
273 # --follow is deprecated and now just an alias for -f/--file
274 # to mimic the behavior of Mercurial before version 1.5
274 # to mimic the behavior of Mercurial before version 1.5
275 opts['file'] = True
275 opts['file'] = True
276
276
277 fm = ui.formatter('annotate', opts)
277 fm = ui.formatter('annotate', opts)
278 datefunc = ui.quiet and util.shortdate or util.datestr
278 datefunc = ui.quiet and util.shortdate or util.datestr
279 if fm or ui.debugflag:
279 if fm or ui.debugflag:
280 hexfn = hex
280 hexfn = hex
281 else:
281 else:
282 hexfn = short
282 hexfn = short
283
283
284 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
284 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
285 ('number', ' ', lambda x: x[0].rev(), str),
285 ('number', ' ', lambda x: x[0].rev(), str),
286 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
286 ('changeset', ' ', lambda x: hexfn(x[0].node()), str),
287 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
287 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
288 ('file', ' ', lambda x: x[0].path(), str),
288 ('file', ' ', lambda x: x[0].path(), str),
289 ('line_number', ':', lambda x: x[1], str),
289 ('line_number', ':', lambda x: x[1], str),
290 ]
290 ]
291 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
291 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
292
292
293 if (not opts.get('user') and not opts.get('changeset')
293 if (not opts.get('user') and not opts.get('changeset')
294 and not opts.get('date') and not opts.get('file')):
294 and not opts.get('date') and not opts.get('file')):
295 opts['number'] = True
295 opts['number'] = True
296
296
297 linenumber = opts.get('line_number') is not None
297 linenumber = opts.get('line_number') is not None
298 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
298 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
299 raise util.Abort(_('at least one of -n/-c is required for -l'))
299 raise util.Abort(_('at least one of -n/-c is required for -l'))
300
300
301 if fm:
301 if fm:
302 def makefunc(get, fmt):
302 def makefunc(get, fmt):
303 return get
303 return get
304 else:
304 else:
305 def makefunc(get, fmt):
305 def makefunc(get, fmt):
306 return lambda x: fmt(get(x))
306 return lambda x: fmt(get(x))
307 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
307 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
308 if opts.get(op)]
308 if opts.get(op)]
309 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
309 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
310 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
310 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
311 if opts.get(op))
311 if opts.get(op))
312
312
313 def bad(x, y):
313 def bad(x, y):
314 raise util.Abort("%s: %s" % (x, y))
314 raise util.Abort("%s: %s" % (x, y))
315
315
316 ctx = scmutil.revsingle(repo, opts.get('rev'))
316 ctx = scmutil.revsingle(repo, opts.get('rev'))
317 m = scmutil.match(ctx, pats, opts)
317 m = scmutil.match(ctx, pats, opts)
318 m.bad = bad
318 m.bad = bad
319 follow = not opts.get('no_follow')
319 follow = not opts.get('no_follow')
320 diffopts = patch.diffopts(ui, opts, section='annotate')
320 diffopts = patch.diffopts(ui, opts, section='annotate')
321 for abs in ctx.walk(m):
321 for abs in ctx.walk(m):
322 fctx = ctx[abs]
322 fctx = ctx[abs]
323 if not opts.get('text') and util.binary(fctx.data()):
323 if not opts.get('text') and util.binary(fctx.data()):
324 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
324 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
325 continue
325 continue
326
326
327 lines = fctx.annotate(follow=follow, linenumber=linenumber,
327 lines = fctx.annotate(follow=follow, linenumber=linenumber,
328 diffopts=diffopts)
328 diffopts=diffopts)
329 formats = []
329 formats = []
330 pieces = []
330 pieces = []
331
331
332 for f, sep in funcmap:
332 for f, sep in funcmap:
333 l = [f(n) for n, dummy in lines]
333 l = [f(n) for n, dummy in lines]
334 if l:
334 if l:
335 if fm:
335 if fm:
336 formats.append(['%s' for x in l])
336 formats.append(['%s' for x in l])
337 else:
337 else:
338 sizes = [encoding.colwidth(x) for x in l]
338 sizes = [encoding.colwidth(x) for x in l]
339 ml = max(sizes)
339 ml = max(sizes)
340 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
340 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
341 pieces.append(l)
341 pieces.append(l)
342
342
343 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
343 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
344 fm.startitem()
344 fm.startitem()
345 fm.write(fields, "".join(f), *p)
345 fm.write(fields, "".join(f), *p)
346 fm.write('line', ": %s", l[1])
346 fm.write('line', ": %s", l[1])
347
347
348 if lines and not lines[-1][1].endswith('\n'):
348 if lines and not lines[-1][1].endswith('\n'):
349 fm.plain('\n')
349 fm.plain('\n')
350
350
351 fm.end()
351 fm.end()
352
352
353 @command('archive',
353 @command('archive',
354 [('', 'no-decode', None, _('do not pass files through decoders')),
354 [('', 'no-decode', None, _('do not pass files through decoders')),
355 ('p', 'prefix', '', _('directory prefix for files in archive'),
355 ('p', 'prefix', '', _('directory prefix for files in archive'),
356 _('PREFIX')),
356 _('PREFIX')),
357 ('r', 'rev', '', _('revision to distribute'), _('REV')),
357 ('r', 'rev', '', _('revision to distribute'), _('REV')),
358 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
358 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
359 ] + subrepoopts + walkopts,
359 ] + subrepoopts + walkopts,
360 _('[OPTION]... DEST'))
360 _('[OPTION]... DEST'))
361 def archive(ui, repo, dest, **opts):
361 def archive(ui, repo, dest, **opts):
362 '''create an unversioned archive of a repository revision
362 '''create an unversioned archive of a repository revision
363
363
364 By default, the revision used is the parent of the working
364 By default, the revision used is the parent of the working
365 directory; use -r/--rev to specify a different revision.
365 directory; use -r/--rev to specify a different revision.
366
366
367 The archive type is automatically detected based on file
367 The archive type is automatically detected based on file
368 extension (or override using -t/--type).
368 extension (or override using -t/--type).
369
369
370 .. container:: verbose
370 .. container:: verbose
371
371
372 Examples:
372 Examples:
373
373
374 - create a zip file containing the 1.0 release::
374 - create a zip file containing the 1.0 release::
375
375
376 hg archive -r 1.0 project-1.0.zip
376 hg archive -r 1.0 project-1.0.zip
377
377
378 - create a tarball excluding .hg files::
378 - create a tarball excluding .hg files::
379
379
380 hg archive project.tar.gz -X ".hg*"
380 hg archive project.tar.gz -X ".hg*"
381
381
382 Valid types are:
382 Valid types are:
383
383
384 :``files``: a directory full of files (default)
384 :``files``: a directory full of files (default)
385 :``tar``: tar archive, uncompressed
385 :``tar``: tar archive, uncompressed
386 :``tbz2``: tar archive, compressed using bzip2
386 :``tbz2``: tar archive, compressed using bzip2
387 :``tgz``: tar archive, compressed using gzip
387 :``tgz``: tar archive, compressed using gzip
388 :``uzip``: zip archive, uncompressed
388 :``uzip``: zip archive, uncompressed
389 :``zip``: zip archive, compressed using deflate
389 :``zip``: zip archive, compressed using deflate
390
390
391 The exact name of the destination archive or directory is given
391 The exact name of the destination archive or directory is given
392 using a format string; see :hg:`help export` for details.
392 using a format string; see :hg:`help export` for details.
393
393
394 Each member added to an archive file has a directory prefix
394 Each member added to an archive file has a directory prefix
395 prepended. Use -p/--prefix to specify a format string for the
395 prepended. Use -p/--prefix to specify a format string for the
396 prefix. The default is the basename of the archive, with suffixes
396 prefix. The default is the basename of the archive, with suffixes
397 removed.
397 removed.
398
398
399 Returns 0 on success.
399 Returns 0 on success.
400 '''
400 '''
401
401
402 ctx = scmutil.revsingle(repo, opts.get('rev'))
402 ctx = scmutil.revsingle(repo, opts.get('rev'))
403 if not ctx:
403 if not ctx:
404 raise util.Abort(_('no working directory: please specify a revision'))
404 raise util.Abort(_('no working directory: please specify a revision'))
405 node = ctx.node()
405 node = ctx.node()
406 dest = cmdutil.makefilename(repo, dest, node)
406 dest = cmdutil.makefilename(repo, dest, node)
407 if os.path.realpath(dest) == repo.root:
407 if os.path.realpath(dest) == repo.root:
408 raise util.Abort(_('repository root cannot be destination'))
408 raise util.Abort(_('repository root cannot be destination'))
409
409
410 kind = opts.get('type') or archival.guesskind(dest) or 'files'
410 kind = opts.get('type') or archival.guesskind(dest) or 'files'
411 prefix = opts.get('prefix')
411 prefix = opts.get('prefix')
412
412
413 if dest == '-':
413 if dest == '-':
414 if kind == 'files':
414 if kind == 'files':
415 raise util.Abort(_('cannot archive plain files to stdout'))
415 raise util.Abort(_('cannot archive plain files to stdout'))
416 dest = cmdutil.makefileobj(repo, dest)
416 dest = cmdutil.makefileobj(repo, dest)
417 if not prefix:
417 if not prefix:
418 prefix = os.path.basename(repo.root) + '-%h'
418 prefix = os.path.basename(repo.root) + '-%h'
419
419
420 prefix = cmdutil.makefilename(repo, prefix, node)
420 prefix = cmdutil.makefilename(repo, prefix, node)
421 matchfn = scmutil.match(ctx, [], opts)
421 matchfn = scmutil.match(ctx, [], opts)
422 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
422 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
423 matchfn, prefix, subrepos=opts.get('subrepos'))
423 matchfn, prefix, subrepos=opts.get('subrepos'))
424
424
425 @command('backout',
425 @command('backout',
426 [('', 'merge', None, _('merge with old dirstate parent after backout')),
426 [('', 'merge', None, _('merge with old dirstate parent after backout')),
427 ('', 'parent', '',
427 ('', 'parent', '',
428 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
428 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
429 ('r', 'rev', '', _('revision to backout'), _('REV')),
429 ('r', 'rev', '', _('revision to backout'), _('REV')),
430 ('e', 'edit', False, _('invoke editor on commit messages')),
430 ('e', 'edit', False, _('invoke editor on commit messages')),
431 ] + mergetoolopts + walkopts + commitopts + commitopts2,
431 ] + mergetoolopts + walkopts + commitopts + commitopts2,
432 _('[OPTION]... [-r] REV'))
432 _('[OPTION]... [-r] REV'))
433 def backout(ui, repo, node=None, rev=None, **opts):
433 def backout(ui, repo, node=None, rev=None, **opts):
434 '''reverse effect of earlier changeset
434 '''reverse effect of earlier changeset
435
435
436 Prepare a new changeset with the effect of REV undone in the
436 Prepare a new changeset with the effect of REV undone in the
437 current working directory.
437 current working directory.
438
438
439 If REV is the parent of the working directory, then this new changeset
439 If REV is the parent of the working directory, then this new changeset
440 is committed automatically. Otherwise, hg needs to merge the
440 is committed automatically. Otherwise, hg needs to merge the
441 changes and the merged result is left uncommitted.
441 changes and the merged result is left uncommitted.
442
442
443 .. note::
443 .. note::
444
444
445 backout cannot be used to fix either an unwanted or
445 backout cannot be used to fix either an unwanted or
446 incorrect merge.
446 incorrect merge.
447
447
448 .. container:: verbose
448 .. container:: verbose
449
449
450 By default, the pending changeset will have one parent,
450 By default, the pending changeset will have one parent,
451 maintaining a linear history. With --merge, the pending
451 maintaining a linear history. With --merge, the pending
452 changeset will instead have two parents: the old parent of the
452 changeset will instead have two parents: the old parent of the
453 working directory and a new child of REV that simply undoes REV.
453 working directory and a new child of REV that simply undoes REV.
454
454
455 Before version 1.7, the behavior without --merge was equivalent
455 Before version 1.7, the behavior without --merge was equivalent
456 to specifying --merge followed by :hg:`update --clean .` to
456 to specifying --merge followed by :hg:`update --clean .` to
457 cancel the merge and leave the child of REV as a head to be
457 cancel the merge and leave the child of REV as a head to be
458 merged separately.
458 merged separately.
459
459
460 See :hg:`help dates` for a list of formats valid for -d/--date.
460 See :hg:`help dates` for a list of formats valid for -d/--date.
461
461
462 Returns 0 on success, 1 if nothing to backout or there are unresolved
462 Returns 0 on success, 1 if nothing to backout or there are unresolved
463 files.
463 files.
464 '''
464 '''
465 if rev and node:
465 if rev and node:
466 raise util.Abort(_("please specify just one revision"))
466 raise util.Abort(_("please specify just one revision"))
467
467
468 if not rev:
468 if not rev:
469 rev = node
469 rev = node
470
470
471 if not rev:
471 if not rev:
472 raise util.Abort(_("please specify a revision to backout"))
472 raise util.Abort(_("please specify a revision to backout"))
473
473
474 date = opts.get('date')
474 date = opts.get('date')
475 if date:
475 if date:
476 opts['date'] = util.parsedate(date)
476 opts['date'] = util.parsedate(date)
477
477
478 cmdutil.checkunfinished(repo)
478 cmdutil.checkunfinished(repo)
479 cmdutil.bailifchanged(repo)
479 cmdutil.bailifchanged(repo)
480 node = scmutil.revsingle(repo, rev).node()
480 node = scmutil.revsingle(repo, rev).node()
481
481
482 op1, op2 = repo.dirstate.parents()
482 op1, op2 = repo.dirstate.parents()
483 if not repo.changelog.isancestor(node, op1):
483 if not repo.changelog.isancestor(node, op1):
484 raise util.Abort(_('cannot backout change that is not an ancestor'))
484 raise util.Abort(_('cannot backout change that is not an ancestor'))
485
485
486 p1, p2 = repo.changelog.parents(node)
486 p1, p2 = repo.changelog.parents(node)
487 if p1 == nullid:
487 if p1 == nullid:
488 raise util.Abort(_('cannot backout a change with no parents'))
488 raise util.Abort(_('cannot backout a change with no parents'))
489 if p2 != nullid:
489 if p2 != nullid:
490 if not opts.get('parent'):
490 if not opts.get('parent'):
491 raise util.Abort(_('cannot backout a merge changeset'))
491 raise util.Abort(_('cannot backout a merge changeset'))
492 p = repo.lookup(opts['parent'])
492 p = repo.lookup(opts['parent'])
493 if p not in (p1, p2):
493 if p not in (p1, p2):
494 raise util.Abort(_('%s is not a parent of %s') %
494 raise util.Abort(_('%s is not a parent of %s') %
495 (short(p), short(node)))
495 (short(p), short(node)))
496 parent = p
496 parent = p
497 else:
497 else:
498 if opts.get('parent'):
498 if opts.get('parent'):
499 raise util.Abort(_('cannot use --parent on non-merge changeset'))
499 raise util.Abort(_('cannot use --parent on non-merge changeset'))
500 parent = p1
500 parent = p1
501
501
502 # the backout should appear on the same branch
502 # the backout should appear on the same branch
503 wlock = repo.wlock()
503 wlock = repo.wlock()
504 try:
504 try:
505 branch = repo.dirstate.branch()
505 branch = repo.dirstate.branch()
506 bheads = repo.branchheads(branch)
506 bheads = repo.branchheads(branch)
507 rctx = scmutil.revsingle(repo, hex(parent))
507 rctx = scmutil.revsingle(repo, hex(parent))
508 if not opts.get('merge') and op1 != node:
508 if not opts.get('merge') and op1 != node:
509 try:
509 try:
510 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
510 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
511 'backout')
511 'backout')
512 repo.dirstate.beginparentchange()
512 repo.dirstate.beginparentchange()
513 stats = mergemod.update(repo, parent, True, True, False,
513 stats = mergemod.update(repo, parent, True, True, False,
514 node, False)
514 node, False)
515 repo.setparents(op1, op2)
515 repo.setparents(op1, op2)
516 repo.dirstate.endparentchange()
516 repo.dirstate.endparentchange()
517 hg._showstats(repo, stats)
517 hg._showstats(repo, stats)
518 if stats[3]:
518 if stats[3]:
519 repo.ui.status(_("use 'hg resolve' to retry unresolved "
519 repo.ui.status(_("use 'hg resolve' to retry unresolved "
520 "file merges\n"))
520 "file merges\n"))
521 else:
521 else:
522 msg = _("changeset %s backed out, "
522 msg = _("changeset %s backed out, "
523 "don't forget to commit.\n")
523 "don't forget to commit.\n")
524 ui.status(msg % short(node))
524 ui.status(msg % short(node))
525 return stats[3] > 0
525 return stats[3] > 0
526 finally:
526 finally:
527 ui.setconfig('ui', 'forcemerge', '', '')
527 ui.setconfig('ui', 'forcemerge', '', '')
528 else:
528 else:
529 hg.clean(repo, node, show_stats=False)
529 hg.clean(repo, node, show_stats=False)
530 repo.dirstate.setbranch(branch)
530 repo.dirstate.setbranch(branch)
531 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
531 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
532
532
533
533
534 def commitfunc(ui, repo, message, match, opts):
534 def commitfunc(ui, repo, message, match, opts):
535 editform = 'backout'
535 editform = 'backout'
536 e = cmdutil.getcommiteditor(editform=editform, **opts)
536 e = cmdutil.getcommiteditor(editform=editform, **opts)
537 if not message:
537 if not message:
538 # we don't translate commit messages
538 # we don't translate commit messages
539 message = "Backed out changeset %s" % short(node)
539 message = "Backed out changeset %s" % short(node)
540 e = cmdutil.getcommiteditor(edit=True, editform=editform)
540 e = cmdutil.getcommiteditor(edit=True, editform=editform)
541 return repo.commit(message, opts.get('user'), opts.get('date'),
541 return repo.commit(message, opts.get('user'), opts.get('date'),
542 match, editor=e)
542 match, editor=e)
543 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
543 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
544 if not newnode:
544 if not newnode:
545 ui.status(_("nothing changed\n"))
545 ui.status(_("nothing changed\n"))
546 return 1
546 return 1
547 cmdutil.commitstatus(repo, newnode, branch, bheads)
547 cmdutil.commitstatus(repo, newnode, branch, bheads)
548
548
549 def nice(node):
549 def nice(node):
550 return '%d:%s' % (repo.changelog.rev(node), short(node))
550 return '%d:%s' % (repo.changelog.rev(node), short(node))
551 ui.status(_('changeset %s backs out changeset %s\n') %
551 ui.status(_('changeset %s backs out changeset %s\n') %
552 (nice(repo.changelog.tip()), nice(node)))
552 (nice(repo.changelog.tip()), nice(node)))
553 if opts.get('merge') and op1 != node:
553 if opts.get('merge') and op1 != node:
554 hg.clean(repo, op1, show_stats=False)
554 hg.clean(repo, op1, show_stats=False)
555 ui.status(_('merging with changeset %s\n')
555 ui.status(_('merging with changeset %s\n')
556 % nice(repo.changelog.tip()))
556 % nice(repo.changelog.tip()))
557 try:
557 try:
558 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
558 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
559 'backout')
559 'backout')
560 return hg.merge(repo, hex(repo.changelog.tip()))
560 return hg.merge(repo, hex(repo.changelog.tip()))
561 finally:
561 finally:
562 ui.setconfig('ui', 'forcemerge', '', '')
562 ui.setconfig('ui', 'forcemerge', '', '')
563 finally:
563 finally:
564 wlock.release()
564 wlock.release()
565 return 0
565 return 0
566
566
567 @command('bisect',
567 @command('bisect',
568 [('r', 'reset', False, _('reset bisect state')),
568 [('r', 'reset', False, _('reset bisect state')),
569 ('g', 'good', False, _('mark changeset good')),
569 ('g', 'good', False, _('mark changeset good')),
570 ('b', 'bad', False, _('mark changeset bad')),
570 ('b', 'bad', False, _('mark changeset bad')),
571 ('s', 'skip', False, _('skip testing changeset')),
571 ('s', 'skip', False, _('skip testing changeset')),
572 ('e', 'extend', False, _('extend the bisect range')),
572 ('e', 'extend', False, _('extend the bisect range')),
573 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
573 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
574 ('U', 'noupdate', False, _('do not update to target'))],
574 ('U', 'noupdate', False, _('do not update to target'))],
575 _("[-gbsr] [-U] [-c CMD] [REV]"))
575 _("[-gbsr] [-U] [-c CMD] [REV]"))
576 def bisect(ui, repo, rev=None, extra=None, command=None,
576 def bisect(ui, repo, rev=None, extra=None, command=None,
577 reset=None, good=None, bad=None, skip=None, extend=None,
577 reset=None, good=None, bad=None, skip=None, extend=None,
578 noupdate=None):
578 noupdate=None):
579 """subdivision search of changesets
579 """subdivision search of changesets
580
580
581 This command helps to find changesets which introduce problems. To
581 This command helps to find changesets which introduce problems. To
582 use, mark the earliest changeset you know exhibits the problem as
582 use, mark the earliest changeset you know exhibits the problem as
583 bad, then mark the latest changeset which is free from the problem
583 bad, then mark the latest changeset which is free from the problem
584 as good. Bisect will update your working directory to a revision
584 as good. Bisect will update your working directory to a revision
585 for testing (unless the -U/--noupdate option is specified). Once
585 for testing (unless the -U/--noupdate option is specified). Once
586 you have performed tests, mark the working directory as good or
586 you have performed tests, mark the working directory as good or
587 bad, and bisect will either update to another candidate changeset
587 bad, and bisect will either update to another candidate changeset
588 or announce that it has found the bad revision.
588 or announce that it has found the bad revision.
589
589
590 As a shortcut, you can also use the revision argument to mark a
590 As a shortcut, you can also use the revision argument to mark a
591 revision as good or bad without checking it out first.
591 revision as good or bad without checking it out first.
592
592
593 If you supply a command, it will be used for automatic bisection.
593 If you supply a command, it will be used for automatic bisection.
594 The environment variable HG_NODE will contain the ID of the
594 The environment variable HG_NODE will contain the ID of the
595 changeset being tested. The exit status of the command will be
595 changeset being tested. The exit status of the command will be
596 used to mark revisions as good or bad: status 0 means good, 125
596 used to mark revisions as good or bad: status 0 means good, 125
597 means to skip the revision, 127 (command not found) will abort the
597 means to skip the revision, 127 (command not found) will abort the
598 bisection, and any other non-zero exit status means the revision
598 bisection, and any other non-zero exit status means the revision
599 is bad.
599 is bad.
600
600
601 .. container:: verbose
601 .. container:: verbose
602
602
603 Some examples:
603 Some examples:
604
604
605 - start a bisection with known bad revision 34, and good revision 12::
605 - start a bisection with known bad revision 34, and good revision 12::
606
606
607 hg bisect --bad 34
607 hg bisect --bad 34
608 hg bisect --good 12
608 hg bisect --good 12
609
609
610 - advance the current bisection by marking current revision as good or
610 - advance the current bisection by marking current revision as good or
611 bad::
611 bad::
612
612
613 hg bisect --good
613 hg bisect --good
614 hg bisect --bad
614 hg bisect --bad
615
615
616 - mark the current revision, or a known revision, to be skipped (e.g. if
616 - mark the current revision, or a known revision, to be skipped (e.g. if
617 that revision is not usable because of another issue)::
617 that revision is not usable because of another issue)::
618
618
619 hg bisect --skip
619 hg bisect --skip
620 hg bisect --skip 23
620 hg bisect --skip 23
621
621
622 - skip all revisions that do not touch directories ``foo`` or ``bar``::
622 - skip all revisions that do not touch directories ``foo`` or ``bar``::
623
623
624 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
624 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
625
625
626 - forget the current bisection::
626 - forget the current bisection::
627
627
628 hg bisect --reset
628 hg bisect --reset
629
629
630 - use 'make && make tests' to automatically find the first broken
630 - use 'make && make tests' to automatically find the first broken
631 revision::
631 revision::
632
632
633 hg bisect --reset
633 hg bisect --reset
634 hg bisect --bad 34
634 hg bisect --bad 34
635 hg bisect --good 12
635 hg bisect --good 12
636 hg bisect --command "make && make tests"
636 hg bisect --command "make && make tests"
637
637
638 - see all changesets whose states are already known in the current
638 - see all changesets whose states are already known in the current
639 bisection::
639 bisection::
640
640
641 hg log -r "bisect(pruned)"
641 hg log -r "bisect(pruned)"
642
642
643 - see the changeset currently being bisected (especially useful
643 - see the changeset currently being bisected (especially useful
644 if running with -U/--noupdate)::
644 if running with -U/--noupdate)::
645
645
646 hg log -r "bisect(current)"
646 hg log -r "bisect(current)"
647
647
648 - see all changesets that took part in the current bisection::
648 - see all changesets that took part in the current bisection::
649
649
650 hg log -r "bisect(range)"
650 hg log -r "bisect(range)"
651
651
652 - you can even get a nice graph::
652 - you can even get a nice graph::
653
653
654 hg log --graph -r "bisect(range)"
654 hg log --graph -r "bisect(range)"
655
655
656 See :hg:`help revsets` for more about the `bisect()` keyword.
656 See :hg:`help revsets` for more about the `bisect()` keyword.
657
657
658 Returns 0 on success.
658 Returns 0 on success.
659 """
659 """
660 def extendbisectrange(nodes, good):
660 def extendbisectrange(nodes, good):
661 # bisect is incomplete when it ends on a merge node and
661 # bisect is incomplete when it ends on a merge node and
662 # one of the parent was not checked.
662 # one of the parent was not checked.
663 parents = repo[nodes[0]].parents()
663 parents = repo[nodes[0]].parents()
664 if len(parents) > 1:
664 if len(parents) > 1:
665 side = good and state['bad'] or state['good']
665 side = good and state['bad'] or state['good']
666 num = len(set(i.node() for i in parents) & set(side))
666 num = len(set(i.node() for i in parents) & set(side))
667 if num == 1:
667 if num == 1:
668 return parents[0].ancestor(parents[1])
668 return parents[0].ancestor(parents[1])
669 return None
669 return None
670
670
671 def print_result(nodes, good):
671 def print_result(nodes, good):
672 displayer = cmdutil.show_changeset(ui, repo, {})
672 displayer = cmdutil.show_changeset(ui, repo, {})
673 if len(nodes) == 1:
673 if len(nodes) == 1:
674 # narrowed it down to a single revision
674 # narrowed it down to a single revision
675 if good:
675 if good:
676 ui.write(_("The first good revision is:\n"))
676 ui.write(_("The first good revision is:\n"))
677 else:
677 else:
678 ui.write(_("The first bad revision is:\n"))
678 ui.write(_("The first bad revision is:\n"))
679 displayer.show(repo[nodes[0]])
679 displayer.show(repo[nodes[0]])
680 extendnode = extendbisectrange(nodes, good)
680 extendnode = extendbisectrange(nodes, good)
681 if extendnode is not None:
681 if extendnode is not None:
682 ui.write(_('Not all ancestors of this changeset have been'
682 ui.write(_('Not all ancestors of this changeset have been'
683 ' checked.\nUse bisect --extend to continue the '
683 ' checked.\nUse bisect --extend to continue the '
684 'bisection from\nthe common ancestor, %s.\n')
684 'bisection from\nthe common ancestor, %s.\n')
685 % extendnode)
685 % extendnode)
686 else:
686 else:
687 # multiple possible revisions
687 # multiple possible revisions
688 if good:
688 if good:
689 ui.write(_("Due to skipped revisions, the first "
689 ui.write(_("Due to skipped revisions, the first "
690 "good revision could be any of:\n"))
690 "good revision could be any of:\n"))
691 else:
691 else:
692 ui.write(_("Due to skipped revisions, the first "
692 ui.write(_("Due to skipped revisions, the first "
693 "bad revision could be any of:\n"))
693 "bad revision could be any of:\n"))
694 for n in nodes:
694 for n in nodes:
695 displayer.show(repo[n])
695 displayer.show(repo[n])
696 displayer.close()
696 displayer.close()
697
697
698 def check_state(state, interactive=True):
698 def check_state(state, interactive=True):
699 if not state['good'] or not state['bad']:
699 if not state['good'] or not state['bad']:
700 if (good or bad or skip or reset) and interactive:
700 if (good or bad or skip or reset) and interactive:
701 return
701 return
702 if not state['good']:
702 if not state['good']:
703 raise util.Abort(_('cannot bisect (no known good revisions)'))
703 raise util.Abort(_('cannot bisect (no known good revisions)'))
704 else:
704 else:
705 raise util.Abort(_('cannot bisect (no known bad revisions)'))
705 raise util.Abort(_('cannot bisect (no known bad revisions)'))
706 return True
706 return True
707
707
708 # backward compatibility
708 # backward compatibility
709 if rev in "good bad reset init".split():
709 if rev in "good bad reset init".split():
710 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
710 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
711 cmd, rev, extra = rev, extra, None
711 cmd, rev, extra = rev, extra, None
712 if cmd == "good":
712 if cmd == "good":
713 good = True
713 good = True
714 elif cmd == "bad":
714 elif cmd == "bad":
715 bad = True
715 bad = True
716 else:
716 else:
717 reset = True
717 reset = True
718 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
718 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
719 raise util.Abort(_('incompatible arguments'))
719 raise util.Abort(_('incompatible arguments'))
720
720
721 cmdutil.checkunfinished(repo)
721 cmdutil.checkunfinished(repo)
722
722
723 if reset:
723 if reset:
724 p = repo.join("bisect.state")
724 p = repo.join("bisect.state")
725 if os.path.exists(p):
725 if os.path.exists(p):
726 os.unlink(p)
726 os.unlink(p)
727 return
727 return
728
728
729 state = hbisect.load_state(repo)
729 state = hbisect.load_state(repo)
730
730
731 if command:
731 if command:
732 changesets = 1
732 changesets = 1
733 if noupdate:
733 if noupdate:
734 try:
734 try:
735 node = state['current'][0]
735 node = state['current'][0]
736 except LookupError:
736 except LookupError:
737 raise util.Abort(_('current bisect revision is unknown - '
737 raise util.Abort(_('current bisect revision is unknown - '
738 'start a new bisect to fix'))
738 'start a new bisect to fix'))
739 else:
739 else:
740 node, p2 = repo.dirstate.parents()
740 node, p2 = repo.dirstate.parents()
741 if p2 != nullid:
741 if p2 != nullid:
742 raise util.Abort(_('current bisect revision is a merge'))
742 raise util.Abort(_('current bisect revision is a merge'))
743 try:
743 try:
744 while changesets:
744 while changesets:
745 # update state
745 # update state
746 state['current'] = [node]
746 state['current'] = [node]
747 hbisect.save_state(repo, state)
747 hbisect.save_state(repo, state)
748 status = util.system(command,
748 status = util.system(command,
749 environ={'HG_NODE': hex(node)},
749 environ={'HG_NODE': hex(node)},
750 out=ui.fout)
750 out=ui.fout)
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 _('hg bookmarks [OPTIONS]... [NAME]...'))
840 _('hg bookmarks [OPTIONS]... [NAME]...'))
841 def bookmark(ui, repo, *names, **opts):
841 def bookmark(ui, repo, *names, **opts):
842 '''create a new bookmark or list existing bookmarks
842 '''create a new bookmark or list existing bookmarks
843
843
844 Bookmarks are labels on changesets to help track lines of development.
844 Bookmarks are labels on changesets to help track lines of development.
845 Bookmarks are unversioned and can be moved, renamed and deleted.
845 Bookmarks are unversioned and can be moved, renamed and deleted.
846 Deleting or moving a bookmark has no effect on the associated changesets.
846 Deleting or moving a bookmark has no effect on the associated changesets.
847
847
848 Creating or updating to a bookmark causes it to be marked as 'active'.
848 Creating or updating to a bookmark causes it to be marked as 'active'.
849 The active bookmark is indicated with a '*'.
849 The active bookmark is indicated with a '*'.
850 When a commit is made, the active bookmark will advance to the new commit.
850 When a commit is made, the active bookmark will advance to the new commit.
851 A plain :hg:`update` will also advance an active bookmark, if possible.
851 A plain :hg:`update` will also advance an active bookmark, if possible.
852 Updating away from a bookmark will cause it to be deactivated.
852 Updating away from a bookmark will cause it to be deactivated.
853
853
854 Bookmarks can be pushed and pulled between repositories (see
854 Bookmarks can be pushed and pulled between repositories (see
855 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
855 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
856 diverged, a new 'divergent bookmark' of the form 'name@path' will
856 diverged, a new 'divergent bookmark' of the form 'name@path' will
857 be created. Using :hg:'merge' will resolve the divergence.
857 be created. Using :hg:'merge' will resolve the divergence.
858
858
859 A bookmark named '@' has the special property that :hg:`clone` will
859 A bookmark named '@' has the special property that :hg:`clone` will
860 check it out by default if it exists.
860 check it out by default if it exists.
861
861
862 .. container:: verbose
862 .. container:: verbose
863
863
864 Examples:
864 Examples:
865
865
866 - create an active bookmark for a new line of development::
866 - create an active bookmark for a new line of development::
867
867
868 hg book new-feature
868 hg book new-feature
869
869
870 - create an inactive bookmark as a place marker::
870 - create an inactive bookmark as a place marker::
871
871
872 hg book -i reviewed
872 hg book -i reviewed
873
873
874 - create an inactive bookmark on another changeset::
874 - create an inactive bookmark on another changeset::
875
875
876 hg book -r .^ tested
876 hg book -r .^ tested
877
877
878 - move the '@' bookmark from another branch::
878 - move the '@' bookmark from another branch::
879
879
880 hg book -f @
880 hg book -f @
881 '''
881 '''
882 force = opts.get('force')
882 force = opts.get('force')
883 rev = opts.get('rev')
883 rev = opts.get('rev')
884 delete = opts.get('delete')
884 delete = opts.get('delete')
885 rename = opts.get('rename')
885 rename = opts.get('rename')
886 inactive = opts.get('inactive')
886 inactive = opts.get('inactive')
887
887
888 def checkformat(mark):
888 def checkformat(mark):
889 mark = mark.strip()
889 mark = mark.strip()
890 if not mark:
890 if not mark:
891 raise util.Abort(_("bookmark names cannot consist entirely of "
891 raise util.Abort(_("bookmark names cannot consist entirely of "
892 "whitespace"))
892 "whitespace"))
893 scmutil.checknewlabel(repo, mark, 'bookmark')
893 scmutil.checknewlabel(repo, mark, 'bookmark')
894 return mark
894 return mark
895
895
896 def checkconflict(repo, mark, cur, force=False, target=None):
896 def checkconflict(repo, mark, cur, force=False, target=None):
897 if mark in marks and not force:
897 if mark in marks and not force:
898 if target:
898 if target:
899 if marks[mark] == target and target == cur:
899 if marks[mark] == target and target == cur:
900 # re-activating a bookmark
900 # re-activating a bookmark
901 return
901 return
902 anc = repo.changelog.ancestors([repo[target].rev()])
902 anc = repo.changelog.ancestors([repo[target].rev()])
903 bmctx = repo[marks[mark]]
903 bmctx = repo[marks[mark]]
904 divs = [repo[b].node() for b in marks
904 divs = [repo[b].node() for b in marks
905 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
905 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
906
906
907 # allow resolving a single divergent bookmark even if moving
907 # allow resolving a single divergent bookmark even if moving
908 # the bookmark across branches when a revision is specified
908 # the bookmark across branches when a revision is specified
909 # that contains a divergent bookmark
909 # that contains a divergent bookmark
910 if bmctx.rev() not in anc and target in divs:
910 if bmctx.rev() not in anc and target in divs:
911 bookmarks.deletedivergent(repo, [target], mark)
911 bookmarks.deletedivergent(repo, [target], mark)
912 return
912 return
913
913
914 deletefrom = [b for b in divs
914 deletefrom = [b for b in divs
915 if repo[b].rev() in anc or b == target]
915 if repo[b].rev() in anc or b == target]
916 bookmarks.deletedivergent(repo, deletefrom, mark)
916 bookmarks.deletedivergent(repo, deletefrom, mark)
917 if bookmarks.validdest(repo, bmctx, repo[target]):
917 if bookmarks.validdest(repo, bmctx, repo[target]):
918 ui.status(_("moving bookmark '%s' forward from %s\n") %
918 ui.status(_("moving bookmark '%s' forward from %s\n") %
919 (mark, short(bmctx.node())))
919 (mark, short(bmctx.node())))
920 return
920 return
921 raise util.Abort(_("bookmark '%s' already exists "
921 raise util.Abort(_("bookmark '%s' already exists "
922 "(use -f to force)") % mark)
922 "(use -f to force)") % mark)
923 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
923 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
924 and not force):
924 and not force):
925 raise util.Abort(
925 raise util.Abort(
926 _("a bookmark cannot have the name of an existing branch"))
926 _("a bookmark cannot have the name of an existing branch"))
927
927
928 if delete and rename:
928 if delete and rename:
929 raise util.Abort(_("--delete and --rename are incompatible"))
929 raise util.Abort(_("--delete and --rename are incompatible"))
930 if delete and rev:
930 if delete and rev:
931 raise util.Abort(_("--rev is incompatible with --delete"))
931 raise util.Abort(_("--rev is incompatible with --delete"))
932 if rename and rev:
932 if rename and rev:
933 raise util.Abort(_("--rev is incompatible with --rename"))
933 raise util.Abort(_("--rev is incompatible with --rename"))
934 if not names and (delete or rev):
934 if not names and (delete or rev):
935 raise util.Abort(_("bookmark name required"))
935 raise util.Abort(_("bookmark name required"))
936
936
937 if delete or rename or names or inactive:
937 if delete or rename or names or inactive:
938 wlock = repo.wlock()
938 wlock = repo.wlock()
939 try:
939 try:
940 cur = repo.changectx('.').node()
940 cur = repo.changectx('.').node()
941 marks = repo._bookmarks
941 marks = repo._bookmarks
942 if delete:
942 if delete:
943 for mark in names:
943 for mark in names:
944 if mark not in marks:
944 if mark not in marks:
945 raise util.Abort(_("bookmark '%s' does not exist") %
945 raise util.Abort(_("bookmark '%s' does not exist") %
946 mark)
946 mark)
947 if mark == repo._bookmarkcurrent:
947 if mark == repo._bookmarkcurrent:
948 bookmarks.unsetcurrent(repo)
948 bookmarks.unsetcurrent(repo)
949 del marks[mark]
949 del marks[mark]
950 marks.write()
950 marks.write()
951
951
952 elif rename:
952 elif rename:
953 if not names:
953 if not names:
954 raise util.Abort(_("new bookmark name required"))
954 raise util.Abort(_("new bookmark name required"))
955 elif len(names) > 1:
955 elif len(names) > 1:
956 raise util.Abort(_("only one new bookmark name allowed"))
956 raise util.Abort(_("only one new bookmark name allowed"))
957 mark = checkformat(names[0])
957 mark = checkformat(names[0])
958 if rename not in marks:
958 if rename not in marks:
959 raise util.Abort(_("bookmark '%s' does not exist") % rename)
959 raise util.Abort(_("bookmark '%s' does not exist") % rename)
960 checkconflict(repo, mark, cur, force)
960 checkconflict(repo, mark, cur, force)
961 marks[mark] = marks[rename]
961 marks[mark] = marks[rename]
962 if repo._bookmarkcurrent == rename and not inactive:
962 if repo._bookmarkcurrent == rename and not inactive:
963 bookmarks.setcurrent(repo, mark)
963 bookmarks.setcurrent(repo, mark)
964 del marks[rename]
964 del marks[rename]
965 marks.write()
965 marks.write()
966
966
967 elif names:
967 elif names:
968 newact = None
968 newact = None
969 for mark in names:
969 for mark in names:
970 mark = checkformat(mark)
970 mark = checkformat(mark)
971 if newact is None:
971 if newact is None:
972 newact = mark
972 newact = mark
973 if inactive and mark == repo._bookmarkcurrent:
973 if inactive and mark == repo._bookmarkcurrent:
974 bookmarks.unsetcurrent(repo)
974 bookmarks.unsetcurrent(repo)
975 return
975 return
976 tgt = cur
976 tgt = cur
977 if rev:
977 if rev:
978 tgt = scmutil.revsingle(repo, rev).node()
978 tgt = scmutil.revsingle(repo, rev).node()
979 checkconflict(repo, mark, cur, force, tgt)
979 checkconflict(repo, mark, cur, force, tgt)
980 marks[mark] = tgt
980 marks[mark] = tgt
981 if not inactive and cur == marks[newact] and not rev:
981 if not inactive and cur == marks[newact] and not rev:
982 bookmarks.setcurrent(repo, newact)
982 bookmarks.setcurrent(repo, newact)
983 elif cur != tgt and newact == repo._bookmarkcurrent:
983 elif cur != tgt and newact == repo._bookmarkcurrent:
984 bookmarks.unsetcurrent(repo)
984 bookmarks.unsetcurrent(repo)
985 marks.write()
985 marks.write()
986
986
987 elif inactive:
987 elif inactive:
988 if len(marks) == 0:
988 if len(marks) == 0:
989 ui.status(_("no bookmarks set\n"))
989 ui.status(_("no bookmarks set\n"))
990 elif not repo._bookmarkcurrent:
990 elif not repo._bookmarkcurrent:
991 ui.status(_("no active bookmark\n"))
991 ui.status(_("no active bookmark\n"))
992 else:
992 else:
993 bookmarks.unsetcurrent(repo)
993 bookmarks.unsetcurrent(repo)
994 finally:
994 finally:
995 wlock.release()
995 wlock.release()
996 else: # show bookmarks
996 else: # show bookmarks
997 hexfn = ui.debugflag and hex or short
997 hexfn = ui.debugflag and hex or short
998 marks = repo._bookmarks
998 marks = repo._bookmarks
999 if len(marks) == 0:
999 if len(marks) == 0:
1000 ui.status(_("no bookmarks set\n"))
1000 ui.status(_("no bookmarks set\n"))
1001 else:
1001 else:
1002 for bmark, n in sorted(marks.iteritems()):
1002 for bmark, n in sorted(marks.iteritems()):
1003 current = repo._bookmarkcurrent
1003 current = repo._bookmarkcurrent
1004 if bmark == current:
1004 if bmark == current:
1005 prefix, label = '*', 'bookmarks.current'
1005 prefix, label = '*', 'bookmarks.current'
1006 else:
1006 else:
1007 prefix, label = ' ', ''
1007 prefix, label = ' ', ''
1008
1008
1009 if ui.quiet:
1009 if ui.quiet:
1010 ui.write("%s\n" % bmark, label=label)
1010 ui.write("%s\n" % bmark, label=label)
1011 else:
1011 else:
1012 pad = " " * (25 - encoding.colwidth(bmark))
1012 pad = " " * (25 - encoding.colwidth(bmark))
1013 ui.write(" %s %s%s %d:%s\n" % (
1013 ui.write(" %s %s%s %d:%s\n" % (
1014 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
1014 prefix, bmark, pad, repo.changelog.rev(n), hexfn(n)),
1015 label=label)
1015 label=label)
1016
1016
1017 @command('branch',
1017 @command('branch',
1018 [('f', 'force', None,
1018 [('f', 'force', None,
1019 _('set branch name even if it shadows an existing branch')),
1019 _('set branch name even if it shadows an existing branch')),
1020 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1020 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1021 _('[-fC] [NAME]'))
1021 _('[-fC] [NAME]'))
1022 def branch(ui, repo, label=None, **opts):
1022 def branch(ui, repo, label=None, **opts):
1023 """set or show the current branch name
1023 """set or show the current branch name
1024
1024
1025 .. note::
1025 .. note::
1026
1026
1027 Branch names are permanent and global. Use :hg:`bookmark` to create a
1027 Branch names are permanent and global. Use :hg:`bookmark` to create a
1028 light-weight bookmark instead. See :hg:`help glossary` for more
1028 light-weight bookmark instead. See :hg:`help glossary` for more
1029 information about named branches and bookmarks.
1029 information about named branches and bookmarks.
1030
1030
1031 With no argument, show the current branch name. With one argument,
1031 With no argument, show the current branch name. With one argument,
1032 set the working directory branch name (the branch will not exist
1032 set the working directory branch name (the branch will not exist
1033 in the repository until the next commit). Standard practice
1033 in the repository until the next commit). Standard practice
1034 recommends that primary development take place on the 'default'
1034 recommends that primary development take place on the 'default'
1035 branch.
1035 branch.
1036
1036
1037 Unless -f/--force is specified, branch will not let you set a
1037 Unless -f/--force is specified, branch will not let you set a
1038 branch name that already exists, even if it's inactive.
1038 branch name that already exists, even if it's inactive.
1039
1039
1040 Use -C/--clean to reset the working directory branch to that of
1040 Use -C/--clean to reset the working directory branch to that of
1041 the parent of the working directory, negating a previous branch
1041 the parent of the working directory, negating a previous branch
1042 change.
1042 change.
1043
1043
1044 Use the command :hg:`update` to switch to an existing branch. Use
1044 Use the command :hg:`update` to switch to an existing branch. Use
1045 :hg:`commit --close-branch` to mark this branch as closed.
1045 :hg:`commit --close-branch` to mark this branch as closed.
1046
1046
1047 Returns 0 on success.
1047 Returns 0 on success.
1048 """
1048 """
1049 if label:
1049 if label:
1050 label = label.strip()
1050 label = label.strip()
1051
1051
1052 if not opts.get('clean') and not label:
1052 if not opts.get('clean') and not label:
1053 ui.write("%s\n" % repo.dirstate.branch())
1053 ui.write("%s\n" % repo.dirstate.branch())
1054 return
1054 return
1055
1055
1056 wlock = repo.wlock()
1056 wlock = repo.wlock()
1057 try:
1057 try:
1058 if opts.get('clean'):
1058 if opts.get('clean'):
1059 label = repo[None].p1().branch()
1059 label = repo[None].p1().branch()
1060 repo.dirstate.setbranch(label)
1060 repo.dirstate.setbranch(label)
1061 ui.status(_('reset working directory to branch %s\n') % label)
1061 ui.status(_('reset working directory to branch %s\n') % label)
1062 elif label:
1062 elif label:
1063 if not opts.get('force') and label in repo.branchmap():
1063 if not opts.get('force') and label in repo.branchmap():
1064 if label not in [p.branch() for p in repo.parents()]:
1064 if label not in [p.branch() for p in repo.parents()]:
1065 raise util.Abort(_('a branch of the same name already'
1065 raise util.Abort(_('a branch of the same name already'
1066 ' exists'),
1066 ' exists'),
1067 # i18n: "it" refers to an existing branch
1067 # i18n: "it" refers to an existing branch
1068 hint=_("use 'hg update' to switch to it"))
1068 hint=_("use 'hg update' to switch to it"))
1069 scmutil.checknewlabel(repo, label, 'branch')
1069 scmutil.checknewlabel(repo, label, 'branch')
1070 repo.dirstate.setbranch(label)
1070 repo.dirstate.setbranch(label)
1071 ui.status(_('marked working directory as branch %s\n') % label)
1071 ui.status(_('marked working directory as branch %s\n') % label)
1072 ui.status(_('(branches are permanent and global, '
1072 ui.status(_('(branches are permanent and global, '
1073 'did you want a bookmark?)\n'))
1073 'did you want a bookmark?)\n'))
1074 finally:
1074 finally:
1075 wlock.release()
1075 wlock.release()
1076
1076
1077 @command('branches',
1077 @command('branches',
1078 [('a', 'active', False, _('show only branches that have unmerged heads')),
1078 [('a', 'active', False, _('show only branches that have unmerged heads')),
1079 ('c', 'closed', False, _('show normal and closed branches'))],
1079 ('c', 'closed', False, _('show normal and closed branches'))],
1080 _('[-ac]'))
1080 _('[-ac]'))
1081 def branches(ui, repo, active=False, closed=False):
1081 def branches(ui, repo, active=False, closed=False):
1082 """list repository named branches
1082 """list repository named branches
1083
1083
1084 List the repository's named branches, indicating which ones are
1084 List the repository's named branches, indicating which ones are
1085 inactive. If -c/--closed is specified, also list branches which have
1085 inactive. If -c/--closed is specified, also list branches which have
1086 been marked closed (see :hg:`commit --close-branch`).
1086 been marked closed (see :hg:`commit --close-branch`).
1087
1087
1088 If -a/--active is specified, only show active branches. A branch
1088 If -a/--active is specified, only show active branches. A branch
1089 is considered active if it contains repository heads.
1089 is considered active if it contains repository heads.
1090
1090
1091 Use the command :hg:`update` to switch to an existing branch.
1091 Use the command :hg:`update` to switch to an existing branch.
1092
1092
1093 Returns 0.
1093 Returns 0.
1094 """
1094 """
1095
1095
1096 hexfunc = ui.debugflag and hex or short
1096 hexfunc = ui.debugflag and hex or short
1097
1097
1098 allheads = set(repo.heads())
1098 allheads = set(repo.heads())
1099 branches = []
1099 branches = []
1100 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1100 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1101 isactive = not isclosed and bool(set(heads) & allheads)
1101 isactive = not isclosed and bool(set(heads) & allheads)
1102 branches.append((tag, repo[tip], isactive, not isclosed))
1102 branches.append((tag, repo[tip], isactive, not isclosed))
1103 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1103 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1104 reverse=True)
1104 reverse=True)
1105
1105
1106 for tag, ctx, isactive, isopen in branches:
1106 for tag, ctx, isactive, isopen in branches:
1107 if (not active) or isactive:
1107 if (not active) or isactive:
1108 if isactive:
1108 if isactive:
1109 label = 'branches.active'
1109 label = 'branches.active'
1110 notice = ''
1110 notice = ''
1111 elif not isopen:
1111 elif not isopen:
1112 if not closed:
1112 if not closed:
1113 continue
1113 continue
1114 label = 'branches.closed'
1114 label = 'branches.closed'
1115 notice = _(' (closed)')
1115 notice = _(' (closed)')
1116 else:
1116 else:
1117 label = 'branches.inactive'
1117 label = 'branches.inactive'
1118 notice = _(' (inactive)')
1118 notice = _(' (inactive)')
1119 if tag == repo.dirstate.branch():
1119 if tag == repo.dirstate.branch():
1120 label = 'branches.current'
1120 label = 'branches.current'
1121 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1121 rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
1122 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1122 rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
1123 'log.changeset changeset.%s' % ctx.phasestr())
1123 'log.changeset changeset.%s' % ctx.phasestr())
1124 labeledtag = ui.label(tag, label)
1124 labeledtag = ui.label(tag, label)
1125 if ui.quiet:
1125 if ui.quiet:
1126 ui.write("%s\n" % labeledtag)
1126 ui.write("%s\n" % labeledtag)
1127 else:
1127 else:
1128 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1128 ui.write("%s %s%s\n" % (labeledtag, rev, notice))
1129
1129
1130 @command('bundle',
1130 @command('bundle',
1131 [('f', 'force', None, _('run even when the destination is unrelated')),
1131 [('f', 'force', None, _('run even when the destination is unrelated')),
1132 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1132 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1133 _('REV')),
1133 _('REV')),
1134 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1134 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1135 _('BRANCH')),
1135 _('BRANCH')),
1136 ('', 'base', [],
1136 ('', 'base', [],
1137 _('a base changeset assumed to be available at the destination'),
1137 _('a base changeset assumed to be available at the destination'),
1138 _('REV')),
1138 _('REV')),
1139 ('a', 'all', None, _('bundle all changesets in the repository')),
1139 ('a', 'all', None, _('bundle all changesets in the repository')),
1140 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1140 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1141 ] + remoteopts,
1141 ] + remoteopts,
1142 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1142 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1143 def bundle(ui, repo, fname, dest=None, **opts):
1143 def bundle(ui, repo, fname, dest=None, **opts):
1144 """create a changegroup file
1144 """create a changegroup file
1145
1145
1146 Generate a compressed changegroup file collecting changesets not
1146 Generate a compressed changegroup file collecting changesets not
1147 known to be in another repository.
1147 known to be in another repository.
1148
1148
1149 If you omit the destination repository, then hg assumes the
1149 If you omit the destination repository, then hg assumes the
1150 destination will have all the nodes you specify with --base
1150 destination will have all the nodes you specify with --base
1151 parameters. To create a bundle containing all changesets, use
1151 parameters. To create a bundle containing all changesets, use
1152 -a/--all (or --base null).
1152 -a/--all (or --base null).
1153
1153
1154 You can change compression method with the -t/--type option.
1154 You can change compression method with the -t/--type option.
1155 The available compression methods are: none, bzip2, and
1155 The available compression methods are: none, bzip2, and
1156 gzip (by default, bundles are compressed using bzip2).
1156 gzip (by default, bundles are compressed using bzip2).
1157
1157
1158 The bundle file can then be transferred using conventional means
1158 The bundle file can then be transferred using conventional means
1159 and applied to another repository with the unbundle or pull
1159 and applied to another repository with the unbundle or pull
1160 command. This is useful when direct push and pull are not
1160 command. This is useful when direct push and pull are not
1161 available or when exporting an entire repository is undesirable.
1161 available or when exporting an entire repository is undesirable.
1162
1162
1163 Applying bundles preserves all changeset contents including
1163 Applying bundles preserves all changeset contents including
1164 permissions, copy/rename information, and revision history.
1164 permissions, copy/rename information, and revision history.
1165
1165
1166 Returns 0 on success, 1 if no changes found.
1166 Returns 0 on success, 1 if no changes found.
1167 """
1167 """
1168 revs = None
1168 revs = None
1169 if 'rev' in opts:
1169 if 'rev' in opts:
1170 revs = scmutil.revrange(repo, opts['rev'])
1170 revs = scmutil.revrange(repo, opts['rev'])
1171
1171
1172 bundletype = opts.get('type', 'bzip2').lower()
1172 bundletype = opts.get('type', 'bzip2').lower()
1173 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1173 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
1174 bundletype = btypes.get(bundletype)
1174 bundletype = btypes.get(bundletype)
1175 if bundletype not in changegroup.bundletypes:
1175 if bundletype not in changegroup.bundletypes:
1176 raise util.Abort(_('unknown bundle type specified with --type'))
1176 raise util.Abort(_('unknown bundle type specified with --type'))
1177
1177
1178 if opts.get('all'):
1178 if opts.get('all'):
1179 base = ['null']
1179 base = ['null']
1180 else:
1180 else:
1181 base = scmutil.revrange(repo, opts.get('base'))
1181 base = scmutil.revrange(repo, opts.get('base'))
1182 # TODO: get desired bundlecaps from command line.
1182 # TODO: get desired bundlecaps from command line.
1183 bundlecaps = None
1183 bundlecaps = None
1184 if base:
1184 if base:
1185 if dest:
1185 if dest:
1186 raise util.Abort(_("--base is incompatible with specifying "
1186 raise util.Abort(_("--base is incompatible with specifying "
1187 "a destination"))
1187 "a destination"))
1188 common = [repo.lookup(rev) for rev in base]
1188 common = [repo.lookup(rev) for rev in base]
1189 heads = revs and map(repo.lookup, revs) or revs
1189 heads = revs and map(repo.lookup, revs) or revs
1190 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1190 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1191 common=common, bundlecaps=bundlecaps)
1191 common=common, bundlecaps=bundlecaps)
1192 outgoing = None
1192 outgoing = None
1193 else:
1193 else:
1194 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1194 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1195 dest, branches = hg.parseurl(dest, opts.get('branch'))
1195 dest, branches = hg.parseurl(dest, opts.get('branch'))
1196 other = hg.peer(repo, opts, dest)
1196 other = hg.peer(repo, opts, dest)
1197 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1197 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1198 heads = revs and map(repo.lookup, revs) or revs
1198 heads = revs and map(repo.lookup, revs) or revs
1199 outgoing = discovery.findcommonoutgoing(repo, other,
1199 outgoing = discovery.findcommonoutgoing(repo, other,
1200 onlyheads=heads,
1200 onlyheads=heads,
1201 force=opts.get('force'),
1201 force=opts.get('force'),
1202 portable=True)
1202 portable=True)
1203 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1203 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1204 bundlecaps)
1204 bundlecaps)
1205 if not cg:
1205 if not cg:
1206 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1206 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1207 return 1
1207 return 1
1208
1208
1209 changegroup.writebundle(cg, fname, bundletype)
1209 changegroup.writebundle(cg, fname, bundletype)
1210
1210
1211 @command('cat',
1211 @command('cat',
1212 [('o', 'output', '',
1212 [('o', 'output', '',
1213 _('print output to file with formatted name'), _('FORMAT')),
1213 _('print output to file with formatted name'), _('FORMAT')),
1214 ('r', 'rev', '', _('print the given revision'), _('REV')),
1214 ('r', 'rev', '', _('print the given revision'), _('REV')),
1215 ('', 'decode', None, _('apply any matching decode filter')),
1215 ('', 'decode', None, _('apply any matching decode filter')),
1216 ] + walkopts,
1216 ] + walkopts,
1217 _('[OPTION]... FILE...'),
1217 _('[OPTION]... FILE...'),
1218 inferrepo=True)
1218 inferrepo=True)
1219 def cat(ui, repo, file1, *pats, **opts):
1219 def cat(ui, repo, file1, *pats, **opts):
1220 """output the current or given revision of files
1220 """output the current or given revision of files
1221
1221
1222 Print the specified files as they were at the given revision. If
1222 Print the specified files as they were at the given revision. If
1223 no revision is given, the parent of the working directory is used.
1223 no revision is given, the parent of the working directory is used.
1224
1224
1225 Output may be to a file, in which case the name of the file is
1225 Output may be to a file, in which case the name of the file is
1226 given using a format string. The formatting rules as follows:
1226 given using a format string. The formatting rules as follows:
1227
1227
1228 :``%%``: literal "%" character
1228 :``%%``: literal "%" character
1229 :``%s``: basename of file being printed
1229 :``%s``: basename of file being printed
1230 :``%d``: dirname of file being printed, or '.' if in repository root
1230 :``%d``: dirname of file being printed, or '.' if in repository root
1231 :``%p``: root-relative path name of file being printed
1231 :``%p``: root-relative path name of file being printed
1232 :``%H``: changeset hash (40 hexadecimal digits)
1232 :``%H``: changeset hash (40 hexadecimal digits)
1233 :``%R``: changeset revision number
1233 :``%R``: changeset revision number
1234 :``%h``: short-form changeset hash (12 hexadecimal digits)
1234 :``%h``: short-form changeset hash (12 hexadecimal digits)
1235 :``%r``: zero-padded changeset revision number
1235 :``%r``: zero-padded changeset revision number
1236 :``%b``: basename of the exporting repository
1236 :``%b``: basename of the exporting repository
1237
1237
1238 Returns 0 on success.
1238 Returns 0 on success.
1239 """
1239 """
1240 ctx = scmutil.revsingle(repo, opts.get('rev'))
1240 ctx = scmutil.revsingle(repo, opts.get('rev'))
1241 m = scmutil.match(ctx, (file1,) + pats, opts)
1241 m = scmutil.match(ctx, (file1,) + pats, opts)
1242
1242
1243 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1243 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1244
1244
1245 @command('^clone',
1245 @command('^clone',
1246 [('U', 'noupdate', None,
1246 [('U', 'noupdate', None,
1247 _('the clone will include an empty working copy (only a repository)')),
1247 _('the clone will include an empty working copy (only a repository)')),
1248 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1248 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1249 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1249 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1250 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1250 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1251 ('', 'pull', None, _('use pull protocol to copy metadata')),
1251 ('', 'pull', None, _('use pull protocol to copy metadata')),
1252 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1252 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1253 ] + remoteopts,
1253 ] + remoteopts,
1254 _('[OPTION]... SOURCE [DEST]'),
1254 _('[OPTION]... SOURCE [DEST]'),
1255 norepo=True)
1255 norepo=True)
1256 def clone(ui, source, dest=None, **opts):
1256 def clone(ui, source, dest=None, **opts):
1257 """make a copy of an existing repository
1257 """make a copy of an existing repository
1258
1258
1259 Create a copy of an existing repository in a new directory.
1259 Create a copy of an existing repository in a new directory.
1260
1260
1261 If no destination directory name is specified, it defaults to the
1261 If no destination directory name is specified, it defaults to the
1262 basename of the source.
1262 basename of the source.
1263
1263
1264 The location of the source is added to the new repository's
1264 The location of the source is added to the new repository's
1265 ``.hg/hgrc`` file, as the default to be used for future pulls.
1265 ``.hg/hgrc`` file, as the default to be used for future pulls.
1266
1266
1267 Only local paths and ``ssh://`` URLs are supported as
1267 Only local paths and ``ssh://`` URLs are supported as
1268 destinations. For ``ssh://`` destinations, no working directory or
1268 destinations. For ``ssh://`` destinations, no working directory or
1269 ``.hg/hgrc`` will be created on the remote side.
1269 ``.hg/hgrc`` will be created on the remote side.
1270
1270
1271 To pull only a subset of changesets, specify one or more revisions
1271 To pull only a subset of changesets, specify one or more revisions
1272 identifiers with -r/--rev or branches with -b/--branch. The
1272 identifiers with -r/--rev or branches with -b/--branch. The
1273 resulting clone will contain only the specified changesets and
1273 resulting clone will contain only the specified changesets and
1274 their ancestors. These options (or 'clone src#rev dest') imply
1274 their ancestors. These options (or 'clone src#rev dest') imply
1275 --pull, even for local source repositories. Note that specifying a
1275 --pull, even for local source repositories. Note that specifying a
1276 tag will include the tagged changeset but not the changeset
1276 tag will include the tagged changeset but not the changeset
1277 containing the tag.
1277 containing the tag.
1278
1278
1279 If the source repository has a bookmark called '@' set, that
1279 If the source repository has a bookmark called '@' set, that
1280 revision will be checked out in the new repository by default.
1280 revision will be checked out in the new repository by default.
1281
1281
1282 To check out a particular version, use -u/--update, or
1282 To check out a particular version, use -u/--update, or
1283 -U/--noupdate to create a clone with no working directory.
1283 -U/--noupdate to create a clone with no working directory.
1284
1284
1285 .. container:: verbose
1285 .. container:: verbose
1286
1286
1287 For efficiency, hardlinks are used for cloning whenever the
1287 For efficiency, hardlinks are used for cloning whenever the
1288 source and destination are on the same filesystem (note this
1288 source and destination are on the same filesystem (note this
1289 applies only to the repository data, not to the working
1289 applies only to the repository data, not to the working
1290 directory). Some filesystems, such as AFS, implement hardlinking
1290 directory). Some filesystems, such as AFS, implement hardlinking
1291 incorrectly, but do not report errors. In these cases, use the
1291 incorrectly, but do not report errors. In these cases, use the
1292 --pull option to avoid hardlinking.
1292 --pull option to avoid hardlinking.
1293
1293
1294 In some cases, you can clone repositories and the working
1294 In some cases, you can clone repositories and the working
1295 directory using full hardlinks with ::
1295 directory using full hardlinks with ::
1296
1296
1297 $ cp -al REPO REPOCLONE
1297 $ cp -al REPO REPOCLONE
1298
1298
1299 This is the fastest way to clone, but it is not always safe. The
1299 This is the fastest way to clone, but it is not always safe. The
1300 operation is not atomic (making sure REPO is not modified during
1300 operation is not atomic (making sure REPO is not modified during
1301 the operation is up to you) and you have to make sure your
1301 the operation is up to you) and you have to make sure your
1302 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1302 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1303 so). Also, this is not compatible with certain extensions that
1303 so). Also, this is not compatible with certain extensions that
1304 place their metadata under the .hg directory, such as mq.
1304 place their metadata under the .hg directory, such as mq.
1305
1305
1306 Mercurial will update the working directory to the first applicable
1306 Mercurial will update the working directory to the first applicable
1307 revision from this list:
1307 revision from this list:
1308
1308
1309 a) null if -U or the source repository has no changesets
1309 a) null if -U or the source repository has no changesets
1310 b) if -u . and the source repository is local, the first parent of
1310 b) if -u . and the source repository is local, the first parent of
1311 the source repository's working directory
1311 the source repository's working directory
1312 c) the changeset specified with -u (if a branch name, this means the
1312 c) the changeset specified with -u (if a branch name, this means the
1313 latest head of that branch)
1313 latest head of that branch)
1314 d) the changeset specified with -r
1314 d) the changeset specified with -r
1315 e) the tipmost head specified with -b
1315 e) the tipmost head specified with -b
1316 f) the tipmost head specified with the url#branch source syntax
1316 f) the tipmost head specified with the url#branch source syntax
1317 g) the revision marked with the '@' bookmark, if present
1317 g) the revision marked with the '@' bookmark, if present
1318 h) the tipmost head of the default branch
1318 h) the tipmost head of the default branch
1319 i) tip
1319 i) tip
1320
1320
1321 Examples:
1321 Examples:
1322
1322
1323 - clone a remote repository to a new directory named hg/::
1323 - clone a remote repository to a new directory named hg/::
1324
1324
1325 hg clone http://selenic.com/hg
1325 hg clone http://selenic.com/hg
1326
1326
1327 - create a lightweight local clone::
1327 - create a lightweight local clone::
1328
1328
1329 hg clone project/ project-feature/
1329 hg clone project/ project-feature/
1330
1330
1331 - clone from an absolute path on an ssh server (note double-slash)::
1331 - clone from an absolute path on an ssh server (note double-slash)::
1332
1332
1333 hg clone ssh://user@server//home/projects/alpha/
1333 hg clone ssh://user@server//home/projects/alpha/
1334
1334
1335 - do a high-speed clone over a LAN while checking out a
1335 - do a high-speed clone over a LAN while checking out a
1336 specified version::
1336 specified version::
1337
1337
1338 hg clone --uncompressed http://server/repo -u 1.5
1338 hg clone --uncompressed http://server/repo -u 1.5
1339
1339
1340 - create a repository without changesets after a particular revision::
1340 - create a repository without changesets after a particular revision::
1341
1341
1342 hg clone -r 04e544 experimental/ good/
1342 hg clone -r 04e544 experimental/ good/
1343
1343
1344 - clone (and track) a particular named branch::
1344 - clone (and track) a particular named branch::
1345
1345
1346 hg clone http://selenic.com/hg#stable
1346 hg clone http://selenic.com/hg#stable
1347
1347
1348 See :hg:`help urls` for details on specifying URLs.
1348 See :hg:`help urls` for details on specifying URLs.
1349
1349
1350 Returns 0 on success.
1350 Returns 0 on success.
1351 """
1351 """
1352 if opts.get('noupdate') and opts.get('updaterev'):
1352 if opts.get('noupdate') and opts.get('updaterev'):
1353 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1353 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
1354
1354
1355 r = hg.clone(ui, opts, source, dest,
1355 r = hg.clone(ui, opts, source, dest,
1356 pull=opts.get('pull'),
1356 pull=opts.get('pull'),
1357 stream=opts.get('uncompressed'),
1357 stream=opts.get('uncompressed'),
1358 rev=opts.get('rev'),
1358 rev=opts.get('rev'),
1359 update=opts.get('updaterev') or not opts.get('noupdate'),
1359 update=opts.get('updaterev') or not opts.get('noupdate'),
1360 branch=opts.get('branch'))
1360 branch=opts.get('branch'))
1361
1361
1362 return r is None
1362 return r is None
1363
1363
1364 @command('^commit|ci',
1364 @command('^commit|ci',
1365 [('A', 'addremove', None,
1365 [('A', 'addremove', None,
1366 _('mark new/missing files as added/removed before committing')),
1366 _('mark new/missing files as added/removed before committing')),
1367 ('', 'close-branch', None,
1367 ('', 'close-branch', None,
1368 _('mark a branch as closed, hiding it from the branch list')),
1368 _('mark a branch as closed, hiding it from the branch list')),
1369 ('', 'amend', None, _('amend the parent of the working dir')),
1369 ('', 'amend', None, _('amend the parent of the working dir')),
1370 ('s', 'secret', None, _('use the secret phase for committing')),
1370 ('s', 'secret', None, _('use the secret phase for committing')),
1371 ('e', 'edit', None, _('invoke editor on commit messages')),
1371 ('e', 'edit', None, _('invoke editor on commit messages')),
1372 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1372 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1373 _('[OPTION]... [FILE]...'),
1373 _('[OPTION]... [FILE]...'),
1374 inferrepo=True)
1374 inferrepo=True)
1375 def commit(ui, repo, *pats, **opts):
1375 def commit(ui, repo, *pats, **opts):
1376 """commit the specified files or all outstanding changes
1376 """commit the specified files or all outstanding changes
1377
1377
1378 Commit changes to the given files into the repository. Unlike a
1378 Commit changes to the given files into the repository. Unlike a
1379 centralized SCM, this operation is a local operation. See
1379 centralized SCM, this operation is a local operation. See
1380 :hg:`push` for a way to actively distribute your changes.
1380 :hg:`push` for a way to actively distribute your changes.
1381
1381
1382 If a list of files is omitted, all changes reported by :hg:`status`
1382 If a list of files is omitted, all changes reported by :hg:`status`
1383 will be committed.
1383 will be committed.
1384
1384
1385 If you are committing the result of a merge, do not provide any
1385 If you are committing the result of a merge, do not provide any
1386 filenames or -I/-X filters.
1386 filenames or -I/-X filters.
1387
1387
1388 If no commit message is specified, Mercurial starts your
1388 If no commit message is specified, Mercurial starts your
1389 configured editor where you can enter a message. In case your
1389 configured editor where you can enter a message. In case your
1390 commit fails, you will find a backup of your message in
1390 commit fails, you will find a backup of your message in
1391 ``.hg/last-message.txt``.
1391 ``.hg/last-message.txt``.
1392
1392
1393 The --amend flag can be used to amend the parent of the
1393 The --amend flag can be used to amend the parent of the
1394 working directory with a new commit that contains the changes
1394 working directory with a new commit that contains the changes
1395 in the parent in addition to those currently reported by :hg:`status`,
1395 in the parent in addition to those currently reported by :hg:`status`,
1396 if there are any. The old commit is stored in a backup bundle in
1396 if there are any. The old commit is stored in a backup bundle in
1397 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1397 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1398 on how to restore it).
1398 on how to restore it).
1399
1399
1400 Message, user and date are taken from the amended commit unless
1400 Message, user and date are taken from the amended commit unless
1401 specified. When a message isn't specified on the command line,
1401 specified. When a message isn't specified on the command line,
1402 the editor will open with the message of the amended commit.
1402 the editor will open with the message of the amended commit.
1403
1403
1404 It is not possible to amend public changesets (see :hg:`help phases`)
1404 It is not possible to amend public changesets (see :hg:`help phases`)
1405 or changesets that have children.
1405 or changesets that have children.
1406
1406
1407 See :hg:`help dates` for a list of formats valid for -d/--date.
1407 See :hg:`help dates` for a list of formats valid for -d/--date.
1408
1408
1409 Returns 0 on success, 1 if nothing changed.
1409 Returns 0 on success, 1 if nothing changed.
1410 """
1410 """
1411 if opts.get('subrepos'):
1411 if opts.get('subrepos'):
1412 if opts.get('amend'):
1412 if opts.get('amend'):
1413 raise util.Abort(_('cannot amend with --subrepos'))
1413 raise util.Abort(_('cannot amend with --subrepos'))
1414 # Let --subrepos on the command line override config setting.
1414 # Let --subrepos on the command line override config setting.
1415 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1415 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1416
1416
1417 cmdutil.checkunfinished(repo, commit=True)
1417 cmdutil.checkunfinished(repo, commit=True)
1418
1418
1419 branch = repo[None].branch()
1419 branch = repo[None].branch()
1420 bheads = repo.branchheads(branch)
1420 bheads = repo.branchheads(branch)
1421
1421
1422 extra = {}
1422 extra = {}
1423 if opts.get('close_branch'):
1423 if opts.get('close_branch'):
1424 extra['close'] = 1
1424 extra['close'] = 1
1425
1425
1426 if not bheads:
1426 if not bheads:
1427 raise util.Abort(_('can only close branch heads'))
1427 raise util.Abort(_('can only close branch heads'))
1428 elif opts.get('amend'):
1428 elif opts.get('amend'):
1429 if repo.parents()[0].p1().branch() != branch and \
1429 if repo.parents()[0].p1().branch() != branch and \
1430 repo.parents()[0].p2().branch() != branch:
1430 repo.parents()[0].p2().branch() != branch:
1431 raise util.Abort(_('can only close branch heads'))
1431 raise util.Abort(_('can only close branch heads'))
1432
1432
1433 if opts.get('amend'):
1433 if opts.get('amend'):
1434 if ui.configbool('ui', 'commitsubrepos'):
1434 if ui.configbool('ui', 'commitsubrepos'):
1435 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1435 raise util.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1436
1436
1437 old = repo['.']
1437 old = repo['.']
1438 if not old.mutable():
1438 if not old.mutable():
1439 raise util.Abort(_('cannot amend public changesets'))
1439 raise util.Abort(_('cannot amend public changesets'))
1440 if len(repo[None].parents()) > 1:
1440 if len(repo[None].parents()) > 1:
1441 raise util.Abort(_('cannot amend while merging'))
1441 raise util.Abort(_('cannot amend while merging'))
1442 if (not obsolete._enabled) and old.children():
1442 if (not obsolete._enabled) and old.children():
1443 raise util.Abort(_('cannot amend changeset with children'))
1443 raise util.Abort(_('cannot amend changeset with children'))
1444
1444
1445 # commitfunc is used only for temporary amend commit by cmdutil.amend
1445 # commitfunc is used only for temporary amend commit by cmdutil.amend
1446 def commitfunc(ui, repo, message, match, opts):
1446 def commitfunc(ui, repo, message, match, opts):
1447 return repo.commit(message,
1447 return repo.commit(message,
1448 opts.get('user') or old.user(),
1448 opts.get('user') or old.user(),
1449 opts.get('date') or old.date(),
1449 opts.get('date') or old.date(),
1450 match,
1450 match,
1451 extra=extra)
1451 extra=extra)
1452
1452
1453 current = repo._bookmarkcurrent
1453 current = repo._bookmarkcurrent
1454 marks = old.bookmarks()
1454 marks = old.bookmarks()
1455 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1455 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1456 if node == old.node():
1456 if node == old.node():
1457 ui.status(_("nothing changed\n"))
1457 ui.status(_("nothing changed\n"))
1458 return 1
1458 return 1
1459 elif marks:
1459 elif marks:
1460 ui.debug('moving bookmarks %r from %s to %s\n' %
1460 ui.debug('moving bookmarks %r from %s to %s\n' %
1461 (marks, old.hex(), hex(node)))
1461 (marks, old.hex(), hex(node)))
1462 newmarks = repo._bookmarks
1462 newmarks = repo._bookmarks
1463 for bm in marks:
1463 for bm in marks:
1464 newmarks[bm] = node
1464 newmarks[bm] = node
1465 if bm == current:
1465 if bm == current:
1466 bookmarks.setcurrent(repo, bm)
1466 bookmarks.setcurrent(repo, bm)
1467 newmarks.write()
1467 newmarks.write()
1468 else:
1468 else:
1469 def commitfunc(ui, repo, message, match, opts):
1469 def commitfunc(ui, repo, message, match, opts):
1470 backup = ui.backupconfig('phases', 'new-commit')
1470 backup = ui.backupconfig('phases', 'new-commit')
1471 baseui = repo.baseui
1471 baseui = repo.baseui
1472 basebackup = baseui.backupconfig('phases', 'new-commit')
1472 basebackup = baseui.backupconfig('phases', 'new-commit')
1473 try:
1473 try:
1474 if opts.get('secret'):
1474 if opts.get('secret'):
1475 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1475 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1476 # Propagate to subrepos
1476 # Propagate to subrepos
1477 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1477 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1478
1478
1479 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1479 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1480 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1480 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1481 return repo.commit(message, opts.get('user'), opts.get('date'),
1481 return repo.commit(message, opts.get('user'), opts.get('date'),
1482 match,
1482 match,
1483 editor=editor,
1483 editor=editor,
1484 extra=extra)
1484 extra=extra)
1485 finally:
1485 finally:
1486 ui.restoreconfig(backup)
1486 ui.restoreconfig(backup)
1487 repo.baseui.restoreconfig(basebackup)
1487 repo.baseui.restoreconfig(basebackup)
1488
1488
1489
1489
1490 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1490 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1491
1491
1492 if not node:
1492 if not node:
1493 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1493 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1494 if stat[3]:
1494 if stat[3]:
1495 ui.status(_("nothing changed (%d missing files, see "
1495 ui.status(_("nothing changed (%d missing files, see "
1496 "'hg status')\n") % len(stat[3]))
1496 "'hg status')\n") % len(stat[3]))
1497 else:
1497 else:
1498 ui.status(_("nothing changed\n"))
1498 ui.status(_("nothing changed\n"))
1499 return 1
1499 return 1
1500
1500
1501 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1501 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1502
1502
1503 @command('config|showconfig|debugconfig',
1503 @command('config|showconfig|debugconfig',
1504 [('u', 'untrusted', None, _('show untrusted configuration options')),
1504 [('u', 'untrusted', None, _('show untrusted configuration options')),
1505 ('e', 'edit', None, _('edit user config')),
1505 ('e', 'edit', None, _('edit user config')),
1506 ('l', 'local', None, _('edit repository config')),
1506 ('l', 'local', None, _('edit repository config')),
1507 ('g', 'global', None, _('edit global config'))],
1507 ('g', 'global', None, _('edit global config'))],
1508 _('[-u] [NAME]...'),
1508 _('[-u] [NAME]...'),
1509 optionalrepo=True)
1509 optionalrepo=True)
1510 def config(ui, repo, *values, **opts):
1510 def config(ui, repo, *values, **opts):
1511 """show combined config settings from all hgrc files
1511 """show combined config settings from all hgrc files
1512
1512
1513 With no arguments, print names and values of all config items.
1513 With no arguments, print names and values of all config items.
1514
1514
1515 With one argument of the form section.name, print just the value
1515 With one argument of the form section.name, print just the value
1516 of that config item.
1516 of that config item.
1517
1517
1518 With multiple arguments, print names and values of all config
1518 With multiple arguments, print names and values of all config
1519 items with matching section names.
1519 items with matching section names.
1520
1520
1521 With --edit, start an editor on the user-level config file. With
1521 With --edit, start an editor on the user-level config file. With
1522 --global, edit the system-wide config file. With --local, edit the
1522 --global, edit the system-wide config file. With --local, edit the
1523 repository-level config file.
1523 repository-level config file.
1524
1524
1525 With --debug, the source (filename and line number) is printed
1525 With --debug, the source (filename and line number) is printed
1526 for each config item.
1526 for each config item.
1527
1527
1528 See :hg:`help config` for more information about config files.
1528 See :hg:`help config` for more information about config files.
1529
1529
1530 Returns 0 on success, 1 if NAME does not exist.
1530 Returns 0 on success, 1 if NAME does not exist.
1531
1531
1532 """
1532 """
1533
1533
1534 if opts.get('edit') or opts.get('local') or opts.get('global'):
1534 if opts.get('edit') or opts.get('local') or opts.get('global'):
1535 if opts.get('local') and opts.get('global'):
1535 if opts.get('local') and opts.get('global'):
1536 raise util.Abort(_("can't use --local and --global together"))
1536 raise util.Abort(_("can't use --local and --global together"))
1537
1537
1538 if opts.get('local'):
1538 if opts.get('local'):
1539 if not repo:
1539 if not repo:
1540 raise util.Abort(_("can't use --local outside a repository"))
1540 raise util.Abort(_("can't use --local outside a repository"))
1541 paths = [repo.join('hgrc')]
1541 paths = [repo.join('hgrc')]
1542 elif opts.get('global'):
1542 elif opts.get('global'):
1543 paths = scmutil.systemrcpath()
1543 paths = scmutil.systemrcpath()
1544 else:
1544 else:
1545 paths = scmutil.userrcpath()
1545 paths = scmutil.userrcpath()
1546
1546
1547 for f in paths:
1547 for f in paths:
1548 if os.path.exists(f):
1548 if os.path.exists(f):
1549 break
1549 break
1550 else:
1550 else:
1551 from ui import samplehgrcs
1551 from ui import samplehgrcs
1552
1552
1553 if opts.get('global'):
1553 if opts.get('global'):
1554 samplehgrc = samplehgrcs['global']
1554 samplehgrc = samplehgrcs['global']
1555 elif opts.get('local'):
1555 elif opts.get('local'):
1556 samplehgrc = samplehgrcs['local']
1556 samplehgrc = samplehgrcs['local']
1557 else:
1557 else:
1558 samplehgrc = samplehgrcs['user']
1558 samplehgrc = samplehgrcs['user']
1559
1559
1560 f = paths[0]
1560 f = paths[0]
1561 fp = open(f, "w")
1561 fp = open(f, "w")
1562 fp.write(samplehgrc)
1562 fp.write(samplehgrc)
1563 fp.close()
1563 fp.close()
1564
1564
1565 editor = ui.geteditor()
1565 editor = ui.geteditor()
1566 util.system("%s \"%s\"" % (editor, f),
1566 util.system("%s \"%s\"" % (editor, f),
1567 onerr=util.Abort, errprefix=_("edit failed"),
1567 onerr=util.Abort, errprefix=_("edit failed"),
1568 out=ui.fout)
1568 out=ui.fout)
1569 return
1569 return
1570
1570
1571 for f in scmutil.rcpath():
1571 for f in scmutil.rcpath():
1572 ui.debug('read config from: %s\n' % f)
1572 ui.debug('read config from: %s\n' % f)
1573 untrusted = bool(opts.get('untrusted'))
1573 untrusted = bool(opts.get('untrusted'))
1574 if values:
1574 if values:
1575 sections = [v for v in values if '.' not in v]
1575 sections = [v for v in values if '.' not in v]
1576 items = [v for v in values if '.' in v]
1576 items = [v for v in values if '.' in v]
1577 if len(items) > 1 or items and sections:
1577 if len(items) > 1 or items and sections:
1578 raise util.Abort(_('only one config item permitted'))
1578 raise util.Abort(_('only one config item permitted'))
1579 matched = False
1579 matched = False
1580 for section, name, value in ui.walkconfig(untrusted=untrusted):
1580 for section, name, value in ui.walkconfig(untrusted=untrusted):
1581 value = str(value).replace('\n', '\\n')
1581 value = str(value).replace('\n', '\\n')
1582 sectname = section + '.' + name
1582 sectname = section + '.' + name
1583 if values:
1583 if values:
1584 for v in values:
1584 for v in values:
1585 if v == section:
1585 if v == section:
1586 ui.debug('%s: ' %
1586 ui.debug('%s: ' %
1587 ui.configsource(section, name, untrusted))
1587 ui.configsource(section, name, untrusted))
1588 ui.write('%s=%s\n' % (sectname, value))
1588 ui.write('%s=%s\n' % (sectname, value))
1589 matched = True
1589 matched = True
1590 elif v == sectname:
1590 elif v == sectname:
1591 ui.debug('%s: ' %
1591 ui.debug('%s: ' %
1592 ui.configsource(section, name, untrusted))
1592 ui.configsource(section, name, untrusted))
1593 ui.write(value, '\n')
1593 ui.write(value, '\n')
1594 matched = True
1594 matched = True
1595 else:
1595 else:
1596 ui.debug('%s: ' %
1596 ui.debug('%s: ' %
1597 ui.configsource(section, name, untrusted))
1597 ui.configsource(section, name, untrusted))
1598 ui.write('%s=%s\n' % (sectname, value))
1598 ui.write('%s=%s\n' % (sectname, value))
1599 matched = True
1599 matched = True
1600 if matched:
1600 if matched:
1601 return 0
1601 return 0
1602 return 1
1602 return 1
1603
1603
1604 @command('copy|cp',
1604 @command('copy|cp',
1605 [('A', 'after', None, _('record a copy that has already occurred')),
1605 [('A', 'after', None, _('record a copy that has already occurred')),
1606 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1606 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1607 ] + walkopts + dryrunopts,
1607 ] + walkopts + dryrunopts,
1608 _('[OPTION]... [SOURCE]... DEST'))
1608 _('[OPTION]... [SOURCE]... DEST'))
1609 def copy(ui, repo, *pats, **opts):
1609 def copy(ui, repo, *pats, **opts):
1610 """mark files as copied for the next commit
1610 """mark files as copied for the next commit
1611
1611
1612 Mark dest as having copies of source files. If dest is a
1612 Mark dest as having copies of source files. If dest is a
1613 directory, copies are put in that directory. If dest is a file,
1613 directory, copies are put in that directory. If dest is a file,
1614 the source must be a single file.
1614 the source must be a single file.
1615
1615
1616 By default, this command copies the contents of files as they
1616 By default, this command copies the contents of files as they
1617 exist in the working directory. If invoked with -A/--after, the
1617 exist in the working directory. If invoked with -A/--after, the
1618 operation is recorded, but no copying is performed.
1618 operation is recorded, but no copying is performed.
1619
1619
1620 This command takes effect with the next commit. To undo a copy
1620 This command takes effect with the next commit. To undo a copy
1621 before that, see :hg:`revert`.
1621 before that, see :hg:`revert`.
1622
1622
1623 Returns 0 on success, 1 if errors are encountered.
1623 Returns 0 on success, 1 if errors are encountered.
1624 """
1624 """
1625 wlock = repo.wlock(False)
1625 wlock = repo.wlock(False)
1626 try:
1626 try:
1627 return cmdutil.copy(ui, repo, pats, opts)
1627 return cmdutil.copy(ui, repo, pats, opts)
1628 finally:
1628 finally:
1629 wlock.release()
1629 wlock.release()
1630
1630
1631 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1631 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1632 def debugancestor(ui, repo, *args):
1632 def debugancestor(ui, repo, *args):
1633 """find the ancestor revision of two revisions in a given index"""
1633 """find the ancestor revision of two revisions in a given index"""
1634 if len(args) == 3:
1634 if len(args) == 3:
1635 index, rev1, rev2 = args
1635 index, rev1, rev2 = args
1636 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1636 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1637 lookup = r.lookup
1637 lookup = r.lookup
1638 elif len(args) == 2:
1638 elif len(args) == 2:
1639 if not repo:
1639 if not repo:
1640 raise util.Abort(_("there is no Mercurial repository here "
1640 raise util.Abort(_("there is no Mercurial repository here "
1641 "(.hg not found)"))
1641 "(.hg not found)"))
1642 rev1, rev2 = args
1642 rev1, rev2 = args
1643 r = repo.changelog
1643 r = repo.changelog
1644 lookup = repo.lookup
1644 lookup = repo.lookup
1645 else:
1645 else:
1646 raise util.Abort(_('either two or three arguments required'))
1646 raise util.Abort(_('either two or three arguments required'))
1647 a = r.ancestor(lookup(rev1), lookup(rev2))
1647 a = r.ancestor(lookup(rev1), lookup(rev2))
1648 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1648 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1649
1649
1650 @command('debugbuilddag',
1650 @command('debugbuilddag',
1651 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1651 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1652 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1652 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1653 ('n', 'new-file', None, _('add new file at each rev'))],
1653 ('n', 'new-file', None, _('add new file at each rev'))],
1654 _('[OPTION]... [TEXT]'))
1654 _('[OPTION]... [TEXT]'))
1655 def debugbuilddag(ui, repo, text=None,
1655 def debugbuilddag(ui, repo, text=None,
1656 mergeable_file=False,
1656 mergeable_file=False,
1657 overwritten_file=False,
1657 overwritten_file=False,
1658 new_file=False):
1658 new_file=False):
1659 """builds a repo with a given DAG from scratch in the current empty repo
1659 """builds a repo with a given DAG from scratch in the current empty repo
1660
1660
1661 The description of the DAG is read from stdin if not given on the
1661 The description of the DAG is read from stdin if not given on the
1662 command line.
1662 command line.
1663
1663
1664 Elements:
1664 Elements:
1665
1665
1666 - "+n" is a linear run of n nodes based on the current default parent
1666 - "+n" is a linear run of n nodes based on the current default parent
1667 - "." is a single node based on the current default parent
1667 - "." is a single node based on the current default parent
1668 - "$" resets the default parent to null (implied at the start);
1668 - "$" resets the default parent to null (implied at the start);
1669 otherwise the default parent is always the last node created
1669 otherwise the default parent is always the last node created
1670 - "<p" sets the default parent to the backref p
1670 - "<p" sets the default parent to the backref p
1671 - "*p" is a fork at parent p, which is a backref
1671 - "*p" is a fork at parent p, which is a backref
1672 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1672 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1673 - "/p2" is a merge of the preceding node and p2
1673 - "/p2" is a merge of the preceding node and p2
1674 - ":tag" defines a local tag for the preceding node
1674 - ":tag" defines a local tag for the preceding node
1675 - "@branch" sets the named branch for subsequent nodes
1675 - "@branch" sets the named branch for subsequent nodes
1676 - "#...\\n" is a comment up to the end of the line
1676 - "#...\\n" is a comment up to the end of the line
1677
1677
1678 Whitespace between the above elements is ignored.
1678 Whitespace between the above elements is ignored.
1679
1679
1680 A backref is either
1680 A backref is either
1681
1681
1682 - a number n, which references the node curr-n, where curr is the current
1682 - a number n, which references the node curr-n, where curr is the current
1683 node, or
1683 node, or
1684 - the name of a local tag you placed earlier using ":tag", or
1684 - the name of a local tag you placed earlier using ":tag", or
1685 - empty to denote the default parent.
1685 - empty to denote the default parent.
1686
1686
1687 All string valued-elements are either strictly alphanumeric, or must
1687 All string valued-elements are either strictly alphanumeric, or must
1688 be enclosed in double quotes ("..."), with "\\" as escape character.
1688 be enclosed in double quotes ("..."), with "\\" as escape character.
1689 """
1689 """
1690
1690
1691 if text is None:
1691 if text is None:
1692 ui.status(_("reading DAG from stdin\n"))
1692 ui.status(_("reading DAG from stdin\n"))
1693 text = ui.fin.read()
1693 text = ui.fin.read()
1694
1694
1695 cl = repo.changelog
1695 cl = repo.changelog
1696 if len(cl) > 0:
1696 if len(cl) > 0:
1697 raise util.Abort(_('repository is not empty'))
1697 raise util.Abort(_('repository is not empty'))
1698
1698
1699 # determine number of revs in DAG
1699 # determine number of revs in DAG
1700 total = 0
1700 total = 0
1701 for type, data in dagparser.parsedag(text):
1701 for type, data in dagparser.parsedag(text):
1702 if type == 'n':
1702 if type == 'n':
1703 total += 1
1703 total += 1
1704
1704
1705 if mergeable_file:
1705 if mergeable_file:
1706 linesperrev = 2
1706 linesperrev = 2
1707 # make a file with k lines per rev
1707 # make a file with k lines per rev
1708 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1708 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1709 initialmergedlines.append("")
1709 initialmergedlines.append("")
1710
1710
1711 tags = []
1711 tags = []
1712
1712
1713 lock = tr = None
1713 lock = tr = None
1714 try:
1714 try:
1715 lock = repo.lock()
1715 lock = repo.lock()
1716 tr = repo.transaction("builddag")
1716 tr = repo.transaction("builddag")
1717
1717
1718 at = -1
1718 at = -1
1719 atbranch = 'default'
1719 atbranch = 'default'
1720 nodeids = []
1720 nodeids = []
1721 id = 0
1721 id = 0
1722 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1722 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1723 for type, data in dagparser.parsedag(text):
1723 for type, data in dagparser.parsedag(text):
1724 if type == 'n':
1724 if type == 'n':
1725 ui.note(('node %s\n' % str(data)))
1725 ui.note(('node %s\n' % str(data)))
1726 id, ps = data
1726 id, ps = data
1727
1727
1728 files = []
1728 files = []
1729 fctxs = {}
1729 fctxs = {}
1730
1730
1731 p2 = None
1731 p2 = None
1732 if mergeable_file:
1732 if mergeable_file:
1733 fn = "mf"
1733 fn = "mf"
1734 p1 = repo[ps[0]]
1734 p1 = repo[ps[0]]
1735 if len(ps) > 1:
1735 if len(ps) > 1:
1736 p2 = repo[ps[1]]
1736 p2 = repo[ps[1]]
1737 pa = p1.ancestor(p2)
1737 pa = p1.ancestor(p2)
1738 base, local, other = [x[fn].data() for x in (pa, p1,
1738 base, local, other = [x[fn].data() for x in (pa, p1,
1739 p2)]
1739 p2)]
1740 m3 = simplemerge.Merge3Text(base, local, other)
1740 m3 = simplemerge.Merge3Text(base, local, other)
1741 ml = [l.strip() for l in m3.merge_lines()]
1741 ml = [l.strip() for l in m3.merge_lines()]
1742 ml.append("")
1742 ml.append("")
1743 elif at > 0:
1743 elif at > 0:
1744 ml = p1[fn].data().split("\n")
1744 ml = p1[fn].data().split("\n")
1745 else:
1745 else:
1746 ml = initialmergedlines
1746 ml = initialmergedlines
1747 ml[id * linesperrev] += " r%i" % id
1747 ml[id * linesperrev] += " r%i" % id
1748 mergedtext = "\n".join(ml)
1748 mergedtext = "\n".join(ml)
1749 files.append(fn)
1749 files.append(fn)
1750 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1750 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1751
1751
1752 if overwritten_file:
1752 if overwritten_file:
1753 fn = "of"
1753 fn = "of"
1754 files.append(fn)
1754 files.append(fn)
1755 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1755 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1756
1756
1757 if new_file:
1757 if new_file:
1758 fn = "nf%i" % id
1758 fn = "nf%i" % id
1759 files.append(fn)
1759 files.append(fn)
1760 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1760 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1761 if len(ps) > 1:
1761 if len(ps) > 1:
1762 if not p2:
1762 if not p2:
1763 p2 = repo[ps[1]]
1763 p2 = repo[ps[1]]
1764 for fn in p2:
1764 for fn in p2:
1765 if fn.startswith("nf"):
1765 if fn.startswith("nf"):
1766 files.append(fn)
1766 files.append(fn)
1767 fctxs[fn] = p2[fn]
1767 fctxs[fn] = p2[fn]
1768
1768
1769 def fctxfn(repo, cx, path):
1769 def fctxfn(repo, cx, path):
1770 return fctxs.get(path)
1770 return fctxs.get(path)
1771
1771
1772 if len(ps) == 0 or ps[0] < 0:
1772 if len(ps) == 0 or ps[0] < 0:
1773 pars = [None, None]
1773 pars = [None, None]
1774 elif len(ps) == 1:
1774 elif len(ps) == 1:
1775 pars = [nodeids[ps[0]], None]
1775 pars = [nodeids[ps[0]], None]
1776 else:
1776 else:
1777 pars = [nodeids[p] for p in ps]
1777 pars = [nodeids[p] for p in ps]
1778 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1778 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1779 date=(id, 0),
1779 date=(id, 0),
1780 user="debugbuilddag",
1780 user="debugbuilddag",
1781 extra={'branch': atbranch})
1781 extra={'branch': atbranch})
1782 nodeid = repo.commitctx(cx)
1782 nodeid = repo.commitctx(cx)
1783 nodeids.append(nodeid)
1783 nodeids.append(nodeid)
1784 at = id
1784 at = id
1785 elif type == 'l':
1785 elif type == 'l':
1786 id, name = data
1786 id, name = data
1787 ui.note(('tag %s\n' % name))
1787 ui.note(('tag %s\n' % name))
1788 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1788 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1789 elif type == 'a':
1789 elif type == 'a':
1790 ui.note(('branch %s\n' % data))
1790 ui.note(('branch %s\n' % data))
1791 atbranch = data
1791 atbranch = data
1792 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1792 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1793 tr.close()
1793 tr.close()
1794
1794
1795 if tags:
1795 if tags:
1796 repo.opener.write("localtags", "".join(tags))
1796 repo.opener.write("localtags", "".join(tags))
1797 finally:
1797 finally:
1798 ui.progress(_('building'), None)
1798 ui.progress(_('building'), None)
1799 release(tr, lock)
1799 release(tr, lock)
1800
1800
1801 @command('debugbundle',
1801 @command('debugbundle',
1802 [('a', 'all', None, _('show all details'))],
1802 [('a', 'all', None, _('show all details'))],
1803 _('FILE'),
1803 _('FILE'),
1804 norepo=True)
1804 norepo=True)
1805 def debugbundle(ui, bundlepath, all=None, **opts):
1805 def debugbundle(ui, bundlepath, all=None, **opts):
1806 """lists the contents of a bundle"""
1806 """lists the contents of a bundle"""
1807 f = hg.openpath(ui, bundlepath)
1807 f = hg.openpath(ui, bundlepath)
1808 try:
1808 try:
1809 gen = exchange.readbundle(ui, f, bundlepath)
1809 gen = exchange.readbundle(ui, f, bundlepath)
1810 if all:
1810 if all:
1811 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1811 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1812
1812
1813 def showchunks(named):
1813 def showchunks(named):
1814 ui.write("\n%s\n" % named)
1814 ui.write("\n%s\n" % named)
1815 chain = None
1815 chain = None
1816 while True:
1816 while True:
1817 chunkdata = gen.deltachunk(chain)
1817 chunkdata = gen.deltachunk(chain)
1818 if not chunkdata:
1818 if not chunkdata:
1819 break
1819 break
1820 node = chunkdata['node']
1820 node = chunkdata['node']
1821 p1 = chunkdata['p1']
1821 p1 = chunkdata['p1']
1822 p2 = chunkdata['p2']
1822 p2 = chunkdata['p2']
1823 cs = chunkdata['cs']
1823 cs = chunkdata['cs']
1824 deltabase = chunkdata['deltabase']
1824 deltabase = chunkdata['deltabase']
1825 delta = chunkdata['delta']
1825 delta = chunkdata['delta']
1826 ui.write("%s %s %s %s %s %s\n" %
1826 ui.write("%s %s %s %s %s %s\n" %
1827 (hex(node), hex(p1), hex(p2),
1827 (hex(node), hex(p1), hex(p2),
1828 hex(cs), hex(deltabase), len(delta)))
1828 hex(cs), hex(deltabase), len(delta)))
1829 chain = node
1829 chain = node
1830
1830
1831 chunkdata = gen.changelogheader()
1831 chunkdata = gen.changelogheader()
1832 showchunks("changelog")
1832 showchunks("changelog")
1833 chunkdata = gen.manifestheader()
1833 chunkdata = gen.manifestheader()
1834 showchunks("manifest")
1834 showchunks("manifest")
1835 while True:
1835 while True:
1836 chunkdata = gen.filelogheader()
1836 chunkdata = gen.filelogheader()
1837 if not chunkdata:
1837 if not chunkdata:
1838 break
1838 break
1839 fname = chunkdata['filename']
1839 fname = chunkdata['filename']
1840 showchunks(fname)
1840 showchunks(fname)
1841 else:
1841 else:
1842 chunkdata = gen.changelogheader()
1842 chunkdata = gen.changelogheader()
1843 chain = None
1843 chain = None
1844 while True:
1844 while True:
1845 chunkdata = gen.deltachunk(chain)
1845 chunkdata = gen.deltachunk(chain)
1846 if not chunkdata:
1846 if not chunkdata:
1847 break
1847 break
1848 node = chunkdata['node']
1848 node = chunkdata['node']
1849 ui.write("%s\n" % hex(node))
1849 ui.write("%s\n" % hex(node))
1850 chain = node
1850 chain = node
1851 finally:
1851 finally:
1852 f.close()
1852 f.close()
1853
1853
1854 @command('debugcheckstate', [], '')
1854 @command('debugcheckstate', [], '')
1855 def debugcheckstate(ui, repo):
1855 def debugcheckstate(ui, repo):
1856 """validate the correctness of the current dirstate"""
1856 """validate the correctness of the current dirstate"""
1857 parent1, parent2 = repo.dirstate.parents()
1857 parent1, parent2 = repo.dirstate.parents()
1858 m1 = repo[parent1].manifest()
1858 m1 = repo[parent1].manifest()
1859 m2 = repo[parent2].manifest()
1859 m2 = repo[parent2].manifest()
1860 errors = 0
1860 errors = 0
1861 for f in repo.dirstate:
1861 for f in repo.dirstate:
1862 state = repo.dirstate[f]
1862 state = repo.dirstate[f]
1863 if state in "nr" and f not in m1:
1863 if state in "nr" and f not in m1:
1864 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1864 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1865 errors += 1
1865 errors += 1
1866 if state in "a" and f in m1:
1866 if state in "a" and f in m1:
1867 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1867 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1868 errors += 1
1868 errors += 1
1869 if state in "m" and f not in m1 and f not in m2:
1869 if state in "m" and f not in m1 and f not in m2:
1870 ui.warn(_("%s in state %s, but not in either manifest\n") %
1870 ui.warn(_("%s in state %s, but not in either manifest\n") %
1871 (f, state))
1871 (f, state))
1872 errors += 1
1872 errors += 1
1873 for f in m1:
1873 for f in m1:
1874 state = repo.dirstate[f]
1874 state = repo.dirstate[f]
1875 if state not in "nrm":
1875 if state not in "nrm":
1876 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1876 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1877 errors += 1
1877 errors += 1
1878 if errors:
1878 if errors:
1879 error = _(".hg/dirstate inconsistent with current parent's manifest")
1879 error = _(".hg/dirstate inconsistent with current parent's manifest")
1880 raise util.Abort(error)
1880 raise util.Abort(error)
1881
1881
1882 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1882 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
1883 def debugcommands(ui, cmd='', *args):
1883 def debugcommands(ui, cmd='', *args):
1884 """list all available commands and options"""
1884 """list all available commands and options"""
1885 for cmd, vals in sorted(table.iteritems()):
1885 for cmd, vals in sorted(table.iteritems()):
1886 cmd = cmd.split('|')[0].strip('^')
1886 cmd = cmd.split('|')[0].strip('^')
1887 opts = ', '.join([i[1] for i in vals[1]])
1887 opts = ', '.join([i[1] for i in vals[1]])
1888 ui.write('%s: %s\n' % (cmd, opts))
1888 ui.write('%s: %s\n' % (cmd, opts))
1889
1889
1890 @command('debugcomplete',
1890 @command('debugcomplete',
1891 [('o', 'options', None, _('show the command options'))],
1891 [('o', 'options', None, _('show the command options'))],
1892 _('[-o] CMD'),
1892 _('[-o] CMD'),
1893 norepo=True)
1893 norepo=True)
1894 def debugcomplete(ui, cmd='', **opts):
1894 def debugcomplete(ui, cmd='', **opts):
1895 """returns the completion list associated with the given command"""
1895 """returns the completion list associated with the given command"""
1896
1896
1897 if opts.get('options'):
1897 if opts.get('options'):
1898 options = []
1898 options = []
1899 otables = [globalopts]
1899 otables = [globalopts]
1900 if cmd:
1900 if cmd:
1901 aliases, entry = cmdutil.findcmd(cmd, table, False)
1901 aliases, entry = cmdutil.findcmd(cmd, table, False)
1902 otables.append(entry[1])
1902 otables.append(entry[1])
1903 for t in otables:
1903 for t in otables:
1904 for o in t:
1904 for o in t:
1905 if "(DEPRECATED)" in o[3]:
1905 if "(DEPRECATED)" in o[3]:
1906 continue
1906 continue
1907 if o[0]:
1907 if o[0]:
1908 options.append('-%s' % o[0])
1908 options.append('-%s' % o[0])
1909 options.append('--%s' % o[1])
1909 options.append('--%s' % o[1])
1910 ui.write("%s\n" % "\n".join(options))
1910 ui.write("%s\n" % "\n".join(options))
1911 return
1911 return
1912
1912
1913 cmdlist = cmdutil.findpossible(cmd, table)
1913 cmdlist = cmdutil.findpossible(cmd, table)
1914 if ui.verbose:
1914 if ui.verbose:
1915 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1915 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1916 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1916 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1917
1917
1918 @command('debugdag',
1918 @command('debugdag',
1919 [('t', 'tags', None, _('use tags as labels')),
1919 [('t', 'tags', None, _('use tags as labels')),
1920 ('b', 'branches', None, _('annotate with branch names')),
1920 ('b', 'branches', None, _('annotate with branch names')),
1921 ('', 'dots', None, _('use dots for runs')),
1921 ('', 'dots', None, _('use dots for runs')),
1922 ('s', 'spaces', None, _('separate elements by spaces'))],
1922 ('s', 'spaces', None, _('separate elements by spaces'))],
1923 _('[OPTION]... [FILE [REV]...]'),
1923 _('[OPTION]... [FILE [REV]...]'),
1924 optionalrepo=True)
1924 optionalrepo=True)
1925 def debugdag(ui, repo, file_=None, *revs, **opts):
1925 def debugdag(ui, repo, file_=None, *revs, **opts):
1926 """format the changelog or an index DAG as a concise textual description
1926 """format the changelog or an index DAG as a concise textual description
1927
1927
1928 If you pass a revlog index, the revlog's DAG is emitted. If you list
1928 If you pass a revlog index, the revlog's DAG is emitted. If you list
1929 revision numbers, they get labeled in the output as rN.
1929 revision numbers, they get labeled in the output as rN.
1930
1930
1931 Otherwise, the changelog DAG of the current repo is emitted.
1931 Otherwise, the changelog DAG of the current repo is emitted.
1932 """
1932 """
1933 spaces = opts.get('spaces')
1933 spaces = opts.get('spaces')
1934 dots = opts.get('dots')
1934 dots = opts.get('dots')
1935 if file_:
1935 if file_:
1936 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1936 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
1937 revs = set((int(r) for r in revs))
1937 revs = set((int(r) for r in revs))
1938 def events():
1938 def events():
1939 for r in rlog:
1939 for r in rlog:
1940 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1940 yield 'n', (r, list(p for p in rlog.parentrevs(r)
1941 if p != -1))
1941 if p != -1))
1942 if r in revs:
1942 if r in revs:
1943 yield 'l', (r, "r%i" % r)
1943 yield 'l', (r, "r%i" % r)
1944 elif repo:
1944 elif repo:
1945 cl = repo.changelog
1945 cl = repo.changelog
1946 tags = opts.get('tags')
1946 tags = opts.get('tags')
1947 branches = opts.get('branches')
1947 branches = opts.get('branches')
1948 if tags:
1948 if tags:
1949 labels = {}
1949 labels = {}
1950 for l, n in repo.tags().items():
1950 for l, n in repo.tags().items():
1951 labels.setdefault(cl.rev(n), []).append(l)
1951 labels.setdefault(cl.rev(n), []).append(l)
1952 def events():
1952 def events():
1953 b = "default"
1953 b = "default"
1954 for r in cl:
1954 for r in cl:
1955 if branches:
1955 if branches:
1956 newb = cl.read(cl.node(r))[5]['branch']
1956 newb = cl.read(cl.node(r))[5]['branch']
1957 if newb != b:
1957 if newb != b:
1958 yield 'a', newb
1958 yield 'a', newb
1959 b = newb
1959 b = newb
1960 yield 'n', (r, list(p for p in cl.parentrevs(r)
1960 yield 'n', (r, list(p for p in cl.parentrevs(r)
1961 if p != -1))
1961 if p != -1))
1962 if tags:
1962 if tags:
1963 ls = labels.get(r)
1963 ls = labels.get(r)
1964 if ls:
1964 if ls:
1965 for l in ls:
1965 for l in ls:
1966 yield 'l', (r, l)
1966 yield 'l', (r, l)
1967 else:
1967 else:
1968 raise util.Abort(_('need repo for changelog dag'))
1968 raise util.Abort(_('need repo for changelog dag'))
1969
1969
1970 for line in dagparser.dagtextlines(events(),
1970 for line in dagparser.dagtextlines(events(),
1971 addspaces=spaces,
1971 addspaces=spaces,
1972 wraplabels=True,
1972 wraplabels=True,
1973 wrapannotations=True,
1973 wrapannotations=True,
1974 wrapnonlinear=dots,
1974 wrapnonlinear=dots,
1975 usedots=dots,
1975 usedots=dots,
1976 maxlinewidth=70):
1976 maxlinewidth=70):
1977 ui.write(line)
1977 ui.write(line)
1978 ui.write("\n")
1978 ui.write("\n")
1979
1979
1980 @command('debugdata',
1980 @command('debugdata',
1981 [('c', 'changelog', False, _('open changelog')),
1981 [('c', 'changelog', False, _('open changelog')),
1982 ('m', 'manifest', False, _('open manifest'))],
1982 ('m', 'manifest', False, _('open manifest'))],
1983 _('-c|-m|FILE REV'))
1983 _('-c|-m|FILE REV'))
1984 def debugdata(ui, repo, file_, rev=None, **opts):
1984 def debugdata(ui, repo, file_, rev=None, **opts):
1985 """dump the contents of a data file revision"""
1985 """dump the contents of a data file revision"""
1986 if opts.get('changelog') or opts.get('manifest'):
1986 if opts.get('changelog') or opts.get('manifest'):
1987 file_, rev = None, file_
1987 file_, rev = None, file_
1988 elif rev is None:
1988 elif rev is None:
1989 raise error.CommandError('debugdata', _('invalid arguments'))
1989 raise error.CommandError('debugdata', _('invalid arguments'))
1990 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1990 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
1991 try:
1991 try:
1992 ui.write(r.revision(r.lookup(rev)))
1992 ui.write(r.revision(r.lookup(rev)))
1993 except KeyError:
1993 except KeyError:
1994 raise util.Abort(_('invalid revision identifier %s') % rev)
1994 raise util.Abort(_('invalid revision identifier %s') % rev)
1995
1995
1996 @command('debugdate',
1996 @command('debugdate',
1997 [('e', 'extended', None, _('try extended date formats'))],
1997 [('e', 'extended', None, _('try extended date formats'))],
1998 _('[-e] DATE [RANGE]'),
1998 _('[-e] DATE [RANGE]'),
1999 norepo=True, optionalrepo=True)
1999 norepo=True, optionalrepo=True)
2000 def debugdate(ui, date, range=None, **opts):
2000 def debugdate(ui, date, range=None, **opts):
2001 """parse and display a date"""
2001 """parse and display a date"""
2002 if opts["extended"]:
2002 if opts["extended"]:
2003 d = util.parsedate(date, util.extendeddateformats)
2003 d = util.parsedate(date, util.extendeddateformats)
2004 else:
2004 else:
2005 d = util.parsedate(date)
2005 d = util.parsedate(date)
2006 ui.write(("internal: %s %s\n") % d)
2006 ui.write(("internal: %s %s\n") % d)
2007 ui.write(("standard: %s\n") % util.datestr(d))
2007 ui.write(("standard: %s\n") % util.datestr(d))
2008 if range:
2008 if range:
2009 m = util.matchdate(range)
2009 m = util.matchdate(range)
2010 ui.write(("match: %s\n") % m(d[0]))
2010 ui.write(("match: %s\n") % m(d[0]))
2011
2011
2012 @command('debugdiscovery',
2012 @command('debugdiscovery',
2013 [('', 'old', None, _('use old-style discovery')),
2013 [('', 'old', None, _('use old-style discovery')),
2014 ('', 'nonheads', None,
2014 ('', 'nonheads', None,
2015 _('use old-style discovery with non-heads included')),
2015 _('use old-style discovery with non-heads included')),
2016 ] + remoteopts,
2016 ] + remoteopts,
2017 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2017 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2018 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2018 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2019 """runs the changeset discovery protocol in isolation"""
2019 """runs the changeset discovery protocol in isolation"""
2020 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2020 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2021 opts.get('branch'))
2021 opts.get('branch'))
2022 remote = hg.peer(repo, opts, remoteurl)
2022 remote = hg.peer(repo, opts, remoteurl)
2023 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2023 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2024
2024
2025 # make sure tests are repeatable
2025 # make sure tests are repeatable
2026 random.seed(12323)
2026 random.seed(12323)
2027
2027
2028 def doit(localheads, remoteheads, remote=remote):
2028 def doit(localheads, remoteheads, remote=remote):
2029 if opts.get('old'):
2029 if opts.get('old'):
2030 if localheads:
2030 if localheads:
2031 raise util.Abort('cannot use localheads with old style '
2031 raise util.Abort('cannot use localheads with old style '
2032 'discovery')
2032 'discovery')
2033 if not util.safehasattr(remote, 'branches'):
2033 if not util.safehasattr(remote, 'branches'):
2034 # enable in-client legacy support
2034 # enable in-client legacy support
2035 remote = localrepo.locallegacypeer(remote.local())
2035 remote = localrepo.locallegacypeer(remote.local())
2036 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2036 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2037 force=True)
2037 force=True)
2038 common = set(common)
2038 common = set(common)
2039 if not opts.get('nonheads'):
2039 if not opts.get('nonheads'):
2040 ui.write(("unpruned common: %s\n") %
2040 ui.write(("unpruned common: %s\n") %
2041 " ".join(sorted(short(n) for n in common)))
2041 " ".join(sorted(short(n) for n in common)))
2042 dag = dagutil.revlogdag(repo.changelog)
2042 dag = dagutil.revlogdag(repo.changelog)
2043 all = dag.ancestorset(dag.internalizeall(common))
2043 all = dag.ancestorset(dag.internalizeall(common))
2044 common = dag.externalizeall(dag.headsetofconnecteds(all))
2044 common = dag.externalizeall(dag.headsetofconnecteds(all))
2045 else:
2045 else:
2046 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2046 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2047 common = set(common)
2047 common = set(common)
2048 rheads = set(hds)
2048 rheads = set(hds)
2049 lheads = set(repo.heads())
2049 lheads = set(repo.heads())
2050 ui.write(("common heads: %s\n") %
2050 ui.write(("common heads: %s\n") %
2051 " ".join(sorted(short(n) for n in common)))
2051 " ".join(sorted(short(n) for n in common)))
2052 if lheads <= common:
2052 if lheads <= common:
2053 ui.write(("local is subset\n"))
2053 ui.write(("local is subset\n"))
2054 elif rheads <= common:
2054 elif rheads <= common:
2055 ui.write(("remote is subset\n"))
2055 ui.write(("remote is subset\n"))
2056
2056
2057 serverlogs = opts.get('serverlog')
2057 serverlogs = opts.get('serverlog')
2058 if serverlogs:
2058 if serverlogs:
2059 for filename in serverlogs:
2059 for filename in serverlogs:
2060 logfile = open(filename, 'r')
2060 logfile = open(filename, 'r')
2061 try:
2061 try:
2062 line = logfile.readline()
2062 line = logfile.readline()
2063 while line:
2063 while line:
2064 parts = line.strip().split(';')
2064 parts = line.strip().split(';')
2065 op = parts[1]
2065 op = parts[1]
2066 if op == 'cg':
2066 if op == 'cg':
2067 pass
2067 pass
2068 elif op == 'cgss':
2068 elif op == 'cgss':
2069 doit(parts[2].split(' '), parts[3].split(' '))
2069 doit(parts[2].split(' '), parts[3].split(' '))
2070 elif op == 'unb':
2070 elif op == 'unb':
2071 doit(parts[3].split(' '), parts[2].split(' '))
2071 doit(parts[3].split(' '), parts[2].split(' '))
2072 line = logfile.readline()
2072 line = logfile.readline()
2073 finally:
2073 finally:
2074 logfile.close()
2074 logfile.close()
2075
2075
2076 else:
2076 else:
2077 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2077 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2078 opts.get('remote_head'))
2078 opts.get('remote_head'))
2079 localrevs = opts.get('local_head')
2079 localrevs = opts.get('local_head')
2080 doit(localrevs, remoterevs)
2080 doit(localrevs, remoterevs)
2081
2081
2082 @command('debugfileset',
2082 @command('debugfileset',
2083 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2083 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2084 _('[-r REV] FILESPEC'))
2084 _('[-r REV] FILESPEC'))
2085 def debugfileset(ui, repo, expr, **opts):
2085 def debugfileset(ui, repo, expr, **opts):
2086 '''parse and apply a fileset specification'''
2086 '''parse and apply a fileset specification'''
2087 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2087 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2088 if ui.verbose:
2088 if ui.verbose:
2089 tree = fileset.parse(expr)[0]
2089 tree = fileset.parse(expr)[0]
2090 ui.note(tree, "\n")
2090 ui.note(tree, "\n")
2091
2091
2092 for f in ctx.getfileset(expr):
2092 for f in ctx.getfileset(expr):
2093 ui.write("%s\n" % f)
2093 ui.write("%s\n" % f)
2094
2094
2095 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2095 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2096 def debugfsinfo(ui, path="."):
2096 def debugfsinfo(ui, path="."):
2097 """show information detected about current filesystem"""
2097 """show information detected about current filesystem"""
2098 util.writefile('.debugfsinfo', '')
2098 util.writefile('.debugfsinfo', '')
2099 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2099 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2100 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2100 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2101 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2101 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2102 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2102 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2103 and 'yes' or 'no'))
2103 and 'yes' or 'no'))
2104 os.unlink('.debugfsinfo')
2104 os.unlink('.debugfsinfo')
2105
2105
2106 @command('debuggetbundle',
2106 @command('debuggetbundle',
2107 [('H', 'head', [], _('id of head node'), _('ID')),
2107 [('H', 'head', [], _('id of head node'), _('ID')),
2108 ('C', 'common', [], _('id of common node'), _('ID')),
2108 ('C', 'common', [], _('id of common node'), _('ID')),
2109 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2109 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2110 _('REPO FILE [-H|-C ID]...'),
2110 _('REPO FILE [-H|-C ID]...'),
2111 norepo=True)
2111 norepo=True)
2112 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2112 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2113 """retrieves a bundle from a repo
2113 """retrieves a bundle from a repo
2114
2114
2115 Every ID must be a full-length hex node id string. Saves the bundle to the
2115 Every ID must be a full-length hex node id string. Saves the bundle to the
2116 given file.
2116 given file.
2117 """
2117 """
2118 repo = hg.peer(ui, opts, repopath)
2118 repo = hg.peer(ui, opts, repopath)
2119 if not repo.capable('getbundle'):
2119 if not repo.capable('getbundle'):
2120 raise util.Abort("getbundle() not supported by target repository")
2120 raise util.Abort("getbundle() not supported by target repository")
2121 args = {}
2121 args = {}
2122 if common:
2122 if common:
2123 args['common'] = [bin(s) for s in common]
2123 args['common'] = [bin(s) for s in common]
2124 if head:
2124 if head:
2125 args['heads'] = [bin(s) for s in head]
2125 args['heads'] = [bin(s) for s in head]
2126 # TODO: get desired bundlecaps from command line.
2126 # TODO: get desired bundlecaps from command line.
2127 args['bundlecaps'] = None
2127 args['bundlecaps'] = None
2128 bundle = repo.getbundle('debug', **args)
2128 bundle = repo.getbundle('debug', **args)
2129
2129
2130 bundletype = opts.get('type', 'bzip2').lower()
2130 bundletype = opts.get('type', 'bzip2').lower()
2131 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2131 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
2132 bundletype = btypes.get(bundletype)
2132 bundletype = btypes.get(bundletype)
2133 if bundletype not in changegroup.bundletypes:
2133 if bundletype not in changegroup.bundletypes:
2134 raise util.Abort(_('unknown bundle type specified with --type'))
2134 raise util.Abort(_('unknown bundle type specified with --type'))
2135 changegroup.writebundle(bundle, bundlepath, bundletype)
2135 changegroup.writebundle(bundle, bundlepath, bundletype)
2136
2136
2137 @command('debugignore', [], '')
2137 @command('debugignore', [], '')
2138 def debugignore(ui, repo, *values, **opts):
2138 def debugignore(ui, repo, *values, **opts):
2139 """display the combined ignore pattern"""
2139 """display the combined ignore pattern"""
2140 ignore = repo.dirstate._ignore
2140 ignore = repo.dirstate._ignore
2141 includepat = getattr(ignore, 'includepat', None)
2141 includepat = getattr(ignore, 'includepat', None)
2142 if includepat is not None:
2142 if includepat is not None:
2143 ui.write("%s\n" % includepat)
2143 ui.write("%s\n" % includepat)
2144 else:
2144 else:
2145 raise util.Abort(_("no ignore patterns found"))
2145 raise util.Abort(_("no ignore patterns found"))
2146
2146
2147 @command('debugindex',
2147 @command('debugindex',
2148 [('c', 'changelog', False, _('open changelog')),
2148 [('c', 'changelog', False, _('open changelog')),
2149 ('m', 'manifest', False, _('open manifest')),
2149 ('m', 'manifest', False, _('open manifest')),
2150 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2150 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2151 _('[-f FORMAT] -c|-m|FILE'),
2151 _('[-f FORMAT] -c|-m|FILE'),
2152 optionalrepo=True)
2152 optionalrepo=True)
2153 def debugindex(ui, repo, file_=None, **opts):
2153 def debugindex(ui, repo, file_=None, **opts):
2154 """dump the contents of an index file"""
2154 """dump the contents of an index file"""
2155 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2155 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2156 format = opts.get('format', 0)
2156 format = opts.get('format', 0)
2157 if format not in (0, 1):
2157 if format not in (0, 1):
2158 raise util.Abort(_("unknown format %d") % format)
2158 raise util.Abort(_("unknown format %d") % format)
2159
2159
2160 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2160 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2161 if generaldelta:
2161 if generaldelta:
2162 basehdr = ' delta'
2162 basehdr = ' delta'
2163 else:
2163 else:
2164 basehdr = ' base'
2164 basehdr = ' base'
2165
2165
2166 if format == 0:
2166 if format == 0:
2167 ui.write(" rev offset length " + basehdr + " linkrev"
2167 ui.write(" rev offset length " + basehdr + " linkrev"
2168 " nodeid p1 p2\n")
2168 " nodeid p1 p2\n")
2169 elif format == 1:
2169 elif format == 1:
2170 ui.write(" rev flag offset length"
2170 ui.write(" rev flag offset length"
2171 " size " + basehdr + " link p1 p2"
2171 " size " + basehdr + " link p1 p2"
2172 " nodeid\n")
2172 " nodeid\n")
2173
2173
2174 for i in r:
2174 for i in r:
2175 node = r.node(i)
2175 node = r.node(i)
2176 if generaldelta:
2176 if generaldelta:
2177 base = r.deltaparent(i)
2177 base = r.deltaparent(i)
2178 else:
2178 else:
2179 base = r.chainbase(i)
2179 base = r.chainbase(i)
2180 if format == 0:
2180 if format == 0:
2181 try:
2181 try:
2182 pp = r.parents(node)
2182 pp = r.parents(node)
2183 except Exception:
2183 except Exception:
2184 pp = [nullid, nullid]
2184 pp = [nullid, nullid]
2185 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2185 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2186 i, r.start(i), r.length(i), base, r.linkrev(i),
2186 i, r.start(i), r.length(i), base, r.linkrev(i),
2187 short(node), short(pp[0]), short(pp[1])))
2187 short(node), short(pp[0]), short(pp[1])))
2188 elif format == 1:
2188 elif format == 1:
2189 pr = r.parentrevs(i)
2189 pr = r.parentrevs(i)
2190 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2190 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2191 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2191 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2192 base, r.linkrev(i), pr[0], pr[1], short(node)))
2192 base, r.linkrev(i), pr[0], pr[1], short(node)))
2193
2193
2194 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2194 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2195 def debugindexdot(ui, repo, file_):
2195 def debugindexdot(ui, repo, file_):
2196 """dump an index DAG as a graphviz dot file"""
2196 """dump an index DAG as a graphviz dot file"""
2197 r = None
2197 r = None
2198 if repo:
2198 if repo:
2199 filelog = repo.file(file_)
2199 filelog = repo.file(file_)
2200 if len(filelog):
2200 if len(filelog):
2201 r = filelog
2201 r = filelog
2202 if not r:
2202 if not r:
2203 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2203 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2204 ui.write(("digraph G {\n"))
2204 ui.write(("digraph G {\n"))
2205 for i in r:
2205 for i in r:
2206 node = r.node(i)
2206 node = r.node(i)
2207 pp = r.parents(node)
2207 pp = r.parents(node)
2208 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2208 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2209 if pp[1] != nullid:
2209 if pp[1] != nullid:
2210 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2210 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2211 ui.write("}\n")
2211 ui.write("}\n")
2212
2212
2213 @command('debuginstall', [], '', norepo=True)
2213 @command('debuginstall', [], '', norepo=True)
2214 def debuginstall(ui):
2214 def debuginstall(ui):
2215 '''test Mercurial installation
2215 '''test Mercurial installation
2216
2216
2217 Returns 0 on success.
2217 Returns 0 on success.
2218 '''
2218 '''
2219
2219
2220 def writetemp(contents):
2220 def writetemp(contents):
2221 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2221 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2222 f = os.fdopen(fd, "wb")
2222 f = os.fdopen(fd, "wb")
2223 f.write(contents)
2223 f.write(contents)
2224 f.close()
2224 f.close()
2225 return name
2225 return name
2226
2226
2227 problems = 0
2227 problems = 0
2228
2228
2229 # encoding
2229 # encoding
2230 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2230 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2231 try:
2231 try:
2232 encoding.fromlocal("test")
2232 encoding.fromlocal("test")
2233 except util.Abort, inst:
2233 except util.Abort, inst:
2234 ui.write(" %s\n" % inst)
2234 ui.write(" %s\n" % inst)
2235 ui.write(_(" (check that your locale is properly set)\n"))
2235 ui.write(_(" (check that your locale is properly set)\n"))
2236 problems += 1
2236 problems += 1
2237
2237
2238 # Python
2238 # Python
2239 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2239 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2240 ui.status(_("checking Python version (%s)\n")
2240 ui.status(_("checking Python version (%s)\n")
2241 % ("%s.%s.%s" % sys.version_info[:3]))
2241 % ("%s.%s.%s" % sys.version_info[:3]))
2242 ui.status(_("checking Python lib (%s)...\n")
2242 ui.status(_("checking Python lib (%s)...\n")
2243 % os.path.dirname(os.__file__))
2243 % os.path.dirname(os.__file__))
2244
2244
2245 # compiled modules
2245 # compiled modules
2246 ui.status(_("checking installed modules (%s)...\n")
2246 ui.status(_("checking installed modules (%s)...\n")
2247 % os.path.dirname(__file__))
2247 % os.path.dirname(__file__))
2248 try:
2248 try:
2249 import bdiff, mpatch, base85, osutil
2249 import bdiff, mpatch, base85, osutil
2250 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2250 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2251 except Exception, inst:
2251 except Exception, inst:
2252 ui.write(" %s\n" % inst)
2252 ui.write(" %s\n" % inst)
2253 ui.write(_(" One or more extensions could not be found"))
2253 ui.write(_(" One or more extensions could not be found"))
2254 ui.write(_(" (check that you compiled the extensions)\n"))
2254 ui.write(_(" (check that you compiled the extensions)\n"))
2255 problems += 1
2255 problems += 1
2256
2256
2257 # templates
2257 # templates
2258 import templater
2258 import templater
2259 p = templater.templatepath()
2259 p = templater.templatepath()
2260 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2260 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2261 if p:
2261 if p:
2262 m = templater.templatepath("map-cmdline.default")
2262 m = templater.templatepath("map-cmdline.default")
2263 if m:
2263 if m:
2264 # template found, check if it is working
2264 # template found, check if it is working
2265 try:
2265 try:
2266 templater.templater(m)
2266 templater.templater(m)
2267 except Exception, inst:
2267 except Exception, inst:
2268 ui.write(" %s\n" % inst)
2268 ui.write(" %s\n" % inst)
2269 p = None
2269 p = None
2270 else:
2270 else:
2271 ui.write(_(" template 'default' not found\n"))
2271 ui.write(_(" template 'default' not found\n"))
2272 p = None
2272 p = None
2273 else:
2273 else:
2274 ui.write(_(" no template directories found\n"))
2274 ui.write(_(" no template directories found\n"))
2275 if not p:
2275 if not p:
2276 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2276 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2277 problems += 1
2277 problems += 1
2278
2278
2279 # editor
2279 # editor
2280 ui.status(_("checking commit editor...\n"))
2280 ui.status(_("checking commit editor...\n"))
2281 editor = ui.geteditor()
2281 editor = ui.geteditor()
2282 cmdpath = util.findexe(shlex.split(editor)[0])
2282 cmdpath = util.findexe(shlex.split(editor)[0])
2283 if not cmdpath:
2283 if not cmdpath:
2284 if editor == 'vi':
2284 if editor == 'vi':
2285 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2285 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2286 ui.write(_(" (specify a commit editor in your configuration"
2286 ui.write(_(" (specify a commit editor in your configuration"
2287 " file)\n"))
2287 " file)\n"))
2288 else:
2288 else:
2289 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2289 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2290 ui.write(_(" (specify a commit editor in your configuration"
2290 ui.write(_(" (specify a commit editor in your configuration"
2291 " file)\n"))
2291 " file)\n"))
2292 problems += 1
2292 problems += 1
2293
2293
2294 # check username
2294 # check username
2295 ui.status(_("checking username...\n"))
2295 ui.status(_("checking username...\n"))
2296 try:
2296 try:
2297 ui.username()
2297 ui.username()
2298 except util.Abort, e:
2298 except util.Abort, e:
2299 ui.write(" %s\n" % e)
2299 ui.write(" %s\n" % e)
2300 ui.write(_(" (specify a username in your configuration file)\n"))
2300 ui.write(_(" (specify a username in your configuration file)\n"))
2301 problems += 1
2301 problems += 1
2302
2302
2303 if not problems:
2303 if not problems:
2304 ui.status(_("no problems detected\n"))
2304 ui.status(_("no problems detected\n"))
2305 else:
2305 else:
2306 ui.write(_("%s problems detected,"
2306 ui.write(_("%s problems detected,"
2307 " please check your install!\n") % problems)
2307 " please check your install!\n") % problems)
2308
2308
2309 return problems
2309 return problems
2310
2310
2311 @command('debugknown', [], _('REPO ID...'), norepo=True)
2311 @command('debugknown', [], _('REPO ID...'), norepo=True)
2312 def debugknown(ui, repopath, *ids, **opts):
2312 def debugknown(ui, repopath, *ids, **opts):
2313 """test whether node ids are known to a repo
2313 """test whether node ids are known to a repo
2314
2314
2315 Every ID must be a full-length hex node id string. Returns a list of 0s
2315 Every ID must be a full-length hex node id string. Returns a list of 0s
2316 and 1s indicating unknown/known.
2316 and 1s indicating unknown/known.
2317 """
2317 """
2318 repo = hg.peer(ui, opts, repopath)
2318 repo = hg.peer(ui, opts, repopath)
2319 if not repo.capable('known'):
2319 if not repo.capable('known'):
2320 raise util.Abort("known() not supported by target repository")
2320 raise util.Abort("known() not supported by target repository")
2321 flags = repo.known([bin(s) for s in ids])
2321 flags = repo.known([bin(s) for s in ids])
2322 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2322 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2323
2323
2324 @command('debuglabelcomplete', [], _('LABEL...'))
2324 @command('debuglabelcomplete', [], _('LABEL...'))
2325 def debuglabelcomplete(ui, repo, *args):
2325 def debuglabelcomplete(ui, repo, *args):
2326 '''complete "labels" - tags, open branch names, bookmark names'''
2326 '''complete "labels" - tags, open branch names, bookmark names'''
2327
2327
2328 labels = set()
2328 labels = set()
2329 labels.update(t[0] for t in repo.tagslist())
2329 labels.update(t[0] for t in repo.tagslist())
2330 labels.update(repo._bookmarks.keys())
2330 labels.update(repo._bookmarks.keys())
2331 labels.update(tag for (tag, heads, tip, closed)
2331 labels.update(tag for (tag, heads, tip, closed)
2332 in repo.branchmap().iterbranches() if not closed)
2332 in repo.branchmap().iterbranches() if not closed)
2333 completions = set()
2333 completions = set()
2334 if not args:
2334 if not args:
2335 args = ['']
2335 args = ['']
2336 for a in args:
2336 for a in args:
2337 completions.update(l for l in labels if l.startswith(a))
2337 completions.update(l for l in labels if l.startswith(a))
2338 ui.write('\n'.join(sorted(completions)))
2338 ui.write('\n'.join(sorted(completions)))
2339 ui.write('\n')
2339 ui.write('\n')
2340
2340
2341 @command('debugobsolete',
2341 @command('debugobsolete',
2342 [('', 'flags', 0, _('markers flag')),
2342 [('', 'flags', 0, _('markers flag')),
2343 ('', 'record-parents', False,
2343 ('', 'record-parents', False,
2344 _('record parent information for the precursor')),
2344 _('record parent information for the precursor')),
2345 ('r', 'rev', [], _('display markers relevant to REV')),
2345 ('r', 'rev', [], _('display markers relevant to REV')),
2346 ] + commitopts2,
2346 ] + commitopts2,
2347 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2347 _('[OBSOLETED [REPLACEMENT] [REPL... ]'))
2348 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2348 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2349 """create arbitrary obsolete marker
2349 """create arbitrary obsolete marker
2350
2350
2351 With no arguments, displays the list of obsolescence markers."""
2351 With no arguments, displays the list of obsolescence markers."""
2352
2352
2353 def parsenodeid(s):
2353 def parsenodeid(s):
2354 try:
2354 try:
2355 # We do not use revsingle/revrange functions here to accept
2355 # We do not use revsingle/revrange functions here to accept
2356 # arbitrary node identifiers, possibly not present in the
2356 # arbitrary node identifiers, possibly not present in the
2357 # local repository.
2357 # local repository.
2358 n = bin(s)
2358 n = bin(s)
2359 if len(n) != len(nullid):
2359 if len(n) != len(nullid):
2360 raise TypeError()
2360 raise TypeError()
2361 return n
2361 return n
2362 except TypeError:
2362 except TypeError:
2363 raise util.Abort('changeset references must be full hexadecimal '
2363 raise util.Abort('changeset references must be full hexadecimal '
2364 'node identifiers')
2364 'node identifiers')
2365
2365
2366 if precursor is not None:
2366 if precursor is not None:
2367 if opts['rev']:
2367 if opts['rev']:
2368 raise util.Abort('cannot select revision when creating marker')
2368 raise util.Abort('cannot select revision when creating marker')
2369 metadata = {}
2369 metadata = {}
2370 metadata['user'] = opts['user'] or ui.username()
2370 metadata['user'] = opts['user'] or ui.username()
2371 succs = tuple(parsenodeid(succ) for succ in successors)
2371 succs = tuple(parsenodeid(succ) for succ in successors)
2372 l = repo.lock()
2372 l = repo.lock()
2373 try:
2373 try:
2374 tr = repo.transaction('debugobsolete')
2374 tr = repo.transaction('debugobsolete')
2375 try:
2375 try:
2376 try:
2376 try:
2377 date = opts.get('date')
2377 date = opts.get('date')
2378 if date:
2378 if date:
2379 date = util.parsedate(date)
2379 date = util.parsedate(date)
2380 else:
2380 else:
2381 date = None
2381 date = None
2382 prec = parsenodeid(precursor)
2382 prec = parsenodeid(precursor)
2383 parents = None
2383 parents = None
2384 if opts['record_parents']:
2384 if opts['record_parents']:
2385 if prec not in repo.unfiltered():
2385 if prec not in repo.unfiltered():
2386 raise util.Abort('cannot used --record-parents on '
2386 raise util.Abort('cannot used --record-parents on '
2387 'unknown changesets')
2387 'unknown changesets')
2388 parents = repo.unfiltered()[prec].parents()
2388 parents = repo.unfiltered()[prec].parents()
2389 parents = tuple(p.node() for p in parents)
2389 parents = tuple(p.node() for p in parents)
2390 repo.obsstore.create(tr, prec, succs, opts['flags'],
2390 repo.obsstore.create(tr, prec, succs, opts['flags'],
2391 parents=parents, date=date,
2391 parents=parents, date=date,
2392 metadata=metadata)
2392 metadata=metadata)
2393 tr.close()
2393 tr.close()
2394 except ValueError, exc:
2394 except ValueError, exc:
2395 raise util.Abort(_('bad obsmarker input: %s') % exc)
2395 raise util.Abort(_('bad obsmarker input: %s') % exc)
2396 finally:
2396 finally:
2397 tr.release()
2397 tr.release()
2398 finally:
2398 finally:
2399 l.release()
2399 l.release()
2400 else:
2400 else:
2401 if opts['rev']:
2401 if opts['rev']:
2402 revs = scmutil.revrange(repo, opts['rev'])
2402 revs = scmutil.revrange(repo, opts['rev'])
2403 nodes = [repo[r].node() for r in revs]
2403 nodes = [repo[r].node() for r in revs]
2404 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2404 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2405 markers.sort(key=lambda x: x._data)
2405 markers.sort(key=lambda x: x._data)
2406 else:
2406 else:
2407 markers = obsolete.getmarkers(repo)
2407 markers = obsolete.getmarkers(repo)
2408
2408
2409 for m in markers:
2409 for m in markers:
2410 cmdutil.showmarker(ui, m)
2410 cmdutil.showmarker(ui, m)
2411
2411
2412 @command('debugpathcomplete',
2412 @command('debugpathcomplete',
2413 [('f', 'full', None, _('complete an entire path')),
2413 [('f', 'full', None, _('complete an entire path')),
2414 ('n', 'normal', None, _('show only normal files')),
2414 ('n', 'normal', None, _('show only normal files')),
2415 ('a', 'added', None, _('show only added files')),
2415 ('a', 'added', None, _('show only added files')),
2416 ('r', 'removed', None, _('show only removed files'))],
2416 ('r', 'removed', None, _('show only removed files'))],
2417 _('FILESPEC...'))
2417 _('FILESPEC...'))
2418 def debugpathcomplete(ui, repo, *specs, **opts):
2418 def debugpathcomplete(ui, repo, *specs, **opts):
2419 '''complete part or all of a tracked path
2419 '''complete part or all of a tracked path
2420
2420
2421 This command supports shells that offer path name completion. It
2421 This command supports shells that offer path name completion. It
2422 currently completes only files already known to the dirstate.
2422 currently completes only files already known to the dirstate.
2423
2423
2424 Completion extends only to the next path segment unless
2424 Completion extends only to the next path segment unless
2425 --full is specified, in which case entire paths are used.'''
2425 --full is specified, in which case entire paths are used.'''
2426
2426
2427 def complete(path, acceptable):
2427 def complete(path, acceptable):
2428 dirstate = repo.dirstate
2428 dirstate = repo.dirstate
2429 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2429 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2430 rootdir = repo.root + os.sep
2430 rootdir = repo.root + os.sep
2431 if spec != repo.root and not spec.startswith(rootdir):
2431 if spec != repo.root and not spec.startswith(rootdir):
2432 return [], []
2432 return [], []
2433 if os.path.isdir(spec):
2433 if os.path.isdir(spec):
2434 spec += '/'
2434 spec += '/'
2435 spec = spec[len(rootdir):]
2435 spec = spec[len(rootdir):]
2436 fixpaths = os.sep != '/'
2436 fixpaths = os.sep != '/'
2437 if fixpaths:
2437 if fixpaths:
2438 spec = spec.replace(os.sep, '/')
2438 spec = spec.replace(os.sep, '/')
2439 speclen = len(spec)
2439 speclen = len(spec)
2440 fullpaths = opts['full']
2440 fullpaths = opts['full']
2441 files, dirs = set(), set()
2441 files, dirs = set(), set()
2442 adddir, addfile = dirs.add, files.add
2442 adddir, addfile = dirs.add, files.add
2443 for f, st in dirstate.iteritems():
2443 for f, st in dirstate.iteritems():
2444 if f.startswith(spec) and st[0] in acceptable:
2444 if f.startswith(spec) and st[0] in acceptable:
2445 if fixpaths:
2445 if fixpaths:
2446 f = f.replace('/', os.sep)
2446 f = f.replace('/', os.sep)
2447 if fullpaths:
2447 if fullpaths:
2448 addfile(f)
2448 addfile(f)
2449 continue
2449 continue
2450 s = f.find(os.sep, speclen)
2450 s = f.find(os.sep, speclen)
2451 if s >= 0:
2451 if s >= 0:
2452 adddir(f[:s])
2452 adddir(f[:s])
2453 else:
2453 else:
2454 addfile(f)
2454 addfile(f)
2455 return files, dirs
2455 return files, dirs
2456
2456
2457 acceptable = ''
2457 acceptable = ''
2458 if opts['normal']:
2458 if opts['normal']:
2459 acceptable += 'nm'
2459 acceptable += 'nm'
2460 if opts['added']:
2460 if opts['added']:
2461 acceptable += 'a'
2461 acceptable += 'a'
2462 if opts['removed']:
2462 if opts['removed']:
2463 acceptable += 'r'
2463 acceptable += 'r'
2464 cwd = repo.getcwd()
2464 cwd = repo.getcwd()
2465 if not specs:
2465 if not specs:
2466 specs = ['.']
2466 specs = ['.']
2467
2467
2468 files, dirs = set(), set()
2468 files, dirs = set(), set()
2469 for spec in specs:
2469 for spec in specs:
2470 f, d = complete(spec, acceptable or 'nmar')
2470 f, d = complete(spec, acceptable or 'nmar')
2471 files.update(f)
2471 files.update(f)
2472 dirs.update(d)
2472 dirs.update(d)
2473 files.update(dirs)
2473 files.update(dirs)
2474 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2474 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2475 ui.write('\n')
2475 ui.write('\n')
2476
2476
2477 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2477 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2478 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2478 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2479 '''access the pushkey key/value protocol
2479 '''access the pushkey key/value protocol
2480
2480
2481 With two args, list the keys in the given namespace.
2481 With two args, list the keys in the given namespace.
2482
2482
2483 With five args, set a key to new if it currently is set to old.
2483 With five args, set a key to new if it currently is set to old.
2484 Reports success or failure.
2484 Reports success or failure.
2485 '''
2485 '''
2486
2486
2487 target = hg.peer(ui, {}, repopath)
2487 target = hg.peer(ui, {}, repopath)
2488 if keyinfo:
2488 if keyinfo:
2489 key, old, new = keyinfo
2489 key, old, new = keyinfo
2490 r = target.pushkey(namespace, key, old, new)
2490 r = target.pushkey(namespace, key, old, new)
2491 ui.status(str(r) + '\n')
2491 ui.status(str(r) + '\n')
2492 return not r
2492 return not r
2493 else:
2493 else:
2494 for k, v in sorted(target.listkeys(namespace).iteritems()):
2494 for k, v in sorted(target.listkeys(namespace).iteritems()):
2495 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2495 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2496 v.encode('string-escape')))
2496 v.encode('string-escape')))
2497
2497
2498 @command('debugpvec', [], _('A B'))
2498 @command('debugpvec', [], _('A B'))
2499 def debugpvec(ui, repo, a, b=None):
2499 def debugpvec(ui, repo, a, b=None):
2500 ca = scmutil.revsingle(repo, a)
2500 ca = scmutil.revsingle(repo, a)
2501 cb = scmutil.revsingle(repo, b)
2501 cb = scmutil.revsingle(repo, b)
2502 pa = pvec.ctxpvec(ca)
2502 pa = pvec.ctxpvec(ca)
2503 pb = pvec.ctxpvec(cb)
2503 pb = pvec.ctxpvec(cb)
2504 if pa == pb:
2504 if pa == pb:
2505 rel = "="
2505 rel = "="
2506 elif pa > pb:
2506 elif pa > pb:
2507 rel = ">"
2507 rel = ">"
2508 elif pa < pb:
2508 elif pa < pb:
2509 rel = "<"
2509 rel = "<"
2510 elif pa | pb:
2510 elif pa | pb:
2511 rel = "|"
2511 rel = "|"
2512 ui.write(_("a: %s\n") % pa)
2512 ui.write(_("a: %s\n") % pa)
2513 ui.write(_("b: %s\n") % pb)
2513 ui.write(_("b: %s\n") % pb)
2514 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2514 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2515 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2515 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2516 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2516 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2517 pa.distance(pb), rel))
2517 pa.distance(pb), rel))
2518
2518
2519 @command('debugrebuilddirstate|debugrebuildstate',
2519 @command('debugrebuilddirstate|debugrebuildstate',
2520 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2520 [('r', 'rev', '', _('revision to rebuild to'), _('REV'))],
2521 _('[-r REV]'))
2521 _('[-r REV]'))
2522 def debugrebuilddirstate(ui, repo, rev):
2522 def debugrebuilddirstate(ui, repo, rev):
2523 """rebuild the dirstate as it would look like for the given revision
2523 """rebuild the dirstate as it would look like for the given revision
2524
2524
2525 If no revision is specified the first current parent will be used.
2525 If no revision is specified the first current parent will be used.
2526
2526
2527 The dirstate will be set to the files of the given revision.
2527 The dirstate will be set to the files of the given revision.
2528 The actual working directory content or existing dirstate
2528 The actual working directory content or existing dirstate
2529 information such as adds or removes is not considered.
2529 information such as adds or removes is not considered.
2530
2530
2531 One use of this command is to make the next :hg:`status` invocation
2531 One use of this command is to make the next :hg:`status` invocation
2532 check the actual file content.
2532 check the actual file content.
2533 """
2533 """
2534 ctx = scmutil.revsingle(repo, rev)
2534 ctx = scmutil.revsingle(repo, rev)
2535 wlock = repo.wlock()
2535 wlock = repo.wlock()
2536 try:
2536 try:
2537 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2537 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
2538 finally:
2538 finally:
2539 wlock.release()
2539 wlock.release()
2540
2540
2541 @command('debugrename',
2541 @command('debugrename',
2542 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2542 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2543 _('[-r REV] FILE'))
2543 _('[-r REV] FILE'))
2544 def debugrename(ui, repo, file1, *pats, **opts):
2544 def debugrename(ui, repo, file1, *pats, **opts):
2545 """dump rename information"""
2545 """dump rename information"""
2546
2546
2547 ctx = scmutil.revsingle(repo, opts.get('rev'))
2547 ctx = scmutil.revsingle(repo, opts.get('rev'))
2548 m = scmutil.match(ctx, (file1,) + pats, opts)
2548 m = scmutil.match(ctx, (file1,) + pats, opts)
2549 for abs in ctx.walk(m):
2549 for abs in ctx.walk(m):
2550 fctx = ctx[abs]
2550 fctx = ctx[abs]
2551 o = fctx.filelog().renamed(fctx.filenode())
2551 o = fctx.filelog().renamed(fctx.filenode())
2552 rel = m.rel(abs)
2552 rel = m.rel(abs)
2553 if o:
2553 if o:
2554 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2554 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2555 else:
2555 else:
2556 ui.write(_("%s not renamed\n") % rel)
2556 ui.write(_("%s not renamed\n") % rel)
2557
2557
2558 @command('debugrevlog',
2558 @command('debugrevlog',
2559 [('c', 'changelog', False, _('open changelog')),
2559 [('c', 'changelog', False, _('open changelog')),
2560 ('m', 'manifest', False, _('open manifest')),
2560 ('m', 'manifest', False, _('open manifest')),
2561 ('d', 'dump', False, _('dump index data'))],
2561 ('d', 'dump', False, _('dump index data'))],
2562 _('-c|-m|FILE'),
2562 _('-c|-m|FILE'),
2563 optionalrepo=True)
2563 optionalrepo=True)
2564 def debugrevlog(ui, repo, file_=None, **opts):
2564 def debugrevlog(ui, repo, file_=None, **opts):
2565 """show data and statistics about a revlog"""
2565 """show data and statistics about a revlog"""
2566 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2566 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2567
2567
2568 if opts.get("dump"):
2568 if opts.get("dump"):
2569 numrevs = len(r)
2569 numrevs = len(r)
2570 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2570 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2571 " rawsize totalsize compression heads chainlen\n")
2571 " rawsize totalsize compression heads chainlen\n")
2572 ts = 0
2572 ts = 0
2573 heads = set()
2573 heads = set()
2574 rindex = r.index
2574 rindex = r.index
2575
2575
2576 def chainbaseandlen(rev):
2576 def chainbaseandlen(rev):
2577 clen = 0
2577 clen = 0
2578 base = rindex[rev][3]
2578 base = rindex[rev][3]
2579 while base != rev:
2579 while base != rev:
2580 clen += 1
2580 clen += 1
2581 rev = base
2581 rev = base
2582 base = rindex[rev][3]
2582 base = rindex[rev][3]
2583 return base, clen
2583 return base, clen
2584
2584
2585 for rev in xrange(numrevs):
2585 for rev in xrange(numrevs):
2586 dbase = r.deltaparent(rev)
2586 dbase = r.deltaparent(rev)
2587 if dbase == -1:
2587 if dbase == -1:
2588 dbase = rev
2588 dbase = rev
2589 cbase, clen = chainbaseandlen(rev)
2589 cbase, clen = chainbaseandlen(rev)
2590 p1, p2 = r.parentrevs(rev)
2590 p1, p2 = r.parentrevs(rev)
2591 rs = r.rawsize(rev)
2591 rs = r.rawsize(rev)
2592 ts = ts + rs
2592 ts = ts + rs
2593 heads -= set(r.parentrevs(rev))
2593 heads -= set(r.parentrevs(rev))
2594 heads.add(rev)
2594 heads.add(rev)
2595 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2595 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2596 "%11d %5d %8d\n" %
2596 "%11d %5d %8d\n" %
2597 (rev, p1, p2, r.start(rev), r.end(rev),
2597 (rev, p1, p2, r.start(rev), r.end(rev),
2598 r.start(dbase), r.start(cbase),
2598 r.start(dbase), r.start(cbase),
2599 r.start(p1), r.start(p2),
2599 r.start(p1), r.start(p2),
2600 rs, ts, ts / r.end(rev), len(heads), clen))
2600 rs, ts, ts / r.end(rev), len(heads), clen))
2601 return 0
2601 return 0
2602
2602
2603 v = r.version
2603 v = r.version
2604 format = v & 0xFFFF
2604 format = v & 0xFFFF
2605 flags = []
2605 flags = []
2606 gdelta = False
2606 gdelta = False
2607 if v & revlog.REVLOGNGINLINEDATA:
2607 if v & revlog.REVLOGNGINLINEDATA:
2608 flags.append('inline')
2608 flags.append('inline')
2609 if v & revlog.REVLOGGENERALDELTA:
2609 if v & revlog.REVLOGGENERALDELTA:
2610 gdelta = True
2610 gdelta = True
2611 flags.append('generaldelta')
2611 flags.append('generaldelta')
2612 if not flags:
2612 if not flags:
2613 flags = ['(none)']
2613 flags = ['(none)']
2614
2614
2615 nummerges = 0
2615 nummerges = 0
2616 numfull = 0
2616 numfull = 0
2617 numprev = 0
2617 numprev = 0
2618 nump1 = 0
2618 nump1 = 0
2619 nump2 = 0
2619 nump2 = 0
2620 numother = 0
2620 numother = 0
2621 nump1prev = 0
2621 nump1prev = 0
2622 nump2prev = 0
2622 nump2prev = 0
2623 chainlengths = []
2623 chainlengths = []
2624
2624
2625 datasize = [None, 0, 0L]
2625 datasize = [None, 0, 0L]
2626 fullsize = [None, 0, 0L]
2626 fullsize = [None, 0, 0L]
2627 deltasize = [None, 0, 0L]
2627 deltasize = [None, 0, 0L]
2628
2628
2629 def addsize(size, l):
2629 def addsize(size, l):
2630 if l[0] is None or size < l[0]:
2630 if l[0] is None or size < l[0]:
2631 l[0] = size
2631 l[0] = size
2632 if size > l[1]:
2632 if size > l[1]:
2633 l[1] = size
2633 l[1] = size
2634 l[2] += size
2634 l[2] += size
2635
2635
2636 numrevs = len(r)
2636 numrevs = len(r)
2637 for rev in xrange(numrevs):
2637 for rev in xrange(numrevs):
2638 p1, p2 = r.parentrevs(rev)
2638 p1, p2 = r.parentrevs(rev)
2639 delta = r.deltaparent(rev)
2639 delta = r.deltaparent(rev)
2640 if format > 0:
2640 if format > 0:
2641 addsize(r.rawsize(rev), datasize)
2641 addsize(r.rawsize(rev), datasize)
2642 if p2 != nullrev:
2642 if p2 != nullrev:
2643 nummerges += 1
2643 nummerges += 1
2644 size = r.length(rev)
2644 size = r.length(rev)
2645 if delta == nullrev:
2645 if delta == nullrev:
2646 chainlengths.append(0)
2646 chainlengths.append(0)
2647 numfull += 1
2647 numfull += 1
2648 addsize(size, fullsize)
2648 addsize(size, fullsize)
2649 else:
2649 else:
2650 chainlengths.append(chainlengths[delta] + 1)
2650 chainlengths.append(chainlengths[delta] + 1)
2651 addsize(size, deltasize)
2651 addsize(size, deltasize)
2652 if delta == rev - 1:
2652 if delta == rev - 1:
2653 numprev += 1
2653 numprev += 1
2654 if delta == p1:
2654 if delta == p1:
2655 nump1prev += 1
2655 nump1prev += 1
2656 elif delta == p2:
2656 elif delta == p2:
2657 nump2prev += 1
2657 nump2prev += 1
2658 elif delta == p1:
2658 elif delta == p1:
2659 nump1 += 1
2659 nump1 += 1
2660 elif delta == p2:
2660 elif delta == p2:
2661 nump2 += 1
2661 nump2 += 1
2662 elif delta != nullrev:
2662 elif delta != nullrev:
2663 numother += 1
2663 numother += 1
2664
2664
2665 # Adjust size min value for empty cases
2665 # Adjust size min value for empty cases
2666 for size in (datasize, fullsize, deltasize):
2666 for size in (datasize, fullsize, deltasize):
2667 if size[0] is None:
2667 if size[0] is None:
2668 size[0] = 0
2668 size[0] = 0
2669
2669
2670 numdeltas = numrevs - numfull
2670 numdeltas = numrevs - numfull
2671 numoprev = numprev - nump1prev - nump2prev
2671 numoprev = numprev - nump1prev - nump2prev
2672 totalrawsize = datasize[2]
2672 totalrawsize = datasize[2]
2673 datasize[2] /= numrevs
2673 datasize[2] /= numrevs
2674 fulltotal = fullsize[2]
2674 fulltotal = fullsize[2]
2675 fullsize[2] /= numfull
2675 fullsize[2] /= numfull
2676 deltatotal = deltasize[2]
2676 deltatotal = deltasize[2]
2677 if numrevs - numfull > 0:
2677 if numrevs - numfull > 0:
2678 deltasize[2] /= numrevs - numfull
2678 deltasize[2] /= numrevs - numfull
2679 totalsize = fulltotal + deltatotal
2679 totalsize = fulltotal + deltatotal
2680 avgchainlen = sum(chainlengths) / numrevs
2680 avgchainlen = sum(chainlengths) / numrevs
2681 compratio = totalrawsize / totalsize
2681 compratio = totalrawsize / totalsize
2682
2682
2683 basedfmtstr = '%%%dd\n'
2683 basedfmtstr = '%%%dd\n'
2684 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2684 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
2685
2685
2686 def dfmtstr(max):
2686 def dfmtstr(max):
2687 return basedfmtstr % len(str(max))
2687 return basedfmtstr % len(str(max))
2688 def pcfmtstr(max, padding=0):
2688 def pcfmtstr(max, padding=0):
2689 return basepcfmtstr % (len(str(max)), ' ' * padding)
2689 return basepcfmtstr % (len(str(max)), ' ' * padding)
2690
2690
2691 def pcfmt(value, total):
2691 def pcfmt(value, total):
2692 return (value, 100 * float(value) / total)
2692 return (value, 100 * float(value) / total)
2693
2693
2694 ui.write(('format : %d\n') % format)
2694 ui.write(('format : %d\n') % format)
2695 ui.write(('flags : %s\n') % ', '.join(flags))
2695 ui.write(('flags : %s\n') % ', '.join(flags))
2696
2696
2697 ui.write('\n')
2697 ui.write('\n')
2698 fmt = pcfmtstr(totalsize)
2698 fmt = pcfmtstr(totalsize)
2699 fmt2 = dfmtstr(totalsize)
2699 fmt2 = dfmtstr(totalsize)
2700 ui.write(('revisions : ') + fmt2 % numrevs)
2700 ui.write(('revisions : ') + fmt2 % numrevs)
2701 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2701 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
2702 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2702 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
2703 ui.write(('revisions : ') + fmt2 % numrevs)
2703 ui.write(('revisions : ') + fmt2 % numrevs)
2704 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2704 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
2705 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2705 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
2706 ui.write(('revision size : ') + fmt2 % totalsize)
2706 ui.write(('revision size : ') + fmt2 % totalsize)
2707 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2707 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
2708 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2708 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
2709
2709
2710 ui.write('\n')
2710 ui.write('\n')
2711 fmt = dfmtstr(max(avgchainlen, compratio))
2711 fmt = dfmtstr(max(avgchainlen, compratio))
2712 ui.write(('avg chain length : ') + fmt % avgchainlen)
2712 ui.write(('avg chain length : ') + fmt % avgchainlen)
2713 ui.write(('compression ratio : ') + fmt % compratio)
2713 ui.write(('compression ratio : ') + fmt % compratio)
2714
2714
2715 if format > 0:
2715 if format > 0:
2716 ui.write('\n')
2716 ui.write('\n')
2717 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2717 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
2718 % tuple(datasize))
2718 % tuple(datasize))
2719 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2719 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
2720 % tuple(fullsize))
2720 % tuple(fullsize))
2721 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2721 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
2722 % tuple(deltasize))
2722 % tuple(deltasize))
2723
2723
2724 if numdeltas > 0:
2724 if numdeltas > 0:
2725 ui.write('\n')
2725 ui.write('\n')
2726 fmt = pcfmtstr(numdeltas)
2726 fmt = pcfmtstr(numdeltas)
2727 fmt2 = pcfmtstr(numdeltas, 4)
2727 fmt2 = pcfmtstr(numdeltas, 4)
2728 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2728 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
2729 if numprev > 0:
2729 if numprev > 0:
2730 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2730 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
2731 numprev))
2731 numprev))
2732 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2732 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
2733 numprev))
2733 numprev))
2734 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2734 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
2735 numprev))
2735 numprev))
2736 if gdelta:
2736 if gdelta:
2737 ui.write(('deltas against p1 : ')
2737 ui.write(('deltas against p1 : ')
2738 + fmt % pcfmt(nump1, numdeltas))
2738 + fmt % pcfmt(nump1, numdeltas))
2739 ui.write(('deltas against p2 : ')
2739 ui.write(('deltas against p2 : ')
2740 + fmt % pcfmt(nump2, numdeltas))
2740 + fmt % pcfmt(nump2, numdeltas))
2741 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2741 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
2742 numdeltas))
2742 numdeltas))
2743
2743
2744 @command('debugrevspec',
2744 @command('debugrevspec',
2745 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2745 [('', 'optimize', None, _('print parsed tree after optimizing'))],
2746 ('REVSPEC'))
2746 ('REVSPEC'))
2747 def debugrevspec(ui, repo, expr, **opts):
2747 def debugrevspec(ui, repo, expr, **opts):
2748 """parse and apply a revision specification
2748 """parse and apply a revision specification
2749
2749
2750 Use --verbose to print the parsed tree before and after aliases
2750 Use --verbose to print the parsed tree before and after aliases
2751 expansion.
2751 expansion.
2752 """
2752 """
2753 if ui.verbose:
2753 if ui.verbose:
2754 tree = revset.parse(expr)[0]
2754 tree = revset.parse(expr)[0]
2755 ui.note(revset.prettyformat(tree), "\n")
2755 ui.note(revset.prettyformat(tree), "\n")
2756 newtree = revset.findaliases(ui, tree)
2756 newtree = revset.findaliases(ui, tree)
2757 if newtree != tree:
2757 if newtree != tree:
2758 ui.note(revset.prettyformat(newtree), "\n")
2758 ui.note(revset.prettyformat(newtree), "\n")
2759 if opts["optimize"]:
2759 if opts["optimize"]:
2760 weight, optimizedtree = revset.optimize(newtree, True)
2760 weight, optimizedtree = revset.optimize(newtree, True)
2761 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2761 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
2762 func = revset.match(ui, expr)
2762 func = revset.match(ui, expr)
2763 for c in func(repo, revset.spanset(repo)):
2763 for c in func(repo, revset.spanset(repo)):
2764 ui.write("%s\n" % c)
2764 ui.write("%s\n" % c)
2765
2765
2766 @command('debugsetparents', [], _('REV1 [REV2]'))
2766 @command('debugsetparents', [], _('REV1 [REV2]'))
2767 def debugsetparents(ui, repo, rev1, rev2=None):
2767 def debugsetparents(ui, repo, rev1, rev2=None):
2768 """manually set the parents of the current working directory
2768 """manually set the parents of the current working directory
2769
2769
2770 This is useful for writing repository conversion tools, but should
2770 This is useful for writing repository conversion tools, but should
2771 be used with care.
2771 be used with care.
2772
2772
2773 Returns 0 on success.
2773 Returns 0 on success.
2774 """
2774 """
2775
2775
2776 r1 = scmutil.revsingle(repo, rev1).node()
2776 r1 = scmutil.revsingle(repo, rev1).node()
2777 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2777 r2 = scmutil.revsingle(repo, rev2, 'null').node()
2778
2778
2779 wlock = repo.wlock()
2779 wlock = repo.wlock()
2780 try:
2780 try:
2781 repo.dirstate.beginparentchange()
2781 repo.dirstate.beginparentchange()
2782 repo.setparents(r1, r2)
2782 repo.setparents(r1, r2)
2783 repo.dirstate.endparentchange()
2783 repo.dirstate.endparentchange()
2784 finally:
2784 finally:
2785 wlock.release()
2785 wlock.release()
2786
2786
2787 @command('debugdirstate|debugstate',
2787 @command('debugdirstate|debugstate',
2788 [('', 'nodates', None, _('do not display the saved mtime')),
2788 [('', 'nodates', None, _('do not display the saved mtime')),
2789 ('', 'datesort', None, _('sort by saved mtime'))],
2789 ('', 'datesort', None, _('sort by saved mtime'))],
2790 _('[OPTION]...'))
2790 _('[OPTION]...'))
2791 def debugstate(ui, repo, nodates=None, datesort=None):
2791 def debugstate(ui, repo, nodates=None, datesort=None):
2792 """show the contents of the current dirstate"""
2792 """show the contents of the current dirstate"""
2793 timestr = ""
2793 timestr = ""
2794 showdate = not nodates
2794 showdate = not nodates
2795 if datesort:
2795 if datesort:
2796 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2796 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
2797 else:
2797 else:
2798 keyfunc = None # sort by filename
2798 keyfunc = None # sort by filename
2799 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2799 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
2800 if showdate:
2800 if showdate:
2801 if ent[3] == -1:
2801 if ent[3] == -1:
2802 # Pad or slice to locale representation
2802 # Pad or slice to locale representation
2803 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2803 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
2804 time.localtime(0)))
2804 time.localtime(0)))
2805 timestr = 'unset'
2805 timestr = 'unset'
2806 timestr = (timestr[:locale_len] +
2806 timestr = (timestr[:locale_len] +
2807 ' ' * (locale_len - len(timestr)))
2807 ' ' * (locale_len - len(timestr)))
2808 else:
2808 else:
2809 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2809 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
2810 time.localtime(ent[3]))
2810 time.localtime(ent[3]))
2811 if ent[1] & 020000:
2811 if ent[1] & 020000:
2812 mode = 'lnk'
2812 mode = 'lnk'
2813 else:
2813 else:
2814 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2814 mode = '%3o' % (ent[1] & 0777 & ~util.umask)
2815 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2815 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
2816 for f in repo.dirstate.copies():
2816 for f in repo.dirstate.copies():
2817 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2817 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
2818
2818
2819 @command('debugsub',
2819 @command('debugsub',
2820 [('r', 'rev', '',
2820 [('r', 'rev', '',
2821 _('revision to check'), _('REV'))],
2821 _('revision to check'), _('REV'))],
2822 _('[-r REV] [REV]'))
2822 _('[-r REV] [REV]'))
2823 def debugsub(ui, repo, rev=None):
2823 def debugsub(ui, repo, rev=None):
2824 ctx = scmutil.revsingle(repo, rev, None)
2824 ctx = scmutil.revsingle(repo, rev, None)
2825 for k, v in sorted(ctx.substate.items()):
2825 for k, v in sorted(ctx.substate.items()):
2826 ui.write(('path %s\n') % k)
2826 ui.write(('path %s\n') % k)
2827 ui.write((' source %s\n') % v[0])
2827 ui.write((' source %s\n') % v[0])
2828 ui.write((' revision %s\n') % v[1])
2828 ui.write((' revision %s\n') % v[1])
2829
2829
2830 @command('debugsuccessorssets',
2830 @command('debugsuccessorssets',
2831 [],
2831 [],
2832 _('[REV]'))
2832 _('[REV]'))
2833 def debugsuccessorssets(ui, repo, *revs):
2833 def debugsuccessorssets(ui, repo, *revs):
2834 """show set of successors for revision
2834 """show set of successors for revision
2835
2835
2836 A successors set of changeset A is a consistent group of revisions that
2836 A successors set of changeset A is a consistent group of revisions that
2837 succeed A. It contains non-obsolete changesets only.
2837 succeed A. It contains non-obsolete changesets only.
2838
2838
2839 In most cases a changeset A has a single successors set containing a single
2839 In most cases a changeset A has a single successors set containing a single
2840 successor (changeset A replaced by A').
2840 successor (changeset A replaced by A').
2841
2841
2842 A changeset that is made obsolete with no successors are called "pruned".
2842 A changeset that is made obsolete with no successors are called "pruned".
2843 Such changesets have no successors sets at all.
2843 Such changesets have no successors sets at all.
2844
2844
2845 A changeset that has been "split" will have a successors set containing
2845 A changeset that has been "split" will have a successors set containing
2846 more than one successor.
2846 more than one successor.
2847
2847
2848 A changeset that has been rewritten in multiple different ways is called
2848 A changeset that has been rewritten in multiple different ways is called
2849 "divergent". Such changesets have multiple successor sets (each of which
2849 "divergent". Such changesets have multiple successor sets (each of which
2850 may also be split, i.e. have multiple successors).
2850 may also be split, i.e. have multiple successors).
2851
2851
2852 Results are displayed as follows::
2852 Results are displayed as follows::
2853
2853
2854 <rev1>
2854 <rev1>
2855 <successors-1A>
2855 <successors-1A>
2856 <rev2>
2856 <rev2>
2857 <successors-2A>
2857 <successors-2A>
2858 <successors-2B1> <successors-2B2> <successors-2B3>
2858 <successors-2B1> <successors-2B2> <successors-2B3>
2859
2859
2860 Here rev2 has two possible (i.e. divergent) successors sets. The first
2860 Here rev2 has two possible (i.e. divergent) successors sets. The first
2861 holds one element, whereas the second holds three (i.e. the changeset has
2861 holds one element, whereas the second holds three (i.e. the changeset has
2862 been split).
2862 been split).
2863 """
2863 """
2864 # passed to successorssets caching computation from one call to another
2864 # passed to successorssets caching computation from one call to another
2865 cache = {}
2865 cache = {}
2866 ctx2str = str
2866 ctx2str = str
2867 node2str = short
2867 node2str = short
2868 if ui.debug():
2868 if ui.debug():
2869 def ctx2str(ctx):
2869 def ctx2str(ctx):
2870 return ctx.hex()
2870 return ctx.hex()
2871 node2str = hex
2871 node2str = hex
2872 for rev in scmutil.revrange(repo, revs):
2872 for rev in scmutil.revrange(repo, revs):
2873 ctx = repo[rev]
2873 ctx = repo[rev]
2874 ui.write('%s\n'% ctx2str(ctx))
2874 ui.write('%s\n'% ctx2str(ctx))
2875 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2875 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
2876 if succsset:
2876 if succsset:
2877 ui.write(' ')
2877 ui.write(' ')
2878 ui.write(node2str(succsset[0]))
2878 ui.write(node2str(succsset[0]))
2879 for node in succsset[1:]:
2879 for node in succsset[1:]:
2880 ui.write(' ')
2880 ui.write(' ')
2881 ui.write(node2str(node))
2881 ui.write(node2str(node))
2882 ui.write('\n')
2882 ui.write('\n')
2883
2883
2884 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2884 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
2885 def debugwalk(ui, repo, *pats, **opts):
2885 def debugwalk(ui, repo, *pats, **opts):
2886 """show how files match on given patterns"""
2886 """show how files match on given patterns"""
2887 m = scmutil.match(repo[None], pats, opts)
2887 m = scmutil.match(repo[None], pats, opts)
2888 items = list(repo.walk(m))
2888 items = list(repo.walk(m))
2889 if not items:
2889 if not items:
2890 return
2890 return
2891 f = lambda fn: fn
2891 f = lambda fn: fn
2892 if ui.configbool('ui', 'slash') and os.sep != '/':
2892 if ui.configbool('ui', 'slash') and os.sep != '/':
2893 f = lambda fn: util.normpath(fn)
2893 f = lambda fn: util.normpath(fn)
2894 fmt = 'f %%-%ds %%-%ds %%s' % (
2894 fmt = 'f %%-%ds %%-%ds %%s' % (
2895 max([len(abs) for abs in items]),
2895 max([len(abs) for abs in items]),
2896 max([len(m.rel(abs)) for abs in items]))
2896 max([len(m.rel(abs)) for abs in items]))
2897 for abs in items:
2897 for abs in items:
2898 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2898 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
2899 ui.write("%s\n" % line.rstrip())
2899 ui.write("%s\n" % line.rstrip())
2900
2900
2901 @command('debugwireargs',
2901 @command('debugwireargs',
2902 [('', 'three', '', 'three'),
2902 [('', 'three', '', 'three'),
2903 ('', 'four', '', 'four'),
2903 ('', 'four', '', 'four'),
2904 ('', 'five', '', 'five'),
2904 ('', 'five', '', 'five'),
2905 ] + remoteopts,
2905 ] + remoteopts,
2906 _('REPO [OPTIONS]... [ONE [TWO]]'),
2906 _('REPO [OPTIONS]... [ONE [TWO]]'),
2907 norepo=True)
2907 norepo=True)
2908 def debugwireargs(ui, repopath, *vals, **opts):
2908 def debugwireargs(ui, repopath, *vals, **opts):
2909 repo = hg.peer(ui, opts, repopath)
2909 repo = hg.peer(ui, opts, repopath)
2910 for opt in remoteopts:
2910 for opt in remoteopts:
2911 del opts[opt[1]]
2911 del opts[opt[1]]
2912 args = {}
2912 args = {}
2913 for k, v in opts.iteritems():
2913 for k, v in opts.iteritems():
2914 if v:
2914 if v:
2915 args[k] = v
2915 args[k] = v
2916 # run twice to check that we don't mess up the stream for the next command
2916 # run twice to check that we don't mess up the stream for the next command
2917 res1 = repo.debugwireargs(*vals, **args)
2917 res1 = repo.debugwireargs(*vals, **args)
2918 res2 = repo.debugwireargs(*vals, **args)
2918 res2 = repo.debugwireargs(*vals, **args)
2919 ui.write("%s\n" % res1)
2919 ui.write("%s\n" % res1)
2920 if res1 != res2:
2920 if res1 != res2:
2921 ui.warn("%s\n" % res2)
2921 ui.warn("%s\n" % res2)
2922
2922
2923 @command('^diff',
2923 @command('^diff',
2924 [('r', 'rev', [], _('revision'), _('REV')),
2924 [('r', 'rev', [], _('revision'), _('REV')),
2925 ('c', 'change', '', _('change made by revision'), _('REV'))
2925 ('c', 'change', '', _('change made by revision'), _('REV'))
2926 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2926 ] + diffopts + diffopts2 + walkopts + subrepoopts,
2927 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2927 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
2928 inferrepo=True)
2928 inferrepo=True)
2929 def diff(ui, repo, *pats, **opts):
2929 def diff(ui, repo, *pats, **opts):
2930 """diff repository (or selected files)
2930 """diff repository (or selected files)
2931
2931
2932 Show differences between revisions for the specified files.
2932 Show differences between revisions for the specified files.
2933
2933
2934 Differences between files are shown using the unified diff format.
2934 Differences between files are shown using the unified diff format.
2935
2935
2936 .. note::
2936 .. note::
2937
2937
2938 diff may generate unexpected results for merges, as it will
2938 diff may generate unexpected results for merges, as it will
2939 default to comparing against the working directory's first
2939 default to comparing against the working directory's first
2940 parent changeset if no revisions are specified.
2940 parent changeset if no revisions are specified.
2941
2941
2942 When two revision arguments are given, then changes are shown
2942 When two revision arguments are given, then changes are shown
2943 between those revisions. If only one revision is specified then
2943 between those revisions. If only one revision is specified then
2944 that revision is compared to the working directory, and, when no
2944 that revision is compared to the working directory, and, when no
2945 revisions are specified, the working directory files are compared
2945 revisions are specified, the working directory files are compared
2946 to its parent.
2946 to its parent.
2947
2947
2948 Alternatively you can specify -c/--change with a revision to see
2948 Alternatively you can specify -c/--change with a revision to see
2949 the changes in that changeset relative to its first parent.
2949 the changes in that changeset relative to its first parent.
2950
2950
2951 Without the -a/--text option, diff will avoid generating diffs of
2951 Without the -a/--text option, diff will avoid generating diffs of
2952 files it detects as binary. With -a, diff will generate a diff
2952 files it detects as binary. With -a, diff will generate a diff
2953 anyway, probably with undesirable results.
2953 anyway, probably with undesirable results.
2954
2954
2955 Use the -g/--git option to generate diffs in the git extended diff
2955 Use the -g/--git option to generate diffs in the git extended diff
2956 format. For more information, read :hg:`help diffs`.
2956 format. For more information, read :hg:`help diffs`.
2957
2957
2958 .. container:: verbose
2958 .. container:: verbose
2959
2959
2960 Examples:
2960 Examples:
2961
2961
2962 - compare a file in the current working directory to its parent::
2962 - compare a file in the current working directory to its parent::
2963
2963
2964 hg diff foo.c
2964 hg diff foo.c
2965
2965
2966 - compare two historical versions of a directory, with rename info::
2966 - compare two historical versions of a directory, with rename info::
2967
2967
2968 hg diff --git -r 1.0:1.2 lib/
2968 hg diff --git -r 1.0:1.2 lib/
2969
2969
2970 - get change stats relative to the last change on some date::
2970 - get change stats relative to the last change on some date::
2971
2971
2972 hg diff --stat -r "date('may 2')"
2972 hg diff --stat -r "date('may 2')"
2973
2973
2974 - diff all newly-added files that contain a keyword::
2974 - diff all newly-added files that contain a keyword::
2975
2975
2976 hg diff "set:added() and grep(GNU)"
2976 hg diff "set:added() and grep(GNU)"
2977
2977
2978 - compare a revision and its parents::
2978 - compare a revision and its parents::
2979
2979
2980 hg diff -c 9353 # compare against first parent
2980 hg diff -c 9353 # compare against first parent
2981 hg diff -r 9353^:9353 # same using revset syntax
2981 hg diff -r 9353^:9353 # same using revset syntax
2982 hg diff -r 9353^2:9353 # compare against the second parent
2982 hg diff -r 9353^2:9353 # compare against the second parent
2983
2983
2984 Returns 0 on success.
2984 Returns 0 on success.
2985 """
2985 """
2986
2986
2987 revs = opts.get('rev')
2987 revs = opts.get('rev')
2988 change = opts.get('change')
2988 change = opts.get('change')
2989 stat = opts.get('stat')
2989 stat = opts.get('stat')
2990 reverse = opts.get('reverse')
2990 reverse = opts.get('reverse')
2991
2991
2992 if revs and change:
2992 if revs and change:
2993 msg = _('cannot specify --rev and --change at the same time')
2993 msg = _('cannot specify --rev and --change at the same time')
2994 raise util.Abort(msg)
2994 raise util.Abort(msg)
2995 elif change:
2995 elif change:
2996 node2 = scmutil.revsingle(repo, change, None).node()
2996 node2 = scmutil.revsingle(repo, change, None).node()
2997 node1 = repo[node2].p1().node()
2997 node1 = repo[node2].p1().node()
2998 else:
2998 else:
2999 node1, node2 = scmutil.revpair(repo, revs)
2999 node1, node2 = scmutil.revpair(repo, revs)
3000
3000
3001 if reverse:
3001 if reverse:
3002 node1, node2 = node2, node1
3002 node1, node2 = node2, node1
3003
3003
3004 diffopts = patch.diffopts(ui, opts)
3004 diffopts = patch.diffopts(ui, opts)
3005 m = scmutil.match(repo[node2], pats, opts)
3005 m = scmutil.match(repo[node2], pats, opts)
3006 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3006 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3007 listsubrepos=opts.get('subrepos'))
3007 listsubrepos=opts.get('subrepos'))
3008
3008
3009 @command('^export',
3009 @command('^export',
3010 [('o', 'output', '',
3010 [('o', 'output', '',
3011 _('print output to file with formatted name'), _('FORMAT')),
3011 _('print output to file with formatted name'), _('FORMAT')),
3012 ('', 'switch-parent', None, _('diff against the second parent')),
3012 ('', 'switch-parent', None, _('diff against the second parent')),
3013 ('r', 'rev', [], _('revisions to export'), _('REV')),
3013 ('r', 'rev', [], _('revisions to export'), _('REV')),
3014 ] + diffopts,
3014 ] + diffopts,
3015 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3015 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3016 def export(ui, repo, *changesets, **opts):
3016 def export(ui, repo, *changesets, **opts):
3017 """dump the header and diffs for one or more changesets
3017 """dump the header and diffs for one or more changesets
3018
3018
3019 Print the changeset header and diffs for one or more revisions.
3019 Print the changeset header and diffs for one or more revisions.
3020 If no revision is given, the parent of the working directory is used.
3020 If no revision is given, the parent of the working directory is used.
3021
3021
3022 The information shown in the changeset header is: author, date,
3022 The information shown in the changeset header is: author, date,
3023 branch name (if non-default), changeset hash, parent(s) and commit
3023 branch name (if non-default), changeset hash, parent(s) and commit
3024 comment.
3024 comment.
3025
3025
3026 .. note::
3026 .. note::
3027
3027
3028 export may generate unexpected diff output for merge
3028 export may generate unexpected diff output for merge
3029 changesets, as it will compare the merge changeset against its
3029 changesets, as it will compare the merge changeset against its
3030 first parent only.
3030 first parent only.
3031
3031
3032 Output may be to a file, in which case the name of the file is
3032 Output may be to a file, in which case the name of the file is
3033 given using a format string. The formatting rules are as follows:
3033 given using a format string. The formatting rules are as follows:
3034
3034
3035 :``%%``: literal "%" character
3035 :``%%``: literal "%" character
3036 :``%H``: changeset hash (40 hexadecimal digits)
3036 :``%H``: changeset hash (40 hexadecimal digits)
3037 :``%N``: number of patches being generated
3037 :``%N``: number of patches being generated
3038 :``%R``: changeset revision number
3038 :``%R``: changeset revision number
3039 :``%b``: basename of the exporting repository
3039 :``%b``: basename of the exporting repository
3040 :``%h``: short-form changeset hash (12 hexadecimal digits)
3040 :``%h``: short-form changeset hash (12 hexadecimal digits)
3041 :``%m``: first line of the commit message (only alphanumeric characters)
3041 :``%m``: first line of the commit message (only alphanumeric characters)
3042 :``%n``: zero-padded sequence number, starting at 1
3042 :``%n``: zero-padded sequence number, starting at 1
3043 :``%r``: zero-padded changeset revision number
3043 :``%r``: zero-padded changeset revision number
3044
3044
3045 Without the -a/--text option, export will avoid generating diffs
3045 Without the -a/--text option, export will avoid generating diffs
3046 of files it detects as binary. With -a, export will generate a
3046 of files it detects as binary. With -a, export will generate a
3047 diff anyway, probably with undesirable results.
3047 diff anyway, probably with undesirable results.
3048
3048
3049 Use the -g/--git option to generate diffs in the git extended diff
3049 Use the -g/--git option to generate diffs in the git extended diff
3050 format. See :hg:`help diffs` for more information.
3050 format. See :hg:`help diffs` for more information.
3051
3051
3052 With the --switch-parent option, the diff will be against the
3052 With the --switch-parent option, the diff will be against the
3053 second parent. It can be useful to review a merge.
3053 second parent. It can be useful to review a merge.
3054
3054
3055 .. container:: verbose
3055 .. container:: verbose
3056
3056
3057 Examples:
3057 Examples:
3058
3058
3059 - use export and import to transplant a bugfix to the current
3059 - use export and import to transplant a bugfix to the current
3060 branch::
3060 branch::
3061
3061
3062 hg export -r 9353 | hg import -
3062 hg export -r 9353 | hg import -
3063
3063
3064 - export all the changesets between two revisions to a file with
3064 - export all the changesets between two revisions to a file with
3065 rename information::
3065 rename information::
3066
3066
3067 hg export --git -r 123:150 > changes.txt
3067 hg export --git -r 123:150 > changes.txt
3068
3068
3069 - split outgoing changes into a series of patches with
3069 - split outgoing changes into a series of patches with
3070 descriptive names::
3070 descriptive names::
3071
3071
3072 hg export -r "outgoing()" -o "%n-%m.patch"
3072 hg export -r "outgoing()" -o "%n-%m.patch"
3073
3073
3074 Returns 0 on success.
3074 Returns 0 on success.
3075 """
3075 """
3076 changesets += tuple(opts.get('rev', []))
3076 changesets += tuple(opts.get('rev', []))
3077 if not changesets:
3077 if not changesets:
3078 changesets = ['.']
3078 changesets = ['.']
3079 revs = scmutil.revrange(repo, changesets)
3079 revs = scmutil.revrange(repo, changesets)
3080 if not revs:
3080 if not revs:
3081 raise util.Abort(_("export requires at least one changeset"))
3081 raise util.Abort(_("export requires at least one changeset"))
3082 if len(revs) > 1:
3082 if len(revs) > 1:
3083 ui.note(_('exporting patches:\n'))
3083 ui.note(_('exporting patches:\n'))
3084 else:
3084 else:
3085 ui.note(_('exporting patch:\n'))
3085 ui.note(_('exporting patch:\n'))
3086 cmdutil.export(repo, revs, template=opts.get('output'),
3086 cmdutil.export(repo, revs, template=opts.get('output'),
3087 switch_parent=opts.get('switch_parent'),
3087 switch_parent=opts.get('switch_parent'),
3088 opts=patch.diffopts(ui, opts))
3088 opts=patch.diffopts(ui, opts))
3089
3089
3090 @command('files',
3090 @command('files',
3091 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3091 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3092 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3092 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3093 ] + walkopts + formatteropts,
3093 ] + walkopts + formatteropts,
3094 _('[OPTION]... [PATTERN]...'))
3094 _('[OPTION]... [PATTERN]...'))
3095 def files(ui, repo, *pats, **opts):
3095 def files(ui, repo, *pats, **opts):
3096 """list tracked files
3096 """list tracked files
3097
3097
3098 Print files under Mercurial control in the working directory or
3098 Print files under Mercurial control in the working directory or
3099 specified revision whose names match the given patterns (excluding
3099 specified revision whose names match the given patterns (excluding
3100 removed files).
3100 removed files).
3101
3101
3102 If no patterns are given to match, this command prints the names
3102 If no patterns are given to match, this command prints the names
3103 of all files under Mercurial control in the working copy.
3103 of all files under Mercurial control in the working copy.
3104
3104
3105 .. container:: verbose
3105 .. container:: verbose
3106
3106
3107 Examples:
3107 Examples:
3108
3108
3109 - list all files under the current directory::
3109 - list all files under the current directory::
3110
3110
3111 hg files .
3111 hg files .
3112
3112
3113 - shows sizes and flags for current revision::
3113 - shows sizes and flags for current revision::
3114
3114
3115 hg files -vr .
3115 hg files -vr .
3116
3116
3117 - list all files named README::
3117 - list all files named README::
3118
3118
3119 hg files -I "**/README"
3119 hg files -I "**/README"
3120
3120
3121 - list all binary files::
3121 - list all binary files::
3122
3122
3123 hg files "set:binary()"
3123 hg files "set:binary()"
3124
3124
3125 - find files containing a regular expression:
3125 - find files containing a regular expression:
3126
3126
3127 hg files "set:grep('bob')"
3127 hg files "set:grep('bob')"
3128
3128
3129 - search tracked file contents with xargs and grep::
3129 - search tracked file contents with xargs and grep::
3130
3130
3131 hg files -0 | xargs -0 grep foo
3131 hg files -0 | xargs -0 grep foo
3132
3132
3133 See :hg:'help pattern' and :hg:'help revsets' for more information
3133 See :hg:'help pattern' and :hg:'help revsets' for more information
3134 on specifying file patterns.
3134 on specifying file patterns.
3135
3135
3136 Returns 0 if a match is found, 1 otherwise.
3136 Returns 0 if a match is found, 1 otherwise.
3137
3137
3138 """
3138 """
3139 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3139 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3140 rev = ctx.rev()
3140 rev = ctx.rev()
3141 ret = 1
3141 ret = 1
3142
3142
3143 end = '\n'
3143 end = '\n'
3144 if opts.get('print0'):
3144 if opts.get('print0'):
3145 end = '\0'
3145 end = '\0'
3146 fm = ui.formatter('files', opts)
3146 fm = ui.formatter('files', opts)
3147 fmt = '%s' + end
3147 fmt = '%s' + end
3148
3148
3149 m = scmutil.match(ctx, pats, opts)
3149 m = scmutil.match(ctx, pats, opts)
3150 for f in ctx.walk(m):
3150 for f in ctx.walk(m):
3151 if rev is None and repo.dirstate[f] in 'R?!':
3151 if rev is None and repo.dirstate[f] in 'R?!':
3152 continue
3152 continue
3153 fm.startitem()
3153 fm.startitem()
3154 if ui.verbose:
3154 if ui.verbose:
3155 fc = ctx[f]
3155 fc = ctx[f]
3156 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3156 fm.write('size flags', '% 10d % 1s ', fc.size(), fc.flags())
3157 fm.data(abspath=f)
3157 fm.data(abspath=f)
3158 fm.write('path', fmt, m.rel(f))
3158 fm.write('path', fmt, m.rel(f))
3159 ret = 0
3159 ret = 0
3160
3160
3161 fm.end()
3161 fm.end()
3162
3162
3163 return ret
3163 return ret
3164
3164
3165 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3165 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3166 def forget(ui, repo, *pats, **opts):
3166 def forget(ui, repo, *pats, **opts):
3167 """forget the specified files on the next commit
3167 """forget the specified files on the next commit
3168
3168
3169 Mark the specified files so they will no longer be tracked
3169 Mark the specified files so they will no longer be tracked
3170 after the next commit.
3170 after the next commit.
3171
3171
3172 This only removes files from the current branch, not from the
3172 This only removes files from the current branch, not from the
3173 entire project history, and it does not delete them from the
3173 entire project history, and it does not delete them from the
3174 working directory.
3174 working directory.
3175
3175
3176 To undo a forget before the next commit, see :hg:`add`.
3176 To undo a forget before the next commit, see :hg:`add`.
3177
3177
3178 .. container:: verbose
3178 .. container:: verbose
3179
3179
3180 Examples:
3180 Examples:
3181
3181
3182 - forget newly-added binary files::
3182 - forget newly-added binary files::
3183
3183
3184 hg forget "set:added() and binary()"
3184 hg forget "set:added() and binary()"
3185
3185
3186 - forget files that would be excluded by .hgignore::
3186 - forget files that would be excluded by .hgignore::
3187
3187
3188 hg forget "set:hgignore()"
3188 hg forget "set:hgignore()"
3189
3189
3190 Returns 0 on success.
3190 Returns 0 on success.
3191 """
3191 """
3192
3192
3193 if not pats:
3193 if not pats:
3194 raise util.Abort(_('no files specified'))
3194 raise util.Abort(_('no files specified'))
3195
3195
3196 m = scmutil.match(repo[None], pats, opts)
3196 m = scmutil.match(repo[None], pats, opts)
3197 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3197 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3198 return rejected and 1 or 0
3198 return rejected and 1 or 0
3199
3199
3200 @command(
3200 @command(
3201 'graft',
3201 'graft',
3202 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3202 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3203 ('c', 'continue', False, _('resume interrupted graft')),
3203 ('c', 'continue', False, _('resume interrupted graft')),
3204 ('e', 'edit', False, _('invoke editor on commit messages')),
3204 ('e', 'edit', False, _('invoke editor on commit messages')),
3205 ('', 'log', None, _('append graft info to log message')),
3205 ('', 'log', None, _('append graft info to log message')),
3206 ('f', 'force', False, _('force graft')),
3206 ('f', 'force', False, _('force graft')),
3207 ('D', 'currentdate', False,
3207 ('D', 'currentdate', False,
3208 _('record the current date as commit date')),
3208 _('record the current date as commit date')),
3209 ('U', 'currentuser', False,
3209 ('U', 'currentuser', False,
3210 _('record the current user as committer'), _('DATE'))]
3210 _('record the current user as committer'), _('DATE'))]
3211 + commitopts2 + mergetoolopts + dryrunopts,
3211 + commitopts2 + mergetoolopts + dryrunopts,
3212 _('[OPTION]... [-r] REV...'))
3212 _('[OPTION]... [-r] REV...'))
3213 def graft(ui, repo, *revs, **opts):
3213 def graft(ui, repo, *revs, **opts):
3214 '''copy changes from other branches onto the current branch
3214 '''copy changes from other branches onto the current branch
3215
3215
3216 This command uses Mercurial's merge logic to copy individual
3216 This command uses Mercurial's merge logic to copy individual
3217 changes from other branches without merging branches in the
3217 changes from other branches without merging branches in the
3218 history graph. This is sometimes known as 'backporting' or
3218 history graph. This is sometimes known as 'backporting' or
3219 'cherry-picking'. By default, graft will copy user, date, and
3219 'cherry-picking'. By default, graft will copy user, date, and
3220 description from the source changesets.
3220 description from the source changesets.
3221
3221
3222 Changesets that are ancestors of the current revision, that have
3222 Changesets that are ancestors of the current revision, that have
3223 already been grafted, or that are merges will be skipped.
3223 already been grafted, or that are merges will be skipped.
3224
3224
3225 If --log is specified, log messages will have a comment appended
3225 If --log is specified, log messages will have a comment appended
3226 of the form::
3226 of the form::
3227
3227
3228 (grafted from CHANGESETHASH)
3228 (grafted from CHANGESETHASH)
3229
3229
3230 If --force is specified, revisions will be grafted even if they
3230 If --force is specified, revisions will be grafted even if they
3231 are already ancestors of or have been grafted to the destination.
3231 are already ancestors of or have been grafted to the destination.
3232 This is useful when the revisions have since been backed out.
3232 This is useful when the revisions have since been backed out.
3233
3233
3234 If a graft merge results in conflicts, the graft process is
3234 If a graft merge results in conflicts, the graft process is
3235 interrupted so that the current merge can be manually resolved.
3235 interrupted so that the current merge can be manually resolved.
3236 Once all conflicts are addressed, the graft process can be
3236 Once all conflicts are addressed, the graft process can be
3237 continued with the -c/--continue option.
3237 continued with the -c/--continue option.
3238
3238
3239 .. note::
3239 .. note::
3240
3240
3241 The -c/--continue option does not reapply earlier options, except
3241 The -c/--continue option does not reapply earlier options, except
3242 for --force.
3242 for --force.
3243
3243
3244 .. container:: verbose
3244 .. container:: verbose
3245
3245
3246 Examples:
3246 Examples:
3247
3247
3248 - copy a single change to the stable branch and edit its description::
3248 - copy a single change to the stable branch and edit its description::
3249
3249
3250 hg update stable
3250 hg update stable
3251 hg graft --edit 9393
3251 hg graft --edit 9393
3252
3252
3253 - graft a range of changesets with one exception, updating dates::
3253 - graft a range of changesets with one exception, updating dates::
3254
3254
3255 hg graft -D "2085::2093 and not 2091"
3255 hg graft -D "2085::2093 and not 2091"
3256
3256
3257 - continue a graft after resolving conflicts::
3257 - continue a graft after resolving conflicts::
3258
3258
3259 hg graft -c
3259 hg graft -c
3260
3260
3261 - show the source of a grafted changeset::
3261 - show the source of a grafted changeset::
3262
3262
3263 hg log --debug -r .
3263 hg log --debug -r .
3264
3264
3265 See :hg:`help revisions` and :hg:`help revsets` for more about
3265 See :hg:`help revisions` and :hg:`help revsets` for more about
3266 specifying revisions.
3266 specifying revisions.
3267
3267
3268 Returns 0 on successful completion.
3268 Returns 0 on successful completion.
3269 '''
3269 '''
3270
3270
3271 revs = list(revs)
3271 revs = list(revs)
3272 revs.extend(opts['rev'])
3272 revs.extend(opts['rev'])
3273
3273
3274 if not opts.get('user') and opts.get('currentuser'):
3274 if not opts.get('user') and opts.get('currentuser'):
3275 opts['user'] = ui.username()
3275 opts['user'] = ui.username()
3276 if not opts.get('date') and opts.get('currentdate'):
3276 if not opts.get('date') and opts.get('currentdate'):
3277 opts['date'] = "%d %d" % util.makedate()
3277 opts['date'] = "%d %d" % util.makedate()
3278
3278
3279 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3279 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3280
3280
3281 cont = False
3281 cont = False
3282 if opts['continue']:
3282 if opts['continue']:
3283 cont = True
3283 cont = True
3284 if revs:
3284 if revs:
3285 raise util.Abort(_("can't specify --continue and revisions"))
3285 raise util.Abort(_("can't specify --continue and revisions"))
3286 # read in unfinished revisions
3286 # read in unfinished revisions
3287 try:
3287 try:
3288 nodes = repo.opener.read('graftstate').splitlines()
3288 nodes = repo.opener.read('graftstate').splitlines()
3289 revs = [repo[node].rev() for node in nodes]
3289 revs = [repo[node].rev() for node in nodes]
3290 except IOError, inst:
3290 except IOError, inst:
3291 if inst.errno != errno.ENOENT:
3291 if inst.errno != errno.ENOENT:
3292 raise
3292 raise
3293 raise util.Abort(_("no graft state found, can't continue"))
3293 raise util.Abort(_("no graft state found, can't continue"))
3294 else:
3294 else:
3295 cmdutil.checkunfinished(repo)
3295 cmdutil.checkunfinished(repo)
3296 cmdutil.bailifchanged(repo)
3296 cmdutil.bailifchanged(repo)
3297 if not revs:
3297 if not revs:
3298 raise util.Abort(_('no revisions specified'))
3298 raise util.Abort(_('no revisions specified'))
3299 revs = scmutil.revrange(repo, revs)
3299 revs = scmutil.revrange(repo, revs)
3300
3300
3301 # check for merges
3301 # check for merges
3302 for rev in repo.revs('%ld and merge()', revs):
3302 for rev in repo.revs('%ld and merge()', revs):
3303 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3303 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3304 revs.remove(rev)
3304 revs.remove(rev)
3305 if not revs:
3305 if not revs:
3306 return -1
3306 return -1
3307
3307
3308 # Don't check in the --continue case, in effect retaining --force across
3308 # Don't check in the --continue case, in effect retaining --force across
3309 # --continues. That's because without --force, any revisions we decided to
3309 # --continues. That's because without --force, any revisions we decided to
3310 # skip would have been filtered out here, so they wouldn't have made their
3310 # skip would have been filtered out here, so they wouldn't have made their
3311 # way to the graftstate. With --force, any revisions we would have otherwise
3311 # way to the graftstate. With --force, any revisions we would have otherwise
3312 # skipped would not have been filtered out, and if they hadn't been applied
3312 # skipped would not have been filtered out, and if they hadn't been applied
3313 # already, they'd have been in the graftstate.
3313 # already, they'd have been in the graftstate.
3314 if not (cont or opts.get('force')):
3314 if not (cont or opts.get('force')):
3315 # check for ancestors of dest branch
3315 # check for ancestors of dest branch
3316 crev = repo['.'].rev()
3316 crev = repo['.'].rev()
3317 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3317 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3318 # Cannot use x.remove(y) on smart set, this has to be a list.
3318 # Cannot use x.remove(y) on smart set, this has to be a list.
3319 # XXX make this lazy in the future
3319 # XXX make this lazy in the future
3320 revs = list(revs)
3320 revs = list(revs)
3321 # don't mutate while iterating, create a copy
3321 # don't mutate while iterating, create a copy
3322 for rev in list(revs):
3322 for rev in list(revs):
3323 if rev in ancestors:
3323 if rev in ancestors:
3324 ui.warn(_('skipping ancestor revision %s\n') % rev)
3324 ui.warn(_('skipping ancestor revision %s\n') % rev)
3325 # XXX remove on list is slow
3325 # XXX remove on list is slow
3326 revs.remove(rev)
3326 revs.remove(rev)
3327 if not revs:
3327 if not revs:
3328 return -1
3328 return -1
3329
3329
3330 # analyze revs for earlier grafts
3330 # analyze revs for earlier grafts
3331 ids = {}
3331 ids = {}
3332 for ctx in repo.set("%ld", revs):
3332 for ctx in repo.set("%ld", revs):
3333 ids[ctx.hex()] = ctx.rev()
3333 ids[ctx.hex()] = ctx.rev()
3334 n = ctx.extra().get('source')
3334 n = ctx.extra().get('source')
3335 if n:
3335 if n:
3336 ids[n] = ctx.rev()
3336 ids[n] = ctx.rev()
3337
3337
3338 # check ancestors for earlier grafts
3338 # check ancestors for earlier grafts
3339 ui.debug('scanning for duplicate grafts\n')
3339 ui.debug('scanning for duplicate grafts\n')
3340
3340
3341 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3341 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3342 ctx = repo[rev]
3342 ctx = repo[rev]
3343 n = ctx.extra().get('source')
3343 n = ctx.extra().get('source')
3344 if n in ids:
3344 if n in ids:
3345 try:
3345 try:
3346 r = repo[n].rev()
3346 r = repo[n].rev()
3347 except error.RepoLookupError:
3347 except error.RepoLookupError:
3348 r = None
3348 r = None
3349 if r in revs:
3349 if r in revs:
3350 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3350 ui.warn(_('skipping revision %s (already grafted to %s)\n')
3351 % (r, rev))
3351 % (r, rev))
3352 revs.remove(r)
3352 revs.remove(r)
3353 elif ids[n] in revs:
3353 elif ids[n] in revs:
3354 if r is None:
3354 if r is None:
3355 ui.warn(_('skipping already grafted revision %s '
3355 ui.warn(_('skipping already grafted revision %s '
3356 '(%s also has unknown origin %s)\n')
3356 '(%s also has unknown origin %s)\n')
3357 % (ids[n], rev, n))
3357 % (ids[n], rev, n))
3358 else:
3358 else:
3359 ui.warn(_('skipping already grafted revision %s '
3359 ui.warn(_('skipping already grafted revision %s '
3360 '(%s also has origin %d)\n')
3360 '(%s also has origin %d)\n')
3361 % (ids[n], rev, r))
3361 % (ids[n], rev, r))
3362 revs.remove(ids[n])
3362 revs.remove(ids[n])
3363 elif ctx.hex() in ids:
3363 elif ctx.hex() in ids:
3364 r = ids[ctx.hex()]
3364 r = ids[ctx.hex()]
3365 ui.warn(_('skipping already grafted revision %s '
3365 ui.warn(_('skipping already grafted revision %s '
3366 '(was grafted from %d)\n') % (r, rev))
3366 '(was grafted from %d)\n') % (r, rev))
3367 revs.remove(r)
3367 revs.remove(r)
3368 if not revs:
3368 if not revs:
3369 return -1
3369 return -1
3370
3370
3371 wlock = repo.wlock()
3371 wlock = repo.wlock()
3372 try:
3372 try:
3373 current = repo['.']
3373 current = repo['.']
3374 for pos, ctx in enumerate(repo.set("%ld", revs)):
3374 for pos, ctx in enumerate(repo.set("%ld", revs)):
3375
3375
3376 ui.status(_('grafting revision %s\n') % ctx.rev())
3376 ui.status(_('grafting revision %s\n') % ctx.rev())
3377 if opts.get('dry_run'):
3377 if opts.get('dry_run'):
3378 continue
3378 continue
3379
3379
3380 source = ctx.extra().get('source')
3380 source = ctx.extra().get('source')
3381 if not source:
3381 if not source:
3382 source = ctx.hex()
3382 source = ctx.hex()
3383 extra = {'source': source}
3383 extra = {'source': source}
3384 user = ctx.user()
3384 user = ctx.user()
3385 if opts.get('user'):
3385 if opts.get('user'):
3386 user = opts['user']
3386 user = opts['user']
3387 date = ctx.date()
3387 date = ctx.date()
3388 if opts.get('date'):
3388 if opts.get('date'):
3389 date = opts['date']
3389 date = opts['date']
3390 message = ctx.description()
3390 message = ctx.description()
3391 if opts.get('log'):
3391 if opts.get('log'):
3392 message += '\n(grafted from %s)' % ctx.hex()
3392 message += '\n(grafted from %s)' % ctx.hex()
3393
3393
3394 # we don't merge the first commit when continuing
3394 # we don't merge the first commit when continuing
3395 if not cont:
3395 if not cont:
3396 # perform the graft merge with p1(rev) as 'ancestor'
3396 # perform the graft merge with p1(rev) as 'ancestor'
3397 try:
3397 try:
3398 # ui.forcemerge is an internal variable, do not document
3398 # ui.forcemerge is an internal variable, do not document
3399 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3399 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3400 'graft')
3400 'graft')
3401 stats = mergemod.update(repo, ctx.node(), True, True, False,
3401 stats = mergemod.update(repo, ctx.node(), True, True, False,
3402 ctx.p1().node(),
3402 ctx.p1().node(),
3403 labels=['local', 'graft'])
3403 labels=['local', 'graft'])
3404 finally:
3404 finally:
3405 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3405 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3406 # report any conflicts
3406 # report any conflicts
3407 if stats and stats[3] > 0:
3407 if stats and stats[3] > 0:
3408 # write out state for --continue
3408 # write out state for --continue
3409 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3409 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3410 repo.opener.write('graftstate', ''.join(nodelines))
3410 repo.opener.write('graftstate', ''.join(nodelines))
3411 raise util.Abort(
3411 raise util.Abort(
3412 _("unresolved conflicts, can't continue"),
3412 _("unresolved conflicts, can't continue"),
3413 hint=_('use hg resolve and hg graft --continue'))
3413 hint=_('use hg resolve and hg graft --continue'))
3414 else:
3414 else:
3415 cont = False
3415 cont = False
3416
3416
3417 # drop the second merge parent
3417 # drop the second merge parent
3418 repo.dirstate.beginparentchange()
3418 repo.dirstate.beginparentchange()
3419 repo.setparents(current.node(), nullid)
3419 repo.setparents(current.node(), nullid)
3420 repo.dirstate.write()
3420 repo.dirstate.write()
3421 # fix up dirstate for copies and renames
3421 # fix up dirstate for copies and renames
3422 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3422 cmdutil.duplicatecopies(repo, ctx.rev(), ctx.p1().rev())
3423 repo.dirstate.endparentchange()
3423 repo.dirstate.endparentchange()
3424
3424
3425 # commit
3425 # commit
3426 node = repo.commit(text=message, user=user,
3426 node = repo.commit(text=message, user=user,
3427 date=date, extra=extra, editor=editor)
3427 date=date, extra=extra, editor=editor)
3428 if node is None:
3428 if node is None:
3429 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3429 ui.status(_('graft for revision %s is empty\n') % ctx.rev())
3430 else:
3430 else:
3431 current = repo[node]
3431 current = repo[node]
3432 finally:
3432 finally:
3433 wlock.release()
3433 wlock.release()
3434
3434
3435 # remove state when we complete successfully
3435 # remove state when we complete successfully
3436 if not opts.get('dry_run'):
3436 if not opts.get('dry_run'):
3437 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3437 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3438
3438
3439 return 0
3439 return 0
3440
3440
3441 @command('grep',
3441 @command('grep',
3442 [('0', 'print0', None, _('end fields with NUL')),
3442 [('0', 'print0', None, _('end fields with NUL')),
3443 ('', 'all', None, _('print all revisions that match')),
3443 ('', 'all', None, _('print all revisions that match')),
3444 ('a', 'text', None, _('treat all files as text')),
3444 ('a', 'text', None, _('treat all files as text')),
3445 ('f', 'follow', None,
3445 ('f', 'follow', None,
3446 _('follow changeset history,'
3446 _('follow changeset history,'
3447 ' or file history across copies and renames')),
3447 ' or file history across copies and renames')),
3448 ('i', 'ignore-case', None, _('ignore case when matching')),
3448 ('i', 'ignore-case', None, _('ignore case when matching')),
3449 ('l', 'files-with-matches', None,
3449 ('l', 'files-with-matches', None,
3450 _('print only filenames and revisions that match')),
3450 _('print only filenames and revisions that match')),
3451 ('n', 'line-number', None, _('print matching line numbers')),
3451 ('n', 'line-number', None, _('print matching line numbers')),
3452 ('r', 'rev', [],
3452 ('r', 'rev', [],
3453 _('only search files changed within revision range'), _('REV')),
3453 _('only search files changed within revision range'), _('REV')),
3454 ('u', 'user', None, _('list the author (long with -v)')),
3454 ('u', 'user', None, _('list the author (long with -v)')),
3455 ('d', 'date', None, _('list the date (short with -q)')),
3455 ('d', 'date', None, _('list the date (short with -q)')),
3456 ] + walkopts,
3456 ] + walkopts,
3457 _('[OPTION]... PATTERN [FILE]...'),
3457 _('[OPTION]... PATTERN [FILE]...'),
3458 inferrepo=True)
3458 inferrepo=True)
3459 def grep(ui, repo, pattern, *pats, **opts):
3459 def grep(ui, repo, pattern, *pats, **opts):
3460 """search for a pattern in specified files and revisions
3460 """search for a pattern in specified files and revisions
3461
3461
3462 Search revisions of files for a regular expression.
3462 Search revisions of files for a regular expression.
3463
3463
3464 This command behaves differently than Unix grep. It only accepts
3464 This command behaves differently than Unix grep. It only accepts
3465 Python/Perl regexps. It searches repository history, not the
3465 Python/Perl regexps. It searches repository history, not the
3466 working directory. It always prints the revision number in which a
3466 working directory. It always prints the revision number in which a
3467 match appears.
3467 match appears.
3468
3468
3469 By default, grep only prints output for the first revision of a
3469 By default, grep only prints output for the first revision of a
3470 file in which it finds a match. To get it to print every revision
3470 file in which it finds a match. To get it to print every revision
3471 that contains a change in match status ("-" for a match that
3471 that contains a change in match status ("-" for a match that
3472 becomes a non-match, or "+" for a non-match that becomes a match),
3472 becomes a non-match, or "+" for a non-match that becomes a match),
3473 use the --all flag.
3473 use the --all flag.
3474
3474
3475 Returns 0 if a match is found, 1 otherwise.
3475 Returns 0 if a match is found, 1 otherwise.
3476 """
3476 """
3477 reflags = re.M
3477 reflags = re.M
3478 if opts.get('ignore_case'):
3478 if opts.get('ignore_case'):
3479 reflags |= re.I
3479 reflags |= re.I
3480 try:
3480 try:
3481 regexp = util.re.compile(pattern, reflags)
3481 regexp = util.re.compile(pattern, reflags)
3482 except re.error, inst:
3482 except re.error, inst:
3483 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3483 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3484 return 1
3484 return 1
3485 sep, eol = ':', '\n'
3485 sep, eol = ':', '\n'
3486 if opts.get('print0'):
3486 if opts.get('print0'):
3487 sep = eol = '\0'
3487 sep = eol = '\0'
3488
3488
3489 getfile = util.lrucachefunc(repo.file)
3489 getfile = util.lrucachefunc(repo.file)
3490
3490
3491 def matchlines(body):
3491 def matchlines(body):
3492 begin = 0
3492 begin = 0
3493 linenum = 0
3493 linenum = 0
3494 while begin < len(body):
3494 while begin < len(body):
3495 match = regexp.search(body, begin)
3495 match = regexp.search(body, begin)
3496 if not match:
3496 if not match:
3497 break
3497 break
3498 mstart, mend = match.span()
3498 mstart, mend = match.span()
3499 linenum += body.count('\n', begin, mstart) + 1
3499 linenum += body.count('\n', begin, mstart) + 1
3500 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3500 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3501 begin = body.find('\n', mend) + 1 or len(body) + 1
3501 begin = body.find('\n', mend) + 1 or len(body) + 1
3502 lend = begin - 1
3502 lend = begin - 1
3503 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3503 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3504
3504
3505 class linestate(object):
3505 class linestate(object):
3506 def __init__(self, line, linenum, colstart, colend):
3506 def __init__(self, line, linenum, colstart, colend):
3507 self.line = line
3507 self.line = line
3508 self.linenum = linenum
3508 self.linenum = linenum
3509 self.colstart = colstart
3509 self.colstart = colstart
3510 self.colend = colend
3510 self.colend = colend
3511
3511
3512 def __hash__(self):
3512 def __hash__(self):
3513 return hash((self.linenum, self.line))
3513 return hash((self.linenum, self.line))
3514
3514
3515 def __eq__(self, other):
3515 def __eq__(self, other):
3516 return self.line == other.line
3516 return self.line == other.line
3517
3517
3518 def __iter__(self):
3518 def __iter__(self):
3519 yield (self.line[:self.colstart], '')
3519 yield (self.line[:self.colstart], '')
3520 yield (self.line[self.colstart:self.colend], 'grep.match')
3520 yield (self.line[self.colstart:self.colend], 'grep.match')
3521 rest = self.line[self.colend:]
3521 rest = self.line[self.colend:]
3522 while rest != '':
3522 while rest != '':
3523 match = regexp.search(rest)
3523 match = regexp.search(rest)
3524 if not match:
3524 if not match:
3525 yield (rest, '')
3525 yield (rest, '')
3526 break
3526 break
3527 mstart, mend = match.span()
3527 mstart, mend = match.span()
3528 yield (rest[:mstart], '')
3528 yield (rest[:mstart], '')
3529 yield (rest[mstart:mend], 'grep.match')
3529 yield (rest[mstart:mend], 'grep.match')
3530 rest = rest[mend:]
3530 rest = rest[mend:]
3531
3531
3532 matches = {}
3532 matches = {}
3533 copies = {}
3533 copies = {}
3534 def grepbody(fn, rev, body):
3534 def grepbody(fn, rev, body):
3535 matches[rev].setdefault(fn, [])
3535 matches[rev].setdefault(fn, [])
3536 m = matches[rev][fn]
3536 m = matches[rev][fn]
3537 for lnum, cstart, cend, line in matchlines(body):
3537 for lnum, cstart, cend, line in matchlines(body):
3538 s = linestate(line, lnum, cstart, cend)
3538 s = linestate(line, lnum, cstart, cend)
3539 m.append(s)
3539 m.append(s)
3540
3540
3541 def difflinestates(a, b):
3541 def difflinestates(a, b):
3542 sm = difflib.SequenceMatcher(None, a, b)
3542 sm = difflib.SequenceMatcher(None, a, b)
3543 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3543 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3544 if tag == 'insert':
3544 if tag == 'insert':
3545 for i in xrange(blo, bhi):
3545 for i in xrange(blo, bhi):
3546 yield ('+', b[i])
3546 yield ('+', b[i])
3547 elif tag == 'delete':
3547 elif tag == 'delete':
3548 for i in xrange(alo, ahi):
3548 for i in xrange(alo, ahi):
3549 yield ('-', a[i])
3549 yield ('-', a[i])
3550 elif tag == 'replace':
3550 elif tag == 'replace':
3551 for i in xrange(alo, ahi):
3551 for i in xrange(alo, ahi):
3552 yield ('-', a[i])
3552 yield ('-', a[i])
3553 for i in xrange(blo, bhi):
3553 for i in xrange(blo, bhi):
3554 yield ('+', b[i])
3554 yield ('+', b[i])
3555
3555
3556 def display(fn, ctx, pstates, states):
3556 def display(fn, ctx, pstates, states):
3557 rev = ctx.rev()
3557 rev = ctx.rev()
3558 datefunc = ui.quiet and util.shortdate or util.datestr
3558 datefunc = ui.quiet and util.shortdate or util.datestr
3559 found = False
3559 found = False
3560 @util.cachefunc
3560 @util.cachefunc
3561 def binary():
3561 def binary():
3562 flog = getfile(fn)
3562 flog = getfile(fn)
3563 return util.binary(flog.read(ctx.filenode(fn)))
3563 return util.binary(flog.read(ctx.filenode(fn)))
3564
3564
3565 if opts.get('all'):
3565 if opts.get('all'):
3566 iter = difflinestates(pstates, states)
3566 iter = difflinestates(pstates, states)
3567 else:
3567 else:
3568 iter = [('', l) for l in states]
3568 iter = [('', l) for l in states]
3569 for change, l in iter:
3569 for change, l in iter:
3570 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3570 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3571
3571
3572 if opts.get('line_number'):
3572 if opts.get('line_number'):
3573 cols.append((str(l.linenum), 'grep.linenumber'))
3573 cols.append((str(l.linenum), 'grep.linenumber'))
3574 if opts.get('all'):
3574 if opts.get('all'):
3575 cols.append((change, 'grep.change'))
3575 cols.append((change, 'grep.change'))
3576 if opts.get('user'):
3576 if opts.get('user'):
3577 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3577 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3578 if opts.get('date'):
3578 if opts.get('date'):
3579 cols.append((datefunc(ctx.date()), 'grep.date'))
3579 cols.append((datefunc(ctx.date()), 'grep.date'))
3580 for col, label in cols[:-1]:
3580 for col, label in cols[:-1]:
3581 ui.write(col, label=label)
3581 ui.write(col, label=label)
3582 ui.write(sep, label='grep.sep')
3582 ui.write(sep, label='grep.sep')
3583 ui.write(cols[-1][0], label=cols[-1][1])
3583 ui.write(cols[-1][0], label=cols[-1][1])
3584 if not opts.get('files_with_matches'):
3584 if not opts.get('files_with_matches'):
3585 ui.write(sep, label='grep.sep')
3585 ui.write(sep, label='grep.sep')
3586 if not opts.get('text') and binary():
3586 if not opts.get('text') and binary():
3587 ui.write(" Binary file matches")
3587 ui.write(" Binary file matches")
3588 else:
3588 else:
3589 for s, label in l:
3589 for s, label in l:
3590 ui.write(s, label=label)
3590 ui.write(s, label=label)
3591 ui.write(eol)
3591 ui.write(eol)
3592 found = True
3592 found = True
3593 if opts.get('files_with_matches'):
3593 if opts.get('files_with_matches'):
3594 break
3594 break
3595 return found
3595 return found
3596
3596
3597 skip = {}
3597 skip = {}
3598 revfiles = {}
3598 revfiles = {}
3599 matchfn = scmutil.match(repo[None], pats, opts)
3599 matchfn = scmutil.match(repo[None], pats, opts)
3600 found = False
3600 found = False
3601 follow = opts.get('follow')
3601 follow = opts.get('follow')
3602
3602
3603 def prep(ctx, fns):
3603 def prep(ctx, fns):
3604 rev = ctx.rev()
3604 rev = ctx.rev()
3605 pctx = ctx.p1()
3605 pctx = ctx.p1()
3606 parent = pctx.rev()
3606 parent = pctx.rev()
3607 matches.setdefault(rev, {})
3607 matches.setdefault(rev, {})
3608 matches.setdefault(parent, {})
3608 matches.setdefault(parent, {})
3609 files = revfiles.setdefault(rev, [])
3609 files = revfiles.setdefault(rev, [])
3610 for fn in fns:
3610 for fn in fns:
3611 flog = getfile(fn)
3611 flog = getfile(fn)
3612 try:
3612 try:
3613 fnode = ctx.filenode(fn)
3613 fnode = ctx.filenode(fn)
3614 except error.LookupError:
3614 except error.LookupError:
3615 continue
3615 continue
3616
3616
3617 copied = flog.renamed(fnode)
3617 copied = flog.renamed(fnode)
3618 copy = follow and copied and copied[0]
3618 copy = follow and copied and copied[0]
3619 if copy:
3619 if copy:
3620 copies.setdefault(rev, {})[fn] = copy
3620 copies.setdefault(rev, {})[fn] = copy
3621 if fn in skip:
3621 if fn in skip:
3622 if copy:
3622 if copy:
3623 skip[copy] = True
3623 skip[copy] = True
3624 continue
3624 continue
3625 files.append(fn)
3625 files.append(fn)
3626
3626
3627 if fn not in matches[rev]:
3627 if fn not in matches[rev]:
3628 grepbody(fn, rev, flog.read(fnode))
3628 grepbody(fn, rev, flog.read(fnode))
3629
3629
3630 pfn = copy or fn
3630 pfn = copy or fn
3631 if pfn not in matches[parent]:
3631 if pfn not in matches[parent]:
3632 try:
3632 try:
3633 fnode = pctx.filenode(pfn)
3633 fnode = pctx.filenode(pfn)
3634 grepbody(pfn, parent, flog.read(fnode))
3634 grepbody(pfn, parent, flog.read(fnode))
3635 except error.LookupError:
3635 except error.LookupError:
3636 pass
3636 pass
3637
3637
3638 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3638 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
3639 rev = ctx.rev()
3639 rev = ctx.rev()
3640 parent = ctx.p1().rev()
3640 parent = ctx.p1().rev()
3641 for fn in sorted(revfiles.get(rev, [])):
3641 for fn in sorted(revfiles.get(rev, [])):
3642 states = matches[rev][fn]
3642 states = matches[rev][fn]
3643 copy = copies.get(rev, {}).get(fn)
3643 copy = copies.get(rev, {}).get(fn)
3644 if fn in skip:
3644 if fn in skip:
3645 if copy:
3645 if copy:
3646 skip[copy] = True
3646 skip[copy] = True
3647 continue
3647 continue
3648 pstates = matches.get(parent, {}).get(copy or fn, [])
3648 pstates = matches.get(parent, {}).get(copy or fn, [])
3649 if pstates or states:
3649 if pstates or states:
3650 r = display(fn, ctx, pstates, states)
3650 r = display(fn, ctx, pstates, states)
3651 found = found or r
3651 found = found or r
3652 if r and not opts.get('all'):
3652 if r and not opts.get('all'):
3653 skip[fn] = True
3653 skip[fn] = True
3654 if copy:
3654 if copy:
3655 skip[copy] = True
3655 skip[copy] = True
3656 del matches[rev]
3656 del matches[rev]
3657 del revfiles[rev]
3657 del revfiles[rev]
3658
3658
3659 return not found
3659 return not found
3660
3660
3661 @command('heads',
3661 @command('heads',
3662 [('r', 'rev', '',
3662 [('r', 'rev', '',
3663 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3663 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
3664 ('t', 'topo', False, _('show topological heads only')),
3664 ('t', 'topo', False, _('show topological heads only')),
3665 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3665 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
3666 ('c', 'closed', False, _('show normal and closed branch heads')),
3666 ('c', 'closed', False, _('show normal and closed branch heads')),
3667 ] + templateopts,
3667 ] + templateopts,
3668 _('[-ct] [-r STARTREV] [REV]...'))
3668 _('[-ct] [-r STARTREV] [REV]...'))
3669 def heads(ui, repo, *branchrevs, **opts):
3669 def heads(ui, repo, *branchrevs, **opts):
3670 """show branch heads
3670 """show branch heads
3671
3671
3672 With no arguments, show all open branch heads in the repository.
3672 With no arguments, show all open branch heads in the repository.
3673 Branch heads are changesets that have no descendants on the
3673 Branch heads are changesets that have no descendants on the
3674 same branch. They are where development generally takes place and
3674 same branch. They are where development generally takes place and
3675 are the usual targets for update and merge operations.
3675 are the usual targets for update and merge operations.
3676
3676
3677 If one or more REVs are given, only open branch heads on the
3677 If one or more REVs are given, only open branch heads on the
3678 branches associated with the specified changesets are shown. This
3678 branches associated with the specified changesets are shown. This
3679 means that you can use :hg:`heads .` to see the heads on the
3679 means that you can use :hg:`heads .` to see the heads on the
3680 currently checked-out branch.
3680 currently checked-out branch.
3681
3681
3682 If -c/--closed is specified, also show branch heads marked closed
3682 If -c/--closed is specified, also show branch heads marked closed
3683 (see :hg:`commit --close-branch`).
3683 (see :hg:`commit --close-branch`).
3684
3684
3685 If STARTREV is specified, only those heads that are descendants of
3685 If STARTREV is specified, only those heads that are descendants of
3686 STARTREV will be displayed.
3686 STARTREV will be displayed.
3687
3687
3688 If -t/--topo is specified, named branch mechanics will be ignored and only
3688 If -t/--topo is specified, named branch mechanics will be ignored and only
3689 topological heads (changesets with no children) will be shown.
3689 topological heads (changesets with no children) will be shown.
3690
3690
3691 Returns 0 if matching heads are found, 1 if not.
3691 Returns 0 if matching heads are found, 1 if not.
3692 """
3692 """
3693
3693
3694 start = None
3694 start = None
3695 if 'rev' in opts:
3695 if 'rev' in opts:
3696 start = scmutil.revsingle(repo, opts['rev'], None).node()
3696 start = scmutil.revsingle(repo, opts['rev'], None).node()
3697
3697
3698 if opts.get('topo'):
3698 if opts.get('topo'):
3699 heads = [repo[h] for h in repo.heads(start)]
3699 heads = [repo[h] for h in repo.heads(start)]
3700 else:
3700 else:
3701 heads = []
3701 heads = []
3702 for branch in repo.branchmap():
3702 for branch in repo.branchmap():
3703 heads += repo.branchheads(branch, start, opts.get('closed'))
3703 heads += repo.branchheads(branch, start, opts.get('closed'))
3704 heads = [repo[h] for h in heads]
3704 heads = [repo[h] for h in heads]
3705
3705
3706 if branchrevs:
3706 if branchrevs:
3707 branches = set(repo[br].branch() for br in branchrevs)
3707 branches = set(repo[br].branch() for br in branchrevs)
3708 heads = [h for h in heads if h.branch() in branches]
3708 heads = [h for h in heads if h.branch() in branches]
3709
3709
3710 if opts.get('active') and branchrevs:
3710 if opts.get('active') and branchrevs:
3711 dagheads = repo.heads(start)
3711 dagheads = repo.heads(start)
3712 heads = [h for h in heads if h.node() in dagheads]
3712 heads = [h for h in heads if h.node() in dagheads]
3713
3713
3714 if branchrevs:
3714 if branchrevs:
3715 haveheads = set(h.branch() for h in heads)
3715 haveheads = set(h.branch() for h in heads)
3716 if branches - haveheads:
3716 if branches - haveheads:
3717 headless = ', '.join(b for b in branches - haveheads)
3717 headless = ', '.join(b for b in branches - haveheads)
3718 msg = _('no open branch heads found on branches %s')
3718 msg = _('no open branch heads found on branches %s')
3719 if opts.get('rev'):
3719 if opts.get('rev'):
3720 msg += _(' (started at %s)') % opts['rev']
3720 msg += _(' (started at %s)') % opts['rev']
3721 ui.warn((msg + '\n') % headless)
3721 ui.warn((msg + '\n') % headless)
3722
3722
3723 if not heads:
3723 if not heads:
3724 return 1
3724 return 1
3725
3725
3726 heads = sorted(heads, key=lambda x: -x.rev())
3726 heads = sorted(heads, key=lambda x: -x.rev())
3727 displayer = cmdutil.show_changeset(ui, repo, opts)
3727 displayer = cmdutil.show_changeset(ui, repo, opts)
3728 for ctx in heads:
3728 for ctx in heads:
3729 displayer.show(ctx)
3729 displayer.show(ctx)
3730 displayer.close()
3730 displayer.close()
3731
3731
3732 @command('help',
3732 @command('help',
3733 [('e', 'extension', None, _('show only help for extensions')),
3733 [('e', 'extension', None, _('show only help for extensions')),
3734 ('c', 'command', None, _('show only help for commands')),
3734 ('c', 'command', None, _('show only help for commands')),
3735 ('k', 'keyword', '', _('show topics matching keyword')),
3735 ('k', 'keyword', '', _('show topics matching keyword')),
3736 ],
3736 ],
3737 _('[-ec] [TOPIC]'),
3737 _('[-ec] [TOPIC]'),
3738 norepo=True)
3738 norepo=True)
3739 def help_(ui, name=None, **opts):
3739 def help_(ui, name=None, **opts):
3740 """show help for a given topic or a help overview
3740 """show help for a given topic or a help overview
3741
3741
3742 With no arguments, print a list of commands with short help messages.
3742 With no arguments, print a list of commands with short help messages.
3743
3743
3744 Given a topic, extension, or command name, print help for that
3744 Given a topic, extension, or command name, print help for that
3745 topic.
3745 topic.
3746
3746
3747 Returns 0 if successful.
3747 Returns 0 if successful.
3748 """
3748 """
3749
3749
3750 textwidth = min(ui.termwidth(), 80) - 2
3750 textwidth = min(ui.termwidth(), 80) - 2
3751
3751
3752 keep = ui.verbose and ['verbose'] or []
3752 keep = ui.verbose and ['verbose'] or []
3753 text = help.help_(ui, name, **opts)
3753 text = help.help_(ui, name, **opts)
3754
3754
3755 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3755 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3756 if 'verbose' in pruned:
3756 if 'verbose' in pruned:
3757 keep.append('omitted')
3757 keep.append('omitted')
3758 else:
3758 else:
3759 keep.append('notomitted')
3759 keep.append('notomitted')
3760 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3760 formatted, pruned = minirst.format(text, textwidth, keep=keep)
3761 ui.write(formatted)
3761 ui.write(formatted)
3762
3762
3763
3763
3764 @command('identify|id',
3764 @command('identify|id',
3765 [('r', 'rev', '',
3765 [('r', 'rev', '',
3766 _('identify the specified revision'), _('REV')),
3766 _('identify the specified revision'), _('REV')),
3767 ('n', 'num', None, _('show local revision number')),
3767 ('n', 'num', None, _('show local revision number')),
3768 ('i', 'id', None, _('show global revision id')),
3768 ('i', 'id', None, _('show global revision id')),
3769 ('b', 'branch', None, _('show branch')),
3769 ('b', 'branch', None, _('show branch')),
3770 ('t', 'tags', None, _('show tags')),
3770 ('t', 'tags', None, _('show tags')),
3771 ('B', 'bookmarks', None, _('show bookmarks')),
3771 ('B', 'bookmarks', None, _('show bookmarks')),
3772 ] + remoteopts,
3772 ] + remoteopts,
3773 _('[-nibtB] [-r REV] [SOURCE]'),
3773 _('[-nibtB] [-r REV] [SOURCE]'),
3774 optionalrepo=True)
3774 optionalrepo=True)
3775 def identify(ui, repo, source=None, rev=None,
3775 def identify(ui, repo, source=None, rev=None,
3776 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3776 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
3777 """identify the working copy or specified revision
3777 """identify the working copy or specified revision
3778
3778
3779 Print a summary identifying the repository state at REV using one or
3779 Print a summary identifying the repository state at REV using one or
3780 two parent hash identifiers, followed by a "+" if the working
3780 two parent hash identifiers, followed by a "+" if the working
3781 directory has uncommitted changes, the branch name (if not default),
3781 directory has uncommitted changes, the branch name (if not default),
3782 a list of tags, and a list of bookmarks.
3782 a list of tags, and a list of bookmarks.
3783
3783
3784 When REV is not given, print a summary of the current state of the
3784 When REV is not given, print a summary of the current state of the
3785 repository.
3785 repository.
3786
3786
3787 Specifying a path to a repository root or Mercurial bundle will
3787 Specifying a path to a repository root or Mercurial bundle will
3788 cause lookup to operate on that repository/bundle.
3788 cause lookup to operate on that repository/bundle.
3789
3789
3790 .. container:: verbose
3790 .. container:: verbose
3791
3791
3792 Examples:
3792 Examples:
3793
3793
3794 - generate a build identifier for the working directory::
3794 - generate a build identifier for the working directory::
3795
3795
3796 hg id --id > build-id.dat
3796 hg id --id > build-id.dat
3797
3797
3798 - find the revision corresponding to a tag::
3798 - find the revision corresponding to a tag::
3799
3799
3800 hg id -n -r 1.3
3800 hg id -n -r 1.3
3801
3801
3802 - check the most recent revision of a remote repository::
3802 - check the most recent revision of a remote repository::
3803
3803
3804 hg id -r tip http://selenic.com/hg/
3804 hg id -r tip http://selenic.com/hg/
3805
3805
3806 Returns 0 if successful.
3806 Returns 0 if successful.
3807 """
3807 """
3808
3808
3809 if not repo and not source:
3809 if not repo and not source:
3810 raise util.Abort(_("there is no Mercurial repository here "
3810 raise util.Abort(_("there is no Mercurial repository here "
3811 "(.hg not found)"))
3811 "(.hg not found)"))
3812
3812
3813 hexfunc = ui.debugflag and hex or short
3813 hexfunc = ui.debugflag and hex or short
3814 default = not (num or id or branch or tags or bookmarks)
3814 default = not (num or id or branch or tags or bookmarks)
3815 output = []
3815 output = []
3816 revs = []
3816 revs = []
3817
3817
3818 if source:
3818 if source:
3819 source, branches = hg.parseurl(ui.expandpath(source))
3819 source, branches = hg.parseurl(ui.expandpath(source))
3820 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3820 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
3821 repo = peer.local()
3821 repo = peer.local()
3822 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3822 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
3823
3823
3824 if not repo:
3824 if not repo:
3825 if num or branch or tags:
3825 if num or branch or tags:
3826 raise util.Abort(
3826 raise util.Abort(
3827 _("can't query remote revision number, branch, or tags"))
3827 _("can't query remote revision number, branch, or tags"))
3828 if not rev and revs:
3828 if not rev and revs:
3829 rev = revs[0]
3829 rev = revs[0]
3830 if not rev:
3830 if not rev:
3831 rev = "tip"
3831 rev = "tip"
3832
3832
3833 remoterev = peer.lookup(rev)
3833 remoterev = peer.lookup(rev)
3834 if default or id:
3834 if default or id:
3835 output = [hexfunc(remoterev)]
3835 output = [hexfunc(remoterev)]
3836
3836
3837 def getbms():
3837 def getbms():
3838 bms = []
3838 bms = []
3839
3839
3840 if 'bookmarks' in peer.listkeys('namespaces'):
3840 if 'bookmarks' in peer.listkeys('namespaces'):
3841 hexremoterev = hex(remoterev)
3841 hexremoterev = hex(remoterev)
3842 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3842 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
3843 if bmr == hexremoterev]
3843 if bmr == hexremoterev]
3844
3844
3845 return sorted(bms)
3845 return sorted(bms)
3846
3846
3847 if bookmarks:
3847 if bookmarks:
3848 output.extend(getbms())
3848 output.extend(getbms())
3849 elif default and not ui.quiet:
3849 elif default and not ui.quiet:
3850 # multiple bookmarks for a single parent separated by '/'
3850 # multiple bookmarks for a single parent separated by '/'
3851 bm = '/'.join(getbms())
3851 bm = '/'.join(getbms())
3852 if bm:
3852 if bm:
3853 output.append(bm)
3853 output.append(bm)
3854 else:
3854 else:
3855 if not rev:
3855 if not rev:
3856 ctx = repo[None]
3856 ctx = repo[None]
3857 parents = ctx.parents()
3857 parents = ctx.parents()
3858 changed = ""
3858 changed = ""
3859 if default or id or num:
3859 if default or id or num:
3860 if (util.any(repo.status())
3860 if (util.any(repo.status())
3861 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3861 or util.any(ctx.sub(s).dirty() for s in ctx.substate)):
3862 changed = '+'
3862 changed = '+'
3863 if default or id:
3863 if default or id:
3864 output = ["%s%s" %
3864 output = ["%s%s" %
3865 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3865 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
3866 if num:
3866 if num:
3867 output.append("%s%s" %
3867 output.append("%s%s" %
3868 ('+'.join([str(p.rev()) for p in parents]), changed))
3868 ('+'.join([str(p.rev()) for p in parents]), changed))
3869 else:
3869 else:
3870 ctx = scmutil.revsingle(repo, rev)
3870 ctx = scmutil.revsingle(repo, rev)
3871 if default or id:
3871 if default or id:
3872 output = [hexfunc(ctx.node())]
3872 output = [hexfunc(ctx.node())]
3873 if num:
3873 if num:
3874 output.append(str(ctx.rev()))
3874 output.append(str(ctx.rev()))
3875
3875
3876 if default and not ui.quiet:
3876 if default and not ui.quiet:
3877 b = ctx.branch()
3877 b = ctx.branch()
3878 if b != 'default':
3878 if b != 'default':
3879 output.append("(%s)" % b)
3879 output.append("(%s)" % b)
3880
3880
3881 # multiple tags for a single parent separated by '/'
3881 # multiple tags for a single parent separated by '/'
3882 t = '/'.join(ctx.tags())
3882 t = '/'.join(ctx.tags())
3883 if t:
3883 if t:
3884 output.append(t)
3884 output.append(t)
3885
3885
3886 # multiple bookmarks for a single parent separated by '/'
3886 # multiple bookmarks for a single parent separated by '/'
3887 bm = '/'.join(ctx.bookmarks())
3887 bm = '/'.join(ctx.bookmarks())
3888 if bm:
3888 if bm:
3889 output.append(bm)
3889 output.append(bm)
3890 else:
3890 else:
3891 if branch:
3891 if branch:
3892 output.append(ctx.branch())
3892 output.append(ctx.branch())
3893
3893
3894 if tags:
3894 if tags:
3895 output.extend(ctx.tags())
3895 output.extend(ctx.tags())
3896
3896
3897 if bookmarks:
3897 if bookmarks:
3898 output.extend(ctx.bookmarks())
3898 output.extend(ctx.bookmarks())
3899
3899
3900 ui.write("%s\n" % ' '.join(output))
3900 ui.write("%s\n" % ' '.join(output))
3901
3901
3902 @command('import|patch',
3902 @command('import|patch',
3903 [('p', 'strip', 1,
3903 [('p', 'strip', 1,
3904 _('directory strip option for patch. This has the same '
3904 _('directory strip option for patch. This has the same '
3905 'meaning as the corresponding patch option'), _('NUM')),
3905 'meaning as the corresponding patch option'), _('NUM')),
3906 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3906 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
3907 ('e', 'edit', False, _('invoke editor on commit messages')),
3907 ('e', 'edit', False, _('invoke editor on commit messages')),
3908 ('f', 'force', None,
3908 ('f', 'force', None,
3909 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3909 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
3910 ('', 'no-commit', None,
3910 ('', 'no-commit', None,
3911 _("don't commit, just update the working directory")),
3911 _("don't commit, just update the working directory")),
3912 ('', 'bypass', None,
3912 ('', 'bypass', None,
3913 _("apply patch without touching the working directory")),
3913 _("apply patch without touching the working directory")),
3914 ('', 'partial', None,
3914 ('', 'partial', None,
3915 _('commit even if some hunks fail')),
3915 _('commit even if some hunks fail')),
3916 ('', 'exact', None,
3916 ('', 'exact', None,
3917 _('apply patch to the nodes from which it was generated')),
3917 _('apply patch to the nodes from which it was generated')),
3918 ('', 'import-branch', None,
3918 ('', 'import-branch', None,
3919 _('use any branch information in patch (implied by --exact)'))] +
3919 _('use any branch information in patch (implied by --exact)'))] +
3920 commitopts + commitopts2 + similarityopts,
3920 commitopts + commitopts2 + similarityopts,
3921 _('[OPTION]... PATCH...'))
3921 _('[OPTION]... PATCH...'))
3922 def import_(ui, repo, patch1=None, *patches, **opts):
3922 def import_(ui, repo, patch1=None, *patches, **opts):
3923 """import an ordered set of patches
3923 """import an ordered set of patches
3924
3924
3925 Import a list of patches and commit them individually (unless
3925 Import a list of patches and commit them individually (unless
3926 --no-commit is specified).
3926 --no-commit is specified).
3927
3927
3928 Because import first applies changes to the working directory,
3928 Because import first applies changes to the working directory,
3929 import will abort if there are outstanding changes.
3929 import will abort if there are outstanding changes.
3930
3930
3931 You can import a patch straight from a mail message. Even patches
3931 You can import a patch straight from a mail message. Even patches
3932 as attachments work (to use the body part, it must have type
3932 as attachments work (to use the body part, it must have type
3933 text/plain or text/x-patch). From and Subject headers of email
3933 text/plain or text/x-patch). From and Subject headers of email
3934 message are used as default committer and commit message. All
3934 message are used as default committer and commit message. All
3935 text/plain body parts before first diff are added to commit
3935 text/plain body parts before first diff are added to commit
3936 message.
3936 message.
3937
3937
3938 If the imported patch was generated by :hg:`export`, user and
3938 If the imported patch was generated by :hg:`export`, user and
3939 description from patch override values from message headers and
3939 description from patch override values from message headers and
3940 body. Values given on command line with -m/--message and -u/--user
3940 body. Values given on command line with -m/--message and -u/--user
3941 override these.
3941 override these.
3942
3942
3943 If --exact is specified, import will set the working directory to
3943 If --exact is specified, import will set the working directory to
3944 the parent of each patch before applying it, and will abort if the
3944 the parent of each patch before applying it, and will abort if the
3945 resulting changeset has a different ID than the one recorded in
3945 resulting changeset has a different ID than the one recorded in
3946 the patch. This may happen due to character set problems or other
3946 the patch. This may happen due to character set problems or other
3947 deficiencies in the text patch format.
3947 deficiencies in the text patch format.
3948
3948
3949 Use --bypass to apply and commit patches directly to the
3949 Use --bypass to apply and commit patches directly to the
3950 repository, not touching the working directory. Without --exact,
3950 repository, not touching the working directory. Without --exact,
3951 patches will be applied on top of the working directory parent
3951 patches will be applied on top of the working directory parent
3952 revision.
3952 revision.
3953
3953
3954 With -s/--similarity, hg will attempt to discover renames and
3954 With -s/--similarity, hg will attempt to discover renames and
3955 copies in the patch in the same way as :hg:`addremove`.
3955 copies in the patch in the same way as :hg:`addremove`.
3956
3956
3957 Use --partial to ensure a changeset will be created from the patch
3957 Use --partial to ensure a changeset will be created from the patch
3958 even if some hunks fail to apply. Hunks that fail to apply will be
3958 even if some hunks fail to apply. Hunks that fail to apply will be
3959 written to a <target-file>.rej file. Conflicts can then be resolved
3959 written to a <target-file>.rej file. Conflicts can then be resolved
3960 by hand before :hg:`commit --amend` is run to update the created
3960 by hand before :hg:`commit --amend` is run to update the created
3961 changeset. This flag exists to let people import patches that
3961 changeset. This flag exists to let people import patches that
3962 partially apply without losing the associated metadata (author,
3962 partially apply without losing the associated metadata (author,
3963 date, description, ...). Note that when none of the hunk applies
3963 date, description, ...). Note that when none of the hunk applies
3964 cleanly, :hg:`import --partial` will create an empty changeset,
3964 cleanly, :hg:`import --partial` will create an empty changeset,
3965 importing only the patch metadata.
3965 importing only the patch metadata.
3966
3966
3967 To read a patch from standard input, use "-" as the patch name. If
3967 To read a patch from standard input, use "-" as the patch name. If
3968 a URL is specified, the patch will be downloaded from it.
3968 a URL is specified, the patch will be downloaded from it.
3969 See :hg:`help dates` for a list of formats valid for -d/--date.
3969 See :hg:`help dates` for a list of formats valid for -d/--date.
3970
3970
3971 .. container:: verbose
3971 .. container:: verbose
3972
3972
3973 Examples:
3973 Examples:
3974
3974
3975 - import a traditional patch from a website and detect renames::
3975 - import a traditional patch from a website and detect renames::
3976
3976
3977 hg import -s 80 http://example.com/bugfix.patch
3977 hg import -s 80 http://example.com/bugfix.patch
3978
3978
3979 - import a changeset from an hgweb server::
3979 - import a changeset from an hgweb server::
3980
3980
3981 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3981 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
3982
3982
3983 - import all the patches in an Unix-style mbox::
3983 - import all the patches in an Unix-style mbox::
3984
3984
3985 hg import incoming-patches.mbox
3985 hg import incoming-patches.mbox
3986
3986
3987 - attempt to exactly restore an exported changeset (not always
3987 - attempt to exactly restore an exported changeset (not always
3988 possible)::
3988 possible)::
3989
3989
3990 hg import --exact proposed-fix.patch
3990 hg import --exact proposed-fix.patch
3991
3991
3992 Returns 0 on success, 1 on partial success (see --partial).
3992 Returns 0 on success, 1 on partial success (see --partial).
3993 """
3993 """
3994
3994
3995 if not patch1:
3995 if not patch1:
3996 raise util.Abort(_('need at least one patch to import'))
3996 raise util.Abort(_('need at least one patch to import'))
3997
3997
3998 patches = (patch1,) + patches
3998 patches = (patch1,) + patches
3999
3999
4000 date = opts.get('date')
4000 date = opts.get('date')
4001 if date:
4001 if date:
4002 opts['date'] = util.parsedate(date)
4002 opts['date'] = util.parsedate(date)
4003
4003
4004 update = not opts.get('bypass')
4004 update = not opts.get('bypass')
4005 if not update and opts.get('no_commit'):
4005 if not update and opts.get('no_commit'):
4006 raise util.Abort(_('cannot use --no-commit with --bypass'))
4006 raise util.Abort(_('cannot use --no-commit with --bypass'))
4007 try:
4007 try:
4008 sim = float(opts.get('similarity') or 0)
4008 sim = float(opts.get('similarity') or 0)
4009 except ValueError:
4009 except ValueError:
4010 raise util.Abort(_('similarity must be a number'))
4010 raise util.Abort(_('similarity must be a number'))
4011 if sim < 0 or sim > 100:
4011 if sim < 0 or sim > 100:
4012 raise util.Abort(_('similarity must be between 0 and 100'))
4012 raise util.Abort(_('similarity must be between 0 and 100'))
4013 if sim and not update:
4013 if sim and not update:
4014 raise util.Abort(_('cannot use --similarity with --bypass'))
4014 raise util.Abort(_('cannot use --similarity with --bypass'))
4015 if opts.get('exact') and opts.get('edit'):
4015 if opts.get('exact') and opts.get('edit'):
4016 raise util.Abort(_('cannot use --exact with --edit'))
4016 raise util.Abort(_('cannot use --exact with --edit'))
4017
4017
4018 if update:
4018 if update:
4019 cmdutil.checkunfinished(repo)
4019 cmdutil.checkunfinished(repo)
4020 if (opts.get('exact') or not opts.get('force')) and update:
4020 if (opts.get('exact') or not opts.get('force')) and update:
4021 cmdutil.bailifchanged(repo)
4021 cmdutil.bailifchanged(repo)
4022
4022
4023 base = opts["base"]
4023 base = opts["base"]
4024 wlock = lock = tr = None
4024 wlock = lock = tr = None
4025 msgs = []
4025 msgs = []
4026 ret = 0
4026 ret = 0
4027
4027
4028
4028
4029 try:
4029 try:
4030 try:
4030 try:
4031 wlock = repo.wlock()
4031 wlock = repo.wlock()
4032 repo.dirstate.beginparentchange()
4032 repo.dirstate.beginparentchange()
4033 if not opts.get('no_commit'):
4033 if not opts.get('no_commit'):
4034 lock = repo.lock()
4034 lock = repo.lock()
4035 tr = repo.transaction('import')
4035 tr = repo.transaction('import')
4036 parents = repo.parents()
4036 parents = repo.parents()
4037 for patchurl in patches:
4037 for patchurl in patches:
4038 if patchurl == '-':
4038 if patchurl == '-':
4039 ui.status(_('applying patch from stdin\n'))
4039 ui.status(_('applying patch from stdin\n'))
4040 patchfile = ui.fin
4040 patchfile = ui.fin
4041 patchurl = 'stdin' # for error message
4041 patchurl = 'stdin' # for error message
4042 else:
4042 else:
4043 patchurl = os.path.join(base, patchurl)
4043 patchurl = os.path.join(base, patchurl)
4044 ui.status(_('applying %s\n') % patchurl)
4044 ui.status(_('applying %s\n') % patchurl)
4045 patchfile = hg.openpath(ui, patchurl)
4045 patchfile = hg.openpath(ui, patchurl)
4046
4046
4047 haspatch = False
4047 haspatch = False
4048 for hunk in patch.split(patchfile):
4048 for hunk in patch.split(patchfile):
4049 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4049 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4050 parents, opts,
4050 parents, opts,
4051 msgs, hg.clean)
4051 msgs, hg.clean)
4052 if msg:
4052 if msg:
4053 haspatch = True
4053 haspatch = True
4054 ui.note(msg + '\n')
4054 ui.note(msg + '\n')
4055 if update or opts.get('exact'):
4055 if update or opts.get('exact'):
4056 parents = repo.parents()
4056 parents = repo.parents()
4057 else:
4057 else:
4058 parents = [repo[node]]
4058 parents = [repo[node]]
4059 if rej:
4059 if rej:
4060 ui.write_err(_("patch applied partially\n"))
4060 ui.write_err(_("patch applied partially\n"))
4061 ui.write_err(_("(fix the .rej files and run "
4061 ui.write_err(_("(fix the .rej files and run "
4062 "`hg commit --amend`)\n"))
4062 "`hg commit --amend`)\n"))
4063 ret = 1
4063 ret = 1
4064 break
4064 break
4065
4065
4066 if not haspatch:
4066 if not haspatch:
4067 raise util.Abort(_('%s: no diffs found') % patchurl)
4067 raise util.Abort(_('%s: no diffs found') % patchurl)
4068
4068
4069 if tr:
4069 if tr:
4070 tr.close()
4070 tr.close()
4071 if msgs:
4071 if msgs:
4072 repo.savecommitmessage('\n* * *\n'.join(msgs))
4072 repo.savecommitmessage('\n* * *\n'.join(msgs))
4073 repo.dirstate.endparentchange()
4073 repo.dirstate.endparentchange()
4074 return ret
4074 return ret
4075 except: # re-raises
4075 except: # re-raises
4076 # wlock.release() indirectly calls dirstate.write(): since
4076 # wlock.release() indirectly calls dirstate.write(): since
4077 # we're crashing, we do not want to change the working dir
4077 # we're crashing, we do not want to change the working dir
4078 # parent after all, so make sure it writes nothing
4078 # parent after all, so make sure it writes nothing
4079 repo.dirstate.invalidate()
4079 repo.dirstate.invalidate()
4080 raise
4080 raise
4081 finally:
4081 finally:
4082 if tr:
4082 if tr:
4083 tr.release()
4083 tr.release()
4084 release(lock, wlock)
4084 release(lock, wlock)
4085
4085
4086 @command('incoming|in',
4086 @command('incoming|in',
4087 [('f', 'force', None,
4087 [('f', 'force', None,
4088 _('run even if remote repository is unrelated')),
4088 _('run even if remote repository is unrelated')),
4089 ('n', 'newest-first', None, _('show newest record first')),
4089 ('n', 'newest-first', None, _('show newest record first')),
4090 ('', 'bundle', '',
4090 ('', 'bundle', '',
4091 _('file to store the bundles into'), _('FILE')),
4091 _('file to store the bundles into'), _('FILE')),
4092 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4092 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4093 ('B', 'bookmarks', False, _("compare bookmarks")),
4093 ('B', 'bookmarks', False, _("compare bookmarks")),
4094 ('b', 'branch', [],
4094 ('b', 'branch', [],
4095 _('a specific branch you would like to pull'), _('BRANCH')),
4095 _('a specific branch you would like to pull'), _('BRANCH')),
4096 ] + logopts + remoteopts + subrepoopts,
4096 ] + logopts + remoteopts + subrepoopts,
4097 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4097 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4098 def incoming(ui, repo, source="default", **opts):
4098 def incoming(ui, repo, source="default", **opts):
4099 """show new changesets found in source
4099 """show new changesets found in source
4100
4100
4101 Show new changesets found in the specified path/URL or the default
4101 Show new changesets found in the specified path/URL or the default
4102 pull location. These are the changesets that would have been pulled
4102 pull location. These are the changesets that would have been pulled
4103 if a pull at the time you issued this command.
4103 if a pull at the time you issued this command.
4104
4104
4105 For remote repository, using --bundle avoids downloading the
4105 For remote repository, using --bundle avoids downloading the
4106 changesets twice if the incoming is followed by a pull.
4106 changesets twice if the incoming is followed by a pull.
4107
4107
4108 See pull for valid source format details.
4108 See pull for valid source format details.
4109
4109
4110 .. container:: verbose
4110 .. container:: verbose
4111
4111
4112 Examples:
4112 Examples:
4113
4113
4114 - show incoming changes with patches and full description::
4114 - show incoming changes with patches and full description::
4115
4115
4116 hg incoming -vp
4116 hg incoming -vp
4117
4117
4118 - show incoming changes excluding merges, store a bundle::
4118 - show incoming changes excluding merges, store a bundle::
4119
4119
4120 hg in -vpM --bundle incoming.hg
4120 hg in -vpM --bundle incoming.hg
4121 hg pull incoming.hg
4121 hg pull incoming.hg
4122
4122
4123 - briefly list changes inside a bundle::
4123 - briefly list changes inside a bundle::
4124
4124
4125 hg in changes.hg -T "{desc|firstline}\\n"
4125 hg in changes.hg -T "{desc|firstline}\\n"
4126
4126
4127 Returns 0 if there are incoming changes, 1 otherwise.
4127 Returns 0 if there are incoming changes, 1 otherwise.
4128 """
4128 """
4129 if opts.get('graph'):
4129 if opts.get('graph'):
4130 cmdutil.checkunsupportedgraphflags([], opts)
4130 cmdutil.checkunsupportedgraphflags([], opts)
4131 def display(other, chlist, displayer):
4131 def display(other, chlist, displayer):
4132 revdag = cmdutil.graphrevs(other, chlist, opts)
4132 revdag = cmdutil.graphrevs(other, chlist, opts)
4133 showparents = [ctx.node() for ctx in repo[None].parents()]
4133 showparents = [ctx.node() for ctx in repo[None].parents()]
4134 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4134 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4135 graphmod.asciiedges)
4135 graphmod.asciiedges)
4136
4136
4137 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4137 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4138 return 0
4138 return 0
4139
4139
4140 if opts.get('bundle') and opts.get('subrepos'):
4140 if opts.get('bundle') and opts.get('subrepos'):
4141 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4141 raise util.Abort(_('cannot combine --bundle and --subrepos'))
4142
4142
4143 if opts.get('bookmarks'):
4143 if opts.get('bookmarks'):
4144 source, branches = hg.parseurl(ui.expandpath(source),
4144 source, branches = hg.parseurl(ui.expandpath(source),
4145 opts.get('branch'))
4145 opts.get('branch'))
4146 other = hg.peer(repo, opts, source)
4146 other = hg.peer(repo, opts, source)
4147 if 'bookmarks' not in other.listkeys('namespaces'):
4147 if 'bookmarks' not in other.listkeys('namespaces'):
4148 ui.warn(_("remote doesn't support bookmarks\n"))
4148 ui.warn(_("remote doesn't support bookmarks\n"))
4149 return 0
4149 return 0
4150 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4150 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4151 return bookmarks.diff(ui, repo, other)
4151 return bookmarks.diff(ui, repo, other)
4152
4152
4153 repo._subtoppath = ui.expandpath(source)
4153 repo._subtoppath = ui.expandpath(source)
4154 try:
4154 try:
4155 return hg.incoming(ui, repo, source, opts)
4155 return hg.incoming(ui, repo, source, opts)
4156 finally:
4156 finally:
4157 del repo._subtoppath
4157 del repo._subtoppath
4158
4158
4159
4159
4160 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4160 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4161 norepo=True)
4161 norepo=True)
4162 def init(ui, dest=".", **opts):
4162 def init(ui, dest=".", **opts):
4163 """create a new repository in the given directory
4163 """create a new repository in the given directory
4164
4164
4165 Initialize a new repository in the given directory. If the given
4165 Initialize a new repository in the given directory. If the given
4166 directory does not exist, it will be created.
4166 directory does not exist, it will be created.
4167
4167
4168 If no directory is given, the current directory is used.
4168 If no directory is given, the current directory is used.
4169
4169
4170 It is possible to specify an ``ssh://`` URL as the destination.
4170 It is possible to specify an ``ssh://`` URL as the destination.
4171 See :hg:`help urls` for more information.
4171 See :hg:`help urls` for more information.
4172
4172
4173 Returns 0 on success.
4173 Returns 0 on success.
4174 """
4174 """
4175 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4175 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4176
4176
4177 @command('locate',
4177 @command('locate',
4178 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4178 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4179 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4179 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4180 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4180 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4181 ] + walkopts,
4181 ] + walkopts,
4182 _('[OPTION]... [PATTERN]...'))
4182 _('[OPTION]... [PATTERN]...'))
4183 def locate(ui, repo, *pats, **opts):
4183 def locate(ui, repo, *pats, **opts):
4184 """locate files matching specific patterns (DEPRECATED)
4184 """locate files matching specific patterns (DEPRECATED)
4185
4185
4186 Print files under Mercurial control in the working directory whose
4186 Print files under Mercurial control in the working directory whose
4187 names match the given patterns.
4187 names match the given patterns.
4188
4188
4189 By default, this command searches all directories in the working
4189 By default, this command searches all directories in the working
4190 directory. To search just the current directory and its
4190 directory. To search just the current directory and its
4191 subdirectories, use "--include .".
4191 subdirectories, use "--include .".
4192
4192
4193 If no patterns are given to match, this command prints the names
4193 If no patterns are given to match, this command prints the names
4194 of all files under Mercurial control in the working directory.
4194 of all files under Mercurial control in the working directory.
4195
4195
4196 If you want to feed the output of this command into the "xargs"
4196 If you want to feed the output of this command into the "xargs"
4197 command, use the -0 option to both this command and "xargs". This
4197 command, use the -0 option to both this command and "xargs". This
4198 will avoid the problem of "xargs" treating single filenames that
4198 will avoid the problem of "xargs" treating single filenames that
4199 contain whitespace as multiple filenames.
4199 contain whitespace as multiple filenames.
4200
4200
4201 See :hg:`help files` for a more versatile command.
4201 See :hg:`help files` for a more versatile command.
4202
4202
4203 Returns 0 if a match is found, 1 otherwise.
4203 Returns 0 if a match is found, 1 otherwise.
4204 """
4204 """
4205 end = opts.get('print0') and '\0' or '\n'
4205 end = opts.get('print0') and '\0' or '\n'
4206 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4206 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4207
4207
4208 ret = 1
4208 ret = 1
4209 ctx = repo[rev]
4209 ctx = repo[rev]
4210 m = scmutil.match(ctx, pats, opts, default='relglob')
4210 m = scmutil.match(ctx, pats, opts, default='relglob')
4211 m.bad = lambda x, y: False
4211 m.bad = lambda x, y: False
4212
4212
4213 for abs in ctx.matches(m):
4213 for abs in ctx.matches(m):
4214 if opts.get('fullpath'):
4214 if opts.get('fullpath'):
4215 ui.write(repo.wjoin(abs), end)
4215 ui.write(repo.wjoin(abs), end)
4216 else:
4216 else:
4217 ui.write(((pats and m.rel(abs)) or abs), end)
4217 ui.write(((pats and m.rel(abs)) or abs), end)
4218 ret = 0
4218 ret = 0
4219
4219
4220 return ret
4220 return ret
4221
4221
4222 @command('^log|history',
4222 @command('^log|history',
4223 [('f', 'follow', None,
4223 [('f', 'follow', None,
4224 _('follow changeset history, or file history across copies and renames')),
4224 _('follow changeset history, or file history across copies and renames')),
4225 ('', 'follow-first', None,
4225 ('', 'follow-first', None,
4226 _('only follow the first parent of merge changesets (DEPRECATED)')),
4226 _('only follow the first parent of merge changesets (DEPRECATED)')),
4227 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4227 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4228 ('C', 'copies', None, _('show copied files')),
4228 ('C', 'copies', None, _('show copied files')),
4229 ('k', 'keyword', [],
4229 ('k', 'keyword', [],
4230 _('do case-insensitive search for a given text'), _('TEXT')),
4230 _('do case-insensitive search for a given text'), _('TEXT')),
4231 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4231 ('r', 'rev', [], _('show the specified revision or range'), _('REV')),
4232 ('', 'removed', None, _('include revisions where files were removed')),
4232 ('', 'removed', None, _('include revisions where files were removed')),
4233 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4233 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4234 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4234 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4235 ('', 'only-branch', [],
4235 ('', 'only-branch', [],
4236 _('show only changesets within the given named branch (DEPRECATED)'),
4236 _('show only changesets within the given named branch (DEPRECATED)'),
4237 _('BRANCH')),
4237 _('BRANCH')),
4238 ('b', 'branch', [],
4238 ('b', 'branch', [],
4239 _('show changesets within the given named branch'), _('BRANCH')),
4239 _('show changesets within the given named branch'), _('BRANCH')),
4240 ('P', 'prune', [],
4240 ('P', 'prune', [],
4241 _('do not display revision or any of its ancestors'), _('REV')),
4241 _('do not display revision or any of its ancestors'), _('REV')),
4242 ] + logopts + walkopts,
4242 ] + logopts + walkopts,
4243 _('[OPTION]... [FILE]'),
4243 _('[OPTION]... [FILE]'),
4244 inferrepo=True)
4244 inferrepo=True)
4245 def log(ui, repo, *pats, **opts):
4245 def log(ui, repo, *pats, **opts):
4246 """show revision history of entire repository or files
4246 """show revision history of entire repository or files
4247
4247
4248 Print the revision history of the specified files or the entire
4248 Print the revision history of the specified files or the entire
4249 project.
4249 project.
4250
4250
4251 If no revision range is specified, the default is ``tip:0`` unless
4251 If no revision range is specified, the default is ``tip:0`` unless
4252 --follow is set, in which case the working directory parent is
4252 --follow is set, in which case the working directory parent is
4253 used as the starting revision.
4253 used as the starting revision.
4254
4254
4255 File history is shown without following rename or copy history of
4255 File history is shown without following rename or copy history of
4256 files. Use -f/--follow with a filename to follow history across
4256 files. Use -f/--follow with a filename to follow history across
4257 renames and copies. --follow without a filename will only show
4257 renames and copies. --follow without a filename will only show
4258 ancestors or descendants of the starting revision.
4258 ancestors or descendants of the starting revision.
4259
4259
4260 By default this command prints revision number and changeset id,
4260 By default this command prints revision number and changeset id,
4261 tags, non-trivial parents, user, date and time, and a summary for
4261 tags, non-trivial parents, user, date and time, and a summary for
4262 each commit. When the -v/--verbose switch is used, the list of
4262 each commit. When the -v/--verbose switch is used, the list of
4263 changed files and full commit message are shown.
4263 changed files and full commit message are shown.
4264
4264
4265 With --graph the revisions are shown as an ASCII art DAG with the most
4265 With --graph the revisions are shown as an ASCII art DAG with the most
4266 recent changeset at the top.
4266 recent changeset at the top.
4267 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4267 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4268 and '+' represents a fork where the changeset from the lines below is a
4268 and '+' represents a fork where the changeset from the lines below is a
4269 parent of the 'o' merge on the same line.
4269 parent of the 'o' merge on the same line.
4270
4270
4271 .. note::
4271 .. note::
4272
4272
4273 log -p/--patch may generate unexpected diff output for merge
4273 log -p/--patch may generate unexpected diff output for merge
4274 changesets, as it will only compare the merge changeset against
4274 changesets, as it will only compare the merge changeset against
4275 its first parent. Also, only files different from BOTH parents
4275 its first parent. Also, only files different from BOTH parents
4276 will appear in files:.
4276 will appear in files:.
4277
4277
4278 .. note::
4278 .. note::
4279
4279
4280 for performance reasons, log FILE may omit duplicate changes
4280 for performance reasons, log FILE may omit duplicate changes
4281 made on branches and will not show removals or mode changes. To
4281 made on branches and will not show removals or mode changes. To
4282 see all such changes, use the --removed switch.
4282 see all such changes, use the --removed switch.
4283
4283
4284 .. container:: verbose
4284 .. container:: verbose
4285
4285
4286 Some examples:
4286 Some examples:
4287
4287
4288 - changesets with full descriptions and file lists::
4288 - changesets with full descriptions and file lists::
4289
4289
4290 hg log -v
4290 hg log -v
4291
4291
4292 - changesets ancestral to the working directory::
4292 - changesets ancestral to the working directory::
4293
4293
4294 hg log -f
4294 hg log -f
4295
4295
4296 - last 10 commits on the current branch::
4296 - last 10 commits on the current branch::
4297
4297
4298 hg log -l 10 -b .
4298 hg log -l 10 -b .
4299
4299
4300 - changesets showing all modifications of a file, including removals::
4300 - changesets showing all modifications of a file, including removals::
4301
4301
4302 hg log --removed file.c
4302 hg log --removed file.c
4303
4303
4304 - all changesets that touch a directory, with diffs, excluding merges::
4304 - all changesets that touch a directory, with diffs, excluding merges::
4305
4305
4306 hg log -Mp lib/
4306 hg log -Mp lib/
4307
4307
4308 - all revision numbers that match a keyword::
4308 - all revision numbers that match a keyword::
4309
4309
4310 hg log -k bug --template "{rev}\\n"
4310 hg log -k bug --template "{rev}\\n"
4311
4311
4312 - list available log templates::
4312 - list available log templates::
4313
4313
4314 hg log -T list
4314 hg log -T list
4315
4315
4316 - check if a given changeset is included is a tagged release::
4316 - check if a given changeset is included is a tagged release::
4317
4317
4318 hg log -r "a21ccf and ancestor(1.9)"
4318 hg log -r "a21ccf and ancestor(1.9)"
4319
4319
4320 - find all changesets by some user in a date range::
4320 - find all changesets by some user in a date range::
4321
4321
4322 hg log -k alice -d "may 2008 to jul 2008"
4322 hg log -k alice -d "may 2008 to jul 2008"
4323
4323
4324 - summary of all changesets after the last tag::
4324 - summary of all changesets after the last tag::
4325
4325
4326 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4326 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4327
4327
4328 See :hg:`help dates` for a list of formats valid for -d/--date.
4328 See :hg:`help dates` for a list of formats valid for -d/--date.
4329
4329
4330 See :hg:`help revisions` and :hg:`help revsets` for more about
4330 See :hg:`help revisions` and :hg:`help revsets` for more about
4331 specifying revisions.
4331 specifying revisions.
4332
4332
4333 See :hg:`help templates` for more about pre-packaged styles and
4333 See :hg:`help templates` for more about pre-packaged styles and
4334 specifying custom templates.
4334 specifying custom templates.
4335
4335
4336 Returns 0 on success.
4336 Returns 0 on success.
4337
4337
4338 """
4338 """
4339 if opts.get('graph'):
4339 if opts.get('graph'):
4340 return cmdutil.graphlog(ui, repo, *pats, **opts)
4340 return cmdutil.graphlog(ui, repo, *pats, **opts)
4341
4341
4342 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4342 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4343 limit = cmdutil.loglimit(opts)
4343 limit = cmdutil.loglimit(opts)
4344 count = 0
4344 count = 0
4345
4345
4346 getrenamed = None
4346 getrenamed = None
4347 if opts.get('copies'):
4347 if opts.get('copies'):
4348 endrev = None
4348 endrev = None
4349 if opts.get('rev'):
4349 if opts.get('rev'):
4350 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4350 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4351 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4351 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4352
4352
4353 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4353 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4354 for rev in revs:
4354 for rev in revs:
4355 if count == limit:
4355 if count == limit:
4356 break
4356 break
4357 ctx = repo[rev]
4357 ctx = repo[rev]
4358 copies = None
4358 copies = None
4359 if getrenamed is not None and rev:
4359 if getrenamed is not None and rev:
4360 copies = []
4360 copies = []
4361 for fn in ctx.files():
4361 for fn in ctx.files():
4362 rename = getrenamed(fn, rev)
4362 rename = getrenamed(fn, rev)
4363 if rename:
4363 if rename:
4364 copies.append((fn, rename[0]))
4364 copies.append((fn, rename[0]))
4365 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4365 revmatchfn = filematcher and filematcher(ctx.rev()) or None
4366 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4366 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4367 if displayer.flush(rev):
4367 if displayer.flush(rev):
4368 count += 1
4368 count += 1
4369
4369
4370 displayer.close()
4370 displayer.close()
4371
4371
4372 @command('manifest',
4372 @command('manifest',
4373 [('r', 'rev', '', _('revision to display'), _('REV')),
4373 [('r', 'rev', '', _('revision to display'), _('REV')),
4374 ('', 'all', False, _("list files from all revisions"))]
4374 ('', 'all', False, _("list files from all revisions"))]
4375 + formatteropts,
4375 + formatteropts,
4376 _('[-r REV]'))
4376 _('[-r REV]'))
4377 def manifest(ui, repo, node=None, rev=None, **opts):
4377 def manifest(ui, repo, node=None, rev=None, **opts):
4378 """output the current or given revision of the project manifest
4378 """output the current or given revision of the project manifest
4379
4379
4380 Print a list of version controlled files for the given revision.
4380 Print a list of version controlled files for the given revision.
4381 If no revision is given, the first parent of the working directory
4381 If no revision is given, the first parent of the working directory
4382 is used, or the null revision if no revision is checked out.
4382 is used, or the null revision if no revision is checked out.
4383
4383
4384 With -v, print file permissions, symlink and executable bits.
4384 With -v, print file permissions, symlink and executable bits.
4385 With --debug, print file revision hashes.
4385 With --debug, print file revision hashes.
4386
4386
4387 If option --all is specified, the list of all files from all revisions
4387 If option --all is specified, the list of all files from all revisions
4388 is printed. This includes deleted and renamed files.
4388 is printed. This includes deleted and renamed files.
4389
4389
4390 Returns 0 on success.
4390 Returns 0 on success.
4391 """
4391 """
4392
4392
4393 fm = ui.formatter('manifest', opts)
4393 fm = ui.formatter('manifest', opts)
4394
4394
4395 if opts.get('all'):
4395 if opts.get('all'):
4396 if rev or node:
4396 if rev or node:
4397 raise util.Abort(_("can't specify a revision with --all"))
4397 raise util.Abort(_("can't specify a revision with --all"))
4398
4398
4399 res = []
4399 res = []
4400 prefix = "data/"
4400 prefix = "data/"
4401 suffix = ".i"
4401 suffix = ".i"
4402 plen = len(prefix)
4402 plen = len(prefix)
4403 slen = len(suffix)
4403 slen = len(suffix)
4404 lock = repo.lock()
4404 lock = repo.lock()
4405 try:
4405 try:
4406 for fn, b, size in repo.store.datafiles():
4406 for fn, b, size in repo.store.datafiles():
4407 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4407 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4408 res.append(fn[plen:-slen])
4408 res.append(fn[plen:-slen])
4409 finally:
4409 finally:
4410 lock.release()
4410 lock.release()
4411 for f in res:
4411 for f in res:
4412 fm.startitem()
4412 fm.startitem()
4413 fm.write("path", '%s\n', f)
4413 fm.write("path", '%s\n', f)
4414 fm.end()
4414 fm.end()
4415 return
4415 return
4416
4416
4417 if rev and node:
4417 if rev and node:
4418 raise util.Abort(_("please specify just one revision"))
4418 raise util.Abort(_("please specify just one revision"))
4419
4419
4420 if not node:
4420 if not node:
4421 node = rev
4421 node = rev
4422
4422
4423 char = {'l': '@', 'x': '*', '': ''}
4423 char = {'l': '@', 'x': '*', '': ''}
4424 mode = {'l': '644', 'x': '755', '': '644'}
4424 mode = {'l': '644', 'x': '755', '': '644'}
4425 ctx = scmutil.revsingle(repo, node)
4425 ctx = scmutil.revsingle(repo, node)
4426 mf = ctx.manifest()
4426 mf = ctx.manifest()
4427 for f in ctx:
4427 for f in ctx:
4428 fm.startitem()
4428 fm.startitem()
4429 fl = ctx[f].flags()
4429 fl = ctx[f].flags()
4430 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4430 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4431 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4431 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4432 fm.write('path', '%s\n', f)
4432 fm.write('path', '%s\n', f)
4433 fm.end()
4433 fm.end()
4434
4434
4435 @command('^merge',
4435 @command('^merge',
4436 [('f', 'force', None,
4436 [('f', 'force', None,
4437 _('force a merge including outstanding changes (DEPRECATED)')),
4437 _('force a merge including outstanding changes (DEPRECATED)')),
4438 ('r', 'rev', '', _('revision to merge'), _('REV')),
4438 ('r', 'rev', '', _('revision to merge'), _('REV')),
4439 ('P', 'preview', None,
4439 ('P', 'preview', None,
4440 _('review revisions to merge (no merge is performed)'))
4440 _('review revisions to merge (no merge is performed)'))
4441 ] + mergetoolopts,
4441 ] + mergetoolopts,
4442 _('[-P] [-f] [[-r] REV]'))
4442 _('[-P] [-f] [[-r] REV]'))
4443 def merge(ui, repo, node=None, **opts):
4443 def merge(ui, repo, node=None, **opts):
4444 """merge working directory with another revision
4444 """merge working directory with another revision
4445
4445
4446 The current working directory is updated with all changes made in
4446 The current working directory is updated with all changes made in
4447 the requested revision since the last common predecessor revision.
4447 the requested revision since the last common predecessor revision.
4448
4448
4449 Files that changed between either parent are marked as changed for
4449 Files that changed between either parent are marked as changed for
4450 the next commit and a commit must be performed before any further
4450 the next commit and a commit must be performed before any further
4451 updates to the repository are allowed. The next commit will have
4451 updates to the repository are allowed. The next commit will have
4452 two parents.
4452 two parents.
4453
4453
4454 ``--tool`` can be used to specify the merge tool used for file
4454 ``--tool`` can be used to specify the merge tool used for file
4455 merges. It overrides the HGMERGE environment variable and your
4455 merges. It overrides the HGMERGE environment variable and your
4456 configuration files. See :hg:`help merge-tools` for options.
4456 configuration files. See :hg:`help merge-tools` for options.
4457
4457
4458 If no revision is specified, the working directory's parent is a
4458 If no revision is specified, the working directory's parent is a
4459 head revision, and the current branch contains exactly one other
4459 head revision, and the current branch contains exactly one other
4460 head, the other head is merged with by default. Otherwise, an
4460 head, the other head is merged with by default. Otherwise, an
4461 explicit revision with which to merge with must be provided.
4461 explicit revision with which to merge with must be provided.
4462
4462
4463 :hg:`resolve` must be used to resolve unresolved files.
4463 :hg:`resolve` must be used to resolve unresolved files.
4464
4464
4465 To undo an uncommitted merge, use :hg:`update --clean .` which
4465 To undo an uncommitted merge, use :hg:`update --clean .` which
4466 will check out a clean copy of the original merge parent, losing
4466 will check out a clean copy of the original merge parent, losing
4467 all changes.
4467 all changes.
4468
4468
4469 Returns 0 on success, 1 if there are unresolved files.
4469 Returns 0 on success, 1 if there are unresolved files.
4470 """
4470 """
4471
4471
4472 if opts.get('rev') and node:
4472 if opts.get('rev') and node:
4473 raise util.Abort(_("please specify just one revision"))
4473 raise util.Abort(_("please specify just one revision"))
4474 if not node:
4474 if not node:
4475 node = opts.get('rev')
4475 node = opts.get('rev')
4476
4476
4477 if node:
4477 if node:
4478 node = scmutil.revsingle(repo, node).node()
4478 node = scmutil.revsingle(repo, node).node()
4479
4479
4480 if not node and repo._bookmarkcurrent:
4480 if not node and repo._bookmarkcurrent:
4481 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4481 bmheads = repo.bookmarkheads(repo._bookmarkcurrent)
4482 curhead = repo[repo._bookmarkcurrent].node()
4482 curhead = repo[repo._bookmarkcurrent].node()
4483 if len(bmheads) == 2:
4483 if len(bmheads) == 2:
4484 if curhead == bmheads[0]:
4484 if curhead == bmheads[0]:
4485 node = bmheads[1]
4485 node = bmheads[1]
4486 else:
4486 else:
4487 node = bmheads[0]
4487 node = bmheads[0]
4488 elif len(bmheads) > 2:
4488 elif len(bmheads) > 2:
4489 raise util.Abort(_("multiple matching bookmarks to merge - "
4489 raise util.Abort(_("multiple matching bookmarks to merge - "
4490 "please merge with an explicit rev or bookmark"),
4490 "please merge with an explicit rev or bookmark"),
4491 hint=_("run 'hg heads' to see all heads"))
4491 hint=_("run 'hg heads' to see all heads"))
4492 elif len(bmheads) <= 1:
4492 elif len(bmheads) <= 1:
4493 raise util.Abort(_("no matching bookmark to merge - "
4493 raise util.Abort(_("no matching bookmark to merge - "
4494 "please merge with an explicit rev or bookmark"),
4494 "please merge with an explicit rev or bookmark"),
4495 hint=_("run 'hg heads' to see all heads"))
4495 hint=_("run 'hg heads' to see all heads"))
4496
4496
4497 if not node and not repo._bookmarkcurrent:
4497 if not node and not repo._bookmarkcurrent:
4498 branch = repo[None].branch()
4498 branch = repo[None].branch()
4499 bheads = repo.branchheads(branch)
4499 bheads = repo.branchheads(branch)
4500 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4500 nbhs = [bh for bh in bheads if not repo[bh].bookmarks()]
4501
4501
4502 if len(nbhs) > 2:
4502 if len(nbhs) > 2:
4503 raise util.Abort(_("branch '%s' has %d heads - "
4503 raise util.Abort(_("branch '%s' has %d heads - "
4504 "please merge with an explicit rev")
4504 "please merge with an explicit rev")
4505 % (branch, len(bheads)),
4505 % (branch, len(bheads)),
4506 hint=_("run 'hg heads .' to see heads"))
4506 hint=_("run 'hg heads .' to see heads"))
4507
4507
4508 parent = repo.dirstate.p1()
4508 parent = repo.dirstate.p1()
4509 if len(nbhs) <= 1:
4509 if len(nbhs) <= 1:
4510 if len(bheads) > 1:
4510 if len(bheads) > 1:
4511 raise util.Abort(_("heads are bookmarked - "
4511 raise util.Abort(_("heads are bookmarked - "
4512 "please merge with an explicit rev"),
4512 "please merge with an explicit rev"),
4513 hint=_("run 'hg heads' to see all heads"))
4513 hint=_("run 'hg heads' to see all heads"))
4514 if len(repo.heads()) > 1:
4514 if len(repo.heads()) > 1:
4515 raise util.Abort(_("branch '%s' has one head - "
4515 raise util.Abort(_("branch '%s' has one head - "
4516 "please merge with an explicit rev")
4516 "please merge with an explicit rev")
4517 % branch,
4517 % branch,
4518 hint=_("run 'hg heads' to see all heads"))
4518 hint=_("run 'hg heads' to see all heads"))
4519 msg, hint = _('nothing to merge'), None
4519 msg, hint = _('nothing to merge'), None
4520 if parent != repo.lookup(branch):
4520 if parent != repo.lookup(branch):
4521 hint = _("use 'hg update' instead")
4521 hint = _("use 'hg update' instead")
4522 raise util.Abort(msg, hint=hint)
4522 raise util.Abort(msg, hint=hint)
4523
4523
4524 if parent not in bheads:
4524 if parent not in bheads:
4525 raise util.Abort(_('working directory not at a head revision'),
4525 raise util.Abort(_('working directory not at a head revision'),
4526 hint=_("use 'hg update' or merge with an "
4526 hint=_("use 'hg update' or merge with an "
4527 "explicit revision"))
4527 "explicit revision"))
4528 if parent == nbhs[0]:
4528 if parent == nbhs[0]:
4529 node = nbhs[-1]
4529 node = nbhs[-1]
4530 else:
4530 else:
4531 node = nbhs[0]
4531 node = nbhs[0]
4532
4532
4533 if opts.get('preview'):
4533 if opts.get('preview'):
4534 # find nodes that are ancestors of p2 but not of p1
4534 # find nodes that are ancestors of p2 but not of p1
4535 p1 = repo.lookup('.')
4535 p1 = repo.lookup('.')
4536 p2 = repo.lookup(node)
4536 p2 = repo.lookup(node)
4537 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4537 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4538
4538
4539 displayer = cmdutil.show_changeset(ui, repo, opts)
4539 displayer = cmdutil.show_changeset(ui, repo, opts)
4540 for node in nodes:
4540 for node in nodes:
4541 displayer.show(repo[node])
4541 displayer.show(repo[node])
4542 displayer.close()
4542 displayer.close()
4543 return 0
4543 return 0
4544
4544
4545 try:
4545 try:
4546 # ui.forcemerge is an internal variable, do not document
4546 # ui.forcemerge is an internal variable, do not document
4547 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4547 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4548 return hg.merge(repo, node, force=opts.get('force'))
4548 return hg.merge(repo, node, force=opts.get('force'))
4549 finally:
4549 finally:
4550 ui.setconfig('ui', 'forcemerge', '', 'merge')
4550 ui.setconfig('ui', 'forcemerge', '', 'merge')
4551
4551
4552 @command('outgoing|out',
4552 @command('outgoing|out',
4553 [('f', 'force', None, _('run even when the destination is unrelated')),
4553 [('f', 'force', None, _('run even when the destination is unrelated')),
4554 ('r', 'rev', [],
4554 ('r', 'rev', [],
4555 _('a changeset intended to be included in the destination'), _('REV')),
4555 _('a changeset intended to be included in the destination'), _('REV')),
4556 ('n', 'newest-first', None, _('show newest record first')),
4556 ('n', 'newest-first', None, _('show newest record first')),
4557 ('B', 'bookmarks', False, _('compare bookmarks')),
4557 ('B', 'bookmarks', False, _('compare bookmarks')),
4558 ('b', 'branch', [], _('a specific branch you would like to push'),
4558 ('b', 'branch', [], _('a specific branch you would like to push'),
4559 _('BRANCH')),
4559 _('BRANCH')),
4560 ] + logopts + remoteopts + subrepoopts,
4560 ] + logopts + remoteopts + subrepoopts,
4561 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4561 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4562 def outgoing(ui, repo, dest=None, **opts):
4562 def outgoing(ui, repo, dest=None, **opts):
4563 """show changesets not found in the destination
4563 """show changesets not found in the destination
4564
4564
4565 Show changesets not found in the specified destination repository
4565 Show changesets not found in the specified destination repository
4566 or the default push location. These are the changesets that would
4566 or the default push location. These are the changesets that would
4567 be pushed if a push was requested.
4567 be pushed if a push was requested.
4568
4568
4569 See pull for details of valid destination formats.
4569 See pull for details of valid destination formats.
4570
4570
4571 Returns 0 if there are outgoing changes, 1 otherwise.
4571 Returns 0 if there are outgoing changes, 1 otherwise.
4572 """
4572 """
4573 if opts.get('graph'):
4573 if opts.get('graph'):
4574 cmdutil.checkunsupportedgraphflags([], opts)
4574 cmdutil.checkunsupportedgraphflags([], opts)
4575 o, other = hg._outgoing(ui, repo, dest, opts)
4575 o, other = hg._outgoing(ui, repo, dest, opts)
4576 if not o:
4576 if not o:
4577 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4577 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4578 return
4578 return
4579
4579
4580 revdag = cmdutil.graphrevs(repo, o, opts)
4580 revdag = cmdutil.graphrevs(repo, o, opts)
4581 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4581 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4582 showparents = [ctx.node() for ctx in repo[None].parents()]
4582 showparents = [ctx.node() for ctx in repo[None].parents()]
4583 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4583 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4584 graphmod.asciiedges)
4584 graphmod.asciiedges)
4585 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4585 cmdutil.outgoinghooks(ui, repo, other, opts, o)
4586 return 0
4586 return 0
4587
4587
4588 if opts.get('bookmarks'):
4588 if opts.get('bookmarks'):
4589 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4589 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4590 dest, branches = hg.parseurl(dest, opts.get('branch'))
4590 dest, branches = hg.parseurl(dest, opts.get('branch'))
4591 other = hg.peer(repo, opts, dest)
4591 other = hg.peer(repo, opts, dest)
4592 if 'bookmarks' not in other.listkeys('namespaces'):
4592 if 'bookmarks' not in other.listkeys('namespaces'):
4593 ui.warn(_("remote doesn't support bookmarks\n"))
4593 ui.warn(_("remote doesn't support bookmarks\n"))
4594 return 0
4594 return 0
4595 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4595 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
4596 return bookmarks.diff(ui, other, repo)
4596 return bookmarks.diff(ui, other, repo)
4597
4597
4598 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4598 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
4599 try:
4599 try:
4600 return hg.outgoing(ui, repo, dest, opts)
4600 return hg.outgoing(ui, repo, dest, opts)
4601 finally:
4601 finally:
4602 del repo._subtoppath
4602 del repo._subtoppath
4603
4603
4604 @command('parents',
4604 @command('parents',
4605 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4605 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
4606 ] + templateopts,
4606 ] + templateopts,
4607 _('[-r REV] [FILE]'),
4607 _('[-r REV] [FILE]'),
4608 inferrepo=True)
4608 inferrepo=True)
4609 def parents(ui, repo, file_=None, **opts):
4609 def parents(ui, repo, file_=None, **opts):
4610 """show the parents of the working directory or revision (DEPRECATED)
4610 """show the parents of the working directory or revision (DEPRECATED)
4611
4611
4612 Print the working directory's parent revisions. If a revision is
4612 Print the working directory's parent revisions. If a revision is
4613 given via -r/--rev, the parent of that revision will be printed.
4613 given via -r/--rev, the parent of that revision will be printed.
4614 If a file argument is given, the revision in which the file was
4614 If a file argument is given, the revision in which the file was
4615 last changed (before the working directory revision or the
4615 last changed (before the working directory revision or the
4616 argument to --rev if given) is printed.
4616 argument to --rev if given) is printed.
4617
4617
4618 See :hg:`summary` and :hg:`help revsets` for related information.
4618 See :hg:`summary` and :hg:`help revsets` for related information.
4619
4619
4620 Returns 0 on success.
4620 Returns 0 on success.
4621 """
4621 """
4622
4622
4623 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4623 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
4624
4624
4625 if file_:
4625 if file_:
4626 m = scmutil.match(ctx, (file_,), opts)
4626 m = scmutil.match(ctx, (file_,), opts)
4627 if m.anypats() or len(m.files()) != 1:
4627 if m.anypats() or len(m.files()) != 1:
4628 raise util.Abort(_('can only specify an explicit filename'))
4628 raise util.Abort(_('can only specify an explicit filename'))
4629 file_ = m.files()[0]
4629 file_ = m.files()[0]
4630 filenodes = []
4630 filenodes = []
4631 for cp in ctx.parents():
4631 for cp in ctx.parents():
4632 if not cp:
4632 if not cp:
4633 continue
4633 continue
4634 try:
4634 try:
4635 filenodes.append(cp.filenode(file_))
4635 filenodes.append(cp.filenode(file_))
4636 except error.LookupError:
4636 except error.LookupError:
4637 pass
4637 pass
4638 if not filenodes:
4638 if not filenodes:
4639 raise util.Abort(_("'%s' not found in manifest!") % file_)
4639 raise util.Abort(_("'%s' not found in manifest!") % file_)
4640 p = []
4640 p = []
4641 for fn in filenodes:
4641 for fn in filenodes:
4642 fctx = repo.filectx(file_, fileid=fn)
4642 fctx = repo.filectx(file_, fileid=fn)
4643 p.append(fctx.node())
4643 p.append(fctx.node())
4644 else:
4644 else:
4645 p = [cp.node() for cp in ctx.parents()]
4645 p = [cp.node() for cp in ctx.parents()]
4646
4646
4647 displayer = cmdutil.show_changeset(ui, repo, opts)
4647 displayer = cmdutil.show_changeset(ui, repo, opts)
4648 for n in p:
4648 for n in p:
4649 if n != nullid:
4649 if n != nullid:
4650 displayer.show(repo[n])
4650 displayer.show(repo[n])
4651 displayer.close()
4651 displayer.close()
4652
4652
4653 @command('paths', [], _('[NAME]'), optionalrepo=True)
4653 @command('paths', [], _('[NAME]'), optionalrepo=True)
4654 def paths(ui, repo, search=None):
4654 def paths(ui, repo, search=None):
4655 """show aliases for remote repositories
4655 """show aliases for remote repositories
4656
4656
4657 Show definition of symbolic path name NAME. If no name is given,
4657 Show definition of symbolic path name NAME. If no name is given,
4658 show definition of all available names.
4658 show definition of all available names.
4659
4659
4660 Option -q/--quiet suppresses all output when searching for NAME
4660 Option -q/--quiet suppresses all output when searching for NAME
4661 and shows only the path names when listing all definitions.
4661 and shows only the path names when listing all definitions.
4662
4662
4663 Path names are defined in the [paths] section of your
4663 Path names are defined in the [paths] section of your
4664 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4664 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
4665 repository, ``.hg/hgrc`` is used, too.
4665 repository, ``.hg/hgrc`` is used, too.
4666
4666
4667 The path names ``default`` and ``default-push`` have a special
4667 The path names ``default`` and ``default-push`` have a special
4668 meaning. When performing a push or pull operation, they are used
4668 meaning. When performing a push or pull operation, they are used
4669 as fallbacks if no location is specified on the command-line.
4669 as fallbacks if no location is specified on the command-line.
4670 When ``default-push`` is set, it will be used for push and
4670 When ``default-push`` is set, it will be used for push and
4671 ``default`` will be used for pull; otherwise ``default`` is used
4671 ``default`` will be used for pull; otherwise ``default`` is used
4672 as the fallback for both. When cloning a repository, the clone
4672 as the fallback for both. When cloning a repository, the clone
4673 source is written as ``default`` in ``.hg/hgrc``. Note that
4673 source is written as ``default`` in ``.hg/hgrc``. Note that
4674 ``default`` and ``default-push`` apply to all inbound (e.g.
4674 ``default`` and ``default-push`` apply to all inbound (e.g.
4675 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4675 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
4676 :hg:`bundle`) operations.
4676 :hg:`bundle`) operations.
4677
4677
4678 See :hg:`help urls` for more information.
4678 See :hg:`help urls` for more information.
4679
4679
4680 Returns 0 on success.
4680 Returns 0 on success.
4681 """
4681 """
4682 if search:
4682 if search:
4683 for name, path in ui.configitems("paths"):
4683 for name, path in ui.configitems("paths"):
4684 if name == search:
4684 if name == search:
4685 ui.status("%s\n" % util.hidepassword(path))
4685 ui.status("%s\n" % util.hidepassword(path))
4686 return
4686 return
4687 if not ui.quiet:
4687 if not ui.quiet:
4688 ui.warn(_("not found!\n"))
4688 ui.warn(_("not found!\n"))
4689 return 1
4689 return 1
4690 else:
4690 else:
4691 for name, path in ui.configitems("paths"):
4691 for name, path in ui.configitems("paths"):
4692 if ui.quiet:
4692 if ui.quiet:
4693 ui.write("%s\n" % name)
4693 ui.write("%s\n" % name)
4694 else:
4694 else:
4695 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4695 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
4696
4696
4697 @command('phase',
4697 @command('phase',
4698 [('p', 'public', False, _('set changeset phase to public')),
4698 [('p', 'public', False, _('set changeset phase to public')),
4699 ('d', 'draft', False, _('set changeset phase to draft')),
4699 ('d', 'draft', False, _('set changeset phase to draft')),
4700 ('s', 'secret', False, _('set changeset phase to secret')),
4700 ('s', 'secret', False, _('set changeset phase to secret')),
4701 ('f', 'force', False, _('allow to move boundary backward')),
4701 ('f', 'force', False, _('allow to move boundary backward')),
4702 ('r', 'rev', [], _('target revision'), _('REV')),
4702 ('r', 'rev', [], _('target revision'), _('REV')),
4703 ],
4703 ],
4704 _('[-p|-d|-s] [-f] [-r] REV...'))
4704 _('[-p|-d|-s] [-f] [-r] REV...'))
4705 def phase(ui, repo, *revs, **opts):
4705 def phase(ui, repo, *revs, **opts):
4706 """set or show the current phase name
4706 """set or show the current phase name
4707
4707
4708 With no argument, show the phase name of specified revisions.
4708 With no argument, show the phase name of specified revisions.
4709
4709
4710 With one of -p/--public, -d/--draft or -s/--secret, change the
4710 With one of -p/--public, -d/--draft or -s/--secret, change the
4711 phase value of the specified revisions.
4711 phase value of the specified revisions.
4712
4712
4713 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4713 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
4714 lower phase to an higher phase. Phases are ordered as follows::
4714 lower phase to an higher phase. Phases are ordered as follows::
4715
4715
4716 public < draft < secret
4716 public < draft < secret
4717
4717
4718 Returns 0 on success, 1 if no phases were changed or some could not
4718 Returns 0 on success, 1 if no phases were changed or some could not
4719 be changed.
4719 be changed.
4720 """
4720 """
4721 # search for a unique phase argument
4721 # search for a unique phase argument
4722 targetphase = None
4722 targetphase = None
4723 for idx, name in enumerate(phases.phasenames):
4723 for idx, name in enumerate(phases.phasenames):
4724 if opts[name]:
4724 if opts[name]:
4725 if targetphase is not None:
4725 if targetphase is not None:
4726 raise util.Abort(_('only one phase can be specified'))
4726 raise util.Abort(_('only one phase can be specified'))
4727 targetphase = idx
4727 targetphase = idx
4728
4728
4729 # look for specified revision
4729 # look for specified revision
4730 revs = list(revs)
4730 revs = list(revs)
4731 revs.extend(opts['rev'])
4731 revs.extend(opts['rev'])
4732 if not revs:
4732 if not revs:
4733 raise util.Abort(_('no revisions specified'))
4733 raise util.Abort(_('no revisions specified'))
4734
4734
4735 revs = scmutil.revrange(repo, revs)
4735 revs = scmutil.revrange(repo, revs)
4736
4736
4737 lock = None
4737 lock = None
4738 ret = 0
4738 ret = 0
4739 if targetphase is None:
4739 if targetphase is None:
4740 # display
4740 # display
4741 for r in revs:
4741 for r in revs:
4742 ctx = repo[r]
4742 ctx = repo[r]
4743 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4743 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
4744 else:
4744 else:
4745 tr = None
4745 tr = None
4746 lock = repo.lock()
4746 lock = repo.lock()
4747 try:
4747 try:
4748 tr = repo.transaction("phase")
4748 tr = repo.transaction("phase")
4749 # set phase
4749 # set phase
4750 if not revs:
4750 if not revs:
4751 raise util.Abort(_('empty revision set'))
4751 raise util.Abort(_('empty revision set'))
4752 nodes = [repo[r].node() for r in revs]
4752 nodes = [repo[r].node() for r in revs]
4753 olddata = repo._phasecache.getphaserevs(repo)[:]
4753 olddata = repo._phasecache.getphaserevs(repo)[:]
4754 phases.advanceboundary(repo, tr, targetphase, nodes)
4754 phases.advanceboundary(repo, tr, targetphase, nodes)
4755 if opts['force']:
4755 if opts['force']:
4756 phases.retractboundary(repo, tr, targetphase, nodes)
4756 phases.retractboundary(repo, tr, targetphase, nodes)
4757 tr.close()
4757 tr.close()
4758 finally:
4758 finally:
4759 if tr is not None:
4759 if tr is not None:
4760 tr.release()
4760 tr.release()
4761 lock.release()
4761 lock.release()
4762 # moving revision from public to draft may hide them
4762 # moving revision from public to draft may hide them
4763 # We have to check result on an unfiltered repository
4763 # We have to check result on an unfiltered repository
4764 unfi = repo.unfiltered()
4764 unfi = repo.unfiltered()
4765 newdata = repo._phasecache.getphaserevs(unfi)
4765 newdata = repo._phasecache.getphaserevs(unfi)
4766 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4766 changes = sum(o != newdata[i] for i, o in enumerate(olddata))
4767 cl = unfi.changelog
4767 cl = unfi.changelog
4768 rejected = [n for n in nodes
4768 rejected = [n for n in nodes
4769 if newdata[cl.rev(n)] < targetphase]
4769 if newdata[cl.rev(n)] < targetphase]
4770 if rejected:
4770 if rejected:
4771 ui.warn(_('cannot move %i changesets to a higher '
4771 ui.warn(_('cannot move %i changesets to a higher '
4772 'phase, use --force\n') % len(rejected))
4772 'phase, use --force\n') % len(rejected))
4773 ret = 1
4773 ret = 1
4774 if changes:
4774 if changes:
4775 msg = _('phase changed for %i changesets\n') % changes
4775 msg = _('phase changed for %i changesets\n') % changes
4776 if ret:
4776 if ret:
4777 ui.status(msg)
4777 ui.status(msg)
4778 else:
4778 else:
4779 ui.note(msg)
4779 ui.note(msg)
4780 else:
4780 else:
4781 ui.warn(_('no phases changed\n'))
4781 ui.warn(_('no phases changed\n'))
4782 ret = 1
4782 ret = 1
4783 return ret
4783 return ret
4784
4784
4785 def postincoming(ui, repo, modheads, optupdate, checkout):
4785 def postincoming(ui, repo, modheads, optupdate, checkout):
4786 if modheads == 0:
4786 if modheads == 0:
4787 return
4787 return
4788 if optupdate:
4788 if optupdate:
4789 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4789 checkout, movemarkfrom = bookmarks.calculateupdate(ui, repo, checkout)
4790 try:
4790 try:
4791 ret = hg.update(repo, checkout)
4791 ret = hg.update(repo, checkout)
4792 except util.Abort, inst:
4792 except util.Abort, inst:
4793 ui.warn(_("not updating: %s\n") % str(inst))
4793 ui.warn(_("not updating: %s\n") % str(inst))
4794 if inst.hint:
4794 if inst.hint:
4795 ui.warn(_("(%s)\n") % inst.hint)
4795 ui.warn(_("(%s)\n") % inst.hint)
4796 return 0
4796 return 0
4797 if not ret and not checkout:
4797 if not ret and not checkout:
4798 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4798 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
4799 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4799 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
4800 return ret
4800 return ret
4801 if modheads > 1:
4801 if modheads > 1:
4802 currentbranchheads = len(repo.branchheads())
4802 currentbranchheads = len(repo.branchheads())
4803 if currentbranchheads == modheads:
4803 if currentbranchheads == modheads:
4804 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4804 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
4805 elif currentbranchheads > 1:
4805 elif currentbranchheads > 1:
4806 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4806 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
4807 "merge)\n"))
4807 "merge)\n"))
4808 else:
4808 else:
4809 ui.status(_("(run 'hg heads' to see heads)\n"))
4809 ui.status(_("(run 'hg heads' to see heads)\n"))
4810 else:
4810 else:
4811 ui.status(_("(run 'hg update' to get a working copy)\n"))
4811 ui.status(_("(run 'hg update' to get a working copy)\n"))
4812
4812
4813 @command('^pull',
4813 @command('^pull',
4814 [('u', 'update', None,
4814 [('u', 'update', None,
4815 _('update to new branch head if changesets were pulled')),
4815 _('update to new branch head if changesets were pulled')),
4816 ('f', 'force', None, _('run even when remote repository is unrelated')),
4816 ('f', 'force', None, _('run even when remote repository is unrelated')),
4817 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4817 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4818 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4818 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4819 ('b', 'branch', [], _('a specific branch you would like to pull'),
4819 ('b', 'branch', [], _('a specific branch you would like to pull'),
4820 _('BRANCH')),
4820 _('BRANCH')),
4821 ] + remoteopts,
4821 ] + remoteopts,
4822 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4822 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
4823 def pull(ui, repo, source="default", **opts):
4823 def pull(ui, repo, source="default", **opts):
4824 """pull changes from the specified source
4824 """pull changes from the specified source
4825
4825
4826 Pull changes from a remote repository to a local one.
4826 Pull changes from a remote repository to a local one.
4827
4827
4828 This finds all changes from the repository at the specified path
4828 This finds all changes from the repository at the specified path
4829 or URL and adds them to a local repository (the current one unless
4829 or URL and adds them to a local repository (the current one unless
4830 -R is specified). By default, this does not update the copy of the
4830 -R is specified). By default, this does not update the copy of the
4831 project in the working directory.
4831 project in the working directory.
4832
4832
4833 Use :hg:`incoming` if you want to see what would have been added
4833 Use :hg:`incoming` if you want to see what would have been added
4834 by a pull at the time you issued this command. If you then decide
4834 by a pull at the time you issued this command. If you then decide
4835 to add those changes to the repository, you should use :hg:`pull
4835 to add those changes to the repository, you should use :hg:`pull
4836 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4836 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
4837
4837
4838 If SOURCE is omitted, the 'default' path will be used.
4838 If SOURCE is omitted, the 'default' path will be used.
4839 See :hg:`help urls` for more information.
4839 See :hg:`help urls` for more information.
4840
4840
4841 Returns 0 on success, 1 if an update had unresolved files.
4841 Returns 0 on success, 1 if an update had unresolved files.
4842 """
4842 """
4843 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4843 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
4844 other = hg.peer(repo, opts, source)
4844 other = hg.peer(repo, opts, source)
4845 try:
4845 try:
4846 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4846 ui.status(_('pulling from %s\n') % util.hidepassword(source))
4847 revs, checkout = hg.addbranchrevs(repo, other, branches,
4847 revs, checkout = hg.addbranchrevs(repo, other, branches,
4848 opts.get('rev'))
4848 opts.get('rev'))
4849
4849
4850 remotebookmarks = other.listkeys('bookmarks')
4850 remotebookmarks = other.listkeys('bookmarks')
4851
4851
4852 if opts.get('bookmark'):
4852 if opts.get('bookmark'):
4853 if not revs:
4853 if not revs:
4854 revs = []
4854 revs = []
4855 for b in opts['bookmark']:
4855 for b in opts['bookmark']:
4856 if b not in remotebookmarks:
4856 if b not in remotebookmarks:
4857 raise util.Abort(_('remote bookmark %s not found!') % b)
4857 raise util.Abort(_('remote bookmark %s not found!') % b)
4858 revs.append(remotebookmarks[b])
4858 revs.append(remotebookmarks[b])
4859
4859
4860 if revs:
4860 if revs:
4861 try:
4861 try:
4862 revs = [other.lookup(rev) for rev in revs]
4862 revs = [other.lookup(rev) for rev in revs]
4863 except error.CapabilityError:
4863 except error.CapabilityError:
4864 err = _("other repository doesn't support revision lookup, "
4864 err = _("other repository doesn't support revision lookup, "
4865 "so a rev cannot be specified.")
4865 "so a rev cannot be specified.")
4866 raise util.Abort(err)
4866 raise util.Abort(err)
4867
4867
4868 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4868 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
4869 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4869 bookmarks.updatefromremote(ui, repo, remotebookmarks, source)
4870 if checkout:
4870 if checkout:
4871 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4871 checkout = str(repo.changelog.rev(other.lookup(checkout)))
4872 repo._subtoppath = source
4872 repo._subtoppath = source
4873 try:
4873 try:
4874 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4874 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
4875
4875
4876 finally:
4876 finally:
4877 del repo._subtoppath
4877 del repo._subtoppath
4878
4878
4879 # update specified bookmarks
4879 # update specified bookmarks
4880 if opts.get('bookmark'):
4880 if opts.get('bookmark'):
4881 marks = repo._bookmarks
4881 marks = repo._bookmarks
4882 for b in opts['bookmark']:
4882 for b in opts['bookmark']:
4883 # explicit pull overrides local bookmark if any
4883 # explicit pull overrides local bookmark if any
4884 ui.status(_("importing bookmark %s\n") % b)
4884 ui.status(_("importing bookmark %s\n") % b)
4885 marks[b] = repo[remotebookmarks[b]].node()
4885 marks[b] = repo[remotebookmarks[b]].node()
4886 marks.write()
4886 marks.write()
4887 finally:
4887 finally:
4888 other.close()
4888 other.close()
4889 return ret
4889 return ret
4890
4890
4891 @command('^push',
4891 @command('^push',
4892 [('f', 'force', None, _('force push')),
4892 [('f', 'force', None, _('force push')),
4893 ('r', 'rev', [],
4893 ('r', 'rev', [],
4894 _('a changeset intended to be included in the destination'),
4894 _('a changeset intended to be included in the destination'),
4895 _('REV')),
4895 _('REV')),
4896 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4896 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4897 ('b', 'branch', [],
4897 ('b', 'branch', [],
4898 _('a specific branch you would like to push'), _('BRANCH')),
4898 _('a specific branch you would like to push'), _('BRANCH')),
4899 ('', 'new-branch', False, _('allow pushing a new branch')),
4899 ('', 'new-branch', False, _('allow pushing a new branch')),
4900 ] + remoteopts,
4900 ] + remoteopts,
4901 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4901 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
4902 def push(ui, repo, dest=None, **opts):
4902 def push(ui, repo, dest=None, **opts):
4903 """push changes to the specified destination
4903 """push changes to the specified destination
4904
4904
4905 Push changesets from the local repository to the specified
4905 Push changesets from the local repository to the specified
4906 destination.
4906 destination.
4907
4907
4908 This operation is symmetrical to pull: it is identical to a pull
4908 This operation is symmetrical to pull: it is identical to a pull
4909 in the destination repository from the current one.
4909 in the destination repository from the current one.
4910
4910
4911 By default, push will not allow creation of new heads at the
4911 By default, push will not allow creation of new heads at the
4912 destination, since multiple heads would make it unclear which head
4912 destination, since multiple heads would make it unclear which head
4913 to use. In this situation, it is recommended to pull and merge
4913 to use. In this situation, it is recommended to pull and merge
4914 before pushing.
4914 before pushing.
4915
4915
4916 Use --new-branch if you want to allow push to create a new named
4916 Use --new-branch if you want to allow push to create a new named
4917 branch that is not present at the destination. This allows you to
4917 branch that is not present at the destination. This allows you to
4918 only create a new branch without forcing other changes.
4918 only create a new branch without forcing other changes.
4919
4919
4920 .. note::
4920 .. note::
4921
4921
4922 Extra care should be taken with the -f/--force option,
4922 Extra care should be taken with the -f/--force option,
4923 which will push all new heads on all branches, an action which will
4923 which will push all new heads on all branches, an action which will
4924 almost always cause confusion for collaborators.
4924 almost always cause confusion for collaborators.
4925
4925
4926 If -r/--rev is used, the specified revision and all its ancestors
4926 If -r/--rev is used, the specified revision and all its ancestors
4927 will be pushed to the remote repository.
4927 will be pushed to the remote repository.
4928
4928
4929 If -B/--bookmark is used, the specified bookmarked revision, its
4929 If -B/--bookmark is used, the specified bookmarked revision, its
4930 ancestors, and the bookmark will be pushed to the remote
4930 ancestors, and the bookmark will be pushed to the remote
4931 repository.
4931 repository.
4932
4932
4933 Please see :hg:`help urls` for important details about ``ssh://``
4933 Please see :hg:`help urls` for important details about ``ssh://``
4934 URLs. If DESTINATION is omitted, a default path will be used.
4934 URLs. If DESTINATION is omitted, a default path will be used.
4935
4935
4936 Returns 0 if push was successful, 1 if nothing to push.
4936 Returns 0 if push was successful, 1 if nothing to push.
4937 """
4937 """
4938
4938
4939 if opts.get('bookmark'):
4939 if opts.get('bookmark'):
4940 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4940 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
4941 for b in opts['bookmark']:
4941 for b in opts['bookmark']:
4942 # translate -B options to -r so changesets get pushed
4942 # translate -B options to -r so changesets get pushed
4943 if b in repo._bookmarks:
4943 if b in repo._bookmarks:
4944 opts.setdefault('rev', []).append(b)
4944 opts.setdefault('rev', []).append(b)
4945 else:
4945 else:
4946 # if we try to push a deleted bookmark, translate it to null
4946 # if we try to push a deleted bookmark, translate it to null
4947 # this lets simultaneous -r, -b options continue working
4947 # this lets simultaneous -r, -b options continue working
4948 opts.setdefault('rev', []).append("null")
4948 opts.setdefault('rev', []).append("null")
4949
4949
4950 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4950 dest = ui.expandpath(dest or 'default-push', dest or 'default')
4951 dest, branches = hg.parseurl(dest, opts.get('branch'))
4951 dest, branches = hg.parseurl(dest, opts.get('branch'))
4952 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4952 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
4953 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4953 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
4954 try:
4954 try:
4955 other = hg.peer(repo, opts, dest)
4955 other = hg.peer(repo, opts, dest)
4956 except error.RepoError:
4956 except error.RepoError:
4957 if dest == "default-push":
4957 if dest == "default-push":
4958 raise util.Abort(_("default repository not configured!"),
4958 raise util.Abort(_("default repository not configured!"),
4959 hint=_('see the "path" section in "hg help config"'))
4959 hint=_('see the "path" section in "hg help config"'))
4960 else:
4960 else:
4961 raise
4961 raise
4962
4962
4963 if revs:
4963 if revs:
4964 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4964 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
4965
4965
4966 repo._subtoppath = dest
4966 repo._subtoppath = dest
4967 try:
4967 try:
4968 # push subrepos depth-first for coherent ordering
4968 # push subrepos depth-first for coherent ordering
4969 c = repo['']
4969 c = repo['']
4970 subs = c.substate # only repos that are committed
4970 subs = c.substate # only repos that are committed
4971 for s in sorted(subs):
4971 for s in sorted(subs):
4972 result = c.sub(s).push(opts)
4972 result = c.sub(s).push(opts)
4973 if result == 0:
4973 if result == 0:
4974 return not result
4974 return not result
4975 finally:
4975 finally:
4976 del repo._subtoppath
4976 del repo._subtoppath
4977 result = repo.push(other, opts.get('force'), revs=revs,
4977 result = repo.push(other, opts.get('force'), revs=revs,
4978 newbranch=opts.get('new_branch'))
4978 newbranch=opts.get('new_branch'))
4979
4979
4980 result = not result
4980 result = not result
4981
4981
4982 if opts.get('bookmark'):
4982 if opts.get('bookmark'):
4983 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4983 bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
4984 if bresult == 2:
4984 if bresult == 2:
4985 return 2
4985 return 2
4986 if not result and bresult:
4986 if not result and bresult:
4987 result = 2
4987 result = 2
4988
4988
4989 return result
4989 return result
4990
4990
4991 @command('recover', [])
4991 @command('recover', [])
4992 def recover(ui, repo):
4992 def recover(ui, repo):
4993 """roll back an interrupted transaction
4993 """roll back an interrupted transaction
4994
4994
4995 Recover from an interrupted commit or pull.
4995 Recover from an interrupted commit or pull.
4996
4996
4997 This command tries to fix the repository status after an
4997 This command tries to fix the repository status after an
4998 interrupted operation. It should only be necessary when Mercurial
4998 interrupted operation. It should only be necessary when Mercurial
4999 suggests it.
4999 suggests it.
5000
5000
5001 Returns 0 if successful, 1 if nothing to recover or verify fails.
5001 Returns 0 if successful, 1 if nothing to recover or verify fails.
5002 """
5002 """
5003 if repo.recover():
5003 if repo.recover():
5004 return hg.verify(repo)
5004 return hg.verify(repo)
5005 return 1
5005 return 1
5006
5006
5007 @command('^remove|rm',
5007 @command('^remove|rm',
5008 [('A', 'after', None, _('record delete for missing files')),
5008 [('A', 'after', None, _('record delete for missing files')),
5009 ('f', 'force', None,
5009 ('f', 'force', None,
5010 _('remove (and delete) file even if added or modified')),
5010 _('remove (and delete) file even if added or modified')),
5011 ] + walkopts,
5011 ] + walkopts,
5012 _('[OPTION]... FILE...'),
5012 _('[OPTION]... FILE...'),
5013 inferrepo=True)
5013 inferrepo=True)
5014 def remove(ui, repo, *pats, **opts):
5014 def remove(ui, repo, *pats, **opts):
5015 """remove the specified files on the next commit
5015 """remove the specified files on the next commit
5016
5016
5017 Schedule the indicated files for removal from the current branch.
5017 Schedule the indicated files for removal from the current branch.
5018
5018
5019 This command schedules the files to be removed at the next commit.
5019 This command schedules the files to be removed at the next commit.
5020 To undo a remove before that, see :hg:`revert`. To undo added
5020 To undo a remove before that, see :hg:`revert`. To undo added
5021 files, see :hg:`forget`.
5021 files, see :hg:`forget`.
5022
5022
5023 .. container:: verbose
5023 .. container:: verbose
5024
5024
5025 -A/--after can be used to remove only files that have already
5025 -A/--after can be used to remove only files that have already
5026 been deleted, -f/--force can be used to force deletion, and -Af
5026 been deleted, -f/--force can be used to force deletion, and -Af
5027 can be used to remove files from the next revision without
5027 can be used to remove files from the next revision without
5028 deleting them from the working directory.
5028 deleting them from the working directory.
5029
5029
5030 The following table details the behavior of remove for different
5030 The following table details the behavior of remove for different
5031 file states (columns) and option combinations (rows). The file
5031 file states (columns) and option combinations (rows). The file
5032 states are Added [A], Clean [C], Modified [M] and Missing [!]
5032 states are Added [A], Clean [C], Modified [M] and Missing [!]
5033 (as reported by :hg:`status`). The actions are Warn, Remove
5033 (as reported by :hg:`status`). The actions are Warn, Remove
5034 (from branch) and Delete (from disk):
5034 (from branch) and Delete (from disk):
5035
5035
5036 ========= == == == ==
5036 ========= == == == ==
5037 opt/state A C M !
5037 opt/state A C M !
5038 ========= == == == ==
5038 ========= == == == ==
5039 none W RD W R
5039 none W RD W R
5040 -f R RD RD R
5040 -f R RD RD R
5041 -A W W W R
5041 -A W W W R
5042 -Af R R R R
5042 -Af R R R R
5043 ========= == == == ==
5043 ========= == == == ==
5044
5044
5045 Note that remove never deletes files in Added [A] state from the
5045 Note that remove never deletes files in Added [A] state from the
5046 working directory, not even if option --force is specified.
5046 working directory, not even if option --force is specified.
5047
5047
5048 Returns 0 on success, 1 if any warnings encountered.
5048 Returns 0 on success, 1 if any warnings encountered.
5049 """
5049 """
5050
5050
5051 ret = 0
5051 ret = 0
5052 after, force = opts.get('after'), opts.get('force')
5052 after, force = opts.get('after'), opts.get('force')
5053 if not pats and not after:
5053 if not pats and not after:
5054 raise util.Abort(_('no files specified'))
5054 raise util.Abort(_('no files specified'))
5055
5055
5056 m = scmutil.match(repo[None], pats, opts)
5056 m = scmutil.match(repo[None], pats, opts)
5057 s = repo.status(match=m, clean=True)
5057 s = repo.status(match=m, clean=True)
5058 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5058 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
5059
5059
5060 # warn about failure to delete explicit files/dirs
5060 # warn about failure to delete explicit files/dirs
5061 wctx = repo[None]
5061 wctx = repo[None]
5062 for f in m.files():
5062 for f in m.files():
5063 if f in repo.dirstate or f in wctx.dirs():
5063 if f in repo.dirstate or f in wctx.dirs():
5064 continue
5064 continue
5065 if os.path.exists(m.rel(f)):
5065 if os.path.exists(m.rel(f)):
5066 if os.path.isdir(m.rel(f)):
5066 if os.path.isdir(m.rel(f)):
5067 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5067 ui.warn(_('not removing %s: no tracked files\n') % m.rel(f))
5068 else:
5068 else:
5069 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5069 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
5070 # missing files will generate a warning elsewhere
5070 # missing files will generate a warning elsewhere
5071 ret = 1
5071 ret = 1
5072
5072
5073 if force:
5073 if force:
5074 list = modified + deleted + clean + added
5074 list = modified + deleted + clean + added
5075 elif after:
5075 elif after:
5076 list = deleted
5076 list = deleted
5077 for f in modified + added + clean:
5077 for f in modified + added + clean:
5078 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5078 ui.warn(_('not removing %s: file still exists\n') % m.rel(f))
5079 ret = 1
5079 ret = 1
5080 else:
5080 else:
5081 list = deleted + clean
5081 list = deleted + clean
5082 for f in modified:
5082 for f in modified:
5083 ui.warn(_('not removing %s: file is modified (use -f'
5083 ui.warn(_('not removing %s: file is modified (use -f'
5084 ' to force removal)\n') % m.rel(f))
5084 ' to force removal)\n') % m.rel(f))
5085 ret = 1
5085 ret = 1
5086 for f in added:
5086 for f in added:
5087 ui.warn(_('not removing %s: file has been marked for add'
5087 ui.warn(_('not removing %s: file has been marked for add'
5088 ' (use forget to undo)\n') % m.rel(f))
5088 ' (use forget to undo)\n') % m.rel(f))
5089 ret = 1
5089 ret = 1
5090
5090
5091 for f in sorted(list):
5091 for f in sorted(list):
5092 if ui.verbose or not m.exact(f):
5092 if ui.verbose or not m.exact(f):
5093 ui.status(_('removing %s\n') % m.rel(f))
5093 ui.status(_('removing %s\n') % m.rel(f))
5094
5094
5095 wlock = repo.wlock()
5095 wlock = repo.wlock()
5096 try:
5096 try:
5097 if not after:
5097 if not after:
5098 for f in list:
5098 for f in list:
5099 if f in added:
5099 if f in added:
5100 continue # we never unlink added files on remove
5100 continue # we never unlink added files on remove
5101 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5101 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
5102 repo[None].forget(list)
5102 repo[None].forget(list)
5103 finally:
5103 finally:
5104 wlock.release()
5104 wlock.release()
5105
5105
5106 return ret
5106 return ret
5107
5107
5108 @command('rename|move|mv',
5108 @command('rename|move|mv',
5109 [('A', 'after', None, _('record a rename that has already occurred')),
5109 [('A', 'after', None, _('record a rename that has already occurred')),
5110 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5110 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5111 ] + walkopts + dryrunopts,
5111 ] + walkopts + dryrunopts,
5112 _('[OPTION]... SOURCE... DEST'))
5112 _('[OPTION]... SOURCE... DEST'))
5113 def rename(ui, repo, *pats, **opts):
5113 def rename(ui, repo, *pats, **opts):
5114 """rename files; equivalent of copy + remove
5114 """rename files; equivalent of copy + remove
5115
5115
5116 Mark dest as copies of sources; mark sources for deletion. If dest
5116 Mark dest as copies of sources; mark sources for deletion. If dest
5117 is a directory, copies are put in that directory. If dest is a
5117 is a directory, copies are put in that directory. If dest is a
5118 file, there can only be one source.
5118 file, there can only be one source.
5119
5119
5120 By default, this command copies the contents of files as they
5120 By default, this command copies the contents of files as they
5121 exist in the working directory. If invoked with -A/--after, the
5121 exist in the working directory. If invoked with -A/--after, the
5122 operation is recorded, but no copying is performed.
5122 operation is recorded, but no copying is performed.
5123
5123
5124 This command takes effect at the next commit. To undo a rename
5124 This command takes effect at the next commit. To undo a rename
5125 before that, see :hg:`revert`.
5125 before that, see :hg:`revert`.
5126
5126
5127 Returns 0 on success, 1 if errors are encountered.
5127 Returns 0 on success, 1 if errors are encountered.
5128 """
5128 """
5129 wlock = repo.wlock(False)
5129 wlock = repo.wlock(False)
5130 try:
5130 try:
5131 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5131 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5132 finally:
5132 finally:
5133 wlock.release()
5133 wlock.release()
5134
5134
5135 @command('resolve',
5135 @command('resolve',
5136 [('a', 'all', None, _('select all unresolved files')),
5136 [('a', 'all', None, _('select all unresolved files')),
5137 ('l', 'list', None, _('list state of files needing merge')),
5137 ('l', 'list', None, _('list state of files needing merge')),
5138 ('m', 'mark', None, _('mark files as resolved')),
5138 ('m', 'mark', None, _('mark files as resolved')),
5139 ('u', 'unmark', None, _('mark files as unresolved')),
5139 ('u', 'unmark', None, _('mark files as unresolved')),
5140 ('n', 'no-status', None, _('hide status prefix'))]
5140 ('n', 'no-status', None, _('hide status prefix'))]
5141 + mergetoolopts + walkopts,
5141 + mergetoolopts + walkopts,
5142 _('[OPTION]... [FILE]...'),
5142 _('[OPTION]... [FILE]...'),
5143 inferrepo=True)
5143 inferrepo=True)
5144 def resolve(ui, repo, *pats, **opts):
5144 def resolve(ui, repo, *pats, **opts):
5145 """redo merges or set/view the merge status of files
5145 """redo merges or set/view the merge status of files
5146
5146
5147 Merges with unresolved conflicts are often the result of
5147 Merges with unresolved conflicts are often the result of
5148 non-interactive merging using the ``internal:merge`` configuration
5148 non-interactive merging using the ``internal:merge`` configuration
5149 setting, or a command-line merge tool like ``diff3``. The resolve
5149 setting, or a command-line merge tool like ``diff3``. The resolve
5150 command is used to manage the files involved in a merge, after
5150 command is used to manage the files involved in a merge, after
5151 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5151 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5152 working directory must have two parents). See :hg:`help
5152 working directory must have two parents). See :hg:`help
5153 merge-tools` for information on configuring merge tools.
5153 merge-tools` for information on configuring merge tools.
5154
5154
5155 The resolve command can be used in the following ways:
5155 The resolve command can be used in the following ways:
5156
5156
5157 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5157 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5158 files, discarding any previous merge attempts. Re-merging is not
5158 files, discarding any previous merge attempts. Re-merging is not
5159 performed for files already marked as resolved. Use ``--all/-a``
5159 performed for files already marked as resolved. Use ``--all/-a``
5160 to select all unresolved files. ``--tool`` can be used to specify
5160 to select all unresolved files. ``--tool`` can be used to specify
5161 the merge tool used for the given files. It overrides the HGMERGE
5161 the merge tool used for the given files. It overrides the HGMERGE
5162 environment variable and your configuration files. Previous file
5162 environment variable and your configuration files. Previous file
5163 contents are saved with a ``.orig`` suffix.
5163 contents are saved with a ``.orig`` suffix.
5164
5164
5165 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5165 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5166 (e.g. after having manually fixed-up the files). The default is
5166 (e.g. after having manually fixed-up the files). The default is
5167 to mark all unresolved files.
5167 to mark all unresolved files.
5168
5168
5169 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5169 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5170 default is to mark all resolved files.
5170 default is to mark all resolved files.
5171
5171
5172 - :hg:`resolve -l`: list files which had or still have conflicts.
5172 - :hg:`resolve -l`: list files which had or still have conflicts.
5173 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5173 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5174
5174
5175 Note that Mercurial will not let you commit files with unresolved
5175 Note that Mercurial will not let you commit files with unresolved
5176 merge conflicts. You must use :hg:`resolve -m ...` before you can
5176 merge conflicts. You must use :hg:`resolve -m ...` before you can
5177 commit after a conflicting merge.
5177 commit after a conflicting merge.
5178
5178
5179 Returns 0 on success, 1 if any files fail a resolve attempt.
5179 Returns 0 on success, 1 if any files fail a resolve attempt.
5180 """
5180 """
5181
5181
5182 all, mark, unmark, show, nostatus = \
5182 all, mark, unmark, show, nostatus = \
5183 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5183 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5184
5184
5185 if (show and (mark or unmark)) or (mark and unmark):
5185 if (show and (mark or unmark)) or (mark and unmark):
5186 raise util.Abort(_("too many options specified"))
5186 raise util.Abort(_("too many options specified"))
5187 if pats and all:
5187 if pats and all:
5188 raise util.Abort(_("can't specify --all and patterns"))
5188 raise util.Abort(_("can't specify --all and patterns"))
5189 if not (all or pats or show or mark or unmark):
5189 if not (all or pats or show or mark or unmark):
5190 raise util.Abort(_('no files or directories specified'),
5190 raise util.Abort(_('no files or directories specified'),
5191 hint=('use --all to remerge all files'))
5191 hint=('use --all to remerge all files'))
5192
5192
5193 wlock = repo.wlock()
5193 wlock = repo.wlock()
5194 try:
5194 try:
5195 ms = mergemod.mergestate(repo)
5195 ms = mergemod.mergestate(repo)
5196
5196
5197 if not ms.active() and not show:
5197 if not ms.active() and not show:
5198 raise util.Abort(
5198 raise util.Abort(
5199 _('resolve command not applicable when not merging'))
5199 _('resolve command not applicable when not merging'))
5200
5200
5201 m = scmutil.match(repo[None], pats, opts)
5201 m = scmutil.match(repo[None], pats, opts)
5202 ret = 0
5202 ret = 0
5203 didwork = False
5203 didwork = False
5204
5204
5205 for f in ms:
5205 for f in ms:
5206 if not m(f):
5206 if not m(f):
5207 continue
5207 continue
5208
5208
5209 didwork = True
5209 didwork = True
5210
5210
5211 if show:
5211 if show:
5212 if nostatus:
5212 if nostatus:
5213 ui.write("%s\n" % f)
5213 ui.write("%s\n" % f)
5214 else:
5214 else:
5215 ui.write("%s %s\n" % (ms[f].upper(), f),
5215 ui.write("%s %s\n" % (ms[f].upper(), f),
5216 label='resolve.' +
5216 label='resolve.' +
5217 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5217 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
5218 elif mark:
5218 elif mark:
5219 ms.mark(f, "r")
5219 ms.mark(f, "r")
5220 elif unmark:
5220 elif unmark:
5221 ms.mark(f, "u")
5221 ms.mark(f, "u")
5222 else:
5222 else:
5223 wctx = repo[None]
5223 wctx = repo[None]
5224
5224
5225 # backup pre-resolve (merge uses .orig for its own purposes)
5225 # backup pre-resolve (merge uses .orig for its own purposes)
5226 a = repo.wjoin(f)
5226 a = repo.wjoin(f)
5227 util.copyfile(a, a + ".resolve")
5227 util.copyfile(a, a + ".resolve")
5228
5228
5229 try:
5229 try:
5230 # resolve file
5230 # resolve file
5231 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5231 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5232 'resolve')
5232 'resolve')
5233 if ms.resolve(f, wctx):
5233 if ms.resolve(f, wctx):
5234 ret = 1
5234 ret = 1
5235 finally:
5235 finally:
5236 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5236 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5237 ms.commit()
5237 ms.commit()
5238
5238
5239 # replace filemerge's .orig file with our resolve file
5239 # replace filemerge's .orig file with our resolve file
5240 util.rename(a + ".resolve", a + ".orig")
5240 util.rename(a + ".resolve", a + ".orig")
5241
5241
5242 ms.commit()
5242 ms.commit()
5243
5243
5244 if not didwork and pats:
5244 if not didwork and pats:
5245 ui.warn(_("arguments do not match paths that need resolving\n"))
5245 ui.warn(_("arguments do not match paths that need resolving\n"))
5246
5246
5247 finally:
5247 finally:
5248 wlock.release()
5248 wlock.release()
5249
5249
5250 # Nudge users into finishing an unfinished operation. We don't print
5250 # Nudge users into finishing an unfinished operation. We don't print
5251 # this with the list/show operation because we want list/show to remain
5251 # this with the list/show operation because we want list/show to remain
5252 # machine readable.
5252 # machine readable.
5253 if not list(ms.unresolved()) and not show:
5253 if not list(ms.unresolved()) and not show:
5254 ui.status(_('(no more unresolved files)\n'))
5254 ui.status(_('(no more unresolved files)\n'))
5255
5255
5256 return ret
5256 return ret
5257
5257
5258 @command('revert',
5258 @command('revert',
5259 [('a', 'all', None, _('revert all changes when no arguments given')),
5259 [('a', 'all', None, _('revert all changes when no arguments given')),
5260 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5260 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5261 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5261 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5262 ('C', 'no-backup', None, _('do not save backup copies of files')),
5262 ('C', 'no-backup', None, _('do not save backup copies of files')),
5263 ] + walkopts + dryrunopts,
5263 ] + walkopts + dryrunopts,
5264 _('[OPTION]... [-r REV] [NAME]...'))
5264 _('[OPTION]... [-r REV] [NAME]...'))
5265 def revert(ui, repo, *pats, **opts):
5265 def revert(ui, repo, *pats, **opts):
5266 """restore files to their checkout state
5266 """restore files to their checkout state
5267
5267
5268 .. note::
5268 .. note::
5269
5269
5270 To check out earlier revisions, you should use :hg:`update REV`.
5270 To check out earlier revisions, you should use :hg:`update REV`.
5271 To cancel an uncommitted merge (and lose your changes),
5271 To cancel an uncommitted merge (and lose your changes),
5272 use :hg:`update --clean .`.
5272 use :hg:`update --clean .`.
5273
5273
5274 With no revision specified, revert the specified files or directories
5274 With no revision specified, revert the specified files or directories
5275 to the contents they had in the parent of the working directory.
5275 to the contents they had in the parent of the working directory.
5276 This restores the contents of files to an unmodified
5276 This restores the contents of files to an unmodified
5277 state and unschedules adds, removes, copies, and renames. If the
5277 state and unschedules adds, removes, copies, and renames. If the
5278 working directory has two parents, you must explicitly specify a
5278 working directory has two parents, you must explicitly specify a
5279 revision.
5279 revision.
5280
5280
5281 Using the -r/--rev or -d/--date options, revert the given files or
5281 Using the -r/--rev or -d/--date options, revert the given files or
5282 directories to their states as of a specific revision. Because
5282 directories to their states as of a specific revision. Because
5283 revert does not change the working directory parents, this will
5283 revert does not change the working directory parents, this will
5284 cause these files to appear modified. This can be helpful to "back
5284 cause these files to appear modified. This can be helpful to "back
5285 out" some or all of an earlier change. See :hg:`backout` for a
5285 out" some or all of an earlier change. See :hg:`backout` for a
5286 related method.
5286 related method.
5287
5287
5288 Modified files are saved with a .orig suffix before reverting.
5288 Modified files are saved with a .orig suffix before reverting.
5289 To disable these backups, use --no-backup.
5289 To disable these backups, use --no-backup.
5290
5290
5291 See :hg:`help dates` for a list of formats valid for -d/--date.
5291 See :hg:`help dates` for a list of formats valid for -d/--date.
5292
5292
5293 Returns 0 on success.
5293 Returns 0 on success.
5294 """
5294 """
5295
5295
5296 if opts.get("date"):
5296 if opts.get("date"):
5297 if opts.get("rev"):
5297 if opts.get("rev"):
5298 raise util.Abort(_("you can't specify a revision and a date"))
5298 raise util.Abort(_("you can't specify a revision and a date"))
5299 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5299 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5300
5300
5301 parent, p2 = repo.dirstate.parents()
5301 parent, p2 = repo.dirstate.parents()
5302 if not opts.get('rev') and p2 != nullid:
5302 if not opts.get('rev') and p2 != nullid:
5303 # revert after merge is a trap for new users (issue2915)
5303 # revert after merge is a trap for new users (issue2915)
5304 raise util.Abort(_('uncommitted merge with no revision specified'),
5304 raise util.Abort(_('uncommitted merge with no revision specified'),
5305 hint=_('use "hg update" or see "hg help revert"'))
5305 hint=_('use "hg update" or see "hg help revert"'))
5306
5306
5307 ctx = scmutil.revsingle(repo, opts.get('rev'))
5307 ctx = scmutil.revsingle(repo, opts.get('rev'))
5308
5308
5309 if not pats and not opts.get('all'):
5309 if not pats and not opts.get('all'):
5310 msg = _("no files or directories specified")
5310 msg = _("no files or directories specified")
5311 if p2 != nullid:
5311 if p2 != nullid:
5312 hint = _("uncommitted merge, use --all to discard all changes,"
5312 hint = _("uncommitted merge, use --all to discard all changes,"
5313 " or 'hg update -C .' to abort the merge")
5313 " or 'hg update -C .' to abort the merge")
5314 raise util.Abort(msg, hint=hint)
5314 raise util.Abort(msg, hint=hint)
5315 dirty = util.any(repo.status())
5315 dirty = util.any(repo.status())
5316 node = ctx.node()
5316 node = ctx.node()
5317 if node != parent:
5317 if node != parent:
5318 if dirty:
5318 if dirty:
5319 hint = _("uncommitted changes, use --all to discard all"
5319 hint = _("uncommitted changes, use --all to discard all"
5320 " changes, or 'hg update %s' to update") % ctx.rev()
5320 " changes, or 'hg update %s' to update") % ctx.rev()
5321 else:
5321 else:
5322 hint = _("use --all to revert all files,"
5322 hint = _("use --all to revert all files,"
5323 " or 'hg update %s' to update") % ctx.rev()
5323 " or 'hg update %s' to update") % ctx.rev()
5324 elif dirty:
5324 elif dirty:
5325 hint = _("uncommitted changes, use --all to discard all changes")
5325 hint = _("uncommitted changes, use --all to discard all changes")
5326 else:
5326 else:
5327 hint = _("use --all to revert all files")
5327 hint = _("use --all to revert all files")
5328 raise util.Abort(msg, hint=hint)
5328 raise util.Abort(msg, hint=hint)
5329
5329
5330 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5330 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5331
5331
5332 @command('rollback', dryrunopts +
5332 @command('rollback', dryrunopts +
5333 [('f', 'force', False, _('ignore safety measures'))])
5333 [('f', 'force', False, _('ignore safety measures'))])
5334 def rollback(ui, repo, **opts):
5334 def rollback(ui, repo, **opts):
5335 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5335 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5336
5336
5337 Please use :hg:`commit --amend` instead of rollback to correct
5337 Please use :hg:`commit --amend` instead of rollback to correct
5338 mistakes in the last commit.
5338 mistakes in the last commit.
5339
5339
5340 This command should be used with care. There is only one level of
5340 This command should be used with care. There is only one level of
5341 rollback, and there is no way to undo a rollback. It will also
5341 rollback, and there is no way to undo a rollback. It will also
5342 restore the dirstate at the time of the last transaction, losing
5342 restore the dirstate at the time of the last transaction, losing
5343 any dirstate changes since that time. This command does not alter
5343 any dirstate changes since that time. This command does not alter
5344 the working directory.
5344 the working directory.
5345
5345
5346 Transactions are used to encapsulate the effects of all commands
5346 Transactions are used to encapsulate the effects of all commands
5347 that create new changesets or propagate existing changesets into a
5347 that create new changesets or propagate existing changesets into a
5348 repository.
5348 repository.
5349
5349
5350 .. container:: verbose
5350 .. container:: verbose
5351
5351
5352 For example, the following commands are transactional, and their
5352 For example, the following commands are transactional, and their
5353 effects can be rolled back:
5353 effects can be rolled back:
5354
5354
5355 - commit
5355 - commit
5356 - import
5356 - import
5357 - pull
5357 - pull
5358 - push (with this repository as the destination)
5358 - push (with this repository as the destination)
5359 - unbundle
5359 - unbundle
5360
5360
5361 To avoid permanent data loss, rollback will refuse to rollback a
5361 To avoid permanent data loss, rollback will refuse to rollback a
5362 commit transaction if it isn't checked out. Use --force to
5362 commit transaction if it isn't checked out. Use --force to
5363 override this protection.
5363 override this protection.
5364
5364
5365 This command is not intended for use on public repositories. Once
5365 This command is not intended for use on public repositories. Once
5366 changes are visible for pull by other users, rolling a transaction
5366 changes are visible for pull by other users, rolling a transaction
5367 back locally is ineffective (someone else may already have pulled
5367 back locally is ineffective (someone else may already have pulled
5368 the changes). Furthermore, a race is possible with readers of the
5368 the changes). Furthermore, a race is possible with readers of the
5369 repository; for example an in-progress pull from the repository
5369 repository; for example an in-progress pull from the repository
5370 may fail if a rollback is performed.
5370 may fail if a rollback is performed.
5371
5371
5372 Returns 0 on success, 1 if no rollback data is available.
5372 Returns 0 on success, 1 if no rollback data is available.
5373 """
5373 """
5374 return repo.rollback(dryrun=opts.get('dry_run'),
5374 return repo.rollback(dryrun=opts.get('dry_run'),
5375 force=opts.get('force'))
5375 force=opts.get('force'))
5376
5376
5377 @command('root', [])
5377 @command('root', [])
5378 def root(ui, repo):
5378 def root(ui, repo):
5379 """print the root (top) of the current working directory
5379 """print the root (top) of the current working directory
5380
5380
5381 Print the root directory of the current repository.
5381 Print the root directory of the current repository.
5382
5382
5383 Returns 0 on success.
5383 Returns 0 on success.
5384 """
5384 """
5385 ui.write(repo.root + "\n")
5385 ui.write(repo.root + "\n")
5386
5386
5387 @command('^serve',
5387 @command('^serve',
5388 [('A', 'accesslog', '', _('name of access log file to write to'),
5388 [('A', 'accesslog', '', _('name of access log file to write to'),
5389 _('FILE')),
5389 _('FILE')),
5390 ('d', 'daemon', None, _('run server in background')),
5390 ('d', 'daemon', None, _('run server in background')),
5391 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5391 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('NUM')),
5392 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5392 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5393 # use string type, then we can check if something was passed
5393 # use string type, then we can check if something was passed
5394 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5394 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5395 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5395 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5396 _('ADDR')),
5396 _('ADDR')),
5397 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5397 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5398 _('PREFIX')),
5398 _('PREFIX')),
5399 ('n', 'name', '',
5399 ('n', 'name', '',
5400 _('name to show in web pages (default: working directory)'), _('NAME')),
5400 _('name to show in web pages (default: working directory)'), _('NAME')),
5401 ('', 'web-conf', '',
5401 ('', 'web-conf', '',
5402 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5402 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5403 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5403 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5404 _('FILE')),
5404 _('FILE')),
5405 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5405 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5406 ('', 'stdio', None, _('for remote clients')),
5406 ('', 'stdio', None, _('for remote clients')),
5407 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5407 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5408 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5408 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5409 ('', 'style', '', _('template style to use'), _('STYLE')),
5409 ('', 'style', '', _('template style to use'), _('STYLE')),
5410 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5410 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5411 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5411 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5412 _('[OPTION]...'),
5412 _('[OPTION]...'),
5413 optionalrepo=True)
5413 optionalrepo=True)
5414 def serve(ui, repo, **opts):
5414 def serve(ui, repo, **opts):
5415 """start stand-alone webserver
5415 """start stand-alone webserver
5416
5416
5417 Start a local HTTP repository browser and pull server. You can use
5417 Start a local HTTP repository browser and pull server. You can use
5418 this for ad-hoc sharing and browsing of repositories. It is
5418 this for ad-hoc sharing and browsing of repositories. It is
5419 recommended to use a real web server to serve a repository for
5419 recommended to use a real web server to serve a repository for
5420 longer periods of time.
5420 longer periods of time.
5421
5421
5422 Please note that the server does not implement access control.
5422 Please note that the server does not implement access control.
5423 This means that, by default, anybody can read from the server and
5423 This means that, by default, anybody can read from the server and
5424 nobody can write to it by default. Set the ``web.allow_push``
5424 nobody can write to it by default. Set the ``web.allow_push``
5425 option to ``*`` to allow everybody to push to the server. You
5425 option to ``*`` to allow everybody to push to the server. You
5426 should use a real web server if you need to authenticate users.
5426 should use a real web server if you need to authenticate users.
5427
5427
5428 By default, the server logs accesses to stdout and errors to
5428 By default, the server logs accesses to stdout and errors to
5429 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5429 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5430 files.
5430 files.
5431
5431
5432 To have the server choose a free port number to listen on, specify
5432 To have the server choose a free port number to listen on, specify
5433 a port number of 0; in this case, the server will print the port
5433 a port number of 0; in this case, the server will print the port
5434 number it uses.
5434 number it uses.
5435
5435
5436 Returns 0 on success.
5436 Returns 0 on success.
5437 """
5437 """
5438
5438
5439 if opts["stdio"] and opts["cmdserver"]:
5439 if opts["stdio"] and opts["cmdserver"]:
5440 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5440 raise util.Abort(_("cannot use --stdio with --cmdserver"))
5441
5441
5442 if opts["stdio"]:
5442 if opts["stdio"]:
5443 if repo is None:
5443 if repo is None:
5444 raise error.RepoError(_("there is no Mercurial repository here"
5444 raise error.RepoError(_("there is no Mercurial repository here"
5445 " (.hg not found)"))
5445 " (.hg not found)"))
5446 s = sshserver.sshserver(ui, repo)
5446 s = sshserver.sshserver(ui, repo)
5447 s.serve_forever()
5447 s.serve_forever()
5448
5448
5449 if opts["cmdserver"]:
5449 if opts["cmdserver"]:
5450 s = commandserver.server(ui, repo, opts["cmdserver"])
5450 s = commandserver.server(ui, repo, opts["cmdserver"])
5451 return s.serve()
5451 return s.serve()
5452
5452
5453 # this way we can check if something was given in the command-line
5453 # this way we can check if something was given in the command-line
5454 if opts.get('port'):
5454 if opts.get('port'):
5455 opts['port'] = util.getport(opts.get('port'))
5455 opts['port'] = util.getport(opts.get('port'))
5456
5456
5457 baseui = repo and repo.baseui or ui
5457 baseui = repo and repo.baseui or ui
5458 optlist = ("name templates style address port prefix ipv6"
5458 optlist = ("name templates style address port prefix ipv6"
5459 " accesslog errorlog certificate encoding")
5459 " accesslog errorlog certificate encoding")
5460 for o in optlist.split():
5460 for o in optlist.split():
5461 val = opts.get(o, '')
5461 val = opts.get(o, '')
5462 if val in (None, ''): # should check against default options instead
5462 if val in (None, ''): # should check against default options instead
5463 continue
5463 continue
5464 baseui.setconfig("web", o, val, 'serve')
5464 baseui.setconfig("web", o, val, 'serve')
5465 if repo and repo.ui != baseui:
5465 if repo and repo.ui != baseui:
5466 repo.ui.setconfig("web", o, val, 'serve')
5466 repo.ui.setconfig("web", o, val, 'serve')
5467
5467
5468 o = opts.get('web_conf') or opts.get('webdir_conf')
5468 o = opts.get('web_conf') or opts.get('webdir_conf')
5469 if not o:
5469 if not o:
5470 if not repo:
5470 if not repo:
5471 raise error.RepoError(_("there is no Mercurial repository"
5471 raise error.RepoError(_("there is no Mercurial repository"
5472 " here (.hg not found)"))
5472 " here (.hg not found)"))
5473 o = repo
5473 o = repo
5474
5474
5475 app = hgweb.hgweb(o, baseui=baseui)
5475 app = hgweb.hgweb(o, baseui=baseui)
5476 service = httpservice(ui, app, opts)
5476 service = httpservice(ui, app, opts)
5477 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5477 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5478
5478
5479 class httpservice(object):
5479 class httpservice(object):
5480 def __init__(self, ui, app, opts):
5480 def __init__(self, ui, app, opts):
5481 self.ui = ui
5481 self.ui = ui
5482 self.app = app
5482 self.app = app
5483 self.opts = opts
5483 self.opts = opts
5484
5484
5485 def init(self):
5485 def init(self):
5486 util.setsignalhandler()
5486 util.setsignalhandler()
5487 self.httpd = hgweb_server.create_server(self.ui, self.app)
5487 self.httpd = hgweb_server.create_server(self.ui, self.app)
5488
5488
5489 if self.opts['port'] and not self.ui.verbose:
5489 if self.opts['port'] and not self.ui.verbose:
5490 return
5490 return
5491
5491
5492 if self.httpd.prefix:
5492 if self.httpd.prefix:
5493 prefix = self.httpd.prefix.strip('/') + '/'
5493 prefix = self.httpd.prefix.strip('/') + '/'
5494 else:
5494 else:
5495 prefix = ''
5495 prefix = ''
5496
5496
5497 port = ':%d' % self.httpd.port
5497 port = ':%d' % self.httpd.port
5498 if port == ':80':
5498 if port == ':80':
5499 port = ''
5499 port = ''
5500
5500
5501 bindaddr = self.httpd.addr
5501 bindaddr = self.httpd.addr
5502 if bindaddr == '0.0.0.0':
5502 if bindaddr == '0.0.0.0':
5503 bindaddr = '*'
5503 bindaddr = '*'
5504 elif ':' in bindaddr: # IPv6
5504 elif ':' in bindaddr: # IPv6
5505 bindaddr = '[%s]' % bindaddr
5505 bindaddr = '[%s]' % bindaddr
5506
5506
5507 fqaddr = self.httpd.fqaddr
5507 fqaddr = self.httpd.fqaddr
5508 if ':' in fqaddr:
5508 if ':' in fqaddr:
5509 fqaddr = '[%s]' % fqaddr
5509 fqaddr = '[%s]' % fqaddr
5510 if self.opts['port']:
5510 if self.opts['port']:
5511 write = self.ui.status
5511 write = self.ui.status
5512 else:
5512 else:
5513 write = self.ui.write
5513 write = self.ui.write
5514 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5514 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5515 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5515 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5516 self.ui.flush() # avoid buffering of status message
5516 self.ui.flush() # avoid buffering of status message
5517
5517
5518 def run(self):
5518 def run(self):
5519 self.httpd.serve_forever()
5519 self.httpd.serve_forever()
5520
5520
5521
5521
5522 @command('^status|st',
5522 @command('^status|st',
5523 [('A', 'all', None, _('show status of all files')),
5523 [('A', 'all', None, _('show status of all files')),
5524 ('m', 'modified', None, _('show only modified files')),
5524 ('m', 'modified', None, _('show only modified files')),
5525 ('a', 'added', None, _('show only added files')),
5525 ('a', 'added', None, _('show only added files')),
5526 ('r', 'removed', None, _('show only removed files')),
5526 ('r', 'removed', None, _('show only removed files')),
5527 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5527 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5528 ('c', 'clean', None, _('show only files without changes')),
5528 ('c', 'clean', None, _('show only files without changes')),
5529 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5529 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5530 ('i', 'ignored', None, _('show only ignored files')),
5530 ('i', 'ignored', None, _('show only ignored files')),
5531 ('n', 'no-status', None, _('hide status prefix')),
5531 ('n', 'no-status', None, _('hide status prefix')),
5532 ('C', 'copies', None, _('show source of copied files')),
5532 ('C', 'copies', None, _('show source of copied files')),
5533 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5533 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
5534 ('', 'rev', [], _('show difference from revision'), _('REV')),
5534 ('', 'rev', [], _('show difference from revision'), _('REV')),
5535 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5535 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
5536 ] + walkopts + subrepoopts + formatteropts,
5536 ] + walkopts + subrepoopts + formatteropts,
5537 _('[OPTION]... [FILE]...'),
5537 _('[OPTION]... [FILE]...'),
5538 inferrepo=True)
5538 inferrepo=True)
5539 def status(ui, repo, *pats, **opts):
5539 def status(ui, repo, *pats, **opts):
5540 """show changed files in the working directory
5540 """show changed files in the working directory
5541
5541
5542 Show status of files in the repository. If names are given, only
5542 Show status of files in the repository. If names are given, only
5543 files that match are shown. Files that are clean or ignored or
5543 files that match are shown. Files that are clean or ignored or
5544 the source of a copy/move operation, are not listed unless
5544 the source of a copy/move operation, are not listed unless
5545 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5545 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
5546 Unless options described with "show only ..." are given, the
5546 Unless options described with "show only ..." are given, the
5547 options -mardu are used.
5547 options -mardu are used.
5548
5548
5549 Option -q/--quiet hides untracked (unknown and ignored) files
5549 Option -q/--quiet hides untracked (unknown and ignored) files
5550 unless explicitly requested with -u/--unknown or -i/--ignored.
5550 unless explicitly requested with -u/--unknown or -i/--ignored.
5551
5551
5552 .. note::
5552 .. note::
5553
5553
5554 status may appear to disagree with diff if permissions have
5554 status may appear to disagree with diff if permissions have
5555 changed or a merge has occurred. The standard diff format does
5555 changed or a merge has occurred. The standard diff format does
5556 not report permission changes and diff only reports changes
5556 not report permission changes and diff only reports changes
5557 relative to one merge parent.
5557 relative to one merge parent.
5558
5558
5559 If one revision is given, it is used as the base revision.
5559 If one revision is given, it is used as the base revision.
5560 If two revisions are given, the differences between them are
5560 If two revisions are given, the differences between them are
5561 shown. The --change option can also be used as a shortcut to list
5561 shown. The --change option can also be used as a shortcut to list
5562 the changed files of a revision from its first parent.
5562 the changed files of a revision from its first parent.
5563
5563
5564 The codes used to show the status of files are::
5564 The codes used to show the status of files are::
5565
5565
5566 M = modified
5566 M = modified
5567 A = added
5567 A = added
5568 R = removed
5568 R = removed
5569 C = clean
5569 C = clean
5570 ! = missing (deleted by non-hg command, but still tracked)
5570 ! = missing (deleted by non-hg command, but still tracked)
5571 ? = not tracked
5571 ? = not tracked
5572 I = ignored
5572 I = ignored
5573 = origin of the previous file (with --copies)
5573 = origin of the previous file (with --copies)
5574
5574
5575 .. container:: verbose
5575 .. container:: verbose
5576
5576
5577 Examples:
5577 Examples:
5578
5578
5579 - show changes in the working directory relative to a
5579 - show changes in the working directory relative to a
5580 changeset::
5580 changeset::
5581
5581
5582 hg status --rev 9353
5582 hg status --rev 9353
5583
5583
5584 - show all changes including copies in an existing changeset::
5584 - show all changes including copies in an existing changeset::
5585
5585
5586 hg status --copies --change 9353
5586 hg status --copies --change 9353
5587
5587
5588 - get a NUL separated list of added files, suitable for xargs::
5588 - get a NUL separated list of added files, suitable for xargs::
5589
5589
5590 hg status -an0
5590 hg status -an0
5591
5591
5592 Returns 0 on success.
5592 Returns 0 on success.
5593 """
5593 """
5594
5594
5595 revs = opts.get('rev')
5595 revs = opts.get('rev')
5596 change = opts.get('change')
5596 change = opts.get('change')
5597
5597
5598 if revs and change:
5598 if revs and change:
5599 msg = _('cannot specify --rev and --change at the same time')
5599 msg = _('cannot specify --rev and --change at the same time')
5600 raise util.Abort(msg)
5600 raise util.Abort(msg)
5601 elif change:
5601 elif change:
5602 node2 = scmutil.revsingle(repo, change, None).node()
5602 node2 = scmutil.revsingle(repo, change, None).node()
5603 node1 = repo[node2].p1().node()
5603 node1 = repo[node2].p1().node()
5604 else:
5604 else:
5605 node1, node2 = scmutil.revpair(repo, revs)
5605 node1, node2 = scmutil.revpair(repo, revs)
5606
5606
5607 cwd = (pats and repo.getcwd()) or ''
5607 cwd = (pats and repo.getcwd()) or ''
5608 end = opts.get('print0') and '\0' or '\n'
5608 end = opts.get('print0') and '\0' or '\n'
5609 copy = {}
5609 copy = {}
5610 states = 'modified added removed deleted unknown ignored clean'.split()
5610 states = 'modified added removed deleted unknown ignored clean'.split()
5611 show = [k for k in states if opts.get(k)]
5611 show = [k for k in states if opts.get(k)]
5612 if opts.get('all'):
5612 if opts.get('all'):
5613 show += ui.quiet and (states[:4] + ['clean']) or states
5613 show += ui.quiet and (states[:4] + ['clean']) or states
5614 if not show:
5614 if not show:
5615 show = ui.quiet and states[:4] or states[:5]
5615 show = ui.quiet and states[:4] or states[:5]
5616
5616
5617 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5617 stat = repo.status(node1, node2, scmutil.match(repo[node2], pats, opts),
5618 'ignored' in show, 'clean' in show, 'unknown' in show,
5618 'ignored' in show, 'clean' in show, 'unknown' in show,
5619 opts.get('subrepos'))
5619 opts.get('subrepos'))
5620 changestates = zip(states, 'MAR!?IC', stat)
5620 changestates = zip(states, 'MAR!?IC', stat)
5621
5621
5622 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5622 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
5623 copy = copies.pathcopies(repo[node1], repo[node2])
5623 copy = copies.pathcopies(repo[node1], repo[node2])
5624
5624
5625 fm = ui.formatter('status', opts)
5625 fm = ui.formatter('status', opts)
5626 fmt = '%s' + end
5626 fmt = '%s' + end
5627 showchar = not opts.get('no_status')
5627 showchar = not opts.get('no_status')
5628
5628
5629 for state, char, files in changestates:
5629 for state, char, files in changestates:
5630 if state in show:
5630 if state in show:
5631 label = 'status.' + state
5631 label = 'status.' + state
5632 for f in files:
5632 for f in files:
5633 fm.startitem()
5633 fm.startitem()
5634 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5634 fm.condwrite(showchar, 'status', '%s ', char, label=label)
5635 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5635 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
5636 if f in copy:
5636 if f in copy:
5637 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5637 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
5638 label='status.copied')
5638 label='status.copied')
5639 fm.end()
5639 fm.end()
5640
5640
5641 @command('^summary|sum',
5641 @command('^summary|sum',
5642 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5642 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
5643 def summary(ui, repo, **opts):
5643 def summary(ui, repo, **opts):
5644 """summarize working directory state
5644 """summarize working directory state
5645
5645
5646 This generates a brief summary of the working directory state,
5646 This generates a brief summary of the working directory state,
5647 including parents, branch, commit status, and available updates.
5647 including parents, branch, commit status, and available updates.
5648
5648
5649 With the --remote option, this will check the default paths for
5649 With the --remote option, this will check the default paths for
5650 incoming and outgoing changes. This can be time-consuming.
5650 incoming and outgoing changes. This can be time-consuming.
5651
5651
5652 Returns 0 on success.
5652 Returns 0 on success.
5653 """
5653 """
5654
5654
5655 ctx = repo[None]
5655 ctx = repo[None]
5656 parents = ctx.parents()
5656 parents = ctx.parents()
5657 pnode = parents[0].node()
5657 pnode = parents[0].node()
5658 marks = []
5658 marks = []
5659
5659
5660 for p in parents:
5660 for p in parents:
5661 # label with log.changeset (instead of log.parent) since this
5661 # label with log.changeset (instead of log.parent) since this
5662 # shows a working directory parent *changeset*:
5662 # shows a working directory parent *changeset*:
5663 # i18n: column positioning for "hg summary"
5663 # i18n: column positioning for "hg summary"
5664 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5664 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
5665 label='log.changeset changeset.%s' % p.phasestr())
5665 label='log.changeset changeset.%s' % p.phasestr())
5666 ui.write(' '.join(p.tags()), label='log.tag')
5666 ui.write(' '.join(p.tags()), label='log.tag')
5667 if p.bookmarks():
5667 if p.bookmarks():
5668 marks.extend(p.bookmarks())
5668 marks.extend(p.bookmarks())
5669 if p.rev() == -1:
5669 if p.rev() == -1:
5670 if not len(repo):
5670 if not len(repo):
5671 ui.write(_(' (empty repository)'))
5671 ui.write(_(' (empty repository)'))
5672 else:
5672 else:
5673 ui.write(_(' (no revision checked out)'))
5673 ui.write(_(' (no revision checked out)'))
5674 ui.write('\n')
5674 ui.write('\n')
5675 if p.description():
5675 if p.description():
5676 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5676 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
5677 label='log.summary')
5677 label='log.summary')
5678
5678
5679 branch = ctx.branch()
5679 branch = ctx.branch()
5680 bheads = repo.branchheads(branch)
5680 bheads = repo.branchheads(branch)
5681 # i18n: column positioning for "hg summary"
5681 # i18n: column positioning for "hg summary"
5682 m = _('branch: %s\n') % branch
5682 m = _('branch: %s\n') % branch
5683 if branch != 'default':
5683 if branch != 'default':
5684 ui.write(m, label='log.branch')
5684 ui.write(m, label='log.branch')
5685 else:
5685 else:
5686 ui.status(m, label='log.branch')
5686 ui.status(m, label='log.branch')
5687
5687
5688 if marks:
5688 if marks:
5689 current = repo._bookmarkcurrent
5689 current = repo._bookmarkcurrent
5690 # i18n: column positioning for "hg summary"
5690 # i18n: column positioning for "hg summary"
5691 ui.write(_('bookmarks:'), label='log.bookmark')
5691 ui.write(_('bookmarks:'), label='log.bookmark')
5692 if current is not None:
5692 if current is not None:
5693 if current in marks:
5693 if current in marks:
5694 ui.write(' *' + current, label='bookmarks.current')
5694 ui.write(' *' + current, label='bookmarks.current')
5695 marks.remove(current)
5695 marks.remove(current)
5696 else:
5696 else:
5697 ui.write(' [%s]' % current, label='bookmarks.current')
5697 ui.write(' [%s]' % current, label='bookmarks.current')
5698 for m in marks:
5698 for m in marks:
5699 ui.write(' ' + m, label='log.bookmark')
5699 ui.write(' ' + m, label='log.bookmark')
5700 ui.write('\n', label='log.bookmark')
5700 ui.write('\n', label='log.bookmark')
5701
5701
5702 st = list(repo.status(unknown=True))[:6]
5702 st = list(repo.status(unknown=True))[:6]
5703
5703
5704 c = repo.dirstate.copies()
5704 c = repo.dirstate.copies()
5705 copied, renamed = [], []
5705 copied, renamed = [], []
5706 for d, s in c.iteritems():
5706 for d, s in c.iteritems():
5707 if s in st[2]:
5707 if s in st[2]:
5708 st[2].remove(s)
5708 st[2].remove(s)
5709 renamed.append(d)
5709 renamed.append(d)
5710 else:
5710 else:
5711 copied.append(d)
5711 copied.append(d)
5712 if d in st[1]:
5712 if d in st[1]:
5713 st[1].remove(d)
5713 st[1].remove(d)
5714 st.insert(3, renamed)
5714 st.insert(3, renamed)
5715 st.insert(4, copied)
5715 st.insert(4, copied)
5716
5716
5717 ms = mergemod.mergestate(repo)
5717 ms = mergemod.mergestate(repo)
5718 st.append([f for f in ms if ms[f] == 'u'])
5718 st.append([f for f in ms if ms[f] == 'u'])
5719
5719
5720 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5720 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
5721 st.append(subs)
5721 st.append(subs)
5722
5722
5723 labels = [ui.label(_('%d modified'), 'status.modified'),
5723 labels = [ui.label(_('%d modified'), 'status.modified'),
5724 ui.label(_('%d added'), 'status.added'),
5724 ui.label(_('%d added'), 'status.added'),
5725 ui.label(_('%d removed'), 'status.removed'),
5725 ui.label(_('%d removed'), 'status.removed'),
5726 ui.label(_('%d renamed'), 'status.copied'),
5726 ui.label(_('%d renamed'), 'status.copied'),
5727 ui.label(_('%d copied'), 'status.copied'),
5727 ui.label(_('%d copied'), 'status.copied'),
5728 ui.label(_('%d deleted'), 'status.deleted'),
5728 ui.label(_('%d deleted'), 'status.deleted'),
5729 ui.label(_('%d unknown'), 'status.unknown'),
5729 ui.label(_('%d unknown'), 'status.unknown'),
5730 ui.label(_('%d ignored'), 'status.ignored'),
5730 ui.label(_('%d ignored'), 'status.ignored'),
5731 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5731 ui.label(_('%d unresolved'), 'resolve.unresolved'),
5732 ui.label(_('%d subrepos'), 'status.modified')]
5732 ui.label(_('%d subrepos'), 'status.modified')]
5733 t = []
5733 t = []
5734 for s, l in zip(st, labels):
5734 for s, l in zip(st, labels):
5735 if s:
5735 if s:
5736 t.append(l % len(s))
5736 t.append(l % len(s))
5737
5737
5738 t = ', '.join(t)
5738 t = ', '.join(t)
5739 cleanworkdir = False
5739 cleanworkdir = False
5740
5740
5741 if repo.vfs.exists('updatestate'):
5741 if repo.vfs.exists('updatestate'):
5742 t += _(' (interrupted update)')
5742 t += _(' (interrupted update)')
5743 elif len(parents) > 1:
5743 elif len(parents) > 1:
5744 t += _(' (merge)')
5744 t += _(' (merge)')
5745 elif branch != parents[0].branch():
5745 elif branch != parents[0].branch():
5746 t += _(' (new branch)')
5746 t += _(' (new branch)')
5747 elif (parents[0].closesbranch() and
5747 elif (parents[0].closesbranch() and
5748 pnode in repo.branchheads(branch, closed=True)):
5748 pnode in repo.branchheads(branch, closed=True)):
5749 t += _(' (head closed)')
5749 t += _(' (head closed)')
5750 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5750 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
5751 t += _(' (clean)')
5751 t += _(' (clean)')
5752 cleanworkdir = True
5752 cleanworkdir = True
5753 elif pnode not in bheads:
5753 elif pnode not in bheads:
5754 t += _(' (new branch head)')
5754 t += _(' (new branch head)')
5755
5755
5756 if cleanworkdir:
5756 if cleanworkdir:
5757 # i18n: column positioning for "hg summary"
5757 # i18n: column positioning for "hg summary"
5758 ui.status(_('commit: %s\n') % t.strip())
5758 ui.status(_('commit: %s\n') % t.strip())
5759 else:
5759 else:
5760 # i18n: column positioning for "hg summary"
5760 # i18n: column positioning for "hg summary"
5761 ui.write(_('commit: %s\n') % t.strip())
5761 ui.write(_('commit: %s\n') % t.strip())
5762
5762
5763 # all ancestors of branch heads - all ancestors of parent = new csets
5763 # all ancestors of branch heads - all ancestors of parent = new csets
5764 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5764 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
5765 bheads))
5765 bheads))
5766
5766
5767 if new == 0:
5767 if new == 0:
5768 # i18n: column positioning for "hg summary"
5768 # i18n: column positioning for "hg summary"
5769 ui.status(_('update: (current)\n'))
5769 ui.status(_('update: (current)\n'))
5770 elif pnode not in bheads:
5770 elif pnode not in bheads:
5771 # i18n: column positioning for "hg summary"
5771 # i18n: column positioning for "hg summary"
5772 ui.write(_('update: %d new changesets (update)\n') % new)
5772 ui.write(_('update: %d new changesets (update)\n') % new)
5773 else:
5773 else:
5774 # i18n: column positioning for "hg summary"
5774 # i18n: column positioning for "hg summary"
5775 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5775 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
5776 (new, len(bheads)))
5776 (new, len(bheads)))
5777
5777
5778 cmdutil.summaryhooks(ui, repo)
5778 cmdutil.summaryhooks(ui, repo)
5779
5779
5780 if opts.get('remote'):
5780 if opts.get('remote'):
5781 needsincoming, needsoutgoing = True, True
5781 needsincoming, needsoutgoing = True, True
5782 else:
5782 else:
5783 needsincoming, needsoutgoing = False, False
5783 needsincoming, needsoutgoing = False, False
5784 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5784 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
5785 if i:
5785 if i:
5786 needsincoming = True
5786 needsincoming = True
5787 if o:
5787 if o:
5788 needsoutgoing = True
5788 needsoutgoing = True
5789 if not needsincoming and not needsoutgoing:
5789 if not needsincoming and not needsoutgoing:
5790 return
5790 return
5791
5791
5792 def getincoming():
5792 def getincoming():
5793 source, branches = hg.parseurl(ui.expandpath('default'))
5793 source, branches = hg.parseurl(ui.expandpath('default'))
5794 sbranch = branches[0]
5794 sbranch = branches[0]
5795 try:
5795 try:
5796 other = hg.peer(repo, {}, source)
5796 other = hg.peer(repo, {}, source)
5797 except error.RepoError:
5797 except error.RepoError:
5798 if opts.get('remote'):
5798 if opts.get('remote'):
5799 raise
5799 raise
5800 return source, sbranch, None, None, None
5800 return source, sbranch, None, None, None
5801 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5801 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
5802 if revs:
5802 if revs:
5803 revs = [other.lookup(rev) for rev in revs]
5803 revs = [other.lookup(rev) for rev in revs]
5804 ui.debug('comparing with %s\n' % util.hidepassword(source))
5804 ui.debug('comparing with %s\n' % util.hidepassword(source))
5805 repo.ui.pushbuffer()
5805 repo.ui.pushbuffer()
5806 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5806 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
5807 repo.ui.popbuffer()
5807 repo.ui.popbuffer()
5808 return source, sbranch, other, commoninc, commoninc[1]
5808 return source, sbranch, other, commoninc, commoninc[1]
5809
5809
5810 if needsincoming:
5810 if needsincoming:
5811 source, sbranch, sother, commoninc, incoming = getincoming()
5811 source, sbranch, sother, commoninc, incoming = getincoming()
5812 else:
5812 else:
5813 source = sbranch = sother = commoninc = incoming = None
5813 source = sbranch = sother = commoninc = incoming = None
5814
5814
5815 def getoutgoing():
5815 def getoutgoing():
5816 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5816 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
5817 dbranch = branches[0]
5817 dbranch = branches[0]
5818 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5818 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
5819 if source != dest:
5819 if source != dest:
5820 try:
5820 try:
5821 dother = hg.peer(repo, {}, dest)
5821 dother = hg.peer(repo, {}, dest)
5822 except error.RepoError:
5822 except error.RepoError:
5823 if opts.get('remote'):
5823 if opts.get('remote'):
5824 raise
5824 raise
5825 return dest, dbranch, None, None
5825 return dest, dbranch, None, None
5826 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5826 ui.debug('comparing with %s\n' % util.hidepassword(dest))
5827 elif sother is None:
5827 elif sother is None:
5828 # there is no explicit destination peer, but source one is invalid
5828 # there is no explicit destination peer, but source one is invalid
5829 return dest, dbranch, None, None
5829 return dest, dbranch, None, None
5830 else:
5830 else:
5831 dother = sother
5831 dother = sother
5832 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5832 if (source != dest or (sbranch is not None and sbranch != dbranch)):
5833 common = None
5833 common = None
5834 else:
5834 else:
5835 common = commoninc
5835 common = commoninc
5836 if revs:
5836 if revs:
5837 revs = [repo.lookup(rev) for rev in revs]
5837 revs = [repo.lookup(rev) for rev in revs]
5838 repo.ui.pushbuffer()
5838 repo.ui.pushbuffer()
5839 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5839 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
5840 commoninc=common)
5840 commoninc=common)
5841 repo.ui.popbuffer()
5841 repo.ui.popbuffer()
5842 return dest, dbranch, dother, outgoing
5842 return dest, dbranch, dother, outgoing
5843
5843
5844 if needsoutgoing:
5844 if needsoutgoing:
5845 dest, dbranch, dother, outgoing = getoutgoing()
5845 dest, dbranch, dother, outgoing = getoutgoing()
5846 else:
5846 else:
5847 dest = dbranch = dother = outgoing = None
5847 dest = dbranch = dother = outgoing = None
5848
5848
5849 if opts.get('remote'):
5849 if opts.get('remote'):
5850 t = []
5850 t = []
5851 if incoming:
5851 if incoming:
5852 t.append(_('1 or more incoming'))
5852 t.append(_('1 or more incoming'))
5853 o = outgoing.missing
5853 o = outgoing.missing
5854 if o:
5854 if o:
5855 t.append(_('%d outgoing') % len(o))
5855 t.append(_('%d outgoing') % len(o))
5856 other = dother or sother
5856 other = dother or sother
5857 if 'bookmarks' in other.listkeys('namespaces'):
5857 if 'bookmarks' in other.listkeys('namespaces'):
5858 lmarks = repo.listkeys('bookmarks')
5858 lmarks = repo.listkeys('bookmarks')
5859 rmarks = other.listkeys('bookmarks')
5859 rmarks = other.listkeys('bookmarks')
5860 diff = set(rmarks) - set(lmarks)
5860 diff = set(rmarks) - set(lmarks)
5861 if len(diff) > 0:
5861 if len(diff) > 0:
5862 t.append(_('%d incoming bookmarks') % len(diff))
5862 t.append(_('%d incoming bookmarks') % len(diff))
5863 diff = set(lmarks) - set(rmarks)
5863 diff = set(lmarks) - set(rmarks)
5864 if len(diff) > 0:
5864 if len(diff) > 0:
5865 t.append(_('%d outgoing bookmarks') % len(diff))
5865 t.append(_('%d outgoing bookmarks') % len(diff))
5866
5866
5867 if t:
5867 if t:
5868 # i18n: column positioning for "hg summary"
5868 # i18n: column positioning for "hg summary"
5869 ui.write(_('remote: %s\n') % (', '.join(t)))
5869 ui.write(_('remote: %s\n') % (', '.join(t)))
5870 else:
5870 else:
5871 # i18n: column positioning for "hg summary"
5871 # i18n: column positioning for "hg summary"
5872 ui.status(_('remote: (synced)\n'))
5872 ui.status(_('remote: (synced)\n'))
5873
5873
5874 cmdutil.summaryremotehooks(ui, repo, opts,
5874 cmdutil.summaryremotehooks(ui, repo, opts,
5875 ((source, sbranch, sother, commoninc),
5875 ((source, sbranch, sother, commoninc),
5876 (dest, dbranch, dother, outgoing)))
5876 (dest, dbranch, dother, outgoing)))
5877
5877
5878 @command('tag',
5878 @command('tag',
5879 [('f', 'force', None, _('force tag')),
5879 [('f', 'force', None, _('force tag')),
5880 ('l', 'local', None, _('make the tag local')),
5880 ('l', 'local', None, _('make the tag local')),
5881 ('r', 'rev', '', _('revision to tag'), _('REV')),
5881 ('r', 'rev', '', _('revision to tag'), _('REV')),
5882 ('', 'remove', None, _('remove a tag')),
5882 ('', 'remove', None, _('remove a tag')),
5883 # -l/--local is already there, commitopts cannot be used
5883 # -l/--local is already there, commitopts cannot be used
5884 ('e', 'edit', None, _('invoke editor on commit messages')),
5884 ('e', 'edit', None, _('invoke editor on commit messages')),
5885 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5885 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
5886 ] + commitopts2,
5886 ] + commitopts2,
5887 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5887 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
5888 def tag(ui, repo, name1, *names, **opts):
5888 def tag(ui, repo, name1, *names, **opts):
5889 """add one or more tags for the current or given revision
5889 """add one or more tags for the current or given revision
5890
5890
5891 Name a particular revision using <name>.
5891 Name a particular revision using <name>.
5892
5892
5893 Tags are used to name particular revisions of the repository and are
5893 Tags are used to name particular revisions of the repository and are
5894 very useful to compare different revisions, to go back to significant
5894 very useful to compare different revisions, to go back to significant
5895 earlier versions or to mark branch points as releases, etc. Changing
5895 earlier versions or to mark branch points as releases, etc. Changing
5896 an existing tag is normally disallowed; use -f/--force to override.
5896 an existing tag is normally disallowed; use -f/--force to override.
5897
5897
5898 If no revision is given, the parent of the working directory is
5898 If no revision is given, the parent of the working directory is
5899 used.
5899 used.
5900
5900
5901 To facilitate version control, distribution, and merging of tags,
5901 To facilitate version control, distribution, and merging of tags,
5902 they are stored as a file named ".hgtags" which is managed similarly
5902 they are stored as a file named ".hgtags" which is managed similarly
5903 to other project files and can be hand-edited if necessary. This
5903 to other project files and can be hand-edited if necessary. This
5904 also means that tagging creates a new commit. The file
5904 also means that tagging creates a new commit. The file
5905 ".hg/localtags" is used for local tags (not shared among
5905 ".hg/localtags" is used for local tags (not shared among
5906 repositories).
5906 repositories).
5907
5907
5908 Tag commits are usually made at the head of a branch. If the parent
5908 Tag commits are usually made at the head of a branch. If the parent
5909 of the working directory is not a branch head, :hg:`tag` aborts; use
5909 of the working directory is not a branch head, :hg:`tag` aborts; use
5910 -f/--force to force the tag commit to be based on a non-head
5910 -f/--force to force the tag commit to be based on a non-head
5911 changeset.
5911 changeset.
5912
5912
5913 See :hg:`help dates` for a list of formats valid for -d/--date.
5913 See :hg:`help dates` for a list of formats valid for -d/--date.
5914
5914
5915 Since tag names have priority over branch names during revision
5915 Since tag names have priority over branch names during revision
5916 lookup, using an existing branch name as a tag name is discouraged.
5916 lookup, using an existing branch name as a tag name is discouraged.
5917
5917
5918 Returns 0 on success.
5918 Returns 0 on success.
5919 """
5919 """
5920 wlock = lock = None
5920 wlock = lock = None
5921 try:
5921 try:
5922 wlock = repo.wlock()
5922 wlock = repo.wlock()
5923 lock = repo.lock()
5923 lock = repo.lock()
5924 rev_ = "."
5924 rev_ = "."
5925 names = [t.strip() for t in (name1,) + names]
5925 names = [t.strip() for t in (name1,) + names]
5926 if len(names) != len(set(names)):
5926 if len(names) != len(set(names)):
5927 raise util.Abort(_('tag names must be unique'))
5927 raise util.Abort(_('tag names must be unique'))
5928 for n in names:
5928 for n in names:
5929 scmutil.checknewlabel(repo, n, 'tag')
5929 scmutil.checknewlabel(repo, n, 'tag')
5930 if not n:
5930 if not n:
5931 raise util.Abort(_('tag names cannot consist entirely of '
5931 raise util.Abort(_('tag names cannot consist entirely of '
5932 'whitespace'))
5932 'whitespace'))
5933 if opts.get('rev') and opts.get('remove'):
5933 if opts.get('rev') and opts.get('remove'):
5934 raise util.Abort(_("--rev and --remove are incompatible"))
5934 raise util.Abort(_("--rev and --remove are incompatible"))
5935 if opts.get('rev'):
5935 if opts.get('rev'):
5936 rev_ = opts['rev']
5936 rev_ = opts['rev']
5937 message = opts.get('message')
5937 message = opts.get('message')
5938 if opts.get('remove'):
5938 if opts.get('remove'):
5939 expectedtype = opts.get('local') and 'local' or 'global'
5939 expectedtype = opts.get('local') and 'local' or 'global'
5940 for n in names:
5940 for n in names:
5941 if not repo.tagtype(n):
5941 if not repo.tagtype(n):
5942 raise util.Abort(_("tag '%s' does not exist") % n)
5942 raise util.Abort(_("tag '%s' does not exist") % n)
5943 if repo.tagtype(n) != expectedtype:
5943 if repo.tagtype(n) != expectedtype:
5944 if expectedtype == 'global':
5944 if expectedtype == 'global':
5945 raise util.Abort(_("tag '%s' is not a global tag") % n)
5945 raise util.Abort(_("tag '%s' is not a global tag") % n)
5946 else:
5946 else:
5947 raise util.Abort(_("tag '%s' is not a local tag") % n)
5947 raise util.Abort(_("tag '%s' is not a local tag") % n)
5948 rev_ = nullid
5948 rev_ = nullid
5949 if not message:
5949 if not message:
5950 # we don't translate commit messages
5950 # we don't translate commit messages
5951 message = 'Removed tag %s' % ', '.join(names)
5951 message = 'Removed tag %s' % ', '.join(names)
5952 elif not opts.get('force'):
5952 elif not opts.get('force'):
5953 for n in names:
5953 for n in names:
5954 if n in repo.tags():
5954 if n in repo.tags():
5955 raise util.Abort(_("tag '%s' already exists "
5955 raise util.Abort(_("tag '%s' already exists "
5956 "(use -f to force)") % n)
5956 "(use -f to force)") % n)
5957 if not opts.get('local'):
5957 if not opts.get('local'):
5958 p1, p2 = repo.dirstate.parents()
5958 p1, p2 = repo.dirstate.parents()
5959 if p2 != nullid:
5959 if p2 != nullid:
5960 raise util.Abort(_('uncommitted merge'))
5960 raise util.Abort(_('uncommitted merge'))
5961 bheads = repo.branchheads()
5961 bheads = repo.branchheads()
5962 if not opts.get('force') and bheads and p1 not in bheads:
5962 if not opts.get('force') and bheads and p1 not in bheads:
5963 raise util.Abort(_('not at a branch head (use -f to force)'))
5963 raise util.Abort(_('not at a branch head (use -f to force)'))
5964 r = scmutil.revsingle(repo, rev_).node()
5964 r = scmutil.revsingle(repo, rev_).node()
5965
5965
5966 if not message:
5966 if not message:
5967 # we don't translate commit messages
5967 # we don't translate commit messages
5968 message = ('Added tag %s for changeset %s' %
5968 message = ('Added tag %s for changeset %s' %
5969 (', '.join(names), short(r)))
5969 (', '.join(names), short(r)))
5970
5970
5971 date = opts.get('date')
5971 date = opts.get('date')
5972 if date:
5972 if date:
5973 date = util.parsedate(date)
5973 date = util.parsedate(date)
5974
5974
5975 if opts.get('remove'):
5975 if opts.get('remove'):
5976 editform = 'tag.remove'
5976 editform = 'tag.remove'
5977 else:
5977 else:
5978 editform = 'tag.add'
5978 editform = 'tag.add'
5979 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5979 editor = cmdutil.getcommiteditor(editform=editform, **opts)
5980
5980
5981 # don't allow tagging the null rev
5981 # don't allow tagging the null rev
5982 if (not opts.get('remove') and
5982 if (not opts.get('remove') and
5983 scmutil.revsingle(repo, rev_).rev() == nullrev):
5983 scmutil.revsingle(repo, rev_).rev() == nullrev):
5984 raise util.Abort(_("cannot tag null revision"))
5984 raise util.Abort(_("cannot tag null revision"))
5985
5985
5986 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5986 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
5987 editor=editor)
5987 editor=editor)
5988 finally:
5988 finally:
5989 release(lock, wlock)
5989 release(lock, wlock)
5990
5990
5991 @command('tags', formatteropts, '')
5991 @command('tags', formatteropts, '')
5992 def tags(ui, repo, **opts):
5992 def tags(ui, repo, **opts):
5993 """list repository tags
5993 """list repository tags
5994
5994
5995 This lists both regular and local tags. When the -v/--verbose
5995 This lists both regular and local tags. When the -v/--verbose
5996 switch is used, a third column "local" is printed for local tags.
5996 switch is used, a third column "local" is printed for local tags.
5997
5997
5998 Returns 0 on success.
5998 Returns 0 on success.
5999 """
5999 """
6000
6000
6001 fm = ui.formatter('tags', opts)
6001 fm = ui.formatter('tags', opts)
6002 hexfunc = ui.debugflag and hex or short
6002 hexfunc = ui.debugflag and hex or short
6003 tagtype = ""
6003 tagtype = ""
6004
6004
6005 for t, n in reversed(repo.tagslist()):
6005 for t, n in reversed(repo.tagslist()):
6006 hn = hexfunc(n)
6006 hn = hexfunc(n)
6007 label = 'tags.normal'
6007 label = 'tags.normal'
6008 tagtype = ''
6008 tagtype = ''
6009 if repo.tagtype(t) == 'local':
6009 if repo.tagtype(t) == 'local':
6010 label = 'tags.local'
6010 label = 'tags.local'
6011 tagtype = 'local'
6011 tagtype = 'local'
6012
6012
6013 fm.startitem()
6013 fm.startitem()
6014 fm.write('tag', '%s', t, label=label)
6014 fm.write('tag', '%s', t, label=label)
6015 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6015 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6016 fm.condwrite(not ui.quiet, 'rev id', fmt,
6016 fm.condwrite(not ui.quiet, 'rev node', fmt,
6017 repo.changelog.rev(n), hn, label=label)
6017 repo.changelog.rev(n), hn, label=label)
6018 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6018 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6019 tagtype, label=label)
6019 tagtype, label=label)
6020 fm.plain('\n')
6020 fm.plain('\n')
6021 fm.end()
6021 fm.end()
6022
6022
6023 @command('tip',
6023 @command('tip',
6024 [('p', 'patch', None, _('show patch')),
6024 [('p', 'patch', None, _('show patch')),
6025 ('g', 'git', None, _('use git extended diff format')),
6025 ('g', 'git', None, _('use git extended diff format')),
6026 ] + templateopts,
6026 ] + templateopts,
6027 _('[-p] [-g]'))
6027 _('[-p] [-g]'))
6028 def tip(ui, repo, **opts):
6028 def tip(ui, repo, **opts):
6029 """show the tip revision (DEPRECATED)
6029 """show the tip revision (DEPRECATED)
6030
6030
6031 The tip revision (usually just called the tip) is the changeset
6031 The tip revision (usually just called the tip) is the changeset
6032 most recently added to the repository (and therefore the most
6032 most recently added to the repository (and therefore the most
6033 recently changed head).
6033 recently changed head).
6034
6034
6035 If you have just made a commit, that commit will be the tip. If
6035 If you have just made a commit, that commit will be the tip. If
6036 you have just pulled changes from another repository, the tip of
6036 you have just pulled changes from another repository, the tip of
6037 that repository becomes the current tip. The "tip" tag is special
6037 that repository becomes the current tip. The "tip" tag is special
6038 and cannot be renamed or assigned to a different changeset.
6038 and cannot be renamed or assigned to a different changeset.
6039
6039
6040 This command is deprecated, please use :hg:`heads` instead.
6040 This command is deprecated, please use :hg:`heads` instead.
6041
6041
6042 Returns 0 on success.
6042 Returns 0 on success.
6043 """
6043 """
6044 displayer = cmdutil.show_changeset(ui, repo, opts)
6044 displayer = cmdutil.show_changeset(ui, repo, opts)
6045 displayer.show(repo['tip'])
6045 displayer.show(repo['tip'])
6046 displayer.close()
6046 displayer.close()
6047
6047
6048 @command('unbundle',
6048 @command('unbundle',
6049 [('u', 'update', None,
6049 [('u', 'update', None,
6050 _('update to new branch head if changesets were unbundled'))],
6050 _('update to new branch head if changesets were unbundled'))],
6051 _('[-u] FILE...'))
6051 _('[-u] FILE...'))
6052 def unbundle(ui, repo, fname1, *fnames, **opts):
6052 def unbundle(ui, repo, fname1, *fnames, **opts):
6053 """apply one or more changegroup files
6053 """apply one or more changegroup files
6054
6054
6055 Apply one or more compressed changegroup files generated by the
6055 Apply one or more compressed changegroup files generated by the
6056 bundle command.
6056 bundle command.
6057
6057
6058 Returns 0 on success, 1 if an update has unresolved files.
6058 Returns 0 on success, 1 if an update has unresolved files.
6059 """
6059 """
6060 fnames = (fname1,) + fnames
6060 fnames = (fname1,) + fnames
6061
6061
6062 lock = repo.lock()
6062 lock = repo.lock()
6063 try:
6063 try:
6064 for fname in fnames:
6064 for fname in fnames:
6065 f = hg.openpath(ui, fname)
6065 f = hg.openpath(ui, fname)
6066 gen = exchange.readbundle(ui, f, fname)
6066 gen = exchange.readbundle(ui, f, fname)
6067 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6067 modheads = changegroup.addchangegroup(repo, gen, 'unbundle',
6068 'bundle:' + fname)
6068 'bundle:' + fname)
6069 finally:
6069 finally:
6070 lock.release()
6070 lock.release()
6071
6071
6072 return postincoming(ui, repo, modheads, opts.get('update'), None)
6072 return postincoming(ui, repo, modheads, opts.get('update'), None)
6073
6073
6074 @command('^update|up|checkout|co',
6074 @command('^update|up|checkout|co',
6075 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6075 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6076 ('c', 'check', None,
6076 ('c', 'check', None,
6077 _('update across branches if no uncommitted changes')),
6077 _('update across branches if no uncommitted changes')),
6078 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6078 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6079 ('r', 'rev', '', _('revision'), _('REV'))
6079 ('r', 'rev', '', _('revision'), _('REV'))
6080 ] + mergetoolopts,
6080 ] + mergetoolopts,
6081 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6081 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6082 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6082 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6083 tool=None):
6083 tool=None):
6084 """update working directory (or switch revisions)
6084 """update working directory (or switch revisions)
6085
6085
6086 Update the repository's working directory to the specified
6086 Update the repository's working directory to the specified
6087 changeset. If no changeset is specified, update to the tip of the
6087 changeset. If no changeset is specified, update to the tip of the
6088 current named branch and move the current bookmark (see :hg:`help
6088 current named branch and move the current bookmark (see :hg:`help
6089 bookmarks`).
6089 bookmarks`).
6090
6090
6091 Update sets the working directory's parent revision to the specified
6091 Update sets the working directory's parent revision to the specified
6092 changeset (see :hg:`help parents`).
6092 changeset (see :hg:`help parents`).
6093
6093
6094 If the changeset is not a descendant or ancestor of the working
6094 If the changeset is not a descendant or ancestor of the working
6095 directory's parent, the update is aborted. With the -c/--check
6095 directory's parent, the update is aborted. With the -c/--check
6096 option, the working directory is checked for uncommitted changes; if
6096 option, the working directory is checked for uncommitted changes; if
6097 none are found, the working directory is updated to the specified
6097 none are found, the working directory is updated to the specified
6098 changeset.
6098 changeset.
6099
6099
6100 .. container:: verbose
6100 .. container:: verbose
6101
6101
6102 The following rules apply when the working directory contains
6102 The following rules apply when the working directory contains
6103 uncommitted changes:
6103 uncommitted changes:
6104
6104
6105 1. If neither -c/--check nor -C/--clean is specified, and if
6105 1. If neither -c/--check nor -C/--clean is specified, and if
6106 the requested changeset is an ancestor or descendant of
6106 the requested changeset is an ancestor or descendant of
6107 the working directory's parent, the uncommitted changes
6107 the working directory's parent, the uncommitted changes
6108 are merged into the requested changeset and the merged
6108 are merged into the requested changeset and the merged
6109 result is left uncommitted. If the requested changeset is
6109 result is left uncommitted. If the requested changeset is
6110 not an ancestor or descendant (that is, it is on another
6110 not an ancestor or descendant (that is, it is on another
6111 branch), the update is aborted and the uncommitted changes
6111 branch), the update is aborted and the uncommitted changes
6112 are preserved.
6112 are preserved.
6113
6113
6114 2. With the -c/--check option, the update is aborted and the
6114 2. With the -c/--check option, the update is aborted and the
6115 uncommitted changes are preserved.
6115 uncommitted changes are preserved.
6116
6116
6117 3. With the -C/--clean option, uncommitted changes are discarded and
6117 3. With the -C/--clean option, uncommitted changes are discarded and
6118 the working directory is updated to the requested changeset.
6118 the working directory is updated to the requested changeset.
6119
6119
6120 To cancel an uncommitted merge (and lose your changes), use
6120 To cancel an uncommitted merge (and lose your changes), use
6121 :hg:`update --clean .`.
6121 :hg:`update --clean .`.
6122
6122
6123 Use null as the changeset to remove the working directory (like
6123 Use null as the changeset to remove the working directory (like
6124 :hg:`clone -U`).
6124 :hg:`clone -U`).
6125
6125
6126 If you want to revert just one file to an older revision, use
6126 If you want to revert just one file to an older revision, use
6127 :hg:`revert [-r REV] NAME`.
6127 :hg:`revert [-r REV] NAME`.
6128
6128
6129 See :hg:`help dates` for a list of formats valid for -d/--date.
6129 See :hg:`help dates` for a list of formats valid for -d/--date.
6130
6130
6131 Returns 0 on success, 1 if there are unresolved files.
6131 Returns 0 on success, 1 if there are unresolved files.
6132 """
6132 """
6133 if rev and node:
6133 if rev and node:
6134 raise util.Abort(_("please specify just one revision"))
6134 raise util.Abort(_("please specify just one revision"))
6135
6135
6136 if rev is None or rev == '':
6136 if rev is None or rev == '':
6137 rev = node
6137 rev = node
6138
6138
6139 cmdutil.clearunfinished(repo)
6139 cmdutil.clearunfinished(repo)
6140
6140
6141 # with no argument, we also move the current bookmark, if any
6141 # with no argument, we also move the current bookmark, if any
6142 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6142 rev, movemarkfrom = bookmarks.calculateupdate(ui, repo, rev)
6143
6143
6144 # if we defined a bookmark, we have to remember the original bookmark name
6144 # if we defined a bookmark, we have to remember the original bookmark name
6145 brev = rev
6145 brev = rev
6146 rev = scmutil.revsingle(repo, rev, rev).rev()
6146 rev = scmutil.revsingle(repo, rev, rev).rev()
6147
6147
6148 if check and clean:
6148 if check and clean:
6149 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6149 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
6150
6150
6151 if date:
6151 if date:
6152 if rev is not None:
6152 if rev is not None:
6153 raise util.Abort(_("you can't specify a revision and a date"))
6153 raise util.Abort(_("you can't specify a revision and a date"))
6154 rev = cmdutil.finddate(ui, repo, date)
6154 rev = cmdutil.finddate(ui, repo, date)
6155
6155
6156 if check:
6156 if check:
6157 c = repo[None]
6157 c = repo[None]
6158 if c.dirty(merge=False, branch=False, missing=True):
6158 if c.dirty(merge=False, branch=False, missing=True):
6159 raise util.Abort(_("uncommitted changes"))
6159 raise util.Abort(_("uncommitted changes"))
6160 if rev is None:
6160 if rev is None:
6161 rev = repo[repo[None].branch()].rev()
6161 rev = repo[repo[None].branch()].rev()
6162 mergemod._checkunknown(repo, repo[None], repo[rev])
6162 mergemod._checkunknown(repo, repo[None], repo[rev])
6163
6163
6164 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6164 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6165
6165
6166 if clean:
6166 if clean:
6167 ret = hg.clean(repo, rev)
6167 ret = hg.clean(repo, rev)
6168 else:
6168 else:
6169 ret = hg.update(repo, rev)
6169 ret = hg.update(repo, rev)
6170
6170
6171 if not ret and movemarkfrom:
6171 if not ret and movemarkfrom:
6172 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6172 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6173 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6173 ui.status(_("updating bookmark %s\n") % repo._bookmarkcurrent)
6174 elif brev in repo._bookmarks:
6174 elif brev in repo._bookmarks:
6175 bookmarks.setcurrent(repo, brev)
6175 bookmarks.setcurrent(repo, brev)
6176 ui.status(_("(activating bookmark %s)\n") % brev)
6176 ui.status(_("(activating bookmark %s)\n") % brev)
6177 elif brev:
6177 elif brev:
6178 if repo._bookmarkcurrent:
6178 if repo._bookmarkcurrent:
6179 ui.status(_("(leaving bookmark %s)\n") %
6179 ui.status(_("(leaving bookmark %s)\n") %
6180 repo._bookmarkcurrent)
6180 repo._bookmarkcurrent)
6181 bookmarks.unsetcurrent(repo)
6181 bookmarks.unsetcurrent(repo)
6182
6182
6183 return ret
6183 return ret
6184
6184
6185 @command('verify', [])
6185 @command('verify', [])
6186 def verify(ui, repo):
6186 def verify(ui, repo):
6187 """verify the integrity of the repository
6187 """verify the integrity of the repository
6188
6188
6189 Verify the integrity of the current repository.
6189 Verify the integrity of the current repository.
6190
6190
6191 This will perform an extensive check of the repository's
6191 This will perform an extensive check of the repository's
6192 integrity, validating the hashes and checksums of each entry in
6192 integrity, validating the hashes and checksums of each entry in
6193 the changelog, manifest, and tracked files, as well as the
6193 the changelog, manifest, and tracked files, as well as the
6194 integrity of their crosslinks and indices.
6194 integrity of their crosslinks and indices.
6195
6195
6196 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6196 Please see http://mercurial.selenic.com/wiki/RepositoryCorruption
6197 for more information about recovery from corruption of the
6197 for more information about recovery from corruption of the
6198 repository.
6198 repository.
6199
6199
6200 Returns 0 on success, 1 if errors are encountered.
6200 Returns 0 on success, 1 if errors are encountered.
6201 """
6201 """
6202 return hg.verify(repo)
6202 return hg.verify(repo)
6203
6203
6204 @command('version', [], norepo=True)
6204 @command('version', [], norepo=True)
6205 def version_(ui):
6205 def version_(ui):
6206 """output version and copyright information"""
6206 """output version and copyright information"""
6207 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6207 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6208 % util.version())
6208 % util.version())
6209 ui.status(_(
6209 ui.status(_(
6210 "(see http://mercurial.selenic.com for more information)\n"
6210 "(see http://mercurial.selenic.com for more information)\n"
6211 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6211 "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
6212 "This is free software; see the source for copying conditions. "
6212 "This is free software; see the source for copying conditions. "
6213 "There is NO\nwarranty; "
6213 "There is NO\nwarranty; "
6214 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6214 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6215 ))
6215 ))
6216
6216
6217 ui.note(_("\nEnabled extensions:\n\n"))
6217 ui.note(_("\nEnabled extensions:\n\n"))
6218 if ui.verbose:
6218 if ui.verbose:
6219 # format names and versions into columns
6219 # format names and versions into columns
6220 names = []
6220 names = []
6221 vers = []
6221 vers = []
6222 for name, module in extensions.extensions():
6222 for name, module in extensions.extensions():
6223 names.append(name)
6223 names.append(name)
6224 vers.append(extensions.moduleversion(module))
6224 vers.append(extensions.moduleversion(module))
6225 if names:
6225 if names:
6226 maxnamelen = max(len(n) for n in names)
6226 maxnamelen = max(len(n) for n in names)
6227 for i, name in enumerate(names):
6227 for i, name in enumerate(names):
6228 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6228 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,274 +1,274 b''
1 Test character encoding
1 Test character encoding
2
2
3 $ hg init t
3 $ hg init t
4 $ cd t
4 $ cd t
5
5
6 we need a repo with some legacy latin-1 changesets
6 we need a repo with some legacy latin-1 changesets
7
7
8 $ hg unbundle "$TESTDIR/bundles/legacy-encoding.hg"
8 $ hg unbundle "$TESTDIR/bundles/legacy-encoding.hg"
9 adding changesets
9 adding changesets
10 adding manifests
10 adding manifests
11 adding file changes
11 adding file changes
12 added 2 changesets with 2 changes to 1 files
12 added 2 changesets with 2 changes to 1 files
13 (run 'hg update' to get a working copy)
13 (run 'hg update' to get a working copy)
14 $ hg co
14 $ hg co
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
15 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
16 $ python << EOF
16 $ python << EOF
17 > f = file('latin-1', 'w'); f.write("latin-1 e' encoded: \xe9"); f.close()
17 > f = file('latin-1', 'w'); f.write("latin-1 e' encoded: \xe9"); f.close()
18 > f = file('utf-8', 'w'); f.write("utf-8 e' encoded: \xc3\xa9"); f.close()
18 > f = file('utf-8', 'w'); f.write("utf-8 e' encoded: \xc3\xa9"); f.close()
19 > f = file('latin-1-tag', 'w'); f.write("\xe9"); f.close()
19 > f = file('latin-1-tag', 'w'); f.write("\xe9"); f.close()
20 > EOF
20 > EOF
21
21
22 should fail with encoding error
22 should fail with encoding error
23
23
24 $ echo "plain old ascii" > a
24 $ echo "plain old ascii" > a
25 $ hg st
25 $ hg st
26 M a
26 M a
27 ? latin-1
27 ? latin-1
28 ? latin-1-tag
28 ? latin-1-tag
29 ? utf-8
29 ? utf-8
30 $ HGENCODING=ascii hg ci -l latin-1
30 $ HGENCODING=ascii hg ci -l latin-1
31 transaction abort!
31 transaction abort!
32 rollback completed
32 rollback completed
33 abort: decoding near ' encoded: \xe9': 'ascii' codec can't decode byte 0xe9 in position 20: ordinal not in range(128)! (esc)
33 abort: decoding near ' encoded: \xe9': 'ascii' codec can't decode byte 0xe9 in position 20: ordinal not in range(128)! (esc)
34 [255]
34 [255]
35
35
36 these should work
36 these should work
37
37
38 $ echo "latin-1" > a
38 $ echo "latin-1" > a
39 $ HGENCODING=latin-1 hg ci -l latin-1
39 $ HGENCODING=latin-1 hg ci -l latin-1
40 $ echo "utf-8" > a
40 $ echo "utf-8" > a
41 $ HGENCODING=utf-8 hg ci -l utf-8
41 $ HGENCODING=utf-8 hg ci -l utf-8
42 $ HGENCODING=latin-1 hg tag `cat latin-1-tag`
42 $ HGENCODING=latin-1 hg tag `cat latin-1-tag`
43 $ HGENCODING=latin-1 hg branch `cat latin-1-tag`
43 $ HGENCODING=latin-1 hg branch `cat latin-1-tag`
44 marked working directory as branch \xe9 (esc)
44 marked working directory as branch \xe9 (esc)
45 (branches are permanent and global, did you want a bookmark?)
45 (branches are permanent and global, did you want a bookmark?)
46 $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
46 $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
47 $ hg -q rollback
47 $ hg -q rollback
48 $ HGENCODING=latin-1 hg branch
48 $ HGENCODING=latin-1 hg branch
49 \xe9 (esc)
49 \xe9 (esc)
50 $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
50 $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
51 $ rm .hg/branch
51 $ rm .hg/branch
52
52
53 hg log (ascii)
53 hg log (ascii)
54
54
55 $ hg --encoding ascii log
55 $ hg --encoding ascii log
56 changeset: 5:a52c0692f24a
56 changeset: 5:a52c0692f24a
57 branch: ?
57 branch: ?
58 tag: tip
58 tag: tip
59 user: test
59 user: test
60 date: Thu Jan 01 00:00:00 1970 +0000
60 date: Thu Jan 01 00:00:00 1970 +0000
61 summary: latin1 branch
61 summary: latin1 branch
62
62
63 changeset: 4:94db611b4196
63 changeset: 4:94db611b4196
64 user: test
64 user: test
65 date: Thu Jan 01 00:00:00 1970 +0000
65 date: Thu Jan 01 00:00:00 1970 +0000
66 summary: Added tag ? for changeset ca661e7520de
66 summary: Added tag ? for changeset ca661e7520de
67
67
68 changeset: 3:ca661e7520de
68 changeset: 3:ca661e7520de
69 tag: ?
69 tag: ?
70 user: test
70 user: test
71 date: Thu Jan 01 00:00:00 1970 +0000
71 date: Thu Jan 01 00:00:00 1970 +0000
72 summary: utf-8 e' encoded: ?
72 summary: utf-8 e' encoded: ?
73
73
74 changeset: 2:650c6f3d55dd
74 changeset: 2:650c6f3d55dd
75 user: test
75 user: test
76 date: Thu Jan 01 00:00:00 1970 +0000
76 date: Thu Jan 01 00:00:00 1970 +0000
77 summary: latin-1 e' encoded: ?
77 summary: latin-1 e' encoded: ?
78
78
79 changeset: 1:0e5b7e3f9c4a
79 changeset: 1:0e5b7e3f9c4a
80 user: test
80 user: test
81 date: Mon Jan 12 13:46:40 1970 +0000
81 date: Mon Jan 12 13:46:40 1970 +0000
82 summary: koi8-r: ????? = u'\u0440\u0442\u0443\u0442\u044c'
82 summary: koi8-r: ????? = u'\u0440\u0442\u0443\u0442\u044c'
83
83
84 changeset: 0:1e78a93102a3
84 changeset: 0:1e78a93102a3
85 user: test
85 user: test
86 date: Mon Jan 12 13:46:40 1970 +0000
86 date: Mon Jan 12 13:46:40 1970 +0000
87 summary: latin-1 e': ? = u'\xe9'
87 summary: latin-1 e': ? = u'\xe9'
88
88
89
89
90 hg log (latin-1)
90 hg log (latin-1)
91
91
92 $ hg --encoding latin-1 log
92 $ hg --encoding latin-1 log
93 changeset: 5:a52c0692f24a
93 changeset: 5:a52c0692f24a
94 branch: \xe9 (esc)
94 branch: \xe9 (esc)
95 tag: tip
95 tag: tip
96 user: test
96 user: test
97 date: Thu Jan 01 00:00:00 1970 +0000
97 date: Thu Jan 01 00:00:00 1970 +0000
98 summary: latin1 branch
98 summary: latin1 branch
99
99
100 changeset: 4:94db611b4196
100 changeset: 4:94db611b4196
101 user: test
101 user: test
102 date: Thu Jan 01 00:00:00 1970 +0000
102 date: Thu Jan 01 00:00:00 1970 +0000
103 summary: Added tag \xe9 for changeset ca661e7520de (esc)
103 summary: Added tag \xe9 for changeset ca661e7520de (esc)
104
104
105 changeset: 3:ca661e7520de
105 changeset: 3:ca661e7520de
106 tag: \xe9 (esc)
106 tag: \xe9 (esc)
107 user: test
107 user: test
108 date: Thu Jan 01 00:00:00 1970 +0000
108 date: Thu Jan 01 00:00:00 1970 +0000
109 summary: utf-8 e' encoded: \xe9 (esc)
109 summary: utf-8 e' encoded: \xe9 (esc)
110
110
111 changeset: 2:650c6f3d55dd
111 changeset: 2:650c6f3d55dd
112 user: test
112 user: test
113 date: Thu Jan 01 00:00:00 1970 +0000
113 date: Thu Jan 01 00:00:00 1970 +0000
114 summary: latin-1 e' encoded: \xe9 (esc)
114 summary: latin-1 e' encoded: \xe9 (esc)
115
115
116 changeset: 1:0e5b7e3f9c4a
116 changeset: 1:0e5b7e3f9c4a
117 user: test
117 user: test
118 date: Mon Jan 12 13:46:40 1970 +0000
118 date: Mon Jan 12 13:46:40 1970 +0000
119 summary: koi8-r: \xd2\xd4\xd5\xd4\xd8 = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
119 summary: koi8-r: \xd2\xd4\xd5\xd4\xd8 = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
120
120
121 changeset: 0:1e78a93102a3
121 changeset: 0:1e78a93102a3
122 user: test
122 user: test
123 date: Mon Jan 12 13:46:40 1970 +0000
123 date: Mon Jan 12 13:46:40 1970 +0000
124 summary: latin-1 e': \xe9 = u'\\xe9' (esc)
124 summary: latin-1 e': \xe9 = u'\\xe9' (esc)
125
125
126
126
127 hg log (utf-8)
127 hg log (utf-8)
128
128
129 $ hg --encoding utf-8 log
129 $ hg --encoding utf-8 log
130 changeset: 5:a52c0692f24a
130 changeset: 5:a52c0692f24a
131 branch: \xc3\xa9 (esc)
131 branch: \xc3\xa9 (esc)
132 tag: tip
132 tag: tip
133 user: test
133 user: test
134 date: Thu Jan 01 00:00:00 1970 +0000
134 date: Thu Jan 01 00:00:00 1970 +0000
135 summary: latin1 branch
135 summary: latin1 branch
136
136
137 changeset: 4:94db611b4196
137 changeset: 4:94db611b4196
138 user: test
138 user: test
139 date: Thu Jan 01 00:00:00 1970 +0000
139 date: Thu Jan 01 00:00:00 1970 +0000
140 summary: Added tag \xc3\xa9 for changeset ca661e7520de (esc)
140 summary: Added tag \xc3\xa9 for changeset ca661e7520de (esc)
141
141
142 changeset: 3:ca661e7520de
142 changeset: 3:ca661e7520de
143 tag: \xc3\xa9 (esc)
143 tag: \xc3\xa9 (esc)
144 user: test
144 user: test
145 date: Thu Jan 01 00:00:00 1970 +0000
145 date: Thu Jan 01 00:00:00 1970 +0000
146 summary: utf-8 e' encoded: \xc3\xa9 (esc)
146 summary: utf-8 e' encoded: \xc3\xa9 (esc)
147
147
148 changeset: 2:650c6f3d55dd
148 changeset: 2:650c6f3d55dd
149 user: test
149 user: test
150 date: Thu Jan 01 00:00:00 1970 +0000
150 date: Thu Jan 01 00:00:00 1970 +0000
151 summary: latin-1 e' encoded: \xc3\xa9 (esc)
151 summary: latin-1 e' encoded: \xc3\xa9 (esc)
152
152
153 changeset: 1:0e5b7e3f9c4a
153 changeset: 1:0e5b7e3f9c4a
154 user: test
154 user: test
155 date: Mon Jan 12 13:46:40 1970 +0000
155 date: Mon Jan 12 13:46:40 1970 +0000
156 summary: koi8-r: \xc3\x92\xc3\x94\xc3\x95\xc3\x94\xc3\x98 = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
156 summary: koi8-r: \xc3\x92\xc3\x94\xc3\x95\xc3\x94\xc3\x98 = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
157
157
158 changeset: 0:1e78a93102a3
158 changeset: 0:1e78a93102a3
159 user: test
159 user: test
160 date: Mon Jan 12 13:46:40 1970 +0000
160 date: Mon Jan 12 13:46:40 1970 +0000
161 summary: latin-1 e': \xc3\xa9 = u'\\xe9' (esc)
161 summary: latin-1 e': \xc3\xa9 = u'\\xe9' (esc)
162
162
163
163
164 hg tags (ascii)
164 hg tags (ascii)
165
165
166 $ HGENCODING=ascii hg tags
166 $ HGENCODING=ascii hg tags
167 tip 5:a52c0692f24a
167 tip 5:a52c0692f24a
168 ? 3:ca661e7520de
168 ? 3:ca661e7520de
169
169
170 hg tags (latin-1)
170 hg tags (latin-1)
171
171
172 $ HGENCODING=latin-1 hg tags
172 $ HGENCODING=latin-1 hg tags
173 tip 5:a52c0692f24a
173 tip 5:a52c0692f24a
174 \xe9 3:ca661e7520de (esc)
174 \xe9 3:ca661e7520de (esc)
175
175
176 hg tags (utf-8)
176 hg tags (utf-8)
177
177
178 $ HGENCODING=utf-8 hg tags
178 $ HGENCODING=utf-8 hg tags
179 tip 5:a52c0692f24a
179 tip 5:a52c0692f24a
180 \xc3\xa9 3:ca661e7520de (esc)
180 \xc3\xa9 3:ca661e7520de (esc)
181
181
182 hg tags (JSON)
182 hg tags (JSON)
183
183
184 $ hg tags -Tjson
184 $ hg tags -Tjson
185 [
185 [
186 {
186 {
187 "id": "a52c0692f24a",
187 "node": "a52c0692f24a",
188 "rev": 5,
188 "rev": 5,
189 "tag": "tip",
189 "tag": "tip",
190 "type": ""
190 "type": ""
191 },
191 },
192 {
192 {
193 "id": "ca661e7520de",
193 "node": "ca661e7520de",
194 "rev": 3,
194 "rev": 3,
195 "tag": "\xc3\xa9", (esc)
195 "tag": "\xc3\xa9", (esc)
196 "type": ""
196 "type": ""
197 }
197 }
198 ]
198 ]
199
199
200 hg branches (ascii)
200 hg branches (ascii)
201
201
202 $ HGENCODING=ascii hg branches
202 $ HGENCODING=ascii hg branches
203 ? 5:a52c0692f24a
203 ? 5:a52c0692f24a
204 default 4:94db611b4196 (inactive)
204 default 4:94db611b4196 (inactive)
205
205
206 hg branches (latin-1)
206 hg branches (latin-1)
207
207
208 $ HGENCODING=latin-1 hg branches
208 $ HGENCODING=latin-1 hg branches
209 \xe9 5:a52c0692f24a (esc)
209 \xe9 5:a52c0692f24a (esc)
210 default 4:94db611b4196 (inactive)
210 default 4:94db611b4196 (inactive)
211
211
212 hg branches (utf-8)
212 hg branches (utf-8)
213
213
214 $ HGENCODING=utf-8 hg branches
214 $ HGENCODING=utf-8 hg branches
215 \xc3\xa9 5:a52c0692f24a (esc)
215 \xc3\xa9 5:a52c0692f24a (esc)
216 default 4:94db611b4196 (inactive)
216 default 4:94db611b4196 (inactive)
217 $ echo '[ui]' >> .hg/hgrc
217 $ echo '[ui]' >> .hg/hgrc
218 $ echo 'fallbackencoding = koi8-r' >> .hg/hgrc
218 $ echo 'fallbackencoding = koi8-r' >> .hg/hgrc
219
219
220 hg log (utf-8)
220 hg log (utf-8)
221
221
222 $ HGENCODING=utf-8 hg log
222 $ HGENCODING=utf-8 hg log
223 changeset: 5:a52c0692f24a
223 changeset: 5:a52c0692f24a
224 branch: \xc3\xa9 (esc)
224 branch: \xc3\xa9 (esc)
225 tag: tip
225 tag: tip
226 user: test
226 user: test
227 date: Thu Jan 01 00:00:00 1970 +0000
227 date: Thu Jan 01 00:00:00 1970 +0000
228 summary: latin1 branch
228 summary: latin1 branch
229
229
230 changeset: 4:94db611b4196
230 changeset: 4:94db611b4196
231 user: test
231 user: test
232 date: Thu Jan 01 00:00:00 1970 +0000
232 date: Thu Jan 01 00:00:00 1970 +0000
233 summary: Added tag \xc3\xa9 for changeset ca661e7520de (esc)
233 summary: Added tag \xc3\xa9 for changeset ca661e7520de (esc)
234
234
235 changeset: 3:ca661e7520de
235 changeset: 3:ca661e7520de
236 tag: \xc3\xa9 (esc)
236 tag: \xc3\xa9 (esc)
237 user: test
237 user: test
238 date: Thu Jan 01 00:00:00 1970 +0000
238 date: Thu Jan 01 00:00:00 1970 +0000
239 summary: utf-8 e' encoded: \xc3\xa9 (esc)
239 summary: utf-8 e' encoded: \xc3\xa9 (esc)
240
240
241 changeset: 2:650c6f3d55dd
241 changeset: 2:650c6f3d55dd
242 user: test
242 user: test
243 date: Thu Jan 01 00:00:00 1970 +0000
243 date: Thu Jan 01 00:00:00 1970 +0000
244 summary: latin-1 e' encoded: \xc3\xa9 (esc)
244 summary: latin-1 e' encoded: \xc3\xa9 (esc)
245
245
246 changeset: 1:0e5b7e3f9c4a
246 changeset: 1:0e5b7e3f9c4a
247 user: test
247 user: test
248 date: Mon Jan 12 13:46:40 1970 +0000
248 date: Mon Jan 12 13:46:40 1970 +0000
249 summary: koi8-r: \xd1\x80\xd1\x82\xd1\x83\xd1\x82\xd1\x8c = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
249 summary: koi8-r: \xd1\x80\xd1\x82\xd1\x83\xd1\x82\xd1\x8c = u'\\u0440\\u0442\\u0443\\u0442\\u044c' (esc)
250
250
251 changeset: 0:1e78a93102a3
251 changeset: 0:1e78a93102a3
252 user: test
252 user: test
253 date: Mon Jan 12 13:46:40 1970 +0000
253 date: Mon Jan 12 13:46:40 1970 +0000
254 summary: latin-1 e': \xd0\x98 = u'\\xe9' (esc)
254 summary: latin-1 e': \xd0\x98 = u'\\xe9' (esc)
255
255
256
256
257 hg log (dolphin)
257 hg log (dolphin)
258
258
259 $ HGENCODING=dolphin hg log
259 $ HGENCODING=dolphin hg log
260 abort: unknown encoding: dolphin
260 abort: unknown encoding: dolphin
261 (please check your locale settings)
261 (please check your locale settings)
262 [255]
262 [255]
263 $ HGENCODING=ascii hg branch `cat latin-1-tag`
263 $ HGENCODING=ascii hg branch `cat latin-1-tag`
264 abort: decoding near '\xe9': 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)! (esc)
264 abort: decoding near '\xe9': 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)! (esc)
265 [255]
265 [255]
266 $ cp latin-1-tag .hg/branch
266 $ cp latin-1-tag .hg/branch
267 $ HGENCODING=latin-1 hg ci -m 'auto-promote legacy name'
267 $ HGENCODING=latin-1 hg ci -m 'auto-promote legacy name'
268
268
269 Test roundtrip encoding of lookup tables when not using UTF-8 (issue2763)
269 Test roundtrip encoding of lookup tables when not using UTF-8 (issue2763)
270
270
271 $ HGENCODING=latin-1 hg up `cat latin-1-tag`
271 $ HGENCODING=latin-1 hg up `cat latin-1-tag`
272 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
272 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
273
273
274 $ cd ..
274 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now