##// END OF EJS Templates
debugrevlog: cope with empty revlog files...
Augie Fackler -
r26826:39dbf495 stable
parent child Browse files
Show More
@@ -1,6760 +1,6765
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullid, nullrev, short
8 from node import hex, bin, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _
10 from i18n import _
11 import os, re, difflib, time, tempfile, errno, shlex
11 import os, re, difflib, time, tempfile, errno, shlex
12 import sys, socket
12 import sys, socket
13 import hg, scmutil, util, revlog, copies, error, bookmarks
13 import hg, scmutil, util, revlog, copies, error, bookmarks
14 import patch, help, encoding, templatekw, discovery
14 import patch, help, encoding, templatekw, discovery
15 import archival, changegroup, cmdutil, hbisect
15 import archival, changegroup, cmdutil, hbisect
16 import sshserver, hgweb
16 import sshserver, hgweb
17 import extensions
17 import extensions
18 from hgweb import server as hgweb_server
18 from hgweb import server as hgweb_server
19 import merge as mergemod
19 import merge as mergemod
20 import minirst, revset, fileset
20 import minirst, revset, fileset
21 import dagparser, context, simplemerge, graphmod, copies
21 import dagparser, context, simplemerge, graphmod, copies
22 import random, operator
22 import random, operator
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
23 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
24 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
24 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
25 import ui as uimod
25 import ui as uimod
26 import streamclone
26 import streamclone
27
27
28 table = {}
28 table = {}
29
29
30 command = cmdutil.command(table)
30 command = cmdutil.command(table)
31
31
32 # Space delimited list of commands that don't require local repositories.
32 # Space delimited list of commands that don't require local repositories.
33 # This should be populated by passing norepo=True into the @command decorator.
33 # This should be populated by passing norepo=True into the @command decorator.
34 norepo = ''
34 norepo = ''
35 # Space delimited list of commands that optionally require local repositories.
35 # Space delimited list of commands that optionally require local repositories.
36 # This should be populated by passing optionalrepo=True into the @command
36 # This should be populated by passing optionalrepo=True into the @command
37 # decorator.
37 # decorator.
38 optionalrepo = ''
38 optionalrepo = ''
39 # Space delimited list of commands that will examine arguments looking for
39 # Space delimited list of commands that will examine arguments looking for
40 # a repository. This should be populated by passing inferrepo=True into the
40 # a repository. This should be populated by passing inferrepo=True into the
41 # @command decorator.
41 # @command decorator.
42 inferrepo = ''
42 inferrepo = ''
43
43
44 # label constants
44 # label constants
45 # until 3.5, bookmarks.current was the advertised name, not
45 # until 3.5, bookmarks.current was the advertised name, not
46 # bookmarks.active, so we must use both to avoid breaking old
46 # bookmarks.active, so we must use both to avoid breaking old
47 # custom styles
47 # custom styles
48 activebookmarklabel = 'bookmarks.active bookmarks.current'
48 activebookmarklabel = 'bookmarks.active bookmarks.current'
49
49
50 # common command options
50 # common command options
51
51
52 globalopts = [
52 globalopts = [
53 ('R', 'repository', '',
53 ('R', 'repository', '',
54 _('repository root directory or name of overlay bundle file'),
54 _('repository root directory or name of overlay bundle file'),
55 _('REPO')),
55 _('REPO')),
56 ('', 'cwd', '',
56 ('', 'cwd', '',
57 _('change working directory'), _('DIR')),
57 _('change working directory'), _('DIR')),
58 ('y', 'noninteractive', None,
58 ('y', 'noninteractive', None,
59 _('do not prompt, automatically pick the first choice for all prompts')),
59 _('do not prompt, automatically pick the first choice for all prompts')),
60 ('q', 'quiet', None, _('suppress output')),
60 ('q', 'quiet', None, _('suppress output')),
61 ('v', 'verbose', None, _('enable additional output')),
61 ('v', 'verbose', None, _('enable additional output')),
62 ('', 'config', [],
62 ('', 'config', [],
63 _('set/override config option (use \'section.name=value\')'),
63 _('set/override config option (use \'section.name=value\')'),
64 _('CONFIG')),
64 _('CONFIG')),
65 ('', 'debug', None, _('enable debugging output')),
65 ('', 'debug', None, _('enable debugging output')),
66 ('', 'debugger', None, _('start debugger')),
66 ('', 'debugger', None, _('start debugger')),
67 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
67 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
68 _('ENCODE')),
68 _('ENCODE')),
69 ('', 'encodingmode', encoding.encodingmode,
69 ('', 'encodingmode', encoding.encodingmode,
70 _('set the charset encoding mode'), _('MODE')),
70 _('set the charset encoding mode'), _('MODE')),
71 ('', 'traceback', None, _('always print a traceback on exception')),
71 ('', 'traceback', None, _('always print a traceback on exception')),
72 ('', 'time', None, _('time how long the command takes')),
72 ('', 'time', None, _('time how long the command takes')),
73 ('', 'profile', None, _('print command execution profile')),
73 ('', 'profile', None, _('print command execution profile')),
74 ('', 'version', None, _('output version information and exit')),
74 ('', 'version', None, _('output version information and exit')),
75 ('h', 'help', None, _('display help and exit')),
75 ('h', 'help', None, _('display help and exit')),
76 ('', 'hidden', False, _('consider hidden changesets')),
76 ('', 'hidden', False, _('consider hidden changesets')),
77 ]
77 ]
78
78
79 dryrunopts = [('n', 'dry-run', None,
79 dryrunopts = [('n', 'dry-run', None,
80 _('do not perform actions, just print output'))]
80 _('do not perform actions, just print output'))]
81
81
82 remoteopts = [
82 remoteopts = [
83 ('e', 'ssh', '',
83 ('e', 'ssh', '',
84 _('specify ssh command to use'), _('CMD')),
84 _('specify ssh command to use'), _('CMD')),
85 ('', 'remotecmd', '',
85 ('', 'remotecmd', '',
86 _('specify hg command to run on the remote side'), _('CMD')),
86 _('specify hg command to run on the remote side'), _('CMD')),
87 ('', 'insecure', None,
87 ('', 'insecure', None,
88 _('do not verify server certificate (ignoring web.cacerts config)')),
88 _('do not verify server certificate (ignoring web.cacerts config)')),
89 ]
89 ]
90
90
91 walkopts = [
91 walkopts = [
92 ('I', 'include', [],
92 ('I', 'include', [],
93 _('include names matching the given patterns'), _('PATTERN')),
93 _('include names matching the given patterns'), _('PATTERN')),
94 ('X', 'exclude', [],
94 ('X', 'exclude', [],
95 _('exclude names matching the given patterns'), _('PATTERN')),
95 _('exclude names matching the given patterns'), _('PATTERN')),
96 ]
96 ]
97
97
98 commitopts = [
98 commitopts = [
99 ('m', 'message', '',
99 ('m', 'message', '',
100 _('use text as commit message'), _('TEXT')),
100 _('use text as commit message'), _('TEXT')),
101 ('l', 'logfile', '',
101 ('l', 'logfile', '',
102 _('read commit message from file'), _('FILE')),
102 _('read commit message from file'), _('FILE')),
103 ]
103 ]
104
104
105 commitopts2 = [
105 commitopts2 = [
106 ('d', 'date', '',
106 ('d', 'date', '',
107 _('record the specified date as commit date'), _('DATE')),
107 _('record the specified date as commit date'), _('DATE')),
108 ('u', 'user', '',
108 ('u', 'user', '',
109 _('record the specified user as committer'), _('USER')),
109 _('record the specified user as committer'), _('USER')),
110 ]
110 ]
111
111
112 # hidden for now
112 # hidden for now
113 formatteropts = [
113 formatteropts = [
114 ('T', 'template', '',
114 ('T', 'template', '',
115 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
115 _('display with template (EXPERIMENTAL)'), _('TEMPLATE')),
116 ]
116 ]
117
117
118 templateopts = [
118 templateopts = [
119 ('', 'style', '',
119 ('', 'style', '',
120 _('display using template map file (DEPRECATED)'), _('STYLE')),
120 _('display using template map file (DEPRECATED)'), _('STYLE')),
121 ('T', 'template', '',
121 ('T', 'template', '',
122 _('display with template'), _('TEMPLATE')),
122 _('display with template'), _('TEMPLATE')),
123 ]
123 ]
124
124
125 logopts = [
125 logopts = [
126 ('p', 'patch', None, _('show patch')),
126 ('p', 'patch', None, _('show patch')),
127 ('g', 'git', None, _('use git extended diff format')),
127 ('g', 'git', None, _('use git extended diff format')),
128 ('l', 'limit', '',
128 ('l', 'limit', '',
129 _('limit number of changes displayed'), _('NUM')),
129 _('limit number of changes displayed'), _('NUM')),
130 ('M', 'no-merges', None, _('do not show merges')),
130 ('M', 'no-merges', None, _('do not show merges')),
131 ('', 'stat', None, _('output diffstat-style summary of changes')),
131 ('', 'stat', None, _('output diffstat-style summary of changes')),
132 ('G', 'graph', None, _("show the revision DAG")),
132 ('G', 'graph', None, _("show the revision DAG")),
133 ] + templateopts
133 ] + templateopts
134
134
135 diffopts = [
135 diffopts = [
136 ('a', 'text', None, _('treat all files as text')),
136 ('a', 'text', None, _('treat all files as text')),
137 ('g', 'git', None, _('use git extended diff format')),
137 ('g', 'git', None, _('use git extended diff format')),
138 ('', 'nodates', None, _('omit dates from diff headers'))
138 ('', 'nodates', None, _('omit dates from diff headers'))
139 ]
139 ]
140
140
141 diffwsopts = [
141 diffwsopts = [
142 ('w', 'ignore-all-space', None,
142 ('w', 'ignore-all-space', None,
143 _('ignore white space when comparing lines')),
143 _('ignore white space when comparing lines')),
144 ('b', 'ignore-space-change', None,
144 ('b', 'ignore-space-change', None,
145 _('ignore changes in the amount of white space')),
145 _('ignore changes in the amount of white space')),
146 ('B', 'ignore-blank-lines', None,
146 ('B', 'ignore-blank-lines', None,
147 _('ignore changes whose lines are all blank')),
147 _('ignore changes whose lines are all blank')),
148 ]
148 ]
149
149
150 diffopts2 = [
150 diffopts2 = [
151 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
151 ('', 'noprefix', None, _('omit a/ and b/ prefixes from filenames')),
152 ('p', 'show-function', None, _('show which function each change is in')),
152 ('p', 'show-function', None, _('show which function each change is in')),
153 ('', 'reverse', None, _('produce a diff that undoes the changes')),
153 ('', 'reverse', None, _('produce a diff that undoes the changes')),
154 ] + diffwsopts + [
154 ] + diffwsopts + [
155 ('U', 'unified', '',
155 ('U', 'unified', '',
156 _('number of lines of context to show'), _('NUM')),
156 _('number of lines of context to show'), _('NUM')),
157 ('', 'stat', None, _('output diffstat-style summary of changes')),
157 ('', 'stat', None, _('output diffstat-style summary of changes')),
158 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
158 ('', 'root', '', _('produce diffs relative to subdirectory'), _('DIR')),
159 ]
159 ]
160
160
161 mergetoolopts = [
161 mergetoolopts = [
162 ('t', 'tool', '', _('specify merge tool')),
162 ('t', 'tool', '', _('specify merge tool')),
163 ]
163 ]
164
164
165 similarityopts = [
165 similarityopts = [
166 ('s', 'similarity', '',
166 ('s', 'similarity', '',
167 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
167 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
168 ]
168 ]
169
169
170 subrepoopts = [
170 subrepoopts = [
171 ('S', 'subrepos', None,
171 ('S', 'subrepos', None,
172 _('recurse into subrepositories'))
172 _('recurse into subrepositories'))
173 ]
173 ]
174
174
175 # Commands start here, listed alphabetically
175 # Commands start here, listed alphabetically
176
176
177 @command('^add',
177 @command('^add',
178 walkopts + subrepoopts + dryrunopts,
178 walkopts + subrepoopts + dryrunopts,
179 _('[OPTION]... [FILE]...'),
179 _('[OPTION]... [FILE]...'),
180 inferrepo=True)
180 inferrepo=True)
181 def add(ui, repo, *pats, **opts):
181 def add(ui, repo, *pats, **opts):
182 """add the specified files on the next commit
182 """add the specified files on the next commit
183
183
184 Schedule files to be version controlled and added to the
184 Schedule files to be version controlled and added to the
185 repository.
185 repository.
186
186
187 The files will be added to the repository at the next commit. To
187 The files will be added to the repository at the next commit. To
188 undo an add before that, see :hg:`forget`.
188 undo an add before that, see :hg:`forget`.
189
189
190 If no names are given, add all files to the repository.
190 If no names are given, add all files to the repository.
191
191
192 .. container:: verbose
192 .. container:: verbose
193
193
194 An example showing how new (unknown) files are added
194 An example showing how new (unknown) files are added
195 automatically by :hg:`add`::
195 automatically by :hg:`add`::
196
196
197 $ ls
197 $ ls
198 foo.c
198 foo.c
199 $ hg status
199 $ hg status
200 ? foo.c
200 ? foo.c
201 $ hg add
201 $ hg add
202 adding foo.c
202 adding foo.c
203 $ hg status
203 $ hg status
204 A foo.c
204 A foo.c
205
205
206 Returns 0 if all files are successfully added.
206 Returns 0 if all files are successfully added.
207 """
207 """
208
208
209 m = scmutil.match(repo[None], pats, opts)
209 m = scmutil.match(repo[None], pats, opts)
210 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
210 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
211 return rejected and 1 or 0
211 return rejected and 1 or 0
212
212
213 @command('addremove',
213 @command('addremove',
214 similarityopts + subrepoopts + walkopts + dryrunopts,
214 similarityopts + subrepoopts + walkopts + dryrunopts,
215 _('[OPTION]... [FILE]...'),
215 _('[OPTION]... [FILE]...'),
216 inferrepo=True)
216 inferrepo=True)
217 def addremove(ui, repo, *pats, **opts):
217 def addremove(ui, repo, *pats, **opts):
218 """add all new files, delete all missing files
218 """add all new files, delete all missing files
219
219
220 Add all new files and remove all missing files from the
220 Add all new files and remove all missing files from the
221 repository.
221 repository.
222
222
223 New files are ignored if they match any of the patterns in
223 New files are ignored if they match any of the patterns in
224 ``.hgignore``. As with add, these changes take effect at the next
224 ``.hgignore``. As with add, these changes take effect at the next
225 commit.
225 commit.
226
226
227 Use the -s/--similarity option to detect renamed files. This
227 Use the -s/--similarity option to detect renamed files. This
228 option takes a percentage between 0 (disabled) and 100 (files must
228 option takes a percentage between 0 (disabled) and 100 (files must
229 be identical) as its parameter. With a parameter greater than 0,
229 be identical) as its parameter. With a parameter greater than 0,
230 this compares every removed file with every added file and records
230 this compares every removed file with every added file and records
231 those similar enough as renames. Detecting renamed files this way
231 those similar enough as renames. Detecting renamed files this way
232 can be expensive. After using this option, :hg:`status -C` can be
232 can be expensive. After using this option, :hg:`status -C` can be
233 used to check which files were identified as moved or renamed. If
233 used to check which files were identified as moved or renamed. If
234 not specified, -s/--similarity defaults to 100 and only renames of
234 not specified, -s/--similarity defaults to 100 and only renames of
235 identical files are detected.
235 identical files are detected.
236
236
237 Returns 0 if all files are successfully added.
237 Returns 0 if all files are successfully added.
238 """
238 """
239 try:
239 try:
240 sim = float(opts.get('similarity') or 100)
240 sim = float(opts.get('similarity') or 100)
241 except ValueError:
241 except ValueError:
242 raise error.Abort(_('similarity must be a number'))
242 raise error.Abort(_('similarity must be a number'))
243 if sim < 0 or sim > 100:
243 if sim < 0 or sim > 100:
244 raise error.Abort(_('similarity must be between 0 and 100'))
244 raise error.Abort(_('similarity must be between 0 and 100'))
245 matcher = scmutil.match(repo[None], pats, opts)
245 matcher = scmutil.match(repo[None], pats, opts)
246 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
246 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
247
247
248 @command('^annotate|blame',
248 @command('^annotate|blame',
249 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
249 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
250 ('', 'follow', None,
250 ('', 'follow', None,
251 _('follow copies/renames and list the filename (DEPRECATED)')),
251 _('follow copies/renames and list the filename (DEPRECATED)')),
252 ('', 'no-follow', None, _("don't follow copies and renames")),
252 ('', 'no-follow', None, _("don't follow copies and renames")),
253 ('a', 'text', None, _('treat all files as text')),
253 ('a', 'text', None, _('treat all files as text')),
254 ('u', 'user', None, _('list the author (long with -v)')),
254 ('u', 'user', None, _('list the author (long with -v)')),
255 ('f', 'file', None, _('list the filename')),
255 ('f', 'file', None, _('list the filename')),
256 ('d', 'date', None, _('list the date (short with -q)')),
256 ('d', 'date', None, _('list the date (short with -q)')),
257 ('n', 'number', None, _('list the revision number (default)')),
257 ('n', 'number', None, _('list the revision number (default)')),
258 ('c', 'changeset', None, _('list the changeset')),
258 ('c', 'changeset', None, _('list the changeset')),
259 ('l', 'line-number', None, _('show line number at the first appearance'))
259 ('l', 'line-number', None, _('show line number at the first appearance'))
260 ] + diffwsopts + walkopts + formatteropts,
260 ] + diffwsopts + walkopts + formatteropts,
261 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
261 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
262 inferrepo=True)
262 inferrepo=True)
263 def annotate(ui, repo, *pats, **opts):
263 def annotate(ui, repo, *pats, **opts):
264 """show changeset information by line for each file
264 """show changeset information by line for each file
265
265
266 List changes in files, showing the revision id responsible for
266 List changes in files, showing the revision id responsible for
267 each line
267 each line
268
268
269 This command is useful for discovering when a change was made and
269 This command is useful for discovering when a change was made and
270 by whom.
270 by whom.
271
271
272 Without the -a/--text option, annotate will avoid processing files
272 Without the -a/--text option, annotate will avoid processing files
273 it detects as binary. With -a, annotate will annotate the file
273 it detects as binary. With -a, annotate will annotate the file
274 anyway, although the results will probably be neither useful
274 anyway, although the results will probably be neither useful
275 nor desirable.
275 nor desirable.
276
276
277 Returns 0 on success.
277 Returns 0 on success.
278 """
278 """
279 if not pats:
279 if not pats:
280 raise error.Abort(_('at least one filename or pattern is required'))
280 raise error.Abort(_('at least one filename or pattern is required'))
281
281
282 if opts.get('follow'):
282 if opts.get('follow'):
283 # --follow is deprecated and now just an alias for -f/--file
283 # --follow is deprecated and now just an alias for -f/--file
284 # to mimic the behavior of Mercurial before version 1.5
284 # to mimic the behavior of Mercurial before version 1.5
285 opts['file'] = True
285 opts['file'] = True
286
286
287 ctx = scmutil.revsingle(repo, opts.get('rev'))
287 ctx = scmutil.revsingle(repo, opts.get('rev'))
288
288
289 fm = ui.formatter('annotate', opts)
289 fm = ui.formatter('annotate', opts)
290 if ui.quiet:
290 if ui.quiet:
291 datefunc = util.shortdate
291 datefunc = util.shortdate
292 else:
292 else:
293 datefunc = util.datestr
293 datefunc = util.datestr
294 if ctx.rev() is None:
294 if ctx.rev() is None:
295 def hexfn(node):
295 def hexfn(node):
296 if node is None:
296 if node is None:
297 return None
297 return None
298 else:
298 else:
299 return fm.hexfunc(node)
299 return fm.hexfunc(node)
300 if opts.get('changeset'):
300 if opts.get('changeset'):
301 # omit "+" suffix which is appended to node hex
301 # omit "+" suffix which is appended to node hex
302 def formatrev(rev):
302 def formatrev(rev):
303 if rev is None:
303 if rev is None:
304 return '%d' % ctx.p1().rev()
304 return '%d' % ctx.p1().rev()
305 else:
305 else:
306 return '%d' % rev
306 return '%d' % rev
307 else:
307 else:
308 def formatrev(rev):
308 def formatrev(rev):
309 if rev is None:
309 if rev is None:
310 return '%d+' % ctx.p1().rev()
310 return '%d+' % ctx.p1().rev()
311 else:
311 else:
312 return '%d ' % rev
312 return '%d ' % rev
313 def formathex(hex):
313 def formathex(hex):
314 if hex is None:
314 if hex is None:
315 return '%s+' % fm.hexfunc(ctx.p1().node())
315 return '%s+' % fm.hexfunc(ctx.p1().node())
316 else:
316 else:
317 return '%s ' % hex
317 return '%s ' % hex
318 else:
318 else:
319 hexfn = fm.hexfunc
319 hexfn = fm.hexfunc
320 formatrev = formathex = str
320 formatrev = formathex = str
321
321
322 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
322 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
323 ('number', ' ', lambda x: x[0].rev(), formatrev),
323 ('number', ' ', lambda x: x[0].rev(), formatrev),
324 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
324 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
325 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
325 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
326 ('file', ' ', lambda x: x[0].path(), str),
326 ('file', ' ', lambda x: x[0].path(), str),
327 ('line_number', ':', lambda x: x[1], str),
327 ('line_number', ':', lambda x: x[1], str),
328 ]
328 ]
329 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
329 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
330
330
331 if (not opts.get('user') and not opts.get('changeset')
331 if (not opts.get('user') and not opts.get('changeset')
332 and not opts.get('date') and not opts.get('file')):
332 and not opts.get('date') and not opts.get('file')):
333 opts['number'] = True
333 opts['number'] = True
334
334
335 linenumber = opts.get('line_number') is not None
335 linenumber = opts.get('line_number') is not None
336 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
336 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
337 raise error.Abort(_('at least one of -n/-c is required for -l'))
337 raise error.Abort(_('at least one of -n/-c is required for -l'))
338
338
339 if fm:
339 if fm:
340 def makefunc(get, fmt):
340 def makefunc(get, fmt):
341 return get
341 return get
342 else:
342 else:
343 def makefunc(get, fmt):
343 def makefunc(get, fmt):
344 return lambda x: fmt(get(x))
344 return lambda x: fmt(get(x))
345 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
345 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
346 if opts.get(op)]
346 if opts.get(op)]
347 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
347 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
348 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
348 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
349 if opts.get(op))
349 if opts.get(op))
350
350
351 def bad(x, y):
351 def bad(x, y):
352 raise error.Abort("%s: %s" % (x, y))
352 raise error.Abort("%s: %s" % (x, y))
353
353
354 m = scmutil.match(ctx, pats, opts, badfn=bad)
354 m = scmutil.match(ctx, pats, opts, badfn=bad)
355
355
356 follow = not opts.get('no_follow')
356 follow = not opts.get('no_follow')
357 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
357 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
358 whitespace=True)
358 whitespace=True)
359 for abs in ctx.walk(m):
359 for abs in ctx.walk(m):
360 fctx = ctx[abs]
360 fctx = ctx[abs]
361 if not opts.get('text') and util.binary(fctx.data()):
361 if not opts.get('text') and util.binary(fctx.data()):
362 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
362 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
363 continue
363 continue
364
364
365 lines = fctx.annotate(follow=follow, linenumber=linenumber,
365 lines = fctx.annotate(follow=follow, linenumber=linenumber,
366 diffopts=diffopts)
366 diffopts=diffopts)
367 formats = []
367 formats = []
368 pieces = []
368 pieces = []
369
369
370 for f, sep in funcmap:
370 for f, sep in funcmap:
371 l = [f(n) for n, dummy in lines]
371 l = [f(n) for n, dummy in lines]
372 if l:
372 if l:
373 if fm:
373 if fm:
374 formats.append(['%s' for x in l])
374 formats.append(['%s' for x in l])
375 else:
375 else:
376 sizes = [encoding.colwidth(x) for x in l]
376 sizes = [encoding.colwidth(x) for x in l]
377 ml = max(sizes)
377 ml = max(sizes)
378 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
378 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
379 pieces.append(l)
379 pieces.append(l)
380
380
381 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
381 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
382 fm.startitem()
382 fm.startitem()
383 fm.write(fields, "".join(f), *p)
383 fm.write(fields, "".join(f), *p)
384 fm.write('line', ": %s", l[1])
384 fm.write('line', ": %s", l[1])
385
385
386 if lines and not lines[-1][1].endswith('\n'):
386 if lines and not lines[-1][1].endswith('\n'):
387 fm.plain('\n')
387 fm.plain('\n')
388
388
389 fm.end()
389 fm.end()
390
390
391 @command('archive',
391 @command('archive',
392 [('', 'no-decode', None, _('do not pass files through decoders')),
392 [('', 'no-decode', None, _('do not pass files through decoders')),
393 ('p', 'prefix', '', _('directory prefix for files in archive'),
393 ('p', 'prefix', '', _('directory prefix for files in archive'),
394 _('PREFIX')),
394 _('PREFIX')),
395 ('r', 'rev', '', _('revision to distribute'), _('REV')),
395 ('r', 'rev', '', _('revision to distribute'), _('REV')),
396 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
396 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
397 ] + subrepoopts + walkopts,
397 ] + subrepoopts + walkopts,
398 _('[OPTION]... DEST'))
398 _('[OPTION]... DEST'))
399 def archive(ui, repo, dest, **opts):
399 def archive(ui, repo, dest, **opts):
400 '''create an unversioned archive of a repository revision
400 '''create an unversioned archive of a repository revision
401
401
402 By default, the revision used is the parent of the working
402 By default, the revision used is the parent of the working
403 directory; use -r/--rev to specify a different revision.
403 directory; use -r/--rev to specify a different revision.
404
404
405 The archive type is automatically detected based on file
405 The archive type is automatically detected based on file
406 extension (or override using -t/--type).
406 extension (or override using -t/--type).
407
407
408 .. container:: verbose
408 .. container:: verbose
409
409
410 Examples:
410 Examples:
411
411
412 - create a zip file containing the 1.0 release::
412 - create a zip file containing the 1.0 release::
413
413
414 hg archive -r 1.0 project-1.0.zip
414 hg archive -r 1.0 project-1.0.zip
415
415
416 - create a tarball excluding .hg files::
416 - create a tarball excluding .hg files::
417
417
418 hg archive project.tar.gz -X ".hg*"
418 hg archive project.tar.gz -X ".hg*"
419
419
420 Valid types are:
420 Valid types are:
421
421
422 :``files``: a directory full of files (default)
422 :``files``: a directory full of files (default)
423 :``tar``: tar archive, uncompressed
423 :``tar``: tar archive, uncompressed
424 :``tbz2``: tar archive, compressed using bzip2
424 :``tbz2``: tar archive, compressed using bzip2
425 :``tgz``: tar archive, compressed using gzip
425 :``tgz``: tar archive, compressed using gzip
426 :``uzip``: zip archive, uncompressed
426 :``uzip``: zip archive, uncompressed
427 :``zip``: zip archive, compressed using deflate
427 :``zip``: zip archive, compressed using deflate
428
428
429 The exact name of the destination archive or directory is given
429 The exact name of the destination archive or directory is given
430 using a format string; see :hg:`help export` for details.
430 using a format string; see :hg:`help export` for details.
431
431
432 Each member added to an archive file has a directory prefix
432 Each member added to an archive file has a directory prefix
433 prepended. Use -p/--prefix to specify a format string for the
433 prepended. Use -p/--prefix to specify a format string for the
434 prefix. The default is the basename of the archive, with suffixes
434 prefix. The default is the basename of the archive, with suffixes
435 removed.
435 removed.
436
436
437 Returns 0 on success.
437 Returns 0 on success.
438 '''
438 '''
439
439
440 ctx = scmutil.revsingle(repo, opts.get('rev'))
440 ctx = scmutil.revsingle(repo, opts.get('rev'))
441 if not ctx:
441 if not ctx:
442 raise error.Abort(_('no working directory: please specify a revision'))
442 raise error.Abort(_('no working directory: please specify a revision'))
443 node = ctx.node()
443 node = ctx.node()
444 dest = cmdutil.makefilename(repo, dest, node)
444 dest = cmdutil.makefilename(repo, dest, node)
445 if os.path.realpath(dest) == repo.root:
445 if os.path.realpath(dest) == repo.root:
446 raise error.Abort(_('repository root cannot be destination'))
446 raise error.Abort(_('repository root cannot be destination'))
447
447
448 kind = opts.get('type') or archival.guesskind(dest) or 'files'
448 kind = opts.get('type') or archival.guesskind(dest) or 'files'
449 prefix = opts.get('prefix')
449 prefix = opts.get('prefix')
450
450
451 if dest == '-':
451 if dest == '-':
452 if kind == 'files':
452 if kind == 'files':
453 raise error.Abort(_('cannot archive plain files to stdout'))
453 raise error.Abort(_('cannot archive plain files to stdout'))
454 dest = cmdutil.makefileobj(repo, dest)
454 dest = cmdutil.makefileobj(repo, dest)
455 if not prefix:
455 if not prefix:
456 prefix = os.path.basename(repo.root) + '-%h'
456 prefix = os.path.basename(repo.root) + '-%h'
457
457
458 prefix = cmdutil.makefilename(repo, prefix, node)
458 prefix = cmdutil.makefilename(repo, prefix, node)
459 matchfn = scmutil.match(ctx, [], opts)
459 matchfn = scmutil.match(ctx, [], opts)
460 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
460 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
461 matchfn, prefix, subrepos=opts.get('subrepos'))
461 matchfn, prefix, subrepos=opts.get('subrepos'))
462
462
463 @command('backout',
463 @command('backout',
464 [('', 'merge', None, _('merge with old dirstate parent after backout')),
464 [('', 'merge', None, _('merge with old dirstate parent after backout')),
465 ('', 'commit', None, _('commit if no conflicts were encountered')),
465 ('', 'commit', None, _('commit if no conflicts were encountered')),
466 ('', 'parent', '',
466 ('', 'parent', '',
467 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
467 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
468 ('r', 'rev', '', _('revision to backout'), _('REV')),
468 ('r', 'rev', '', _('revision to backout'), _('REV')),
469 ('e', 'edit', False, _('invoke editor on commit messages')),
469 ('e', 'edit', False, _('invoke editor on commit messages')),
470 ] + mergetoolopts + walkopts + commitopts + commitopts2,
470 ] + mergetoolopts + walkopts + commitopts + commitopts2,
471 _('[OPTION]... [-r] REV'))
471 _('[OPTION]... [-r] REV'))
472 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
472 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
473 '''reverse effect of earlier changeset
473 '''reverse effect of earlier changeset
474
474
475 Prepare a new changeset with the effect of REV undone in the
475 Prepare a new changeset with the effect of REV undone in the
476 current working directory.
476 current working directory.
477
477
478 If REV is the parent of the working directory, then this new changeset
478 If REV is the parent of the working directory, then this new changeset
479 is committed automatically. Otherwise, hg needs to merge the
479 is committed automatically. Otherwise, hg needs to merge the
480 changes and the merged result is left uncommitted.
480 changes and the merged result is left uncommitted.
481
481
482 .. note::
482 .. note::
483
483
484 backout cannot be used to fix either an unwanted or
484 backout cannot be used to fix either an unwanted or
485 incorrect merge.
485 incorrect merge.
486
486
487 .. container:: verbose
487 .. container:: verbose
488
488
489 By default, the pending changeset will have one parent,
489 By default, the pending changeset will have one parent,
490 maintaining a linear history. With --merge, the pending
490 maintaining a linear history. With --merge, the pending
491 changeset will instead have two parents: the old parent of the
491 changeset will instead have two parents: the old parent of the
492 working directory and a new child of REV that simply undoes REV.
492 working directory and a new child of REV that simply undoes REV.
493
493
494 Before version 1.7, the behavior without --merge was equivalent
494 Before version 1.7, the behavior without --merge was equivalent
495 to specifying --merge followed by :hg:`update --clean .` to
495 to specifying --merge followed by :hg:`update --clean .` to
496 cancel the merge and leave the child of REV as a head to be
496 cancel the merge and leave the child of REV as a head to be
497 merged separately.
497 merged separately.
498
498
499 See :hg:`help dates` for a list of formats valid for -d/--date.
499 See :hg:`help dates` for a list of formats valid for -d/--date.
500
500
501 See :hg:`help revert` for a way to restore files to the state
501 See :hg:`help revert` for a way to restore files to the state
502 of another revision.
502 of another revision.
503
503
504 Returns 0 on success, 1 if nothing to backout or there are unresolved
504 Returns 0 on success, 1 if nothing to backout or there are unresolved
505 files.
505 files.
506 '''
506 '''
507 if rev and node:
507 if rev and node:
508 raise error.Abort(_("please specify just one revision"))
508 raise error.Abort(_("please specify just one revision"))
509
509
510 if not rev:
510 if not rev:
511 rev = node
511 rev = node
512
512
513 if not rev:
513 if not rev:
514 raise error.Abort(_("please specify a revision to backout"))
514 raise error.Abort(_("please specify a revision to backout"))
515
515
516 date = opts.get('date')
516 date = opts.get('date')
517 if date:
517 if date:
518 opts['date'] = util.parsedate(date)
518 opts['date'] = util.parsedate(date)
519
519
520 cmdutil.checkunfinished(repo)
520 cmdutil.checkunfinished(repo)
521 cmdutil.bailifchanged(repo)
521 cmdutil.bailifchanged(repo)
522 node = scmutil.revsingle(repo, rev).node()
522 node = scmutil.revsingle(repo, rev).node()
523
523
524 op1, op2 = repo.dirstate.parents()
524 op1, op2 = repo.dirstate.parents()
525 if not repo.changelog.isancestor(node, op1):
525 if not repo.changelog.isancestor(node, op1):
526 raise error.Abort(_('cannot backout change that is not an ancestor'))
526 raise error.Abort(_('cannot backout change that is not an ancestor'))
527
527
528 p1, p2 = repo.changelog.parents(node)
528 p1, p2 = repo.changelog.parents(node)
529 if p1 == nullid:
529 if p1 == nullid:
530 raise error.Abort(_('cannot backout a change with no parents'))
530 raise error.Abort(_('cannot backout a change with no parents'))
531 if p2 != nullid:
531 if p2 != nullid:
532 if not opts.get('parent'):
532 if not opts.get('parent'):
533 raise error.Abort(_('cannot backout a merge changeset'))
533 raise error.Abort(_('cannot backout a merge changeset'))
534 p = repo.lookup(opts['parent'])
534 p = repo.lookup(opts['parent'])
535 if p not in (p1, p2):
535 if p not in (p1, p2):
536 raise error.Abort(_('%s is not a parent of %s') %
536 raise error.Abort(_('%s is not a parent of %s') %
537 (short(p), short(node)))
537 (short(p), short(node)))
538 parent = p
538 parent = p
539 else:
539 else:
540 if opts.get('parent'):
540 if opts.get('parent'):
541 raise error.Abort(_('cannot use --parent on non-merge changeset'))
541 raise error.Abort(_('cannot use --parent on non-merge changeset'))
542 parent = p1
542 parent = p1
543
543
544 # the backout should appear on the same branch
544 # the backout should appear on the same branch
545 wlock = repo.wlock()
545 wlock = repo.wlock()
546 try:
546 try:
547 branch = repo.dirstate.branch()
547 branch = repo.dirstate.branch()
548 bheads = repo.branchheads(branch)
548 bheads = repo.branchheads(branch)
549 rctx = scmutil.revsingle(repo, hex(parent))
549 rctx = scmutil.revsingle(repo, hex(parent))
550 if not opts.get('merge') and op1 != node:
550 if not opts.get('merge') and op1 != node:
551 dsguard = cmdutil.dirstateguard(repo, 'backout')
551 dsguard = cmdutil.dirstateguard(repo, 'backout')
552 try:
552 try:
553 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
553 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
554 'backout')
554 'backout')
555 stats = mergemod.update(repo, parent, True, True, False,
555 stats = mergemod.update(repo, parent, True, True, False,
556 node, False)
556 node, False)
557 repo.setparents(op1, op2)
557 repo.setparents(op1, op2)
558 dsguard.close()
558 dsguard.close()
559 hg._showstats(repo, stats)
559 hg._showstats(repo, stats)
560 if stats[3]:
560 if stats[3]:
561 repo.ui.status(_("use 'hg resolve' to retry unresolved "
561 repo.ui.status(_("use 'hg resolve' to retry unresolved "
562 "file merges\n"))
562 "file merges\n"))
563 return 1
563 return 1
564 elif not commit:
564 elif not commit:
565 msg = _("changeset %s backed out, "
565 msg = _("changeset %s backed out, "
566 "don't forget to commit.\n")
566 "don't forget to commit.\n")
567 ui.status(msg % short(node))
567 ui.status(msg % short(node))
568 return 0
568 return 0
569 finally:
569 finally:
570 ui.setconfig('ui', 'forcemerge', '', '')
570 ui.setconfig('ui', 'forcemerge', '', '')
571 lockmod.release(dsguard)
571 lockmod.release(dsguard)
572 else:
572 else:
573 hg.clean(repo, node, show_stats=False)
573 hg.clean(repo, node, show_stats=False)
574 repo.dirstate.setbranch(branch)
574 repo.dirstate.setbranch(branch)
575 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
575 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
576
576
577
577
578 def commitfunc(ui, repo, message, match, opts):
578 def commitfunc(ui, repo, message, match, opts):
579 editform = 'backout'
579 editform = 'backout'
580 e = cmdutil.getcommiteditor(editform=editform, **opts)
580 e = cmdutil.getcommiteditor(editform=editform, **opts)
581 if not message:
581 if not message:
582 # we don't translate commit messages
582 # we don't translate commit messages
583 message = "Backed out changeset %s" % short(node)
583 message = "Backed out changeset %s" % short(node)
584 e = cmdutil.getcommiteditor(edit=True, editform=editform)
584 e = cmdutil.getcommiteditor(edit=True, editform=editform)
585 return repo.commit(message, opts.get('user'), opts.get('date'),
585 return repo.commit(message, opts.get('user'), opts.get('date'),
586 match, editor=e)
586 match, editor=e)
587 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
587 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
588 if not newnode:
588 if not newnode:
589 ui.status(_("nothing changed\n"))
589 ui.status(_("nothing changed\n"))
590 return 1
590 return 1
591 cmdutil.commitstatus(repo, newnode, branch, bheads)
591 cmdutil.commitstatus(repo, newnode, branch, bheads)
592
592
593 def nice(node):
593 def nice(node):
594 return '%d:%s' % (repo.changelog.rev(node), short(node))
594 return '%d:%s' % (repo.changelog.rev(node), short(node))
595 ui.status(_('changeset %s backs out changeset %s\n') %
595 ui.status(_('changeset %s backs out changeset %s\n') %
596 (nice(repo.changelog.tip()), nice(node)))
596 (nice(repo.changelog.tip()), nice(node)))
597 if opts.get('merge') and op1 != node:
597 if opts.get('merge') and op1 != node:
598 hg.clean(repo, op1, show_stats=False)
598 hg.clean(repo, op1, show_stats=False)
599 ui.status(_('merging with changeset %s\n')
599 ui.status(_('merging with changeset %s\n')
600 % nice(repo.changelog.tip()))
600 % nice(repo.changelog.tip()))
601 try:
601 try:
602 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
602 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
603 'backout')
603 'backout')
604 return hg.merge(repo, hex(repo.changelog.tip()))
604 return hg.merge(repo, hex(repo.changelog.tip()))
605 finally:
605 finally:
606 ui.setconfig('ui', 'forcemerge', '', '')
606 ui.setconfig('ui', 'forcemerge', '', '')
607 finally:
607 finally:
608 wlock.release()
608 wlock.release()
609 return 0
609 return 0
610
610
611 @command('bisect',
611 @command('bisect',
612 [('r', 'reset', False, _('reset bisect state')),
612 [('r', 'reset', False, _('reset bisect state')),
613 ('g', 'good', False, _('mark changeset good')),
613 ('g', 'good', False, _('mark changeset good')),
614 ('b', 'bad', False, _('mark changeset bad')),
614 ('b', 'bad', False, _('mark changeset bad')),
615 ('s', 'skip', False, _('skip testing changeset')),
615 ('s', 'skip', False, _('skip testing changeset')),
616 ('e', 'extend', False, _('extend the bisect range')),
616 ('e', 'extend', False, _('extend the bisect range')),
617 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
617 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
618 ('U', 'noupdate', False, _('do not update to target'))],
618 ('U', 'noupdate', False, _('do not update to target'))],
619 _("[-gbsr] [-U] [-c CMD] [REV]"))
619 _("[-gbsr] [-U] [-c CMD] [REV]"))
620 def bisect(ui, repo, rev=None, extra=None, command=None,
620 def bisect(ui, repo, rev=None, extra=None, command=None,
621 reset=None, good=None, bad=None, skip=None, extend=None,
621 reset=None, good=None, bad=None, skip=None, extend=None,
622 noupdate=None):
622 noupdate=None):
623 """subdivision search of changesets
623 """subdivision search of changesets
624
624
625 This command helps to find changesets which introduce problems. To
625 This command helps to find changesets which introduce problems. To
626 use, mark the earliest changeset you know exhibits the problem as
626 use, mark the earliest changeset you know exhibits the problem as
627 bad, then mark the latest changeset which is free from the problem
627 bad, then mark the latest changeset which is free from the problem
628 as good. Bisect will update your working directory to a revision
628 as good. Bisect will update your working directory to a revision
629 for testing (unless the -U/--noupdate option is specified). Once
629 for testing (unless the -U/--noupdate option is specified). Once
630 you have performed tests, mark the working directory as good or
630 you have performed tests, mark the working directory as good or
631 bad, and bisect will either update to another candidate changeset
631 bad, and bisect will either update to another candidate changeset
632 or announce that it has found the bad revision.
632 or announce that it has found the bad revision.
633
633
634 As a shortcut, you can also use the revision argument to mark a
634 As a shortcut, you can also use the revision argument to mark a
635 revision as good or bad without checking it out first.
635 revision as good or bad without checking it out first.
636
636
637 If you supply a command, it will be used for automatic bisection.
637 If you supply a command, it will be used for automatic bisection.
638 The environment variable HG_NODE will contain the ID of the
638 The environment variable HG_NODE will contain the ID of the
639 changeset being tested. The exit status of the command will be
639 changeset being tested. The exit status of the command will be
640 used to mark revisions as good or bad: status 0 means good, 125
640 used to mark revisions as good or bad: status 0 means good, 125
641 means to skip the revision, 127 (command not found) will abort the
641 means to skip the revision, 127 (command not found) will abort the
642 bisection, and any other non-zero exit status means the revision
642 bisection, and any other non-zero exit status means the revision
643 is bad.
643 is bad.
644
644
645 .. container:: verbose
645 .. container:: verbose
646
646
647 Some examples:
647 Some examples:
648
648
649 - start a bisection with known bad revision 34, and good revision 12::
649 - start a bisection with known bad revision 34, and good revision 12::
650
650
651 hg bisect --bad 34
651 hg bisect --bad 34
652 hg bisect --good 12
652 hg bisect --good 12
653
653
654 - advance the current bisection by marking current revision as good or
654 - advance the current bisection by marking current revision as good or
655 bad::
655 bad::
656
656
657 hg bisect --good
657 hg bisect --good
658 hg bisect --bad
658 hg bisect --bad
659
659
660 - mark the current revision, or a known revision, to be skipped (e.g. if
660 - mark the current revision, or a known revision, to be skipped (e.g. if
661 that revision is not usable because of another issue)::
661 that revision is not usable because of another issue)::
662
662
663 hg bisect --skip
663 hg bisect --skip
664 hg bisect --skip 23
664 hg bisect --skip 23
665
665
666 - skip all revisions that do not touch directories ``foo`` or ``bar``::
666 - skip all revisions that do not touch directories ``foo`` or ``bar``::
667
667
668 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
668 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
669
669
670 - forget the current bisection::
670 - forget the current bisection::
671
671
672 hg bisect --reset
672 hg bisect --reset
673
673
674 - use 'make && make tests' to automatically find the first broken
674 - use 'make && make tests' to automatically find the first broken
675 revision::
675 revision::
676
676
677 hg bisect --reset
677 hg bisect --reset
678 hg bisect --bad 34
678 hg bisect --bad 34
679 hg bisect --good 12
679 hg bisect --good 12
680 hg bisect --command "make && make tests"
680 hg bisect --command "make && make tests"
681
681
682 - see all changesets whose states are already known in the current
682 - see all changesets whose states are already known in the current
683 bisection::
683 bisection::
684
684
685 hg log -r "bisect(pruned)"
685 hg log -r "bisect(pruned)"
686
686
687 - see the changeset currently being bisected (especially useful
687 - see the changeset currently being bisected (especially useful
688 if running with -U/--noupdate)::
688 if running with -U/--noupdate)::
689
689
690 hg log -r "bisect(current)"
690 hg log -r "bisect(current)"
691
691
692 - see all changesets that took part in the current bisection::
692 - see all changesets that took part in the current bisection::
693
693
694 hg log -r "bisect(range)"
694 hg log -r "bisect(range)"
695
695
696 - you can even get a nice graph::
696 - you can even get a nice graph::
697
697
698 hg log --graph -r "bisect(range)"
698 hg log --graph -r "bisect(range)"
699
699
700 See :hg:`help revsets` for more about the `bisect()` keyword.
700 See :hg:`help revsets` for more about the `bisect()` keyword.
701
701
702 Returns 0 on success.
702 Returns 0 on success.
703 """
703 """
704 def extendbisectrange(nodes, good):
704 def extendbisectrange(nodes, good):
705 # bisect is incomplete when it ends on a merge node and
705 # bisect is incomplete when it ends on a merge node and
706 # one of the parent was not checked.
706 # one of the parent was not checked.
707 parents = repo[nodes[0]].parents()
707 parents = repo[nodes[0]].parents()
708 if len(parents) > 1:
708 if len(parents) > 1:
709 if good:
709 if good:
710 side = state['bad']
710 side = state['bad']
711 else:
711 else:
712 side = state['good']
712 side = state['good']
713 num = len(set(i.node() for i in parents) & set(side))
713 num = len(set(i.node() for i in parents) & set(side))
714 if num == 1:
714 if num == 1:
715 return parents[0].ancestor(parents[1])
715 return parents[0].ancestor(parents[1])
716 return None
716 return None
717
717
718 def print_result(nodes, good):
718 def print_result(nodes, good):
719 displayer = cmdutil.show_changeset(ui, repo, {})
719 displayer = cmdutil.show_changeset(ui, repo, {})
720 if len(nodes) == 1:
720 if len(nodes) == 1:
721 # narrowed it down to a single revision
721 # narrowed it down to a single revision
722 if good:
722 if good:
723 ui.write(_("The first good revision is:\n"))
723 ui.write(_("The first good revision is:\n"))
724 else:
724 else:
725 ui.write(_("The first bad revision is:\n"))
725 ui.write(_("The first bad revision is:\n"))
726 displayer.show(repo[nodes[0]])
726 displayer.show(repo[nodes[0]])
727 extendnode = extendbisectrange(nodes, good)
727 extendnode = extendbisectrange(nodes, good)
728 if extendnode is not None:
728 if extendnode is not None:
729 ui.write(_('Not all ancestors of this changeset have been'
729 ui.write(_('Not all ancestors of this changeset have been'
730 ' checked.\nUse bisect --extend to continue the '
730 ' checked.\nUse bisect --extend to continue the '
731 'bisection from\nthe common ancestor, %s.\n')
731 'bisection from\nthe common ancestor, %s.\n')
732 % extendnode)
732 % extendnode)
733 else:
733 else:
734 # multiple possible revisions
734 # multiple possible revisions
735 if good:
735 if good:
736 ui.write(_("Due to skipped revisions, the first "
736 ui.write(_("Due to skipped revisions, the first "
737 "good revision could be any of:\n"))
737 "good revision could be any of:\n"))
738 else:
738 else:
739 ui.write(_("Due to skipped revisions, the first "
739 ui.write(_("Due to skipped revisions, the first "
740 "bad revision could be any of:\n"))
740 "bad revision could be any of:\n"))
741 for n in nodes:
741 for n in nodes:
742 displayer.show(repo[n])
742 displayer.show(repo[n])
743 displayer.close()
743 displayer.close()
744
744
745 def check_state(state, interactive=True):
745 def check_state(state, interactive=True):
746 if not state['good'] or not state['bad']:
746 if not state['good'] or not state['bad']:
747 if (good or bad or skip or reset) and interactive:
747 if (good or bad or skip or reset) and interactive:
748 return
748 return
749 if not state['good']:
749 if not state['good']:
750 raise error.Abort(_('cannot bisect (no known good revisions)'))
750 raise error.Abort(_('cannot bisect (no known good revisions)'))
751 else:
751 else:
752 raise error.Abort(_('cannot bisect (no known bad revisions)'))
752 raise error.Abort(_('cannot bisect (no known bad revisions)'))
753 return True
753 return True
754
754
755 # backward compatibility
755 # backward compatibility
756 if rev in "good bad reset init".split():
756 if rev in "good bad reset init".split():
757 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
757 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
758 cmd, rev, extra = rev, extra, None
758 cmd, rev, extra = rev, extra, None
759 if cmd == "good":
759 if cmd == "good":
760 good = True
760 good = True
761 elif cmd == "bad":
761 elif cmd == "bad":
762 bad = True
762 bad = True
763 else:
763 else:
764 reset = True
764 reset = True
765 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
765 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
766 raise error.Abort(_('incompatible arguments'))
766 raise error.Abort(_('incompatible arguments'))
767
767
768 cmdutil.checkunfinished(repo)
768 cmdutil.checkunfinished(repo)
769
769
770 if reset:
770 if reset:
771 p = repo.join("bisect.state")
771 p = repo.join("bisect.state")
772 if os.path.exists(p):
772 if os.path.exists(p):
773 os.unlink(p)
773 os.unlink(p)
774 return
774 return
775
775
776 state = hbisect.load_state(repo)
776 state = hbisect.load_state(repo)
777
777
778 if command:
778 if command:
779 changesets = 1
779 changesets = 1
780 if noupdate:
780 if noupdate:
781 try:
781 try:
782 node = state['current'][0]
782 node = state['current'][0]
783 except LookupError:
783 except LookupError:
784 raise error.Abort(_('current bisect revision is unknown - '
784 raise error.Abort(_('current bisect revision is unknown - '
785 'start a new bisect to fix'))
785 'start a new bisect to fix'))
786 else:
786 else:
787 node, p2 = repo.dirstate.parents()
787 node, p2 = repo.dirstate.parents()
788 if p2 != nullid:
788 if p2 != nullid:
789 raise error.Abort(_('current bisect revision is a merge'))
789 raise error.Abort(_('current bisect revision is a merge'))
790 try:
790 try:
791 while changesets:
791 while changesets:
792 # update state
792 # update state
793 state['current'] = [node]
793 state['current'] = [node]
794 hbisect.save_state(repo, state)
794 hbisect.save_state(repo, state)
795 status = ui.system(command, environ={'HG_NODE': hex(node)})
795 status = ui.system(command, environ={'HG_NODE': hex(node)})
796 if status == 125:
796 if status == 125:
797 transition = "skip"
797 transition = "skip"
798 elif status == 0:
798 elif status == 0:
799 transition = "good"
799 transition = "good"
800 # status < 0 means process was killed
800 # status < 0 means process was killed
801 elif status == 127:
801 elif status == 127:
802 raise error.Abort(_("failed to execute %s") % command)
802 raise error.Abort(_("failed to execute %s") % command)
803 elif status < 0:
803 elif status < 0:
804 raise error.Abort(_("%s killed") % command)
804 raise error.Abort(_("%s killed") % command)
805 else:
805 else:
806 transition = "bad"
806 transition = "bad"
807 ctx = scmutil.revsingle(repo, rev, node)
807 ctx = scmutil.revsingle(repo, rev, node)
808 rev = None # clear for future iterations
808 rev = None # clear for future iterations
809 state[transition].append(ctx.node())
809 state[transition].append(ctx.node())
810 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
810 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
811 check_state(state, interactive=False)
811 check_state(state, interactive=False)
812 # bisect
812 # bisect
813 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
813 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
814 # update to next check
814 # update to next check
815 node = nodes[0]
815 node = nodes[0]
816 if not noupdate:
816 if not noupdate:
817 cmdutil.bailifchanged(repo)
817 cmdutil.bailifchanged(repo)
818 hg.clean(repo, node, show_stats=False)
818 hg.clean(repo, node, show_stats=False)
819 finally:
819 finally:
820 state['current'] = [node]
820 state['current'] = [node]
821 hbisect.save_state(repo, state)
821 hbisect.save_state(repo, state)
822 print_result(nodes, bgood)
822 print_result(nodes, bgood)
823 return
823 return
824
824
825 # update state
825 # update state
826
826
827 if rev:
827 if rev:
828 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
828 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
829 else:
829 else:
830 nodes = [repo.lookup('.')]
830 nodes = [repo.lookup('.')]
831
831
832 if good or bad or skip:
832 if good or bad or skip:
833 if good:
833 if good:
834 state['good'] += nodes
834 state['good'] += nodes
835 elif bad:
835 elif bad:
836 state['bad'] += nodes
836 state['bad'] += nodes
837 elif skip:
837 elif skip:
838 state['skip'] += nodes
838 state['skip'] += nodes
839 hbisect.save_state(repo, state)
839 hbisect.save_state(repo, state)
840
840
841 if not check_state(state):
841 if not check_state(state):
842 return
842 return
843
843
844 # actually bisect
844 # actually bisect
845 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
845 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
846 if extend:
846 if extend:
847 if not changesets:
847 if not changesets:
848 extendnode = extendbisectrange(nodes, good)
848 extendnode = extendbisectrange(nodes, good)
849 if extendnode is not None:
849 if extendnode is not None:
850 ui.write(_("Extending search to changeset %d:%s\n")
850 ui.write(_("Extending search to changeset %d:%s\n")
851 % (extendnode.rev(), extendnode))
851 % (extendnode.rev(), extendnode))
852 state['current'] = [extendnode.node()]
852 state['current'] = [extendnode.node()]
853 hbisect.save_state(repo, state)
853 hbisect.save_state(repo, state)
854 if noupdate:
854 if noupdate:
855 return
855 return
856 cmdutil.bailifchanged(repo)
856 cmdutil.bailifchanged(repo)
857 return hg.clean(repo, extendnode.node())
857 return hg.clean(repo, extendnode.node())
858 raise error.Abort(_("nothing to extend"))
858 raise error.Abort(_("nothing to extend"))
859
859
860 if changesets == 0:
860 if changesets == 0:
861 print_result(nodes, good)
861 print_result(nodes, good)
862 else:
862 else:
863 assert len(nodes) == 1 # only a single node can be tested next
863 assert len(nodes) == 1 # only a single node can be tested next
864 node = nodes[0]
864 node = nodes[0]
865 # compute the approximate number of remaining tests
865 # compute the approximate number of remaining tests
866 tests, size = 0, 2
866 tests, size = 0, 2
867 while size <= changesets:
867 while size <= changesets:
868 tests, size = tests + 1, size * 2
868 tests, size = tests + 1, size * 2
869 rev = repo.changelog.rev(node)
869 rev = repo.changelog.rev(node)
870 ui.write(_("Testing changeset %d:%s "
870 ui.write(_("Testing changeset %d:%s "
871 "(%d changesets remaining, ~%d tests)\n")
871 "(%d changesets remaining, ~%d tests)\n")
872 % (rev, short(node), changesets, tests))
872 % (rev, short(node), changesets, tests))
873 state['current'] = [node]
873 state['current'] = [node]
874 hbisect.save_state(repo, state)
874 hbisect.save_state(repo, state)
875 if not noupdate:
875 if not noupdate:
876 cmdutil.bailifchanged(repo)
876 cmdutil.bailifchanged(repo)
877 return hg.clean(repo, node)
877 return hg.clean(repo, node)
878
878
879 @command('bookmarks|bookmark',
879 @command('bookmarks|bookmark',
880 [('f', 'force', False, _('force')),
880 [('f', 'force', False, _('force')),
881 ('r', 'rev', '', _('revision'), _('REV')),
881 ('r', 'rev', '', _('revision'), _('REV')),
882 ('d', 'delete', False, _('delete a given bookmark')),
882 ('d', 'delete', False, _('delete a given bookmark')),
883 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
883 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
884 ('i', 'inactive', False, _('mark a bookmark inactive')),
884 ('i', 'inactive', False, _('mark a bookmark inactive')),
885 ] + formatteropts,
885 ] + formatteropts,
886 _('hg bookmarks [OPTIONS]... [NAME]...'))
886 _('hg bookmarks [OPTIONS]... [NAME]...'))
887 def bookmark(ui, repo, *names, **opts):
887 def bookmark(ui, repo, *names, **opts):
888 '''create a new bookmark or list existing bookmarks
888 '''create a new bookmark or list existing bookmarks
889
889
890 Bookmarks are labels on changesets to help track lines of development.
890 Bookmarks are labels on changesets to help track lines of development.
891 Bookmarks are unversioned and can be moved, renamed and deleted.
891 Bookmarks are unversioned and can be moved, renamed and deleted.
892 Deleting or moving a bookmark has no effect on the associated changesets.
892 Deleting or moving a bookmark has no effect on the associated changesets.
893
893
894 Creating or updating to a bookmark causes it to be marked as 'active'.
894 Creating or updating to a bookmark causes it to be marked as 'active'.
895 The active bookmark is indicated with a '*'.
895 The active bookmark is indicated with a '*'.
896 When a commit is made, the active bookmark will advance to the new commit.
896 When a commit is made, the active bookmark will advance to the new commit.
897 A plain :hg:`update` will also advance an active bookmark, if possible.
897 A plain :hg:`update` will also advance an active bookmark, if possible.
898 Updating away from a bookmark will cause it to be deactivated.
898 Updating away from a bookmark will cause it to be deactivated.
899
899
900 Bookmarks can be pushed and pulled between repositories (see
900 Bookmarks can be pushed and pulled between repositories (see
901 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
901 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
902 diverged, a new 'divergent bookmark' of the form 'name@path' will
902 diverged, a new 'divergent bookmark' of the form 'name@path' will
903 be created. Using :hg:`merge` will resolve the divergence.
903 be created. Using :hg:`merge` will resolve the divergence.
904
904
905 A bookmark named '@' has the special property that :hg:`clone` will
905 A bookmark named '@' has the special property that :hg:`clone` will
906 check it out by default if it exists.
906 check it out by default if it exists.
907
907
908 .. container:: verbose
908 .. container:: verbose
909
909
910 Examples:
910 Examples:
911
911
912 - create an active bookmark for a new line of development::
912 - create an active bookmark for a new line of development::
913
913
914 hg book new-feature
914 hg book new-feature
915
915
916 - create an inactive bookmark as a place marker::
916 - create an inactive bookmark as a place marker::
917
917
918 hg book -i reviewed
918 hg book -i reviewed
919
919
920 - create an inactive bookmark on another changeset::
920 - create an inactive bookmark on another changeset::
921
921
922 hg book -r .^ tested
922 hg book -r .^ tested
923
923
924 - rename bookmark turkey to dinner::
924 - rename bookmark turkey to dinner::
925
925
926 hg book -m turkey dinner
926 hg book -m turkey dinner
927
927
928 - move the '@' bookmark from another branch::
928 - move the '@' bookmark from another branch::
929
929
930 hg book -f @
930 hg book -f @
931 '''
931 '''
932 force = opts.get('force')
932 force = opts.get('force')
933 rev = opts.get('rev')
933 rev = opts.get('rev')
934 delete = opts.get('delete')
934 delete = opts.get('delete')
935 rename = opts.get('rename')
935 rename = opts.get('rename')
936 inactive = opts.get('inactive')
936 inactive = opts.get('inactive')
937
937
938 def checkformat(mark):
938 def checkformat(mark):
939 mark = mark.strip()
939 mark = mark.strip()
940 if not mark:
940 if not mark:
941 raise error.Abort(_("bookmark names cannot consist entirely of "
941 raise error.Abort(_("bookmark names cannot consist entirely of "
942 "whitespace"))
942 "whitespace"))
943 scmutil.checknewlabel(repo, mark, 'bookmark')
943 scmutil.checknewlabel(repo, mark, 'bookmark')
944 return mark
944 return mark
945
945
946 def checkconflict(repo, mark, cur, force=False, target=None):
946 def checkconflict(repo, mark, cur, force=False, target=None):
947 if mark in marks and not force:
947 if mark in marks and not force:
948 if target:
948 if target:
949 if marks[mark] == target and target == cur:
949 if marks[mark] == target and target == cur:
950 # re-activating a bookmark
950 # re-activating a bookmark
951 return
951 return
952 anc = repo.changelog.ancestors([repo[target].rev()])
952 anc = repo.changelog.ancestors([repo[target].rev()])
953 bmctx = repo[marks[mark]]
953 bmctx = repo[marks[mark]]
954 divs = [repo[b].node() for b in marks
954 divs = [repo[b].node() for b in marks
955 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
955 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
956
956
957 # allow resolving a single divergent bookmark even if moving
957 # allow resolving a single divergent bookmark even if moving
958 # the bookmark across branches when a revision is specified
958 # the bookmark across branches when a revision is specified
959 # that contains a divergent bookmark
959 # that contains a divergent bookmark
960 if bmctx.rev() not in anc and target in divs:
960 if bmctx.rev() not in anc and target in divs:
961 bookmarks.deletedivergent(repo, [target], mark)
961 bookmarks.deletedivergent(repo, [target], mark)
962 return
962 return
963
963
964 deletefrom = [b for b in divs
964 deletefrom = [b for b in divs
965 if repo[b].rev() in anc or b == target]
965 if repo[b].rev() in anc or b == target]
966 bookmarks.deletedivergent(repo, deletefrom, mark)
966 bookmarks.deletedivergent(repo, deletefrom, mark)
967 if bookmarks.validdest(repo, bmctx, repo[target]):
967 if bookmarks.validdest(repo, bmctx, repo[target]):
968 ui.status(_("moving bookmark '%s' forward from %s\n") %
968 ui.status(_("moving bookmark '%s' forward from %s\n") %
969 (mark, short(bmctx.node())))
969 (mark, short(bmctx.node())))
970 return
970 return
971 raise error.Abort(_("bookmark '%s' already exists "
971 raise error.Abort(_("bookmark '%s' already exists "
972 "(use -f to force)") % mark)
972 "(use -f to force)") % mark)
973 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
973 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
974 and not force):
974 and not force):
975 raise error.Abort(
975 raise error.Abort(
976 _("a bookmark cannot have the name of an existing branch"))
976 _("a bookmark cannot have the name of an existing branch"))
977
977
978 if delete and rename:
978 if delete and rename:
979 raise error.Abort(_("--delete and --rename are incompatible"))
979 raise error.Abort(_("--delete and --rename are incompatible"))
980 if delete and rev:
980 if delete and rev:
981 raise error.Abort(_("--rev is incompatible with --delete"))
981 raise error.Abort(_("--rev is incompatible with --delete"))
982 if rename and rev:
982 if rename and rev:
983 raise error.Abort(_("--rev is incompatible with --rename"))
983 raise error.Abort(_("--rev is incompatible with --rename"))
984 if not names and (delete or rev):
984 if not names and (delete or rev):
985 raise error.Abort(_("bookmark name required"))
985 raise error.Abort(_("bookmark name required"))
986
986
987 if delete or rename or names or inactive:
987 if delete or rename or names or inactive:
988 wlock = lock = tr = None
988 wlock = lock = tr = None
989 try:
989 try:
990 wlock = repo.wlock()
990 wlock = repo.wlock()
991 lock = repo.lock()
991 lock = repo.lock()
992 cur = repo.changectx('.').node()
992 cur = repo.changectx('.').node()
993 marks = repo._bookmarks
993 marks = repo._bookmarks
994 if delete:
994 if delete:
995 tr = repo.transaction('bookmark')
995 tr = repo.transaction('bookmark')
996 for mark in names:
996 for mark in names:
997 if mark not in marks:
997 if mark not in marks:
998 raise error.Abort(_("bookmark '%s' does not exist") %
998 raise error.Abort(_("bookmark '%s' does not exist") %
999 mark)
999 mark)
1000 if mark == repo._activebookmark:
1000 if mark == repo._activebookmark:
1001 bookmarks.deactivate(repo)
1001 bookmarks.deactivate(repo)
1002 del marks[mark]
1002 del marks[mark]
1003
1003
1004 elif rename:
1004 elif rename:
1005 tr = repo.transaction('bookmark')
1005 tr = repo.transaction('bookmark')
1006 if not names:
1006 if not names:
1007 raise error.Abort(_("new bookmark name required"))
1007 raise error.Abort(_("new bookmark name required"))
1008 elif len(names) > 1:
1008 elif len(names) > 1:
1009 raise error.Abort(_("only one new bookmark name allowed"))
1009 raise error.Abort(_("only one new bookmark name allowed"))
1010 mark = checkformat(names[0])
1010 mark = checkformat(names[0])
1011 if rename not in marks:
1011 if rename not in marks:
1012 raise error.Abort(_("bookmark '%s' does not exist")
1012 raise error.Abort(_("bookmark '%s' does not exist")
1013 % rename)
1013 % rename)
1014 checkconflict(repo, mark, cur, force)
1014 checkconflict(repo, mark, cur, force)
1015 marks[mark] = marks[rename]
1015 marks[mark] = marks[rename]
1016 if repo._activebookmark == rename and not inactive:
1016 if repo._activebookmark == rename and not inactive:
1017 bookmarks.activate(repo, mark)
1017 bookmarks.activate(repo, mark)
1018 del marks[rename]
1018 del marks[rename]
1019 elif names:
1019 elif names:
1020 tr = repo.transaction('bookmark')
1020 tr = repo.transaction('bookmark')
1021 newact = None
1021 newact = None
1022 for mark in names:
1022 for mark in names:
1023 mark = checkformat(mark)
1023 mark = checkformat(mark)
1024 if newact is None:
1024 if newact is None:
1025 newact = mark
1025 newact = mark
1026 if inactive and mark == repo._activebookmark:
1026 if inactive and mark == repo._activebookmark:
1027 bookmarks.deactivate(repo)
1027 bookmarks.deactivate(repo)
1028 return
1028 return
1029 tgt = cur
1029 tgt = cur
1030 if rev:
1030 if rev:
1031 tgt = scmutil.revsingle(repo, rev).node()
1031 tgt = scmutil.revsingle(repo, rev).node()
1032 checkconflict(repo, mark, cur, force, tgt)
1032 checkconflict(repo, mark, cur, force, tgt)
1033 marks[mark] = tgt
1033 marks[mark] = tgt
1034 if not inactive and cur == marks[newact] and not rev:
1034 if not inactive and cur == marks[newact] and not rev:
1035 bookmarks.activate(repo, newact)
1035 bookmarks.activate(repo, newact)
1036 elif cur != tgt and newact == repo._activebookmark:
1036 elif cur != tgt and newact == repo._activebookmark:
1037 bookmarks.deactivate(repo)
1037 bookmarks.deactivate(repo)
1038 elif inactive:
1038 elif inactive:
1039 if len(marks) == 0:
1039 if len(marks) == 0:
1040 ui.status(_("no bookmarks set\n"))
1040 ui.status(_("no bookmarks set\n"))
1041 elif not repo._activebookmark:
1041 elif not repo._activebookmark:
1042 ui.status(_("no active bookmark\n"))
1042 ui.status(_("no active bookmark\n"))
1043 else:
1043 else:
1044 bookmarks.deactivate(repo)
1044 bookmarks.deactivate(repo)
1045 if tr is not None:
1045 if tr is not None:
1046 marks.recordchange(tr)
1046 marks.recordchange(tr)
1047 tr.close()
1047 tr.close()
1048 finally:
1048 finally:
1049 lockmod.release(tr, lock, wlock)
1049 lockmod.release(tr, lock, wlock)
1050 else: # show bookmarks
1050 else: # show bookmarks
1051 fm = ui.formatter('bookmarks', opts)
1051 fm = ui.formatter('bookmarks', opts)
1052 hexfn = fm.hexfunc
1052 hexfn = fm.hexfunc
1053 marks = repo._bookmarks
1053 marks = repo._bookmarks
1054 if len(marks) == 0 and not fm:
1054 if len(marks) == 0 and not fm:
1055 ui.status(_("no bookmarks set\n"))
1055 ui.status(_("no bookmarks set\n"))
1056 for bmark, n in sorted(marks.iteritems()):
1056 for bmark, n in sorted(marks.iteritems()):
1057 active = repo._activebookmark
1057 active = repo._activebookmark
1058 if bmark == active:
1058 if bmark == active:
1059 prefix, label = '*', activebookmarklabel
1059 prefix, label = '*', activebookmarklabel
1060 else:
1060 else:
1061 prefix, label = ' ', ''
1061 prefix, label = ' ', ''
1062
1062
1063 fm.startitem()
1063 fm.startitem()
1064 if not ui.quiet:
1064 if not ui.quiet:
1065 fm.plain(' %s ' % prefix, label=label)
1065 fm.plain(' %s ' % prefix, label=label)
1066 fm.write('bookmark', '%s', bmark, label=label)
1066 fm.write('bookmark', '%s', bmark, label=label)
1067 pad = " " * (25 - encoding.colwidth(bmark))
1067 pad = " " * (25 - encoding.colwidth(bmark))
1068 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1068 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1069 repo.changelog.rev(n), hexfn(n), label=label)
1069 repo.changelog.rev(n), hexfn(n), label=label)
1070 fm.data(active=(bmark == active))
1070 fm.data(active=(bmark == active))
1071 fm.plain('\n')
1071 fm.plain('\n')
1072 fm.end()
1072 fm.end()
1073
1073
1074 @command('branch',
1074 @command('branch',
1075 [('f', 'force', None,
1075 [('f', 'force', None,
1076 _('set branch name even if it shadows an existing branch')),
1076 _('set branch name even if it shadows an existing branch')),
1077 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1077 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1078 _('[-fC] [NAME]'))
1078 _('[-fC] [NAME]'))
1079 def branch(ui, repo, label=None, **opts):
1079 def branch(ui, repo, label=None, **opts):
1080 """set or show the current branch name
1080 """set or show the current branch name
1081
1081
1082 .. note::
1082 .. note::
1083
1083
1084 Branch names are permanent and global. Use :hg:`bookmark` to create a
1084 Branch names are permanent and global. Use :hg:`bookmark` to create a
1085 light-weight bookmark instead. See :hg:`help glossary` for more
1085 light-weight bookmark instead. See :hg:`help glossary` for more
1086 information about named branches and bookmarks.
1086 information about named branches and bookmarks.
1087
1087
1088 With no argument, show the current branch name. With one argument,
1088 With no argument, show the current branch name. With one argument,
1089 set the working directory branch name (the branch will not exist
1089 set the working directory branch name (the branch will not exist
1090 in the repository until the next commit). Standard practice
1090 in the repository until the next commit). Standard practice
1091 recommends that primary development take place on the 'default'
1091 recommends that primary development take place on the 'default'
1092 branch.
1092 branch.
1093
1093
1094 Unless -f/--force is specified, branch will not let you set a
1094 Unless -f/--force is specified, branch will not let you set a
1095 branch name that already exists.
1095 branch name that already exists.
1096
1096
1097 Use -C/--clean to reset the working directory branch to that of
1097 Use -C/--clean to reset the working directory branch to that of
1098 the parent of the working directory, negating a previous branch
1098 the parent of the working directory, negating a previous branch
1099 change.
1099 change.
1100
1100
1101 Use the command :hg:`update` to switch to an existing branch. Use
1101 Use the command :hg:`update` to switch to an existing branch. Use
1102 :hg:`commit --close-branch` to mark this branch head as closed.
1102 :hg:`commit --close-branch` to mark this branch head as closed.
1103 When all heads of the branch are closed, the branch will be
1103 When all heads of the branch are closed, the branch will be
1104 considered closed.
1104 considered closed.
1105
1105
1106 Returns 0 on success.
1106 Returns 0 on success.
1107 """
1107 """
1108 if label:
1108 if label:
1109 label = label.strip()
1109 label = label.strip()
1110
1110
1111 if not opts.get('clean') and not label:
1111 if not opts.get('clean') and not label:
1112 ui.write("%s\n" % repo.dirstate.branch())
1112 ui.write("%s\n" % repo.dirstate.branch())
1113 return
1113 return
1114
1114
1115 wlock = repo.wlock()
1115 wlock = repo.wlock()
1116 try:
1116 try:
1117 if opts.get('clean'):
1117 if opts.get('clean'):
1118 label = repo[None].p1().branch()
1118 label = repo[None].p1().branch()
1119 repo.dirstate.setbranch(label)
1119 repo.dirstate.setbranch(label)
1120 ui.status(_('reset working directory to branch %s\n') % label)
1120 ui.status(_('reset working directory to branch %s\n') % label)
1121 elif label:
1121 elif label:
1122 if not opts.get('force') and label in repo.branchmap():
1122 if not opts.get('force') and label in repo.branchmap():
1123 if label not in [p.branch() for p in repo.parents()]:
1123 if label not in [p.branch() for p in repo.parents()]:
1124 raise error.Abort(_('a branch of the same name already'
1124 raise error.Abort(_('a branch of the same name already'
1125 ' exists'),
1125 ' exists'),
1126 # i18n: "it" refers to an existing branch
1126 # i18n: "it" refers to an existing branch
1127 hint=_("use 'hg update' to switch to it"))
1127 hint=_("use 'hg update' to switch to it"))
1128 scmutil.checknewlabel(repo, label, 'branch')
1128 scmutil.checknewlabel(repo, label, 'branch')
1129 repo.dirstate.setbranch(label)
1129 repo.dirstate.setbranch(label)
1130 ui.status(_('marked working directory as branch %s\n') % label)
1130 ui.status(_('marked working directory as branch %s\n') % label)
1131
1131
1132 # find any open named branches aside from default
1132 # find any open named branches aside from default
1133 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1133 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1134 if n != "default" and not c]
1134 if n != "default" and not c]
1135 if not others:
1135 if not others:
1136 ui.status(_('(branches are permanent and global, '
1136 ui.status(_('(branches are permanent and global, '
1137 'did you want a bookmark?)\n'))
1137 'did you want a bookmark?)\n'))
1138 finally:
1138 finally:
1139 wlock.release()
1139 wlock.release()
1140
1140
1141 @command('branches',
1141 @command('branches',
1142 [('a', 'active', False,
1142 [('a', 'active', False,
1143 _('show only branches that have unmerged heads (DEPRECATED)')),
1143 _('show only branches that have unmerged heads (DEPRECATED)')),
1144 ('c', 'closed', False, _('show normal and closed branches')),
1144 ('c', 'closed', False, _('show normal and closed branches')),
1145 ] + formatteropts,
1145 ] + formatteropts,
1146 _('[-ac]'))
1146 _('[-ac]'))
1147 def branches(ui, repo, active=False, closed=False, **opts):
1147 def branches(ui, repo, active=False, closed=False, **opts):
1148 """list repository named branches
1148 """list repository named branches
1149
1149
1150 List the repository's named branches, indicating which ones are
1150 List the repository's named branches, indicating which ones are
1151 inactive. If -c/--closed is specified, also list branches which have
1151 inactive. If -c/--closed is specified, also list branches which have
1152 been marked closed (see :hg:`commit --close-branch`).
1152 been marked closed (see :hg:`commit --close-branch`).
1153
1153
1154 Use the command :hg:`update` to switch to an existing branch.
1154 Use the command :hg:`update` to switch to an existing branch.
1155
1155
1156 Returns 0.
1156 Returns 0.
1157 """
1157 """
1158
1158
1159 fm = ui.formatter('branches', opts)
1159 fm = ui.formatter('branches', opts)
1160 hexfunc = fm.hexfunc
1160 hexfunc = fm.hexfunc
1161
1161
1162 allheads = set(repo.heads())
1162 allheads = set(repo.heads())
1163 branches = []
1163 branches = []
1164 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1164 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1165 isactive = not isclosed and bool(set(heads) & allheads)
1165 isactive = not isclosed and bool(set(heads) & allheads)
1166 branches.append((tag, repo[tip], isactive, not isclosed))
1166 branches.append((tag, repo[tip], isactive, not isclosed))
1167 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1167 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1168 reverse=True)
1168 reverse=True)
1169
1169
1170 for tag, ctx, isactive, isopen in branches:
1170 for tag, ctx, isactive, isopen in branches:
1171 if active and not isactive:
1171 if active and not isactive:
1172 continue
1172 continue
1173 if isactive:
1173 if isactive:
1174 label = 'branches.active'
1174 label = 'branches.active'
1175 notice = ''
1175 notice = ''
1176 elif not isopen:
1176 elif not isopen:
1177 if not closed:
1177 if not closed:
1178 continue
1178 continue
1179 label = 'branches.closed'
1179 label = 'branches.closed'
1180 notice = _(' (closed)')
1180 notice = _(' (closed)')
1181 else:
1181 else:
1182 label = 'branches.inactive'
1182 label = 'branches.inactive'
1183 notice = _(' (inactive)')
1183 notice = _(' (inactive)')
1184 current = (tag == repo.dirstate.branch())
1184 current = (tag == repo.dirstate.branch())
1185 if current:
1185 if current:
1186 label = 'branches.current'
1186 label = 'branches.current'
1187
1187
1188 fm.startitem()
1188 fm.startitem()
1189 fm.write('branch', '%s', tag, label=label)
1189 fm.write('branch', '%s', tag, label=label)
1190 rev = ctx.rev()
1190 rev = ctx.rev()
1191 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1191 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1192 fmt = ' ' * padsize + ' %d:%s'
1192 fmt = ' ' * padsize + ' %d:%s'
1193 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1193 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1194 label='log.changeset changeset.%s' % ctx.phasestr())
1194 label='log.changeset changeset.%s' % ctx.phasestr())
1195 fm.data(active=isactive, closed=not isopen, current=current)
1195 fm.data(active=isactive, closed=not isopen, current=current)
1196 if not ui.quiet:
1196 if not ui.quiet:
1197 fm.plain(notice)
1197 fm.plain(notice)
1198 fm.plain('\n')
1198 fm.plain('\n')
1199 fm.end()
1199 fm.end()
1200
1200
1201 @command('bundle',
1201 @command('bundle',
1202 [('f', 'force', None, _('run even when the destination is unrelated')),
1202 [('f', 'force', None, _('run even when the destination is unrelated')),
1203 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1203 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1204 _('REV')),
1204 _('REV')),
1205 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1205 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1206 _('BRANCH')),
1206 _('BRANCH')),
1207 ('', 'base', [],
1207 ('', 'base', [],
1208 _('a base changeset assumed to be available at the destination'),
1208 _('a base changeset assumed to be available at the destination'),
1209 _('REV')),
1209 _('REV')),
1210 ('a', 'all', None, _('bundle all changesets in the repository')),
1210 ('a', 'all', None, _('bundle all changesets in the repository')),
1211 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1211 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1212 ] + remoteopts,
1212 ] + remoteopts,
1213 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1213 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1214 def bundle(ui, repo, fname, dest=None, **opts):
1214 def bundle(ui, repo, fname, dest=None, **opts):
1215 """create a changegroup file
1215 """create a changegroup file
1216
1216
1217 Generate a compressed changegroup file collecting changesets not
1217 Generate a compressed changegroup file collecting changesets not
1218 known to be in another repository.
1218 known to be in another repository.
1219
1219
1220 If you omit the destination repository, then hg assumes the
1220 If you omit the destination repository, then hg assumes the
1221 destination will have all the nodes you specify with --base
1221 destination will have all the nodes you specify with --base
1222 parameters. To create a bundle containing all changesets, use
1222 parameters. To create a bundle containing all changesets, use
1223 -a/--all (or --base null).
1223 -a/--all (or --base null).
1224
1224
1225 You can change bundle format with the -t/--type option. You can
1225 You can change bundle format with the -t/--type option. You can
1226 specify a compression, a bundle version or both using a dash
1226 specify a compression, a bundle version or both using a dash
1227 (comp-version). The available compression methods are: none, bzip2,
1227 (comp-version). The available compression methods are: none, bzip2,
1228 and gzip (by default, bundles are compressed using bzip2). The
1228 and gzip (by default, bundles are compressed using bzip2). The
1229 available format are: v1, v2 (default to most suitable).
1229 available format are: v1, v2 (default to most suitable).
1230
1230
1231 The bundle file can then be transferred using conventional means
1231 The bundle file can then be transferred using conventional means
1232 and applied to another repository with the unbundle or pull
1232 and applied to another repository with the unbundle or pull
1233 command. This is useful when direct push and pull are not
1233 command. This is useful when direct push and pull are not
1234 available or when exporting an entire repository is undesirable.
1234 available or when exporting an entire repository is undesirable.
1235
1235
1236 Applying bundles preserves all changeset contents including
1236 Applying bundles preserves all changeset contents including
1237 permissions, copy/rename information, and revision history.
1237 permissions, copy/rename information, and revision history.
1238
1238
1239 Returns 0 on success, 1 if no changes found.
1239 Returns 0 on success, 1 if no changes found.
1240 """
1240 """
1241 revs = None
1241 revs = None
1242 if 'rev' in opts:
1242 if 'rev' in opts:
1243 revs = scmutil.revrange(repo, opts['rev'])
1243 revs = scmutil.revrange(repo, opts['rev'])
1244
1244
1245 bundletype = opts.get('type', 'bzip2').lower()
1245 bundletype = opts.get('type', 'bzip2').lower()
1246 try:
1246 try:
1247 bcompression, cgversion, params = exchange.parsebundlespec(
1247 bcompression, cgversion, params = exchange.parsebundlespec(
1248 repo, bundletype, strict=False)
1248 repo, bundletype, strict=False)
1249 except error.UnsupportedBundleSpecification as e:
1249 except error.UnsupportedBundleSpecification as e:
1250 raise error.Abort(str(e),
1250 raise error.Abort(str(e),
1251 hint=_('see "hg help bundle" for supported '
1251 hint=_('see "hg help bundle" for supported '
1252 'values for --type'))
1252 'values for --type'))
1253
1253
1254 # Packed bundles are a pseudo bundle format for now.
1254 # Packed bundles are a pseudo bundle format for now.
1255 if cgversion == 's1':
1255 if cgversion == 's1':
1256 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1256 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1257 hint=_('use "hg debugcreatestreamclonebundle"'))
1257 hint=_('use "hg debugcreatestreamclonebundle"'))
1258
1258
1259 if opts.get('all'):
1259 if opts.get('all'):
1260 base = ['null']
1260 base = ['null']
1261 else:
1261 else:
1262 base = scmutil.revrange(repo, opts.get('base'))
1262 base = scmutil.revrange(repo, opts.get('base'))
1263 # TODO: get desired bundlecaps from command line.
1263 # TODO: get desired bundlecaps from command line.
1264 bundlecaps = None
1264 bundlecaps = None
1265 if base:
1265 if base:
1266 if dest:
1266 if dest:
1267 raise error.Abort(_("--base is incompatible with specifying "
1267 raise error.Abort(_("--base is incompatible with specifying "
1268 "a destination"))
1268 "a destination"))
1269 common = [repo.lookup(rev) for rev in base]
1269 common = [repo.lookup(rev) for rev in base]
1270 heads = revs and map(repo.lookup, revs) or revs
1270 heads = revs and map(repo.lookup, revs) or revs
1271 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1271 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1272 common=common, bundlecaps=bundlecaps,
1272 common=common, bundlecaps=bundlecaps,
1273 version=cgversion)
1273 version=cgversion)
1274 outgoing = None
1274 outgoing = None
1275 else:
1275 else:
1276 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1276 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1277 dest, branches = hg.parseurl(dest, opts.get('branch'))
1277 dest, branches = hg.parseurl(dest, opts.get('branch'))
1278 other = hg.peer(repo, opts, dest)
1278 other = hg.peer(repo, opts, dest)
1279 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1279 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1280 heads = revs and map(repo.lookup, revs) or revs
1280 heads = revs and map(repo.lookup, revs) or revs
1281 outgoing = discovery.findcommonoutgoing(repo, other,
1281 outgoing = discovery.findcommonoutgoing(repo, other,
1282 onlyheads=heads,
1282 onlyheads=heads,
1283 force=opts.get('force'),
1283 force=opts.get('force'),
1284 portable=True)
1284 portable=True)
1285 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1285 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1286 bundlecaps, version=cgversion)
1286 bundlecaps, version=cgversion)
1287 if not cg:
1287 if not cg:
1288 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1288 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1289 return 1
1289 return 1
1290
1290
1291 if cgversion == '01': #bundle1
1291 if cgversion == '01': #bundle1
1292 if bcompression is None:
1292 if bcompression is None:
1293 bcompression = 'UN'
1293 bcompression = 'UN'
1294 bversion = 'HG10' + bcompression
1294 bversion = 'HG10' + bcompression
1295 bcompression = None
1295 bcompression = None
1296 else:
1296 else:
1297 assert cgversion == '02'
1297 assert cgversion == '02'
1298 bversion = 'HG20'
1298 bversion = 'HG20'
1299
1299
1300
1300
1301 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1301 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1302
1302
1303 @command('cat',
1303 @command('cat',
1304 [('o', 'output', '',
1304 [('o', 'output', '',
1305 _('print output to file with formatted name'), _('FORMAT')),
1305 _('print output to file with formatted name'), _('FORMAT')),
1306 ('r', 'rev', '', _('print the given revision'), _('REV')),
1306 ('r', 'rev', '', _('print the given revision'), _('REV')),
1307 ('', 'decode', None, _('apply any matching decode filter')),
1307 ('', 'decode', None, _('apply any matching decode filter')),
1308 ] + walkopts,
1308 ] + walkopts,
1309 _('[OPTION]... FILE...'),
1309 _('[OPTION]... FILE...'),
1310 inferrepo=True)
1310 inferrepo=True)
1311 def cat(ui, repo, file1, *pats, **opts):
1311 def cat(ui, repo, file1, *pats, **opts):
1312 """output the current or given revision of files
1312 """output the current or given revision of files
1313
1313
1314 Print the specified files as they were at the given revision. If
1314 Print the specified files as they were at the given revision. If
1315 no revision is given, the parent of the working directory is used.
1315 no revision is given, the parent of the working directory is used.
1316
1316
1317 Output may be to a file, in which case the name of the file is
1317 Output may be to a file, in which case the name of the file is
1318 given using a format string. The formatting rules as follows:
1318 given using a format string. The formatting rules as follows:
1319
1319
1320 :``%%``: literal "%" character
1320 :``%%``: literal "%" character
1321 :``%s``: basename of file being printed
1321 :``%s``: basename of file being printed
1322 :``%d``: dirname of file being printed, or '.' if in repository root
1322 :``%d``: dirname of file being printed, or '.' if in repository root
1323 :``%p``: root-relative path name of file being printed
1323 :``%p``: root-relative path name of file being printed
1324 :``%H``: changeset hash (40 hexadecimal digits)
1324 :``%H``: changeset hash (40 hexadecimal digits)
1325 :``%R``: changeset revision number
1325 :``%R``: changeset revision number
1326 :``%h``: short-form changeset hash (12 hexadecimal digits)
1326 :``%h``: short-form changeset hash (12 hexadecimal digits)
1327 :``%r``: zero-padded changeset revision number
1327 :``%r``: zero-padded changeset revision number
1328 :``%b``: basename of the exporting repository
1328 :``%b``: basename of the exporting repository
1329
1329
1330 Returns 0 on success.
1330 Returns 0 on success.
1331 """
1331 """
1332 ctx = scmutil.revsingle(repo, opts.get('rev'))
1332 ctx = scmutil.revsingle(repo, opts.get('rev'))
1333 m = scmutil.match(ctx, (file1,) + pats, opts)
1333 m = scmutil.match(ctx, (file1,) + pats, opts)
1334
1334
1335 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1335 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1336
1336
1337 @command('^clone',
1337 @command('^clone',
1338 [('U', 'noupdate', None, _('the clone will include an empty working '
1338 [('U', 'noupdate', None, _('the clone will include an empty working '
1339 'directory (only a repository)')),
1339 'directory (only a repository)')),
1340 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1340 ('u', 'updaterev', '', _('revision, tag or branch to check out'), _('REV')),
1341 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1341 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1342 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1342 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1343 ('', 'pull', None, _('use pull protocol to copy metadata')),
1343 ('', 'pull', None, _('use pull protocol to copy metadata')),
1344 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1344 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1345 ] + remoteopts,
1345 ] + remoteopts,
1346 _('[OPTION]... SOURCE [DEST]'),
1346 _('[OPTION]... SOURCE [DEST]'),
1347 norepo=True)
1347 norepo=True)
1348 def clone(ui, source, dest=None, **opts):
1348 def clone(ui, source, dest=None, **opts):
1349 """make a copy of an existing repository
1349 """make a copy of an existing repository
1350
1350
1351 Create a copy of an existing repository in a new directory.
1351 Create a copy of an existing repository in a new directory.
1352
1352
1353 If no destination directory name is specified, it defaults to the
1353 If no destination directory name is specified, it defaults to the
1354 basename of the source.
1354 basename of the source.
1355
1355
1356 The location of the source is added to the new repository's
1356 The location of the source is added to the new repository's
1357 ``.hg/hgrc`` file, as the default to be used for future pulls.
1357 ``.hg/hgrc`` file, as the default to be used for future pulls.
1358
1358
1359 Only local paths and ``ssh://`` URLs are supported as
1359 Only local paths and ``ssh://`` URLs are supported as
1360 destinations. For ``ssh://`` destinations, no working directory or
1360 destinations. For ``ssh://`` destinations, no working directory or
1361 ``.hg/hgrc`` will be created on the remote side.
1361 ``.hg/hgrc`` will be created on the remote side.
1362
1362
1363 To pull only a subset of changesets, specify one or more revisions
1363 To pull only a subset of changesets, specify one or more revisions
1364 identifiers with -r/--rev or branches with -b/--branch. The
1364 identifiers with -r/--rev or branches with -b/--branch. The
1365 resulting clone will contain only the specified changesets and
1365 resulting clone will contain only the specified changesets and
1366 their ancestors. These options (or 'clone src#rev dest') imply
1366 their ancestors. These options (or 'clone src#rev dest') imply
1367 --pull, even for local source repositories. Note that specifying a
1367 --pull, even for local source repositories. Note that specifying a
1368 tag will include the tagged changeset but not the changeset
1368 tag will include the tagged changeset but not the changeset
1369 containing the tag.
1369 containing the tag.
1370
1370
1371 If the source repository has a bookmark called '@' set, that
1371 If the source repository has a bookmark called '@' set, that
1372 revision will be checked out in the new repository by default.
1372 revision will be checked out in the new repository by default.
1373
1373
1374 To check out a particular version, use -u/--update, or
1374 To check out a particular version, use -u/--update, or
1375 -U/--noupdate to create a clone with no working directory.
1375 -U/--noupdate to create a clone with no working directory.
1376
1376
1377 .. container:: verbose
1377 .. container:: verbose
1378
1378
1379 For efficiency, hardlinks are used for cloning whenever the
1379 For efficiency, hardlinks are used for cloning whenever the
1380 source and destination are on the same filesystem (note this
1380 source and destination are on the same filesystem (note this
1381 applies only to the repository data, not to the working
1381 applies only to the repository data, not to the working
1382 directory). Some filesystems, such as AFS, implement hardlinking
1382 directory). Some filesystems, such as AFS, implement hardlinking
1383 incorrectly, but do not report errors. In these cases, use the
1383 incorrectly, but do not report errors. In these cases, use the
1384 --pull option to avoid hardlinking.
1384 --pull option to avoid hardlinking.
1385
1385
1386 In some cases, you can clone repositories and the working
1386 In some cases, you can clone repositories and the working
1387 directory using full hardlinks with ::
1387 directory using full hardlinks with ::
1388
1388
1389 $ cp -al REPO REPOCLONE
1389 $ cp -al REPO REPOCLONE
1390
1390
1391 This is the fastest way to clone, but it is not always safe. The
1391 This is the fastest way to clone, but it is not always safe. The
1392 operation is not atomic (making sure REPO is not modified during
1392 operation is not atomic (making sure REPO is not modified during
1393 the operation is up to you) and you have to make sure your
1393 the operation is up to you) and you have to make sure your
1394 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1394 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1395 so). Also, this is not compatible with certain extensions that
1395 so). Also, this is not compatible with certain extensions that
1396 place their metadata under the .hg directory, such as mq.
1396 place their metadata under the .hg directory, such as mq.
1397
1397
1398 Mercurial will update the working directory to the first applicable
1398 Mercurial will update the working directory to the first applicable
1399 revision from this list:
1399 revision from this list:
1400
1400
1401 a) null if -U or the source repository has no changesets
1401 a) null if -U or the source repository has no changesets
1402 b) if -u . and the source repository is local, the first parent of
1402 b) if -u . and the source repository is local, the first parent of
1403 the source repository's working directory
1403 the source repository's working directory
1404 c) the changeset specified with -u (if a branch name, this means the
1404 c) the changeset specified with -u (if a branch name, this means the
1405 latest head of that branch)
1405 latest head of that branch)
1406 d) the changeset specified with -r
1406 d) the changeset specified with -r
1407 e) the tipmost head specified with -b
1407 e) the tipmost head specified with -b
1408 f) the tipmost head specified with the url#branch source syntax
1408 f) the tipmost head specified with the url#branch source syntax
1409 g) the revision marked with the '@' bookmark, if present
1409 g) the revision marked with the '@' bookmark, if present
1410 h) the tipmost head of the default branch
1410 h) the tipmost head of the default branch
1411 i) tip
1411 i) tip
1412
1412
1413 Examples:
1413 Examples:
1414
1414
1415 - clone a remote repository to a new directory named hg/::
1415 - clone a remote repository to a new directory named hg/::
1416
1416
1417 hg clone http://selenic.com/hg
1417 hg clone http://selenic.com/hg
1418
1418
1419 - create a lightweight local clone::
1419 - create a lightweight local clone::
1420
1420
1421 hg clone project/ project-feature/
1421 hg clone project/ project-feature/
1422
1422
1423 - clone from an absolute path on an ssh server (note double-slash)::
1423 - clone from an absolute path on an ssh server (note double-slash)::
1424
1424
1425 hg clone ssh://user@server//home/projects/alpha/
1425 hg clone ssh://user@server//home/projects/alpha/
1426
1426
1427 - do a high-speed clone over a LAN while checking out a
1427 - do a high-speed clone over a LAN while checking out a
1428 specified version::
1428 specified version::
1429
1429
1430 hg clone --uncompressed http://server/repo -u 1.5
1430 hg clone --uncompressed http://server/repo -u 1.5
1431
1431
1432 - create a repository without changesets after a particular revision::
1432 - create a repository without changesets after a particular revision::
1433
1433
1434 hg clone -r 04e544 experimental/ good/
1434 hg clone -r 04e544 experimental/ good/
1435
1435
1436 - clone (and track) a particular named branch::
1436 - clone (and track) a particular named branch::
1437
1437
1438 hg clone http://selenic.com/hg#stable
1438 hg clone http://selenic.com/hg#stable
1439
1439
1440 See :hg:`help urls` for details on specifying URLs.
1440 See :hg:`help urls` for details on specifying URLs.
1441
1441
1442 Returns 0 on success.
1442 Returns 0 on success.
1443 """
1443 """
1444 if opts.get('noupdate') and opts.get('updaterev'):
1444 if opts.get('noupdate') and opts.get('updaterev'):
1445 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1445 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1446
1446
1447 r = hg.clone(ui, opts, source, dest,
1447 r = hg.clone(ui, opts, source, dest,
1448 pull=opts.get('pull'),
1448 pull=opts.get('pull'),
1449 stream=opts.get('uncompressed'),
1449 stream=opts.get('uncompressed'),
1450 rev=opts.get('rev'),
1450 rev=opts.get('rev'),
1451 update=opts.get('updaterev') or not opts.get('noupdate'),
1451 update=opts.get('updaterev') or not opts.get('noupdate'),
1452 branch=opts.get('branch'),
1452 branch=opts.get('branch'),
1453 shareopts=opts.get('shareopts'))
1453 shareopts=opts.get('shareopts'))
1454
1454
1455 return r is None
1455 return r is None
1456
1456
1457 @command('^commit|ci',
1457 @command('^commit|ci',
1458 [('A', 'addremove', None,
1458 [('A', 'addremove', None,
1459 _('mark new/missing files as added/removed before committing')),
1459 _('mark new/missing files as added/removed before committing')),
1460 ('', 'close-branch', None,
1460 ('', 'close-branch', None,
1461 _('mark a branch head as closed')),
1461 _('mark a branch head as closed')),
1462 ('', 'amend', None, _('amend the parent of the working directory')),
1462 ('', 'amend', None, _('amend the parent of the working directory')),
1463 ('s', 'secret', None, _('use the secret phase for committing')),
1463 ('s', 'secret', None, _('use the secret phase for committing')),
1464 ('e', 'edit', None, _('invoke editor on commit messages')),
1464 ('e', 'edit', None, _('invoke editor on commit messages')),
1465 ('i', 'interactive', None, _('use interactive mode')),
1465 ('i', 'interactive', None, _('use interactive mode')),
1466 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1466 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1467 _('[OPTION]... [FILE]...'),
1467 _('[OPTION]... [FILE]...'),
1468 inferrepo=True)
1468 inferrepo=True)
1469 def commit(ui, repo, *pats, **opts):
1469 def commit(ui, repo, *pats, **opts):
1470 """commit the specified files or all outstanding changes
1470 """commit the specified files or all outstanding changes
1471
1471
1472 Commit changes to the given files into the repository. Unlike a
1472 Commit changes to the given files into the repository. Unlike a
1473 centralized SCM, this operation is a local operation. See
1473 centralized SCM, this operation is a local operation. See
1474 :hg:`push` for a way to actively distribute your changes.
1474 :hg:`push` for a way to actively distribute your changes.
1475
1475
1476 If a list of files is omitted, all changes reported by :hg:`status`
1476 If a list of files is omitted, all changes reported by :hg:`status`
1477 will be committed.
1477 will be committed.
1478
1478
1479 If you are committing the result of a merge, do not provide any
1479 If you are committing the result of a merge, do not provide any
1480 filenames or -I/-X filters.
1480 filenames or -I/-X filters.
1481
1481
1482 If no commit message is specified, Mercurial starts your
1482 If no commit message is specified, Mercurial starts your
1483 configured editor where you can enter a message. In case your
1483 configured editor where you can enter a message. In case your
1484 commit fails, you will find a backup of your message in
1484 commit fails, you will find a backup of your message in
1485 ``.hg/last-message.txt``.
1485 ``.hg/last-message.txt``.
1486
1486
1487 The --close-branch flag can be used to mark the current branch
1487 The --close-branch flag can be used to mark the current branch
1488 head closed. When all heads of a branch are closed, the branch
1488 head closed. When all heads of a branch are closed, the branch
1489 will be considered closed and no longer listed.
1489 will be considered closed and no longer listed.
1490
1490
1491 The --amend flag can be used to amend the parent of the
1491 The --amend flag can be used to amend the parent of the
1492 working directory with a new commit that contains the changes
1492 working directory with a new commit that contains the changes
1493 in the parent in addition to those currently reported by :hg:`status`,
1493 in the parent in addition to those currently reported by :hg:`status`,
1494 if there are any. The old commit is stored in a backup bundle in
1494 if there are any. The old commit is stored in a backup bundle in
1495 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1495 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1496 on how to restore it).
1496 on how to restore it).
1497
1497
1498 Message, user and date are taken from the amended commit unless
1498 Message, user and date are taken from the amended commit unless
1499 specified. When a message isn't specified on the command line,
1499 specified. When a message isn't specified on the command line,
1500 the editor will open with the message of the amended commit.
1500 the editor will open with the message of the amended commit.
1501
1501
1502 It is not possible to amend public changesets (see :hg:`help phases`)
1502 It is not possible to amend public changesets (see :hg:`help phases`)
1503 or changesets that have children.
1503 or changesets that have children.
1504
1504
1505 See :hg:`help dates` for a list of formats valid for -d/--date.
1505 See :hg:`help dates` for a list of formats valid for -d/--date.
1506
1506
1507 Returns 0 on success, 1 if nothing changed.
1507 Returns 0 on success, 1 if nothing changed.
1508 """
1508 """
1509 if opts.get('interactive'):
1509 if opts.get('interactive'):
1510 opts.pop('interactive')
1510 opts.pop('interactive')
1511 cmdutil.dorecord(ui, repo, commit, None, False,
1511 cmdutil.dorecord(ui, repo, commit, None, False,
1512 cmdutil.recordfilter, *pats, **opts)
1512 cmdutil.recordfilter, *pats, **opts)
1513 return
1513 return
1514
1514
1515 if opts.get('subrepos'):
1515 if opts.get('subrepos'):
1516 if opts.get('amend'):
1516 if opts.get('amend'):
1517 raise error.Abort(_('cannot amend with --subrepos'))
1517 raise error.Abort(_('cannot amend with --subrepos'))
1518 # Let --subrepos on the command line override config setting.
1518 # Let --subrepos on the command line override config setting.
1519 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1519 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1520
1520
1521 cmdutil.checkunfinished(repo, commit=True)
1521 cmdutil.checkunfinished(repo, commit=True)
1522
1522
1523 branch = repo[None].branch()
1523 branch = repo[None].branch()
1524 bheads = repo.branchheads(branch)
1524 bheads = repo.branchheads(branch)
1525
1525
1526 extra = {}
1526 extra = {}
1527 if opts.get('close_branch'):
1527 if opts.get('close_branch'):
1528 extra['close'] = 1
1528 extra['close'] = 1
1529
1529
1530 if not bheads:
1530 if not bheads:
1531 raise error.Abort(_('can only close branch heads'))
1531 raise error.Abort(_('can only close branch heads'))
1532 elif opts.get('amend'):
1532 elif opts.get('amend'):
1533 if repo.parents()[0].p1().branch() != branch and \
1533 if repo.parents()[0].p1().branch() != branch and \
1534 repo.parents()[0].p2().branch() != branch:
1534 repo.parents()[0].p2().branch() != branch:
1535 raise error.Abort(_('can only close branch heads'))
1535 raise error.Abort(_('can only close branch heads'))
1536
1536
1537 if opts.get('amend'):
1537 if opts.get('amend'):
1538 if ui.configbool('ui', 'commitsubrepos'):
1538 if ui.configbool('ui', 'commitsubrepos'):
1539 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1539 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1540
1540
1541 old = repo['.']
1541 old = repo['.']
1542 if not old.mutable():
1542 if not old.mutable():
1543 raise error.Abort(_('cannot amend public changesets'))
1543 raise error.Abort(_('cannot amend public changesets'))
1544 if len(repo[None].parents()) > 1:
1544 if len(repo[None].parents()) > 1:
1545 raise error.Abort(_('cannot amend while merging'))
1545 raise error.Abort(_('cannot amend while merging'))
1546 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1546 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1547 if not allowunstable and old.children():
1547 if not allowunstable and old.children():
1548 raise error.Abort(_('cannot amend changeset with children'))
1548 raise error.Abort(_('cannot amend changeset with children'))
1549
1549
1550 # commitfunc is used only for temporary amend commit by cmdutil.amend
1550 # commitfunc is used only for temporary amend commit by cmdutil.amend
1551 def commitfunc(ui, repo, message, match, opts):
1551 def commitfunc(ui, repo, message, match, opts):
1552 return repo.commit(message,
1552 return repo.commit(message,
1553 opts.get('user') or old.user(),
1553 opts.get('user') or old.user(),
1554 opts.get('date') or old.date(),
1554 opts.get('date') or old.date(),
1555 match,
1555 match,
1556 extra=extra)
1556 extra=extra)
1557
1557
1558 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1558 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1559 if node == old.node():
1559 if node == old.node():
1560 ui.status(_("nothing changed\n"))
1560 ui.status(_("nothing changed\n"))
1561 return 1
1561 return 1
1562 else:
1562 else:
1563 def commitfunc(ui, repo, message, match, opts):
1563 def commitfunc(ui, repo, message, match, opts):
1564 backup = ui.backupconfig('phases', 'new-commit')
1564 backup = ui.backupconfig('phases', 'new-commit')
1565 baseui = repo.baseui
1565 baseui = repo.baseui
1566 basebackup = baseui.backupconfig('phases', 'new-commit')
1566 basebackup = baseui.backupconfig('phases', 'new-commit')
1567 try:
1567 try:
1568 if opts.get('secret'):
1568 if opts.get('secret'):
1569 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1569 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1570 # Propagate to subrepos
1570 # Propagate to subrepos
1571 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1571 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1572
1572
1573 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1573 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1574 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1574 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1575 return repo.commit(message, opts.get('user'), opts.get('date'),
1575 return repo.commit(message, opts.get('user'), opts.get('date'),
1576 match,
1576 match,
1577 editor=editor,
1577 editor=editor,
1578 extra=extra)
1578 extra=extra)
1579 finally:
1579 finally:
1580 ui.restoreconfig(backup)
1580 ui.restoreconfig(backup)
1581 repo.baseui.restoreconfig(basebackup)
1581 repo.baseui.restoreconfig(basebackup)
1582
1582
1583
1583
1584 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1584 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1585
1585
1586 if not node:
1586 if not node:
1587 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1587 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1588 if stat[3]:
1588 if stat[3]:
1589 ui.status(_("nothing changed (%d missing files, see "
1589 ui.status(_("nothing changed (%d missing files, see "
1590 "'hg status')\n") % len(stat[3]))
1590 "'hg status')\n") % len(stat[3]))
1591 else:
1591 else:
1592 ui.status(_("nothing changed\n"))
1592 ui.status(_("nothing changed\n"))
1593 return 1
1593 return 1
1594
1594
1595 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1595 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1596
1596
1597 @command('config|showconfig|debugconfig',
1597 @command('config|showconfig|debugconfig',
1598 [('u', 'untrusted', None, _('show untrusted configuration options')),
1598 [('u', 'untrusted', None, _('show untrusted configuration options')),
1599 ('e', 'edit', None, _('edit user config')),
1599 ('e', 'edit', None, _('edit user config')),
1600 ('l', 'local', None, _('edit repository config')),
1600 ('l', 'local', None, _('edit repository config')),
1601 ('g', 'global', None, _('edit global config'))],
1601 ('g', 'global', None, _('edit global config'))],
1602 _('[-u] [NAME]...'),
1602 _('[-u] [NAME]...'),
1603 optionalrepo=True)
1603 optionalrepo=True)
1604 def config(ui, repo, *values, **opts):
1604 def config(ui, repo, *values, **opts):
1605 """show combined config settings from all hgrc files
1605 """show combined config settings from all hgrc files
1606
1606
1607 With no arguments, print names and values of all config items.
1607 With no arguments, print names and values of all config items.
1608
1608
1609 With one argument of the form section.name, print just the value
1609 With one argument of the form section.name, print just the value
1610 of that config item.
1610 of that config item.
1611
1611
1612 With multiple arguments, print names and values of all config
1612 With multiple arguments, print names and values of all config
1613 items with matching section names.
1613 items with matching section names.
1614
1614
1615 With --edit, start an editor on the user-level config file. With
1615 With --edit, start an editor on the user-level config file. With
1616 --global, edit the system-wide config file. With --local, edit the
1616 --global, edit the system-wide config file. With --local, edit the
1617 repository-level config file.
1617 repository-level config file.
1618
1618
1619 With --debug, the source (filename and line number) is printed
1619 With --debug, the source (filename and line number) is printed
1620 for each config item.
1620 for each config item.
1621
1621
1622 See :hg:`help config` for more information about config files.
1622 See :hg:`help config` for more information about config files.
1623
1623
1624 Returns 0 on success, 1 if NAME does not exist.
1624 Returns 0 on success, 1 if NAME does not exist.
1625
1625
1626 """
1626 """
1627
1627
1628 if opts.get('edit') or opts.get('local') or opts.get('global'):
1628 if opts.get('edit') or opts.get('local') or opts.get('global'):
1629 if opts.get('local') and opts.get('global'):
1629 if opts.get('local') and opts.get('global'):
1630 raise error.Abort(_("can't use --local and --global together"))
1630 raise error.Abort(_("can't use --local and --global together"))
1631
1631
1632 if opts.get('local'):
1632 if opts.get('local'):
1633 if not repo:
1633 if not repo:
1634 raise error.Abort(_("can't use --local outside a repository"))
1634 raise error.Abort(_("can't use --local outside a repository"))
1635 paths = [repo.join('hgrc')]
1635 paths = [repo.join('hgrc')]
1636 elif opts.get('global'):
1636 elif opts.get('global'):
1637 paths = scmutil.systemrcpath()
1637 paths = scmutil.systemrcpath()
1638 else:
1638 else:
1639 paths = scmutil.userrcpath()
1639 paths = scmutil.userrcpath()
1640
1640
1641 for f in paths:
1641 for f in paths:
1642 if os.path.exists(f):
1642 if os.path.exists(f):
1643 break
1643 break
1644 else:
1644 else:
1645 if opts.get('global'):
1645 if opts.get('global'):
1646 samplehgrc = uimod.samplehgrcs['global']
1646 samplehgrc = uimod.samplehgrcs['global']
1647 elif opts.get('local'):
1647 elif opts.get('local'):
1648 samplehgrc = uimod.samplehgrcs['local']
1648 samplehgrc = uimod.samplehgrcs['local']
1649 else:
1649 else:
1650 samplehgrc = uimod.samplehgrcs['user']
1650 samplehgrc = uimod.samplehgrcs['user']
1651
1651
1652 f = paths[0]
1652 f = paths[0]
1653 fp = open(f, "w")
1653 fp = open(f, "w")
1654 fp.write(samplehgrc)
1654 fp.write(samplehgrc)
1655 fp.close()
1655 fp.close()
1656
1656
1657 editor = ui.geteditor()
1657 editor = ui.geteditor()
1658 ui.system("%s \"%s\"" % (editor, f),
1658 ui.system("%s \"%s\"" % (editor, f),
1659 onerr=error.Abort, errprefix=_("edit failed"))
1659 onerr=error.Abort, errprefix=_("edit failed"))
1660 return
1660 return
1661
1661
1662 for f in scmutil.rcpath():
1662 for f in scmutil.rcpath():
1663 ui.debug('read config from: %s\n' % f)
1663 ui.debug('read config from: %s\n' % f)
1664 untrusted = bool(opts.get('untrusted'))
1664 untrusted = bool(opts.get('untrusted'))
1665 if values:
1665 if values:
1666 sections = [v for v in values if '.' not in v]
1666 sections = [v for v in values if '.' not in v]
1667 items = [v for v in values if '.' in v]
1667 items = [v for v in values if '.' in v]
1668 if len(items) > 1 or items and sections:
1668 if len(items) > 1 or items and sections:
1669 raise error.Abort(_('only one config item permitted'))
1669 raise error.Abort(_('only one config item permitted'))
1670 matched = False
1670 matched = False
1671 for section, name, value in ui.walkconfig(untrusted=untrusted):
1671 for section, name, value in ui.walkconfig(untrusted=untrusted):
1672 value = str(value).replace('\n', '\\n')
1672 value = str(value).replace('\n', '\\n')
1673 sectname = section + '.' + name
1673 sectname = section + '.' + name
1674 if values:
1674 if values:
1675 for v in values:
1675 for v in values:
1676 if v == section:
1676 if v == section:
1677 ui.debug('%s: ' %
1677 ui.debug('%s: ' %
1678 ui.configsource(section, name, untrusted))
1678 ui.configsource(section, name, untrusted))
1679 ui.write('%s=%s\n' % (sectname, value))
1679 ui.write('%s=%s\n' % (sectname, value))
1680 matched = True
1680 matched = True
1681 elif v == sectname:
1681 elif v == sectname:
1682 ui.debug('%s: ' %
1682 ui.debug('%s: ' %
1683 ui.configsource(section, name, untrusted))
1683 ui.configsource(section, name, untrusted))
1684 ui.write(value, '\n')
1684 ui.write(value, '\n')
1685 matched = True
1685 matched = True
1686 else:
1686 else:
1687 ui.debug('%s: ' %
1687 ui.debug('%s: ' %
1688 ui.configsource(section, name, untrusted))
1688 ui.configsource(section, name, untrusted))
1689 ui.write('%s=%s\n' % (sectname, value))
1689 ui.write('%s=%s\n' % (sectname, value))
1690 matched = True
1690 matched = True
1691 if matched:
1691 if matched:
1692 return 0
1692 return 0
1693 return 1
1693 return 1
1694
1694
1695 @command('copy|cp',
1695 @command('copy|cp',
1696 [('A', 'after', None, _('record a copy that has already occurred')),
1696 [('A', 'after', None, _('record a copy that has already occurred')),
1697 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1697 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1698 ] + walkopts + dryrunopts,
1698 ] + walkopts + dryrunopts,
1699 _('[OPTION]... [SOURCE]... DEST'))
1699 _('[OPTION]... [SOURCE]... DEST'))
1700 def copy(ui, repo, *pats, **opts):
1700 def copy(ui, repo, *pats, **opts):
1701 """mark files as copied for the next commit
1701 """mark files as copied for the next commit
1702
1702
1703 Mark dest as having copies of source files. If dest is a
1703 Mark dest as having copies of source files. If dest is a
1704 directory, copies are put in that directory. If dest is a file,
1704 directory, copies are put in that directory. If dest is a file,
1705 the source must be a single file.
1705 the source must be a single file.
1706
1706
1707 By default, this command copies the contents of files as they
1707 By default, this command copies the contents of files as they
1708 exist in the working directory. If invoked with -A/--after, the
1708 exist in the working directory. If invoked with -A/--after, the
1709 operation is recorded, but no copying is performed.
1709 operation is recorded, but no copying is performed.
1710
1710
1711 This command takes effect with the next commit. To undo a copy
1711 This command takes effect with the next commit. To undo a copy
1712 before that, see :hg:`revert`.
1712 before that, see :hg:`revert`.
1713
1713
1714 Returns 0 on success, 1 if errors are encountered.
1714 Returns 0 on success, 1 if errors are encountered.
1715 """
1715 """
1716 wlock = repo.wlock(False)
1716 wlock = repo.wlock(False)
1717 try:
1717 try:
1718 return cmdutil.copy(ui, repo, pats, opts)
1718 return cmdutil.copy(ui, repo, pats, opts)
1719 finally:
1719 finally:
1720 wlock.release()
1720 wlock.release()
1721
1721
1722 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1722 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1723 def debugancestor(ui, repo, *args):
1723 def debugancestor(ui, repo, *args):
1724 """find the ancestor revision of two revisions in a given index"""
1724 """find the ancestor revision of two revisions in a given index"""
1725 if len(args) == 3:
1725 if len(args) == 3:
1726 index, rev1, rev2 = args
1726 index, rev1, rev2 = args
1727 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1727 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1728 lookup = r.lookup
1728 lookup = r.lookup
1729 elif len(args) == 2:
1729 elif len(args) == 2:
1730 if not repo:
1730 if not repo:
1731 raise error.Abort(_("there is no Mercurial repository here "
1731 raise error.Abort(_("there is no Mercurial repository here "
1732 "(.hg not found)"))
1732 "(.hg not found)"))
1733 rev1, rev2 = args
1733 rev1, rev2 = args
1734 r = repo.changelog
1734 r = repo.changelog
1735 lookup = repo.lookup
1735 lookup = repo.lookup
1736 else:
1736 else:
1737 raise error.Abort(_('either two or three arguments required'))
1737 raise error.Abort(_('either two or three arguments required'))
1738 a = r.ancestor(lookup(rev1), lookup(rev2))
1738 a = r.ancestor(lookup(rev1), lookup(rev2))
1739 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1739 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1740
1740
1741 @command('debugbuilddag',
1741 @command('debugbuilddag',
1742 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1742 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1743 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1743 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1744 ('n', 'new-file', None, _('add new file at each rev'))],
1744 ('n', 'new-file', None, _('add new file at each rev'))],
1745 _('[OPTION]... [TEXT]'))
1745 _('[OPTION]... [TEXT]'))
1746 def debugbuilddag(ui, repo, text=None,
1746 def debugbuilddag(ui, repo, text=None,
1747 mergeable_file=False,
1747 mergeable_file=False,
1748 overwritten_file=False,
1748 overwritten_file=False,
1749 new_file=False):
1749 new_file=False):
1750 """builds a repo with a given DAG from scratch in the current empty repo
1750 """builds a repo with a given DAG from scratch in the current empty repo
1751
1751
1752 The description of the DAG is read from stdin if not given on the
1752 The description of the DAG is read from stdin if not given on the
1753 command line.
1753 command line.
1754
1754
1755 Elements:
1755 Elements:
1756
1756
1757 - "+n" is a linear run of n nodes based on the current default parent
1757 - "+n" is a linear run of n nodes based on the current default parent
1758 - "." is a single node based on the current default parent
1758 - "." is a single node based on the current default parent
1759 - "$" resets the default parent to null (implied at the start);
1759 - "$" resets the default parent to null (implied at the start);
1760 otherwise the default parent is always the last node created
1760 otherwise the default parent is always the last node created
1761 - "<p" sets the default parent to the backref p
1761 - "<p" sets the default parent to the backref p
1762 - "*p" is a fork at parent p, which is a backref
1762 - "*p" is a fork at parent p, which is a backref
1763 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1763 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1764 - "/p2" is a merge of the preceding node and p2
1764 - "/p2" is a merge of the preceding node and p2
1765 - ":tag" defines a local tag for the preceding node
1765 - ":tag" defines a local tag for the preceding node
1766 - "@branch" sets the named branch for subsequent nodes
1766 - "@branch" sets the named branch for subsequent nodes
1767 - "#...\\n" is a comment up to the end of the line
1767 - "#...\\n" is a comment up to the end of the line
1768
1768
1769 Whitespace between the above elements is ignored.
1769 Whitespace between the above elements is ignored.
1770
1770
1771 A backref is either
1771 A backref is either
1772
1772
1773 - a number n, which references the node curr-n, where curr is the current
1773 - a number n, which references the node curr-n, where curr is the current
1774 node, or
1774 node, or
1775 - the name of a local tag you placed earlier using ":tag", or
1775 - the name of a local tag you placed earlier using ":tag", or
1776 - empty to denote the default parent.
1776 - empty to denote the default parent.
1777
1777
1778 All string valued-elements are either strictly alphanumeric, or must
1778 All string valued-elements are either strictly alphanumeric, or must
1779 be enclosed in double quotes ("..."), with "\\" as escape character.
1779 be enclosed in double quotes ("..."), with "\\" as escape character.
1780 """
1780 """
1781
1781
1782 if text is None:
1782 if text is None:
1783 ui.status(_("reading DAG from stdin\n"))
1783 ui.status(_("reading DAG from stdin\n"))
1784 text = ui.fin.read()
1784 text = ui.fin.read()
1785
1785
1786 cl = repo.changelog
1786 cl = repo.changelog
1787 if len(cl) > 0:
1787 if len(cl) > 0:
1788 raise error.Abort(_('repository is not empty'))
1788 raise error.Abort(_('repository is not empty'))
1789
1789
1790 # determine number of revs in DAG
1790 # determine number of revs in DAG
1791 total = 0
1791 total = 0
1792 for type, data in dagparser.parsedag(text):
1792 for type, data in dagparser.parsedag(text):
1793 if type == 'n':
1793 if type == 'n':
1794 total += 1
1794 total += 1
1795
1795
1796 if mergeable_file:
1796 if mergeable_file:
1797 linesperrev = 2
1797 linesperrev = 2
1798 # make a file with k lines per rev
1798 # make a file with k lines per rev
1799 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1799 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1800 initialmergedlines.append("")
1800 initialmergedlines.append("")
1801
1801
1802 tags = []
1802 tags = []
1803
1803
1804 lock = tr = None
1804 lock = tr = None
1805 try:
1805 try:
1806 lock = repo.lock()
1806 lock = repo.lock()
1807 tr = repo.transaction("builddag")
1807 tr = repo.transaction("builddag")
1808
1808
1809 at = -1
1809 at = -1
1810 atbranch = 'default'
1810 atbranch = 'default'
1811 nodeids = []
1811 nodeids = []
1812 id = 0
1812 id = 0
1813 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1813 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1814 for type, data in dagparser.parsedag(text):
1814 for type, data in dagparser.parsedag(text):
1815 if type == 'n':
1815 if type == 'n':
1816 ui.note(('node %s\n' % str(data)))
1816 ui.note(('node %s\n' % str(data)))
1817 id, ps = data
1817 id, ps = data
1818
1818
1819 files = []
1819 files = []
1820 fctxs = {}
1820 fctxs = {}
1821
1821
1822 p2 = None
1822 p2 = None
1823 if mergeable_file:
1823 if mergeable_file:
1824 fn = "mf"
1824 fn = "mf"
1825 p1 = repo[ps[0]]
1825 p1 = repo[ps[0]]
1826 if len(ps) > 1:
1826 if len(ps) > 1:
1827 p2 = repo[ps[1]]
1827 p2 = repo[ps[1]]
1828 pa = p1.ancestor(p2)
1828 pa = p1.ancestor(p2)
1829 base, local, other = [x[fn].data() for x in (pa, p1,
1829 base, local, other = [x[fn].data() for x in (pa, p1,
1830 p2)]
1830 p2)]
1831 m3 = simplemerge.Merge3Text(base, local, other)
1831 m3 = simplemerge.Merge3Text(base, local, other)
1832 ml = [l.strip() for l in m3.merge_lines()]
1832 ml = [l.strip() for l in m3.merge_lines()]
1833 ml.append("")
1833 ml.append("")
1834 elif at > 0:
1834 elif at > 0:
1835 ml = p1[fn].data().split("\n")
1835 ml = p1[fn].data().split("\n")
1836 else:
1836 else:
1837 ml = initialmergedlines
1837 ml = initialmergedlines
1838 ml[id * linesperrev] += " r%i" % id
1838 ml[id * linesperrev] += " r%i" % id
1839 mergedtext = "\n".join(ml)
1839 mergedtext = "\n".join(ml)
1840 files.append(fn)
1840 files.append(fn)
1841 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1841 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1842
1842
1843 if overwritten_file:
1843 if overwritten_file:
1844 fn = "of"
1844 fn = "of"
1845 files.append(fn)
1845 files.append(fn)
1846 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1846 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1847
1847
1848 if new_file:
1848 if new_file:
1849 fn = "nf%i" % id
1849 fn = "nf%i" % id
1850 files.append(fn)
1850 files.append(fn)
1851 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1851 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1852 if len(ps) > 1:
1852 if len(ps) > 1:
1853 if not p2:
1853 if not p2:
1854 p2 = repo[ps[1]]
1854 p2 = repo[ps[1]]
1855 for fn in p2:
1855 for fn in p2:
1856 if fn.startswith("nf"):
1856 if fn.startswith("nf"):
1857 files.append(fn)
1857 files.append(fn)
1858 fctxs[fn] = p2[fn]
1858 fctxs[fn] = p2[fn]
1859
1859
1860 def fctxfn(repo, cx, path):
1860 def fctxfn(repo, cx, path):
1861 return fctxs.get(path)
1861 return fctxs.get(path)
1862
1862
1863 if len(ps) == 0 or ps[0] < 0:
1863 if len(ps) == 0 or ps[0] < 0:
1864 pars = [None, None]
1864 pars = [None, None]
1865 elif len(ps) == 1:
1865 elif len(ps) == 1:
1866 pars = [nodeids[ps[0]], None]
1866 pars = [nodeids[ps[0]], None]
1867 else:
1867 else:
1868 pars = [nodeids[p] for p in ps]
1868 pars = [nodeids[p] for p in ps]
1869 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1869 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1870 date=(id, 0),
1870 date=(id, 0),
1871 user="debugbuilddag",
1871 user="debugbuilddag",
1872 extra={'branch': atbranch})
1872 extra={'branch': atbranch})
1873 nodeid = repo.commitctx(cx)
1873 nodeid = repo.commitctx(cx)
1874 nodeids.append(nodeid)
1874 nodeids.append(nodeid)
1875 at = id
1875 at = id
1876 elif type == 'l':
1876 elif type == 'l':
1877 id, name = data
1877 id, name = data
1878 ui.note(('tag %s\n' % name))
1878 ui.note(('tag %s\n' % name))
1879 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1879 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1880 elif type == 'a':
1880 elif type == 'a':
1881 ui.note(('branch %s\n' % data))
1881 ui.note(('branch %s\n' % data))
1882 atbranch = data
1882 atbranch = data
1883 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1883 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1884 tr.close()
1884 tr.close()
1885
1885
1886 if tags:
1886 if tags:
1887 repo.vfs.write("localtags", "".join(tags))
1887 repo.vfs.write("localtags", "".join(tags))
1888 finally:
1888 finally:
1889 ui.progress(_('building'), None)
1889 ui.progress(_('building'), None)
1890 release(tr, lock)
1890 release(tr, lock)
1891
1891
1892 @command('debugbundle',
1892 @command('debugbundle',
1893 [('a', 'all', None, _('show all details'))],
1893 [('a', 'all', None, _('show all details'))],
1894 _('FILE'),
1894 _('FILE'),
1895 norepo=True)
1895 norepo=True)
1896 def debugbundle(ui, bundlepath, all=None, **opts):
1896 def debugbundle(ui, bundlepath, all=None, **opts):
1897 """lists the contents of a bundle"""
1897 """lists the contents of a bundle"""
1898 f = hg.openpath(ui, bundlepath)
1898 f = hg.openpath(ui, bundlepath)
1899 try:
1899 try:
1900 gen = exchange.readbundle(ui, f, bundlepath)
1900 gen = exchange.readbundle(ui, f, bundlepath)
1901 if isinstance(gen, bundle2.unbundle20):
1901 if isinstance(gen, bundle2.unbundle20):
1902 return _debugbundle2(ui, gen, all=all, **opts)
1902 return _debugbundle2(ui, gen, all=all, **opts)
1903 if all:
1903 if all:
1904 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1904 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
1905
1905
1906 def showchunks(named):
1906 def showchunks(named):
1907 ui.write("\n%s\n" % named)
1907 ui.write("\n%s\n" % named)
1908 chain = None
1908 chain = None
1909 while True:
1909 while True:
1910 chunkdata = gen.deltachunk(chain)
1910 chunkdata = gen.deltachunk(chain)
1911 if not chunkdata:
1911 if not chunkdata:
1912 break
1912 break
1913 node = chunkdata['node']
1913 node = chunkdata['node']
1914 p1 = chunkdata['p1']
1914 p1 = chunkdata['p1']
1915 p2 = chunkdata['p2']
1915 p2 = chunkdata['p2']
1916 cs = chunkdata['cs']
1916 cs = chunkdata['cs']
1917 deltabase = chunkdata['deltabase']
1917 deltabase = chunkdata['deltabase']
1918 delta = chunkdata['delta']
1918 delta = chunkdata['delta']
1919 ui.write("%s %s %s %s %s %s\n" %
1919 ui.write("%s %s %s %s %s %s\n" %
1920 (hex(node), hex(p1), hex(p2),
1920 (hex(node), hex(p1), hex(p2),
1921 hex(cs), hex(deltabase), len(delta)))
1921 hex(cs), hex(deltabase), len(delta)))
1922 chain = node
1922 chain = node
1923
1923
1924 chunkdata = gen.changelogheader()
1924 chunkdata = gen.changelogheader()
1925 showchunks("changelog")
1925 showchunks("changelog")
1926 chunkdata = gen.manifestheader()
1926 chunkdata = gen.manifestheader()
1927 showchunks("manifest")
1927 showchunks("manifest")
1928 while True:
1928 while True:
1929 chunkdata = gen.filelogheader()
1929 chunkdata = gen.filelogheader()
1930 if not chunkdata:
1930 if not chunkdata:
1931 break
1931 break
1932 fname = chunkdata['filename']
1932 fname = chunkdata['filename']
1933 showchunks(fname)
1933 showchunks(fname)
1934 else:
1934 else:
1935 if isinstance(gen, bundle2.unbundle20):
1935 if isinstance(gen, bundle2.unbundle20):
1936 raise error.Abort(_('use debugbundle2 for this file'))
1936 raise error.Abort(_('use debugbundle2 for this file'))
1937 chunkdata = gen.changelogheader()
1937 chunkdata = gen.changelogheader()
1938 chain = None
1938 chain = None
1939 while True:
1939 while True:
1940 chunkdata = gen.deltachunk(chain)
1940 chunkdata = gen.deltachunk(chain)
1941 if not chunkdata:
1941 if not chunkdata:
1942 break
1942 break
1943 node = chunkdata['node']
1943 node = chunkdata['node']
1944 ui.write("%s\n" % hex(node))
1944 ui.write("%s\n" % hex(node))
1945 chain = node
1945 chain = node
1946 finally:
1946 finally:
1947 f.close()
1947 f.close()
1948
1948
1949 def _debugbundle2(ui, gen, **opts):
1949 def _debugbundle2(ui, gen, **opts):
1950 """lists the contents of a bundle2"""
1950 """lists the contents of a bundle2"""
1951 if not isinstance(gen, bundle2.unbundle20):
1951 if not isinstance(gen, bundle2.unbundle20):
1952 raise error.Abort(_('not a bundle2 file'))
1952 raise error.Abort(_('not a bundle2 file'))
1953 ui.write(('Stream params: %s\n' % repr(gen.params)))
1953 ui.write(('Stream params: %s\n' % repr(gen.params)))
1954 for part in gen.iterparts():
1954 for part in gen.iterparts():
1955 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1955 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
1956 if part.type == 'changegroup':
1956 if part.type == 'changegroup':
1957 version = part.params.get('version', '01')
1957 version = part.params.get('version', '01')
1958 cg = changegroup.packermap[version][1](part, 'UN')
1958 cg = changegroup.packermap[version][1](part, 'UN')
1959 chunkdata = cg.changelogheader()
1959 chunkdata = cg.changelogheader()
1960 chain = None
1960 chain = None
1961 while True:
1961 while True:
1962 chunkdata = cg.deltachunk(chain)
1962 chunkdata = cg.deltachunk(chain)
1963 if not chunkdata:
1963 if not chunkdata:
1964 break
1964 break
1965 node = chunkdata['node']
1965 node = chunkdata['node']
1966 ui.write(" %s\n" % hex(node))
1966 ui.write(" %s\n" % hex(node))
1967 chain = node
1967 chain = node
1968
1968
1969 @command('debugcreatestreamclonebundle', [], 'FILE')
1969 @command('debugcreatestreamclonebundle', [], 'FILE')
1970 def debugcreatestreamclonebundle(ui, repo, fname):
1970 def debugcreatestreamclonebundle(ui, repo, fname):
1971 """create a stream clone bundle file
1971 """create a stream clone bundle file
1972
1972
1973 Stream bundles are special bundles that are essentially archives of
1973 Stream bundles are special bundles that are essentially archives of
1974 revlog files. They are commonly used for cloning very quickly.
1974 revlog files. They are commonly used for cloning very quickly.
1975 """
1975 """
1976 requirements, gen = streamclone.generatebundlev1(repo)
1976 requirements, gen = streamclone.generatebundlev1(repo)
1977 changegroup.writechunks(ui, gen, fname)
1977 changegroup.writechunks(ui, gen, fname)
1978
1978
1979 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
1979 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
1980
1980
1981 @command('debugapplystreamclonebundle', [], 'FILE')
1981 @command('debugapplystreamclonebundle', [], 'FILE')
1982 def debugapplystreamclonebundle(ui, repo, fname):
1982 def debugapplystreamclonebundle(ui, repo, fname):
1983 """apply a stream clone bundle file"""
1983 """apply a stream clone bundle file"""
1984 f = hg.openpath(ui, fname)
1984 f = hg.openpath(ui, fname)
1985 gen = exchange.readbundle(ui, f, fname)
1985 gen = exchange.readbundle(ui, f, fname)
1986 gen.apply(repo)
1986 gen.apply(repo)
1987
1987
1988 @command('debugcheckstate', [], '')
1988 @command('debugcheckstate', [], '')
1989 def debugcheckstate(ui, repo):
1989 def debugcheckstate(ui, repo):
1990 """validate the correctness of the current dirstate"""
1990 """validate the correctness of the current dirstate"""
1991 parent1, parent2 = repo.dirstate.parents()
1991 parent1, parent2 = repo.dirstate.parents()
1992 m1 = repo[parent1].manifest()
1992 m1 = repo[parent1].manifest()
1993 m2 = repo[parent2].manifest()
1993 m2 = repo[parent2].manifest()
1994 errors = 0
1994 errors = 0
1995 for f in repo.dirstate:
1995 for f in repo.dirstate:
1996 state = repo.dirstate[f]
1996 state = repo.dirstate[f]
1997 if state in "nr" and f not in m1:
1997 if state in "nr" and f not in m1:
1998 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1998 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1999 errors += 1
1999 errors += 1
2000 if state in "a" and f in m1:
2000 if state in "a" and f in m1:
2001 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2001 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2002 errors += 1
2002 errors += 1
2003 if state in "m" and f not in m1 and f not in m2:
2003 if state in "m" and f not in m1 and f not in m2:
2004 ui.warn(_("%s in state %s, but not in either manifest\n") %
2004 ui.warn(_("%s in state %s, but not in either manifest\n") %
2005 (f, state))
2005 (f, state))
2006 errors += 1
2006 errors += 1
2007 for f in m1:
2007 for f in m1:
2008 state = repo.dirstate[f]
2008 state = repo.dirstate[f]
2009 if state not in "nrm":
2009 if state not in "nrm":
2010 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2010 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2011 errors += 1
2011 errors += 1
2012 if errors:
2012 if errors:
2013 error = _(".hg/dirstate inconsistent with current parent's manifest")
2013 error = _(".hg/dirstate inconsistent with current parent's manifest")
2014 raise error.Abort(error)
2014 raise error.Abort(error)
2015
2015
2016 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2016 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2017 def debugcommands(ui, cmd='', *args):
2017 def debugcommands(ui, cmd='', *args):
2018 """list all available commands and options"""
2018 """list all available commands and options"""
2019 for cmd, vals in sorted(table.iteritems()):
2019 for cmd, vals in sorted(table.iteritems()):
2020 cmd = cmd.split('|')[0].strip('^')
2020 cmd = cmd.split('|')[0].strip('^')
2021 opts = ', '.join([i[1] for i in vals[1]])
2021 opts = ', '.join([i[1] for i in vals[1]])
2022 ui.write('%s: %s\n' % (cmd, opts))
2022 ui.write('%s: %s\n' % (cmd, opts))
2023
2023
2024 @command('debugcomplete',
2024 @command('debugcomplete',
2025 [('o', 'options', None, _('show the command options'))],
2025 [('o', 'options', None, _('show the command options'))],
2026 _('[-o] CMD'),
2026 _('[-o] CMD'),
2027 norepo=True)
2027 norepo=True)
2028 def debugcomplete(ui, cmd='', **opts):
2028 def debugcomplete(ui, cmd='', **opts):
2029 """returns the completion list associated with the given command"""
2029 """returns the completion list associated with the given command"""
2030
2030
2031 if opts.get('options'):
2031 if opts.get('options'):
2032 options = []
2032 options = []
2033 otables = [globalopts]
2033 otables = [globalopts]
2034 if cmd:
2034 if cmd:
2035 aliases, entry = cmdutil.findcmd(cmd, table, False)
2035 aliases, entry = cmdutil.findcmd(cmd, table, False)
2036 otables.append(entry[1])
2036 otables.append(entry[1])
2037 for t in otables:
2037 for t in otables:
2038 for o in t:
2038 for o in t:
2039 if "(DEPRECATED)" in o[3]:
2039 if "(DEPRECATED)" in o[3]:
2040 continue
2040 continue
2041 if o[0]:
2041 if o[0]:
2042 options.append('-%s' % o[0])
2042 options.append('-%s' % o[0])
2043 options.append('--%s' % o[1])
2043 options.append('--%s' % o[1])
2044 ui.write("%s\n" % "\n".join(options))
2044 ui.write("%s\n" % "\n".join(options))
2045 return
2045 return
2046
2046
2047 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2047 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2048 if ui.verbose:
2048 if ui.verbose:
2049 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2049 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2050 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2050 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2051
2051
2052 @command('debugdag',
2052 @command('debugdag',
2053 [('t', 'tags', None, _('use tags as labels')),
2053 [('t', 'tags', None, _('use tags as labels')),
2054 ('b', 'branches', None, _('annotate with branch names')),
2054 ('b', 'branches', None, _('annotate with branch names')),
2055 ('', 'dots', None, _('use dots for runs')),
2055 ('', 'dots', None, _('use dots for runs')),
2056 ('s', 'spaces', None, _('separate elements by spaces'))],
2056 ('s', 'spaces', None, _('separate elements by spaces'))],
2057 _('[OPTION]... [FILE [REV]...]'),
2057 _('[OPTION]... [FILE [REV]...]'),
2058 optionalrepo=True)
2058 optionalrepo=True)
2059 def debugdag(ui, repo, file_=None, *revs, **opts):
2059 def debugdag(ui, repo, file_=None, *revs, **opts):
2060 """format the changelog or an index DAG as a concise textual description
2060 """format the changelog or an index DAG as a concise textual description
2061
2061
2062 If you pass a revlog index, the revlog's DAG is emitted. If you list
2062 If you pass a revlog index, the revlog's DAG is emitted. If you list
2063 revision numbers, they get labeled in the output as rN.
2063 revision numbers, they get labeled in the output as rN.
2064
2064
2065 Otherwise, the changelog DAG of the current repo is emitted.
2065 Otherwise, the changelog DAG of the current repo is emitted.
2066 """
2066 """
2067 spaces = opts.get('spaces')
2067 spaces = opts.get('spaces')
2068 dots = opts.get('dots')
2068 dots = opts.get('dots')
2069 if file_:
2069 if file_:
2070 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2070 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2071 revs = set((int(r) for r in revs))
2071 revs = set((int(r) for r in revs))
2072 def events():
2072 def events():
2073 for r in rlog:
2073 for r in rlog:
2074 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2074 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2075 if p != -1))
2075 if p != -1))
2076 if r in revs:
2076 if r in revs:
2077 yield 'l', (r, "r%i" % r)
2077 yield 'l', (r, "r%i" % r)
2078 elif repo:
2078 elif repo:
2079 cl = repo.changelog
2079 cl = repo.changelog
2080 tags = opts.get('tags')
2080 tags = opts.get('tags')
2081 branches = opts.get('branches')
2081 branches = opts.get('branches')
2082 if tags:
2082 if tags:
2083 labels = {}
2083 labels = {}
2084 for l, n in repo.tags().items():
2084 for l, n in repo.tags().items():
2085 labels.setdefault(cl.rev(n), []).append(l)
2085 labels.setdefault(cl.rev(n), []).append(l)
2086 def events():
2086 def events():
2087 b = "default"
2087 b = "default"
2088 for r in cl:
2088 for r in cl:
2089 if branches:
2089 if branches:
2090 newb = cl.read(cl.node(r))[5]['branch']
2090 newb = cl.read(cl.node(r))[5]['branch']
2091 if newb != b:
2091 if newb != b:
2092 yield 'a', newb
2092 yield 'a', newb
2093 b = newb
2093 b = newb
2094 yield 'n', (r, list(p for p in cl.parentrevs(r)
2094 yield 'n', (r, list(p for p in cl.parentrevs(r)
2095 if p != -1))
2095 if p != -1))
2096 if tags:
2096 if tags:
2097 ls = labels.get(r)
2097 ls = labels.get(r)
2098 if ls:
2098 if ls:
2099 for l in ls:
2099 for l in ls:
2100 yield 'l', (r, l)
2100 yield 'l', (r, l)
2101 else:
2101 else:
2102 raise error.Abort(_('need repo for changelog dag'))
2102 raise error.Abort(_('need repo for changelog dag'))
2103
2103
2104 for line in dagparser.dagtextlines(events(),
2104 for line in dagparser.dagtextlines(events(),
2105 addspaces=spaces,
2105 addspaces=spaces,
2106 wraplabels=True,
2106 wraplabels=True,
2107 wrapannotations=True,
2107 wrapannotations=True,
2108 wrapnonlinear=dots,
2108 wrapnonlinear=dots,
2109 usedots=dots,
2109 usedots=dots,
2110 maxlinewidth=70):
2110 maxlinewidth=70):
2111 ui.write(line)
2111 ui.write(line)
2112 ui.write("\n")
2112 ui.write("\n")
2113
2113
2114 @command('debugdata',
2114 @command('debugdata',
2115 [('c', 'changelog', False, _('open changelog')),
2115 [('c', 'changelog', False, _('open changelog')),
2116 ('m', 'manifest', False, _('open manifest')),
2116 ('m', 'manifest', False, _('open manifest')),
2117 ('', 'dir', False, _('open directory manifest'))],
2117 ('', 'dir', False, _('open directory manifest'))],
2118 _('-c|-m|FILE REV'))
2118 _('-c|-m|FILE REV'))
2119 def debugdata(ui, repo, file_, rev=None, **opts):
2119 def debugdata(ui, repo, file_, rev=None, **opts):
2120 """dump the contents of a data file revision"""
2120 """dump the contents of a data file revision"""
2121 if opts.get('changelog') or opts.get('manifest'):
2121 if opts.get('changelog') or opts.get('manifest'):
2122 file_, rev = None, file_
2122 file_, rev = None, file_
2123 elif rev is None:
2123 elif rev is None:
2124 raise error.CommandError('debugdata', _('invalid arguments'))
2124 raise error.CommandError('debugdata', _('invalid arguments'))
2125 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2125 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2126 try:
2126 try:
2127 ui.write(r.revision(r.lookup(rev)))
2127 ui.write(r.revision(r.lookup(rev)))
2128 except KeyError:
2128 except KeyError:
2129 raise error.Abort(_('invalid revision identifier %s') % rev)
2129 raise error.Abort(_('invalid revision identifier %s') % rev)
2130
2130
2131 @command('debugdate',
2131 @command('debugdate',
2132 [('e', 'extended', None, _('try extended date formats'))],
2132 [('e', 'extended', None, _('try extended date formats'))],
2133 _('[-e] DATE [RANGE]'),
2133 _('[-e] DATE [RANGE]'),
2134 norepo=True, optionalrepo=True)
2134 norepo=True, optionalrepo=True)
2135 def debugdate(ui, date, range=None, **opts):
2135 def debugdate(ui, date, range=None, **opts):
2136 """parse and display a date"""
2136 """parse and display a date"""
2137 if opts["extended"]:
2137 if opts["extended"]:
2138 d = util.parsedate(date, util.extendeddateformats)
2138 d = util.parsedate(date, util.extendeddateformats)
2139 else:
2139 else:
2140 d = util.parsedate(date)
2140 d = util.parsedate(date)
2141 ui.write(("internal: %s %s\n") % d)
2141 ui.write(("internal: %s %s\n") % d)
2142 ui.write(("standard: %s\n") % util.datestr(d))
2142 ui.write(("standard: %s\n") % util.datestr(d))
2143 if range:
2143 if range:
2144 m = util.matchdate(range)
2144 m = util.matchdate(range)
2145 ui.write(("match: %s\n") % m(d[0]))
2145 ui.write(("match: %s\n") % m(d[0]))
2146
2146
2147 @command('debugdiscovery',
2147 @command('debugdiscovery',
2148 [('', 'old', None, _('use old-style discovery')),
2148 [('', 'old', None, _('use old-style discovery')),
2149 ('', 'nonheads', None,
2149 ('', 'nonheads', None,
2150 _('use old-style discovery with non-heads included')),
2150 _('use old-style discovery with non-heads included')),
2151 ] + remoteopts,
2151 ] + remoteopts,
2152 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2152 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2153 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2153 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2154 """runs the changeset discovery protocol in isolation"""
2154 """runs the changeset discovery protocol in isolation"""
2155 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2155 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2156 opts.get('branch'))
2156 opts.get('branch'))
2157 remote = hg.peer(repo, opts, remoteurl)
2157 remote = hg.peer(repo, opts, remoteurl)
2158 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2158 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2159
2159
2160 # make sure tests are repeatable
2160 # make sure tests are repeatable
2161 random.seed(12323)
2161 random.seed(12323)
2162
2162
2163 def doit(localheads, remoteheads, remote=remote):
2163 def doit(localheads, remoteheads, remote=remote):
2164 if opts.get('old'):
2164 if opts.get('old'):
2165 if localheads:
2165 if localheads:
2166 raise error.Abort('cannot use localheads with old style '
2166 raise error.Abort('cannot use localheads with old style '
2167 'discovery')
2167 'discovery')
2168 if not util.safehasattr(remote, 'branches'):
2168 if not util.safehasattr(remote, 'branches'):
2169 # enable in-client legacy support
2169 # enable in-client legacy support
2170 remote = localrepo.locallegacypeer(remote.local())
2170 remote = localrepo.locallegacypeer(remote.local())
2171 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2171 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2172 force=True)
2172 force=True)
2173 common = set(common)
2173 common = set(common)
2174 if not opts.get('nonheads'):
2174 if not opts.get('nonheads'):
2175 ui.write(("unpruned common: %s\n") %
2175 ui.write(("unpruned common: %s\n") %
2176 " ".join(sorted(short(n) for n in common)))
2176 " ".join(sorted(short(n) for n in common)))
2177 dag = dagutil.revlogdag(repo.changelog)
2177 dag = dagutil.revlogdag(repo.changelog)
2178 all = dag.ancestorset(dag.internalizeall(common))
2178 all = dag.ancestorset(dag.internalizeall(common))
2179 common = dag.externalizeall(dag.headsetofconnecteds(all))
2179 common = dag.externalizeall(dag.headsetofconnecteds(all))
2180 else:
2180 else:
2181 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2181 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2182 common = set(common)
2182 common = set(common)
2183 rheads = set(hds)
2183 rheads = set(hds)
2184 lheads = set(repo.heads())
2184 lheads = set(repo.heads())
2185 ui.write(("common heads: %s\n") %
2185 ui.write(("common heads: %s\n") %
2186 " ".join(sorted(short(n) for n in common)))
2186 " ".join(sorted(short(n) for n in common)))
2187 if lheads <= common:
2187 if lheads <= common:
2188 ui.write(("local is subset\n"))
2188 ui.write(("local is subset\n"))
2189 elif rheads <= common:
2189 elif rheads <= common:
2190 ui.write(("remote is subset\n"))
2190 ui.write(("remote is subset\n"))
2191
2191
2192 serverlogs = opts.get('serverlog')
2192 serverlogs = opts.get('serverlog')
2193 if serverlogs:
2193 if serverlogs:
2194 for filename in serverlogs:
2194 for filename in serverlogs:
2195 logfile = open(filename, 'r')
2195 logfile = open(filename, 'r')
2196 try:
2196 try:
2197 line = logfile.readline()
2197 line = logfile.readline()
2198 while line:
2198 while line:
2199 parts = line.strip().split(';')
2199 parts = line.strip().split(';')
2200 op = parts[1]
2200 op = parts[1]
2201 if op == 'cg':
2201 if op == 'cg':
2202 pass
2202 pass
2203 elif op == 'cgss':
2203 elif op == 'cgss':
2204 doit(parts[2].split(' '), parts[3].split(' '))
2204 doit(parts[2].split(' '), parts[3].split(' '))
2205 elif op == 'unb':
2205 elif op == 'unb':
2206 doit(parts[3].split(' '), parts[2].split(' '))
2206 doit(parts[3].split(' '), parts[2].split(' '))
2207 line = logfile.readline()
2207 line = logfile.readline()
2208 finally:
2208 finally:
2209 logfile.close()
2209 logfile.close()
2210
2210
2211 else:
2211 else:
2212 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2212 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2213 opts.get('remote_head'))
2213 opts.get('remote_head'))
2214 localrevs = opts.get('local_head')
2214 localrevs = opts.get('local_head')
2215 doit(localrevs, remoterevs)
2215 doit(localrevs, remoterevs)
2216
2216
2217 @command('debugextensions', formatteropts, [], norepo=True)
2217 @command('debugextensions', formatteropts, [], norepo=True)
2218 def debugextensions(ui, **opts):
2218 def debugextensions(ui, **opts):
2219 '''show information about active extensions'''
2219 '''show information about active extensions'''
2220 exts = extensions.extensions(ui)
2220 exts = extensions.extensions(ui)
2221 fm = ui.formatter('debugextensions', opts)
2221 fm = ui.formatter('debugextensions', opts)
2222 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2222 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2223 extsource = extmod.__file__
2223 extsource = extmod.__file__
2224 exttestedwith = getattr(extmod, 'testedwith', None)
2224 exttestedwith = getattr(extmod, 'testedwith', None)
2225 if exttestedwith is not None:
2225 if exttestedwith is not None:
2226 exttestedwith = exttestedwith.split()
2226 exttestedwith = exttestedwith.split()
2227 extbuglink = getattr(extmod, 'buglink', None)
2227 extbuglink = getattr(extmod, 'buglink', None)
2228
2228
2229 fm.startitem()
2229 fm.startitem()
2230
2230
2231 if ui.quiet or ui.verbose:
2231 if ui.quiet or ui.verbose:
2232 fm.write('name', '%s\n', extname)
2232 fm.write('name', '%s\n', extname)
2233 else:
2233 else:
2234 fm.write('name', '%s', extname)
2234 fm.write('name', '%s', extname)
2235 if not exttestedwith:
2235 if not exttestedwith:
2236 fm.plain(_(' (untested!)\n'))
2236 fm.plain(_(' (untested!)\n'))
2237 else:
2237 else:
2238 if exttestedwith == ['internal'] or \
2238 if exttestedwith == ['internal'] or \
2239 util.version() in exttestedwith:
2239 util.version() in exttestedwith:
2240 fm.plain('\n')
2240 fm.plain('\n')
2241 else:
2241 else:
2242 lasttestedversion = exttestedwith[-1]
2242 lasttestedversion = exttestedwith[-1]
2243 fm.plain(' (%s!)\n' % lasttestedversion)
2243 fm.plain(' (%s!)\n' % lasttestedversion)
2244
2244
2245 fm.condwrite(ui.verbose and extsource, 'source',
2245 fm.condwrite(ui.verbose and extsource, 'source',
2246 _(' location: %s\n'), extsource or "")
2246 _(' location: %s\n'), extsource or "")
2247
2247
2248 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2248 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2249 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2249 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2250
2250
2251 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2251 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2252 _(' bug reporting: %s\n'), extbuglink or "")
2252 _(' bug reporting: %s\n'), extbuglink or "")
2253
2253
2254 fm.end()
2254 fm.end()
2255
2255
2256 @command('debugfileset',
2256 @command('debugfileset',
2257 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2257 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2258 _('[-r REV] FILESPEC'))
2258 _('[-r REV] FILESPEC'))
2259 def debugfileset(ui, repo, expr, **opts):
2259 def debugfileset(ui, repo, expr, **opts):
2260 '''parse and apply a fileset specification'''
2260 '''parse and apply a fileset specification'''
2261 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2261 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2262 if ui.verbose:
2262 if ui.verbose:
2263 tree = fileset.parse(expr)
2263 tree = fileset.parse(expr)
2264 ui.note(fileset.prettyformat(tree), "\n")
2264 ui.note(fileset.prettyformat(tree), "\n")
2265
2265
2266 for f in ctx.getfileset(expr):
2266 for f in ctx.getfileset(expr):
2267 ui.write("%s\n" % f)
2267 ui.write("%s\n" % f)
2268
2268
2269 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2269 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2270 def debugfsinfo(ui, path="."):
2270 def debugfsinfo(ui, path="."):
2271 """show information detected about current filesystem"""
2271 """show information detected about current filesystem"""
2272 util.writefile('.debugfsinfo', '')
2272 util.writefile('.debugfsinfo', '')
2273 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2273 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2274 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2274 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2275 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2275 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2276 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2276 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2277 and 'yes' or 'no'))
2277 and 'yes' or 'no'))
2278 os.unlink('.debugfsinfo')
2278 os.unlink('.debugfsinfo')
2279
2279
2280 @command('debuggetbundle',
2280 @command('debuggetbundle',
2281 [('H', 'head', [], _('id of head node'), _('ID')),
2281 [('H', 'head', [], _('id of head node'), _('ID')),
2282 ('C', 'common', [], _('id of common node'), _('ID')),
2282 ('C', 'common', [], _('id of common node'), _('ID')),
2283 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2283 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2284 _('REPO FILE [-H|-C ID]...'),
2284 _('REPO FILE [-H|-C ID]...'),
2285 norepo=True)
2285 norepo=True)
2286 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2286 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2287 """retrieves a bundle from a repo
2287 """retrieves a bundle from a repo
2288
2288
2289 Every ID must be a full-length hex node id string. Saves the bundle to the
2289 Every ID must be a full-length hex node id string. Saves the bundle to the
2290 given file.
2290 given file.
2291 """
2291 """
2292 repo = hg.peer(ui, opts, repopath)
2292 repo = hg.peer(ui, opts, repopath)
2293 if not repo.capable('getbundle'):
2293 if not repo.capable('getbundle'):
2294 raise error.Abort("getbundle() not supported by target repository")
2294 raise error.Abort("getbundle() not supported by target repository")
2295 args = {}
2295 args = {}
2296 if common:
2296 if common:
2297 args['common'] = [bin(s) for s in common]
2297 args['common'] = [bin(s) for s in common]
2298 if head:
2298 if head:
2299 args['heads'] = [bin(s) for s in head]
2299 args['heads'] = [bin(s) for s in head]
2300 # TODO: get desired bundlecaps from command line.
2300 # TODO: get desired bundlecaps from command line.
2301 args['bundlecaps'] = None
2301 args['bundlecaps'] = None
2302 bundle = repo.getbundle('debug', **args)
2302 bundle = repo.getbundle('debug', **args)
2303
2303
2304 bundletype = opts.get('type', 'bzip2').lower()
2304 bundletype = opts.get('type', 'bzip2').lower()
2305 btypes = {'none': 'HG10UN',
2305 btypes = {'none': 'HG10UN',
2306 'bzip2': 'HG10BZ',
2306 'bzip2': 'HG10BZ',
2307 'gzip': 'HG10GZ',
2307 'gzip': 'HG10GZ',
2308 'bundle2': 'HG20'}
2308 'bundle2': 'HG20'}
2309 bundletype = btypes.get(bundletype)
2309 bundletype = btypes.get(bundletype)
2310 if bundletype not in changegroup.bundletypes:
2310 if bundletype not in changegroup.bundletypes:
2311 raise error.Abort(_('unknown bundle type specified with --type'))
2311 raise error.Abort(_('unknown bundle type specified with --type'))
2312 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2312 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2313
2313
2314 @command('debugignore', [], '')
2314 @command('debugignore', [], '')
2315 def debugignore(ui, repo, *values, **opts):
2315 def debugignore(ui, repo, *values, **opts):
2316 """display the combined ignore pattern"""
2316 """display the combined ignore pattern"""
2317 ignore = repo.dirstate._ignore
2317 ignore = repo.dirstate._ignore
2318 includepat = getattr(ignore, 'includepat', None)
2318 includepat = getattr(ignore, 'includepat', None)
2319 if includepat is not None:
2319 if includepat is not None:
2320 ui.write("%s\n" % includepat)
2320 ui.write("%s\n" % includepat)
2321 else:
2321 else:
2322 raise error.Abort(_("no ignore patterns found"))
2322 raise error.Abort(_("no ignore patterns found"))
2323
2323
2324 @command('debugindex',
2324 @command('debugindex',
2325 [('c', 'changelog', False, _('open changelog')),
2325 [('c', 'changelog', False, _('open changelog')),
2326 ('m', 'manifest', False, _('open manifest')),
2326 ('m', 'manifest', False, _('open manifest')),
2327 ('', 'dir', False, _('open directory manifest')),
2327 ('', 'dir', False, _('open directory manifest')),
2328 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2328 ('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2329 _('[-f FORMAT] -c|-m|FILE'),
2329 _('[-f FORMAT] -c|-m|FILE'),
2330 optionalrepo=True)
2330 optionalrepo=True)
2331 def debugindex(ui, repo, file_=None, **opts):
2331 def debugindex(ui, repo, file_=None, **opts):
2332 """dump the contents of an index file"""
2332 """dump the contents of an index file"""
2333 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2333 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2334 format = opts.get('format', 0)
2334 format = opts.get('format', 0)
2335 if format not in (0, 1):
2335 if format not in (0, 1):
2336 raise error.Abort(_("unknown format %d") % format)
2336 raise error.Abort(_("unknown format %d") % format)
2337
2337
2338 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2338 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2339 if generaldelta:
2339 if generaldelta:
2340 basehdr = ' delta'
2340 basehdr = ' delta'
2341 else:
2341 else:
2342 basehdr = ' base'
2342 basehdr = ' base'
2343
2343
2344 if ui.debugflag:
2344 if ui.debugflag:
2345 shortfn = hex
2345 shortfn = hex
2346 else:
2346 else:
2347 shortfn = short
2347 shortfn = short
2348
2348
2349 # There might not be anything in r, so have a sane default
2349 # There might not be anything in r, so have a sane default
2350 idlen = 12
2350 idlen = 12
2351 for i in r:
2351 for i in r:
2352 idlen = len(shortfn(r.node(i)))
2352 idlen = len(shortfn(r.node(i)))
2353 break
2353 break
2354
2354
2355 if format == 0:
2355 if format == 0:
2356 ui.write(" rev offset length " + basehdr + " linkrev"
2356 ui.write(" rev offset length " + basehdr + " linkrev"
2357 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2357 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2358 elif format == 1:
2358 elif format == 1:
2359 ui.write(" rev flag offset length"
2359 ui.write(" rev flag offset length"
2360 " size " + basehdr + " link p1 p2"
2360 " size " + basehdr + " link p1 p2"
2361 " %s\n" % "nodeid".rjust(idlen))
2361 " %s\n" % "nodeid".rjust(idlen))
2362
2362
2363 for i in r:
2363 for i in r:
2364 node = r.node(i)
2364 node = r.node(i)
2365 if generaldelta:
2365 if generaldelta:
2366 base = r.deltaparent(i)
2366 base = r.deltaparent(i)
2367 else:
2367 else:
2368 base = r.chainbase(i)
2368 base = r.chainbase(i)
2369 if format == 0:
2369 if format == 0:
2370 try:
2370 try:
2371 pp = r.parents(node)
2371 pp = r.parents(node)
2372 except Exception:
2372 except Exception:
2373 pp = [nullid, nullid]
2373 pp = [nullid, nullid]
2374 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2374 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2375 i, r.start(i), r.length(i), base, r.linkrev(i),
2375 i, r.start(i), r.length(i), base, r.linkrev(i),
2376 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2376 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2377 elif format == 1:
2377 elif format == 1:
2378 pr = r.parentrevs(i)
2378 pr = r.parentrevs(i)
2379 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2379 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2380 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2380 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2381 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2381 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2382
2382
2383 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2383 @command('debugindexdot', [], _('FILE'), optionalrepo=True)
2384 def debugindexdot(ui, repo, file_):
2384 def debugindexdot(ui, repo, file_):
2385 """dump an index DAG as a graphviz dot file"""
2385 """dump an index DAG as a graphviz dot file"""
2386 r = None
2386 r = None
2387 if repo:
2387 if repo:
2388 filelog = repo.file(file_)
2388 filelog = repo.file(file_)
2389 if len(filelog):
2389 if len(filelog):
2390 r = filelog
2390 r = filelog
2391 if not r:
2391 if not r:
2392 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2392 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2393 ui.write(("digraph G {\n"))
2393 ui.write(("digraph G {\n"))
2394 for i in r:
2394 for i in r:
2395 node = r.node(i)
2395 node = r.node(i)
2396 pp = r.parents(node)
2396 pp = r.parents(node)
2397 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2397 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2398 if pp[1] != nullid:
2398 if pp[1] != nullid:
2399 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2399 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2400 ui.write("}\n")
2400 ui.write("}\n")
2401
2401
2402 @command('debuginstall', [], '', norepo=True)
2402 @command('debuginstall', [], '', norepo=True)
2403 def debuginstall(ui):
2403 def debuginstall(ui):
2404 '''test Mercurial installation
2404 '''test Mercurial installation
2405
2405
2406 Returns 0 on success.
2406 Returns 0 on success.
2407 '''
2407 '''
2408
2408
2409 def writetemp(contents):
2409 def writetemp(contents):
2410 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2410 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2411 f = os.fdopen(fd, "wb")
2411 f = os.fdopen(fd, "wb")
2412 f.write(contents)
2412 f.write(contents)
2413 f.close()
2413 f.close()
2414 return name
2414 return name
2415
2415
2416 problems = 0
2416 problems = 0
2417
2417
2418 # encoding
2418 # encoding
2419 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2419 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2420 try:
2420 try:
2421 encoding.fromlocal("test")
2421 encoding.fromlocal("test")
2422 except error.Abort as inst:
2422 except error.Abort as inst:
2423 ui.write(" %s\n" % inst)
2423 ui.write(" %s\n" % inst)
2424 ui.write(_(" (check that your locale is properly set)\n"))
2424 ui.write(_(" (check that your locale is properly set)\n"))
2425 problems += 1
2425 problems += 1
2426
2426
2427 # Python
2427 # Python
2428 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2428 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2429 ui.status(_("checking Python version (%s)\n")
2429 ui.status(_("checking Python version (%s)\n")
2430 % ("%s.%s.%s" % sys.version_info[:3]))
2430 % ("%s.%s.%s" % sys.version_info[:3]))
2431 ui.status(_("checking Python lib (%s)...\n")
2431 ui.status(_("checking Python lib (%s)...\n")
2432 % os.path.dirname(os.__file__))
2432 % os.path.dirname(os.__file__))
2433
2433
2434 # compiled modules
2434 # compiled modules
2435 ui.status(_("checking installed modules (%s)...\n")
2435 ui.status(_("checking installed modules (%s)...\n")
2436 % os.path.dirname(__file__))
2436 % os.path.dirname(__file__))
2437 try:
2437 try:
2438 import bdiff, mpatch, base85, osutil
2438 import bdiff, mpatch, base85, osutil
2439 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2439 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2440 except Exception as inst:
2440 except Exception as inst:
2441 ui.write(" %s\n" % inst)
2441 ui.write(" %s\n" % inst)
2442 ui.write(_(" One or more extensions could not be found"))
2442 ui.write(_(" One or more extensions could not be found"))
2443 ui.write(_(" (check that you compiled the extensions)\n"))
2443 ui.write(_(" (check that you compiled the extensions)\n"))
2444 problems += 1
2444 problems += 1
2445
2445
2446 # templates
2446 # templates
2447 import templater
2447 import templater
2448 p = templater.templatepaths()
2448 p = templater.templatepaths()
2449 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2449 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2450 if p:
2450 if p:
2451 m = templater.templatepath("map-cmdline.default")
2451 m = templater.templatepath("map-cmdline.default")
2452 if m:
2452 if m:
2453 # template found, check if it is working
2453 # template found, check if it is working
2454 try:
2454 try:
2455 templater.templater(m)
2455 templater.templater(m)
2456 except Exception as inst:
2456 except Exception as inst:
2457 ui.write(" %s\n" % inst)
2457 ui.write(" %s\n" % inst)
2458 p = None
2458 p = None
2459 else:
2459 else:
2460 ui.write(_(" template 'default' not found\n"))
2460 ui.write(_(" template 'default' not found\n"))
2461 p = None
2461 p = None
2462 else:
2462 else:
2463 ui.write(_(" no template directories found\n"))
2463 ui.write(_(" no template directories found\n"))
2464 if not p:
2464 if not p:
2465 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2465 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2466 problems += 1
2466 problems += 1
2467
2467
2468 # editor
2468 # editor
2469 ui.status(_("checking commit editor...\n"))
2469 ui.status(_("checking commit editor...\n"))
2470 editor = ui.geteditor()
2470 editor = ui.geteditor()
2471 editor = util.expandpath(editor)
2471 editor = util.expandpath(editor)
2472 cmdpath = util.findexe(shlex.split(editor)[0])
2472 cmdpath = util.findexe(shlex.split(editor)[0])
2473 if not cmdpath:
2473 if not cmdpath:
2474 if editor == 'vi':
2474 if editor == 'vi':
2475 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2475 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2476 ui.write(_(" (specify a commit editor in your configuration"
2476 ui.write(_(" (specify a commit editor in your configuration"
2477 " file)\n"))
2477 " file)\n"))
2478 else:
2478 else:
2479 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2479 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2480 ui.write(_(" (specify a commit editor in your configuration"
2480 ui.write(_(" (specify a commit editor in your configuration"
2481 " file)\n"))
2481 " file)\n"))
2482 problems += 1
2482 problems += 1
2483
2483
2484 # check username
2484 # check username
2485 ui.status(_("checking username...\n"))
2485 ui.status(_("checking username...\n"))
2486 try:
2486 try:
2487 ui.username()
2487 ui.username()
2488 except error.Abort as e:
2488 except error.Abort as e:
2489 ui.write(" %s\n" % e)
2489 ui.write(" %s\n" % e)
2490 ui.write(_(" (specify a username in your configuration file)\n"))
2490 ui.write(_(" (specify a username in your configuration file)\n"))
2491 problems += 1
2491 problems += 1
2492
2492
2493 if not problems:
2493 if not problems:
2494 ui.status(_("no problems detected\n"))
2494 ui.status(_("no problems detected\n"))
2495 else:
2495 else:
2496 ui.write(_("%s problems detected,"
2496 ui.write(_("%s problems detected,"
2497 " please check your install!\n") % problems)
2497 " please check your install!\n") % problems)
2498
2498
2499 return problems
2499 return problems
2500
2500
2501 @command('debugknown', [], _('REPO ID...'), norepo=True)
2501 @command('debugknown', [], _('REPO ID...'), norepo=True)
2502 def debugknown(ui, repopath, *ids, **opts):
2502 def debugknown(ui, repopath, *ids, **opts):
2503 """test whether node ids are known to a repo
2503 """test whether node ids are known to a repo
2504
2504
2505 Every ID must be a full-length hex node id string. Returns a list of 0s
2505 Every ID must be a full-length hex node id string. Returns a list of 0s
2506 and 1s indicating unknown/known.
2506 and 1s indicating unknown/known.
2507 """
2507 """
2508 repo = hg.peer(ui, opts, repopath)
2508 repo = hg.peer(ui, opts, repopath)
2509 if not repo.capable('known'):
2509 if not repo.capable('known'):
2510 raise error.Abort("known() not supported by target repository")
2510 raise error.Abort("known() not supported by target repository")
2511 flags = repo.known([bin(s) for s in ids])
2511 flags = repo.known([bin(s) for s in ids])
2512 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2512 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2513
2513
2514 @command('debuglabelcomplete', [], _('LABEL...'))
2514 @command('debuglabelcomplete', [], _('LABEL...'))
2515 def debuglabelcomplete(ui, repo, *args):
2515 def debuglabelcomplete(ui, repo, *args):
2516 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2516 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2517 debugnamecomplete(ui, repo, *args)
2517 debugnamecomplete(ui, repo, *args)
2518
2518
2519 @command('debugmergestate', [], '')
2519 @command('debugmergestate', [], '')
2520 def debugmergestate(ui, repo, *args):
2520 def debugmergestate(ui, repo, *args):
2521 """print merge state
2521 """print merge state
2522
2522
2523 Use --verbose to print out information about whether v1 or v2 merge state
2523 Use --verbose to print out information about whether v1 or v2 merge state
2524 was chosen."""
2524 was chosen."""
2525 def printrecords(version):
2525 def printrecords(version):
2526 ui.write(('* version %s records\n') % version)
2526 ui.write(('* version %s records\n') % version)
2527 if version == 1:
2527 if version == 1:
2528 records = v1records
2528 records = v1records
2529 else:
2529 else:
2530 records = v2records
2530 records = v2records
2531
2531
2532 for rtype, record in records:
2532 for rtype, record in records:
2533 # pretty print some record types
2533 # pretty print some record types
2534 if rtype == 'L':
2534 if rtype == 'L':
2535 ui.write(('local: %s\n') % record)
2535 ui.write(('local: %s\n') % record)
2536 elif rtype == 'O':
2536 elif rtype == 'O':
2537 ui.write(('other: %s\n') % record)
2537 ui.write(('other: %s\n') % record)
2538 elif rtype == 'm':
2538 elif rtype == 'm':
2539 driver, mdstate = record.split('\0', 1)
2539 driver, mdstate = record.split('\0', 1)
2540 ui.write(('merge driver: %s (state "%s")\n')
2540 ui.write(('merge driver: %s (state "%s")\n')
2541 % (driver, mdstate))
2541 % (driver, mdstate))
2542 elif rtype in 'FD':
2542 elif rtype in 'FD':
2543 r = record.split('\0')
2543 r = record.split('\0')
2544 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2544 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2545 if version == 1:
2545 if version == 1:
2546 onode = 'not stored in v1 format'
2546 onode = 'not stored in v1 format'
2547 flags = r[7]
2547 flags = r[7]
2548 else:
2548 else:
2549 onode, flags = r[7:9]
2549 onode, flags = r[7:9]
2550 ui.write(('file: %s (state "%s", hash %s)\n')
2550 ui.write(('file: %s (state "%s", hash %s)\n')
2551 % (f, state, hash))
2551 % (f, state, hash))
2552 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2552 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2553 ui.write((' ancestor path: %s (node %s)\n') % (afile, anode))
2553 ui.write((' ancestor path: %s (node %s)\n') % (afile, anode))
2554 ui.write((' other path: %s (node %s)\n') % (ofile, onode))
2554 ui.write((' other path: %s (node %s)\n') % (ofile, onode))
2555 else:
2555 else:
2556 ui.write(('unrecognized entry: %s\t%s\n')
2556 ui.write(('unrecognized entry: %s\t%s\n')
2557 % (rtype, record.replace('\0', '\t')))
2557 % (rtype, record.replace('\0', '\t')))
2558
2558
2559 ms = mergemod.mergestate(repo)
2559 ms = mergemod.mergestate(repo)
2560
2560
2561 # sort so that reasonable information is on top
2561 # sort so that reasonable information is on top
2562 v1records = ms._readrecordsv1()
2562 v1records = ms._readrecordsv1()
2563 v2records = ms._readrecordsv2()
2563 v2records = ms._readrecordsv2()
2564 order = 'LOm'
2564 order = 'LOm'
2565 def key(r):
2565 def key(r):
2566 idx = order.find(r[0])
2566 idx = order.find(r[0])
2567 if idx == -1:
2567 if idx == -1:
2568 return (1, r[1])
2568 return (1, r[1])
2569 else:
2569 else:
2570 return (0, idx)
2570 return (0, idx)
2571 v1records.sort(key=key)
2571 v1records.sort(key=key)
2572 v2records.sort(key=key)
2572 v2records.sort(key=key)
2573
2573
2574 if not v1records and not v2records:
2574 if not v1records and not v2records:
2575 ui.write(('no merge state found\n'))
2575 ui.write(('no merge state found\n'))
2576 elif not v2records:
2576 elif not v2records:
2577 ui.note(('no version 2 merge state\n'))
2577 ui.note(('no version 2 merge state\n'))
2578 printrecords(1)
2578 printrecords(1)
2579 elif ms._v1v2match(v1records, v2records):
2579 elif ms._v1v2match(v1records, v2records):
2580 ui.note(('v1 and v2 states match: using v2\n'))
2580 ui.note(('v1 and v2 states match: using v2\n'))
2581 printrecords(2)
2581 printrecords(2)
2582 else:
2582 else:
2583 ui.note(('v1 and v2 states mismatch: using v1\n'))
2583 ui.note(('v1 and v2 states mismatch: using v1\n'))
2584 printrecords(1)
2584 printrecords(1)
2585 if ui.verbose:
2585 if ui.verbose:
2586 printrecords(2)
2586 printrecords(2)
2587
2587
2588 @command('debugnamecomplete', [], _('NAME...'))
2588 @command('debugnamecomplete', [], _('NAME...'))
2589 def debugnamecomplete(ui, repo, *args):
2589 def debugnamecomplete(ui, repo, *args):
2590 '''complete "names" - tags, open branch names, bookmark names'''
2590 '''complete "names" - tags, open branch names, bookmark names'''
2591
2591
2592 names = set()
2592 names = set()
2593 # since we previously only listed open branches, we will handle that
2593 # since we previously only listed open branches, we will handle that
2594 # specially (after this for loop)
2594 # specially (after this for loop)
2595 for name, ns in repo.names.iteritems():
2595 for name, ns in repo.names.iteritems():
2596 if name != 'branches':
2596 if name != 'branches':
2597 names.update(ns.listnames(repo))
2597 names.update(ns.listnames(repo))
2598 names.update(tag for (tag, heads, tip, closed)
2598 names.update(tag for (tag, heads, tip, closed)
2599 in repo.branchmap().iterbranches() if not closed)
2599 in repo.branchmap().iterbranches() if not closed)
2600 completions = set()
2600 completions = set()
2601 if not args:
2601 if not args:
2602 args = ['']
2602 args = ['']
2603 for a in args:
2603 for a in args:
2604 completions.update(n for n in names if n.startswith(a))
2604 completions.update(n for n in names if n.startswith(a))
2605 ui.write('\n'.join(sorted(completions)))
2605 ui.write('\n'.join(sorted(completions)))
2606 ui.write('\n')
2606 ui.write('\n')
2607
2607
2608 @command('debuglocks',
2608 @command('debuglocks',
2609 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2609 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2610 ('W', 'force-wlock', None,
2610 ('W', 'force-wlock', None,
2611 _('free the working state lock (DANGEROUS)'))],
2611 _('free the working state lock (DANGEROUS)'))],
2612 _('[OPTION]...'))
2612 _('[OPTION]...'))
2613 def debuglocks(ui, repo, **opts):
2613 def debuglocks(ui, repo, **opts):
2614 """show or modify state of locks
2614 """show or modify state of locks
2615
2615
2616 By default, this command will show which locks are held. This
2616 By default, this command will show which locks are held. This
2617 includes the user and process holding the lock, the amount of time
2617 includes the user and process holding the lock, the amount of time
2618 the lock has been held, and the machine name where the process is
2618 the lock has been held, and the machine name where the process is
2619 running if it's not local.
2619 running if it's not local.
2620
2620
2621 Locks protect the integrity of Mercurial's data, so should be
2621 Locks protect the integrity of Mercurial's data, so should be
2622 treated with care. System crashes or other interruptions may cause
2622 treated with care. System crashes or other interruptions may cause
2623 locks to not be properly released, though Mercurial will usually
2623 locks to not be properly released, though Mercurial will usually
2624 detect and remove such stale locks automatically.
2624 detect and remove such stale locks automatically.
2625
2625
2626 However, detecting stale locks may not always be possible (for
2626 However, detecting stale locks may not always be possible (for
2627 instance, on a shared filesystem). Removing locks may also be
2627 instance, on a shared filesystem). Removing locks may also be
2628 blocked by filesystem permissions.
2628 blocked by filesystem permissions.
2629
2629
2630 Returns 0 if no locks are held.
2630 Returns 0 if no locks are held.
2631
2631
2632 """
2632 """
2633
2633
2634 if opts.get('force_lock'):
2634 if opts.get('force_lock'):
2635 repo.svfs.unlink('lock')
2635 repo.svfs.unlink('lock')
2636 if opts.get('force_wlock'):
2636 if opts.get('force_wlock'):
2637 repo.vfs.unlink('wlock')
2637 repo.vfs.unlink('wlock')
2638 if opts.get('force_lock') or opts.get('force_lock'):
2638 if opts.get('force_lock') or opts.get('force_lock'):
2639 return 0
2639 return 0
2640
2640
2641 now = time.time()
2641 now = time.time()
2642 held = 0
2642 held = 0
2643
2643
2644 def report(vfs, name, method):
2644 def report(vfs, name, method):
2645 # this causes stale locks to get reaped for more accurate reporting
2645 # this causes stale locks to get reaped for more accurate reporting
2646 try:
2646 try:
2647 l = method(False)
2647 l = method(False)
2648 except error.LockHeld:
2648 except error.LockHeld:
2649 l = None
2649 l = None
2650
2650
2651 if l:
2651 if l:
2652 l.release()
2652 l.release()
2653 else:
2653 else:
2654 try:
2654 try:
2655 stat = vfs.lstat(name)
2655 stat = vfs.lstat(name)
2656 age = now - stat.st_mtime
2656 age = now - stat.st_mtime
2657 user = util.username(stat.st_uid)
2657 user = util.username(stat.st_uid)
2658 locker = vfs.readlock(name)
2658 locker = vfs.readlock(name)
2659 if ":" in locker:
2659 if ":" in locker:
2660 host, pid = locker.split(':')
2660 host, pid = locker.split(':')
2661 if host == socket.gethostname():
2661 if host == socket.gethostname():
2662 locker = 'user %s, process %s' % (user, pid)
2662 locker = 'user %s, process %s' % (user, pid)
2663 else:
2663 else:
2664 locker = 'user %s, process %s, host %s' \
2664 locker = 'user %s, process %s, host %s' \
2665 % (user, pid, host)
2665 % (user, pid, host)
2666 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2666 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2667 return 1
2667 return 1
2668 except OSError as e:
2668 except OSError as e:
2669 if e.errno != errno.ENOENT:
2669 if e.errno != errno.ENOENT:
2670 raise
2670 raise
2671
2671
2672 ui.write("%-6s free\n" % (name + ":"))
2672 ui.write("%-6s free\n" % (name + ":"))
2673 return 0
2673 return 0
2674
2674
2675 held += report(repo.svfs, "lock", repo.lock)
2675 held += report(repo.svfs, "lock", repo.lock)
2676 held += report(repo.vfs, "wlock", repo.wlock)
2676 held += report(repo.vfs, "wlock", repo.wlock)
2677
2677
2678 return held
2678 return held
2679
2679
2680 @command('debugobsolete',
2680 @command('debugobsolete',
2681 [('', 'flags', 0, _('markers flag')),
2681 [('', 'flags', 0, _('markers flag')),
2682 ('', 'record-parents', False,
2682 ('', 'record-parents', False,
2683 _('record parent information for the precursor')),
2683 _('record parent information for the precursor')),
2684 ('r', 'rev', [], _('display markers relevant to REV')),
2684 ('r', 'rev', [], _('display markers relevant to REV')),
2685 ] + commitopts2,
2685 ] + commitopts2,
2686 _('[OBSOLETED [REPLACEMENT ...]]'))
2686 _('[OBSOLETED [REPLACEMENT ...]]'))
2687 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2687 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2688 """create arbitrary obsolete marker
2688 """create arbitrary obsolete marker
2689
2689
2690 With no arguments, displays the list of obsolescence markers."""
2690 With no arguments, displays the list of obsolescence markers."""
2691
2691
2692 def parsenodeid(s):
2692 def parsenodeid(s):
2693 try:
2693 try:
2694 # We do not use revsingle/revrange functions here to accept
2694 # We do not use revsingle/revrange functions here to accept
2695 # arbitrary node identifiers, possibly not present in the
2695 # arbitrary node identifiers, possibly not present in the
2696 # local repository.
2696 # local repository.
2697 n = bin(s)
2697 n = bin(s)
2698 if len(n) != len(nullid):
2698 if len(n) != len(nullid):
2699 raise TypeError()
2699 raise TypeError()
2700 return n
2700 return n
2701 except TypeError:
2701 except TypeError:
2702 raise error.Abort('changeset references must be full hexadecimal '
2702 raise error.Abort('changeset references must be full hexadecimal '
2703 'node identifiers')
2703 'node identifiers')
2704
2704
2705 if precursor is not None:
2705 if precursor is not None:
2706 if opts['rev']:
2706 if opts['rev']:
2707 raise error.Abort('cannot select revision when creating marker')
2707 raise error.Abort('cannot select revision when creating marker')
2708 metadata = {}
2708 metadata = {}
2709 metadata['user'] = opts['user'] or ui.username()
2709 metadata['user'] = opts['user'] or ui.username()
2710 succs = tuple(parsenodeid(succ) for succ in successors)
2710 succs = tuple(parsenodeid(succ) for succ in successors)
2711 l = repo.lock()
2711 l = repo.lock()
2712 try:
2712 try:
2713 tr = repo.transaction('debugobsolete')
2713 tr = repo.transaction('debugobsolete')
2714 try:
2714 try:
2715 date = opts.get('date')
2715 date = opts.get('date')
2716 if date:
2716 if date:
2717 date = util.parsedate(date)
2717 date = util.parsedate(date)
2718 else:
2718 else:
2719 date = None
2719 date = None
2720 prec = parsenodeid(precursor)
2720 prec = parsenodeid(precursor)
2721 parents = None
2721 parents = None
2722 if opts['record_parents']:
2722 if opts['record_parents']:
2723 if prec not in repo.unfiltered():
2723 if prec not in repo.unfiltered():
2724 raise error.Abort('cannot used --record-parents on '
2724 raise error.Abort('cannot used --record-parents on '
2725 'unknown changesets')
2725 'unknown changesets')
2726 parents = repo.unfiltered()[prec].parents()
2726 parents = repo.unfiltered()[prec].parents()
2727 parents = tuple(p.node() for p in parents)
2727 parents = tuple(p.node() for p in parents)
2728 repo.obsstore.create(tr, prec, succs, opts['flags'],
2728 repo.obsstore.create(tr, prec, succs, opts['flags'],
2729 parents=parents, date=date,
2729 parents=parents, date=date,
2730 metadata=metadata)
2730 metadata=metadata)
2731 tr.close()
2731 tr.close()
2732 except ValueError as exc:
2732 except ValueError as exc:
2733 raise error.Abort(_('bad obsmarker input: %s') % exc)
2733 raise error.Abort(_('bad obsmarker input: %s') % exc)
2734 finally:
2734 finally:
2735 tr.release()
2735 tr.release()
2736 finally:
2736 finally:
2737 l.release()
2737 l.release()
2738 else:
2738 else:
2739 if opts['rev']:
2739 if opts['rev']:
2740 revs = scmutil.revrange(repo, opts['rev'])
2740 revs = scmutil.revrange(repo, opts['rev'])
2741 nodes = [repo[r].node() for r in revs]
2741 nodes = [repo[r].node() for r in revs]
2742 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2742 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2743 markers.sort(key=lambda x: x._data)
2743 markers.sort(key=lambda x: x._data)
2744 else:
2744 else:
2745 markers = obsolete.getmarkers(repo)
2745 markers = obsolete.getmarkers(repo)
2746
2746
2747 for m in markers:
2747 for m in markers:
2748 cmdutil.showmarker(ui, m)
2748 cmdutil.showmarker(ui, m)
2749
2749
2750 @command('debugpathcomplete',
2750 @command('debugpathcomplete',
2751 [('f', 'full', None, _('complete an entire path')),
2751 [('f', 'full', None, _('complete an entire path')),
2752 ('n', 'normal', None, _('show only normal files')),
2752 ('n', 'normal', None, _('show only normal files')),
2753 ('a', 'added', None, _('show only added files')),
2753 ('a', 'added', None, _('show only added files')),
2754 ('r', 'removed', None, _('show only removed files'))],
2754 ('r', 'removed', None, _('show only removed files'))],
2755 _('FILESPEC...'))
2755 _('FILESPEC...'))
2756 def debugpathcomplete(ui, repo, *specs, **opts):
2756 def debugpathcomplete(ui, repo, *specs, **opts):
2757 '''complete part or all of a tracked path
2757 '''complete part or all of a tracked path
2758
2758
2759 This command supports shells that offer path name completion. It
2759 This command supports shells that offer path name completion. It
2760 currently completes only files already known to the dirstate.
2760 currently completes only files already known to the dirstate.
2761
2761
2762 Completion extends only to the next path segment unless
2762 Completion extends only to the next path segment unless
2763 --full is specified, in which case entire paths are used.'''
2763 --full is specified, in which case entire paths are used.'''
2764
2764
2765 def complete(path, acceptable):
2765 def complete(path, acceptable):
2766 dirstate = repo.dirstate
2766 dirstate = repo.dirstate
2767 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2767 spec = os.path.normpath(os.path.join(os.getcwd(), path))
2768 rootdir = repo.root + os.sep
2768 rootdir = repo.root + os.sep
2769 if spec != repo.root and not spec.startswith(rootdir):
2769 if spec != repo.root and not spec.startswith(rootdir):
2770 return [], []
2770 return [], []
2771 if os.path.isdir(spec):
2771 if os.path.isdir(spec):
2772 spec += '/'
2772 spec += '/'
2773 spec = spec[len(rootdir):]
2773 spec = spec[len(rootdir):]
2774 fixpaths = os.sep != '/'
2774 fixpaths = os.sep != '/'
2775 if fixpaths:
2775 if fixpaths:
2776 spec = spec.replace(os.sep, '/')
2776 spec = spec.replace(os.sep, '/')
2777 speclen = len(spec)
2777 speclen = len(spec)
2778 fullpaths = opts['full']
2778 fullpaths = opts['full']
2779 files, dirs = set(), set()
2779 files, dirs = set(), set()
2780 adddir, addfile = dirs.add, files.add
2780 adddir, addfile = dirs.add, files.add
2781 for f, st in dirstate.iteritems():
2781 for f, st in dirstate.iteritems():
2782 if f.startswith(spec) and st[0] in acceptable:
2782 if f.startswith(spec) and st[0] in acceptable:
2783 if fixpaths:
2783 if fixpaths:
2784 f = f.replace('/', os.sep)
2784 f = f.replace('/', os.sep)
2785 if fullpaths:
2785 if fullpaths:
2786 addfile(f)
2786 addfile(f)
2787 continue
2787 continue
2788 s = f.find(os.sep, speclen)
2788 s = f.find(os.sep, speclen)
2789 if s >= 0:
2789 if s >= 0:
2790 adddir(f[:s])
2790 adddir(f[:s])
2791 else:
2791 else:
2792 addfile(f)
2792 addfile(f)
2793 return files, dirs
2793 return files, dirs
2794
2794
2795 acceptable = ''
2795 acceptable = ''
2796 if opts['normal']:
2796 if opts['normal']:
2797 acceptable += 'nm'
2797 acceptable += 'nm'
2798 if opts['added']:
2798 if opts['added']:
2799 acceptable += 'a'
2799 acceptable += 'a'
2800 if opts['removed']:
2800 if opts['removed']:
2801 acceptable += 'r'
2801 acceptable += 'r'
2802 cwd = repo.getcwd()
2802 cwd = repo.getcwd()
2803 if not specs:
2803 if not specs:
2804 specs = ['.']
2804 specs = ['.']
2805
2805
2806 files, dirs = set(), set()
2806 files, dirs = set(), set()
2807 for spec in specs:
2807 for spec in specs:
2808 f, d = complete(spec, acceptable or 'nmar')
2808 f, d = complete(spec, acceptable or 'nmar')
2809 files.update(f)
2809 files.update(f)
2810 dirs.update(d)
2810 dirs.update(d)
2811 files.update(dirs)
2811 files.update(dirs)
2812 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2812 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
2813 ui.write('\n')
2813 ui.write('\n')
2814
2814
2815 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2815 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
2816 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2816 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
2817 '''access the pushkey key/value protocol
2817 '''access the pushkey key/value protocol
2818
2818
2819 With two args, list the keys in the given namespace.
2819 With two args, list the keys in the given namespace.
2820
2820
2821 With five args, set a key to new if it currently is set to old.
2821 With five args, set a key to new if it currently is set to old.
2822 Reports success or failure.
2822 Reports success or failure.
2823 '''
2823 '''
2824
2824
2825 target = hg.peer(ui, {}, repopath)
2825 target = hg.peer(ui, {}, repopath)
2826 if keyinfo:
2826 if keyinfo:
2827 key, old, new = keyinfo
2827 key, old, new = keyinfo
2828 r = target.pushkey(namespace, key, old, new)
2828 r = target.pushkey(namespace, key, old, new)
2829 ui.status(str(r) + '\n')
2829 ui.status(str(r) + '\n')
2830 return not r
2830 return not r
2831 else:
2831 else:
2832 for k, v in sorted(target.listkeys(namespace).iteritems()):
2832 for k, v in sorted(target.listkeys(namespace).iteritems()):
2833 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2833 ui.write("%s\t%s\n" % (k.encode('string-escape'),
2834 v.encode('string-escape')))
2834 v.encode('string-escape')))
2835
2835
2836 @command('debugpvec', [], _('A B'))
2836 @command('debugpvec', [], _('A B'))
2837 def debugpvec(ui, repo, a, b=None):
2837 def debugpvec(ui, repo, a, b=None):
2838 ca = scmutil.revsingle(repo, a)
2838 ca = scmutil.revsingle(repo, a)
2839 cb = scmutil.revsingle(repo, b)
2839 cb = scmutil.revsingle(repo, b)
2840 pa = pvec.ctxpvec(ca)
2840 pa = pvec.ctxpvec(ca)
2841 pb = pvec.ctxpvec(cb)
2841 pb = pvec.ctxpvec(cb)
2842 if pa == pb:
2842 if pa == pb:
2843 rel = "="
2843 rel = "="
2844 elif pa > pb:
2844 elif pa > pb:
2845 rel = ">"
2845 rel = ">"
2846 elif pa < pb:
2846 elif pa < pb:
2847 rel = "<"
2847 rel = "<"
2848 elif pa | pb:
2848 elif pa | pb:
2849 rel = "|"
2849 rel = "|"
2850 ui.write(_("a: %s\n") % pa)
2850 ui.write(_("a: %s\n") % pa)
2851 ui.write(_("b: %s\n") % pb)
2851 ui.write(_("b: %s\n") % pb)
2852 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2852 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
2853 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2853 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
2854 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2854 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
2855 pa.distance(pb), rel))
2855 pa.distance(pb), rel))
2856
2856
2857 @command('debugrebuilddirstate|debugrebuildstate',
2857 @command('debugrebuilddirstate|debugrebuildstate',
2858 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
2858 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
2859 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
2859 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
2860 'the working copy parent')),
2860 'the working copy parent')),
2861 ],
2861 ],
2862 _('[-r REV]'))
2862 _('[-r REV]'))
2863 def debugrebuilddirstate(ui, repo, rev, **opts):
2863 def debugrebuilddirstate(ui, repo, rev, **opts):
2864 """rebuild the dirstate as it would look like for the given revision
2864 """rebuild the dirstate as it would look like for the given revision
2865
2865
2866 If no revision is specified the first current parent will be used.
2866 If no revision is specified the first current parent will be used.
2867
2867
2868 The dirstate will be set to the files of the given revision.
2868 The dirstate will be set to the files of the given revision.
2869 The actual working directory content or existing dirstate
2869 The actual working directory content or existing dirstate
2870 information such as adds or removes is not considered.
2870 information such as adds or removes is not considered.
2871
2871
2872 ``minimal`` will only rebuild the dirstate status for files that claim to be
2872 ``minimal`` will only rebuild the dirstate status for files that claim to be
2873 tracked but are not in the parent manifest, or that exist in the parent
2873 tracked but are not in the parent manifest, or that exist in the parent
2874 manifest but are not in the dirstate. It will not change adds, removes, or
2874 manifest but are not in the dirstate. It will not change adds, removes, or
2875 modified files that are in the working copy parent.
2875 modified files that are in the working copy parent.
2876
2876
2877 One use of this command is to make the next :hg:`status` invocation
2877 One use of this command is to make the next :hg:`status` invocation
2878 check the actual file content.
2878 check the actual file content.
2879 """
2879 """
2880 ctx = scmutil.revsingle(repo, rev)
2880 ctx = scmutil.revsingle(repo, rev)
2881 wlock = repo.wlock()
2881 wlock = repo.wlock()
2882 try:
2882 try:
2883 dirstate = repo.dirstate
2883 dirstate = repo.dirstate
2884
2884
2885 # See command doc for what minimal does.
2885 # See command doc for what minimal does.
2886 if opts.get('minimal'):
2886 if opts.get('minimal'):
2887 dirstatefiles = set(dirstate)
2887 dirstatefiles = set(dirstate)
2888 ctxfiles = set(ctx.manifest().keys())
2888 ctxfiles = set(ctx.manifest().keys())
2889 for file in (dirstatefiles | ctxfiles):
2889 for file in (dirstatefiles | ctxfiles):
2890 indirstate = file in dirstatefiles
2890 indirstate = file in dirstatefiles
2891 inctx = file in ctxfiles
2891 inctx = file in ctxfiles
2892
2892
2893 if indirstate and not inctx and dirstate[file] != 'a':
2893 if indirstate and not inctx and dirstate[file] != 'a':
2894 dirstate.drop(file)
2894 dirstate.drop(file)
2895 elif inctx and not indirstate:
2895 elif inctx and not indirstate:
2896 dirstate.normallookup(file)
2896 dirstate.normallookup(file)
2897 else:
2897 else:
2898 dirstate.rebuild(ctx.node(), ctx.manifest())
2898 dirstate.rebuild(ctx.node(), ctx.manifest())
2899 finally:
2899 finally:
2900 wlock.release()
2900 wlock.release()
2901
2901
2902 @command('debugrebuildfncache', [], '')
2902 @command('debugrebuildfncache', [], '')
2903 def debugrebuildfncache(ui, repo):
2903 def debugrebuildfncache(ui, repo):
2904 """rebuild the fncache file"""
2904 """rebuild the fncache file"""
2905 repair.rebuildfncache(ui, repo)
2905 repair.rebuildfncache(ui, repo)
2906
2906
2907 @command('debugrename',
2907 @command('debugrename',
2908 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2908 [('r', 'rev', '', _('revision to debug'), _('REV'))],
2909 _('[-r REV] FILE'))
2909 _('[-r REV] FILE'))
2910 def debugrename(ui, repo, file1, *pats, **opts):
2910 def debugrename(ui, repo, file1, *pats, **opts):
2911 """dump rename information"""
2911 """dump rename information"""
2912
2912
2913 ctx = scmutil.revsingle(repo, opts.get('rev'))
2913 ctx = scmutil.revsingle(repo, opts.get('rev'))
2914 m = scmutil.match(ctx, (file1,) + pats, opts)
2914 m = scmutil.match(ctx, (file1,) + pats, opts)
2915 for abs in ctx.walk(m):
2915 for abs in ctx.walk(m):
2916 fctx = ctx[abs]
2916 fctx = ctx[abs]
2917 o = fctx.filelog().renamed(fctx.filenode())
2917 o = fctx.filelog().renamed(fctx.filenode())
2918 rel = m.rel(abs)
2918 rel = m.rel(abs)
2919 if o:
2919 if o:
2920 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2920 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
2921 else:
2921 else:
2922 ui.write(_("%s not renamed\n") % rel)
2922 ui.write(_("%s not renamed\n") % rel)
2923
2923
2924 @command('debugrevlog',
2924 @command('debugrevlog',
2925 [('c', 'changelog', False, _('open changelog')),
2925 [('c', 'changelog', False, _('open changelog')),
2926 ('m', 'manifest', False, _('open manifest')),
2926 ('m', 'manifest', False, _('open manifest')),
2927 ('', 'dir', False, _('open directory manifest')),
2927 ('', 'dir', False, _('open directory manifest')),
2928 ('d', 'dump', False, _('dump index data'))],
2928 ('d', 'dump', False, _('dump index data'))],
2929 _('-c|-m|FILE'),
2929 _('-c|-m|FILE'),
2930 optionalrepo=True)
2930 optionalrepo=True)
2931 def debugrevlog(ui, repo, file_=None, **opts):
2931 def debugrevlog(ui, repo, file_=None, **opts):
2932 """show data and statistics about a revlog"""
2932 """show data and statistics about a revlog"""
2933 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2933 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
2934
2934
2935 if opts.get("dump"):
2935 if opts.get("dump"):
2936 numrevs = len(r)
2936 numrevs = len(r)
2937 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2937 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
2938 " rawsize totalsize compression heads chainlen\n")
2938 " rawsize totalsize compression heads chainlen\n")
2939 ts = 0
2939 ts = 0
2940 heads = set()
2940 heads = set()
2941
2941
2942 for rev in xrange(numrevs):
2942 for rev in xrange(numrevs):
2943 dbase = r.deltaparent(rev)
2943 dbase = r.deltaparent(rev)
2944 if dbase == -1:
2944 if dbase == -1:
2945 dbase = rev
2945 dbase = rev
2946 cbase = r.chainbase(rev)
2946 cbase = r.chainbase(rev)
2947 clen = r.chainlen(rev)
2947 clen = r.chainlen(rev)
2948 p1, p2 = r.parentrevs(rev)
2948 p1, p2 = r.parentrevs(rev)
2949 rs = r.rawsize(rev)
2949 rs = r.rawsize(rev)
2950 ts = ts + rs
2950 ts = ts + rs
2951 heads -= set(r.parentrevs(rev))
2951 heads -= set(r.parentrevs(rev))
2952 heads.add(rev)
2952 heads.add(rev)
2953 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2953 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
2954 "%11d %5d %8d\n" %
2954 "%11d %5d %8d\n" %
2955 (rev, p1, p2, r.start(rev), r.end(rev),
2955 (rev, p1, p2, r.start(rev), r.end(rev),
2956 r.start(dbase), r.start(cbase),
2956 r.start(dbase), r.start(cbase),
2957 r.start(p1), r.start(p2),
2957 r.start(p1), r.start(p2),
2958 rs, ts, ts / r.end(rev), len(heads), clen))
2958 rs, ts, ts / r.end(rev), len(heads), clen))
2959 return 0
2959 return 0
2960
2960
2961 v = r.version
2961 v = r.version
2962 format = v & 0xFFFF
2962 format = v & 0xFFFF
2963 flags = []
2963 flags = []
2964 gdelta = False
2964 gdelta = False
2965 if v & revlog.REVLOGNGINLINEDATA:
2965 if v & revlog.REVLOGNGINLINEDATA:
2966 flags.append('inline')
2966 flags.append('inline')
2967 if v & revlog.REVLOGGENERALDELTA:
2967 if v & revlog.REVLOGGENERALDELTA:
2968 gdelta = True
2968 gdelta = True
2969 flags.append('generaldelta')
2969 flags.append('generaldelta')
2970 if not flags:
2970 if not flags:
2971 flags = ['(none)']
2971 flags = ['(none)']
2972
2972
2973 nummerges = 0
2973 nummerges = 0
2974 numfull = 0
2974 numfull = 0
2975 numprev = 0
2975 numprev = 0
2976 nump1 = 0
2976 nump1 = 0
2977 nump2 = 0
2977 nump2 = 0
2978 numother = 0
2978 numother = 0
2979 nump1prev = 0
2979 nump1prev = 0
2980 nump2prev = 0
2980 nump2prev = 0
2981 chainlengths = []
2981 chainlengths = []
2982
2982
2983 datasize = [None, 0, 0L]
2983 datasize = [None, 0, 0L]
2984 fullsize = [None, 0, 0L]
2984 fullsize = [None, 0, 0L]
2985 deltasize = [None, 0, 0L]
2985 deltasize = [None, 0, 0L]
2986
2986
2987 def addsize(size, l):
2987 def addsize(size, l):
2988 if l[0] is None or size < l[0]:
2988 if l[0] is None or size < l[0]:
2989 l[0] = size
2989 l[0] = size
2990 if size > l[1]:
2990 if size > l[1]:
2991 l[1] = size
2991 l[1] = size
2992 l[2] += size
2992 l[2] += size
2993
2993
2994 numrevs = len(r)
2994 numrevs = len(r)
2995 for rev in xrange(numrevs):
2995 for rev in xrange(numrevs):
2996 p1, p2 = r.parentrevs(rev)
2996 p1, p2 = r.parentrevs(rev)
2997 delta = r.deltaparent(rev)
2997 delta = r.deltaparent(rev)
2998 if format > 0:
2998 if format > 0:
2999 addsize(r.rawsize(rev), datasize)
2999 addsize(r.rawsize(rev), datasize)
3000 if p2 != nullrev:
3000 if p2 != nullrev:
3001 nummerges += 1
3001 nummerges += 1
3002 size = r.length(rev)
3002 size = r.length(rev)
3003 if delta == nullrev:
3003 if delta == nullrev:
3004 chainlengths.append(0)
3004 chainlengths.append(0)
3005 numfull += 1
3005 numfull += 1
3006 addsize(size, fullsize)
3006 addsize(size, fullsize)
3007 else:
3007 else:
3008 chainlengths.append(chainlengths[delta] + 1)
3008 chainlengths.append(chainlengths[delta] + 1)
3009 addsize(size, deltasize)
3009 addsize(size, deltasize)
3010 if delta == rev - 1:
3010 if delta == rev - 1:
3011 numprev += 1
3011 numprev += 1
3012 if delta == p1:
3012 if delta == p1:
3013 nump1prev += 1
3013 nump1prev += 1
3014 elif delta == p2:
3014 elif delta == p2:
3015 nump2prev += 1
3015 nump2prev += 1
3016 elif delta == p1:
3016 elif delta == p1:
3017 nump1 += 1
3017 nump1 += 1
3018 elif delta == p2:
3018 elif delta == p2:
3019 nump2 += 1
3019 nump2 += 1
3020 elif delta != nullrev:
3020 elif delta != nullrev:
3021 numother += 1
3021 numother += 1
3022
3022
3023 # Adjust size min value for empty cases
3023 # Adjust size min value for empty cases
3024 for size in (datasize, fullsize, deltasize):
3024 for size in (datasize, fullsize, deltasize):
3025 if size[0] is None:
3025 if size[0] is None:
3026 size[0] = 0
3026 size[0] = 0
3027
3027
3028 numdeltas = numrevs - numfull
3028 numdeltas = numrevs - numfull
3029 numoprev = numprev - nump1prev - nump2prev
3029 numoprev = numprev - nump1prev - nump2prev
3030 totalrawsize = datasize[2]
3030 totalrawsize = datasize[2]
3031 datasize[2] /= numrevs
3031 datasize[2] /= numrevs
3032 fulltotal = fullsize[2]
3032 fulltotal = fullsize[2]
3033 fullsize[2] /= numfull
3033 fullsize[2] /= numfull
3034 deltatotal = deltasize[2]
3034 deltatotal = deltasize[2]
3035 if numrevs - numfull > 0:
3035 if numrevs - numfull > 0:
3036 deltasize[2] /= numrevs - numfull
3036 deltasize[2] /= numrevs - numfull
3037 totalsize = fulltotal + deltatotal
3037 totalsize = fulltotal + deltatotal
3038 avgchainlen = sum(chainlengths) / numrevs
3038 avgchainlen = sum(chainlengths) / numrevs
3039 maxchainlen = max(chainlengths)
3039 maxchainlen = max(chainlengths)
3040 compratio = totalrawsize / totalsize
3040 compratio = 1
3041 if totalsize:
3042 compratio = totalrawsize / totalsize
3041
3043
3042 basedfmtstr = '%%%dd\n'
3044 basedfmtstr = '%%%dd\n'
3043 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3045 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3044
3046
3045 def dfmtstr(max):
3047 def dfmtstr(max):
3046 return basedfmtstr % len(str(max))
3048 return basedfmtstr % len(str(max))
3047 def pcfmtstr(max, padding=0):
3049 def pcfmtstr(max, padding=0):
3048 return basepcfmtstr % (len(str(max)), ' ' * padding)
3050 return basepcfmtstr % (len(str(max)), ' ' * padding)
3049
3051
3050 def pcfmt(value, total):
3052 def pcfmt(value, total):
3051 return (value, 100 * float(value) / total)
3053 if total:
3054 return (value, 100 * float(value) / total)
3055 else:
3056 return value, 100.0
3052
3057
3053 ui.write(('format : %d\n') % format)
3058 ui.write(('format : %d\n') % format)
3054 ui.write(('flags : %s\n') % ', '.join(flags))
3059 ui.write(('flags : %s\n') % ', '.join(flags))
3055
3060
3056 ui.write('\n')
3061 ui.write('\n')
3057 fmt = pcfmtstr(totalsize)
3062 fmt = pcfmtstr(totalsize)
3058 fmt2 = dfmtstr(totalsize)
3063 fmt2 = dfmtstr(totalsize)
3059 ui.write(('revisions : ') + fmt2 % numrevs)
3064 ui.write(('revisions : ') + fmt2 % numrevs)
3060 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3065 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3061 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3066 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3062 ui.write(('revisions : ') + fmt2 % numrevs)
3067 ui.write(('revisions : ') + fmt2 % numrevs)
3063 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3068 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3064 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3069 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3065 ui.write(('revision size : ') + fmt2 % totalsize)
3070 ui.write(('revision size : ') + fmt2 % totalsize)
3066 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3071 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3067 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3072 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3068
3073
3069 ui.write('\n')
3074 ui.write('\n')
3070 fmt = dfmtstr(max(avgchainlen, compratio))
3075 fmt = dfmtstr(max(avgchainlen, compratio))
3071 ui.write(('avg chain length : ') + fmt % avgchainlen)
3076 ui.write(('avg chain length : ') + fmt % avgchainlen)
3072 ui.write(('max chain length : ') + fmt % maxchainlen)
3077 ui.write(('max chain length : ') + fmt % maxchainlen)
3073 ui.write(('compression ratio : ') + fmt % compratio)
3078 ui.write(('compression ratio : ') + fmt % compratio)
3074
3079
3075 if format > 0:
3080 if format > 0:
3076 ui.write('\n')
3081 ui.write('\n')
3077 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3082 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3078 % tuple(datasize))
3083 % tuple(datasize))
3079 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3084 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3080 % tuple(fullsize))
3085 % tuple(fullsize))
3081 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3086 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3082 % tuple(deltasize))
3087 % tuple(deltasize))
3083
3088
3084 if numdeltas > 0:
3089 if numdeltas > 0:
3085 ui.write('\n')
3090 ui.write('\n')
3086 fmt = pcfmtstr(numdeltas)
3091 fmt = pcfmtstr(numdeltas)
3087 fmt2 = pcfmtstr(numdeltas, 4)
3092 fmt2 = pcfmtstr(numdeltas, 4)
3088 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3093 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3089 if numprev > 0:
3094 if numprev > 0:
3090 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3095 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3091 numprev))
3096 numprev))
3092 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3097 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3093 numprev))
3098 numprev))
3094 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3099 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3095 numprev))
3100 numprev))
3096 if gdelta:
3101 if gdelta:
3097 ui.write(('deltas against p1 : ')
3102 ui.write(('deltas against p1 : ')
3098 + fmt % pcfmt(nump1, numdeltas))
3103 + fmt % pcfmt(nump1, numdeltas))
3099 ui.write(('deltas against p2 : ')
3104 ui.write(('deltas against p2 : ')
3100 + fmt % pcfmt(nump2, numdeltas))
3105 + fmt % pcfmt(nump2, numdeltas))
3101 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3106 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3102 numdeltas))
3107 numdeltas))
3103
3108
3104 @command('debugrevspec',
3109 @command('debugrevspec',
3105 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3110 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3106 ('REVSPEC'))
3111 ('REVSPEC'))
3107 def debugrevspec(ui, repo, expr, **opts):
3112 def debugrevspec(ui, repo, expr, **opts):
3108 """parse and apply a revision specification
3113 """parse and apply a revision specification
3109
3114
3110 Use --verbose to print the parsed tree before and after aliases
3115 Use --verbose to print the parsed tree before and after aliases
3111 expansion.
3116 expansion.
3112 """
3117 """
3113 if ui.verbose:
3118 if ui.verbose:
3114 tree = revset.parse(expr, lookup=repo.__contains__)
3119 tree = revset.parse(expr, lookup=repo.__contains__)
3115 ui.note(revset.prettyformat(tree), "\n")
3120 ui.note(revset.prettyformat(tree), "\n")
3116 newtree = revset.findaliases(ui, tree)
3121 newtree = revset.findaliases(ui, tree)
3117 if newtree != tree:
3122 if newtree != tree:
3118 ui.note(revset.prettyformat(newtree), "\n")
3123 ui.note(revset.prettyformat(newtree), "\n")
3119 tree = newtree
3124 tree = newtree
3120 newtree = revset.foldconcat(tree)
3125 newtree = revset.foldconcat(tree)
3121 if newtree != tree:
3126 if newtree != tree:
3122 ui.note(revset.prettyformat(newtree), "\n")
3127 ui.note(revset.prettyformat(newtree), "\n")
3123 if opts["optimize"]:
3128 if opts["optimize"]:
3124 weight, optimizedtree = revset.optimize(newtree, True)
3129 weight, optimizedtree = revset.optimize(newtree, True)
3125 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3130 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3126 func = revset.match(ui, expr, repo)
3131 func = revset.match(ui, expr, repo)
3127 revs = func(repo)
3132 revs = func(repo)
3128 if ui.verbose:
3133 if ui.verbose:
3129 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3134 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3130 for c in revs:
3135 for c in revs:
3131 ui.write("%s\n" % c)
3136 ui.write("%s\n" % c)
3132
3137
3133 @command('debugsetparents', [], _('REV1 [REV2]'))
3138 @command('debugsetparents', [], _('REV1 [REV2]'))
3134 def debugsetparents(ui, repo, rev1, rev2=None):
3139 def debugsetparents(ui, repo, rev1, rev2=None):
3135 """manually set the parents of the current working directory
3140 """manually set the parents of the current working directory
3136
3141
3137 This is useful for writing repository conversion tools, but should
3142 This is useful for writing repository conversion tools, but should
3138 be used with care. For example, neither the working directory nor the
3143 be used with care. For example, neither the working directory nor the
3139 dirstate is updated, so file status may be incorrect after running this
3144 dirstate is updated, so file status may be incorrect after running this
3140 command.
3145 command.
3141
3146
3142 Returns 0 on success.
3147 Returns 0 on success.
3143 """
3148 """
3144
3149
3145 r1 = scmutil.revsingle(repo, rev1).node()
3150 r1 = scmutil.revsingle(repo, rev1).node()
3146 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3151 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3147
3152
3148 wlock = repo.wlock()
3153 wlock = repo.wlock()
3149 try:
3154 try:
3150 repo.dirstate.beginparentchange()
3155 repo.dirstate.beginparentchange()
3151 repo.setparents(r1, r2)
3156 repo.setparents(r1, r2)
3152 repo.dirstate.endparentchange()
3157 repo.dirstate.endparentchange()
3153 finally:
3158 finally:
3154 wlock.release()
3159 wlock.release()
3155
3160
3156 @command('debugdirstate|debugstate',
3161 @command('debugdirstate|debugstate',
3157 [('', 'nodates', None, _('do not display the saved mtime')),
3162 [('', 'nodates', None, _('do not display the saved mtime')),
3158 ('', 'datesort', None, _('sort by saved mtime'))],
3163 ('', 'datesort', None, _('sort by saved mtime'))],
3159 _('[OPTION]...'))
3164 _('[OPTION]...'))
3160 def debugstate(ui, repo, nodates=None, datesort=None):
3165 def debugstate(ui, repo, nodates=None, datesort=None):
3161 """show the contents of the current dirstate"""
3166 """show the contents of the current dirstate"""
3162 timestr = ""
3167 timestr = ""
3163 if datesort:
3168 if datesort:
3164 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3169 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3165 else:
3170 else:
3166 keyfunc = None # sort by filename
3171 keyfunc = None # sort by filename
3167 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3172 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3168 if ent[3] == -1:
3173 if ent[3] == -1:
3169 timestr = 'unset '
3174 timestr = 'unset '
3170 elif nodates:
3175 elif nodates:
3171 timestr = 'set '
3176 timestr = 'set '
3172 else:
3177 else:
3173 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3178 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3174 time.localtime(ent[3]))
3179 time.localtime(ent[3]))
3175 if ent[1] & 0o20000:
3180 if ent[1] & 0o20000:
3176 mode = 'lnk'
3181 mode = 'lnk'
3177 else:
3182 else:
3178 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3183 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3179 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3184 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3180 for f in repo.dirstate.copies():
3185 for f in repo.dirstate.copies():
3181 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3186 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3182
3187
3183 @command('debugsub',
3188 @command('debugsub',
3184 [('r', 'rev', '',
3189 [('r', 'rev', '',
3185 _('revision to check'), _('REV'))],
3190 _('revision to check'), _('REV'))],
3186 _('[-r REV] [REV]'))
3191 _('[-r REV] [REV]'))
3187 def debugsub(ui, repo, rev=None):
3192 def debugsub(ui, repo, rev=None):
3188 ctx = scmutil.revsingle(repo, rev, None)
3193 ctx = scmutil.revsingle(repo, rev, None)
3189 for k, v in sorted(ctx.substate.items()):
3194 for k, v in sorted(ctx.substate.items()):
3190 ui.write(('path %s\n') % k)
3195 ui.write(('path %s\n') % k)
3191 ui.write((' source %s\n') % v[0])
3196 ui.write((' source %s\n') % v[0])
3192 ui.write((' revision %s\n') % v[1])
3197 ui.write((' revision %s\n') % v[1])
3193
3198
3194 @command('debugsuccessorssets',
3199 @command('debugsuccessorssets',
3195 [],
3200 [],
3196 _('[REV]'))
3201 _('[REV]'))
3197 def debugsuccessorssets(ui, repo, *revs):
3202 def debugsuccessorssets(ui, repo, *revs):
3198 """show set of successors for revision
3203 """show set of successors for revision
3199
3204
3200 A successors set of changeset A is a consistent group of revisions that
3205 A successors set of changeset A is a consistent group of revisions that
3201 succeed A. It contains non-obsolete changesets only.
3206 succeed A. It contains non-obsolete changesets only.
3202
3207
3203 In most cases a changeset A has a single successors set containing a single
3208 In most cases a changeset A has a single successors set containing a single
3204 successor (changeset A replaced by A').
3209 successor (changeset A replaced by A').
3205
3210
3206 A changeset that is made obsolete with no successors are called "pruned".
3211 A changeset that is made obsolete with no successors are called "pruned".
3207 Such changesets have no successors sets at all.
3212 Such changesets have no successors sets at all.
3208
3213
3209 A changeset that has been "split" will have a successors set containing
3214 A changeset that has been "split" will have a successors set containing
3210 more than one successor.
3215 more than one successor.
3211
3216
3212 A changeset that has been rewritten in multiple different ways is called
3217 A changeset that has been rewritten in multiple different ways is called
3213 "divergent". Such changesets have multiple successor sets (each of which
3218 "divergent". Such changesets have multiple successor sets (each of which
3214 may also be split, i.e. have multiple successors).
3219 may also be split, i.e. have multiple successors).
3215
3220
3216 Results are displayed as follows::
3221 Results are displayed as follows::
3217
3222
3218 <rev1>
3223 <rev1>
3219 <successors-1A>
3224 <successors-1A>
3220 <rev2>
3225 <rev2>
3221 <successors-2A>
3226 <successors-2A>
3222 <successors-2B1> <successors-2B2> <successors-2B3>
3227 <successors-2B1> <successors-2B2> <successors-2B3>
3223
3228
3224 Here rev2 has two possible (i.e. divergent) successors sets. The first
3229 Here rev2 has two possible (i.e. divergent) successors sets. The first
3225 holds one element, whereas the second holds three (i.e. the changeset has
3230 holds one element, whereas the second holds three (i.e. the changeset has
3226 been split).
3231 been split).
3227 """
3232 """
3228 # passed to successorssets caching computation from one call to another
3233 # passed to successorssets caching computation from one call to another
3229 cache = {}
3234 cache = {}
3230 ctx2str = str
3235 ctx2str = str
3231 node2str = short
3236 node2str = short
3232 if ui.debug():
3237 if ui.debug():
3233 def ctx2str(ctx):
3238 def ctx2str(ctx):
3234 return ctx.hex()
3239 return ctx.hex()
3235 node2str = hex
3240 node2str = hex
3236 for rev in scmutil.revrange(repo, revs):
3241 for rev in scmutil.revrange(repo, revs):
3237 ctx = repo[rev]
3242 ctx = repo[rev]
3238 ui.write('%s\n'% ctx2str(ctx))
3243 ui.write('%s\n'% ctx2str(ctx))
3239 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3244 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3240 if succsset:
3245 if succsset:
3241 ui.write(' ')
3246 ui.write(' ')
3242 ui.write(node2str(succsset[0]))
3247 ui.write(node2str(succsset[0]))
3243 for node in succsset[1:]:
3248 for node in succsset[1:]:
3244 ui.write(' ')
3249 ui.write(' ')
3245 ui.write(node2str(node))
3250 ui.write(node2str(node))
3246 ui.write('\n')
3251 ui.write('\n')
3247
3252
3248 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3253 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3249 def debugwalk(ui, repo, *pats, **opts):
3254 def debugwalk(ui, repo, *pats, **opts):
3250 """show how files match on given patterns"""
3255 """show how files match on given patterns"""
3251 m = scmutil.match(repo[None], pats, opts)
3256 m = scmutil.match(repo[None], pats, opts)
3252 items = list(repo.walk(m))
3257 items = list(repo.walk(m))
3253 if not items:
3258 if not items:
3254 return
3259 return
3255 f = lambda fn: fn
3260 f = lambda fn: fn
3256 if ui.configbool('ui', 'slash') and os.sep != '/':
3261 if ui.configbool('ui', 'slash') and os.sep != '/':
3257 f = lambda fn: util.normpath(fn)
3262 f = lambda fn: util.normpath(fn)
3258 fmt = 'f %%-%ds %%-%ds %%s' % (
3263 fmt = 'f %%-%ds %%-%ds %%s' % (
3259 max([len(abs) for abs in items]),
3264 max([len(abs) for abs in items]),
3260 max([len(m.rel(abs)) for abs in items]))
3265 max([len(m.rel(abs)) for abs in items]))
3261 for abs in items:
3266 for abs in items:
3262 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3267 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3263 ui.write("%s\n" % line.rstrip())
3268 ui.write("%s\n" % line.rstrip())
3264
3269
3265 @command('debugwireargs',
3270 @command('debugwireargs',
3266 [('', 'three', '', 'three'),
3271 [('', 'three', '', 'three'),
3267 ('', 'four', '', 'four'),
3272 ('', 'four', '', 'four'),
3268 ('', 'five', '', 'five'),
3273 ('', 'five', '', 'five'),
3269 ] + remoteopts,
3274 ] + remoteopts,
3270 _('REPO [OPTIONS]... [ONE [TWO]]'),
3275 _('REPO [OPTIONS]... [ONE [TWO]]'),
3271 norepo=True)
3276 norepo=True)
3272 def debugwireargs(ui, repopath, *vals, **opts):
3277 def debugwireargs(ui, repopath, *vals, **opts):
3273 repo = hg.peer(ui, opts, repopath)
3278 repo = hg.peer(ui, opts, repopath)
3274 for opt in remoteopts:
3279 for opt in remoteopts:
3275 del opts[opt[1]]
3280 del opts[opt[1]]
3276 args = {}
3281 args = {}
3277 for k, v in opts.iteritems():
3282 for k, v in opts.iteritems():
3278 if v:
3283 if v:
3279 args[k] = v
3284 args[k] = v
3280 # run twice to check that we don't mess up the stream for the next command
3285 # run twice to check that we don't mess up the stream for the next command
3281 res1 = repo.debugwireargs(*vals, **args)
3286 res1 = repo.debugwireargs(*vals, **args)
3282 res2 = repo.debugwireargs(*vals, **args)
3287 res2 = repo.debugwireargs(*vals, **args)
3283 ui.write("%s\n" % res1)
3288 ui.write("%s\n" % res1)
3284 if res1 != res2:
3289 if res1 != res2:
3285 ui.warn("%s\n" % res2)
3290 ui.warn("%s\n" % res2)
3286
3291
3287 @command('^diff',
3292 @command('^diff',
3288 [('r', 'rev', [], _('revision'), _('REV')),
3293 [('r', 'rev', [], _('revision'), _('REV')),
3289 ('c', 'change', '', _('change made by revision'), _('REV'))
3294 ('c', 'change', '', _('change made by revision'), _('REV'))
3290 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3295 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3291 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3296 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3292 inferrepo=True)
3297 inferrepo=True)
3293 def diff(ui, repo, *pats, **opts):
3298 def diff(ui, repo, *pats, **opts):
3294 """diff repository (or selected files)
3299 """diff repository (or selected files)
3295
3300
3296 Show differences between revisions for the specified files.
3301 Show differences between revisions for the specified files.
3297
3302
3298 Differences between files are shown using the unified diff format.
3303 Differences between files are shown using the unified diff format.
3299
3304
3300 .. note::
3305 .. note::
3301
3306
3302 diff may generate unexpected results for merges, as it will
3307 diff may generate unexpected results for merges, as it will
3303 default to comparing against the working directory's first
3308 default to comparing against the working directory's first
3304 parent changeset if no revisions are specified.
3309 parent changeset if no revisions are specified.
3305
3310
3306 When two revision arguments are given, then changes are shown
3311 When two revision arguments are given, then changes are shown
3307 between those revisions. If only one revision is specified then
3312 between those revisions. If only one revision is specified then
3308 that revision is compared to the working directory, and, when no
3313 that revision is compared to the working directory, and, when no
3309 revisions are specified, the working directory files are compared
3314 revisions are specified, the working directory files are compared
3310 to its parent.
3315 to its parent.
3311
3316
3312 Alternatively you can specify -c/--change with a revision to see
3317 Alternatively you can specify -c/--change with a revision to see
3313 the changes in that changeset relative to its first parent.
3318 the changes in that changeset relative to its first parent.
3314
3319
3315 Without the -a/--text option, diff will avoid generating diffs of
3320 Without the -a/--text option, diff will avoid generating diffs of
3316 files it detects as binary. With -a, diff will generate a diff
3321 files it detects as binary. With -a, diff will generate a diff
3317 anyway, probably with undesirable results.
3322 anyway, probably with undesirable results.
3318
3323
3319 Use the -g/--git option to generate diffs in the git extended diff
3324 Use the -g/--git option to generate diffs in the git extended diff
3320 format. For more information, read :hg:`help diffs`.
3325 format. For more information, read :hg:`help diffs`.
3321
3326
3322 .. container:: verbose
3327 .. container:: verbose
3323
3328
3324 Examples:
3329 Examples:
3325
3330
3326 - compare a file in the current working directory to its parent::
3331 - compare a file in the current working directory to its parent::
3327
3332
3328 hg diff foo.c
3333 hg diff foo.c
3329
3334
3330 - compare two historical versions of a directory, with rename info::
3335 - compare two historical versions of a directory, with rename info::
3331
3336
3332 hg diff --git -r 1.0:1.2 lib/
3337 hg diff --git -r 1.0:1.2 lib/
3333
3338
3334 - get change stats relative to the last change on some date::
3339 - get change stats relative to the last change on some date::
3335
3340
3336 hg diff --stat -r "date('may 2')"
3341 hg diff --stat -r "date('may 2')"
3337
3342
3338 - diff all newly-added files that contain a keyword::
3343 - diff all newly-added files that contain a keyword::
3339
3344
3340 hg diff "set:added() and grep(GNU)"
3345 hg diff "set:added() and grep(GNU)"
3341
3346
3342 - compare a revision and its parents::
3347 - compare a revision and its parents::
3343
3348
3344 hg diff -c 9353 # compare against first parent
3349 hg diff -c 9353 # compare against first parent
3345 hg diff -r 9353^:9353 # same using revset syntax
3350 hg diff -r 9353^:9353 # same using revset syntax
3346 hg diff -r 9353^2:9353 # compare against the second parent
3351 hg diff -r 9353^2:9353 # compare against the second parent
3347
3352
3348 Returns 0 on success.
3353 Returns 0 on success.
3349 """
3354 """
3350
3355
3351 revs = opts.get('rev')
3356 revs = opts.get('rev')
3352 change = opts.get('change')
3357 change = opts.get('change')
3353 stat = opts.get('stat')
3358 stat = opts.get('stat')
3354 reverse = opts.get('reverse')
3359 reverse = opts.get('reverse')
3355
3360
3356 if revs and change:
3361 if revs and change:
3357 msg = _('cannot specify --rev and --change at the same time')
3362 msg = _('cannot specify --rev and --change at the same time')
3358 raise error.Abort(msg)
3363 raise error.Abort(msg)
3359 elif change:
3364 elif change:
3360 node2 = scmutil.revsingle(repo, change, None).node()
3365 node2 = scmutil.revsingle(repo, change, None).node()
3361 node1 = repo[node2].p1().node()
3366 node1 = repo[node2].p1().node()
3362 else:
3367 else:
3363 node1, node2 = scmutil.revpair(repo, revs)
3368 node1, node2 = scmutil.revpair(repo, revs)
3364
3369
3365 if reverse:
3370 if reverse:
3366 node1, node2 = node2, node1
3371 node1, node2 = node2, node1
3367
3372
3368 diffopts = patch.diffallopts(ui, opts)
3373 diffopts = patch.diffallopts(ui, opts)
3369 m = scmutil.match(repo[node2], pats, opts)
3374 m = scmutil.match(repo[node2], pats, opts)
3370 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3375 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3371 listsubrepos=opts.get('subrepos'),
3376 listsubrepos=opts.get('subrepos'),
3372 root=opts.get('root'))
3377 root=opts.get('root'))
3373
3378
3374 @command('^export',
3379 @command('^export',
3375 [('o', 'output', '',
3380 [('o', 'output', '',
3376 _('print output to file with formatted name'), _('FORMAT')),
3381 _('print output to file with formatted name'), _('FORMAT')),
3377 ('', 'switch-parent', None, _('diff against the second parent')),
3382 ('', 'switch-parent', None, _('diff against the second parent')),
3378 ('r', 'rev', [], _('revisions to export'), _('REV')),
3383 ('r', 'rev', [], _('revisions to export'), _('REV')),
3379 ] + diffopts,
3384 ] + diffopts,
3380 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3385 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3381 def export(ui, repo, *changesets, **opts):
3386 def export(ui, repo, *changesets, **opts):
3382 """dump the header and diffs for one or more changesets
3387 """dump the header and diffs for one or more changesets
3383
3388
3384 Print the changeset header and diffs for one or more revisions.
3389 Print the changeset header and diffs for one or more revisions.
3385 If no revision is given, the parent of the working directory is used.
3390 If no revision is given, the parent of the working directory is used.
3386
3391
3387 The information shown in the changeset header is: author, date,
3392 The information shown in the changeset header is: author, date,
3388 branch name (if non-default), changeset hash, parent(s) and commit
3393 branch name (if non-default), changeset hash, parent(s) and commit
3389 comment.
3394 comment.
3390
3395
3391 .. note::
3396 .. note::
3392
3397
3393 export may generate unexpected diff output for merge
3398 export may generate unexpected diff output for merge
3394 changesets, as it will compare the merge changeset against its
3399 changesets, as it will compare the merge changeset against its
3395 first parent only.
3400 first parent only.
3396
3401
3397 Output may be to a file, in which case the name of the file is
3402 Output may be to a file, in which case the name of the file is
3398 given using a format string. The formatting rules are as follows:
3403 given using a format string. The formatting rules are as follows:
3399
3404
3400 :``%%``: literal "%" character
3405 :``%%``: literal "%" character
3401 :``%H``: changeset hash (40 hexadecimal digits)
3406 :``%H``: changeset hash (40 hexadecimal digits)
3402 :``%N``: number of patches being generated
3407 :``%N``: number of patches being generated
3403 :``%R``: changeset revision number
3408 :``%R``: changeset revision number
3404 :``%b``: basename of the exporting repository
3409 :``%b``: basename of the exporting repository
3405 :``%h``: short-form changeset hash (12 hexadecimal digits)
3410 :``%h``: short-form changeset hash (12 hexadecimal digits)
3406 :``%m``: first line of the commit message (only alphanumeric characters)
3411 :``%m``: first line of the commit message (only alphanumeric characters)
3407 :``%n``: zero-padded sequence number, starting at 1
3412 :``%n``: zero-padded sequence number, starting at 1
3408 :``%r``: zero-padded changeset revision number
3413 :``%r``: zero-padded changeset revision number
3409
3414
3410 Without the -a/--text option, export will avoid generating diffs
3415 Without the -a/--text option, export will avoid generating diffs
3411 of files it detects as binary. With -a, export will generate a
3416 of files it detects as binary. With -a, export will generate a
3412 diff anyway, probably with undesirable results.
3417 diff anyway, probably with undesirable results.
3413
3418
3414 Use the -g/--git option to generate diffs in the git extended diff
3419 Use the -g/--git option to generate diffs in the git extended diff
3415 format. See :hg:`help diffs` for more information.
3420 format. See :hg:`help diffs` for more information.
3416
3421
3417 With the --switch-parent option, the diff will be against the
3422 With the --switch-parent option, the diff will be against the
3418 second parent. It can be useful to review a merge.
3423 second parent. It can be useful to review a merge.
3419
3424
3420 .. container:: verbose
3425 .. container:: verbose
3421
3426
3422 Examples:
3427 Examples:
3423
3428
3424 - use export and import to transplant a bugfix to the current
3429 - use export and import to transplant a bugfix to the current
3425 branch::
3430 branch::
3426
3431
3427 hg export -r 9353 | hg import -
3432 hg export -r 9353 | hg import -
3428
3433
3429 - export all the changesets between two revisions to a file with
3434 - export all the changesets between two revisions to a file with
3430 rename information::
3435 rename information::
3431
3436
3432 hg export --git -r 123:150 > changes.txt
3437 hg export --git -r 123:150 > changes.txt
3433
3438
3434 - split outgoing changes into a series of patches with
3439 - split outgoing changes into a series of patches with
3435 descriptive names::
3440 descriptive names::
3436
3441
3437 hg export -r "outgoing()" -o "%n-%m.patch"
3442 hg export -r "outgoing()" -o "%n-%m.patch"
3438
3443
3439 Returns 0 on success.
3444 Returns 0 on success.
3440 """
3445 """
3441 changesets += tuple(opts.get('rev', []))
3446 changesets += tuple(opts.get('rev', []))
3442 if not changesets:
3447 if not changesets:
3443 changesets = ['.']
3448 changesets = ['.']
3444 revs = scmutil.revrange(repo, changesets)
3449 revs = scmutil.revrange(repo, changesets)
3445 if not revs:
3450 if not revs:
3446 raise error.Abort(_("export requires at least one changeset"))
3451 raise error.Abort(_("export requires at least one changeset"))
3447 if len(revs) > 1:
3452 if len(revs) > 1:
3448 ui.note(_('exporting patches:\n'))
3453 ui.note(_('exporting patches:\n'))
3449 else:
3454 else:
3450 ui.note(_('exporting patch:\n'))
3455 ui.note(_('exporting patch:\n'))
3451 cmdutil.export(repo, revs, template=opts.get('output'),
3456 cmdutil.export(repo, revs, template=opts.get('output'),
3452 switch_parent=opts.get('switch_parent'),
3457 switch_parent=opts.get('switch_parent'),
3453 opts=patch.diffallopts(ui, opts))
3458 opts=patch.diffallopts(ui, opts))
3454
3459
3455 @command('files',
3460 @command('files',
3456 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3461 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3457 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3462 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3458 ] + walkopts + formatteropts + subrepoopts,
3463 ] + walkopts + formatteropts + subrepoopts,
3459 _('[OPTION]... [PATTERN]...'))
3464 _('[OPTION]... [PATTERN]...'))
3460 def files(ui, repo, *pats, **opts):
3465 def files(ui, repo, *pats, **opts):
3461 """list tracked files
3466 """list tracked files
3462
3467
3463 Print files under Mercurial control in the working directory or
3468 Print files under Mercurial control in the working directory or
3464 specified revision whose names match the given patterns (excluding
3469 specified revision whose names match the given patterns (excluding
3465 removed files).
3470 removed files).
3466
3471
3467 If no patterns are given to match, this command prints the names
3472 If no patterns are given to match, this command prints the names
3468 of all files under Mercurial control in the working directory.
3473 of all files under Mercurial control in the working directory.
3469
3474
3470 .. container:: verbose
3475 .. container:: verbose
3471
3476
3472 Examples:
3477 Examples:
3473
3478
3474 - list all files under the current directory::
3479 - list all files under the current directory::
3475
3480
3476 hg files .
3481 hg files .
3477
3482
3478 - shows sizes and flags for current revision::
3483 - shows sizes and flags for current revision::
3479
3484
3480 hg files -vr .
3485 hg files -vr .
3481
3486
3482 - list all files named README::
3487 - list all files named README::
3483
3488
3484 hg files -I "**/README"
3489 hg files -I "**/README"
3485
3490
3486 - list all binary files::
3491 - list all binary files::
3487
3492
3488 hg files "set:binary()"
3493 hg files "set:binary()"
3489
3494
3490 - find files containing a regular expression::
3495 - find files containing a regular expression::
3491
3496
3492 hg files "set:grep('bob')"
3497 hg files "set:grep('bob')"
3493
3498
3494 - search tracked file contents with xargs and grep::
3499 - search tracked file contents with xargs and grep::
3495
3500
3496 hg files -0 | xargs -0 grep foo
3501 hg files -0 | xargs -0 grep foo
3497
3502
3498 See :hg:`help patterns` and :hg:`help filesets` for more information
3503 See :hg:`help patterns` and :hg:`help filesets` for more information
3499 on specifying file patterns.
3504 on specifying file patterns.
3500
3505
3501 Returns 0 if a match is found, 1 otherwise.
3506 Returns 0 if a match is found, 1 otherwise.
3502
3507
3503 """
3508 """
3504 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3509 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3505
3510
3506 end = '\n'
3511 end = '\n'
3507 if opts.get('print0'):
3512 if opts.get('print0'):
3508 end = '\0'
3513 end = '\0'
3509 fm = ui.formatter('files', opts)
3514 fm = ui.formatter('files', opts)
3510 fmt = '%s' + end
3515 fmt = '%s' + end
3511
3516
3512 m = scmutil.match(ctx, pats, opts)
3517 m = scmutil.match(ctx, pats, opts)
3513 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3518 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3514
3519
3515 fm.end()
3520 fm.end()
3516
3521
3517 return ret
3522 return ret
3518
3523
3519 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3524 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3520 def forget(ui, repo, *pats, **opts):
3525 def forget(ui, repo, *pats, **opts):
3521 """forget the specified files on the next commit
3526 """forget the specified files on the next commit
3522
3527
3523 Mark the specified files so they will no longer be tracked
3528 Mark the specified files so they will no longer be tracked
3524 after the next commit.
3529 after the next commit.
3525
3530
3526 This only removes files from the current branch, not from the
3531 This only removes files from the current branch, not from the
3527 entire project history, and it does not delete them from the
3532 entire project history, and it does not delete them from the
3528 working directory.
3533 working directory.
3529
3534
3530 To delete the file from the working directory, see :hg:`remove`.
3535 To delete the file from the working directory, see :hg:`remove`.
3531
3536
3532 To undo a forget before the next commit, see :hg:`add`.
3537 To undo a forget before the next commit, see :hg:`add`.
3533
3538
3534 .. container:: verbose
3539 .. container:: verbose
3535
3540
3536 Examples:
3541 Examples:
3537
3542
3538 - forget newly-added binary files::
3543 - forget newly-added binary files::
3539
3544
3540 hg forget "set:added() and binary()"
3545 hg forget "set:added() and binary()"
3541
3546
3542 - forget files that would be excluded by .hgignore::
3547 - forget files that would be excluded by .hgignore::
3543
3548
3544 hg forget "set:hgignore()"
3549 hg forget "set:hgignore()"
3545
3550
3546 Returns 0 on success.
3551 Returns 0 on success.
3547 """
3552 """
3548
3553
3549 if not pats:
3554 if not pats:
3550 raise error.Abort(_('no files specified'))
3555 raise error.Abort(_('no files specified'))
3551
3556
3552 m = scmutil.match(repo[None], pats, opts)
3557 m = scmutil.match(repo[None], pats, opts)
3553 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3558 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3554 return rejected and 1 or 0
3559 return rejected and 1 or 0
3555
3560
3556 @command(
3561 @command(
3557 'graft',
3562 'graft',
3558 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3563 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3559 ('c', 'continue', False, _('resume interrupted graft')),
3564 ('c', 'continue', False, _('resume interrupted graft')),
3560 ('e', 'edit', False, _('invoke editor on commit messages')),
3565 ('e', 'edit', False, _('invoke editor on commit messages')),
3561 ('', 'log', None, _('append graft info to log message')),
3566 ('', 'log', None, _('append graft info to log message')),
3562 ('f', 'force', False, _('force graft')),
3567 ('f', 'force', False, _('force graft')),
3563 ('D', 'currentdate', False,
3568 ('D', 'currentdate', False,
3564 _('record the current date as commit date')),
3569 _('record the current date as commit date')),
3565 ('U', 'currentuser', False,
3570 ('U', 'currentuser', False,
3566 _('record the current user as committer'), _('DATE'))]
3571 _('record the current user as committer'), _('DATE'))]
3567 + commitopts2 + mergetoolopts + dryrunopts,
3572 + commitopts2 + mergetoolopts + dryrunopts,
3568 _('[OPTION]... [-r] REV...'))
3573 _('[OPTION]... [-r] REV...'))
3569 def graft(ui, repo, *revs, **opts):
3574 def graft(ui, repo, *revs, **opts):
3570 '''copy changes from other branches onto the current branch
3575 '''copy changes from other branches onto the current branch
3571
3576
3572 This command uses Mercurial's merge logic to copy individual
3577 This command uses Mercurial's merge logic to copy individual
3573 changes from other branches without merging branches in the
3578 changes from other branches without merging branches in the
3574 history graph. This is sometimes known as 'backporting' or
3579 history graph. This is sometimes known as 'backporting' or
3575 'cherry-picking'. By default, graft will copy user, date, and
3580 'cherry-picking'. By default, graft will copy user, date, and
3576 description from the source changesets.
3581 description from the source changesets.
3577
3582
3578 Changesets that are ancestors of the current revision, that have
3583 Changesets that are ancestors of the current revision, that have
3579 already been grafted, or that are merges will be skipped.
3584 already been grafted, or that are merges will be skipped.
3580
3585
3581 If --log is specified, log messages will have a comment appended
3586 If --log is specified, log messages will have a comment appended
3582 of the form::
3587 of the form::
3583
3588
3584 (grafted from CHANGESETHASH)
3589 (grafted from CHANGESETHASH)
3585
3590
3586 If --force is specified, revisions will be grafted even if they
3591 If --force is specified, revisions will be grafted even if they
3587 are already ancestors of or have been grafted to the destination.
3592 are already ancestors of or have been grafted to the destination.
3588 This is useful when the revisions have since been backed out.
3593 This is useful when the revisions have since been backed out.
3589
3594
3590 If a graft merge results in conflicts, the graft process is
3595 If a graft merge results in conflicts, the graft process is
3591 interrupted so that the current merge can be manually resolved.
3596 interrupted so that the current merge can be manually resolved.
3592 Once all conflicts are addressed, the graft process can be
3597 Once all conflicts are addressed, the graft process can be
3593 continued with the -c/--continue option.
3598 continued with the -c/--continue option.
3594
3599
3595 .. note::
3600 .. note::
3596
3601
3597 The -c/--continue option does not reapply earlier options, except
3602 The -c/--continue option does not reapply earlier options, except
3598 for --force.
3603 for --force.
3599
3604
3600 .. container:: verbose
3605 .. container:: verbose
3601
3606
3602 Examples:
3607 Examples:
3603
3608
3604 - copy a single change to the stable branch and edit its description::
3609 - copy a single change to the stable branch and edit its description::
3605
3610
3606 hg update stable
3611 hg update stable
3607 hg graft --edit 9393
3612 hg graft --edit 9393
3608
3613
3609 - graft a range of changesets with one exception, updating dates::
3614 - graft a range of changesets with one exception, updating dates::
3610
3615
3611 hg graft -D "2085::2093 and not 2091"
3616 hg graft -D "2085::2093 and not 2091"
3612
3617
3613 - continue a graft after resolving conflicts::
3618 - continue a graft after resolving conflicts::
3614
3619
3615 hg graft -c
3620 hg graft -c
3616
3621
3617 - show the source of a grafted changeset::
3622 - show the source of a grafted changeset::
3618
3623
3619 hg log --debug -r .
3624 hg log --debug -r .
3620
3625
3621 See :hg:`help revisions` and :hg:`help revsets` for more about
3626 See :hg:`help revisions` and :hg:`help revsets` for more about
3622 specifying revisions.
3627 specifying revisions.
3623
3628
3624 Returns 0 on successful completion.
3629 Returns 0 on successful completion.
3625 '''
3630 '''
3626
3631
3627 revs = list(revs)
3632 revs = list(revs)
3628 revs.extend(opts['rev'])
3633 revs.extend(opts['rev'])
3629
3634
3630 if not opts.get('user') and opts.get('currentuser'):
3635 if not opts.get('user') and opts.get('currentuser'):
3631 opts['user'] = ui.username()
3636 opts['user'] = ui.username()
3632 if not opts.get('date') and opts.get('currentdate'):
3637 if not opts.get('date') and opts.get('currentdate'):
3633 opts['date'] = "%d %d" % util.makedate()
3638 opts['date'] = "%d %d" % util.makedate()
3634
3639
3635 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3640 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3636
3641
3637 cont = False
3642 cont = False
3638 if opts['continue']:
3643 if opts['continue']:
3639 cont = True
3644 cont = True
3640 if revs:
3645 if revs:
3641 raise error.Abort(_("can't specify --continue and revisions"))
3646 raise error.Abort(_("can't specify --continue and revisions"))
3642 # read in unfinished revisions
3647 # read in unfinished revisions
3643 try:
3648 try:
3644 nodes = repo.vfs.read('graftstate').splitlines()
3649 nodes = repo.vfs.read('graftstate').splitlines()
3645 revs = [repo[node].rev() for node in nodes]
3650 revs = [repo[node].rev() for node in nodes]
3646 except IOError as inst:
3651 except IOError as inst:
3647 if inst.errno != errno.ENOENT:
3652 if inst.errno != errno.ENOENT:
3648 raise
3653 raise
3649 raise error.Abort(_("no graft state found, can't continue"))
3654 raise error.Abort(_("no graft state found, can't continue"))
3650 else:
3655 else:
3651 cmdutil.checkunfinished(repo)
3656 cmdutil.checkunfinished(repo)
3652 cmdutil.bailifchanged(repo)
3657 cmdutil.bailifchanged(repo)
3653 if not revs:
3658 if not revs:
3654 raise error.Abort(_('no revisions specified'))
3659 raise error.Abort(_('no revisions specified'))
3655 revs = scmutil.revrange(repo, revs)
3660 revs = scmutil.revrange(repo, revs)
3656
3661
3657 skipped = set()
3662 skipped = set()
3658 # check for merges
3663 # check for merges
3659 for rev in repo.revs('%ld and merge()', revs):
3664 for rev in repo.revs('%ld and merge()', revs):
3660 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3665 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3661 skipped.add(rev)
3666 skipped.add(rev)
3662 revs = [r for r in revs if r not in skipped]
3667 revs = [r for r in revs if r not in skipped]
3663 if not revs:
3668 if not revs:
3664 return -1
3669 return -1
3665
3670
3666 # Don't check in the --continue case, in effect retaining --force across
3671 # Don't check in the --continue case, in effect retaining --force across
3667 # --continues. That's because without --force, any revisions we decided to
3672 # --continues. That's because without --force, any revisions we decided to
3668 # skip would have been filtered out here, so they wouldn't have made their
3673 # skip would have been filtered out here, so they wouldn't have made their
3669 # way to the graftstate. With --force, any revisions we would have otherwise
3674 # way to the graftstate. With --force, any revisions we would have otherwise
3670 # skipped would not have been filtered out, and if they hadn't been applied
3675 # skipped would not have been filtered out, and if they hadn't been applied
3671 # already, they'd have been in the graftstate.
3676 # already, they'd have been in the graftstate.
3672 if not (cont or opts.get('force')):
3677 if not (cont or opts.get('force')):
3673 # check for ancestors of dest branch
3678 # check for ancestors of dest branch
3674 crev = repo['.'].rev()
3679 crev = repo['.'].rev()
3675 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3680 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3676 # Cannot use x.remove(y) on smart set, this has to be a list.
3681 # Cannot use x.remove(y) on smart set, this has to be a list.
3677 # XXX make this lazy in the future
3682 # XXX make this lazy in the future
3678 revs = list(revs)
3683 revs = list(revs)
3679 # don't mutate while iterating, create a copy
3684 # don't mutate while iterating, create a copy
3680 for rev in list(revs):
3685 for rev in list(revs):
3681 if rev in ancestors:
3686 if rev in ancestors:
3682 ui.warn(_('skipping ancestor revision %d:%s\n') %
3687 ui.warn(_('skipping ancestor revision %d:%s\n') %
3683 (rev, repo[rev]))
3688 (rev, repo[rev]))
3684 # XXX remove on list is slow
3689 # XXX remove on list is slow
3685 revs.remove(rev)
3690 revs.remove(rev)
3686 if not revs:
3691 if not revs:
3687 return -1
3692 return -1
3688
3693
3689 # analyze revs for earlier grafts
3694 # analyze revs for earlier grafts
3690 ids = {}
3695 ids = {}
3691 for ctx in repo.set("%ld", revs):
3696 for ctx in repo.set("%ld", revs):
3692 ids[ctx.hex()] = ctx.rev()
3697 ids[ctx.hex()] = ctx.rev()
3693 n = ctx.extra().get('source')
3698 n = ctx.extra().get('source')
3694 if n:
3699 if n:
3695 ids[n] = ctx.rev()
3700 ids[n] = ctx.rev()
3696
3701
3697 # check ancestors for earlier grafts
3702 # check ancestors for earlier grafts
3698 ui.debug('scanning for duplicate grafts\n')
3703 ui.debug('scanning for duplicate grafts\n')
3699
3704
3700 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3705 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3701 ctx = repo[rev]
3706 ctx = repo[rev]
3702 n = ctx.extra().get('source')
3707 n = ctx.extra().get('source')
3703 if n in ids:
3708 if n in ids:
3704 try:
3709 try:
3705 r = repo[n].rev()
3710 r = repo[n].rev()
3706 except error.RepoLookupError:
3711 except error.RepoLookupError:
3707 r = None
3712 r = None
3708 if r in revs:
3713 if r in revs:
3709 ui.warn(_('skipping revision %d:%s '
3714 ui.warn(_('skipping revision %d:%s '
3710 '(already grafted to %d:%s)\n')
3715 '(already grafted to %d:%s)\n')
3711 % (r, repo[r], rev, ctx))
3716 % (r, repo[r], rev, ctx))
3712 revs.remove(r)
3717 revs.remove(r)
3713 elif ids[n] in revs:
3718 elif ids[n] in revs:
3714 if r is None:
3719 if r is None:
3715 ui.warn(_('skipping already grafted revision %d:%s '
3720 ui.warn(_('skipping already grafted revision %d:%s '
3716 '(%d:%s also has unknown origin %s)\n')
3721 '(%d:%s also has unknown origin %s)\n')
3717 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3722 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3718 else:
3723 else:
3719 ui.warn(_('skipping already grafted revision %d:%s '
3724 ui.warn(_('skipping already grafted revision %d:%s '
3720 '(%d:%s also has origin %d:%s)\n')
3725 '(%d:%s also has origin %d:%s)\n')
3721 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3726 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3722 revs.remove(ids[n])
3727 revs.remove(ids[n])
3723 elif ctx.hex() in ids:
3728 elif ctx.hex() in ids:
3724 r = ids[ctx.hex()]
3729 r = ids[ctx.hex()]
3725 ui.warn(_('skipping already grafted revision %d:%s '
3730 ui.warn(_('skipping already grafted revision %d:%s '
3726 '(was grafted from %d:%s)\n') %
3731 '(was grafted from %d:%s)\n') %
3727 (r, repo[r], rev, ctx))
3732 (r, repo[r], rev, ctx))
3728 revs.remove(r)
3733 revs.remove(r)
3729 if not revs:
3734 if not revs:
3730 return -1
3735 return -1
3731
3736
3732 wlock = repo.wlock()
3737 wlock = repo.wlock()
3733 try:
3738 try:
3734 for pos, ctx in enumerate(repo.set("%ld", revs)):
3739 for pos, ctx in enumerate(repo.set("%ld", revs)):
3735 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3740 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3736 ctx.description().split('\n', 1)[0])
3741 ctx.description().split('\n', 1)[0])
3737 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3742 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3738 if names:
3743 if names:
3739 desc += ' (%s)' % ' '.join(names)
3744 desc += ' (%s)' % ' '.join(names)
3740 ui.status(_('grafting %s\n') % desc)
3745 ui.status(_('grafting %s\n') % desc)
3741 if opts.get('dry_run'):
3746 if opts.get('dry_run'):
3742 continue
3747 continue
3743
3748
3744 source = ctx.extra().get('source')
3749 source = ctx.extra().get('source')
3745 extra = {}
3750 extra = {}
3746 if source:
3751 if source:
3747 extra['source'] = source
3752 extra['source'] = source
3748 extra['intermediate-source'] = ctx.hex()
3753 extra['intermediate-source'] = ctx.hex()
3749 else:
3754 else:
3750 extra['source'] = ctx.hex()
3755 extra['source'] = ctx.hex()
3751 user = ctx.user()
3756 user = ctx.user()
3752 if opts.get('user'):
3757 if opts.get('user'):
3753 user = opts['user']
3758 user = opts['user']
3754 date = ctx.date()
3759 date = ctx.date()
3755 if opts.get('date'):
3760 if opts.get('date'):
3756 date = opts['date']
3761 date = opts['date']
3757 message = ctx.description()
3762 message = ctx.description()
3758 if opts.get('log'):
3763 if opts.get('log'):
3759 message += '\n(grafted from %s)' % ctx.hex()
3764 message += '\n(grafted from %s)' % ctx.hex()
3760
3765
3761 # we don't merge the first commit when continuing
3766 # we don't merge the first commit when continuing
3762 if not cont:
3767 if not cont:
3763 # perform the graft merge with p1(rev) as 'ancestor'
3768 # perform the graft merge with p1(rev) as 'ancestor'
3764 try:
3769 try:
3765 # ui.forcemerge is an internal variable, do not document
3770 # ui.forcemerge is an internal variable, do not document
3766 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3771 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
3767 'graft')
3772 'graft')
3768 stats = mergemod.graft(repo, ctx, ctx.p1(),
3773 stats = mergemod.graft(repo, ctx, ctx.p1(),
3769 ['local', 'graft'])
3774 ['local', 'graft'])
3770 finally:
3775 finally:
3771 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3776 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
3772 # report any conflicts
3777 # report any conflicts
3773 if stats and stats[3] > 0:
3778 if stats and stats[3] > 0:
3774 # write out state for --continue
3779 # write out state for --continue
3775 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3780 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
3776 repo.vfs.write('graftstate', ''.join(nodelines))
3781 repo.vfs.write('graftstate', ''.join(nodelines))
3777 raise error.Abort(
3782 raise error.Abort(
3778 _("unresolved conflicts, can't continue"),
3783 _("unresolved conflicts, can't continue"),
3779 hint=_('use hg resolve and hg graft --continue'))
3784 hint=_('use hg resolve and hg graft --continue'))
3780 else:
3785 else:
3781 cont = False
3786 cont = False
3782
3787
3783 # commit
3788 # commit
3784 node = repo.commit(text=message, user=user,
3789 node = repo.commit(text=message, user=user,
3785 date=date, extra=extra, editor=editor)
3790 date=date, extra=extra, editor=editor)
3786 if node is None:
3791 if node is None:
3787 ui.warn(
3792 ui.warn(
3788 _('note: graft of %d:%s created no changes to commit\n') %
3793 _('note: graft of %d:%s created no changes to commit\n') %
3789 (ctx.rev(), ctx))
3794 (ctx.rev(), ctx))
3790 finally:
3795 finally:
3791 wlock.release()
3796 wlock.release()
3792
3797
3793 # remove state when we complete successfully
3798 # remove state when we complete successfully
3794 if not opts.get('dry_run'):
3799 if not opts.get('dry_run'):
3795 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3800 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
3796
3801
3797 return 0
3802 return 0
3798
3803
3799 @command('grep',
3804 @command('grep',
3800 [('0', 'print0', None, _('end fields with NUL')),
3805 [('0', 'print0', None, _('end fields with NUL')),
3801 ('', 'all', None, _('print all revisions that match')),
3806 ('', 'all', None, _('print all revisions that match')),
3802 ('a', 'text', None, _('treat all files as text')),
3807 ('a', 'text', None, _('treat all files as text')),
3803 ('f', 'follow', None,
3808 ('f', 'follow', None,
3804 _('follow changeset history,'
3809 _('follow changeset history,'
3805 ' or file history across copies and renames')),
3810 ' or file history across copies and renames')),
3806 ('i', 'ignore-case', None, _('ignore case when matching')),
3811 ('i', 'ignore-case', None, _('ignore case when matching')),
3807 ('l', 'files-with-matches', None,
3812 ('l', 'files-with-matches', None,
3808 _('print only filenames and revisions that match')),
3813 _('print only filenames and revisions that match')),
3809 ('n', 'line-number', None, _('print matching line numbers')),
3814 ('n', 'line-number', None, _('print matching line numbers')),
3810 ('r', 'rev', [],
3815 ('r', 'rev', [],
3811 _('only search files changed within revision range'), _('REV')),
3816 _('only search files changed within revision range'), _('REV')),
3812 ('u', 'user', None, _('list the author (long with -v)')),
3817 ('u', 'user', None, _('list the author (long with -v)')),
3813 ('d', 'date', None, _('list the date (short with -q)')),
3818 ('d', 'date', None, _('list the date (short with -q)')),
3814 ] + walkopts,
3819 ] + walkopts,
3815 _('[OPTION]... PATTERN [FILE]...'),
3820 _('[OPTION]... PATTERN [FILE]...'),
3816 inferrepo=True)
3821 inferrepo=True)
3817 def grep(ui, repo, pattern, *pats, **opts):
3822 def grep(ui, repo, pattern, *pats, **opts):
3818 """search for a pattern in specified files and revisions
3823 """search for a pattern in specified files and revisions
3819
3824
3820 Search revisions of files for a regular expression.
3825 Search revisions of files for a regular expression.
3821
3826
3822 This command behaves differently than Unix grep. It only accepts
3827 This command behaves differently than Unix grep. It only accepts
3823 Python/Perl regexps. It searches repository history, not the
3828 Python/Perl regexps. It searches repository history, not the
3824 working directory. It always prints the revision number in which a
3829 working directory. It always prints the revision number in which a
3825 match appears.
3830 match appears.
3826
3831
3827 By default, grep only prints output for the first revision of a
3832 By default, grep only prints output for the first revision of a
3828 file in which it finds a match. To get it to print every revision
3833 file in which it finds a match. To get it to print every revision
3829 that contains a change in match status ("-" for a match that
3834 that contains a change in match status ("-" for a match that
3830 becomes a non-match, or "+" for a non-match that becomes a match),
3835 becomes a non-match, or "+" for a non-match that becomes a match),
3831 use the --all flag.
3836 use the --all flag.
3832
3837
3833 Returns 0 if a match is found, 1 otherwise.
3838 Returns 0 if a match is found, 1 otherwise.
3834 """
3839 """
3835 reflags = re.M
3840 reflags = re.M
3836 if opts.get('ignore_case'):
3841 if opts.get('ignore_case'):
3837 reflags |= re.I
3842 reflags |= re.I
3838 try:
3843 try:
3839 regexp = util.re.compile(pattern, reflags)
3844 regexp = util.re.compile(pattern, reflags)
3840 except re.error as inst:
3845 except re.error as inst:
3841 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3846 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
3842 return 1
3847 return 1
3843 sep, eol = ':', '\n'
3848 sep, eol = ':', '\n'
3844 if opts.get('print0'):
3849 if opts.get('print0'):
3845 sep = eol = '\0'
3850 sep = eol = '\0'
3846
3851
3847 getfile = util.lrucachefunc(repo.file)
3852 getfile = util.lrucachefunc(repo.file)
3848
3853
3849 def matchlines(body):
3854 def matchlines(body):
3850 begin = 0
3855 begin = 0
3851 linenum = 0
3856 linenum = 0
3852 while begin < len(body):
3857 while begin < len(body):
3853 match = regexp.search(body, begin)
3858 match = regexp.search(body, begin)
3854 if not match:
3859 if not match:
3855 break
3860 break
3856 mstart, mend = match.span()
3861 mstart, mend = match.span()
3857 linenum += body.count('\n', begin, mstart) + 1
3862 linenum += body.count('\n', begin, mstart) + 1
3858 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3863 lstart = body.rfind('\n', begin, mstart) + 1 or begin
3859 begin = body.find('\n', mend) + 1 or len(body) + 1
3864 begin = body.find('\n', mend) + 1 or len(body) + 1
3860 lend = begin - 1
3865 lend = begin - 1
3861 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3866 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
3862
3867
3863 class linestate(object):
3868 class linestate(object):
3864 def __init__(self, line, linenum, colstart, colend):
3869 def __init__(self, line, linenum, colstart, colend):
3865 self.line = line
3870 self.line = line
3866 self.linenum = linenum
3871 self.linenum = linenum
3867 self.colstart = colstart
3872 self.colstart = colstart
3868 self.colend = colend
3873 self.colend = colend
3869
3874
3870 def __hash__(self):
3875 def __hash__(self):
3871 return hash((self.linenum, self.line))
3876 return hash((self.linenum, self.line))
3872
3877
3873 def __eq__(self, other):
3878 def __eq__(self, other):
3874 return self.line == other.line
3879 return self.line == other.line
3875
3880
3876 def __iter__(self):
3881 def __iter__(self):
3877 yield (self.line[:self.colstart], '')
3882 yield (self.line[:self.colstart], '')
3878 yield (self.line[self.colstart:self.colend], 'grep.match')
3883 yield (self.line[self.colstart:self.colend], 'grep.match')
3879 rest = self.line[self.colend:]
3884 rest = self.line[self.colend:]
3880 while rest != '':
3885 while rest != '':
3881 match = regexp.search(rest)
3886 match = regexp.search(rest)
3882 if not match:
3887 if not match:
3883 yield (rest, '')
3888 yield (rest, '')
3884 break
3889 break
3885 mstart, mend = match.span()
3890 mstart, mend = match.span()
3886 yield (rest[:mstart], '')
3891 yield (rest[:mstart], '')
3887 yield (rest[mstart:mend], 'grep.match')
3892 yield (rest[mstart:mend], 'grep.match')
3888 rest = rest[mend:]
3893 rest = rest[mend:]
3889
3894
3890 matches = {}
3895 matches = {}
3891 copies = {}
3896 copies = {}
3892 def grepbody(fn, rev, body):
3897 def grepbody(fn, rev, body):
3893 matches[rev].setdefault(fn, [])
3898 matches[rev].setdefault(fn, [])
3894 m = matches[rev][fn]
3899 m = matches[rev][fn]
3895 for lnum, cstart, cend, line in matchlines(body):
3900 for lnum, cstart, cend, line in matchlines(body):
3896 s = linestate(line, lnum, cstart, cend)
3901 s = linestate(line, lnum, cstart, cend)
3897 m.append(s)
3902 m.append(s)
3898
3903
3899 def difflinestates(a, b):
3904 def difflinestates(a, b):
3900 sm = difflib.SequenceMatcher(None, a, b)
3905 sm = difflib.SequenceMatcher(None, a, b)
3901 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3906 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
3902 if tag == 'insert':
3907 if tag == 'insert':
3903 for i in xrange(blo, bhi):
3908 for i in xrange(blo, bhi):
3904 yield ('+', b[i])
3909 yield ('+', b[i])
3905 elif tag == 'delete':
3910 elif tag == 'delete':
3906 for i in xrange(alo, ahi):
3911 for i in xrange(alo, ahi):
3907 yield ('-', a[i])
3912 yield ('-', a[i])
3908 elif tag == 'replace':
3913 elif tag == 'replace':
3909 for i in xrange(alo, ahi):
3914 for i in xrange(alo, ahi):
3910 yield ('-', a[i])
3915 yield ('-', a[i])
3911 for i in xrange(blo, bhi):
3916 for i in xrange(blo, bhi):
3912 yield ('+', b[i])
3917 yield ('+', b[i])
3913
3918
3914 def display(fn, ctx, pstates, states):
3919 def display(fn, ctx, pstates, states):
3915 rev = ctx.rev()
3920 rev = ctx.rev()
3916 if ui.quiet:
3921 if ui.quiet:
3917 datefunc = util.shortdate
3922 datefunc = util.shortdate
3918 else:
3923 else:
3919 datefunc = util.datestr
3924 datefunc = util.datestr
3920 found = False
3925 found = False
3921 @util.cachefunc
3926 @util.cachefunc
3922 def binary():
3927 def binary():
3923 flog = getfile(fn)
3928 flog = getfile(fn)
3924 return util.binary(flog.read(ctx.filenode(fn)))
3929 return util.binary(flog.read(ctx.filenode(fn)))
3925
3930
3926 if opts.get('all'):
3931 if opts.get('all'):
3927 iter = difflinestates(pstates, states)
3932 iter = difflinestates(pstates, states)
3928 else:
3933 else:
3929 iter = [('', l) for l in states]
3934 iter = [('', l) for l in states]
3930 for change, l in iter:
3935 for change, l in iter:
3931 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3936 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
3932
3937
3933 if opts.get('line_number'):
3938 if opts.get('line_number'):
3934 cols.append((str(l.linenum), 'grep.linenumber'))
3939 cols.append((str(l.linenum), 'grep.linenumber'))
3935 if opts.get('all'):
3940 if opts.get('all'):
3936 cols.append((change, 'grep.change'))
3941 cols.append((change, 'grep.change'))
3937 if opts.get('user'):
3942 if opts.get('user'):
3938 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3943 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
3939 if opts.get('date'):
3944 if opts.get('date'):
3940 cols.append((datefunc(ctx.date()), 'grep.date'))
3945 cols.append((datefunc(ctx.date()), 'grep.date'))
3941 for col, label in cols[:-1]:
3946 for col, label in cols[:-1]:
3942 ui.write(col, label=label)
3947 ui.write(col, label=label)
3943 ui.write(sep, label='grep.sep')
3948 ui.write(sep, label='grep.sep')
3944 ui.write(cols[-1][0], label=cols[-1][1])
3949 ui.write(cols[-1][0], label=cols[-1][1])
3945 if not opts.get('files_with_matches'):
3950 if not opts.get('files_with_matches'):
3946 ui.write(sep, label='grep.sep')
3951 ui.write(sep, label='grep.sep')
3947 if not opts.get('text') and binary():
3952 if not opts.get('text') and binary():
3948 ui.write(" Binary file matches")
3953 ui.write(" Binary file matches")
3949 else:
3954 else:
3950 for s, label in l:
3955 for s, label in l:
3951 ui.write(s, label=label)
3956 ui.write(s, label=label)
3952 ui.write(eol)
3957 ui.write(eol)
3953 found = True
3958 found = True
3954 if opts.get('files_with_matches'):
3959 if opts.get('files_with_matches'):
3955 break
3960 break
3956 return found
3961 return found
3957
3962
3958 skip = {}
3963 skip = {}
3959 revfiles = {}
3964 revfiles = {}
3960 matchfn = scmutil.match(repo[None], pats, opts)
3965 matchfn = scmutil.match(repo[None], pats, opts)
3961 found = False
3966 found = False
3962 follow = opts.get('follow')
3967 follow = opts.get('follow')
3963
3968
3964 def prep(ctx, fns):
3969 def prep(ctx, fns):
3965 rev = ctx.rev()
3970 rev = ctx.rev()
3966 pctx = ctx.p1()
3971 pctx = ctx.p1()
3967 parent = pctx.rev()
3972 parent = pctx.rev()
3968 matches.setdefault(rev, {})
3973 matches.setdefault(rev, {})
3969 matches.setdefault(parent, {})
3974 matches.setdefault(parent, {})
3970 files = revfiles.setdefault(rev, [])
3975 files = revfiles.setdefault(rev, [])
3971 for fn in fns:
3976 for fn in fns:
3972 flog = getfile(fn)
3977 flog = getfile(fn)
3973 try:
3978 try:
3974 fnode = ctx.filenode(fn)
3979 fnode = ctx.filenode(fn)
3975 except error.LookupError:
3980 except error.LookupError:
3976 continue
3981 continue
3977
3982
3978 copied = flog.renamed(fnode)
3983 copied = flog.renamed(fnode)
3979 copy = follow and copied and copied[0]
3984 copy = follow and copied and copied[0]
3980 if copy:
3985 if copy:
3981 copies.setdefault(rev, {})[fn] = copy
3986 copies.setdefault(rev, {})[fn] = copy
3982 if fn in skip:
3987 if fn in skip:
3983 if copy:
3988 if copy:
3984 skip[copy] = True
3989 skip[copy] = True
3985 continue
3990 continue
3986 files.append(fn)
3991 files.append(fn)
3987
3992
3988 if fn not in matches[rev]:
3993 if fn not in matches[rev]:
3989 grepbody(fn, rev, flog.read(fnode))
3994 grepbody(fn, rev, flog.read(fnode))
3990
3995
3991 pfn = copy or fn
3996 pfn = copy or fn
3992 if pfn not in matches[parent]:
3997 if pfn not in matches[parent]:
3993 try:
3998 try:
3994 fnode = pctx.filenode(pfn)
3999 fnode = pctx.filenode(pfn)
3995 grepbody(pfn, parent, flog.read(fnode))
4000 grepbody(pfn, parent, flog.read(fnode))
3996 except error.LookupError:
4001 except error.LookupError:
3997 pass
4002 pass
3998
4003
3999 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4004 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4000 rev = ctx.rev()
4005 rev = ctx.rev()
4001 parent = ctx.p1().rev()
4006 parent = ctx.p1().rev()
4002 for fn in sorted(revfiles.get(rev, [])):
4007 for fn in sorted(revfiles.get(rev, [])):
4003 states = matches[rev][fn]
4008 states = matches[rev][fn]
4004 copy = copies.get(rev, {}).get(fn)
4009 copy = copies.get(rev, {}).get(fn)
4005 if fn in skip:
4010 if fn in skip:
4006 if copy:
4011 if copy:
4007 skip[copy] = True
4012 skip[copy] = True
4008 continue
4013 continue
4009 pstates = matches.get(parent, {}).get(copy or fn, [])
4014 pstates = matches.get(parent, {}).get(copy or fn, [])
4010 if pstates or states:
4015 if pstates or states:
4011 r = display(fn, ctx, pstates, states)
4016 r = display(fn, ctx, pstates, states)
4012 found = found or r
4017 found = found or r
4013 if r and not opts.get('all'):
4018 if r and not opts.get('all'):
4014 skip[fn] = True
4019 skip[fn] = True
4015 if copy:
4020 if copy:
4016 skip[copy] = True
4021 skip[copy] = True
4017 del matches[rev]
4022 del matches[rev]
4018 del revfiles[rev]
4023 del revfiles[rev]
4019
4024
4020 return not found
4025 return not found
4021
4026
4022 @command('heads',
4027 @command('heads',
4023 [('r', 'rev', '',
4028 [('r', 'rev', '',
4024 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4029 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4025 ('t', 'topo', False, _('show topological heads only')),
4030 ('t', 'topo', False, _('show topological heads only')),
4026 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4031 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4027 ('c', 'closed', False, _('show normal and closed branch heads')),
4032 ('c', 'closed', False, _('show normal and closed branch heads')),
4028 ] + templateopts,
4033 ] + templateopts,
4029 _('[-ct] [-r STARTREV] [REV]...'))
4034 _('[-ct] [-r STARTREV] [REV]...'))
4030 def heads(ui, repo, *branchrevs, **opts):
4035 def heads(ui, repo, *branchrevs, **opts):
4031 """show branch heads
4036 """show branch heads
4032
4037
4033 With no arguments, show all open branch heads in the repository.
4038 With no arguments, show all open branch heads in the repository.
4034 Branch heads are changesets that have no descendants on the
4039 Branch heads are changesets that have no descendants on the
4035 same branch. They are where development generally takes place and
4040 same branch. They are where development generally takes place and
4036 are the usual targets for update and merge operations.
4041 are the usual targets for update and merge operations.
4037
4042
4038 If one or more REVs are given, only open branch heads on the
4043 If one or more REVs are given, only open branch heads on the
4039 branches associated with the specified changesets are shown. This
4044 branches associated with the specified changesets are shown. This
4040 means that you can use :hg:`heads .` to see the heads on the
4045 means that you can use :hg:`heads .` to see the heads on the
4041 currently checked-out branch.
4046 currently checked-out branch.
4042
4047
4043 If -c/--closed is specified, also show branch heads marked closed
4048 If -c/--closed is specified, also show branch heads marked closed
4044 (see :hg:`commit --close-branch`).
4049 (see :hg:`commit --close-branch`).
4045
4050
4046 If STARTREV is specified, only those heads that are descendants of
4051 If STARTREV is specified, only those heads that are descendants of
4047 STARTREV will be displayed.
4052 STARTREV will be displayed.
4048
4053
4049 If -t/--topo is specified, named branch mechanics will be ignored and only
4054 If -t/--topo is specified, named branch mechanics will be ignored and only
4050 topological heads (changesets with no children) will be shown.
4055 topological heads (changesets with no children) will be shown.
4051
4056
4052 Returns 0 if matching heads are found, 1 if not.
4057 Returns 0 if matching heads are found, 1 if not.
4053 """
4058 """
4054
4059
4055 start = None
4060 start = None
4056 if 'rev' in opts:
4061 if 'rev' in opts:
4057 start = scmutil.revsingle(repo, opts['rev'], None).node()
4062 start = scmutil.revsingle(repo, opts['rev'], None).node()
4058
4063
4059 if opts.get('topo'):
4064 if opts.get('topo'):
4060 heads = [repo[h] for h in repo.heads(start)]
4065 heads = [repo[h] for h in repo.heads(start)]
4061 else:
4066 else:
4062 heads = []
4067 heads = []
4063 for branch in repo.branchmap():
4068 for branch in repo.branchmap():
4064 heads += repo.branchheads(branch, start, opts.get('closed'))
4069 heads += repo.branchheads(branch, start, opts.get('closed'))
4065 heads = [repo[h] for h in heads]
4070 heads = [repo[h] for h in heads]
4066
4071
4067 if branchrevs:
4072 if branchrevs:
4068 branches = set(repo[br].branch() for br in branchrevs)
4073 branches = set(repo[br].branch() for br in branchrevs)
4069 heads = [h for h in heads if h.branch() in branches]
4074 heads = [h for h in heads if h.branch() in branches]
4070
4075
4071 if opts.get('active') and branchrevs:
4076 if opts.get('active') and branchrevs:
4072 dagheads = repo.heads(start)
4077 dagheads = repo.heads(start)
4073 heads = [h for h in heads if h.node() in dagheads]
4078 heads = [h for h in heads if h.node() in dagheads]
4074
4079
4075 if branchrevs:
4080 if branchrevs:
4076 haveheads = set(h.branch() for h in heads)
4081 haveheads = set(h.branch() for h in heads)
4077 if branches - haveheads:
4082 if branches - haveheads:
4078 headless = ', '.join(b for b in branches - haveheads)
4083 headless = ', '.join(b for b in branches - haveheads)
4079 msg = _('no open branch heads found on branches %s')
4084 msg = _('no open branch heads found on branches %s')
4080 if opts.get('rev'):
4085 if opts.get('rev'):
4081 msg += _(' (started at %s)') % opts['rev']
4086 msg += _(' (started at %s)') % opts['rev']
4082 ui.warn((msg + '\n') % headless)
4087 ui.warn((msg + '\n') % headless)
4083
4088
4084 if not heads:
4089 if not heads:
4085 return 1
4090 return 1
4086
4091
4087 heads = sorted(heads, key=lambda x: -x.rev())
4092 heads = sorted(heads, key=lambda x: -x.rev())
4088 displayer = cmdutil.show_changeset(ui, repo, opts)
4093 displayer = cmdutil.show_changeset(ui, repo, opts)
4089 for ctx in heads:
4094 for ctx in heads:
4090 displayer.show(ctx)
4095 displayer.show(ctx)
4091 displayer.close()
4096 displayer.close()
4092
4097
4093 @command('help',
4098 @command('help',
4094 [('e', 'extension', None, _('show only help for extensions')),
4099 [('e', 'extension', None, _('show only help for extensions')),
4095 ('c', 'command', None, _('show only help for commands')),
4100 ('c', 'command', None, _('show only help for commands')),
4096 ('k', 'keyword', None, _('show topics matching keyword')),
4101 ('k', 'keyword', None, _('show topics matching keyword')),
4097 ],
4102 ],
4098 _('[-eck] [TOPIC]'),
4103 _('[-eck] [TOPIC]'),
4099 norepo=True)
4104 norepo=True)
4100 def help_(ui, name=None, **opts):
4105 def help_(ui, name=None, **opts):
4101 """show help for a given topic or a help overview
4106 """show help for a given topic or a help overview
4102
4107
4103 With no arguments, print a list of commands with short help messages.
4108 With no arguments, print a list of commands with short help messages.
4104
4109
4105 Given a topic, extension, or command name, print help for that
4110 Given a topic, extension, or command name, print help for that
4106 topic.
4111 topic.
4107
4112
4108 Returns 0 if successful.
4113 Returns 0 if successful.
4109 """
4114 """
4110
4115
4111 textwidth = min(ui.termwidth(), 80) - 2
4116 textwidth = min(ui.termwidth(), 80) - 2
4112
4117
4113 keep = []
4118 keep = []
4114 if ui.verbose:
4119 if ui.verbose:
4115 keep.append('verbose')
4120 keep.append('verbose')
4116 if sys.platform.startswith('win'):
4121 if sys.platform.startswith('win'):
4117 keep.append('windows')
4122 keep.append('windows')
4118 elif sys.platform == 'OpenVMS':
4123 elif sys.platform == 'OpenVMS':
4119 keep.append('vms')
4124 keep.append('vms')
4120 elif sys.platform == 'plan9':
4125 elif sys.platform == 'plan9':
4121 keep.append('plan9')
4126 keep.append('plan9')
4122 else:
4127 else:
4123 keep.append('unix')
4128 keep.append('unix')
4124 keep.append(sys.platform.lower())
4129 keep.append(sys.platform.lower())
4125
4130
4126 section = None
4131 section = None
4127 if name and '.' in name:
4132 if name and '.' in name:
4128 name, section = name.split('.', 1)
4133 name, section = name.split('.', 1)
4129 section = section.lower()
4134 section = section.lower()
4130
4135
4131 text = help.help_(ui, name, **opts)
4136 text = help.help_(ui, name, **opts)
4132
4137
4133 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4138 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4134 section=section)
4139 section=section)
4135
4140
4136 # We could have been given a weird ".foo" section without a name
4141 # We could have been given a weird ".foo" section without a name
4137 # to look for, or we could have simply failed to found "foo.bar"
4142 # to look for, or we could have simply failed to found "foo.bar"
4138 # because bar isn't a section of foo
4143 # because bar isn't a section of foo
4139 if section and not (formatted and name):
4144 if section and not (formatted and name):
4140 raise error.Abort(_("help section not found"))
4145 raise error.Abort(_("help section not found"))
4141
4146
4142 if 'verbose' in pruned:
4147 if 'verbose' in pruned:
4143 keep.append('omitted')
4148 keep.append('omitted')
4144 else:
4149 else:
4145 keep.append('notomitted')
4150 keep.append('notomitted')
4146 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4151 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4147 section=section)
4152 section=section)
4148 ui.write(formatted)
4153 ui.write(formatted)
4149
4154
4150
4155
4151 @command('identify|id',
4156 @command('identify|id',
4152 [('r', 'rev', '',
4157 [('r', 'rev', '',
4153 _('identify the specified revision'), _('REV')),
4158 _('identify the specified revision'), _('REV')),
4154 ('n', 'num', None, _('show local revision number')),
4159 ('n', 'num', None, _('show local revision number')),
4155 ('i', 'id', None, _('show global revision id')),
4160 ('i', 'id', None, _('show global revision id')),
4156 ('b', 'branch', None, _('show branch')),
4161 ('b', 'branch', None, _('show branch')),
4157 ('t', 'tags', None, _('show tags')),
4162 ('t', 'tags', None, _('show tags')),
4158 ('B', 'bookmarks', None, _('show bookmarks')),
4163 ('B', 'bookmarks', None, _('show bookmarks')),
4159 ] + remoteopts,
4164 ] + remoteopts,
4160 _('[-nibtB] [-r REV] [SOURCE]'),
4165 _('[-nibtB] [-r REV] [SOURCE]'),
4161 optionalrepo=True)
4166 optionalrepo=True)
4162 def identify(ui, repo, source=None, rev=None,
4167 def identify(ui, repo, source=None, rev=None,
4163 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4168 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4164 """identify the working directory or specified revision
4169 """identify the working directory or specified revision
4165
4170
4166 Print a summary identifying the repository state at REV using one or
4171 Print a summary identifying the repository state at REV using one or
4167 two parent hash identifiers, followed by a "+" if the working
4172 two parent hash identifiers, followed by a "+" if the working
4168 directory has uncommitted changes, the branch name (if not default),
4173 directory has uncommitted changes, the branch name (if not default),
4169 a list of tags, and a list of bookmarks.
4174 a list of tags, and a list of bookmarks.
4170
4175
4171 When REV is not given, print a summary of the current state of the
4176 When REV is not given, print a summary of the current state of the
4172 repository.
4177 repository.
4173
4178
4174 Specifying a path to a repository root or Mercurial bundle will
4179 Specifying a path to a repository root or Mercurial bundle will
4175 cause lookup to operate on that repository/bundle.
4180 cause lookup to operate on that repository/bundle.
4176
4181
4177 .. container:: verbose
4182 .. container:: verbose
4178
4183
4179 Examples:
4184 Examples:
4180
4185
4181 - generate a build identifier for the working directory::
4186 - generate a build identifier for the working directory::
4182
4187
4183 hg id --id > build-id.dat
4188 hg id --id > build-id.dat
4184
4189
4185 - find the revision corresponding to a tag::
4190 - find the revision corresponding to a tag::
4186
4191
4187 hg id -n -r 1.3
4192 hg id -n -r 1.3
4188
4193
4189 - check the most recent revision of a remote repository::
4194 - check the most recent revision of a remote repository::
4190
4195
4191 hg id -r tip http://selenic.com/hg/
4196 hg id -r tip http://selenic.com/hg/
4192
4197
4193 Returns 0 if successful.
4198 Returns 0 if successful.
4194 """
4199 """
4195
4200
4196 if not repo and not source:
4201 if not repo and not source:
4197 raise error.Abort(_("there is no Mercurial repository here "
4202 raise error.Abort(_("there is no Mercurial repository here "
4198 "(.hg not found)"))
4203 "(.hg not found)"))
4199
4204
4200 if ui.debugflag:
4205 if ui.debugflag:
4201 hexfunc = hex
4206 hexfunc = hex
4202 else:
4207 else:
4203 hexfunc = short
4208 hexfunc = short
4204 default = not (num or id or branch or tags or bookmarks)
4209 default = not (num or id or branch or tags or bookmarks)
4205 output = []
4210 output = []
4206 revs = []
4211 revs = []
4207
4212
4208 if source:
4213 if source:
4209 source, branches = hg.parseurl(ui.expandpath(source))
4214 source, branches = hg.parseurl(ui.expandpath(source))
4210 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4215 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4211 repo = peer.local()
4216 repo = peer.local()
4212 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4217 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4213
4218
4214 if not repo:
4219 if not repo:
4215 if num or branch or tags:
4220 if num or branch or tags:
4216 raise error.Abort(
4221 raise error.Abort(
4217 _("can't query remote revision number, branch, or tags"))
4222 _("can't query remote revision number, branch, or tags"))
4218 if not rev and revs:
4223 if not rev and revs:
4219 rev = revs[0]
4224 rev = revs[0]
4220 if not rev:
4225 if not rev:
4221 rev = "tip"
4226 rev = "tip"
4222
4227
4223 remoterev = peer.lookup(rev)
4228 remoterev = peer.lookup(rev)
4224 if default or id:
4229 if default or id:
4225 output = [hexfunc(remoterev)]
4230 output = [hexfunc(remoterev)]
4226
4231
4227 def getbms():
4232 def getbms():
4228 bms = []
4233 bms = []
4229
4234
4230 if 'bookmarks' in peer.listkeys('namespaces'):
4235 if 'bookmarks' in peer.listkeys('namespaces'):
4231 hexremoterev = hex(remoterev)
4236 hexremoterev = hex(remoterev)
4232 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4237 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4233 if bmr == hexremoterev]
4238 if bmr == hexremoterev]
4234
4239
4235 return sorted(bms)
4240 return sorted(bms)
4236
4241
4237 if bookmarks:
4242 if bookmarks:
4238 output.extend(getbms())
4243 output.extend(getbms())
4239 elif default and not ui.quiet:
4244 elif default and not ui.quiet:
4240 # multiple bookmarks for a single parent separated by '/'
4245 # multiple bookmarks for a single parent separated by '/'
4241 bm = '/'.join(getbms())
4246 bm = '/'.join(getbms())
4242 if bm:
4247 if bm:
4243 output.append(bm)
4248 output.append(bm)
4244 else:
4249 else:
4245 ctx = scmutil.revsingle(repo, rev, None)
4250 ctx = scmutil.revsingle(repo, rev, None)
4246
4251
4247 if ctx.rev() is None:
4252 if ctx.rev() is None:
4248 ctx = repo[None]
4253 ctx = repo[None]
4249 parents = ctx.parents()
4254 parents = ctx.parents()
4250 taglist = []
4255 taglist = []
4251 for p in parents:
4256 for p in parents:
4252 taglist.extend(p.tags())
4257 taglist.extend(p.tags())
4253
4258
4254 changed = ""
4259 changed = ""
4255 if default or id or num:
4260 if default or id or num:
4256 if (any(repo.status())
4261 if (any(repo.status())
4257 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4262 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4258 changed = '+'
4263 changed = '+'
4259 if default or id:
4264 if default or id:
4260 output = ["%s%s" %
4265 output = ["%s%s" %
4261 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4266 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4262 if num:
4267 if num:
4263 output.append("%s%s" %
4268 output.append("%s%s" %
4264 ('+'.join([str(p.rev()) for p in parents]), changed))
4269 ('+'.join([str(p.rev()) for p in parents]), changed))
4265 else:
4270 else:
4266 if default or id:
4271 if default or id:
4267 output = [hexfunc(ctx.node())]
4272 output = [hexfunc(ctx.node())]
4268 if num:
4273 if num:
4269 output.append(str(ctx.rev()))
4274 output.append(str(ctx.rev()))
4270 taglist = ctx.tags()
4275 taglist = ctx.tags()
4271
4276
4272 if default and not ui.quiet:
4277 if default and not ui.quiet:
4273 b = ctx.branch()
4278 b = ctx.branch()
4274 if b != 'default':
4279 if b != 'default':
4275 output.append("(%s)" % b)
4280 output.append("(%s)" % b)
4276
4281
4277 # multiple tags for a single parent separated by '/'
4282 # multiple tags for a single parent separated by '/'
4278 t = '/'.join(taglist)
4283 t = '/'.join(taglist)
4279 if t:
4284 if t:
4280 output.append(t)
4285 output.append(t)
4281
4286
4282 # multiple bookmarks for a single parent separated by '/'
4287 # multiple bookmarks for a single parent separated by '/'
4283 bm = '/'.join(ctx.bookmarks())
4288 bm = '/'.join(ctx.bookmarks())
4284 if bm:
4289 if bm:
4285 output.append(bm)
4290 output.append(bm)
4286 else:
4291 else:
4287 if branch:
4292 if branch:
4288 output.append(ctx.branch())
4293 output.append(ctx.branch())
4289
4294
4290 if tags:
4295 if tags:
4291 output.extend(taglist)
4296 output.extend(taglist)
4292
4297
4293 if bookmarks:
4298 if bookmarks:
4294 output.extend(ctx.bookmarks())
4299 output.extend(ctx.bookmarks())
4295
4300
4296 ui.write("%s\n" % ' '.join(output))
4301 ui.write("%s\n" % ' '.join(output))
4297
4302
4298 @command('import|patch',
4303 @command('import|patch',
4299 [('p', 'strip', 1,
4304 [('p', 'strip', 1,
4300 _('directory strip option for patch. This has the same '
4305 _('directory strip option for patch. This has the same '
4301 'meaning as the corresponding patch option'), _('NUM')),
4306 'meaning as the corresponding patch option'), _('NUM')),
4302 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4307 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4303 ('e', 'edit', False, _('invoke editor on commit messages')),
4308 ('e', 'edit', False, _('invoke editor on commit messages')),
4304 ('f', 'force', None,
4309 ('f', 'force', None,
4305 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4310 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4306 ('', 'no-commit', None,
4311 ('', 'no-commit', None,
4307 _("don't commit, just update the working directory")),
4312 _("don't commit, just update the working directory")),
4308 ('', 'bypass', None,
4313 ('', 'bypass', None,
4309 _("apply patch without touching the working directory")),
4314 _("apply patch without touching the working directory")),
4310 ('', 'partial', None,
4315 ('', 'partial', None,
4311 _('commit even if some hunks fail')),
4316 _('commit even if some hunks fail')),
4312 ('', 'exact', None,
4317 ('', 'exact', None,
4313 _('apply patch to the nodes from which it was generated')),
4318 _('apply patch to the nodes from which it was generated')),
4314 ('', 'prefix', '',
4319 ('', 'prefix', '',
4315 _('apply patch to subdirectory'), _('DIR')),
4320 _('apply patch to subdirectory'), _('DIR')),
4316 ('', 'import-branch', None,
4321 ('', 'import-branch', None,
4317 _('use any branch information in patch (implied by --exact)'))] +
4322 _('use any branch information in patch (implied by --exact)'))] +
4318 commitopts + commitopts2 + similarityopts,
4323 commitopts + commitopts2 + similarityopts,
4319 _('[OPTION]... PATCH...'))
4324 _('[OPTION]... PATCH...'))
4320 def import_(ui, repo, patch1=None, *patches, **opts):
4325 def import_(ui, repo, patch1=None, *patches, **opts):
4321 """import an ordered set of patches
4326 """import an ordered set of patches
4322
4327
4323 Import a list of patches and commit them individually (unless
4328 Import a list of patches and commit them individually (unless
4324 --no-commit is specified).
4329 --no-commit is specified).
4325
4330
4326 Because import first applies changes to the working directory,
4331 Because import first applies changes to the working directory,
4327 import will abort if there are outstanding changes.
4332 import will abort if there are outstanding changes.
4328
4333
4329 You can import a patch straight from a mail message. Even patches
4334 You can import a patch straight from a mail message. Even patches
4330 as attachments work (to use the body part, it must have type
4335 as attachments work (to use the body part, it must have type
4331 text/plain or text/x-patch). From and Subject headers of email
4336 text/plain or text/x-patch). From and Subject headers of email
4332 message are used as default committer and commit message. All
4337 message are used as default committer and commit message. All
4333 text/plain body parts before first diff are added to commit
4338 text/plain body parts before first diff are added to commit
4334 message.
4339 message.
4335
4340
4336 If the imported patch was generated by :hg:`export`, user and
4341 If the imported patch was generated by :hg:`export`, user and
4337 description from patch override values from message headers and
4342 description from patch override values from message headers and
4338 body. Values given on command line with -m/--message and -u/--user
4343 body. Values given on command line with -m/--message and -u/--user
4339 override these.
4344 override these.
4340
4345
4341 If --exact is specified, import will set the working directory to
4346 If --exact is specified, import will set the working directory to
4342 the parent of each patch before applying it, and will abort if the
4347 the parent of each patch before applying it, and will abort if the
4343 resulting changeset has a different ID than the one recorded in
4348 resulting changeset has a different ID than the one recorded in
4344 the patch. This may happen due to character set problems or other
4349 the patch. This may happen due to character set problems or other
4345 deficiencies in the text patch format.
4350 deficiencies in the text patch format.
4346
4351
4347 Use --bypass to apply and commit patches directly to the
4352 Use --bypass to apply and commit patches directly to the
4348 repository, not touching the working directory. Without --exact,
4353 repository, not touching the working directory. Without --exact,
4349 patches will be applied on top of the working directory parent
4354 patches will be applied on top of the working directory parent
4350 revision.
4355 revision.
4351
4356
4352 With -s/--similarity, hg will attempt to discover renames and
4357 With -s/--similarity, hg will attempt to discover renames and
4353 copies in the patch in the same way as :hg:`addremove`.
4358 copies in the patch in the same way as :hg:`addremove`.
4354
4359
4355 Use --partial to ensure a changeset will be created from the patch
4360 Use --partial to ensure a changeset will be created from the patch
4356 even if some hunks fail to apply. Hunks that fail to apply will be
4361 even if some hunks fail to apply. Hunks that fail to apply will be
4357 written to a <target-file>.rej file. Conflicts can then be resolved
4362 written to a <target-file>.rej file. Conflicts can then be resolved
4358 by hand before :hg:`commit --amend` is run to update the created
4363 by hand before :hg:`commit --amend` is run to update the created
4359 changeset. This flag exists to let people import patches that
4364 changeset. This flag exists to let people import patches that
4360 partially apply without losing the associated metadata (author,
4365 partially apply without losing the associated metadata (author,
4361 date, description, ...). Note that when none of the hunk applies
4366 date, description, ...). Note that when none of the hunk applies
4362 cleanly, :hg:`import --partial` will create an empty changeset,
4367 cleanly, :hg:`import --partial` will create an empty changeset,
4363 importing only the patch metadata.
4368 importing only the patch metadata.
4364
4369
4365 It is possible to use external patch programs to perform the patch
4370 It is possible to use external patch programs to perform the patch
4366 by setting the ``ui.patch`` configuration option. For the default
4371 by setting the ``ui.patch`` configuration option. For the default
4367 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4372 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4368 See :hg:`help config` for more information about configuration
4373 See :hg:`help config` for more information about configuration
4369 files and how to use these options.
4374 files and how to use these options.
4370
4375
4371 To read a patch from standard input, use "-" as the patch name. If
4376 To read a patch from standard input, use "-" as the patch name. If
4372 a URL is specified, the patch will be downloaded from it.
4377 a URL is specified, the patch will be downloaded from it.
4373 See :hg:`help dates` for a list of formats valid for -d/--date.
4378 See :hg:`help dates` for a list of formats valid for -d/--date.
4374
4379
4375 .. container:: verbose
4380 .. container:: verbose
4376
4381
4377 Examples:
4382 Examples:
4378
4383
4379 - import a traditional patch from a website and detect renames::
4384 - import a traditional patch from a website and detect renames::
4380
4385
4381 hg import -s 80 http://example.com/bugfix.patch
4386 hg import -s 80 http://example.com/bugfix.patch
4382
4387
4383 - import a changeset from an hgweb server::
4388 - import a changeset from an hgweb server::
4384
4389
4385 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4390 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4386
4391
4387 - import all the patches in an Unix-style mbox::
4392 - import all the patches in an Unix-style mbox::
4388
4393
4389 hg import incoming-patches.mbox
4394 hg import incoming-patches.mbox
4390
4395
4391 - attempt to exactly restore an exported changeset (not always
4396 - attempt to exactly restore an exported changeset (not always
4392 possible)::
4397 possible)::
4393
4398
4394 hg import --exact proposed-fix.patch
4399 hg import --exact proposed-fix.patch
4395
4400
4396 - use an external tool to apply a patch which is too fuzzy for
4401 - use an external tool to apply a patch which is too fuzzy for
4397 the default internal tool.
4402 the default internal tool.
4398
4403
4399 hg import --config ui.patch="patch --merge" fuzzy.patch
4404 hg import --config ui.patch="patch --merge" fuzzy.patch
4400
4405
4401 - change the default fuzzing from 2 to a less strict 7
4406 - change the default fuzzing from 2 to a less strict 7
4402
4407
4403 hg import --config ui.fuzz=7 fuzz.patch
4408 hg import --config ui.fuzz=7 fuzz.patch
4404
4409
4405 Returns 0 on success, 1 on partial success (see --partial).
4410 Returns 0 on success, 1 on partial success (see --partial).
4406 """
4411 """
4407
4412
4408 if not patch1:
4413 if not patch1:
4409 raise error.Abort(_('need at least one patch to import'))
4414 raise error.Abort(_('need at least one patch to import'))
4410
4415
4411 patches = (patch1,) + patches
4416 patches = (patch1,) + patches
4412
4417
4413 date = opts.get('date')
4418 date = opts.get('date')
4414 if date:
4419 if date:
4415 opts['date'] = util.parsedate(date)
4420 opts['date'] = util.parsedate(date)
4416
4421
4417 update = not opts.get('bypass')
4422 update = not opts.get('bypass')
4418 if not update and opts.get('no_commit'):
4423 if not update and opts.get('no_commit'):
4419 raise error.Abort(_('cannot use --no-commit with --bypass'))
4424 raise error.Abort(_('cannot use --no-commit with --bypass'))
4420 try:
4425 try:
4421 sim = float(opts.get('similarity') or 0)
4426 sim = float(opts.get('similarity') or 0)
4422 except ValueError:
4427 except ValueError:
4423 raise error.Abort(_('similarity must be a number'))
4428 raise error.Abort(_('similarity must be a number'))
4424 if sim < 0 or sim > 100:
4429 if sim < 0 or sim > 100:
4425 raise error.Abort(_('similarity must be between 0 and 100'))
4430 raise error.Abort(_('similarity must be between 0 and 100'))
4426 if sim and not update:
4431 if sim and not update:
4427 raise error.Abort(_('cannot use --similarity with --bypass'))
4432 raise error.Abort(_('cannot use --similarity with --bypass'))
4428 if opts.get('exact') and opts.get('edit'):
4433 if opts.get('exact') and opts.get('edit'):
4429 raise error.Abort(_('cannot use --exact with --edit'))
4434 raise error.Abort(_('cannot use --exact with --edit'))
4430 if opts.get('exact') and opts.get('prefix'):
4435 if opts.get('exact') and opts.get('prefix'):
4431 raise error.Abort(_('cannot use --exact with --prefix'))
4436 raise error.Abort(_('cannot use --exact with --prefix'))
4432
4437
4433 if update:
4438 if update:
4434 cmdutil.checkunfinished(repo)
4439 cmdutil.checkunfinished(repo)
4435 if (opts.get('exact') or not opts.get('force')) and update:
4440 if (opts.get('exact') or not opts.get('force')) and update:
4436 cmdutil.bailifchanged(repo)
4441 cmdutil.bailifchanged(repo)
4437
4442
4438 base = opts["base"]
4443 base = opts["base"]
4439 wlock = dsguard = lock = tr = None
4444 wlock = dsguard = lock = tr = None
4440 msgs = []
4445 msgs = []
4441 ret = 0
4446 ret = 0
4442
4447
4443
4448
4444 try:
4449 try:
4445 try:
4450 try:
4446 wlock = repo.wlock()
4451 wlock = repo.wlock()
4447 if not opts.get('no_commit'):
4452 if not opts.get('no_commit'):
4448 lock = repo.lock()
4453 lock = repo.lock()
4449 tr = repo.transaction('import')
4454 tr = repo.transaction('import')
4450 else:
4455 else:
4451 dsguard = cmdutil.dirstateguard(repo, 'import')
4456 dsguard = cmdutil.dirstateguard(repo, 'import')
4452 parents = repo.parents()
4457 parents = repo.parents()
4453 for patchurl in patches:
4458 for patchurl in patches:
4454 if patchurl == '-':
4459 if patchurl == '-':
4455 ui.status(_('applying patch from stdin\n'))
4460 ui.status(_('applying patch from stdin\n'))
4456 patchfile = ui.fin
4461 patchfile = ui.fin
4457 patchurl = 'stdin' # for error message
4462 patchurl = 'stdin' # for error message
4458 else:
4463 else:
4459 patchurl = os.path.join(base, patchurl)
4464 patchurl = os.path.join(base, patchurl)
4460 ui.status(_('applying %s\n') % patchurl)
4465 ui.status(_('applying %s\n') % patchurl)
4461 patchfile = hg.openpath(ui, patchurl)
4466 patchfile = hg.openpath(ui, patchurl)
4462
4467
4463 haspatch = False
4468 haspatch = False
4464 for hunk in patch.split(patchfile):
4469 for hunk in patch.split(patchfile):
4465 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4470 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4466 parents, opts,
4471 parents, opts,
4467 msgs, hg.clean)
4472 msgs, hg.clean)
4468 if msg:
4473 if msg:
4469 haspatch = True
4474 haspatch = True
4470 ui.note(msg + '\n')
4475 ui.note(msg + '\n')
4471 if update or opts.get('exact'):
4476 if update or opts.get('exact'):
4472 parents = repo.parents()
4477 parents = repo.parents()
4473 else:
4478 else:
4474 parents = [repo[node]]
4479 parents = [repo[node]]
4475 if rej:
4480 if rej:
4476 ui.write_err(_("patch applied partially\n"))
4481 ui.write_err(_("patch applied partially\n"))
4477 ui.write_err(_("(fix the .rej files and run "
4482 ui.write_err(_("(fix the .rej files and run "
4478 "`hg commit --amend`)\n"))
4483 "`hg commit --amend`)\n"))
4479 ret = 1
4484 ret = 1
4480 break
4485 break
4481
4486
4482 if not haspatch:
4487 if not haspatch:
4483 raise error.Abort(_('%s: no diffs found') % patchurl)
4488 raise error.Abort(_('%s: no diffs found') % patchurl)
4484
4489
4485 if tr:
4490 if tr:
4486 tr.close()
4491 tr.close()
4487 if msgs:
4492 if msgs:
4488 repo.savecommitmessage('\n* * *\n'.join(msgs))
4493 repo.savecommitmessage('\n* * *\n'.join(msgs))
4489 if dsguard:
4494 if dsguard:
4490 dsguard.close()
4495 dsguard.close()
4491 return ret
4496 return ret
4492 finally:
4497 finally:
4493 # TODO: get rid of this meaningless try/finally enclosing.
4498 # TODO: get rid of this meaningless try/finally enclosing.
4494 # this is kept only to reduce changes in a patch.
4499 # this is kept only to reduce changes in a patch.
4495 pass
4500 pass
4496 finally:
4501 finally:
4497 if tr:
4502 if tr:
4498 tr.release()
4503 tr.release()
4499 release(lock, dsguard, wlock)
4504 release(lock, dsguard, wlock)
4500
4505
4501 @command('incoming|in',
4506 @command('incoming|in',
4502 [('f', 'force', None,
4507 [('f', 'force', None,
4503 _('run even if remote repository is unrelated')),
4508 _('run even if remote repository is unrelated')),
4504 ('n', 'newest-first', None, _('show newest record first')),
4509 ('n', 'newest-first', None, _('show newest record first')),
4505 ('', 'bundle', '',
4510 ('', 'bundle', '',
4506 _('file to store the bundles into'), _('FILE')),
4511 _('file to store the bundles into'), _('FILE')),
4507 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4512 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4508 ('B', 'bookmarks', False, _("compare bookmarks")),
4513 ('B', 'bookmarks', False, _("compare bookmarks")),
4509 ('b', 'branch', [],
4514 ('b', 'branch', [],
4510 _('a specific branch you would like to pull'), _('BRANCH')),
4515 _('a specific branch you would like to pull'), _('BRANCH')),
4511 ] + logopts + remoteopts + subrepoopts,
4516 ] + logopts + remoteopts + subrepoopts,
4512 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4517 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4513 def incoming(ui, repo, source="default", **opts):
4518 def incoming(ui, repo, source="default", **opts):
4514 """show new changesets found in source
4519 """show new changesets found in source
4515
4520
4516 Show new changesets found in the specified path/URL or the default
4521 Show new changesets found in the specified path/URL or the default
4517 pull location. These are the changesets that would have been pulled
4522 pull location. These are the changesets that would have been pulled
4518 if a pull at the time you issued this command.
4523 if a pull at the time you issued this command.
4519
4524
4520 See pull for valid source format details.
4525 See pull for valid source format details.
4521
4526
4522 .. container:: verbose
4527 .. container:: verbose
4523
4528
4524 With -B/--bookmarks, the result of bookmark comparison between
4529 With -B/--bookmarks, the result of bookmark comparison between
4525 local and remote repositories is displayed. With -v/--verbose,
4530 local and remote repositories is displayed. With -v/--verbose,
4526 status is also displayed for each bookmark like below::
4531 status is also displayed for each bookmark like below::
4527
4532
4528 BM1 01234567890a added
4533 BM1 01234567890a added
4529 BM2 1234567890ab advanced
4534 BM2 1234567890ab advanced
4530 BM3 234567890abc diverged
4535 BM3 234567890abc diverged
4531 BM4 34567890abcd changed
4536 BM4 34567890abcd changed
4532
4537
4533 The action taken locally when pulling depends on the
4538 The action taken locally when pulling depends on the
4534 status of each bookmark:
4539 status of each bookmark:
4535
4540
4536 :``added``: pull will create it
4541 :``added``: pull will create it
4537 :``advanced``: pull will update it
4542 :``advanced``: pull will update it
4538 :``diverged``: pull will create a divergent bookmark
4543 :``diverged``: pull will create a divergent bookmark
4539 :``changed``: result depends on remote changesets
4544 :``changed``: result depends on remote changesets
4540
4545
4541 From the point of view of pulling behavior, bookmark
4546 From the point of view of pulling behavior, bookmark
4542 existing only in the remote repository are treated as ``added``,
4547 existing only in the remote repository are treated as ``added``,
4543 even if it is in fact locally deleted.
4548 even if it is in fact locally deleted.
4544
4549
4545 .. container:: verbose
4550 .. container:: verbose
4546
4551
4547 For remote repository, using --bundle avoids downloading the
4552 For remote repository, using --bundle avoids downloading the
4548 changesets twice if the incoming is followed by a pull.
4553 changesets twice if the incoming is followed by a pull.
4549
4554
4550 Examples:
4555 Examples:
4551
4556
4552 - show incoming changes with patches and full description::
4557 - show incoming changes with patches and full description::
4553
4558
4554 hg incoming -vp
4559 hg incoming -vp
4555
4560
4556 - show incoming changes excluding merges, store a bundle::
4561 - show incoming changes excluding merges, store a bundle::
4557
4562
4558 hg in -vpM --bundle incoming.hg
4563 hg in -vpM --bundle incoming.hg
4559 hg pull incoming.hg
4564 hg pull incoming.hg
4560
4565
4561 - briefly list changes inside a bundle::
4566 - briefly list changes inside a bundle::
4562
4567
4563 hg in changes.hg -T "{desc|firstline}\\n"
4568 hg in changes.hg -T "{desc|firstline}\\n"
4564
4569
4565 Returns 0 if there are incoming changes, 1 otherwise.
4570 Returns 0 if there are incoming changes, 1 otherwise.
4566 """
4571 """
4567 if opts.get('graph'):
4572 if opts.get('graph'):
4568 cmdutil.checkunsupportedgraphflags([], opts)
4573 cmdutil.checkunsupportedgraphflags([], opts)
4569 def display(other, chlist, displayer):
4574 def display(other, chlist, displayer):
4570 revdag = cmdutil.graphrevs(other, chlist, opts)
4575 revdag = cmdutil.graphrevs(other, chlist, opts)
4571 showparents = [ctx.node() for ctx in repo[None].parents()]
4576 showparents = [ctx.node() for ctx in repo[None].parents()]
4572 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4577 cmdutil.displaygraph(ui, revdag, displayer, showparents,
4573 graphmod.asciiedges)
4578 graphmod.asciiedges)
4574
4579
4575 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4580 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4576 return 0
4581 return 0
4577
4582
4578 if opts.get('bundle') and opts.get('subrepos'):
4583 if opts.get('bundle') and opts.get('subrepos'):
4579 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4584 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4580
4585
4581 if opts.get('bookmarks'):
4586 if opts.get('bookmarks'):
4582 source, branches = hg.parseurl(ui.expandpath(source),
4587 source, branches = hg.parseurl(ui.expandpath(source),
4583 opts.get('branch'))
4588 opts.get('branch'))
4584 other = hg.peer(repo, opts, source)
4589 other = hg.peer(repo, opts, source)
4585 if 'bookmarks' not in other.listkeys('namespaces'):
4590 if 'bookmarks' not in other.listkeys('namespaces'):
4586 ui.warn(_("remote doesn't support bookmarks\n"))
4591 ui.warn(_("remote doesn't support bookmarks\n"))
4587 return 0
4592 return 0
4588 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4593 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4589 return bookmarks.incoming(ui, repo, other)
4594 return bookmarks.incoming(ui, repo, other)
4590
4595
4591 repo._subtoppath = ui.expandpath(source)
4596 repo._subtoppath = ui.expandpath(source)
4592 try:
4597 try:
4593 return hg.incoming(ui, repo, source, opts)
4598 return hg.incoming(ui, repo, source, opts)
4594 finally:
4599 finally:
4595 del repo._subtoppath
4600 del repo._subtoppath
4596
4601
4597
4602
4598 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4603 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4599 norepo=True)
4604 norepo=True)
4600 def init(ui, dest=".", **opts):
4605 def init(ui, dest=".", **opts):
4601 """create a new repository in the given directory
4606 """create a new repository in the given directory
4602
4607
4603 Initialize a new repository in the given directory. If the given
4608 Initialize a new repository in the given directory. If the given
4604 directory does not exist, it will be created.
4609 directory does not exist, it will be created.
4605
4610
4606 If no directory is given, the current directory is used.
4611 If no directory is given, the current directory is used.
4607
4612
4608 It is possible to specify an ``ssh://`` URL as the destination.
4613 It is possible to specify an ``ssh://`` URL as the destination.
4609 See :hg:`help urls` for more information.
4614 See :hg:`help urls` for more information.
4610
4615
4611 Returns 0 on success.
4616 Returns 0 on success.
4612 """
4617 """
4613 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4618 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4614
4619
4615 @command('locate',
4620 @command('locate',
4616 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4621 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4617 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4622 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4618 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4623 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4619 ] + walkopts,
4624 ] + walkopts,
4620 _('[OPTION]... [PATTERN]...'))
4625 _('[OPTION]... [PATTERN]...'))
4621 def locate(ui, repo, *pats, **opts):
4626 def locate(ui, repo, *pats, **opts):
4622 """locate files matching specific patterns (DEPRECATED)
4627 """locate files matching specific patterns (DEPRECATED)
4623
4628
4624 Print files under Mercurial control in the working directory whose
4629 Print files under Mercurial control in the working directory whose
4625 names match the given patterns.
4630 names match the given patterns.
4626
4631
4627 By default, this command searches all directories in the working
4632 By default, this command searches all directories in the working
4628 directory. To search just the current directory and its
4633 directory. To search just the current directory and its
4629 subdirectories, use "--include .".
4634 subdirectories, use "--include .".
4630
4635
4631 If no patterns are given to match, this command prints the names
4636 If no patterns are given to match, this command prints the names
4632 of all files under Mercurial control in the working directory.
4637 of all files under Mercurial control in the working directory.
4633
4638
4634 If you want to feed the output of this command into the "xargs"
4639 If you want to feed the output of this command into the "xargs"
4635 command, use the -0 option to both this command and "xargs". This
4640 command, use the -0 option to both this command and "xargs". This
4636 will avoid the problem of "xargs" treating single filenames that
4641 will avoid the problem of "xargs" treating single filenames that
4637 contain whitespace as multiple filenames.
4642 contain whitespace as multiple filenames.
4638
4643
4639 See :hg:`help files` for a more versatile command.
4644 See :hg:`help files` for a more versatile command.
4640
4645
4641 Returns 0 if a match is found, 1 otherwise.
4646 Returns 0 if a match is found, 1 otherwise.
4642 """
4647 """
4643 if opts.get('print0'):
4648 if opts.get('print0'):
4644 end = '\0'
4649 end = '\0'
4645 else:
4650 else:
4646 end = '\n'
4651 end = '\n'
4647 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4652 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4648
4653
4649 ret = 1
4654 ret = 1
4650 ctx = repo[rev]
4655 ctx = repo[rev]
4651 m = scmutil.match(ctx, pats, opts, default='relglob',
4656 m = scmutil.match(ctx, pats, opts, default='relglob',
4652 badfn=lambda x, y: False)
4657 badfn=lambda x, y: False)
4653
4658
4654 for abs in ctx.matches(m):
4659 for abs in ctx.matches(m):
4655 if opts.get('fullpath'):
4660 if opts.get('fullpath'):
4656 ui.write(repo.wjoin(abs), end)
4661 ui.write(repo.wjoin(abs), end)
4657 else:
4662 else:
4658 ui.write(((pats and m.rel(abs)) or abs), end)
4663 ui.write(((pats and m.rel(abs)) or abs), end)
4659 ret = 0
4664 ret = 0
4660
4665
4661 return ret
4666 return ret
4662
4667
4663 @command('^log|history',
4668 @command('^log|history',
4664 [('f', 'follow', None,
4669 [('f', 'follow', None,
4665 _('follow changeset history, or file history across copies and renames')),
4670 _('follow changeset history, or file history across copies and renames')),
4666 ('', 'follow-first', None,
4671 ('', 'follow-first', None,
4667 _('only follow the first parent of merge changesets (DEPRECATED)')),
4672 _('only follow the first parent of merge changesets (DEPRECATED)')),
4668 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4673 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4669 ('C', 'copies', None, _('show copied files')),
4674 ('C', 'copies', None, _('show copied files')),
4670 ('k', 'keyword', [],
4675 ('k', 'keyword', [],
4671 _('do case-insensitive search for a given text'), _('TEXT')),
4676 _('do case-insensitive search for a given text'), _('TEXT')),
4672 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4677 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4673 ('', 'removed', None, _('include revisions where files were removed')),
4678 ('', 'removed', None, _('include revisions where files were removed')),
4674 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4679 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4675 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4680 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4676 ('', 'only-branch', [],
4681 ('', 'only-branch', [],
4677 _('show only changesets within the given named branch (DEPRECATED)'),
4682 _('show only changesets within the given named branch (DEPRECATED)'),
4678 _('BRANCH')),
4683 _('BRANCH')),
4679 ('b', 'branch', [],
4684 ('b', 'branch', [],
4680 _('show changesets within the given named branch'), _('BRANCH')),
4685 _('show changesets within the given named branch'), _('BRANCH')),
4681 ('P', 'prune', [],
4686 ('P', 'prune', [],
4682 _('do not display revision or any of its ancestors'), _('REV')),
4687 _('do not display revision or any of its ancestors'), _('REV')),
4683 ] + logopts + walkopts,
4688 ] + logopts + walkopts,
4684 _('[OPTION]... [FILE]'),
4689 _('[OPTION]... [FILE]'),
4685 inferrepo=True)
4690 inferrepo=True)
4686 def log(ui, repo, *pats, **opts):
4691 def log(ui, repo, *pats, **opts):
4687 """show revision history of entire repository or files
4692 """show revision history of entire repository or files
4688
4693
4689 Print the revision history of the specified files or the entire
4694 Print the revision history of the specified files or the entire
4690 project.
4695 project.
4691
4696
4692 If no revision range is specified, the default is ``tip:0`` unless
4697 If no revision range is specified, the default is ``tip:0`` unless
4693 --follow is set, in which case the working directory parent is
4698 --follow is set, in which case the working directory parent is
4694 used as the starting revision.
4699 used as the starting revision.
4695
4700
4696 File history is shown without following rename or copy history of
4701 File history is shown without following rename or copy history of
4697 files. Use -f/--follow with a filename to follow history across
4702 files. Use -f/--follow with a filename to follow history across
4698 renames and copies. --follow without a filename will only show
4703 renames and copies. --follow without a filename will only show
4699 ancestors or descendants of the starting revision.
4704 ancestors or descendants of the starting revision.
4700
4705
4701 By default this command prints revision number and changeset id,
4706 By default this command prints revision number and changeset id,
4702 tags, non-trivial parents, user, date and time, and a summary for
4707 tags, non-trivial parents, user, date and time, and a summary for
4703 each commit. When the -v/--verbose switch is used, the list of
4708 each commit. When the -v/--verbose switch is used, the list of
4704 changed files and full commit message are shown.
4709 changed files and full commit message are shown.
4705
4710
4706 With --graph the revisions are shown as an ASCII art DAG with the most
4711 With --graph the revisions are shown as an ASCII art DAG with the most
4707 recent changeset at the top.
4712 recent changeset at the top.
4708 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4713 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4709 and '+' represents a fork where the changeset from the lines below is a
4714 and '+' represents a fork where the changeset from the lines below is a
4710 parent of the 'o' merge on the same line.
4715 parent of the 'o' merge on the same line.
4711
4716
4712 .. note::
4717 .. note::
4713
4718
4714 log -p/--patch may generate unexpected diff output for merge
4719 log -p/--patch may generate unexpected diff output for merge
4715 changesets, as it will only compare the merge changeset against
4720 changesets, as it will only compare the merge changeset against
4716 its first parent. Also, only files different from BOTH parents
4721 its first parent. Also, only files different from BOTH parents
4717 will appear in files:.
4722 will appear in files:.
4718
4723
4719 .. note::
4724 .. note::
4720
4725
4721 for performance reasons, log FILE may omit duplicate changes
4726 for performance reasons, log FILE may omit duplicate changes
4722 made on branches and will not show removals or mode changes. To
4727 made on branches and will not show removals or mode changes. To
4723 see all such changes, use the --removed switch.
4728 see all such changes, use the --removed switch.
4724
4729
4725 .. container:: verbose
4730 .. container:: verbose
4726
4731
4727 Some examples:
4732 Some examples:
4728
4733
4729 - changesets with full descriptions and file lists::
4734 - changesets with full descriptions and file lists::
4730
4735
4731 hg log -v
4736 hg log -v
4732
4737
4733 - changesets ancestral to the working directory::
4738 - changesets ancestral to the working directory::
4734
4739
4735 hg log -f
4740 hg log -f
4736
4741
4737 - last 10 commits on the current branch::
4742 - last 10 commits on the current branch::
4738
4743
4739 hg log -l 10 -b .
4744 hg log -l 10 -b .
4740
4745
4741 - changesets showing all modifications of a file, including removals::
4746 - changesets showing all modifications of a file, including removals::
4742
4747
4743 hg log --removed file.c
4748 hg log --removed file.c
4744
4749
4745 - all changesets that touch a directory, with diffs, excluding merges::
4750 - all changesets that touch a directory, with diffs, excluding merges::
4746
4751
4747 hg log -Mp lib/
4752 hg log -Mp lib/
4748
4753
4749 - all revision numbers that match a keyword::
4754 - all revision numbers that match a keyword::
4750
4755
4751 hg log -k bug --template "{rev}\\n"
4756 hg log -k bug --template "{rev}\\n"
4752
4757
4753 - list available log templates::
4758 - list available log templates::
4754
4759
4755 hg log -T list
4760 hg log -T list
4756
4761
4757 - check if a given changeset is included in a tagged release::
4762 - check if a given changeset is included in a tagged release::
4758
4763
4759 hg log -r "a21ccf and ancestor(1.9)"
4764 hg log -r "a21ccf and ancestor(1.9)"
4760
4765
4761 - find all changesets by some user in a date range::
4766 - find all changesets by some user in a date range::
4762
4767
4763 hg log -k alice -d "may 2008 to jul 2008"
4768 hg log -k alice -d "may 2008 to jul 2008"
4764
4769
4765 - summary of all changesets after the last tag::
4770 - summary of all changesets after the last tag::
4766
4771
4767 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4772 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
4768
4773
4769 See :hg:`help dates` for a list of formats valid for -d/--date.
4774 See :hg:`help dates` for a list of formats valid for -d/--date.
4770
4775
4771 See :hg:`help revisions` and :hg:`help revsets` for more about
4776 See :hg:`help revisions` and :hg:`help revsets` for more about
4772 specifying revisions.
4777 specifying revisions.
4773
4778
4774 See :hg:`help templates` for more about pre-packaged styles and
4779 See :hg:`help templates` for more about pre-packaged styles and
4775 specifying custom templates.
4780 specifying custom templates.
4776
4781
4777 Returns 0 on success.
4782 Returns 0 on success.
4778
4783
4779 """
4784 """
4780 if opts.get('follow') and opts.get('rev'):
4785 if opts.get('follow') and opts.get('rev'):
4781 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4786 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
4782 del opts['follow']
4787 del opts['follow']
4783
4788
4784 if opts.get('graph'):
4789 if opts.get('graph'):
4785 return cmdutil.graphlog(ui, repo, *pats, **opts)
4790 return cmdutil.graphlog(ui, repo, *pats, **opts)
4786
4791
4787 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4792 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
4788 limit = cmdutil.loglimit(opts)
4793 limit = cmdutil.loglimit(opts)
4789 count = 0
4794 count = 0
4790
4795
4791 getrenamed = None
4796 getrenamed = None
4792 if opts.get('copies'):
4797 if opts.get('copies'):
4793 endrev = None
4798 endrev = None
4794 if opts.get('rev'):
4799 if opts.get('rev'):
4795 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4800 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
4796 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4801 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
4797
4802
4798 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4803 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
4799 for rev in revs:
4804 for rev in revs:
4800 if count == limit:
4805 if count == limit:
4801 break
4806 break
4802 ctx = repo[rev]
4807 ctx = repo[rev]
4803 copies = None
4808 copies = None
4804 if getrenamed is not None and rev:
4809 if getrenamed is not None and rev:
4805 copies = []
4810 copies = []
4806 for fn in ctx.files():
4811 for fn in ctx.files():
4807 rename = getrenamed(fn, rev)
4812 rename = getrenamed(fn, rev)
4808 if rename:
4813 if rename:
4809 copies.append((fn, rename[0]))
4814 copies.append((fn, rename[0]))
4810 if filematcher:
4815 if filematcher:
4811 revmatchfn = filematcher(ctx.rev())
4816 revmatchfn = filematcher(ctx.rev())
4812 else:
4817 else:
4813 revmatchfn = None
4818 revmatchfn = None
4814 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4819 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
4815 if displayer.flush(ctx):
4820 if displayer.flush(ctx):
4816 count += 1
4821 count += 1
4817
4822
4818 displayer.close()
4823 displayer.close()
4819
4824
4820 @command('manifest',
4825 @command('manifest',
4821 [('r', 'rev', '', _('revision to display'), _('REV')),
4826 [('r', 'rev', '', _('revision to display'), _('REV')),
4822 ('', 'all', False, _("list files from all revisions"))]
4827 ('', 'all', False, _("list files from all revisions"))]
4823 + formatteropts,
4828 + formatteropts,
4824 _('[-r REV]'))
4829 _('[-r REV]'))
4825 def manifest(ui, repo, node=None, rev=None, **opts):
4830 def manifest(ui, repo, node=None, rev=None, **opts):
4826 """output the current or given revision of the project manifest
4831 """output the current or given revision of the project manifest
4827
4832
4828 Print a list of version controlled files for the given revision.
4833 Print a list of version controlled files for the given revision.
4829 If no revision is given, the first parent of the working directory
4834 If no revision is given, the first parent of the working directory
4830 is used, or the null revision if no revision is checked out.
4835 is used, or the null revision if no revision is checked out.
4831
4836
4832 With -v, print file permissions, symlink and executable bits.
4837 With -v, print file permissions, symlink and executable bits.
4833 With --debug, print file revision hashes.
4838 With --debug, print file revision hashes.
4834
4839
4835 If option --all is specified, the list of all files from all revisions
4840 If option --all is specified, the list of all files from all revisions
4836 is printed. This includes deleted and renamed files.
4841 is printed. This includes deleted and renamed files.
4837
4842
4838 Returns 0 on success.
4843 Returns 0 on success.
4839 """
4844 """
4840
4845
4841 fm = ui.formatter('manifest', opts)
4846 fm = ui.formatter('manifest', opts)
4842
4847
4843 if opts.get('all'):
4848 if opts.get('all'):
4844 if rev or node:
4849 if rev or node:
4845 raise error.Abort(_("can't specify a revision with --all"))
4850 raise error.Abort(_("can't specify a revision with --all"))
4846
4851
4847 res = []
4852 res = []
4848 prefix = "data/"
4853 prefix = "data/"
4849 suffix = ".i"
4854 suffix = ".i"
4850 plen = len(prefix)
4855 plen = len(prefix)
4851 slen = len(suffix)
4856 slen = len(suffix)
4852 lock = repo.lock()
4857 lock = repo.lock()
4853 try:
4858 try:
4854 for fn, b, size in repo.store.datafiles():
4859 for fn, b, size in repo.store.datafiles():
4855 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4860 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
4856 res.append(fn[plen:-slen])
4861 res.append(fn[plen:-slen])
4857 finally:
4862 finally:
4858 lock.release()
4863 lock.release()
4859 for f in res:
4864 for f in res:
4860 fm.startitem()
4865 fm.startitem()
4861 fm.write("path", '%s\n', f)
4866 fm.write("path", '%s\n', f)
4862 fm.end()
4867 fm.end()
4863 return
4868 return
4864
4869
4865 if rev and node:
4870 if rev and node:
4866 raise error.Abort(_("please specify just one revision"))
4871 raise error.Abort(_("please specify just one revision"))
4867
4872
4868 if not node:
4873 if not node:
4869 node = rev
4874 node = rev
4870
4875
4871 char = {'l': '@', 'x': '*', '': ''}
4876 char = {'l': '@', 'x': '*', '': ''}
4872 mode = {'l': '644', 'x': '755', '': '644'}
4877 mode = {'l': '644', 'x': '755', '': '644'}
4873 ctx = scmutil.revsingle(repo, node)
4878 ctx = scmutil.revsingle(repo, node)
4874 mf = ctx.manifest()
4879 mf = ctx.manifest()
4875 for f in ctx:
4880 for f in ctx:
4876 fm.startitem()
4881 fm.startitem()
4877 fl = ctx[f].flags()
4882 fl = ctx[f].flags()
4878 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4883 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
4879 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4884 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
4880 fm.write('path', '%s\n', f)
4885 fm.write('path', '%s\n', f)
4881 fm.end()
4886 fm.end()
4882
4887
4883 @command('^merge',
4888 @command('^merge',
4884 [('f', 'force', None,
4889 [('f', 'force', None,
4885 _('force a merge including outstanding changes (DEPRECATED)')),
4890 _('force a merge including outstanding changes (DEPRECATED)')),
4886 ('r', 'rev', '', _('revision to merge'), _('REV')),
4891 ('r', 'rev', '', _('revision to merge'), _('REV')),
4887 ('P', 'preview', None,
4892 ('P', 'preview', None,
4888 _('review revisions to merge (no merge is performed)'))
4893 _('review revisions to merge (no merge is performed)'))
4889 ] + mergetoolopts,
4894 ] + mergetoolopts,
4890 _('[-P] [-f] [[-r] REV]'))
4895 _('[-P] [-f] [[-r] REV]'))
4891 def merge(ui, repo, node=None, **opts):
4896 def merge(ui, repo, node=None, **opts):
4892 """merge another revision into working directory
4897 """merge another revision into working directory
4893
4898
4894 The current working directory is updated with all changes made in
4899 The current working directory is updated with all changes made in
4895 the requested revision since the last common predecessor revision.
4900 the requested revision since the last common predecessor revision.
4896
4901
4897 Files that changed between either parent are marked as changed for
4902 Files that changed between either parent are marked as changed for
4898 the next commit and a commit must be performed before any further
4903 the next commit and a commit must be performed before any further
4899 updates to the repository are allowed. The next commit will have
4904 updates to the repository are allowed. The next commit will have
4900 two parents.
4905 two parents.
4901
4906
4902 ``--tool`` can be used to specify the merge tool used for file
4907 ``--tool`` can be used to specify the merge tool used for file
4903 merges. It overrides the HGMERGE environment variable and your
4908 merges. It overrides the HGMERGE environment variable and your
4904 configuration files. See :hg:`help merge-tools` for options.
4909 configuration files. See :hg:`help merge-tools` for options.
4905
4910
4906 If no revision is specified, the working directory's parent is a
4911 If no revision is specified, the working directory's parent is a
4907 head revision, and the current branch contains exactly one other
4912 head revision, and the current branch contains exactly one other
4908 head, the other head is merged with by default. Otherwise, an
4913 head, the other head is merged with by default. Otherwise, an
4909 explicit revision with which to merge with must be provided.
4914 explicit revision with which to merge with must be provided.
4910
4915
4911 :hg:`resolve` must be used to resolve unresolved files.
4916 :hg:`resolve` must be used to resolve unresolved files.
4912
4917
4913 To undo an uncommitted merge, use :hg:`update --clean .` which
4918 To undo an uncommitted merge, use :hg:`update --clean .` which
4914 will check out a clean copy of the original merge parent, losing
4919 will check out a clean copy of the original merge parent, losing
4915 all changes.
4920 all changes.
4916
4921
4917 Returns 0 on success, 1 if there are unresolved files.
4922 Returns 0 on success, 1 if there are unresolved files.
4918 """
4923 """
4919
4924
4920 if opts.get('rev') and node:
4925 if opts.get('rev') and node:
4921 raise error.Abort(_("please specify just one revision"))
4926 raise error.Abort(_("please specify just one revision"))
4922 if not node:
4927 if not node:
4923 node = opts.get('rev')
4928 node = opts.get('rev')
4924
4929
4925 if node:
4930 if node:
4926 node = scmutil.revsingle(repo, node).node()
4931 node = scmutil.revsingle(repo, node).node()
4927
4932
4928 if not node:
4933 if not node:
4929 node = repo[destutil.destmerge(repo)].node()
4934 node = repo[destutil.destmerge(repo)].node()
4930
4935
4931 if opts.get('preview'):
4936 if opts.get('preview'):
4932 # find nodes that are ancestors of p2 but not of p1
4937 # find nodes that are ancestors of p2 but not of p1
4933 p1 = repo.lookup('.')
4938 p1 = repo.lookup('.')
4934 p2 = repo.lookup(node)
4939 p2 = repo.lookup(node)
4935 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4940 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
4936
4941
4937 displayer = cmdutil.show_changeset(ui, repo, opts)
4942 displayer = cmdutil.show_changeset(ui, repo, opts)
4938 for node in nodes:
4943 for node in nodes:
4939 displayer.show(repo[node])
4944 displayer.show(repo[node])
4940 displayer.close()
4945 displayer.close()
4941 return 0
4946 return 0
4942
4947
4943 try:
4948 try:
4944 # ui.forcemerge is an internal variable, do not document
4949 # ui.forcemerge is an internal variable, do not document
4945 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4950 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
4946 return hg.merge(repo, node, force=opts.get('force'))
4951 return hg.merge(repo, node, force=opts.get('force'))
4947 finally:
4952 finally:
4948 ui.setconfig('ui', 'forcemerge', '', 'merge')
4953 ui.setconfig('ui', 'forcemerge', '', 'merge')
4949
4954
4950 @command('outgoing|out',
4955 @command('outgoing|out',
4951 [('f', 'force', None, _('run even when the destination is unrelated')),
4956 [('f', 'force', None, _('run even when the destination is unrelated')),
4952 ('r', 'rev', [],
4957 ('r', 'rev', [],
4953 _('a changeset intended to be included in the destination'), _('REV')),
4958 _('a changeset intended to be included in the destination'), _('REV')),
4954 ('n', 'newest-first', None, _('show newest record first')),
4959 ('n', 'newest-first', None, _('show newest record first')),
4955 ('B', 'bookmarks', False, _('compare bookmarks')),
4960 ('B', 'bookmarks', False, _('compare bookmarks')),
4956 ('b', 'branch', [], _('a specific branch you would like to push'),
4961 ('b', 'branch', [], _('a specific branch you would like to push'),
4957 _('BRANCH')),
4962 _('BRANCH')),
4958 ] + logopts + remoteopts + subrepoopts,
4963 ] + logopts + remoteopts + subrepoopts,
4959 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4964 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
4960 def outgoing(ui, repo, dest=None, **opts):
4965 def outgoing(ui, repo, dest=None, **opts):
4961 """show changesets not found in the destination
4966 """show changesets not found in the destination
4962
4967
4963 Show changesets not found in the specified destination repository
4968 Show changesets not found in the specified destination repository
4964 or the default push location. These are the changesets that would
4969 or the default push location. These are the changesets that would
4965 be pushed if a push was requested.
4970 be pushed if a push was requested.
4966
4971
4967 See pull for details of valid destination formats.
4972 See pull for details of valid destination formats.
4968
4973
4969 .. container:: verbose
4974 .. container:: verbose
4970
4975
4971 With -B/--bookmarks, the result of bookmark comparison between
4976 With -B/--bookmarks, the result of bookmark comparison between
4972 local and remote repositories is displayed. With -v/--verbose,
4977 local and remote repositories is displayed. With -v/--verbose,
4973 status is also displayed for each bookmark like below::
4978 status is also displayed for each bookmark like below::
4974
4979
4975 BM1 01234567890a added
4980 BM1 01234567890a added
4976 BM2 deleted
4981 BM2 deleted
4977 BM3 234567890abc advanced
4982 BM3 234567890abc advanced
4978 BM4 34567890abcd diverged
4983 BM4 34567890abcd diverged
4979 BM5 4567890abcde changed
4984 BM5 4567890abcde changed
4980
4985
4981 The action taken when pushing depends on the
4986 The action taken when pushing depends on the
4982 status of each bookmark:
4987 status of each bookmark:
4983
4988
4984 :``added``: push with ``-B`` will create it
4989 :``added``: push with ``-B`` will create it
4985 :``deleted``: push with ``-B`` will delete it
4990 :``deleted``: push with ``-B`` will delete it
4986 :``advanced``: push will update it
4991 :``advanced``: push will update it
4987 :``diverged``: push with ``-B`` will update it
4992 :``diverged``: push with ``-B`` will update it
4988 :``changed``: push with ``-B`` will update it
4993 :``changed``: push with ``-B`` will update it
4989
4994
4990 From the point of view of pushing behavior, bookmarks
4995 From the point of view of pushing behavior, bookmarks
4991 existing only in the remote repository are treated as
4996 existing only in the remote repository are treated as
4992 ``deleted``, even if it is in fact added remotely.
4997 ``deleted``, even if it is in fact added remotely.
4993
4998
4994 Returns 0 if there are outgoing changes, 1 otherwise.
4999 Returns 0 if there are outgoing changes, 1 otherwise.
4995 """
5000 """
4996 if opts.get('graph'):
5001 if opts.get('graph'):
4997 cmdutil.checkunsupportedgraphflags([], opts)
5002 cmdutil.checkunsupportedgraphflags([], opts)
4998 o, other = hg._outgoing(ui, repo, dest, opts)
5003 o, other = hg._outgoing(ui, repo, dest, opts)
4999 if not o:
5004 if not o:
5000 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5005 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5001 return
5006 return
5002
5007
5003 revdag = cmdutil.graphrevs(repo, o, opts)
5008 revdag = cmdutil.graphrevs(repo, o, opts)
5004 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5009 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5005 showparents = [ctx.node() for ctx in repo[None].parents()]
5010 showparents = [ctx.node() for ctx in repo[None].parents()]
5006 cmdutil.displaygraph(ui, revdag, displayer, showparents,
5011 cmdutil.displaygraph(ui, revdag, displayer, showparents,
5007 graphmod.asciiedges)
5012 graphmod.asciiedges)
5008 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5013 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5009 return 0
5014 return 0
5010
5015
5011 if opts.get('bookmarks'):
5016 if opts.get('bookmarks'):
5012 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5017 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5013 dest, branches = hg.parseurl(dest, opts.get('branch'))
5018 dest, branches = hg.parseurl(dest, opts.get('branch'))
5014 other = hg.peer(repo, opts, dest)
5019 other = hg.peer(repo, opts, dest)
5015 if 'bookmarks' not in other.listkeys('namespaces'):
5020 if 'bookmarks' not in other.listkeys('namespaces'):
5016 ui.warn(_("remote doesn't support bookmarks\n"))
5021 ui.warn(_("remote doesn't support bookmarks\n"))
5017 return 0
5022 return 0
5018 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5023 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5019 return bookmarks.outgoing(ui, repo, other)
5024 return bookmarks.outgoing(ui, repo, other)
5020
5025
5021 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5026 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5022 try:
5027 try:
5023 return hg.outgoing(ui, repo, dest, opts)
5028 return hg.outgoing(ui, repo, dest, opts)
5024 finally:
5029 finally:
5025 del repo._subtoppath
5030 del repo._subtoppath
5026
5031
5027 @command('parents',
5032 @command('parents',
5028 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5033 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5029 ] + templateopts,
5034 ] + templateopts,
5030 _('[-r REV] [FILE]'),
5035 _('[-r REV] [FILE]'),
5031 inferrepo=True)
5036 inferrepo=True)
5032 def parents(ui, repo, file_=None, **opts):
5037 def parents(ui, repo, file_=None, **opts):
5033 """show the parents of the working directory or revision (DEPRECATED)
5038 """show the parents of the working directory or revision (DEPRECATED)
5034
5039
5035 Print the working directory's parent revisions. If a revision is
5040 Print the working directory's parent revisions. If a revision is
5036 given via -r/--rev, the parent of that revision will be printed.
5041 given via -r/--rev, the parent of that revision will be printed.
5037 If a file argument is given, the revision in which the file was
5042 If a file argument is given, the revision in which the file was
5038 last changed (before the working directory revision or the
5043 last changed (before the working directory revision or the
5039 argument to --rev if given) is printed.
5044 argument to --rev if given) is printed.
5040
5045
5041 See :hg:`summary` and :hg:`help revsets` for related information.
5046 See :hg:`summary` and :hg:`help revsets` for related information.
5042
5047
5043 Returns 0 on success.
5048 Returns 0 on success.
5044 """
5049 """
5045
5050
5046 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5051 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5047
5052
5048 if file_:
5053 if file_:
5049 m = scmutil.match(ctx, (file_,), opts)
5054 m = scmutil.match(ctx, (file_,), opts)
5050 if m.anypats() or len(m.files()) != 1:
5055 if m.anypats() or len(m.files()) != 1:
5051 raise error.Abort(_('can only specify an explicit filename'))
5056 raise error.Abort(_('can only specify an explicit filename'))
5052 file_ = m.files()[0]
5057 file_ = m.files()[0]
5053 filenodes = []
5058 filenodes = []
5054 for cp in ctx.parents():
5059 for cp in ctx.parents():
5055 if not cp:
5060 if not cp:
5056 continue
5061 continue
5057 try:
5062 try:
5058 filenodes.append(cp.filenode(file_))
5063 filenodes.append(cp.filenode(file_))
5059 except error.LookupError:
5064 except error.LookupError:
5060 pass
5065 pass
5061 if not filenodes:
5066 if not filenodes:
5062 raise error.Abort(_("'%s' not found in manifest!") % file_)
5067 raise error.Abort(_("'%s' not found in manifest!") % file_)
5063 p = []
5068 p = []
5064 for fn in filenodes:
5069 for fn in filenodes:
5065 fctx = repo.filectx(file_, fileid=fn)
5070 fctx = repo.filectx(file_, fileid=fn)
5066 p.append(fctx.node())
5071 p.append(fctx.node())
5067 else:
5072 else:
5068 p = [cp.node() for cp in ctx.parents()]
5073 p = [cp.node() for cp in ctx.parents()]
5069
5074
5070 displayer = cmdutil.show_changeset(ui, repo, opts)
5075 displayer = cmdutil.show_changeset(ui, repo, opts)
5071 for n in p:
5076 for n in p:
5072 if n != nullid:
5077 if n != nullid:
5073 displayer.show(repo[n])
5078 displayer.show(repo[n])
5074 displayer.close()
5079 displayer.close()
5075
5080
5076 @command('paths', [], _('[NAME]'), optionalrepo=True)
5081 @command('paths', [], _('[NAME]'), optionalrepo=True)
5077 def paths(ui, repo, search=None):
5082 def paths(ui, repo, search=None):
5078 """show aliases for remote repositories
5083 """show aliases for remote repositories
5079
5084
5080 Show definition of symbolic path name NAME. If no name is given,
5085 Show definition of symbolic path name NAME. If no name is given,
5081 show definition of all available names.
5086 show definition of all available names.
5082
5087
5083 Option -q/--quiet suppresses all output when searching for NAME
5088 Option -q/--quiet suppresses all output when searching for NAME
5084 and shows only the path names when listing all definitions.
5089 and shows only the path names when listing all definitions.
5085
5090
5086 Path names are defined in the [paths] section of your
5091 Path names are defined in the [paths] section of your
5087 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5092 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5088 repository, ``.hg/hgrc`` is used, too.
5093 repository, ``.hg/hgrc`` is used, too.
5089
5094
5090 The path names ``default`` and ``default-push`` have a special
5095 The path names ``default`` and ``default-push`` have a special
5091 meaning. When performing a push or pull operation, they are used
5096 meaning. When performing a push or pull operation, they are used
5092 as fallbacks if no location is specified on the command-line.
5097 as fallbacks if no location is specified on the command-line.
5093 When ``default-push`` is set, it will be used for push and
5098 When ``default-push`` is set, it will be used for push and
5094 ``default`` will be used for pull; otherwise ``default`` is used
5099 ``default`` will be used for pull; otherwise ``default`` is used
5095 as the fallback for both. When cloning a repository, the clone
5100 as the fallback for both. When cloning a repository, the clone
5096 source is written as ``default`` in ``.hg/hgrc``. Note that
5101 source is written as ``default`` in ``.hg/hgrc``. Note that
5097 ``default`` and ``default-push`` apply to all inbound (e.g.
5102 ``default`` and ``default-push`` apply to all inbound (e.g.
5098 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
5103 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
5099 :hg:`bundle`) operations.
5104 :hg:`bundle`) operations.
5100
5105
5101 See :hg:`help urls` for more information.
5106 See :hg:`help urls` for more information.
5102
5107
5103 Returns 0 on success.
5108 Returns 0 on success.
5104 """
5109 """
5105 if search:
5110 if search:
5106 for name, path in sorted(ui.paths.iteritems()):
5111 for name, path in sorted(ui.paths.iteritems()):
5107 if name == search:
5112 if name == search:
5108 ui.status("%s\n" % util.hidepassword(path.loc))
5113 ui.status("%s\n" % util.hidepassword(path.loc))
5109 return
5114 return
5110 if not ui.quiet:
5115 if not ui.quiet:
5111 ui.warn(_("not found!\n"))
5116 ui.warn(_("not found!\n"))
5112 return 1
5117 return 1
5113 else:
5118 else:
5114 for name, path in sorted(ui.paths.iteritems()):
5119 for name, path in sorted(ui.paths.iteritems()):
5115 if ui.quiet:
5120 if ui.quiet:
5116 ui.write("%s\n" % name)
5121 ui.write("%s\n" % name)
5117 else:
5122 else:
5118 ui.write("%s = %s\n" % (name,
5123 ui.write("%s = %s\n" % (name,
5119 util.hidepassword(path.loc)))
5124 util.hidepassword(path.loc)))
5120
5125
5121 @command('phase',
5126 @command('phase',
5122 [('p', 'public', False, _('set changeset phase to public')),
5127 [('p', 'public', False, _('set changeset phase to public')),
5123 ('d', 'draft', False, _('set changeset phase to draft')),
5128 ('d', 'draft', False, _('set changeset phase to draft')),
5124 ('s', 'secret', False, _('set changeset phase to secret')),
5129 ('s', 'secret', False, _('set changeset phase to secret')),
5125 ('f', 'force', False, _('allow to move boundary backward')),
5130 ('f', 'force', False, _('allow to move boundary backward')),
5126 ('r', 'rev', [], _('target revision'), _('REV')),
5131 ('r', 'rev', [], _('target revision'), _('REV')),
5127 ],
5132 ],
5128 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5133 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5129 def phase(ui, repo, *revs, **opts):
5134 def phase(ui, repo, *revs, **opts):
5130 """set or show the current phase name
5135 """set or show the current phase name
5131
5136
5132 With no argument, show the phase name of the current revision(s).
5137 With no argument, show the phase name of the current revision(s).
5133
5138
5134 With one of -p/--public, -d/--draft or -s/--secret, change the
5139 With one of -p/--public, -d/--draft or -s/--secret, change the
5135 phase value of the specified revisions.
5140 phase value of the specified revisions.
5136
5141
5137 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5142 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5138 lower phase to an higher phase. Phases are ordered as follows::
5143 lower phase to an higher phase. Phases are ordered as follows::
5139
5144
5140 public < draft < secret
5145 public < draft < secret
5141
5146
5142 Returns 0 on success, 1 if some phases could not be changed.
5147 Returns 0 on success, 1 if some phases could not be changed.
5143
5148
5144 (For more information about the phases concept, see :hg:`help phases`.)
5149 (For more information about the phases concept, see :hg:`help phases`.)
5145 """
5150 """
5146 # search for a unique phase argument
5151 # search for a unique phase argument
5147 targetphase = None
5152 targetphase = None
5148 for idx, name in enumerate(phases.phasenames):
5153 for idx, name in enumerate(phases.phasenames):
5149 if opts[name]:
5154 if opts[name]:
5150 if targetphase is not None:
5155 if targetphase is not None:
5151 raise error.Abort(_('only one phase can be specified'))
5156 raise error.Abort(_('only one phase can be specified'))
5152 targetphase = idx
5157 targetphase = idx
5153
5158
5154 # look for specified revision
5159 # look for specified revision
5155 revs = list(revs)
5160 revs = list(revs)
5156 revs.extend(opts['rev'])
5161 revs.extend(opts['rev'])
5157 if not revs:
5162 if not revs:
5158 # display both parents as the second parent phase can influence
5163 # display both parents as the second parent phase can influence
5159 # the phase of a merge commit
5164 # the phase of a merge commit
5160 revs = [c.rev() for c in repo[None].parents()]
5165 revs = [c.rev() for c in repo[None].parents()]
5161
5166
5162 revs = scmutil.revrange(repo, revs)
5167 revs = scmutil.revrange(repo, revs)
5163
5168
5164 lock = None
5169 lock = None
5165 ret = 0
5170 ret = 0
5166 if targetphase is None:
5171 if targetphase is None:
5167 # display
5172 # display
5168 for r in revs:
5173 for r in revs:
5169 ctx = repo[r]
5174 ctx = repo[r]
5170 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5175 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5171 else:
5176 else:
5172 tr = None
5177 tr = None
5173 lock = repo.lock()
5178 lock = repo.lock()
5174 try:
5179 try:
5175 tr = repo.transaction("phase")
5180 tr = repo.transaction("phase")
5176 # set phase
5181 # set phase
5177 if not revs:
5182 if not revs:
5178 raise error.Abort(_('empty revision set'))
5183 raise error.Abort(_('empty revision set'))
5179 nodes = [repo[r].node() for r in revs]
5184 nodes = [repo[r].node() for r in revs]
5180 # moving revision from public to draft may hide them
5185 # moving revision from public to draft may hide them
5181 # We have to check result on an unfiltered repository
5186 # We have to check result on an unfiltered repository
5182 unfi = repo.unfiltered()
5187 unfi = repo.unfiltered()
5183 getphase = unfi._phasecache.phase
5188 getphase = unfi._phasecache.phase
5184 olddata = [getphase(unfi, r) for r in unfi]
5189 olddata = [getphase(unfi, r) for r in unfi]
5185 phases.advanceboundary(repo, tr, targetphase, nodes)
5190 phases.advanceboundary(repo, tr, targetphase, nodes)
5186 if opts['force']:
5191 if opts['force']:
5187 phases.retractboundary(repo, tr, targetphase, nodes)
5192 phases.retractboundary(repo, tr, targetphase, nodes)
5188 tr.close()
5193 tr.close()
5189 finally:
5194 finally:
5190 if tr is not None:
5195 if tr is not None:
5191 tr.release()
5196 tr.release()
5192 lock.release()
5197 lock.release()
5193 getphase = unfi._phasecache.phase
5198 getphase = unfi._phasecache.phase
5194 newdata = [getphase(unfi, r) for r in unfi]
5199 newdata = [getphase(unfi, r) for r in unfi]
5195 changes = sum(newdata[r] != olddata[r] for r in unfi)
5200 changes = sum(newdata[r] != olddata[r] for r in unfi)
5196 cl = unfi.changelog
5201 cl = unfi.changelog
5197 rejected = [n for n in nodes
5202 rejected = [n for n in nodes
5198 if newdata[cl.rev(n)] < targetphase]
5203 if newdata[cl.rev(n)] < targetphase]
5199 if rejected:
5204 if rejected:
5200 ui.warn(_('cannot move %i changesets to a higher '
5205 ui.warn(_('cannot move %i changesets to a higher '
5201 'phase, use --force\n') % len(rejected))
5206 'phase, use --force\n') % len(rejected))
5202 ret = 1
5207 ret = 1
5203 if changes:
5208 if changes:
5204 msg = _('phase changed for %i changesets\n') % changes
5209 msg = _('phase changed for %i changesets\n') % changes
5205 if ret:
5210 if ret:
5206 ui.status(msg)
5211 ui.status(msg)
5207 else:
5212 else:
5208 ui.note(msg)
5213 ui.note(msg)
5209 else:
5214 else:
5210 ui.warn(_('no phases changed\n'))
5215 ui.warn(_('no phases changed\n'))
5211 return ret
5216 return ret
5212
5217
5213 def postincoming(ui, repo, modheads, optupdate, checkout):
5218 def postincoming(ui, repo, modheads, optupdate, checkout):
5214 if modheads == 0:
5219 if modheads == 0:
5215 return
5220 return
5216 if optupdate:
5221 if optupdate:
5217 try:
5222 try:
5218 brev = checkout
5223 brev = checkout
5219 movemarkfrom = None
5224 movemarkfrom = None
5220 if not checkout:
5225 if not checkout:
5221 updata = destutil.destupdate(repo)
5226 updata = destutil.destupdate(repo)
5222 checkout, movemarkfrom, brev = updata
5227 checkout, movemarkfrom, brev = updata
5223 ret = hg.update(repo, checkout)
5228 ret = hg.update(repo, checkout)
5224 except error.UpdateAbort as inst:
5229 except error.UpdateAbort as inst:
5225 ui.warn(_("not updating: %s\n") % str(inst))
5230 ui.warn(_("not updating: %s\n") % str(inst))
5226 if inst.hint:
5231 if inst.hint:
5227 ui.warn(_("(%s)\n") % inst.hint)
5232 ui.warn(_("(%s)\n") % inst.hint)
5228 return 0
5233 return 0
5229 if not ret and not checkout:
5234 if not ret and not checkout:
5230 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5235 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5231 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5236 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5232 return ret
5237 return ret
5233 if modheads > 1:
5238 if modheads > 1:
5234 currentbranchheads = len(repo.branchheads())
5239 currentbranchheads = len(repo.branchheads())
5235 if currentbranchheads == modheads:
5240 if currentbranchheads == modheads:
5236 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5241 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5237 elif currentbranchheads > 1:
5242 elif currentbranchheads > 1:
5238 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5243 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5239 "merge)\n"))
5244 "merge)\n"))
5240 else:
5245 else:
5241 ui.status(_("(run 'hg heads' to see heads)\n"))
5246 ui.status(_("(run 'hg heads' to see heads)\n"))
5242 else:
5247 else:
5243 ui.status(_("(run 'hg update' to get a working copy)\n"))
5248 ui.status(_("(run 'hg update' to get a working copy)\n"))
5244
5249
5245 @command('^pull',
5250 @command('^pull',
5246 [('u', 'update', None,
5251 [('u', 'update', None,
5247 _('update to new branch head if changesets were pulled')),
5252 _('update to new branch head if changesets were pulled')),
5248 ('f', 'force', None, _('run even when remote repository is unrelated')),
5253 ('f', 'force', None, _('run even when remote repository is unrelated')),
5249 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5254 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5250 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5255 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5251 ('b', 'branch', [], _('a specific branch you would like to pull'),
5256 ('b', 'branch', [], _('a specific branch you would like to pull'),
5252 _('BRANCH')),
5257 _('BRANCH')),
5253 ] + remoteopts,
5258 ] + remoteopts,
5254 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5259 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5255 def pull(ui, repo, source="default", **opts):
5260 def pull(ui, repo, source="default", **opts):
5256 """pull changes from the specified source
5261 """pull changes from the specified source
5257
5262
5258 Pull changes from a remote repository to a local one.
5263 Pull changes from a remote repository to a local one.
5259
5264
5260 This finds all changes from the repository at the specified path
5265 This finds all changes from the repository at the specified path
5261 or URL and adds them to a local repository (the current one unless
5266 or URL and adds them to a local repository (the current one unless
5262 -R is specified). By default, this does not update the copy of the
5267 -R is specified). By default, this does not update the copy of the
5263 project in the working directory.
5268 project in the working directory.
5264
5269
5265 Use :hg:`incoming` if you want to see what would have been added
5270 Use :hg:`incoming` if you want to see what would have been added
5266 by a pull at the time you issued this command. If you then decide
5271 by a pull at the time you issued this command. If you then decide
5267 to add those changes to the repository, you should use :hg:`pull
5272 to add those changes to the repository, you should use :hg:`pull
5268 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5273 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5269
5274
5270 If SOURCE is omitted, the 'default' path will be used.
5275 If SOURCE is omitted, the 'default' path will be used.
5271 See :hg:`help urls` for more information.
5276 See :hg:`help urls` for more information.
5272
5277
5273 Returns 0 on success, 1 if an update had unresolved files.
5278 Returns 0 on success, 1 if an update had unresolved files.
5274 """
5279 """
5275 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5280 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5276 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5281 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5277 other = hg.peer(repo, opts, source)
5282 other = hg.peer(repo, opts, source)
5278 try:
5283 try:
5279 revs, checkout = hg.addbranchrevs(repo, other, branches,
5284 revs, checkout = hg.addbranchrevs(repo, other, branches,
5280 opts.get('rev'))
5285 opts.get('rev'))
5281
5286
5282
5287
5283 pullopargs = {}
5288 pullopargs = {}
5284 if opts.get('bookmark'):
5289 if opts.get('bookmark'):
5285 if not revs:
5290 if not revs:
5286 revs = []
5291 revs = []
5287 # The list of bookmark used here is not the one used to actually
5292 # The list of bookmark used here is not the one used to actually
5288 # update the bookmark name. This can result in the revision pulled
5293 # update the bookmark name. This can result in the revision pulled
5289 # not ending up with the name of the bookmark because of a race
5294 # not ending up with the name of the bookmark because of a race
5290 # condition on the server. (See issue 4689 for details)
5295 # condition on the server. (See issue 4689 for details)
5291 remotebookmarks = other.listkeys('bookmarks')
5296 remotebookmarks = other.listkeys('bookmarks')
5292 pullopargs['remotebookmarks'] = remotebookmarks
5297 pullopargs['remotebookmarks'] = remotebookmarks
5293 for b in opts['bookmark']:
5298 for b in opts['bookmark']:
5294 if b not in remotebookmarks:
5299 if b not in remotebookmarks:
5295 raise error.Abort(_('remote bookmark %s not found!') % b)
5300 raise error.Abort(_('remote bookmark %s not found!') % b)
5296 revs.append(remotebookmarks[b])
5301 revs.append(remotebookmarks[b])
5297
5302
5298 if revs:
5303 if revs:
5299 try:
5304 try:
5300 # When 'rev' is a bookmark name, we cannot guarantee that it
5305 # When 'rev' is a bookmark name, we cannot guarantee that it
5301 # will be updated with that name because of a race condition
5306 # will be updated with that name because of a race condition
5302 # server side. (See issue 4689 for details)
5307 # server side. (See issue 4689 for details)
5303 oldrevs = revs
5308 oldrevs = revs
5304 revs = [] # actually, nodes
5309 revs = [] # actually, nodes
5305 for r in oldrevs:
5310 for r in oldrevs:
5306 node = other.lookup(r)
5311 node = other.lookup(r)
5307 revs.append(node)
5312 revs.append(node)
5308 if r == checkout:
5313 if r == checkout:
5309 checkout = node
5314 checkout = node
5310 except error.CapabilityError:
5315 except error.CapabilityError:
5311 err = _("other repository doesn't support revision lookup, "
5316 err = _("other repository doesn't support revision lookup, "
5312 "so a rev cannot be specified.")
5317 "so a rev cannot be specified.")
5313 raise error.Abort(err)
5318 raise error.Abort(err)
5314
5319
5315 pullopargs.update(opts.get('opargs', {}))
5320 pullopargs.update(opts.get('opargs', {}))
5316 modheads = exchange.pull(repo, other, heads=revs,
5321 modheads = exchange.pull(repo, other, heads=revs,
5317 force=opts.get('force'),
5322 force=opts.get('force'),
5318 bookmarks=opts.get('bookmark', ()),
5323 bookmarks=opts.get('bookmark', ()),
5319 opargs=pullopargs).cgresult
5324 opargs=pullopargs).cgresult
5320 if checkout:
5325 if checkout:
5321 checkout = str(repo.changelog.rev(checkout))
5326 checkout = str(repo.changelog.rev(checkout))
5322 repo._subtoppath = source
5327 repo._subtoppath = source
5323 try:
5328 try:
5324 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5329 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5325
5330
5326 finally:
5331 finally:
5327 del repo._subtoppath
5332 del repo._subtoppath
5328
5333
5329 finally:
5334 finally:
5330 other.close()
5335 other.close()
5331 return ret
5336 return ret
5332
5337
5333 @command('^push',
5338 @command('^push',
5334 [('f', 'force', None, _('force push')),
5339 [('f', 'force', None, _('force push')),
5335 ('r', 'rev', [],
5340 ('r', 'rev', [],
5336 _('a changeset intended to be included in the destination'),
5341 _('a changeset intended to be included in the destination'),
5337 _('REV')),
5342 _('REV')),
5338 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5343 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5339 ('b', 'branch', [],
5344 ('b', 'branch', [],
5340 _('a specific branch you would like to push'), _('BRANCH')),
5345 _('a specific branch you would like to push'), _('BRANCH')),
5341 ('', 'new-branch', False, _('allow pushing a new branch')),
5346 ('', 'new-branch', False, _('allow pushing a new branch')),
5342 ] + remoteopts,
5347 ] + remoteopts,
5343 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5348 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5344 def push(ui, repo, dest=None, **opts):
5349 def push(ui, repo, dest=None, **opts):
5345 """push changes to the specified destination
5350 """push changes to the specified destination
5346
5351
5347 Push changesets from the local repository to the specified
5352 Push changesets from the local repository to the specified
5348 destination.
5353 destination.
5349
5354
5350 This operation is symmetrical to pull: it is identical to a pull
5355 This operation is symmetrical to pull: it is identical to a pull
5351 in the destination repository from the current one.
5356 in the destination repository from the current one.
5352
5357
5353 By default, push will not allow creation of new heads at the
5358 By default, push will not allow creation of new heads at the
5354 destination, since multiple heads would make it unclear which head
5359 destination, since multiple heads would make it unclear which head
5355 to use. In this situation, it is recommended to pull and merge
5360 to use. In this situation, it is recommended to pull and merge
5356 before pushing.
5361 before pushing.
5357
5362
5358 Use --new-branch if you want to allow push to create a new named
5363 Use --new-branch if you want to allow push to create a new named
5359 branch that is not present at the destination. This allows you to
5364 branch that is not present at the destination. This allows you to
5360 only create a new branch without forcing other changes.
5365 only create a new branch without forcing other changes.
5361
5366
5362 .. note::
5367 .. note::
5363
5368
5364 Extra care should be taken with the -f/--force option,
5369 Extra care should be taken with the -f/--force option,
5365 which will push all new heads on all branches, an action which will
5370 which will push all new heads on all branches, an action which will
5366 almost always cause confusion for collaborators.
5371 almost always cause confusion for collaborators.
5367
5372
5368 If -r/--rev is used, the specified revision and all its ancestors
5373 If -r/--rev is used, the specified revision and all its ancestors
5369 will be pushed to the remote repository.
5374 will be pushed to the remote repository.
5370
5375
5371 If -B/--bookmark is used, the specified bookmarked revision, its
5376 If -B/--bookmark is used, the specified bookmarked revision, its
5372 ancestors, and the bookmark will be pushed to the remote
5377 ancestors, and the bookmark will be pushed to the remote
5373 repository.
5378 repository.
5374
5379
5375 Please see :hg:`help urls` for important details about ``ssh://``
5380 Please see :hg:`help urls` for important details about ``ssh://``
5376 URLs. If DESTINATION is omitted, a default path will be used.
5381 URLs. If DESTINATION is omitted, a default path will be used.
5377
5382
5378 Returns 0 if push was successful, 1 if nothing to push.
5383 Returns 0 if push was successful, 1 if nothing to push.
5379 """
5384 """
5380
5385
5381 if opts.get('bookmark'):
5386 if opts.get('bookmark'):
5382 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5387 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5383 for b in opts['bookmark']:
5388 for b in opts['bookmark']:
5384 # translate -B options to -r so changesets get pushed
5389 # translate -B options to -r so changesets get pushed
5385 if b in repo._bookmarks:
5390 if b in repo._bookmarks:
5386 opts.setdefault('rev', []).append(b)
5391 opts.setdefault('rev', []).append(b)
5387 else:
5392 else:
5388 # if we try to push a deleted bookmark, translate it to null
5393 # if we try to push a deleted bookmark, translate it to null
5389 # this lets simultaneous -r, -b options continue working
5394 # this lets simultaneous -r, -b options continue working
5390 opts.setdefault('rev', []).append("null")
5395 opts.setdefault('rev', []).append("null")
5391
5396
5392 path = ui.paths.getpath(dest, default='default')
5397 path = ui.paths.getpath(dest, default='default')
5393 if not path:
5398 if not path:
5394 raise error.Abort(_('default repository not configured!'),
5399 raise error.Abort(_('default repository not configured!'),
5395 hint=_('see the "path" section in "hg help config"'))
5400 hint=_('see the "path" section in "hg help config"'))
5396 dest, branches = path.pushloc, (path.branch, opts.get('branch') or [])
5401 dest, branches = path.pushloc, (path.branch, opts.get('branch') or [])
5397 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5402 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5398 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5403 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5399 other = hg.peer(repo, opts, dest)
5404 other = hg.peer(repo, opts, dest)
5400
5405
5401 if revs:
5406 if revs:
5402 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5407 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5403 if not revs:
5408 if not revs:
5404 raise error.Abort(_("specified revisions evaluate to an empty set"),
5409 raise error.Abort(_("specified revisions evaluate to an empty set"),
5405 hint=_("use different revision arguments"))
5410 hint=_("use different revision arguments"))
5406
5411
5407 repo._subtoppath = dest
5412 repo._subtoppath = dest
5408 try:
5413 try:
5409 # push subrepos depth-first for coherent ordering
5414 # push subrepos depth-first for coherent ordering
5410 c = repo['']
5415 c = repo['']
5411 subs = c.substate # only repos that are committed
5416 subs = c.substate # only repos that are committed
5412 for s in sorted(subs):
5417 for s in sorted(subs):
5413 result = c.sub(s).push(opts)
5418 result = c.sub(s).push(opts)
5414 if result == 0:
5419 if result == 0:
5415 return not result
5420 return not result
5416 finally:
5421 finally:
5417 del repo._subtoppath
5422 del repo._subtoppath
5418 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5423 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5419 newbranch=opts.get('new_branch'),
5424 newbranch=opts.get('new_branch'),
5420 bookmarks=opts.get('bookmark', ()),
5425 bookmarks=opts.get('bookmark', ()),
5421 opargs=opts.get('opargs'))
5426 opargs=opts.get('opargs'))
5422
5427
5423 result = not pushop.cgresult
5428 result = not pushop.cgresult
5424
5429
5425 if pushop.bkresult is not None:
5430 if pushop.bkresult is not None:
5426 if pushop.bkresult == 2:
5431 if pushop.bkresult == 2:
5427 result = 2
5432 result = 2
5428 elif not result and pushop.bkresult:
5433 elif not result and pushop.bkresult:
5429 result = 2
5434 result = 2
5430
5435
5431 return result
5436 return result
5432
5437
5433 @command('recover', [])
5438 @command('recover', [])
5434 def recover(ui, repo):
5439 def recover(ui, repo):
5435 """roll back an interrupted transaction
5440 """roll back an interrupted transaction
5436
5441
5437 Recover from an interrupted commit or pull.
5442 Recover from an interrupted commit or pull.
5438
5443
5439 This command tries to fix the repository status after an
5444 This command tries to fix the repository status after an
5440 interrupted operation. It should only be necessary when Mercurial
5445 interrupted operation. It should only be necessary when Mercurial
5441 suggests it.
5446 suggests it.
5442
5447
5443 Returns 0 if successful, 1 if nothing to recover or verify fails.
5448 Returns 0 if successful, 1 if nothing to recover or verify fails.
5444 """
5449 """
5445 if repo.recover():
5450 if repo.recover():
5446 return hg.verify(repo)
5451 return hg.verify(repo)
5447 return 1
5452 return 1
5448
5453
5449 @command('^remove|rm',
5454 @command('^remove|rm',
5450 [('A', 'after', None, _('record delete for missing files')),
5455 [('A', 'after', None, _('record delete for missing files')),
5451 ('f', 'force', None,
5456 ('f', 'force', None,
5452 _('remove (and delete) file even if added or modified')),
5457 _('remove (and delete) file even if added or modified')),
5453 ] + subrepoopts + walkopts,
5458 ] + subrepoopts + walkopts,
5454 _('[OPTION]... FILE...'),
5459 _('[OPTION]... FILE...'),
5455 inferrepo=True)
5460 inferrepo=True)
5456 def remove(ui, repo, *pats, **opts):
5461 def remove(ui, repo, *pats, **opts):
5457 """remove the specified files on the next commit
5462 """remove the specified files on the next commit
5458
5463
5459 Schedule the indicated files for removal from the current branch.
5464 Schedule the indicated files for removal from the current branch.
5460
5465
5461 This command schedules the files to be removed at the next commit.
5466 This command schedules the files to be removed at the next commit.
5462 To undo a remove before that, see :hg:`revert`. To undo added
5467 To undo a remove before that, see :hg:`revert`. To undo added
5463 files, see :hg:`forget`.
5468 files, see :hg:`forget`.
5464
5469
5465 .. container:: verbose
5470 .. container:: verbose
5466
5471
5467 -A/--after can be used to remove only files that have already
5472 -A/--after can be used to remove only files that have already
5468 been deleted, -f/--force can be used to force deletion, and -Af
5473 been deleted, -f/--force can be used to force deletion, and -Af
5469 can be used to remove files from the next revision without
5474 can be used to remove files from the next revision without
5470 deleting them from the working directory.
5475 deleting them from the working directory.
5471
5476
5472 The following table details the behavior of remove for different
5477 The following table details the behavior of remove for different
5473 file states (columns) and option combinations (rows). The file
5478 file states (columns) and option combinations (rows). The file
5474 states are Added [A], Clean [C], Modified [M] and Missing [!]
5479 states are Added [A], Clean [C], Modified [M] and Missing [!]
5475 (as reported by :hg:`status`). The actions are Warn, Remove
5480 (as reported by :hg:`status`). The actions are Warn, Remove
5476 (from branch) and Delete (from disk):
5481 (from branch) and Delete (from disk):
5477
5482
5478 ========= == == == ==
5483 ========= == == == ==
5479 opt/state A C M !
5484 opt/state A C M !
5480 ========= == == == ==
5485 ========= == == == ==
5481 none W RD W R
5486 none W RD W R
5482 -f R RD RD R
5487 -f R RD RD R
5483 -A W W W R
5488 -A W W W R
5484 -Af R R R R
5489 -Af R R R R
5485 ========= == == == ==
5490 ========= == == == ==
5486
5491
5487 Note that remove never deletes files in Added [A] state from the
5492 Note that remove never deletes files in Added [A] state from the
5488 working directory, not even if option --force is specified.
5493 working directory, not even if option --force is specified.
5489
5494
5490 Returns 0 on success, 1 if any warnings encountered.
5495 Returns 0 on success, 1 if any warnings encountered.
5491 """
5496 """
5492
5497
5493 after, force = opts.get('after'), opts.get('force')
5498 after, force = opts.get('after'), opts.get('force')
5494 if not pats and not after:
5499 if not pats and not after:
5495 raise error.Abort(_('no files specified'))
5500 raise error.Abort(_('no files specified'))
5496
5501
5497 m = scmutil.match(repo[None], pats, opts)
5502 m = scmutil.match(repo[None], pats, opts)
5498 subrepos = opts.get('subrepos')
5503 subrepos = opts.get('subrepos')
5499 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5504 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5500
5505
5501 @command('rename|move|mv',
5506 @command('rename|move|mv',
5502 [('A', 'after', None, _('record a rename that has already occurred')),
5507 [('A', 'after', None, _('record a rename that has already occurred')),
5503 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5508 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5504 ] + walkopts + dryrunopts,
5509 ] + walkopts + dryrunopts,
5505 _('[OPTION]... SOURCE... DEST'))
5510 _('[OPTION]... SOURCE... DEST'))
5506 def rename(ui, repo, *pats, **opts):
5511 def rename(ui, repo, *pats, **opts):
5507 """rename files; equivalent of copy + remove
5512 """rename files; equivalent of copy + remove
5508
5513
5509 Mark dest as copies of sources; mark sources for deletion. If dest
5514 Mark dest as copies of sources; mark sources for deletion. If dest
5510 is a directory, copies are put in that directory. If dest is a
5515 is a directory, copies are put in that directory. If dest is a
5511 file, there can only be one source.
5516 file, there can only be one source.
5512
5517
5513 By default, this command copies the contents of files as they
5518 By default, this command copies the contents of files as they
5514 exist in the working directory. If invoked with -A/--after, the
5519 exist in the working directory. If invoked with -A/--after, the
5515 operation is recorded, but no copying is performed.
5520 operation is recorded, but no copying is performed.
5516
5521
5517 This command takes effect at the next commit. To undo a rename
5522 This command takes effect at the next commit. To undo a rename
5518 before that, see :hg:`revert`.
5523 before that, see :hg:`revert`.
5519
5524
5520 Returns 0 on success, 1 if errors are encountered.
5525 Returns 0 on success, 1 if errors are encountered.
5521 """
5526 """
5522 wlock = repo.wlock(False)
5527 wlock = repo.wlock(False)
5523 try:
5528 try:
5524 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5529 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5525 finally:
5530 finally:
5526 wlock.release()
5531 wlock.release()
5527
5532
5528 @command('resolve',
5533 @command('resolve',
5529 [('a', 'all', None, _('select all unresolved files')),
5534 [('a', 'all', None, _('select all unresolved files')),
5530 ('l', 'list', None, _('list state of files needing merge')),
5535 ('l', 'list', None, _('list state of files needing merge')),
5531 ('m', 'mark', None, _('mark files as resolved')),
5536 ('m', 'mark', None, _('mark files as resolved')),
5532 ('u', 'unmark', None, _('mark files as unresolved')),
5537 ('u', 'unmark', None, _('mark files as unresolved')),
5533 ('n', 'no-status', None, _('hide status prefix'))]
5538 ('n', 'no-status', None, _('hide status prefix'))]
5534 + mergetoolopts + walkopts + formatteropts,
5539 + mergetoolopts + walkopts + formatteropts,
5535 _('[OPTION]... [FILE]...'),
5540 _('[OPTION]... [FILE]...'),
5536 inferrepo=True)
5541 inferrepo=True)
5537 def resolve(ui, repo, *pats, **opts):
5542 def resolve(ui, repo, *pats, **opts):
5538 """redo merges or set/view the merge status of files
5543 """redo merges or set/view the merge status of files
5539
5544
5540 Merges with unresolved conflicts are often the result of
5545 Merges with unresolved conflicts are often the result of
5541 non-interactive merging using the ``internal:merge`` configuration
5546 non-interactive merging using the ``internal:merge`` configuration
5542 setting, or a command-line merge tool like ``diff3``. The resolve
5547 setting, or a command-line merge tool like ``diff3``. The resolve
5543 command is used to manage the files involved in a merge, after
5548 command is used to manage the files involved in a merge, after
5544 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5549 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5545 working directory must have two parents). See :hg:`help
5550 working directory must have two parents). See :hg:`help
5546 merge-tools` for information on configuring merge tools.
5551 merge-tools` for information on configuring merge tools.
5547
5552
5548 The resolve command can be used in the following ways:
5553 The resolve command can be used in the following ways:
5549
5554
5550 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5555 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5551 files, discarding any previous merge attempts. Re-merging is not
5556 files, discarding any previous merge attempts. Re-merging is not
5552 performed for files already marked as resolved. Use ``--all/-a``
5557 performed for files already marked as resolved. Use ``--all/-a``
5553 to select all unresolved files. ``--tool`` can be used to specify
5558 to select all unresolved files. ``--tool`` can be used to specify
5554 the merge tool used for the given files. It overrides the HGMERGE
5559 the merge tool used for the given files. It overrides the HGMERGE
5555 environment variable and your configuration files. Previous file
5560 environment variable and your configuration files. Previous file
5556 contents are saved with a ``.orig`` suffix.
5561 contents are saved with a ``.orig`` suffix.
5557
5562
5558 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5563 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5559 (e.g. after having manually fixed-up the files). The default is
5564 (e.g. after having manually fixed-up the files). The default is
5560 to mark all unresolved files.
5565 to mark all unresolved files.
5561
5566
5562 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5567 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5563 default is to mark all resolved files.
5568 default is to mark all resolved files.
5564
5569
5565 - :hg:`resolve -l`: list files which had or still have conflicts.
5570 - :hg:`resolve -l`: list files which had or still have conflicts.
5566 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5571 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5567
5572
5568 Note that Mercurial will not let you commit files with unresolved
5573 Note that Mercurial will not let you commit files with unresolved
5569 merge conflicts. You must use :hg:`resolve -m ...` before you can
5574 merge conflicts. You must use :hg:`resolve -m ...` before you can
5570 commit after a conflicting merge.
5575 commit after a conflicting merge.
5571
5576
5572 Returns 0 on success, 1 if any files fail a resolve attempt.
5577 Returns 0 on success, 1 if any files fail a resolve attempt.
5573 """
5578 """
5574
5579
5575 all, mark, unmark, show, nostatus = \
5580 all, mark, unmark, show, nostatus = \
5576 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5581 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5577
5582
5578 if (show and (mark or unmark)) or (mark and unmark):
5583 if (show and (mark or unmark)) or (mark and unmark):
5579 raise error.Abort(_("too many options specified"))
5584 raise error.Abort(_("too many options specified"))
5580 if pats and all:
5585 if pats and all:
5581 raise error.Abort(_("can't specify --all and patterns"))
5586 raise error.Abort(_("can't specify --all and patterns"))
5582 if not (all or pats or show or mark or unmark):
5587 if not (all or pats or show or mark or unmark):
5583 raise error.Abort(_('no files or directories specified'),
5588 raise error.Abort(_('no files or directories specified'),
5584 hint=('use --all to re-merge all unresolved files'))
5589 hint=('use --all to re-merge all unresolved files'))
5585
5590
5586 if show:
5591 if show:
5587 fm = ui.formatter('resolve', opts)
5592 fm = ui.formatter('resolve', opts)
5588 ms = mergemod.mergestate(repo)
5593 ms = mergemod.mergestate(repo)
5589 m = scmutil.match(repo[None], pats, opts)
5594 m = scmutil.match(repo[None], pats, opts)
5590 for f in ms:
5595 for f in ms:
5591 if not m(f):
5596 if not m(f):
5592 continue
5597 continue
5593 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5598 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5594 'd': 'driverresolved'}[ms[f]]
5599 'd': 'driverresolved'}[ms[f]]
5595 fm.startitem()
5600 fm.startitem()
5596 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5601 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5597 fm.write('path', '%s\n', f, label=l)
5602 fm.write('path', '%s\n', f, label=l)
5598 fm.end()
5603 fm.end()
5599 return 0
5604 return 0
5600
5605
5601 wlock = repo.wlock()
5606 wlock = repo.wlock()
5602 try:
5607 try:
5603 ms = mergemod.mergestate(repo)
5608 ms = mergemod.mergestate(repo)
5604
5609
5605 if not (ms.active() or repo.dirstate.p2() != nullid):
5610 if not (ms.active() or repo.dirstate.p2() != nullid):
5606 raise error.Abort(
5611 raise error.Abort(
5607 _('resolve command not applicable when not merging'))
5612 _('resolve command not applicable when not merging'))
5608
5613
5609 wctx = repo[None]
5614 wctx = repo[None]
5610
5615
5611 if ms.mergedriver and ms.mdstate() == 'u':
5616 if ms.mergedriver and ms.mdstate() == 'u':
5612 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5617 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5613 ms.commit()
5618 ms.commit()
5614 # allow mark and unmark to go through
5619 # allow mark and unmark to go through
5615 if not mark and not unmark and not proceed:
5620 if not mark and not unmark and not proceed:
5616 return 1
5621 return 1
5617
5622
5618 m = scmutil.match(wctx, pats, opts)
5623 m = scmutil.match(wctx, pats, opts)
5619 ret = 0
5624 ret = 0
5620 didwork = False
5625 didwork = False
5621 runconclude = False
5626 runconclude = False
5622
5627
5623 tocomplete = []
5628 tocomplete = []
5624 for f in ms:
5629 for f in ms:
5625 if not m(f):
5630 if not m(f):
5626 continue
5631 continue
5627
5632
5628 didwork = True
5633 didwork = True
5629
5634
5630 # don't let driver-resolved files be marked, and run the conclude
5635 # don't let driver-resolved files be marked, and run the conclude
5631 # step if asked to resolve
5636 # step if asked to resolve
5632 if ms[f] == "d":
5637 if ms[f] == "d":
5633 exact = m.exact(f)
5638 exact = m.exact(f)
5634 if mark:
5639 if mark:
5635 if exact:
5640 if exact:
5636 ui.warn(_('not marking %s as it is driver-resolved\n')
5641 ui.warn(_('not marking %s as it is driver-resolved\n')
5637 % f)
5642 % f)
5638 elif unmark:
5643 elif unmark:
5639 if exact:
5644 if exact:
5640 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5645 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5641 % f)
5646 % f)
5642 else:
5647 else:
5643 runconclude = True
5648 runconclude = True
5644 continue
5649 continue
5645
5650
5646 if mark:
5651 if mark:
5647 ms.mark(f, "r")
5652 ms.mark(f, "r")
5648 elif unmark:
5653 elif unmark:
5649 ms.mark(f, "u")
5654 ms.mark(f, "u")
5650 else:
5655 else:
5651 # backup pre-resolve (merge uses .orig for its own purposes)
5656 # backup pre-resolve (merge uses .orig for its own purposes)
5652 a = repo.wjoin(f)
5657 a = repo.wjoin(f)
5653 util.copyfile(a, a + ".resolve")
5658 util.copyfile(a, a + ".resolve")
5654
5659
5655 try:
5660 try:
5656 # preresolve file
5661 # preresolve file
5657 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5662 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5658 'resolve')
5663 'resolve')
5659 complete, r = ms.preresolve(f, wctx)
5664 complete, r = ms.preresolve(f, wctx)
5660 if not complete:
5665 if not complete:
5661 tocomplete.append(f)
5666 tocomplete.append(f)
5662 elif r:
5667 elif r:
5663 ret = 1
5668 ret = 1
5664 finally:
5669 finally:
5665 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5670 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5666 ms.commit()
5671 ms.commit()
5667
5672
5668 # replace filemerge's .orig file with our resolve file
5673 # replace filemerge's .orig file with our resolve file
5669 # for files in tocomplete, ms.resolve will not overwrite
5674 # for files in tocomplete, ms.resolve will not overwrite
5670 # .orig -- only preresolve does
5675 # .orig -- only preresolve does
5671 util.rename(a + ".resolve", a + ".orig")
5676 util.rename(a + ".resolve", a + ".orig")
5672
5677
5673 for f in tocomplete:
5678 for f in tocomplete:
5674 try:
5679 try:
5675 # resolve file
5680 # resolve file
5676 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5681 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5677 'resolve')
5682 'resolve')
5678 r = ms.resolve(f, wctx)
5683 r = ms.resolve(f, wctx)
5679 if r:
5684 if r:
5680 ret = 1
5685 ret = 1
5681 finally:
5686 finally:
5682 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5687 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5683 ms.commit()
5688 ms.commit()
5684
5689
5685 ms.commit()
5690 ms.commit()
5686
5691
5687 if not didwork and pats:
5692 if not didwork and pats:
5688 ui.warn(_("arguments do not match paths that need resolving\n"))
5693 ui.warn(_("arguments do not match paths that need resolving\n"))
5689 elif ms.mergedriver and ms.mdstate() != 's':
5694 elif ms.mergedriver and ms.mdstate() != 's':
5690 # run conclude step when either a driver-resolved file is requested
5695 # run conclude step when either a driver-resolved file is requested
5691 # or there are no driver-resolved files
5696 # or there are no driver-resolved files
5692 # we can't use 'ret' to determine whether any files are unresolved
5697 # we can't use 'ret' to determine whether any files are unresolved
5693 # because we might not have tried to resolve some
5698 # because we might not have tried to resolve some
5694 if ((runconclude or not list(ms.driverresolved()))
5699 if ((runconclude or not list(ms.driverresolved()))
5695 and not list(ms.unresolved())):
5700 and not list(ms.unresolved())):
5696 proceed = mergemod.driverconclude(repo, ms, wctx)
5701 proceed = mergemod.driverconclude(repo, ms, wctx)
5697 ms.commit()
5702 ms.commit()
5698 if not proceed:
5703 if not proceed:
5699 return 1
5704 return 1
5700
5705
5701 finally:
5706 finally:
5702 wlock.release()
5707 wlock.release()
5703
5708
5704 # Nudge users into finishing an unfinished operation
5709 # Nudge users into finishing an unfinished operation
5705 unresolvedf = list(ms.unresolved())
5710 unresolvedf = list(ms.unresolved())
5706 driverresolvedf = list(ms.driverresolved())
5711 driverresolvedf = list(ms.driverresolved())
5707 if not unresolvedf and not driverresolvedf:
5712 if not unresolvedf and not driverresolvedf:
5708 ui.status(_('(no more unresolved files)\n'))
5713 ui.status(_('(no more unresolved files)\n'))
5709 elif not unresolvedf:
5714 elif not unresolvedf:
5710 ui.status(_('(no more unresolved files -- '
5715 ui.status(_('(no more unresolved files -- '
5711 'run "hg resolve --all" to conclude)\n'))
5716 'run "hg resolve --all" to conclude)\n'))
5712
5717
5713 return ret
5718 return ret
5714
5719
5715 @command('revert',
5720 @command('revert',
5716 [('a', 'all', None, _('revert all changes when no arguments given')),
5721 [('a', 'all', None, _('revert all changes when no arguments given')),
5717 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5722 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
5718 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5723 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
5719 ('C', 'no-backup', None, _('do not save backup copies of files')),
5724 ('C', 'no-backup', None, _('do not save backup copies of files')),
5720 ('i', 'interactive', None,
5725 ('i', 'interactive', None,
5721 _('interactively select the changes (EXPERIMENTAL)')),
5726 _('interactively select the changes (EXPERIMENTAL)')),
5722 ] + walkopts + dryrunopts,
5727 ] + walkopts + dryrunopts,
5723 _('[OPTION]... [-r REV] [NAME]...'))
5728 _('[OPTION]... [-r REV] [NAME]...'))
5724 def revert(ui, repo, *pats, **opts):
5729 def revert(ui, repo, *pats, **opts):
5725 """restore files to their checkout state
5730 """restore files to their checkout state
5726
5731
5727 .. note::
5732 .. note::
5728
5733
5729 To check out earlier revisions, you should use :hg:`update REV`.
5734 To check out earlier revisions, you should use :hg:`update REV`.
5730 To cancel an uncommitted merge (and lose your changes),
5735 To cancel an uncommitted merge (and lose your changes),
5731 use :hg:`update --clean .`.
5736 use :hg:`update --clean .`.
5732
5737
5733 With no revision specified, revert the specified files or directories
5738 With no revision specified, revert the specified files or directories
5734 to the contents they had in the parent of the working directory.
5739 to the contents they had in the parent of the working directory.
5735 This restores the contents of files to an unmodified
5740 This restores the contents of files to an unmodified
5736 state and unschedules adds, removes, copies, and renames. If the
5741 state and unschedules adds, removes, copies, and renames. If the
5737 working directory has two parents, you must explicitly specify a
5742 working directory has two parents, you must explicitly specify a
5738 revision.
5743 revision.
5739
5744
5740 Using the -r/--rev or -d/--date options, revert the given files or
5745 Using the -r/--rev or -d/--date options, revert the given files or
5741 directories to their states as of a specific revision. Because
5746 directories to their states as of a specific revision. Because
5742 revert does not change the working directory parents, this will
5747 revert does not change the working directory parents, this will
5743 cause these files to appear modified. This can be helpful to "back
5748 cause these files to appear modified. This can be helpful to "back
5744 out" some or all of an earlier change. See :hg:`backout` for a
5749 out" some or all of an earlier change. See :hg:`backout` for a
5745 related method.
5750 related method.
5746
5751
5747 Modified files are saved with a .orig suffix before reverting.
5752 Modified files are saved with a .orig suffix before reverting.
5748 To disable these backups, use --no-backup.
5753 To disable these backups, use --no-backup.
5749
5754
5750 See :hg:`help dates` for a list of formats valid for -d/--date.
5755 See :hg:`help dates` for a list of formats valid for -d/--date.
5751
5756
5752 See :hg:`help backout` for a way to reverse the effect of an
5757 See :hg:`help backout` for a way to reverse the effect of an
5753 earlier changeset.
5758 earlier changeset.
5754
5759
5755 Returns 0 on success.
5760 Returns 0 on success.
5756 """
5761 """
5757
5762
5758 if opts.get("date"):
5763 if opts.get("date"):
5759 if opts.get("rev"):
5764 if opts.get("rev"):
5760 raise error.Abort(_("you can't specify a revision and a date"))
5765 raise error.Abort(_("you can't specify a revision and a date"))
5761 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5766 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
5762
5767
5763 parent, p2 = repo.dirstate.parents()
5768 parent, p2 = repo.dirstate.parents()
5764 if not opts.get('rev') and p2 != nullid:
5769 if not opts.get('rev') and p2 != nullid:
5765 # revert after merge is a trap for new users (issue2915)
5770 # revert after merge is a trap for new users (issue2915)
5766 raise error.Abort(_('uncommitted merge with no revision specified'),
5771 raise error.Abort(_('uncommitted merge with no revision specified'),
5767 hint=_('use "hg update" or see "hg help revert"'))
5772 hint=_('use "hg update" or see "hg help revert"'))
5768
5773
5769 ctx = scmutil.revsingle(repo, opts.get('rev'))
5774 ctx = scmutil.revsingle(repo, opts.get('rev'))
5770
5775
5771 if (not (pats or opts.get('include') or opts.get('exclude') or
5776 if (not (pats or opts.get('include') or opts.get('exclude') or
5772 opts.get('all') or opts.get('interactive'))):
5777 opts.get('all') or opts.get('interactive'))):
5773 msg = _("no files or directories specified")
5778 msg = _("no files or directories specified")
5774 if p2 != nullid:
5779 if p2 != nullid:
5775 hint = _("uncommitted merge, use --all to discard all changes,"
5780 hint = _("uncommitted merge, use --all to discard all changes,"
5776 " or 'hg update -C .' to abort the merge")
5781 " or 'hg update -C .' to abort the merge")
5777 raise error.Abort(msg, hint=hint)
5782 raise error.Abort(msg, hint=hint)
5778 dirty = any(repo.status())
5783 dirty = any(repo.status())
5779 node = ctx.node()
5784 node = ctx.node()
5780 if node != parent:
5785 if node != parent:
5781 if dirty:
5786 if dirty:
5782 hint = _("uncommitted changes, use --all to discard all"
5787 hint = _("uncommitted changes, use --all to discard all"
5783 " changes, or 'hg update %s' to update") % ctx.rev()
5788 " changes, or 'hg update %s' to update") % ctx.rev()
5784 else:
5789 else:
5785 hint = _("use --all to revert all files,"
5790 hint = _("use --all to revert all files,"
5786 " or 'hg update %s' to update") % ctx.rev()
5791 " or 'hg update %s' to update") % ctx.rev()
5787 elif dirty:
5792 elif dirty:
5788 hint = _("uncommitted changes, use --all to discard all changes")
5793 hint = _("uncommitted changes, use --all to discard all changes")
5789 else:
5794 else:
5790 hint = _("use --all to revert all files")
5795 hint = _("use --all to revert all files")
5791 raise error.Abort(msg, hint=hint)
5796 raise error.Abort(msg, hint=hint)
5792
5797
5793 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5798 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
5794
5799
5795 @command('rollback', dryrunopts +
5800 @command('rollback', dryrunopts +
5796 [('f', 'force', False, _('ignore safety measures'))])
5801 [('f', 'force', False, _('ignore safety measures'))])
5797 def rollback(ui, repo, **opts):
5802 def rollback(ui, repo, **opts):
5798 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5803 """roll back the last transaction (DANGEROUS) (DEPRECATED)
5799
5804
5800 Please use :hg:`commit --amend` instead of rollback to correct
5805 Please use :hg:`commit --amend` instead of rollback to correct
5801 mistakes in the last commit.
5806 mistakes in the last commit.
5802
5807
5803 This command should be used with care. There is only one level of
5808 This command should be used with care. There is only one level of
5804 rollback, and there is no way to undo a rollback. It will also
5809 rollback, and there is no way to undo a rollback. It will also
5805 restore the dirstate at the time of the last transaction, losing
5810 restore the dirstate at the time of the last transaction, losing
5806 any dirstate changes since that time. This command does not alter
5811 any dirstate changes since that time. This command does not alter
5807 the working directory.
5812 the working directory.
5808
5813
5809 Transactions are used to encapsulate the effects of all commands
5814 Transactions are used to encapsulate the effects of all commands
5810 that create new changesets or propagate existing changesets into a
5815 that create new changesets or propagate existing changesets into a
5811 repository.
5816 repository.
5812
5817
5813 .. container:: verbose
5818 .. container:: verbose
5814
5819
5815 For example, the following commands are transactional, and their
5820 For example, the following commands are transactional, and their
5816 effects can be rolled back:
5821 effects can be rolled back:
5817
5822
5818 - commit
5823 - commit
5819 - import
5824 - import
5820 - pull
5825 - pull
5821 - push (with this repository as the destination)
5826 - push (with this repository as the destination)
5822 - unbundle
5827 - unbundle
5823
5828
5824 To avoid permanent data loss, rollback will refuse to rollback a
5829 To avoid permanent data loss, rollback will refuse to rollback a
5825 commit transaction if it isn't checked out. Use --force to
5830 commit transaction if it isn't checked out. Use --force to
5826 override this protection.
5831 override this protection.
5827
5832
5828 This command is not intended for use on public repositories. Once
5833 This command is not intended for use on public repositories. Once
5829 changes are visible for pull by other users, rolling a transaction
5834 changes are visible for pull by other users, rolling a transaction
5830 back locally is ineffective (someone else may already have pulled
5835 back locally is ineffective (someone else may already have pulled
5831 the changes). Furthermore, a race is possible with readers of the
5836 the changes). Furthermore, a race is possible with readers of the
5832 repository; for example an in-progress pull from the repository
5837 repository; for example an in-progress pull from the repository
5833 may fail if a rollback is performed.
5838 may fail if a rollback is performed.
5834
5839
5835 Returns 0 on success, 1 if no rollback data is available.
5840 Returns 0 on success, 1 if no rollback data is available.
5836 """
5841 """
5837 return repo.rollback(dryrun=opts.get('dry_run'),
5842 return repo.rollback(dryrun=opts.get('dry_run'),
5838 force=opts.get('force'))
5843 force=opts.get('force'))
5839
5844
5840 @command('root', [])
5845 @command('root', [])
5841 def root(ui, repo):
5846 def root(ui, repo):
5842 """print the root (top) of the current working directory
5847 """print the root (top) of the current working directory
5843
5848
5844 Print the root directory of the current repository.
5849 Print the root directory of the current repository.
5845
5850
5846 Returns 0 on success.
5851 Returns 0 on success.
5847 """
5852 """
5848 ui.write(repo.root + "\n")
5853 ui.write(repo.root + "\n")
5849
5854
5850 @command('^serve',
5855 @command('^serve',
5851 [('A', 'accesslog', '', _('name of access log file to write to'),
5856 [('A', 'accesslog', '', _('name of access log file to write to'),
5852 _('FILE')),
5857 _('FILE')),
5853 ('d', 'daemon', None, _('run server in background')),
5858 ('d', 'daemon', None, _('run server in background')),
5854 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5859 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
5855 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5860 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
5856 # use string type, then we can check if something was passed
5861 # use string type, then we can check if something was passed
5857 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5862 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
5858 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5863 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
5859 _('ADDR')),
5864 _('ADDR')),
5860 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5865 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
5861 _('PREFIX')),
5866 _('PREFIX')),
5862 ('n', 'name', '',
5867 ('n', 'name', '',
5863 _('name to show in web pages (default: working directory)'), _('NAME')),
5868 _('name to show in web pages (default: working directory)'), _('NAME')),
5864 ('', 'web-conf', '',
5869 ('', 'web-conf', '',
5865 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5870 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
5866 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5871 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
5867 _('FILE')),
5872 _('FILE')),
5868 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5873 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
5869 ('', 'stdio', None, _('for remote clients')),
5874 ('', 'stdio', None, _('for remote clients')),
5870 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5875 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
5871 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5876 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
5872 ('', 'style', '', _('template style to use'), _('STYLE')),
5877 ('', 'style', '', _('template style to use'), _('STYLE')),
5873 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5878 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
5874 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5879 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
5875 _('[OPTION]...'),
5880 _('[OPTION]...'),
5876 optionalrepo=True)
5881 optionalrepo=True)
5877 def serve(ui, repo, **opts):
5882 def serve(ui, repo, **opts):
5878 """start stand-alone webserver
5883 """start stand-alone webserver
5879
5884
5880 Start a local HTTP repository browser and pull server. You can use
5885 Start a local HTTP repository browser and pull server. You can use
5881 this for ad-hoc sharing and browsing of repositories. It is
5886 this for ad-hoc sharing and browsing of repositories. It is
5882 recommended to use a real web server to serve a repository for
5887 recommended to use a real web server to serve a repository for
5883 longer periods of time.
5888 longer periods of time.
5884
5889
5885 Please note that the server does not implement access control.
5890 Please note that the server does not implement access control.
5886 This means that, by default, anybody can read from the server and
5891 This means that, by default, anybody can read from the server and
5887 nobody can write to it by default. Set the ``web.allow_push``
5892 nobody can write to it by default. Set the ``web.allow_push``
5888 option to ``*`` to allow everybody to push to the server. You
5893 option to ``*`` to allow everybody to push to the server. You
5889 should use a real web server if you need to authenticate users.
5894 should use a real web server if you need to authenticate users.
5890
5895
5891 By default, the server logs accesses to stdout and errors to
5896 By default, the server logs accesses to stdout and errors to
5892 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5897 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
5893 files.
5898 files.
5894
5899
5895 To have the server choose a free port number to listen on, specify
5900 To have the server choose a free port number to listen on, specify
5896 a port number of 0; in this case, the server will print the port
5901 a port number of 0; in this case, the server will print the port
5897 number it uses.
5902 number it uses.
5898
5903
5899 Returns 0 on success.
5904 Returns 0 on success.
5900 """
5905 """
5901
5906
5902 if opts["stdio"] and opts["cmdserver"]:
5907 if opts["stdio"] and opts["cmdserver"]:
5903 raise error.Abort(_("cannot use --stdio with --cmdserver"))
5908 raise error.Abort(_("cannot use --stdio with --cmdserver"))
5904
5909
5905 if opts["stdio"]:
5910 if opts["stdio"]:
5906 if repo is None:
5911 if repo is None:
5907 raise error.RepoError(_("there is no Mercurial repository here"
5912 raise error.RepoError(_("there is no Mercurial repository here"
5908 " (.hg not found)"))
5913 " (.hg not found)"))
5909 s = sshserver.sshserver(ui, repo)
5914 s = sshserver.sshserver(ui, repo)
5910 s.serve_forever()
5915 s.serve_forever()
5911
5916
5912 if opts["cmdserver"]:
5917 if opts["cmdserver"]:
5913 import commandserver
5918 import commandserver
5914 service = commandserver.createservice(ui, repo, opts)
5919 service = commandserver.createservice(ui, repo, opts)
5915 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5920 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
5916
5921
5917 # this way we can check if something was given in the command-line
5922 # this way we can check if something was given in the command-line
5918 if opts.get('port'):
5923 if opts.get('port'):
5919 opts['port'] = util.getport(opts.get('port'))
5924 opts['port'] = util.getport(opts.get('port'))
5920
5925
5921 if repo:
5926 if repo:
5922 baseui = repo.baseui
5927 baseui = repo.baseui
5923 else:
5928 else:
5924 baseui = ui
5929 baseui = ui
5925 optlist = ("name templates style address port prefix ipv6"
5930 optlist = ("name templates style address port prefix ipv6"
5926 " accesslog errorlog certificate encoding")
5931 " accesslog errorlog certificate encoding")
5927 for o in optlist.split():
5932 for o in optlist.split():
5928 val = opts.get(o, '')
5933 val = opts.get(o, '')
5929 if val in (None, ''): # should check against default options instead
5934 if val in (None, ''): # should check against default options instead
5930 continue
5935 continue
5931 baseui.setconfig("web", o, val, 'serve')
5936 baseui.setconfig("web", o, val, 'serve')
5932 if repo and repo.ui != baseui:
5937 if repo and repo.ui != baseui:
5933 repo.ui.setconfig("web", o, val, 'serve')
5938 repo.ui.setconfig("web", o, val, 'serve')
5934
5939
5935 o = opts.get('web_conf') or opts.get('webdir_conf')
5940 o = opts.get('web_conf') or opts.get('webdir_conf')
5936 if not o:
5941 if not o:
5937 if not repo:
5942 if not repo:
5938 raise error.RepoError(_("there is no Mercurial repository"
5943 raise error.RepoError(_("there is no Mercurial repository"
5939 " here (.hg not found)"))
5944 " here (.hg not found)"))
5940 o = repo
5945 o = repo
5941
5946
5942 app = hgweb.hgweb(o, baseui=baseui)
5947 app = hgweb.hgweb(o, baseui=baseui)
5943 service = httpservice(ui, app, opts)
5948 service = httpservice(ui, app, opts)
5944 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5949 cmdutil.service(opts, initfn=service.init, runfn=service.run)
5945
5950
5946 class httpservice(object):
5951 class httpservice(object):
5947 def __init__(self, ui, app, opts):
5952 def __init__(self, ui, app, opts):
5948 self.ui = ui
5953 self.ui = ui
5949 self.app = app
5954 self.app = app
5950 self.opts = opts
5955 self.opts = opts
5951
5956
5952 def init(self):
5957 def init(self):
5953 util.setsignalhandler()
5958 util.setsignalhandler()
5954 self.httpd = hgweb_server.create_server(self.ui, self.app)
5959 self.httpd = hgweb_server.create_server(self.ui, self.app)
5955
5960
5956 if self.opts['port'] and not self.ui.verbose:
5961 if self.opts['port'] and not self.ui.verbose:
5957 return
5962 return
5958
5963
5959 if self.httpd.prefix:
5964 if self.httpd.prefix:
5960 prefix = self.httpd.prefix.strip('/') + '/'
5965 prefix = self.httpd.prefix.strip('/') + '/'
5961 else:
5966 else:
5962 prefix = ''
5967 prefix = ''
5963
5968
5964 port = ':%d' % self.httpd.port
5969 port = ':%d' % self.httpd.port
5965 if port == ':80':
5970 if port == ':80':
5966 port = ''
5971 port = ''
5967
5972
5968 bindaddr = self.httpd.addr
5973 bindaddr = self.httpd.addr
5969 if bindaddr == '0.0.0.0':
5974 if bindaddr == '0.0.0.0':
5970 bindaddr = '*'
5975 bindaddr = '*'
5971 elif ':' in bindaddr: # IPv6
5976 elif ':' in bindaddr: # IPv6
5972 bindaddr = '[%s]' % bindaddr
5977 bindaddr = '[%s]' % bindaddr
5973
5978
5974 fqaddr = self.httpd.fqaddr
5979 fqaddr = self.httpd.fqaddr
5975 if ':' in fqaddr:
5980 if ':' in fqaddr:
5976 fqaddr = '[%s]' % fqaddr
5981 fqaddr = '[%s]' % fqaddr
5977 if self.opts['port']:
5982 if self.opts['port']:
5978 write = self.ui.status
5983 write = self.ui.status
5979 else:
5984 else:
5980 write = self.ui.write
5985 write = self.ui.write
5981 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5986 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
5982 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5987 (fqaddr, port, prefix, bindaddr, self.httpd.port))
5983 self.ui.flush() # avoid buffering of status message
5988 self.ui.flush() # avoid buffering of status message
5984
5989
5985 def run(self):
5990 def run(self):
5986 self.httpd.serve_forever()
5991 self.httpd.serve_forever()
5987
5992
5988
5993
5989 @command('^status|st',
5994 @command('^status|st',
5990 [('A', 'all', None, _('show status of all files')),
5995 [('A', 'all', None, _('show status of all files')),
5991 ('m', 'modified', None, _('show only modified files')),
5996 ('m', 'modified', None, _('show only modified files')),
5992 ('a', 'added', None, _('show only added files')),
5997 ('a', 'added', None, _('show only added files')),
5993 ('r', 'removed', None, _('show only removed files')),
5998 ('r', 'removed', None, _('show only removed files')),
5994 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5999 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
5995 ('c', 'clean', None, _('show only files without changes')),
6000 ('c', 'clean', None, _('show only files without changes')),
5996 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6001 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
5997 ('i', 'ignored', None, _('show only ignored files')),
6002 ('i', 'ignored', None, _('show only ignored files')),
5998 ('n', 'no-status', None, _('hide status prefix')),
6003 ('n', 'no-status', None, _('hide status prefix')),
5999 ('C', 'copies', None, _('show source of copied files')),
6004 ('C', 'copies', None, _('show source of copied files')),
6000 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6005 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6001 ('', 'rev', [], _('show difference from revision'), _('REV')),
6006 ('', 'rev', [], _('show difference from revision'), _('REV')),
6002 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6007 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6003 ] + walkopts + subrepoopts + formatteropts,
6008 ] + walkopts + subrepoopts + formatteropts,
6004 _('[OPTION]... [FILE]...'),
6009 _('[OPTION]... [FILE]...'),
6005 inferrepo=True)
6010 inferrepo=True)
6006 def status(ui, repo, *pats, **opts):
6011 def status(ui, repo, *pats, **opts):
6007 """show changed files in the working directory
6012 """show changed files in the working directory
6008
6013
6009 Show status of files in the repository. If names are given, only
6014 Show status of files in the repository. If names are given, only
6010 files that match are shown. Files that are clean or ignored or
6015 files that match are shown. Files that are clean or ignored or
6011 the source of a copy/move operation, are not listed unless
6016 the source of a copy/move operation, are not listed unless
6012 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6017 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6013 Unless options described with "show only ..." are given, the
6018 Unless options described with "show only ..." are given, the
6014 options -mardu are used.
6019 options -mardu are used.
6015
6020
6016 Option -q/--quiet hides untracked (unknown and ignored) files
6021 Option -q/--quiet hides untracked (unknown and ignored) files
6017 unless explicitly requested with -u/--unknown or -i/--ignored.
6022 unless explicitly requested with -u/--unknown or -i/--ignored.
6018
6023
6019 .. note::
6024 .. note::
6020
6025
6021 status may appear to disagree with diff if permissions have
6026 status may appear to disagree with diff if permissions have
6022 changed or a merge has occurred. The standard diff format does
6027 changed or a merge has occurred. The standard diff format does
6023 not report permission changes and diff only reports changes
6028 not report permission changes and diff only reports changes
6024 relative to one merge parent.
6029 relative to one merge parent.
6025
6030
6026 If one revision is given, it is used as the base revision.
6031 If one revision is given, it is used as the base revision.
6027 If two revisions are given, the differences between them are
6032 If two revisions are given, the differences between them are
6028 shown. The --change option can also be used as a shortcut to list
6033 shown. The --change option can also be used as a shortcut to list
6029 the changed files of a revision from its first parent.
6034 the changed files of a revision from its first parent.
6030
6035
6031 The codes used to show the status of files are::
6036 The codes used to show the status of files are::
6032
6037
6033 M = modified
6038 M = modified
6034 A = added
6039 A = added
6035 R = removed
6040 R = removed
6036 C = clean
6041 C = clean
6037 ! = missing (deleted by non-hg command, but still tracked)
6042 ! = missing (deleted by non-hg command, but still tracked)
6038 ? = not tracked
6043 ? = not tracked
6039 I = ignored
6044 I = ignored
6040 = origin of the previous file (with --copies)
6045 = origin of the previous file (with --copies)
6041
6046
6042 .. container:: verbose
6047 .. container:: verbose
6043
6048
6044 Examples:
6049 Examples:
6045
6050
6046 - show changes in the working directory relative to a
6051 - show changes in the working directory relative to a
6047 changeset::
6052 changeset::
6048
6053
6049 hg status --rev 9353
6054 hg status --rev 9353
6050
6055
6051 - show changes in the working directory relative to the
6056 - show changes in the working directory relative to the
6052 current directory (see :hg:`help patterns` for more information)::
6057 current directory (see :hg:`help patterns` for more information)::
6053
6058
6054 hg status re:
6059 hg status re:
6055
6060
6056 - show all changes including copies in an existing changeset::
6061 - show all changes including copies in an existing changeset::
6057
6062
6058 hg status --copies --change 9353
6063 hg status --copies --change 9353
6059
6064
6060 - get a NUL separated list of added files, suitable for xargs::
6065 - get a NUL separated list of added files, suitable for xargs::
6061
6066
6062 hg status -an0
6067 hg status -an0
6063
6068
6064 Returns 0 on success.
6069 Returns 0 on success.
6065 """
6070 """
6066
6071
6067 revs = opts.get('rev')
6072 revs = opts.get('rev')
6068 change = opts.get('change')
6073 change = opts.get('change')
6069
6074
6070 if revs and change:
6075 if revs and change:
6071 msg = _('cannot specify --rev and --change at the same time')
6076 msg = _('cannot specify --rev and --change at the same time')
6072 raise error.Abort(msg)
6077 raise error.Abort(msg)
6073 elif change:
6078 elif change:
6074 node2 = scmutil.revsingle(repo, change, None).node()
6079 node2 = scmutil.revsingle(repo, change, None).node()
6075 node1 = repo[node2].p1().node()
6080 node1 = repo[node2].p1().node()
6076 else:
6081 else:
6077 node1, node2 = scmutil.revpair(repo, revs)
6082 node1, node2 = scmutil.revpair(repo, revs)
6078
6083
6079 if pats:
6084 if pats:
6080 cwd = repo.getcwd()
6085 cwd = repo.getcwd()
6081 else:
6086 else:
6082 cwd = ''
6087 cwd = ''
6083
6088
6084 if opts.get('print0'):
6089 if opts.get('print0'):
6085 end = '\0'
6090 end = '\0'
6086 else:
6091 else:
6087 end = '\n'
6092 end = '\n'
6088 copy = {}
6093 copy = {}
6089 states = 'modified added removed deleted unknown ignored clean'.split()
6094 states = 'modified added removed deleted unknown ignored clean'.split()
6090 show = [k for k in states if opts.get(k)]
6095 show = [k for k in states if opts.get(k)]
6091 if opts.get('all'):
6096 if opts.get('all'):
6092 show += ui.quiet and (states[:4] + ['clean']) or states
6097 show += ui.quiet and (states[:4] + ['clean']) or states
6093 if not show:
6098 if not show:
6094 if ui.quiet:
6099 if ui.quiet:
6095 show = states[:4]
6100 show = states[:4]
6096 else:
6101 else:
6097 show = states[:5]
6102 show = states[:5]
6098
6103
6099 m = scmutil.match(repo[node2], pats, opts)
6104 m = scmutil.match(repo[node2], pats, opts)
6100 stat = repo.status(node1, node2, m,
6105 stat = repo.status(node1, node2, m,
6101 'ignored' in show, 'clean' in show, 'unknown' in show,
6106 'ignored' in show, 'clean' in show, 'unknown' in show,
6102 opts.get('subrepos'))
6107 opts.get('subrepos'))
6103 changestates = zip(states, 'MAR!?IC', stat)
6108 changestates = zip(states, 'MAR!?IC', stat)
6104
6109
6105 if (opts.get('all') or opts.get('copies')
6110 if (opts.get('all') or opts.get('copies')
6106 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6111 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6107 copy = copies.pathcopies(repo[node1], repo[node2], m)
6112 copy = copies.pathcopies(repo[node1], repo[node2], m)
6108
6113
6109 fm = ui.formatter('status', opts)
6114 fm = ui.formatter('status', opts)
6110 fmt = '%s' + end
6115 fmt = '%s' + end
6111 showchar = not opts.get('no_status')
6116 showchar = not opts.get('no_status')
6112
6117
6113 for state, char, files in changestates:
6118 for state, char, files in changestates:
6114 if state in show:
6119 if state in show:
6115 label = 'status.' + state
6120 label = 'status.' + state
6116 for f in files:
6121 for f in files:
6117 fm.startitem()
6122 fm.startitem()
6118 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6123 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6119 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6124 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6120 if f in copy:
6125 if f in copy:
6121 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6126 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6122 label='status.copied')
6127 label='status.copied')
6123 fm.end()
6128 fm.end()
6124
6129
6125 @command('^summary|sum',
6130 @command('^summary|sum',
6126 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6131 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6127 def summary(ui, repo, **opts):
6132 def summary(ui, repo, **opts):
6128 """summarize working directory state
6133 """summarize working directory state
6129
6134
6130 This generates a brief summary of the working directory state,
6135 This generates a brief summary of the working directory state,
6131 including parents, branch, commit status, phase and available updates.
6136 including parents, branch, commit status, phase and available updates.
6132
6137
6133 With the --remote option, this will check the default paths for
6138 With the --remote option, this will check the default paths for
6134 incoming and outgoing changes. This can be time-consuming.
6139 incoming and outgoing changes. This can be time-consuming.
6135
6140
6136 Returns 0 on success.
6141 Returns 0 on success.
6137 """
6142 """
6138
6143
6139 ctx = repo[None]
6144 ctx = repo[None]
6140 parents = ctx.parents()
6145 parents = ctx.parents()
6141 pnode = parents[0].node()
6146 pnode = parents[0].node()
6142 marks = []
6147 marks = []
6143
6148
6144 for p in parents:
6149 for p in parents:
6145 # label with log.changeset (instead of log.parent) since this
6150 # label with log.changeset (instead of log.parent) since this
6146 # shows a working directory parent *changeset*:
6151 # shows a working directory parent *changeset*:
6147 # i18n: column positioning for "hg summary"
6152 # i18n: column positioning for "hg summary"
6148 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6153 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6149 label='log.changeset changeset.%s' % p.phasestr())
6154 label='log.changeset changeset.%s' % p.phasestr())
6150 ui.write(' '.join(p.tags()), label='log.tag')
6155 ui.write(' '.join(p.tags()), label='log.tag')
6151 if p.bookmarks():
6156 if p.bookmarks():
6152 marks.extend(p.bookmarks())
6157 marks.extend(p.bookmarks())
6153 if p.rev() == -1:
6158 if p.rev() == -1:
6154 if not len(repo):
6159 if not len(repo):
6155 ui.write(_(' (empty repository)'))
6160 ui.write(_(' (empty repository)'))
6156 else:
6161 else:
6157 ui.write(_(' (no revision checked out)'))
6162 ui.write(_(' (no revision checked out)'))
6158 ui.write('\n')
6163 ui.write('\n')
6159 if p.description():
6164 if p.description():
6160 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6165 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6161 label='log.summary')
6166 label='log.summary')
6162
6167
6163 branch = ctx.branch()
6168 branch = ctx.branch()
6164 bheads = repo.branchheads(branch)
6169 bheads = repo.branchheads(branch)
6165 # i18n: column positioning for "hg summary"
6170 # i18n: column positioning for "hg summary"
6166 m = _('branch: %s\n') % branch
6171 m = _('branch: %s\n') % branch
6167 if branch != 'default':
6172 if branch != 'default':
6168 ui.write(m, label='log.branch')
6173 ui.write(m, label='log.branch')
6169 else:
6174 else:
6170 ui.status(m, label='log.branch')
6175 ui.status(m, label='log.branch')
6171
6176
6172 if marks:
6177 if marks:
6173 active = repo._activebookmark
6178 active = repo._activebookmark
6174 # i18n: column positioning for "hg summary"
6179 # i18n: column positioning for "hg summary"
6175 ui.write(_('bookmarks:'), label='log.bookmark')
6180 ui.write(_('bookmarks:'), label='log.bookmark')
6176 if active is not None:
6181 if active is not None:
6177 if active in marks:
6182 if active in marks:
6178 ui.write(' *' + active, label=activebookmarklabel)
6183 ui.write(' *' + active, label=activebookmarklabel)
6179 marks.remove(active)
6184 marks.remove(active)
6180 else:
6185 else:
6181 ui.write(' [%s]' % active, label=activebookmarklabel)
6186 ui.write(' [%s]' % active, label=activebookmarklabel)
6182 for m in marks:
6187 for m in marks:
6183 ui.write(' ' + m, label='log.bookmark')
6188 ui.write(' ' + m, label='log.bookmark')
6184 ui.write('\n', label='log.bookmark')
6189 ui.write('\n', label='log.bookmark')
6185
6190
6186 status = repo.status(unknown=True)
6191 status = repo.status(unknown=True)
6187
6192
6188 c = repo.dirstate.copies()
6193 c = repo.dirstate.copies()
6189 copied, renamed = [], []
6194 copied, renamed = [], []
6190 for d, s in c.iteritems():
6195 for d, s in c.iteritems():
6191 if s in status.removed:
6196 if s in status.removed:
6192 status.removed.remove(s)
6197 status.removed.remove(s)
6193 renamed.append(d)
6198 renamed.append(d)
6194 else:
6199 else:
6195 copied.append(d)
6200 copied.append(d)
6196 if d in status.added:
6201 if d in status.added:
6197 status.added.remove(d)
6202 status.added.remove(d)
6198
6203
6199 ms = mergemod.mergestate(repo)
6204 ms = mergemod.mergestate(repo)
6200 unresolved = [f for f in ms if ms[f] == 'u']
6205 unresolved = [f for f in ms if ms[f] == 'u']
6201
6206
6202 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6207 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6203
6208
6204 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6209 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6205 (ui.label(_('%d added'), 'status.added'), status.added),
6210 (ui.label(_('%d added'), 'status.added'), status.added),
6206 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6211 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6207 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6212 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6208 (ui.label(_('%d copied'), 'status.copied'), copied),
6213 (ui.label(_('%d copied'), 'status.copied'), copied),
6209 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6214 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6210 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6215 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6211 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6216 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6212 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6217 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6213 t = []
6218 t = []
6214 for l, s in labels:
6219 for l, s in labels:
6215 if s:
6220 if s:
6216 t.append(l % len(s))
6221 t.append(l % len(s))
6217
6222
6218 t = ', '.join(t)
6223 t = ', '.join(t)
6219 cleanworkdir = False
6224 cleanworkdir = False
6220
6225
6221 if repo.vfs.exists('updatestate'):
6226 if repo.vfs.exists('updatestate'):
6222 t += _(' (interrupted update)')
6227 t += _(' (interrupted update)')
6223 elif len(parents) > 1:
6228 elif len(parents) > 1:
6224 t += _(' (merge)')
6229 t += _(' (merge)')
6225 elif branch != parents[0].branch():
6230 elif branch != parents[0].branch():
6226 t += _(' (new branch)')
6231 t += _(' (new branch)')
6227 elif (parents[0].closesbranch() and
6232 elif (parents[0].closesbranch() and
6228 pnode in repo.branchheads(branch, closed=True)):
6233 pnode in repo.branchheads(branch, closed=True)):
6229 t += _(' (head closed)')
6234 t += _(' (head closed)')
6230 elif not (status.modified or status.added or status.removed or renamed or
6235 elif not (status.modified or status.added or status.removed or renamed or
6231 copied or subs):
6236 copied or subs):
6232 t += _(' (clean)')
6237 t += _(' (clean)')
6233 cleanworkdir = True
6238 cleanworkdir = True
6234 elif pnode not in bheads:
6239 elif pnode not in bheads:
6235 t += _(' (new branch head)')
6240 t += _(' (new branch head)')
6236
6241
6237 if parents:
6242 if parents:
6238 pendingphase = max(p.phase() for p in parents)
6243 pendingphase = max(p.phase() for p in parents)
6239 else:
6244 else:
6240 pendingphase = phases.public
6245 pendingphase = phases.public
6241
6246
6242 if pendingphase > phases.newcommitphase(ui):
6247 if pendingphase > phases.newcommitphase(ui):
6243 t += ' (%s)' % phases.phasenames[pendingphase]
6248 t += ' (%s)' % phases.phasenames[pendingphase]
6244
6249
6245 if cleanworkdir:
6250 if cleanworkdir:
6246 # i18n: column positioning for "hg summary"
6251 # i18n: column positioning for "hg summary"
6247 ui.status(_('commit: %s\n') % t.strip())
6252 ui.status(_('commit: %s\n') % t.strip())
6248 else:
6253 else:
6249 # i18n: column positioning for "hg summary"
6254 # i18n: column positioning for "hg summary"
6250 ui.write(_('commit: %s\n') % t.strip())
6255 ui.write(_('commit: %s\n') % t.strip())
6251
6256
6252 # all ancestors of branch heads - all ancestors of parent = new csets
6257 # all ancestors of branch heads - all ancestors of parent = new csets
6253 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6258 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6254 bheads))
6259 bheads))
6255
6260
6256 if new == 0:
6261 if new == 0:
6257 # i18n: column positioning for "hg summary"
6262 # i18n: column positioning for "hg summary"
6258 ui.status(_('update: (current)\n'))
6263 ui.status(_('update: (current)\n'))
6259 elif pnode not in bheads:
6264 elif pnode not in bheads:
6260 # i18n: column positioning for "hg summary"
6265 # i18n: column positioning for "hg summary"
6261 ui.write(_('update: %d new changesets (update)\n') % new)
6266 ui.write(_('update: %d new changesets (update)\n') % new)
6262 else:
6267 else:
6263 # i18n: column positioning for "hg summary"
6268 # i18n: column positioning for "hg summary"
6264 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6269 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6265 (new, len(bheads)))
6270 (new, len(bheads)))
6266
6271
6267 t = []
6272 t = []
6268 draft = len(repo.revs('draft()'))
6273 draft = len(repo.revs('draft()'))
6269 if draft:
6274 if draft:
6270 t.append(_('%d draft') % draft)
6275 t.append(_('%d draft') % draft)
6271 secret = len(repo.revs('secret()'))
6276 secret = len(repo.revs('secret()'))
6272 if secret:
6277 if secret:
6273 t.append(_('%d secret') % secret)
6278 t.append(_('%d secret') % secret)
6274
6279
6275 if draft or secret:
6280 if draft or secret:
6276 ui.status(_('phases: %s\n') % ', '.join(t))
6281 ui.status(_('phases: %s\n') % ', '.join(t))
6277
6282
6278 cmdutil.summaryhooks(ui, repo)
6283 cmdutil.summaryhooks(ui, repo)
6279
6284
6280 if opts.get('remote'):
6285 if opts.get('remote'):
6281 needsincoming, needsoutgoing = True, True
6286 needsincoming, needsoutgoing = True, True
6282 else:
6287 else:
6283 needsincoming, needsoutgoing = False, False
6288 needsincoming, needsoutgoing = False, False
6284 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6289 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6285 if i:
6290 if i:
6286 needsincoming = True
6291 needsincoming = True
6287 if o:
6292 if o:
6288 needsoutgoing = True
6293 needsoutgoing = True
6289 if not needsincoming and not needsoutgoing:
6294 if not needsincoming and not needsoutgoing:
6290 return
6295 return
6291
6296
6292 def getincoming():
6297 def getincoming():
6293 source, branches = hg.parseurl(ui.expandpath('default'))
6298 source, branches = hg.parseurl(ui.expandpath('default'))
6294 sbranch = branches[0]
6299 sbranch = branches[0]
6295 try:
6300 try:
6296 other = hg.peer(repo, {}, source)
6301 other = hg.peer(repo, {}, source)
6297 except error.RepoError:
6302 except error.RepoError:
6298 if opts.get('remote'):
6303 if opts.get('remote'):
6299 raise
6304 raise
6300 return source, sbranch, None, None, None
6305 return source, sbranch, None, None, None
6301 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6306 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6302 if revs:
6307 if revs:
6303 revs = [other.lookup(rev) for rev in revs]
6308 revs = [other.lookup(rev) for rev in revs]
6304 ui.debug('comparing with %s\n' % util.hidepassword(source))
6309 ui.debug('comparing with %s\n' % util.hidepassword(source))
6305 repo.ui.pushbuffer()
6310 repo.ui.pushbuffer()
6306 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6311 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6307 repo.ui.popbuffer()
6312 repo.ui.popbuffer()
6308 return source, sbranch, other, commoninc, commoninc[1]
6313 return source, sbranch, other, commoninc, commoninc[1]
6309
6314
6310 if needsincoming:
6315 if needsincoming:
6311 source, sbranch, sother, commoninc, incoming = getincoming()
6316 source, sbranch, sother, commoninc, incoming = getincoming()
6312 else:
6317 else:
6313 source = sbranch = sother = commoninc = incoming = None
6318 source = sbranch = sother = commoninc = incoming = None
6314
6319
6315 def getoutgoing():
6320 def getoutgoing():
6316 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6321 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6317 dbranch = branches[0]
6322 dbranch = branches[0]
6318 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6323 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6319 if source != dest:
6324 if source != dest:
6320 try:
6325 try:
6321 dother = hg.peer(repo, {}, dest)
6326 dother = hg.peer(repo, {}, dest)
6322 except error.RepoError:
6327 except error.RepoError:
6323 if opts.get('remote'):
6328 if opts.get('remote'):
6324 raise
6329 raise
6325 return dest, dbranch, None, None
6330 return dest, dbranch, None, None
6326 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6331 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6327 elif sother is None:
6332 elif sother is None:
6328 # there is no explicit destination peer, but source one is invalid
6333 # there is no explicit destination peer, but source one is invalid
6329 return dest, dbranch, None, None
6334 return dest, dbranch, None, None
6330 else:
6335 else:
6331 dother = sother
6336 dother = sother
6332 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6337 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6333 common = None
6338 common = None
6334 else:
6339 else:
6335 common = commoninc
6340 common = commoninc
6336 if revs:
6341 if revs:
6337 revs = [repo.lookup(rev) for rev in revs]
6342 revs = [repo.lookup(rev) for rev in revs]
6338 repo.ui.pushbuffer()
6343 repo.ui.pushbuffer()
6339 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6344 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6340 commoninc=common)
6345 commoninc=common)
6341 repo.ui.popbuffer()
6346 repo.ui.popbuffer()
6342 return dest, dbranch, dother, outgoing
6347 return dest, dbranch, dother, outgoing
6343
6348
6344 if needsoutgoing:
6349 if needsoutgoing:
6345 dest, dbranch, dother, outgoing = getoutgoing()
6350 dest, dbranch, dother, outgoing = getoutgoing()
6346 else:
6351 else:
6347 dest = dbranch = dother = outgoing = None
6352 dest = dbranch = dother = outgoing = None
6348
6353
6349 if opts.get('remote'):
6354 if opts.get('remote'):
6350 t = []
6355 t = []
6351 if incoming:
6356 if incoming:
6352 t.append(_('1 or more incoming'))
6357 t.append(_('1 or more incoming'))
6353 o = outgoing.missing
6358 o = outgoing.missing
6354 if o:
6359 if o:
6355 t.append(_('%d outgoing') % len(o))
6360 t.append(_('%d outgoing') % len(o))
6356 other = dother or sother
6361 other = dother or sother
6357 if 'bookmarks' in other.listkeys('namespaces'):
6362 if 'bookmarks' in other.listkeys('namespaces'):
6358 counts = bookmarks.summary(repo, other)
6363 counts = bookmarks.summary(repo, other)
6359 if counts[0] > 0:
6364 if counts[0] > 0:
6360 t.append(_('%d incoming bookmarks') % counts[0])
6365 t.append(_('%d incoming bookmarks') % counts[0])
6361 if counts[1] > 0:
6366 if counts[1] > 0:
6362 t.append(_('%d outgoing bookmarks') % counts[1])
6367 t.append(_('%d outgoing bookmarks') % counts[1])
6363
6368
6364 if t:
6369 if t:
6365 # i18n: column positioning for "hg summary"
6370 # i18n: column positioning for "hg summary"
6366 ui.write(_('remote: %s\n') % (', '.join(t)))
6371 ui.write(_('remote: %s\n') % (', '.join(t)))
6367 else:
6372 else:
6368 # i18n: column positioning for "hg summary"
6373 # i18n: column positioning for "hg summary"
6369 ui.status(_('remote: (synced)\n'))
6374 ui.status(_('remote: (synced)\n'))
6370
6375
6371 cmdutil.summaryremotehooks(ui, repo, opts,
6376 cmdutil.summaryremotehooks(ui, repo, opts,
6372 ((source, sbranch, sother, commoninc),
6377 ((source, sbranch, sother, commoninc),
6373 (dest, dbranch, dother, outgoing)))
6378 (dest, dbranch, dother, outgoing)))
6374
6379
6375 @command('tag',
6380 @command('tag',
6376 [('f', 'force', None, _('force tag')),
6381 [('f', 'force', None, _('force tag')),
6377 ('l', 'local', None, _('make the tag local')),
6382 ('l', 'local', None, _('make the tag local')),
6378 ('r', 'rev', '', _('revision to tag'), _('REV')),
6383 ('r', 'rev', '', _('revision to tag'), _('REV')),
6379 ('', 'remove', None, _('remove a tag')),
6384 ('', 'remove', None, _('remove a tag')),
6380 # -l/--local is already there, commitopts cannot be used
6385 # -l/--local is already there, commitopts cannot be used
6381 ('e', 'edit', None, _('invoke editor on commit messages')),
6386 ('e', 'edit', None, _('invoke editor on commit messages')),
6382 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6387 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6383 ] + commitopts2,
6388 ] + commitopts2,
6384 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6389 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6385 def tag(ui, repo, name1, *names, **opts):
6390 def tag(ui, repo, name1, *names, **opts):
6386 """add one or more tags for the current or given revision
6391 """add one or more tags for the current or given revision
6387
6392
6388 Name a particular revision using <name>.
6393 Name a particular revision using <name>.
6389
6394
6390 Tags are used to name particular revisions of the repository and are
6395 Tags are used to name particular revisions of the repository and are
6391 very useful to compare different revisions, to go back to significant
6396 very useful to compare different revisions, to go back to significant
6392 earlier versions or to mark branch points as releases, etc. Changing
6397 earlier versions or to mark branch points as releases, etc. Changing
6393 an existing tag is normally disallowed; use -f/--force to override.
6398 an existing tag is normally disallowed; use -f/--force to override.
6394
6399
6395 If no revision is given, the parent of the working directory is
6400 If no revision is given, the parent of the working directory is
6396 used.
6401 used.
6397
6402
6398 To facilitate version control, distribution, and merging of tags,
6403 To facilitate version control, distribution, and merging of tags,
6399 they are stored as a file named ".hgtags" which is managed similarly
6404 they are stored as a file named ".hgtags" which is managed similarly
6400 to other project files and can be hand-edited if necessary. This
6405 to other project files and can be hand-edited if necessary. This
6401 also means that tagging creates a new commit. The file
6406 also means that tagging creates a new commit. The file
6402 ".hg/localtags" is used for local tags (not shared among
6407 ".hg/localtags" is used for local tags (not shared among
6403 repositories).
6408 repositories).
6404
6409
6405 Tag commits are usually made at the head of a branch. If the parent
6410 Tag commits are usually made at the head of a branch. If the parent
6406 of the working directory is not a branch head, :hg:`tag` aborts; use
6411 of the working directory is not a branch head, :hg:`tag` aborts; use
6407 -f/--force to force the tag commit to be based on a non-head
6412 -f/--force to force the tag commit to be based on a non-head
6408 changeset.
6413 changeset.
6409
6414
6410 See :hg:`help dates` for a list of formats valid for -d/--date.
6415 See :hg:`help dates` for a list of formats valid for -d/--date.
6411
6416
6412 Since tag names have priority over branch names during revision
6417 Since tag names have priority over branch names during revision
6413 lookup, using an existing branch name as a tag name is discouraged.
6418 lookup, using an existing branch name as a tag name is discouraged.
6414
6419
6415 Returns 0 on success.
6420 Returns 0 on success.
6416 """
6421 """
6417 wlock = lock = None
6422 wlock = lock = None
6418 try:
6423 try:
6419 wlock = repo.wlock()
6424 wlock = repo.wlock()
6420 lock = repo.lock()
6425 lock = repo.lock()
6421 rev_ = "."
6426 rev_ = "."
6422 names = [t.strip() for t in (name1,) + names]
6427 names = [t.strip() for t in (name1,) + names]
6423 if len(names) != len(set(names)):
6428 if len(names) != len(set(names)):
6424 raise error.Abort(_('tag names must be unique'))
6429 raise error.Abort(_('tag names must be unique'))
6425 for n in names:
6430 for n in names:
6426 scmutil.checknewlabel(repo, n, 'tag')
6431 scmutil.checknewlabel(repo, n, 'tag')
6427 if not n:
6432 if not n:
6428 raise error.Abort(_('tag names cannot consist entirely of '
6433 raise error.Abort(_('tag names cannot consist entirely of '
6429 'whitespace'))
6434 'whitespace'))
6430 if opts.get('rev') and opts.get('remove'):
6435 if opts.get('rev') and opts.get('remove'):
6431 raise error.Abort(_("--rev and --remove are incompatible"))
6436 raise error.Abort(_("--rev and --remove are incompatible"))
6432 if opts.get('rev'):
6437 if opts.get('rev'):
6433 rev_ = opts['rev']
6438 rev_ = opts['rev']
6434 message = opts.get('message')
6439 message = opts.get('message')
6435 if opts.get('remove'):
6440 if opts.get('remove'):
6436 if opts.get('local'):
6441 if opts.get('local'):
6437 expectedtype = 'local'
6442 expectedtype = 'local'
6438 else:
6443 else:
6439 expectedtype = 'global'
6444 expectedtype = 'global'
6440
6445
6441 for n in names:
6446 for n in names:
6442 if not repo.tagtype(n):
6447 if not repo.tagtype(n):
6443 raise error.Abort(_("tag '%s' does not exist") % n)
6448 raise error.Abort(_("tag '%s' does not exist") % n)
6444 if repo.tagtype(n) != expectedtype:
6449 if repo.tagtype(n) != expectedtype:
6445 if expectedtype == 'global':
6450 if expectedtype == 'global':
6446 raise error.Abort(_("tag '%s' is not a global tag") % n)
6451 raise error.Abort(_("tag '%s' is not a global tag") % n)
6447 else:
6452 else:
6448 raise error.Abort(_("tag '%s' is not a local tag") % n)
6453 raise error.Abort(_("tag '%s' is not a local tag") % n)
6449 rev_ = 'null'
6454 rev_ = 'null'
6450 if not message:
6455 if not message:
6451 # we don't translate commit messages
6456 # we don't translate commit messages
6452 message = 'Removed tag %s' % ', '.join(names)
6457 message = 'Removed tag %s' % ', '.join(names)
6453 elif not opts.get('force'):
6458 elif not opts.get('force'):
6454 for n in names:
6459 for n in names:
6455 if n in repo.tags():
6460 if n in repo.tags():
6456 raise error.Abort(_("tag '%s' already exists "
6461 raise error.Abort(_("tag '%s' already exists "
6457 "(use -f to force)") % n)
6462 "(use -f to force)") % n)
6458 if not opts.get('local'):
6463 if not opts.get('local'):
6459 p1, p2 = repo.dirstate.parents()
6464 p1, p2 = repo.dirstate.parents()
6460 if p2 != nullid:
6465 if p2 != nullid:
6461 raise error.Abort(_('uncommitted merge'))
6466 raise error.Abort(_('uncommitted merge'))
6462 bheads = repo.branchheads()
6467 bheads = repo.branchheads()
6463 if not opts.get('force') and bheads and p1 not in bheads:
6468 if not opts.get('force') and bheads and p1 not in bheads:
6464 raise error.Abort(_('not at a branch head (use -f to force)'))
6469 raise error.Abort(_('not at a branch head (use -f to force)'))
6465 r = scmutil.revsingle(repo, rev_).node()
6470 r = scmutil.revsingle(repo, rev_).node()
6466
6471
6467 if not message:
6472 if not message:
6468 # we don't translate commit messages
6473 # we don't translate commit messages
6469 message = ('Added tag %s for changeset %s' %
6474 message = ('Added tag %s for changeset %s' %
6470 (', '.join(names), short(r)))
6475 (', '.join(names), short(r)))
6471
6476
6472 date = opts.get('date')
6477 date = opts.get('date')
6473 if date:
6478 if date:
6474 date = util.parsedate(date)
6479 date = util.parsedate(date)
6475
6480
6476 if opts.get('remove'):
6481 if opts.get('remove'):
6477 editform = 'tag.remove'
6482 editform = 'tag.remove'
6478 else:
6483 else:
6479 editform = 'tag.add'
6484 editform = 'tag.add'
6480 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6485 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6481
6486
6482 # don't allow tagging the null rev
6487 # don't allow tagging the null rev
6483 if (not opts.get('remove') and
6488 if (not opts.get('remove') and
6484 scmutil.revsingle(repo, rev_).rev() == nullrev):
6489 scmutil.revsingle(repo, rev_).rev() == nullrev):
6485 raise error.Abort(_("cannot tag null revision"))
6490 raise error.Abort(_("cannot tag null revision"))
6486
6491
6487 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6492 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6488 editor=editor)
6493 editor=editor)
6489 finally:
6494 finally:
6490 release(lock, wlock)
6495 release(lock, wlock)
6491
6496
6492 @command('tags', formatteropts, '')
6497 @command('tags', formatteropts, '')
6493 def tags(ui, repo, **opts):
6498 def tags(ui, repo, **opts):
6494 """list repository tags
6499 """list repository tags
6495
6500
6496 This lists both regular and local tags. When the -v/--verbose
6501 This lists both regular and local tags. When the -v/--verbose
6497 switch is used, a third column "local" is printed for local tags.
6502 switch is used, a third column "local" is printed for local tags.
6498
6503
6499 Returns 0 on success.
6504 Returns 0 on success.
6500 """
6505 """
6501
6506
6502 fm = ui.formatter('tags', opts)
6507 fm = ui.formatter('tags', opts)
6503 hexfunc = fm.hexfunc
6508 hexfunc = fm.hexfunc
6504 tagtype = ""
6509 tagtype = ""
6505
6510
6506 for t, n in reversed(repo.tagslist()):
6511 for t, n in reversed(repo.tagslist()):
6507 hn = hexfunc(n)
6512 hn = hexfunc(n)
6508 label = 'tags.normal'
6513 label = 'tags.normal'
6509 tagtype = ''
6514 tagtype = ''
6510 if repo.tagtype(t) == 'local':
6515 if repo.tagtype(t) == 'local':
6511 label = 'tags.local'
6516 label = 'tags.local'
6512 tagtype = 'local'
6517 tagtype = 'local'
6513
6518
6514 fm.startitem()
6519 fm.startitem()
6515 fm.write('tag', '%s', t, label=label)
6520 fm.write('tag', '%s', t, label=label)
6516 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6521 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6517 fm.condwrite(not ui.quiet, 'rev node', fmt,
6522 fm.condwrite(not ui.quiet, 'rev node', fmt,
6518 repo.changelog.rev(n), hn, label=label)
6523 repo.changelog.rev(n), hn, label=label)
6519 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6524 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6520 tagtype, label=label)
6525 tagtype, label=label)
6521 fm.plain('\n')
6526 fm.plain('\n')
6522 fm.end()
6527 fm.end()
6523
6528
6524 @command('tip',
6529 @command('tip',
6525 [('p', 'patch', None, _('show patch')),
6530 [('p', 'patch', None, _('show patch')),
6526 ('g', 'git', None, _('use git extended diff format')),
6531 ('g', 'git', None, _('use git extended diff format')),
6527 ] + templateopts,
6532 ] + templateopts,
6528 _('[-p] [-g]'))
6533 _('[-p] [-g]'))
6529 def tip(ui, repo, **opts):
6534 def tip(ui, repo, **opts):
6530 """show the tip revision (DEPRECATED)
6535 """show the tip revision (DEPRECATED)
6531
6536
6532 The tip revision (usually just called the tip) is the changeset
6537 The tip revision (usually just called the tip) is the changeset
6533 most recently added to the repository (and therefore the most
6538 most recently added to the repository (and therefore the most
6534 recently changed head).
6539 recently changed head).
6535
6540
6536 If you have just made a commit, that commit will be the tip. If
6541 If you have just made a commit, that commit will be the tip. If
6537 you have just pulled changes from another repository, the tip of
6542 you have just pulled changes from another repository, the tip of
6538 that repository becomes the current tip. The "tip" tag is special
6543 that repository becomes the current tip. The "tip" tag is special
6539 and cannot be renamed or assigned to a different changeset.
6544 and cannot be renamed or assigned to a different changeset.
6540
6545
6541 This command is deprecated, please use :hg:`heads` instead.
6546 This command is deprecated, please use :hg:`heads` instead.
6542
6547
6543 Returns 0 on success.
6548 Returns 0 on success.
6544 """
6549 """
6545 displayer = cmdutil.show_changeset(ui, repo, opts)
6550 displayer = cmdutil.show_changeset(ui, repo, opts)
6546 displayer.show(repo['tip'])
6551 displayer.show(repo['tip'])
6547 displayer.close()
6552 displayer.close()
6548
6553
6549 @command('unbundle',
6554 @command('unbundle',
6550 [('u', 'update', None,
6555 [('u', 'update', None,
6551 _('update to new branch head if changesets were unbundled'))],
6556 _('update to new branch head if changesets were unbundled'))],
6552 _('[-u] FILE...'))
6557 _('[-u] FILE...'))
6553 def unbundle(ui, repo, fname1, *fnames, **opts):
6558 def unbundle(ui, repo, fname1, *fnames, **opts):
6554 """apply one or more changegroup files
6559 """apply one or more changegroup files
6555
6560
6556 Apply one or more compressed changegroup files generated by the
6561 Apply one or more compressed changegroup files generated by the
6557 bundle command.
6562 bundle command.
6558
6563
6559 Returns 0 on success, 1 if an update has unresolved files.
6564 Returns 0 on success, 1 if an update has unresolved files.
6560 """
6565 """
6561 fnames = (fname1,) + fnames
6566 fnames = (fname1,) + fnames
6562
6567
6563 lock = repo.lock()
6568 lock = repo.lock()
6564 try:
6569 try:
6565 for fname in fnames:
6570 for fname in fnames:
6566 f = hg.openpath(ui, fname)
6571 f = hg.openpath(ui, fname)
6567 gen = exchange.readbundle(ui, f, fname)
6572 gen = exchange.readbundle(ui, f, fname)
6568 if isinstance(gen, bundle2.unbundle20):
6573 if isinstance(gen, bundle2.unbundle20):
6569 tr = repo.transaction('unbundle')
6574 tr = repo.transaction('unbundle')
6570 try:
6575 try:
6571 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6576 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6572 url='bundle:' + fname)
6577 url='bundle:' + fname)
6573 tr.close()
6578 tr.close()
6574 except error.BundleUnknownFeatureError as exc:
6579 except error.BundleUnknownFeatureError as exc:
6575 raise error.Abort(_('%s: unknown bundle feature, %s')
6580 raise error.Abort(_('%s: unknown bundle feature, %s')
6576 % (fname, exc),
6581 % (fname, exc),
6577 hint=_("see https://mercurial-scm.org/"
6582 hint=_("see https://mercurial-scm.org/"
6578 "wiki/BundleFeature for more "
6583 "wiki/BundleFeature for more "
6579 "information"))
6584 "information"))
6580 finally:
6585 finally:
6581 if tr:
6586 if tr:
6582 tr.release()
6587 tr.release()
6583 changes = [r.get('return', 0)
6588 changes = [r.get('return', 0)
6584 for r in op.records['changegroup']]
6589 for r in op.records['changegroup']]
6585 modheads = changegroup.combineresults(changes)
6590 modheads = changegroup.combineresults(changes)
6586 elif isinstance(gen, streamclone.streamcloneapplier):
6591 elif isinstance(gen, streamclone.streamcloneapplier):
6587 raise error.Abort(
6592 raise error.Abort(
6588 _('packed bundles cannot be applied with '
6593 _('packed bundles cannot be applied with '
6589 '"hg unbundle"'),
6594 '"hg unbundle"'),
6590 hint=_('use "hg debugapplystreamclonebundle"'))
6595 hint=_('use "hg debugapplystreamclonebundle"'))
6591 else:
6596 else:
6592 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6597 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6593 finally:
6598 finally:
6594 lock.release()
6599 lock.release()
6595
6600
6596 return postincoming(ui, repo, modheads, opts.get('update'), None)
6601 return postincoming(ui, repo, modheads, opts.get('update'), None)
6597
6602
6598 @command('^update|up|checkout|co',
6603 @command('^update|up|checkout|co',
6599 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6604 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6600 ('c', 'check', None,
6605 ('c', 'check', None,
6601 _('update across branches if no uncommitted changes')),
6606 _('update across branches if no uncommitted changes')),
6602 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6607 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6603 ('r', 'rev', '', _('revision'), _('REV'))
6608 ('r', 'rev', '', _('revision'), _('REV'))
6604 ] + mergetoolopts,
6609 ] + mergetoolopts,
6605 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6610 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6606 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6611 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6607 tool=None):
6612 tool=None):
6608 """update working directory (or switch revisions)
6613 """update working directory (or switch revisions)
6609
6614
6610 Update the repository's working directory to the specified
6615 Update the repository's working directory to the specified
6611 changeset. If no changeset is specified, update to the tip of the
6616 changeset. If no changeset is specified, update to the tip of the
6612 current named branch and move the active bookmark (see :hg:`help
6617 current named branch and move the active bookmark (see :hg:`help
6613 bookmarks`).
6618 bookmarks`).
6614
6619
6615 Update sets the working directory's parent revision to the specified
6620 Update sets the working directory's parent revision to the specified
6616 changeset (see :hg:`help parents`).
6621 changeset (see :hg:`help parents`).
6617
6622
6618 If the changeset is not a descendant or ancestor of the working
6623 If the changeset is not a descendant or ancestor of the working
6619 directory's parent, the update is aborted. With the -c/--check
6624 directory's parent, the update is aborted. With the -c/--check
6620 option, the working directory is checked for uncommitted changes; if
6625 option, the working directory is checked for uncommitted changes; if
6621 none are found, the working directory is updated to the specified
6626 none are found, the working directory is updated to the specified
6622 changeset.
6627 changeset.
6623
6628
6624 .. container:: verbose
6629 .. container:: verbose
6625
6630
6626 The following rules apply when the working directory contains
6631 The following rules apply when the working directory contains
6627 uncommitted changes:
6632 uncommitted changes:
6628
6633
6629 1. If neither -c/--check nor -C/--clean is specified, and if
6634 1. If neither -c/--check nor -C/--clean is specified, and if
6630 the requested changeset is an ancestor or descendant of
6635 the requested changeset is an ancestor or descendant of
6631 the working directory's parent, the uncommitted changes
6636 the working directory's parent, the uncommitted changes
6632 are merged into the requested changeset and the merged
6637 are merged into the requested changeset and the merged
6633 result is left uncommitted. If the requested changeset is
6638 result is left uncommitted. If the requested changeset is
6634 not an ancestor or descendant (that is, it is on another
6639 not an ancestor or descendant (that is, it is on another
6635 branch), the update is aborted and the uncommitted changes
6640 branch), the update is aborted and the uncommitted changes
6636 are preserved.
6641 are preserved.
6637
6642
6638 2. With the -c/--check option, the update is aborted and the
6643 2. With the -c/--check option, the update is aborted and the
6639 uncommitted changes are preserved.
6644 uncommitted changes are preserved.
6640
6645
6641 3. With the -C/--clean option, uncommitted changes are discarded and
6646 3. With the -C/--clean option, uncommitted changes are discarded and
6642 the working directory is updated to the requested changeset.
6647 the working directory is updated to the requested changeset.
6643
6648
6644 To cancel an uncommitted merge (and lose your changes), use
6649 To cancel an uncommitted merge (and lose your changes), use
6645 :hg:`update --clean .`.
6650 :hg:`update --clean .`.
6646
6651
6647 Use null as the changeset to remove the working directory (like
6652 Use null as the changeset to remove the working directory (like
6648 :hg:`clone -U`).
6653 :hg:`clone -U`).
6649
6654
6650 If you want to revert just one file to an older revision, use
6655 If you want to revert just one file to an older revision, use
6651 :hg:`revert [-r REV] NAME`.
6656 :hg:`revert [-r REV] NAME`.
6652
6657
6653 See :hg:`help dates` for a list of formats valid for -d/--date.
6658 See :hg:`help dates` for a list of formats valid for -d/--date.
6654
6659
6655 Returns 0 on success, 1 if there are unresolved files.
6660 Returns 0 on success, 1 if there are unresolved files.
6656 """
6661 """
6657 movemarkfrom = None
6662 movemarkfrom = None
6658 if rev and node:
6663 if rev and node:
6659 raise error.Abort(_("please specify just one revision"))
6664 raise error.Abort(_("please specify just one revision"))
6660
6665
6661 if rev is None or rev == '':
6666 if rev is None or rev == '':
6662 rev = node
6667 rev = node
6663
6668
6664 wlock = repo.wlock()
6669 wlock = repo.wlock()
6665 try:
6670 try:
6666 cmdutil.clearunfinished(repo)
6671 cmdutil.clearunfinished(repo)
6667
6672
6668 if date:
6673 if date:
6669 if rev is not None:
6674 if rev is not None:
6670 raise error.Abort(_("you can't specify a revision and a date"))
6675 raise error.Abort(_("you can't specify a revision and a date"))
6671 rev = cmdutil.finddate(ui, repo, date)
6676 rev = cmdutil.finddate(ui, repo, date)
6672
6677
6673 # if we defined a bookmark, we have to remember the original name
6678 # if we defined a bookmark, we have to remember the original name
6674 brev = rev
6679 brev = rev
6675 rev = scmutil.revsingle(repo, rev, rev).rev()
6680 rev = scmutil.revsingle(repo, rev, rev).rev()
6676
6681
6677 if check and clean:
6682 if check and clean:
6678 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6683 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6679 )
6684 )
6680
6685
6681 if check:
6686 if check:
6682 cmdutil.bailifchanged(repo, merge=False)
6687 cmdutil.bailifchanged(repo, merge=False)
6683 if rev is None:
6688 if rev is None:
6684 updata = destutil.destupdate(repo, clean=clean, check=check)
6689 updata = destutil.destupdate(repo, clean=clean, check=check)
6685 rev, movemarkfrom, brev = updata
6690 rev, movemarkfrom, brev = updata
6686
6691
6687 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6692 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6688
6693
6689 if clean:
6694 if clean:
6690 ret = hg.clean(repo, rev)
6695 ret = hg.clean(repo, rev)
6691 else:
6696 else:
6692 ret = hg.update(repo, rev)
6697 ret = hg.update(repo, rev)
6693
6698
6694 if not ret and movemarkfrom:
6699 if not ret and movemarkfrom:
6695 if movemarkfrom == repo['.'].node():
6700 if movemarkfrom == repo['.'].node():
6696 pass # no-op update
6701 pass # no-op update
6697 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6702 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6698 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6703 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6699 else:
6704 else:
6700 # this can happen with a non-linear update
6705 # this can happen with a non-linear update
6701 ui.status(_("(leaving bookmark %s)\n") %
6706 ui.status(_("(leaving bookmark %s)\n") %
6702 repo._activebookmark)
6707 repo._activebookmark)
6703 bookmarks.deactivate(repo)
6708 bookmarks.deactivate(repo)
6704 elif brev in repo._bookmarks:
6709 elif brev in repo._bookmarks:
6705 bookmarks.activate(repo, brev)
6710 bookmarks.activate(repo, brev)
6706 ui.status(_("(activating bookmark %s)\n") % brev)
6711 ui.status(_("(activating bookmark %s)\n") % brev)
6707 elif brev:
6712 elif brev:
6708 if repo._activebookmark:
6713 if repo._activebookmark:
6709 ui.status(_("(leaving bookmark %s)\n") %
6714 ui.status(_("(leaving bookmark %s)\n") %
6710 repo._activebookmark)
6715 repo._activebookmark)
6711 bookmarks.deactivate(repo)
6716 bookmarks.deactivate(repo)
6712 finally:
6717 finally:
6713 wlock.release()
6718 wlock.release()
6714
6719
6715 return ret
6720 return ret
6716
6721
6717 @command('verify', [])
6722 @command('verify', [])
6718 def verify(ui, repo):
6723 def verify(ui, repo):
6719 """verify the integrity of the repository
6724 """verify the integrity of the repository
6720
6725
6721 Verify the integrity of the current repository.
6726 Verify the integrity of the current repository.
6722
6727
6723 This will perform an extensive check of the repository's
6728 This will perform an extensive check of the repository's
6724 integrity, validating the hashes and checksums of each entry in
6729 integrity, validating the hashes and checksums of each entry in
6725 the changelog, manifest, and tracked files, as well as the
6730 the changelog, manifest, and tracked files, as well as the
6726 integrity of their crosslinks and indices.
6731 integrity of their crosslinks and indices.
6727
6732
6728 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6733 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6729 for more information about recovery from corruption of the
6734 for more information about recovery from corruption of the
6730 repository.
6735 repository.
6731
6736
6732 Returns 0 on success, 1 if errors are encountered.
6737 Returns 0 on success, 1 if errors are encountered.
6733 """
6738 """
6734 return hg.verify(repo)
6739 return hg.verify(repo)
6735
6740
6736 @command('version', [], norepo=True)
6741 @command('version', [], norepo=True)
6737 def version_(ui):
6742 def version_(ui):
6738 """output version and copyright information"""
6743 """output version and copyright information"""
6739 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6744 ui.write(_("Mercurial Distributed SCM (version %s)\n")
6740 % util.version())
6745 % util.version())
6741 ui.status(_(
6746 ui.status(_(
6742 "(see https://mercurial-scm.org for more information)\n"
6747 "(see https://mercurial-scm.org for more information)\n"
6743 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6748 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
6744 "This is free software; see the source for copying conditions. "
6749 "This is free software; see the source for copying conditions. "
6745 "There is NO\nwarranty; "
6750 "There is NO\nwarranty; "
6746 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6751 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
6747 ))
6752 ))
6748
6753
6749 ui.note(_("\nEnabled extensions:\n\n"))
6754 ui.note(_("\nEnabled extensions:\n\n"))
6750 if ui.verbose:
6755 if ui.verbose:
6751 # format names and versions into columns
6756 # format names and versions into columns
6752 names = []
6757 names = []
6753 vers = []
6758 vers = []
6754 for name, module in extensions.extensions():
6759 for name, module in extensions.extensions():
6755 names.append(name)
6760 names.append(name)
6756 vers.append(extensions.moduleversion(module))
6761 vers.append(extensions.moduleversion(module))
6757 if names:
6762 if names:
6758 maxnamelen = max(len(n) for n in names)
6763 maxnamelen = max(len(n) for n in names)
6759 for i, name in enumerate(names):
6764 for i, name in enumerate(names):
6760 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
6765 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now