##// END OF EJS Templates
paths: port to generic templater...
Yuya Nishihara -
r27728:29403715 default
parent child Browse files
Show More
@@ -1,7041 +1,7049 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, bin, nullhex, nullid, nullrev, short
8 from node import hex, bin, nullhex, 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 import merge as mergemod
18 import merge as mergemod
19 import minirst, revset, fileset
19 import minirst, revset, fileset
20 import dagparser, context, simplemerge, graphmod, copies
20 import dagparser, context, simplemerge, graphmod, copies
21 import random, operator
21 import random, operator
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
22 import setdiscovery, treediscovery, dagutil, pvec, localrepo, destutil
23 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
23 import phases, obsolete, exchange, bundle2, repair, lock as lockmod
24 import ui as uimod
24 import ui as uimod
25 import streamclone
25 import streamclone
26 import commandserver
26 import commandserver
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 debugrevlogopts = [
175 debugrevlogopts = [
176 ('c', 'changelog', False, _('open changelog')),
176 ('c', 'changelog', False, _('open changelog')),
177 ('m', 'manifest', False, _('open manifest')),
177 ('m', 'manifest', False, _('open manifest')),
178 ('', 'dir', False, _('open directory manifest')),
178 ('', 'dir', False, _('open directory manifest')),
179 ]
179 ]
180
180
181 # Commands start here, listed alphabetically
181 # Commands start here, listed alphabetically
182
182
183 @command('^add',
183 @command('^add',
184 walkopts + subrepoopts + dryrunopts,
184 walkopts + subrepoopts + dryrunopts,
185 _('[OPTION]... [FILE]...'),
185 _('[OPTION]... [FILE]...'),
186 inferrepo=True)
186 inferrepo=True)
187 def add(ui, repo, *pats, **opts):
187 def add(ui, repo, *pats, **opts):
188 """add the specified files on the next commit
188 """add the specified files on the next commit
189
189
190 Schedule files to be version controlled and added to the
190 Schedule files to be version controlled and added to the
191 repository.
191 repository.
192
192
193 The files will be added to the repository at the next commit. To
193 The files will be added to the repository at the next commit. To
194 undo an add before that, see :hg:`forget`.
194 undo an add before that, see :hg:`forget`.
195
195
196 If no names are given, add all files to the repository (except
196 If no names are given, add all files to the repository (except
197 files matching ``.hgignore``).
197 files matching ``.hgignore``).
198
198
199 .. container:: verbose
199 .. container:: verbose
200
200
201 Examples:
201 Examples:
202
202
203 - New (unknown) files are added
203 - New (unknown) files are added
204 automatically by :hg:`add`::
204 automatically by :hg:`add`::
205
205
206 $ ls
206 $ ls
207 foo.c
207 foo.c
208 $ hg status
208 $ hg status
209 ? foo.c
209 ? foo.c
210 $ hg add
210 $ hg add
211 adding foo.c
211 adding foo.c
212 $ hg status
212 $ hg status
213 A foo.c
213 A foo.c
214
214
215 - Specific files to be added can be specified::
215 - Specific files to be added can be specified::
216
216
217 $ ls
217 $ ls
218 bar.c foo.c
218 bar.c foo.c
219 $ hg status
219 $ hg status
220 ? bar.c
220 ? bar.c
221 ? foo.c
221 ? foo.c
222 $ hg add bar.c
222 $ hg add bar.c
223 $ hg status
223 $ hg status
224 A bar.c
224 A bar.c
225 ? foo.c
225 ? foo.c
226
226
227 Returns 0 if all files are successfully added.
227 Returns 0 if all files are successfully added.
228 """
228 """
229
229
230 m = scmutil.match(repo[None], pats, opts)
230 m = scmutil.match(repo[None], pats, opts)
231 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
231 rejected = cmdutil.add(ui, repo, m, "", False, **opts)
232 return rejected and 1 or 0
232 return rejected and 1 or 0
233
233
234 @command('addremove',
234 @command('addremove',
235 similarityopts + subrepoopts + walkopts + dryrunopts,
235 similarityopts + subrepoopts + walkopts + dryrunopts,
236 _('[OPTION]... [FILE]...'),
236 _('[OPTION]... [FILE]...'),
237 inferrepo=True)
237 inferrepo=True)
238 def addremove(ui, repo, *pats, **opts):
238 def addremove(ui, repo, *pats, **opts):
239 """add all new files, delete all missing files
239 """add all new files, delete all missing files
240
240
241 Add all new files and remove all missing files from the
241 Add all new files and remove all missing files from the
242 repository.
242 repository.
243
243
244 Unless names are given, new files are ignored if they match any of
244 Unless names are given, new files are ignored if they match any of
245 the patterns in ``.hgignore``. As with add, these changes take
245 the patterns in ``.hgignore``. As with add, these changes take
246 effect at the next commit.
246 effect at the next commit.
247
247
248 Use the -s/--similarity option to detect renamed files. This
248 Use the -s/--similarity option to detect renamed files. This
249 option takes a percentage between 0 (disabled) and 100 (files must
249 option takes a percentage between 0 (disabled) and 100 (files must
250 be identical) as its parameter. With a parameter greater than 0,
250 be identical) as its parameter. With a parameter greater than 0,
251 this compares every removed file with every added file and records
251 this compares every removed file with every added file and records
252 those similar enough as renames. Detecting renamed files this way
252 those similar enough as renames. Detecting renamed files this way
253 can be expensive. After using this option, :hg:`status -C` can be
253 can be expensive. After using this option, :hg:`status -C` can be
254 used to check which files were identified as moved or renamed. If
254 used to check which files were identified as moved or renamed. If
255 not specified, -s/--similarity defaults to 100 and only renames of
255 not specified, -s/--similarity defaults to 100 and only renames of
256 identical files are detected.
256 identical files are detected.
257
257
258 .. container:: verbose
258 .. container:: verbose
259
259
260 Examples:
260 Examples:
261
261
262 - A number of files (bar.c and foo.c) are new,
262 - A number of files (bar.c and foo.c) are new,
263 while foobar.c has been removed (without using :hg:`remove`)
263 while foobar.c has been removed (without using :hg:`remove`)
264 from the repository::
264 from the repository::
265
265
266 $ ls
266 $ ls
267 bar.c foo.c
267 bar.c foo.c
268 $ hg status
268 $ hg status
269 ! foobar.c
269 ! foobar.c
270 ? bar.c
270 ? bar.c
271 ? foo.c
271 ? foo.c
272 $ hg addremove
272 $ hg addremove
273 adding bar.c
273 adding bar.c
274 adding foo.c
274 adding foo.c
275 removing foobar.c
275 removing foobar.c
276 $ hg status
276 $ hg status
277 A bar.c
277 A bar.c
278 A foo.c
278 A foo.c
279 R foobar.c
279 R foobar.c
280
280
281 - A file foobar.c was moved to foo.c without using :hg:`rename`.
281 - A file foobar.c was moved to foo.c without using :hg:`rename`.
282 Afterwards, it was edited slightly::
282 Afterwards, it was edited slightly::
283
283
284 $ ls
284 $ ls
285 foo.c
285 foo.c
286 $ hg status
286 $ hg status
287 ! foobar.c
287 ! foobar.c
288 ? foo.c
288 ? foo.c
289 $ hg addremove --similarity 90
289 $ hg addremove --similarity 90
290 removing foobar.c
290 removing foobar.c
291 adding foo.c
291 adding foo.c
292 recording removal of foobar.c as rename to foo.c (94% similar)
292 recording removal of foobar.c as rename to foo.c (94% similar)
293 $ hg status -C
293 $ hg status -C
294 A foo.c
294 A foo.c
295 foobar.c
295 foobar.c
296 R foobar.c
296 R foobar.c
297
297
298 Returns 0 if all files are successfully added.
298 Returns 0 if all files are successfully added.
299 """
299 """
300 try:
300 try:
301 sim = float(opts.get('similarity') or 100)
301 sim = float(opts.get('similarity') or 100)
302 except ValueError:
302 except ValueError:
303 raise error.Abort(_('similarity must be a number'))
303 raise error.Abort(_('similarity must be a number'))
304 if sim < 0 or sim > 100:
304 if sim < 0 or sim > 100:
305 raise error.Abort(_('similarity must be between 0 and 100'))
305 raise error.Abort(_('similarity must be between 0 and 100'))
306 matcher = scmutil.match(repo[None], pats, opts)
306 matcher = scmutil.match(repo[None], pats, opts)
307 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
307 return scmutil.addremove(repo, matcher, "", opts, similarity=sim / 100.0)
308
308
309 @command('^annotate|blame',
309 @command('^annotate|blame',
310 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
310 [('r', 'rev', '', _('annotate the specified revision'), _('REV')),
311 ('', 'follow', None,
311 ('', 'follow', None,
312 _('follow copies/renames and list the filename (DEPRECATED)')),
312 _('follow copies/renames and list the filename (DEPRECATED)')),
313 ('', 'no-follow', None, _("don't follow copies and renames")),
313 ('', 'no-follow', None, _("don't follow copies and renames")),
314 ('a', 'text', None, _('treat all files as text')),
314 ('a', 'text', None, _('treat all files as text')),
315 ('u', 'user', None, _('list the author (long with -v)')),
315 ('u', 'user', None, _('list the author (long with -v)')),
316 ('f', 'file', None, _('list the filename')),
316 ('f', 'file', None, _('list the filename')),
317 ('d', 'date', None, _('list the date (short with -q)')),
317 ('d', 'date', None, _('list the date (short with -q)')),
318 ('n', 'number', None, _('list the revision number (default)')),
318 ('n', 'number', None, _('list the revision number (default)')),
319 ('c', 'changeset', None, _('list the changeset')),
319 ('c', 'changeset', None, _('list the changeset')),
320 ('l', 'line-number', None, _('show line number at the first appearance'))
320 ('l', 'line-number', None, _('show line number at the first appearance'))
321 ] + diffwsopts + walkopts + formatteropts,
321 ] + diffwsopts + walkopts + formatteropts,
322 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
322 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...'),
323 inferrepo=True)
323 inferrepo=True)
324 def annotate(ui, repo, *pats, **opts):
324 def annotate(ui, repo, *pats, **opts):
325 """show changeset information by line for each file
325 """show changeset information by line for each file
326
326
327 List changes in files, showing the revision id responsible for
327 List changes in files, showing the revision id responsible for
328 each line.
328 each line.
329
329
330 This command is useful for discovering when a change was made and
330 This command is useful for discovering when a change was made and
331 by whom.
331 by whom.
332
332
333 If you include --file, --user, or --date, the revision number is
333 If you include --file, --user, or --date, the revision number is
334 suppressed unless you also include --number.
334 suppressed unless you also include --number.
335
335
336 Without the -a/--text option, annotate will avoid processing files
336 Without the -a/--text option, annotate will avoid processing files
337 it detects as binary. With -a, annotate will annotate the file
337 it detects as binary. With -a, annotate will annotate the file
338 anyway, although the results will probably be neither useful
338 anyway, although the results will probably be neither useful
339 nor desirable.
339 nor desirable.
340
340
341 Returns 0 on success.
341 Returns 0 on success.
342 """
342 """
343 if not pats:
343 if not pats:
344 raise error.Abort(_('at least one filename or pattern is required'))
344 raise error.Abort(_('at least one filename or pattern is required'))
345
345
346 if opts.get('follow'):
346 if opts.get('follow'):
347 # --follow is deprecated and now just an alias for -f/--file
347 # --follow is deprecated and now just an alias for -f/--file
348 # to mimic the behavior of Mercurial before version 1.5
348 # to mimic the behavior of Mercurial before version 1.5
349 opts['file'] = True
349 opts['file'] = True
350
350
351 ctx = scmutil.revsingle(repo, opts.get('rev'))
351 ctx = scmutil.revsingle(repo, opts.get('rev'))
352
352
353 fm = ui.formatter('annotate', opts)
353 fm = ui.formatter('annotate', opts)
354 if ui.quiet:
354 if ui.quiet:
355 datefunc = util.shortdate
355 datefunc = util.shortdate
356 else:
356 else:
357 datefunc = util.datestr
357 datefunc = util.datestr
358 if ctx.rev() is None:
358 if ctx.rev() is None:
359 def hexfn(node):
359 def hexfn(node):
360 if node is None:
360 if node is None:
361 return None
361 return None
362 else:
362 else:
363 return fm.hexfunc(node)
363 return fm.hexfunc(node)
364 if opts.get('changeset'):
364 if opts.get('changeset'):
365 # omit "+" suffix which is appended to node hex
365 # omit "+" suffix which is appended to node hex
366 def formatrev(rev):
366 def formatrev(rev):
367 if rev is None:
367 if rev is None:
368 return '%d' % ctx.p1().rev()
368 return '%d' % ctx.p1().rev()
369 else:
369 else:
370 return '%d' % rev
370 return '%d' % rev
371 else:
371 else:
372 def formatrev(rev):
372 def formatrev(rev):
373 if rev is None:
373 if rev is None:
374 return '%d+' % ctx.p1().rev()
374 return '%d+' % ctx.p1().rev()
375 else:
375 else:
376 return '%d ' % rev
376 return '%d ' % rev
377 def formathex(hex):
377 def formathex(hex):
378 if hex is None:
378 if hex is None:
379 return '%s+' % fm.hexfunc(ctx.p1().node())
379 return '%s+' % fm.hexfunc(ctx.p1().node())
380 else:
380 else:
381 return '%s ' % hex
381 return '%s ' % hex
382 else:
382 else:
383 hexfn = fm.hexfunc
383 hexfn = fm.hexfunc
384 formatrev = formathex = str
384 formatrev = formathex = str
385
385
386 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
386 opmap = [('user', ' ', lambda x: x[0].user(), ui.shortuser),
387 ('number', ' ', lambda x: x[0].rev(), formatrev),
387 ('number', ' ', lambda x: x[0].rev(), formatrev),
388 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
388 ('changeset', ' ', lambda x: hexfn(x[0].node()), formathex),
389 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
389 ('date', ' ', lambda x: x[0].date(), util.cachefunc(datefunc)),
390 ('file', ' ', lambda x: x[0].path(), str),
390 ('file', ' ', lambda x: x[0].path(), str),
391 ('line_number', ':', lambda x: x[1], str),
391 ('line_number', ':', lambda x: x[1], str),
392 ]
392 ]
393 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
393 fieldnamemap = {'number': 'rev', 'changeset': 'node'}
394
394
395 if (not opts.get('user') and not opts.get('changeset')
395 if (not opts.get('user') and not opts.get('changeset')
396 and not opts.get('date') and not opts.get('file')):
396 and not opts.get('date') and not opts.get('file')):
397 opts['number'] = True
397 opts['number'] = True
398
398
399 linenumber = opts.get('line_number') is not None
399 linenumber = opts.get('line_number') is not None
400 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
400 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
401 raise error.Abort(_('at least one of -n/-c is required for -l'))
401 raise error.Abort(_('at least one of -n/-c is required for -l'))
402
402
403 if fm:
403 if fm:
404 def makefunc(get, fmt):
404 def makefunc(get, fmt):
405 return get
405 return get
406 else:
406 else:
407 def makefunc(get, fmt):
407 def makefunc(get, fmt):
408 return lambda x: fmt(get(x))
408 return lambda x: fmt(get(x))
409 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
409 funcmap = [(makefunc(get, fmt), sep) for op, sep, get, fmt in opmap
410 if opts.get(op)]
410 if opts.get(op)]
411 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
411 funcmap[0] = (funcmap[0][0], '') # no separator in front of first column
412 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
412 fields = ' '.join(fieldnamemap.get(op, op) for op, sep, get, fmt in opmap
413 if opts.get(op))
413 if opts.get(op))
414
414
415 def bad(x, y):
415 def bad(x, y):
416 raise error.Abort("%s: %s" % (x, y))
416 raise error.Abort("%s: %s" % (x, y))
417
417
418 m = scmutil.match(ctx, pats, opts, badfn=bad)
418 m = scmutil.match(ctx, pats, opts, badfn=bad)
419
419
420 follow = not opts.get('no_follow')
420 follow = not opts.get('no_follow')
421 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
421 diffopts = patch.difffeatureopts(ui, opts, section='annotate',
422 whitespace=True)
422 whitespace=True)
423 for abs in ctx.walk(m):
423 for abs in ctx.walk(m):
424 fctx = ctx[abs]
424 fctx = ctx[abs]
425 if not opts.get('text') and util.binary(fctx.data()):
425 if not opts.get('text') and util.binary(fctx.data()):
426 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
426 fm.plain(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
427 continue
427 continue
428
428
429 lines = fctx.annotate(follow=follow, linenumber=linenumber,
429 lines = fctx.annotate(follow=follow, linenumber=linenumber,
430 diffopts=diffopts)
430 diffopts=diffopts)
431 formats = []
431 formats = []
432 pieces = []
432 pieces = []
433
433
434 for f, sep in funcmap:
434 for f, sep in funcmap:
435 l = [f(n) for n, dummy in lines]
435 l = [f(n) for n, dummy in lines]
436 if l:
436 if l:
437 if fm:
437 if fm:
438 formats.append(['%s' for x in l])
438 formats.append(['%s' for x in l])
439 else:
439 else:
440 sizes = [encoding.colwidth(x) for x in l]
440 sizes = [encoding.colwidth(x) for x in l]
441 ml = max(sizes)
441 ml = max(sizes)
442 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
442 formats.append([sep + ' ' * (ml - w) + '%s' for w in sizes])
443 pieces.append(l)
443 pieces.append(l)
444
444
445 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
445 for f, p, l in zip(zip(*formats), zip(*pieces), lines):
446 fm.startitem()
446 fm.startitem()
447 fm.write(fields, "".join(f), *p)
447 fm.write(fields, "".join(f), *p)
448 fm.write('line', ": %s", l[1])
448 fm.write('line', ": %s", l[1])
449
449
450 if lines and not lines[-1][1].endswith('\n'):
450 if lines and not lines[-1][1].endswith('\n'):
451 fm.plain('\n')
451 fm.plain('\n')
452
452
453 fm.end()
453 fm.end()
454
454
455 @command('archive',
455 @command('archive',
456 [('', 'no-decode', None, _('do not pass files through decoders')),
456 [('', 'no-decode', None, _('do not pass files through decoders')),
457 ('p', 'prefix', '', _('directory prefix for files in archive'),
457 ('p', 'prefix', '', _('directory prefix for files in archive'),
458 _('PREFIX')),
458 _('PREFIX')),
459 ('r', 'rev', '', _('revision to distribute'), _('REV')),
459 ('r', 'rev', '', _('revision to distribute'), _('REV')),
460 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
460 ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
461 ] + subrepoopts + walkopts,
461 ] + subrepoopts + walkopts,
462 _('[OPTION]... DEST'))
462 _('[OPTION]... DEST'))
463 def archive(ui, repo, dest, **opts):
463 def archive(ui, repo, dest, **opts):
464 '''create an unversioned archive of a repository revision
464 '''create an unversioned archive of a repository revision
465
465
466 By default, the revision used is the parent of the working
466 By default, the revision used is the parent of the working
467 directory; use -r/--rev to specify a different revision.
467 directory; use -r/--rev to specify a different revision.
468
468
469 The archive type is automatically detected based on file
469 The archive type is automatically detected based on file
470 extension (to override, use -t/--type).
470 extension (to override, use -t/--type).
471
471
472 .. container:: verbose
472 .. container:: verbose
473
473
474 Examples:
474 Examples:
475
475
476 - create a zip file containing the 1.0 release::
476 - create a zip file containing the 1.0 release::
477
477
478 hg archive -r 1.0 project-1.0.zip
478 hg archive -r 1.0 project-1.0.zip
479
479
480 - create a tarball excluding .hg files::
480 - create a tarball excluding .hg files::
481
481
482 hg archive project.tar.gz -X ".hg*"
482 hg archive project.tar.gz -X ".hg*"
483
483
484 Valid types are:
484 Valid types are:
485
485
486 :``files``: a directory full of files (default)
486 :``files``: a directory full of files (default)
487 :``tar``: tar archive, uncompressed
487 :``tar``: tar archive, uncompressed
488 :``tbz2``: tar archive, compressed using bzip2
488 :``tbz2``: tar archive, compressed using bzip2
489 :``tgz``: tar archive, compressed using gzip
489 :``tgz``: tar archive, compressed using gzip
490 :``uzip``: zip archive, uncompressed
490 :``uzip``: zip archive, uncompressed
491 :``zip``: zip archive, compressed using deflate
491 :``zip``: zip archive, compressed using deflate
492
492
493 The exact name of the destination archive or directory is given
493 The exact name of the destination archive or directory is given
494 using a format string; see :hg:`help export` for details.
494 using a format string; see :hg:`help export` for details.
495
495
496 Each member added to an archive file has a directory prefix
496 Each member added to an archive file has a directory prefix
497 prepended. Use -p/--prefix to specify a format string for the
497 prepended. Use -p/--prefix to specify a format string for the
498 prefix. The default is the basename of the archive, with suffixes
498 prefix. The default is the basename of the archive, with suffixes
499 removed.
499 removed.
500
500
501 Returns 0 on success.
501 Returns 0 on success.
502 '''
502 '''
503
503
504 ctx = scmutil.revsingle(repo, opts.get('rev'))
504 ctx = scmutil.revsingle(repo, opts.get('rev'))
505 if not ctx:
505 if not ctx:
506 raise error.Abort(_('no working directory: please specify a revision'))
506 raise error.Abort(_('no working directory: please specify a revision'))
507 node = ctx.node()
507 node = ctx.node()
508 dest = cmdutil.makefilename(repo, dest, node)
508 dest = cmdutil.makefilename(repo, dest, node)
509 if os.path.realpath(dest) == repo.root:
509 if os.path.realpath(dest) == repo.root:
510 raise error.Abort(_('repository root cannot be destination'))
510 raise error.Abort(_('repository root cannot be destination'))
511
511
512 kind = opts.get('type') or archival.guesskind(dest) or 'files'
512 kind = opts.get('type') or archival.guesskind(dest) or 'files'
513 prefix = opts.get('prefix')
513 prefix = opts.get('prefix')
514
514
515 if dest == '-':
515 if dest == '-':
516 if kind == 'files':
516 if kind == 'files':
517 raise error.Abort(_('cannot archive plain files to stdout'))
517 raise error.Abort(_('cannot archive plain files to stdout'))
518 dest = cmdutil.makefileobj(repo, dest)
518 dest = cmdutil.makefileobj(repo, dest)
519 if not prefix:
519 if not prefix:
520 prefix = os.path.basename(repo.root) + '-%h'
520 prefix = os.path.basename(repo.root) + '-%h'
521
521
522 prefix = cmdutil.makefilename(repo, prefix, node)
522 prefix = cmdutil.makefilename(repo, prefix, node)
523 matchfn = scmutil.match(ctx, [], opts)
523 matchfn = scmutil.match(ctx, [], opts)
524 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
524 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
525 matchfn, prefix, subrepos=opts.get('subrepos'))
525 matchfn, prefix, subrepos=opts.get('subrepos'))
526
526
527 @command('backout',
527 @command('backout',
528 [('', 'merge', None, _('merge with old dirstate parent after backout')),
528 [('', 'merge', None, _('merge with old dirstate parent after backout')),
529 ('', 'commit', None, _('commit if no conflicts were encountered')),
529 ('', 'commit', None, _('commit if no conflicts were encountered')),
530 ('', 'parent', '',
530 ('', 'parent', '',
531 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
531 _('parent to choose when backing out merge (DEPRECATED)'), _('REV')),
532 ('r', 'rev', '', _('revision to backout'), _('REV')),
532 ('r', 'rev', '', _('revision to backout'), _('REV')),
533 ('e', 'edit', False, _('invoke editor on commit messages')),
533 ('e', 'edit', False, _('invoke editor on commit messages')),
534 ] + mergetoolopts + walkopts + commitopts + commitopts2,
534 ] + mergetoolopts + walkopts + commitopts + commitopts2,
535 _('[OPTION]... [-r] REV'))
535 _('[OPTION]... [-r] REV'))
536 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
536 def backout(ui, repo, node=None, rev=None, commit=False, **opts):
537 '''reverse effect of earlier changeset
537 '''reverse effect of earlier changeset
538
538
539 Prepare a new changeset with the effect of REV undone in the
539 Prepare a new changeset with the effect of REV undone in the
540 current working directory.
540 current working directory.
541
541
542 If REV is the parent of the working directory, then this new changeset
542 If REV is the parent of the working directory, then this new changeset
543 is committed automatically. Otherwise, hg needs to merge the
543 is committed automatically. Otherwise, hg needs to merge the
544 changes and the merged result is left uncommitted.
544 changes and the merged result is left uncommitted.
545
545
546 .. note::
546 .. note::
547
547
548 :hg:`backout` cannot be used to fix either an unwanted or
548 :hg:`backout` cannot be used to fix either an unwanted or
549 incorrect merge.
549 incorrect merge.
550
550
551 .. container:: verbose
551 .. container:: verbose
552
552
553 Examples:
553 Examples:
554
554
555 - Reverse the effect of the parent of the working directory.
555 - Reverse the effect of the parent of the working directory.
556 This backout will be committed immediately::
556 This backout will be committed immediately::
557
557
558 hg backout -r .
558 hg backout -r .
559
559
560 - Reverse the effect of previous bad revision 23::
560 - Reverse the effect of previous bad revision 23::
561
561
562 hg backout -r 23
562 hg backout -r 23
563 hg commit -m "Backout revision 23"
563 hg commit -m "Backout revision 23"
564
564
565 - Reverse the effect of previous bad revision 23 and
565 - Reverse the effect of previous bad revision 23 and
566 commit the backout immediately::
566 commit the backout immediately::
567
567
568 hg backout -r 23 --commit
568 hg backout -r 23 --commit
569
569
570 By default, the pending changeset will have one parent,
570 By default, the pending changeset will have one parent,
571 maintaining a linear history. With --merge, the pending
571 maintaining a linear history. With --merge, the pending
572 changeset will instead have two parents: the old parent of the
572 changeset will instead have two parents: the old parent of the
573 working directory and a new child of REV that simply undoes REV.
573 working directory and a new child of REV that simply undoes REV.
574
574
575 Before version 1.7, the behavior without --merge was equivalent
575 Before version 1.7, the behavior without --merge was equivalent
576 to specifying --merge followed by :hg:`update --clean .` to
576 to specifying --merge followed by :hg:`update --clean .` to
577 cancel the merge and leave the child of REV as a head to be
577 cancel the merge and leave the child of REV as a head to be
578 merged separately.
578 merged separately.
579
579
580 See :hg:`help dates` for a list of formats valid for -d/--date.
580 See :hg:`help dates` for a list of formats valid for -d/--date.
581
581
582 See :hg:`help revert` for a way to restore files to the state
582 See :hg:`help revert` for a way to restore files to the state
583 of another revision.
583 of another revision.
584
584
585 Returns 0 on success, 1 if nothing to backout or there are unresolved
585 Returns 0 on success, 1 if nothing to backout or there are unresolved
586 files.
586 files.
587 '''
587 '''
588 wlock = lock = None
588 wlock = lock = None
589 try:
589 try:
590 wlock = repo.wlock()
590 wlock = repo.wlock()
591 lock = repo.lock()
591 lock = repo.lock()
592 return _dobackout(ui, repo, node, rev, commit, **opts)
592 return _dobackout(ui, repo, node, rev, commit, **opts)
593 finally:
593 finally:
594 release(lock, wlock)
594 release(lock, wlock)
595
595
596 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
596 def _dobackout(ui, repo, node=None, rev=None, commit=False, **opts):
597 if rev and node:
597 if rev and node:
598 raise error.Abort(_("please specify just one revision"))
598 raise error.Abort(_("please specify just one revision"))
599
599
600 if not rev:
600 if not rev:
601 rev = node
601 rev = node
602
602
603 if not rev:
603 if not rev:
604 raise error.Abort(_("please specify a revision to backout"))
604 raise error.Abort(_("please specify a revision to backout"))
605
605
606 date = opts.get('date')
606 date = opts.get('date')
607 if date:
607 if date:
608 opts['date'] = util.parsedate(date)
608 opts['date'] = util.parsedate(date)
609
609
610 cmdutil.checkunfinished(repo)
610 cmdutil.checkunfinished(repo)
611 cmdutil.bailifchanged(repo)
611 cmdutil.bailifchanged(repo)
612 node = scmutil.revsingle(repo, rev).node()
612 node = scmutil.revsingle(repo, rev).node()
613
613
614 op1, op2 = repo.dirstate.parents()
614 op1, op2 = repo.dirstate.parents()
615 if not repo.changelog.isancestor(node, op1):
615 if not repo.changelog.isancestor(node, op1):
616 raise error.Abort(_('cannot backout change that is not an ancestor'))
616 raise error.Abort(_('cannot backout change that is not an ancestor'))
617
617
618 p1, p2 = repo.changelog.parents(node)
618 p1, p2 = repo.changelog.parents(node)
619 if p1 == nullid:
619 if p1 == nullid:
620 raise error.Abort(_('cannot backout a change with no parents'))
620 raise error.Abort(_('cannot backout a change with no parents'))
621 if p2 != nullid:
621 if p2 != nullid:
622 if not opts.get('parent'):
622 if not opts.get('parent'):
623 raise error.Abort(_('cannot backout a merge changeset'))
623 raise error.Abort(_('cannot backout a merge changeset'))
624 p = repo.lookup(opts['parent'])
624 p = repo.lookup(opts['parent'])
625 if p not in (p1, p2):
625 if p not in (p1, p2):
626 raise error.Abort(_('%s is not a parent of %s') %
626 raise error.Abort(_('%s is not a parent of %s') %
627 (short(p), short(node)))
627 (short(p), short(node)))
628 parent = p
628 parent = p
629 else:
629 else:
630 if opts.get('parent'):
630 if opts.get('parent'):
631 raise error.Abort(_('cannot use --parent on non-merge changeset'))
631 raise error.Abort(_('cannot use --parent on non-merge changeset'))
632 parent = p1
632 parent = p1
633
633
634 # the backout should appear on the same branch
634 # the backout should appear on the same branch
635 branch = repo.dirstate.branch()
635 branch = repo.dirstate.branch()
636 bheads = repo.branchheads(branch)
636 bheads = repo.branchheads(branch)
637 rctx = scmutil.revsingle(repo, hex(parent))
637 rctx = scmutil.revsingle(repo, hex(parent))
638 if not opts.get('merge') and op1 != node:
638 if not opts.get('merge') and op1 != node:
639 dsguard = cmdutil.dirstateguard(repo, 'backout')
639 dsguard = cmdutil.dirstateguard(repo, 'backout')
640 try:
640 try:
641 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
641 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
642 'backout')
642 'backout')
643 stats = mergemod.update(repo, parent, True, True, node, False)
643 stats = mergemod.update(repo, parent, True, True, node, False)
644 repo.setparents(op1, op2)
644 repo.setparents(op1, op2)
645 dsguard.close()
645 dsguard.close()
646 hg._showstats(repo, stats)
646 hg._showstats(repo, stats)
647 if stats[3]:
647 if stats[3]:
648 repo.ui.status(_("use 'hg resolve' to retry unresolved "
648 repo.ui.status(_("use 'hg resolve' to retry unresolved "
649 "file merges\n"))
649 "file merges\n"))
650 return 1
650 return 1
651 elif not commit:
651 elif not commit:
652 msg = _("changeset %s backed out, "
652 msg = _("changeset %s backed out, "
653 "don't forget to commit.\n")
653 "don't forget to commit.\n")
654 ui.status(msg % short(node))
654 ui.status(msg % short(node))
655 return 0
655 return 0
656 finally:
656 finally:
657 ui.setconfig('ui', 'forcemerge', '', '')
657 ui.setconfig('ui', 'forcemerge', '', '')
658 lockmod.release(dsguard)
658 lockmod.release(dsguard)
659 else:
659 else:
660 hg.clean(repo, node, show_stats=False)
660 hg.clean(repo, node, show_stats=False)
661 repo.dirstate.setbranch(branch)
661 repo.dirstate.setbranch(branch)
662 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
662 cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
663
663
664
664
665 def commitfunc(ui, repo, message, match, opts):
665 def commitfunc(ui, repo, message, match, opts):
666 editform = 'backout'
666 editform = 'backout'
667 e = cmdutil.getcommiteditor(editform=editform, **opts)
667 e = cmdutil.getcommiteditor(editform=editform, **opts)
668 if not message:
668 if not message:
669 # we don't translate commit messages
669 # we don't translate commit messages
670 message = "Backed out changeset %s" % short(node)
670 message = "Backed out changeset %s" % short(node)
671 e = cmdutil.getcommiteditor(edit=True, editform=editform)
671 e = cmdutil.getcommiteditor(edit=True, editform=editform)
672 return repo.commit(message, opts.get('user'), opts.get('date'),
672 return repo.commit(message, opts.get('user'), opts.get('date'),
673 match, editor=e)
673 match, editor=e)
674 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
674 newnode = cmdutil.commit(ui, repo, commitfunc, [], opts)
675 if not newnode:
675 if not newnode:
676 ui.status(_("nothing changed\n"))
676 ui.status(_("nothing changed\n"))
677 return 1
677 return 1
678 cmdutil.commitstatus(repo, newnode, branch, bheads)
678 cmdutil.commitstatus(repo, newnode, branch, bheads)
679
679
680 def nice(node):
680 def nice(node):
681 return '%d:%s' % (repo.changelog.rev(node), short(node))
681 return '%d:%s' % (repo.changelog.rev(node), short(node))
682 ui.status(_('changeset %s backs out changeset %s\n') %
682 ui.status(_('changeset %s backs out changeset %s\n') %
683 (nice(repo.changelog.tip()), nice(node)))
683 (nice(repo.changelog.tip()), nice(node)))
684 if opts.get('merge') and op1 != node:
684 if opts.get('merge') and op1 != node:
685 hg.clean(repo, op1, show_stats=False)
685 hg.clean(repo, op1, show_stats=False)
686 ui.status(_('merging with changeset %s\n')
686 ui.status(_('merging with changeset %s\n')
687 % nice(repo.changelog.tip()))
687 % nice(repo.changelog.tip()))
688 try:
688 try:
689 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
689 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
690 'backout')
690 'backout')
691 return hg.merge(repo, hex(repo.changelog.tip()))
691 return hg.merge(repo, hex(repo.changelog.tip()))
692 finally:
692 finally:
693 ui.setconfig('ui', 'forcemerge', '', '')
693 ui.setconfig('ui', 'forcemerge', '', '')
694 return 0
694 return 0
695
695
696 @command('bisect',
696 @command('bisect',
697 [('r', 'reset', False, _('reset bisect state')),
697 [('r', 'reset', False, _('reset bisect state')),
698 ('g', 'good', False, _('mark changeset good')),
698 ('g', 'good', False, _('mark changeset good')),
699 ('b', 'bad', False, _('mark changeset bad')),
699 ('b', 'bad', False, _('mark changeset bad')),
700 ('s', 'skip', False, _('skip testing changeset')),
700 ('s', 'skip', False, _('skip testing changeset')),
701 ('e', 'extend', False, _('extend the bisect range')),
701 ('e', 'extend', False, _('extend the bisect range')),
702 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
702 ('c', 'command', '', _('use command to check changeset state'), _('CMD')),
703 ('U', 'noupdate', False, _('do not update to target'))],
703 ('U', 'noupdate', False, _('do not update to target'))],
704 _("[-gbsr] [-U] [-c CMD] [REV]"))
704 _("[-gbsr] [-U] [-c CMD] [REV]"))
705 def bisect(ui, repo, rev=None, extra=None, command=None,
705 def bisect(ui, repo, rev=None, extra=None, command=None,
706 reset=None, good=None, bad=None, skip=None, extend=None,
706 reset=None, good=None, bad=None, skip=None, extend=None,
707 noupdate=None):
707 noupdate=None):
708 """subdivision search of changesets
708 """subdivision search of changesets
709
709
710 This command helps to find changesets which introduce problems. To
710 This command helps to find changesets which introduce problems. To
711 use, mark the earliest changeset you know exhibits the problem as
711 use, mark the earliest changeset you know exhibits the problem as
712 bad, then mark the latest changeset which is free from the problem
712 bad, then mark the latest changeset which is free from the problem
713 as good. Bisect will update your working directory to a revision
713 as good. Bisect will update your working directory to a revision
714 for testing (unless the -U/--noupdate option is specified). Once
714 for testing (unless the -U/--noupdate option is specified). Once
715 you have performed tests, mark the working directory as good or
715 you have performed tests, mark the working directory as good or
716 bad, and bisect will either update to another candidate changeset
716 bad, and bisect will either update to another candidate changeset
717 or announce that it has found the bad revision.
717 or announce that it has found the bad revision.
718
718
719 As a shortcut, you can also use the revision argument to mark a
719 As a shortcut, you can also use the revision argument to mark a
720 revision as good or bad without checking it out first.
720 revision as good or bad without checking it out first.
721
721
722 If you supply a command, it will be used for automatic bisection.
722 If you supply a command, it will be used for automatic bisection.
723 The environment variable HG_NODE will contain the ID of the
723 The environment variable HG_NODE will contain the ID of the
724 changeset being tested. The exit status of the command will be
724 changeset being tested. The exit status of the command will be
725 used to mark revisions as good or bad: status 0 means good, 125
725 used to mark revisions as good or bad: status 0 means good, 125
726 means to skip the revision, 127 (command not found) will abort the
726 means to skip the revision, 127 (command not found) will abort the
727 bisection, and any other non-zero exit status means the revision
727 bisection, and any other non-zero exit status means the revision
728 is bad.
728 is bad.
729
729
730 .. container:: verbose
730 .. container:: verbose
731
731
732 Some examples:
732 Some examples:
733
733
734 - start a bisection with known bad revision 34, and good revision 12::
734 - start a bisection with known bad revision 34, and good revision 12::
735
735
736 hg bisect --bad 34
736 hg bisect --bad 34
737 hg bisect --good 12
737 hg bisect --good 12
738
738
739 - advance the current bisection by marking current revision as good or
739 - advance the current bisection by marking current revision as good or
740 bad::
740 bad::
741
741
742 hg bisect --good
742 hg bisect --good
743 hg bisect --bad
743 hg bisect --bad
744
744
745 - mark the current revision, or a known revision, to be skipped (e.g. if
745 - mark the current revision, or a known revision, to be skipped (e.g. if
746 that revision is not usable because of another issue)::
746 that revision is not usable because of another issue)::
747
747
748 hg bisect --skip
748 hg bisect --skip
749 hg bisect --skip 23
749 hg bisect --skip 23
750
750
751 - skip all revisions that do not touch directories ``foo`` or ``bar``::
751 - skip all revisions that do not touch directories ``foo`` or ``bar``::
752
752
753 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
753 hg bisect --skip "!( file('path:foo') & file('path:bar') )"
754
754
755 - forget the current bisection::
755 - forget the current bisection::
756
756
757 hg bisect --reset
757 hg bisect --reset
758
758
759 - use 'make && make tests' to automatically find the first broken
759 - use 'make && make tests' to automatically find the first broken
760 revision::
760 revision::
761
761
762 hg bisect --reset
762 hg bisect --reset
763 hg bisect --bad 34
763 hg bisect --bad 34
764 hg bisect --good 12
764 hg bisect --good 12
765 hg bisect --command "make && make tests"
765 hg bisect --command "make && make tests"
766
766
767 - see all changesets whose states are already known in the current
767 - see all changesets whose states are already known in the current
768 bisection::
768 bisection::
769
769
770 hg log -r "bisect(pruned)"
770 hg log -r "bisect(pruned)"
771
771
772 - see the changeset currently being bisected (especially useful
772 - see the changeset currently being bisected (especially useful
773 if running with -U/--noupdate)::
773 if running with -U/--noupdate)::
774
774
775 hg log -r "bisect(current)"
775 hg log -r "bisect(current)"
776
776
777 - see all changesets that took part in the current bisection::
777 - see all changesets that took part in the current bisection::
778
778
779 hg log -r "bisect(range)"
779 hg log -r "bisect(range)"
780
780
781 - you can even get a nice graph::
781 - you can even get a nice graph::
782
782
783 hg log --graph -r "bisect(range)"
783 hg log --graph -r "bisect(range)"
784
784
785 See :hg:`help revsets` for more about the `bisect()` keyword.
785 See :hg:`help revsets` for more about the `bisect()` keyword.
786
786
787 Returns 0 on success.
787 Returns 0 on success.
788 """
788 """
789 def extendbisectrange(nodes, good):
789 def extendbisectrange(nodes, good):
790 # bisect is incomplete when it ends on a merge node and
790 # bisect is incomplete when it ends on a merge node and
791 # one of the parent was not checked.
791 # one of the parent was not checked.
792 parents = repo[nodes[0]].parents()
792 parents = repo[nodes[0]].parents()
793 if len(parents) > 1:
793 if len(parents) > 1:
794 if good:
794 if good:
795 side = state['bad']
795 side = state['bad']
796 else:
796 else:
797 side = state['good']
797 side = state['good']
798 num = len(set(i.node() for i in parents) & set(side))
798 num = len(set(i.node() for i in parents) & set(side))
799 if num == 1:
799 if num == 1:
800 return parents[0].ancestor(parents[1])
800 return parents[0].ancestor(parents[1])
801 return None
801 return None
802
802
803 def print_result(nodes, good):
803 def print_result(nodes, good):
804 displayer = cmdutil.show_changeset(ui, repo, {})
804 displayer = cmdutil.show_changeset(ui, repo, {})
805 if len(nodes) == 1:
805 if len(nodes) == 1:
806 # narrowed it down to a single revision
806 # narrowed it down to a single revision
807 if good:
807 if good:
808 ui.write(_("The first good revision is:\n"))
808 ui.write(_("The first good revision is:\n"))
809 else:
809 else:
810 ui.write(_("The first bad revision is:\n"))
810 ui.write(_("The first bad revision is:\n"))
811 displayer.show(repo[nodes[0]])
811 displayer.show(repo[nodes[0]])
812 extendnode = extendbisectrange(nodes, good)
812 extendnode = extendbisectrange(nodes, good)
813 if extendnode is not None:
813 if extendnode is not None:
814 ui.write(_('Not all ancestors of this changeset have been'
814 ui.write(_('Not all ancestors of this changeset have been'
815 ' checked.\nUse bisect --extend to continue the '
815 ' checked.\nUse bisect --extend to continue the '
816 'bisection from\nthe common ancestor, %s.\n')
816 'bisection from\nthe common ancestor, %s.\n')
817 % extendnode)
817 % extendnode)
818 else:
818 else:
819 # multiple possible revisions
819 # multiple possible revisions
820 if good:
820 if good:
821 ui.write(_("Due to skipped revisions, the first "
821 ui.write(_("Due to skipped revisions, the first "
822 "good revision could be any of:\n"))
822 "good revision could be any of:\n"))
823 else:
823 else:
824 ui.write(_("Due to skipped revisions, the first "
824 ui.write(_("Due to skipped revisions, the first "
825 "bad revision could be any of:\n"))
825 "bad revision could be any of:\n"))
826 for n in nodes:
826 for n in nodes:
827 displayer.show(repo[n])
827 displayer.show(repo[n])
828 displayer.close()
828 displayer.close()
829
829
830 def check_state(state, interactive=True):
830 def check_state(state, interactive=True):
831 if not state['good'] or not state['bad']:
831 if not state['good'] or not state['bad']:
832 if (good or bad or skip or reset) and interactive:
832 if (good or bad or skip or reset) and interactive:
833 return
833 return
834 if not state['good']:
834 if not state['good']:
835 raise error.Abort(_('cannot bisect (no known good revisions)'))
835 raise error.Abort(_('cannot bisect (no known good revisions)'))
836 else:
836 else:
837 raise error.Abort(_('cannot bisect (no known bad revisions)'))
837 raise error.Abort(_('cannot bisect (no known bad revisions)'))
838 return True
838 return True
839
839
840 # backward compatibility
840 # backward compatibility
841 if rev in "good bad reset init".split():
841 if rev in "good bad reset init".split():
842 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
842 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
843 cmd, rev, extra = rev, extra, None
843 cmd, rev, extra = rev, extra, None
844 if cmd == "good":
844 if cmd == "good":
845 good = True
845 good = True
846 elif cmd == "bad":
846 elif cmd == "bad":
847 bad = True
847 bad = True
848 else:
848 else:
849 reset = True
849 reset = True
850 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
850 elif extra or good + bad + skip + reset + extend + bool(command) > 1:
851 raise error.Abort(_('incompatible arguments'))
851 raise error.Abort(_('incompatible arguments'))
852
852
853 cmdutil.checkunfinished(repo)
853 cmdutil.checkunfinished(repo)
854
854
855 if reset:
855 if reset:
856 p = repo.join("bisect.state")
856 p = repo.join("bisect.state")
857 if os.path.exists(p):
857 if os.path.exists(p):
858 os.unlink(p)
858 os.unlink(p)
859 return
859 return
860
860
861 state = hbisect.load_state(repo)
861 state = hbisect.load_state(repo)
862
862
863 if command:
863 if command:
864 changesets = 1
864 changesets = 1
865 if noupdate:
865 if noupdate:
866 try:
866 try:
867 node = state['current'][0]
867 node = state['current'][0]
868 except LookupError:
868 except LookupError:
869 raise error.Abort(_('current bisect revision is unknown - '
869 raise error.Abort(_('current bisect revision is unknown - '
870 'start a new bisect to fix'))
870 'start a new bisect to fix'))
871 else:
871 else:
872 node, p2 = repo.dirstate.parents()
872 node, p2 = repo.dirstate.parents()
873 if p2 != nullid:
873 if p2 != nullid:
874 raise error.Abort(_('current bisect revision is a merge'))
874 raise error.Abort(_('current bisect revision is a merge'))
875 try:
875 try:
876 while changesets:
876 while changesets:
877 # update state
877 # update state
878 state['current'] = [node]
878 state['current'] = [node]
879 hbisect.save_state(repo, state)
879 hbisect.save_state(repo, state)
880 status = ui.system(command, environ={'HG_NODE': hex(node)})
880 status = ui.system(command, environ={'HG_NODE': hex(node)})
881 if status == 125:
881 if status == 125:
882 transition = "skip"
882 transition = "skip"
883 elif status == 0:
883 elif status == 0:
884 transition = "good"
884 transition = "good"
885 # status < 0 means process was killed
885 # status < 0 means process was killed
886 elif status == 127:
886 elif status == 127:
887 raise error.Abort(_("failed to execute %s") % command)
887 raise error.Abort(_("failed to execute %s") % command)
888 elif status < 0:
888 elif status < 0:
889 raise error.Abort(_("%s killed") % command)
889 raise error.Abort(_("%s killed") % command)
890 else:
890 else:
891 transition = "bad"
891 transition = "bad"
892 ctx = scmutil.revsingle(repo, rev, node)
892 ctx = scmutil.revsingle(repo, rev, node)
893 rev = None # clear for future iterations
893 rev = None # clear for future iterations
894 state[transition].append(ctx.node())
894 state[transition].append(ctx.node())
895 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
895 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
896 check_state(state, interactive=False)
896 check_state(state, interactive=False)
897 # bisect
897 # bisect
898 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
898 nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
899 # update to next check
899 # update to next check
900 node = nodes[0]
900 node = nodes[0]
901 if not noupdate:
901 if not noupdate:
902 cmdutil.bailifchanged(repo)
902 cmdutil.bailifchanged(repo)
903 hg.clean(repo, node, show_stats=False)
903 hg.clean(repo, node, show_stats=False)
904 finally:
904 finally:
905 state['current'] = [node]
905 state['current'] = [node]
906 hbisect.save_state(repo, state)
906 hbisect.save_state(repo, state)
907 print_result(nodes, bgood)
907 print_result(nodes, bgood)
908 return
908 return
909
909
910 # update state
910 # update state
911
911
912 if rev:
912 if rev:
913 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
913 nodes = [repo.lookup(i) for i in scmutil.revrange(repo, [rev])]
914 else:
914 else:
915 nodes = [repo.lookup('.')]
915 nodes = [repo.lookup('.')]
916
916
917 if good or bad or skip:
917 if good or bad or skip:
918 if good:
918 if good:
919 state['good'] += nodes
919 state['good'] += nodes
920 elif bad:
920 elif bad:
921 state['bad'] += nodes
921 state['bad'] += nodes
922 elif skip:
922 elif skip:
923 state['skip'] += nodes
923 state['skip'] += nodes
924 hbisect.save_state(repo, state)
924 hbisect.save_state(repo, state)
925
925
926 if not check_state(state):
926 if not check_state(state):
927 return
927 return
928
928
929 # actually bisect
929 # actually bisect
930 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
930 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
931 if extend:
931 if extend:
932 if not changesets:
932 if not changesets:
933 extendnode = extendbisectrange(nodes, good)
933 extendnode = extendbisectrange(nodes, good)
934 if extendnode is not None:
934 if extendnode is not None:
935 ui.write(_("Extending search to changeset %d:%s\n")
935 ui.write(_("Extending search to changeset %d:%s\n")
936 % (extendnode.rev(), extendnode))
936 % (extendnode.rev(), extendnode))
937 state['current'] = [extendnode.node()]
937 state['current'] = [extendnode.node()]
938 hbisect.save_state(repo, state)
938 hbisect.save_state(repo, state)
939 if noupdate:
939 if noupdate:
940 return
940 return
941 cmdutil.bailifchanged(repo)
941 cmdutil.bailifchanged(repo)
942 return hg.clean(repo, extendnode.node())
942 return hg.clean(repo, extendnode.node())
943 raise error.Abort(_("nothing to extend"))
943 raise error.Abort(_("nothing to extend"))
944
944
945 if changesets == 0:
945 if changesets == 0:
946 print_result(nodes, good)
946 print_result(nodes, good)
947 else:
947 else:
948 assert len(nodes) == 1 # only a single node can be tested next
948 assert len(nodes) == 1 # only a single node can be tested next
949 node = nodes[0]
949 node = nodes[0]
950 # compute the approximate number of remaining tests
950 # compute the approximate number of remaining tests
951 tests, size = 0, 2
951 tests, size = 0, 2
952 while size <= changesets:
952 while size <= changesets:
953 tests, size = tests + 1, size * 2
953 tests, size = tests + 1, size * 2
954 rev = repo.changelog.rev(node)
954 rev = repo.changelog.rev(node)
955 ui.write(_("Testing changeset %d:%s "
955 ui.write(_("Testing changeset %d:%s "
956 "(%d changesets remaining, ~%d tests)\n")
956 "(%d changesets remaining, ~%d tests)\n")
957 % (rev, short(node), changesets, tests))
957 % (rev, short(node), changesets, tests))
958 state['current'] = [node]
958 state['current'] = [node]
959 hbisect.save_state(repo, state)
959 hbisect.save_state(repo, state)
960 if not noupdate:
960 if not noupdate:
961 cmdutil.bailifchanged(repo)
961 cmdutil.bailifchanged(repo)
962 return hg.clean(repo, node)
962 return hg.clean(repo, node)
963
963
964 @command('bookmarks|bookmark',
964 @command('bookmarks|bookmark',
965 [('f', 'force', False, _('force')),
965 [('f', 'force', False, _('force')),
966 ('r', 'rev', '', _('revision'), _('REV')),
966 ('r', 'rev', '', _('revision'), _('REV')),
967 ('d', 'delete', False, _('delete a given bookmark')),
967 ('d', 'delete', False, _('delete a given bookmark')),
968 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
968 ('m', 'rename', '', _('rename a given bookmark'), _('OLD')),
969 ('i', 'inactive', False, _('mark a bookmark inactive')),
969 ('i', 'inactive', False, _('mark a bookmark inactive')),
970 ] + formatteropts,
970 ] + formatteropts,
971 _('hg bookmarks [OPTIONS]... [NAME]...'))
971 _('hg bookmarks [OPTIONS]... [NAME]...'))
972 def bookmark(ui, repo, *names, **opts):
972 def bookmark(ui, repo, *names, **opts):
973 '''create a new bookmark or list existing bookmarks
973 '''create a new bookmark or list existing bookmarks
974
974
975 Bookmarks are labels on changesets to help track lines of development.
975 Bookmarks are labels on changesets to help track lines of development.
976 Bookmarks are unversioned and can be moved, renamed and deleted.
976 Bookmarks are unversioned and can be moved, renamed and deleted.
977 Deleting or moving a bookmark has no effect on the associated changesets.
977 Deleting or moving a bookmark has no effect on the associated changesets.
978
978
979 Creating or updating to a bookmark causes it to be marked as 'active'.
979 Creating or updating to a bookmark causes it to be marked as 'active'.
980 The active bookmark is indicated with a '*'.
980 The active bookmark is indicated with a '*'.
981 When a commit is made, the active bookmark will advance to the new commit.
981 When a commit is made, the active bookmark will advance to the new commit.
982 A plain :hg:`update` will also advance an active bookmark, if possible.
982 A plain :hg:`update` will also advance an active bookmark, if possible.
983 Updating away from a bookmark will cause it to be deactivated.
983 Updating away from a bookmark will cause it to be deactivated.
984
984
985 Bookmarks can be pushed and pulled between repositories (see
985 Bookmarks can be pushed and pulled between repositories (see
986 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
986 :hg:`help push` and :hg:`help pull`). If a shared bookmark has
987 diverged, a new 'divergent bookmark' of the form 'name@path' will
987 diverged, a new 'divergent bookmark' of the form 'name@path' will
988 be created. Using :hg:`merge` will resolve the divergence.
988 be created. Using :hg:`merge` will resolve the divergence.
989
989
990 A bookmark named '@' has the special property that :hg:`clone` will
990 A bookmark named '@' has the special property that :hg:`clone` will
991 check it out by default if it exists.
991 check it out by default if it exists.
992
992
993 .. container:: verbose
993 .. container:: verbose
994
994
995 Examples:
995 Examples:
996
996
997 - create an active bookmark for a new line of development::
997 - create an active bookmark for a new line of development::
998
998
999 hg book new-feature
999 hg book new-feature
1000
1000
1001 - create an inactive bookmark as a place marker::
1001 - create an inactive bookmark as a place marker::
1002
1002
1003 hg book -i reviewed
1003 hg book -i reviewed
1004
1004
1005 - create an inactive bookmark on another changeset::
1005 - create an inactive bookmark on another changeset::
1006
1006
1007 hg book -r .^ tested
1007 hg book -r .^ tested
1008
1008
1009 - rename bookmark turkey to dinner::
1009 - rename bookmark turkey to dinner::
1010
1010
1011 hg book -m turkey dinner
1011 hg book -m turkey dinner
1012
1012
1013 - move the '@' bookmark from another branch::
1013 - move the '@' bookmark from another branch::
1014
1014
1015 hg book -f @
1015 hg book -f @
1016 '''
1016 '''
1017 force = opts.get('force')
1017 force = opts.get('force')
1018 rev = opts.get('rev')
1018 rev = opts.get('rev')
1019 delete = opts.get('delete')
1019 delete = opts.get('delete')
1020 rename = opts.get('rename')
1020 rename = opts.get('rename')
1021 inactive = opts.get('inactive')
1021 inactive = opts.get('inactive')
1022
1022
1023 def checkformat(mark):
1023 def checkformat(mark):
1024 mark = mark.strip()
1024 mark = mark.strip()
1025 if not mark:
1025 if not mark:
1026 raise error.Abort(_("bookmark names cannot consist entirely of "
1026 raise error.Abort(_("bookmark names cannot consist entirely of "
1027 "whitespace"))
1027 "whitespace"))
1028 scmutil.checknewlabel(repo, mark, 'bookmark')
1028 scmutil.checknewlabel(repo, mark, 'bookmark')
1029 return mark
1029 return mark
1030
1030
1031 def checkconflict(repo, mark, cur, force=False, target=None):
1031 def checkconflict(repo, mark, cur, force=False, target=None):
1032 if mark in marks and not force:
1032 if mark in marks and not force:
1033 if target:
1033 if target:
1034 if marks[mark] == target and target == cur:
1034 if marks[mark] == target and target == cur:
1035 # re-activating a bookmark
1035 # re-activating a bookmark
1036 return
1036 return
1037 anc = repo.changelog.ancestors([repo[target].rev()])
1037 anc = repo.changelog.ancestors([repo[target].rev()])
1038 bmctx = repo[marks[mark]]
1038 bmctx = repo[marks[mark]]
1039 divs = [repo[b].node() for b in marks
1039 divs = [repo[b].node() for b in marks
1040 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1040 if b.split('@', 1)[0] == mark.split('@', 1)[0]]
1041
1041
1042 # allow resolving a single divergent bookmark even if moving
1042 # allow resolving a single divergent bookmark even if moving
1043 # the bookmark across branches when a revision is specified
1043 # the bookmark across branches when a revision is specified
1044 # that contains a divergent bookmark
1044 # that contains a divergent bookmark
1045 if bmctx.rev() not in anc and target in divs:
1045 if bmctx.rev() not in anc and target in divs:
1046 bookmarks.deletedivergent(repo, [target], mark)
1046 bookmarks.deletedivergent(repo, [target], mark)
1047 return
1047 return
1048
1048
1049 deletefrom = [b for b in divs
1049 deletefrom = [b for b in divs
1050 if repo[b].rev() in anc or b == target]
1050 if repo[b].rev() in anc or b == target]
1051 bookmarks.deletedivergent(repo, deletefrom, mark)
1051 bookmarks.deletedivergent(repo, deletefrom, mark)
1052 if bookmarks.validdest(repo, bmctx, repo[target]):
1052 if bookmarks.validdest(repo, bmctx, repo[target]):
1053 ui.status(_("moving bookmark '%s' forward from %s\n") %
1053 ui.status(_("moving bookmark '%s' forward from %s\n") %
1054 (mark, short(bmctx.node())))
1054 (mark, short(bmctx.node())))
1055 return
1055 return
1056 raise error.Abort(_("bookmark '%s' already exists "
1056 raise error.Abort(_("bookmark '%s' already exists "
1057 "(use -f to force)") % mark)
1057 "(use -f to force)") % mark)
1058 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1058 if ((mark in repo.branchmap() or mark == repo.dirstate.branch())
1059 and not force):
1059 and not force):
1060 raise error.Abort(
1060 raise error.Abort(
1061 _("a bookmark cannot have the name of an existing branch"))
1061 _("a bookmark cannot have the name of an existing branch"))
1062
1062
1063 if delete and rename:
1063 if delete and rename:
1064 raise error.Abort(_("--delete and --rename are incompatible"))
1064 raise error.Abort(_("--delete and --rename are incompatible"))
1065 if delete and rev:
1065 if delete and rev:
1066 raise error.Abort(_("--rev is incompatible with --delete"))
1066 raise error.Abort(_("--rev is incompatible with --delete"))
1067 if rename and rev:
1067 if rename and rev:
1068 raise error.Abort(_("--rev is incompatible with --rename"))
1068 raise error.Abort(_("--rev is incompatible with --rename"))
1069 if not names and (delete or rev):
1069 if not names and (delete or rev):
1070 raise error.Abort(_("bookmark name required"))
1070 raise error.Abort(_("bookmark name required"))
1071
1071
1072 if delete or rename or names or inactive:
1072 if delete or rename or names or inactive:
1073 wlock = lock = tr = None
1073 wlock = lock = tr = None
1074 try:
1074 try:
1075 wlock = repo.wlock()
1075 wlock = repo.wlock()
1076 lock = repo.lock()
1076 lock = repo.lock()
1077 cur = repo.changectx('.').node()
1077 cur = repo.changectx('.').node()
1078 marks = repo._bookmarks
1078 marks = repo._bookmarks
1079 if delete:
1079 if delete:
1080 tr = repo.transaction('bookmark')
1080 tr = repo.transaction('bookmark')
1081 for mark in names:
1081 for mark in names:
1082 if mark not in marks:
1082 if mark not in marks:
1083 raise error.Abort(_("bookmark '%s' does not exist") %
1083 raise error.Abort(_("bookmark '%s' does not exist") %
1084 mark)
1084 mark)
1085 if mark == repo._activebookmark:
1085 if mark == repo._activebookmark:
1086 bookmarks.deactivate(repo)
1086 bookmarks.deactivate(repo)
1087 del marks[mark]
1087 del marks[mark]
1088
1088
1089 elif rename:
1089 elif rename:
1090 tr = repo.transaction('bookmark')
1090 tr = repo.transaction('bookmark')
1091 if not names:
1091 if not names:
1092 raise error.Abort(_("new bookmark name required"))
1092 raise error.Abort(_("new bookmark name required"))
1093 elif len(names) > 1:
1093 elif len(names) > 1:
1094 raise error.Abort(_("only one new bookmark name allowed"))
1094 raise error.Abort(_("only one new bookmark name allowed"))
1095 mark = checkformat(names[0])
1095 mark = checkformat(names[0])
1096 if rename not in marks:
1096 if rename not in marks:
1097 raise error.Abort(_("bookmark '%s' does not exist")
1097 raise error.Abort(_("bookmark '%s' does not exist")
1098 % rename)
1098 % rename)
1099 checkconflict(repo, mark, cur, force)
1099 checkconflict(repo, mark, cur, force)
1100 marks[mark] = marks[rename]
1100 marks[mark] = marks[rename]
1101 if repo._activebookmark == rename and not inactive:
1101 if repo._activebookmark == rename and not inactive:
1102 bookmarks.activate(repo, mark)
1102 bookmarks.activate(repo, mark)
1103 del marks[rename]
1103 del marks[rename]
1104 elif names:
1104 elif names:
1105 tr = repo.transaction('bookmark')
1105 tr = repo.transaction('bookmark')
1106 newact = None
1106 newact = None
1107 for mark in names:
1107 for mark in names:
1108 mark = checkformat(mark)
1108 mark = checkformat(mark)
1109 if newact is None:
1109 if newact is None:
1110 newact = mark
1110 newact = mark
1111 if inactive and mark == repo._activebookmark:
1111 if inactive and mark == repo._activebookmark:
1112 bookmarks.deactivate(repo)
1112 bookmarks.deactivate(repo)
1113 return
1113 return
1114 tgt = cur
1114 tgt = cur
1115 if rev:
1115 if rev:
1116 tgt = scmutil.revsingle(repo, rev).node()
1116 tgt = scmutil.revsingle(repo, rev).node()
1117 checkconflict(repo, mark, cur, force, tgt)
1117 checkconflict(repo, mark, cur, force, tgt)
1118 marks[mark] = tgt
1118 marks[mark] = tgt
1119 if not inactive and cur == marks[newact] and not rev:
1119 if not inactive and cur == marks[newact] and not rev:
1120 bookmarks.activate(repo, newact)
1120 bookmarks.activate(repo, newact)
1121 elif cur != tgt and newact == repo._activebookmark:
1121 elif cur != tgt and newact == repo._activebookmark:
1122 bookmarks.deactivate(repo)
1122 bookmarks.deactivate(repo)
1123 elif inactive:
1123 elif inactive:
1124 if len(marks) == 0:
1124 if len(marks) == 0:
1125 ui.status(_("no bookmarks set\n"))
1125 ui.status(_("no bookmarks set\n"))
1126 elif not repo._activebookmark:
1126 elif not repo._activebookmark:
1127 ui.status(_("no active bookmark\n"))
1127 ui.status(_("no active bookmark\n"))
1128 else:
1128 else:
1129 bookmarks.deactivate(repo)
1129 bookmarks.deactivate(repo)
1130 if tr is not None:
1130 if tr is not None:
1131 marks.recordchange(tr)
1131 marks.recordchange(tr)
1132 tr.close()
1132 tr.close()
1133 finally:
1133 finally:
1134 lockmod.release(tr, lock, wlock)
1134 lockmod.release(tr, lock, wlock)
1135 else: # show bookmarks
1135 else: # show bookmarks
1136 fm = ui.formatter('bookmarks', opts)
1136 fm = ui.formatter('bookmarks', opts)
1137 hexfn = fm.hexfunc
1137 hexfn = fm.hexfunc
1138 marks = repo._bookmarks
1138 marks = repo._bookmarks
1139 if len(marks) == 0 and not fm:
1139 if len(marks) == 0 and not fm:
1140 ui.status(_("no bookmarks set\n"))
1140 ui.status(_("no bookmarks set\n"))
1141 for bmark, n in sorted(marks.iteritems()):
1141 for bmark, n in sorted(marks.iteritems()):
1142 active = repo._activebookmark
1142 active = repo._activebookmark
1143 if bmark == active:
1143 if bmark == active:
1144 prefix, label = '*', activebookmarklabel
1144 prefix, label = '*', activebookmarklabel
1145 else:
1145 else:
1146 prefix, label = ' ', ''
1146 prefix, label = ' ', ''
1147
1147
1148 fm.startitem()
1148 fm.startitem()
1149 if not ui.quiet:
1149 if not ui.quiet:
1150 fm.plain(' %s ' % prefix, label=label)
1150 fm.plain(' %s ' % prefix, label=label)
1151 fm.write('bookmark', '%s', bmark, label=label)
1151 fm.write('bookmark', '%s', bmark, label=label)
1152 pad = " " * (25 - encoding.colwidth(bmark))
1152 pad = " " * (25 - encoding.colwidth(bmark))
1153 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1153 fm.condwrite(not ui.quiet, 'rev node', pad + ' %d:%s',
1154 repo.changelog.rev(n), hexfn(n), label=label)
1154 repo.changelog.rev(n), hexfn(n), label=label)
1155 fm.data(active=(bmark == active))
1155 fm.data(active=(bmark == active))
1156 fm.plain('\n')
1156 fm.plain('\n')
1157 fm.end()
1157 fm.end()
1158
1158
1159 @command('branch',
1159 @command('branch',
1160 [('f', 'force', None,
1160 [('f', 'force', None,
1161 _('set branch name even if it shadows an existing branch')),
1161 _('set branch name even if it shadows an existing branch')),
1162 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1162 ('C', 'clean', None, _('reset branch name to parent branch name'))],
1163 _('[-fC] [NAME]'))
1163 _('[-fC] [NAME]'))
1164 def branch(ui, repo, label=None, **opts):
1164 def branch(ui, repo, label=None, **opts):
1165 """set or show the current branch name
1165 """set or show the current branch name
1166
1166
1167 .. note::
1167 .. note::
1168
1168
1169 Branch names are permanent and global. Use :hg:`bookmark` to create a
1169 Branch names are permanent and global. Use :hg:`bookmark` to create a
1170 light-weight bookmark instead. See :hg:`help glossary` for more
1170 light-weight bookmark instead. See :hg:`help glossary` for more
1171 information about named branches and bookmarks.
1171 information about named branches and bookmarks.
1172
1172
1173 With no argument, show the current branch name. With one argument,
1173 With no argument, show the current branch name. With one argument,
1174 set the working directory branch name (the branch will not exist
1174 set the working directory branch name (the branch will not exist
1175 in the repository until the next commit). Standard practice
1175 in the repository until the next commit). Standard practice
1176 recommends that primary development take place on the 'default'
1176 recommends that primary development take place on the 'default'
1177 branch.
1177 branch.
1178
1178
1179 Unless -f/--force is specified, branch will not let you set a
1179 Unless -f/--force is specified, branch will not let you set a
1180 branch name that already exists.
1180 branch name that already exists.
1181
1181
1182 Use -C/--clean to reset the working directory branch to that of
1182 Use -C/--clean to reset the working directory branch to that of
1183 the parent of the working directory, negating a previous branch
1183 the parent of the working directory, negating a previous branch
1184 change.
1184 change.
1185
1185
1186 Use the command :hg:`update` to switch to an existing branch. Use
1186 Use the command :hg:`update` to switch to an existing branch. Use
1187 :hg:`commit --close-branch` to mark this branch head as closed.
1187 :hg:`commit --close-branch` to mark this branch head as closed.
1188 When all heads of a branch are closed, the branch will be
1188 When all heads of a branch are closed, the branch will be
1189 considered closed.
1189 considered closed.
1190
1190
1191 Returns 0 on success.
1191 Returns 0 on success.
1192 """
1192 """
1193 if label:
1193 if label:
1194 label = label.strip()
1194 label = label.strip()
1195
1195
1196 if not opts.get('clean') and not label:
1196 if not opts.get('clean') and not label:
1197 ui.write("%s\n" % repo.dirstate.branch())
1197 ui.write("%s\n" % repo.dirstate.branch())
1198 return
1198 return
1199
1199
1200 wlock = repo.wlock()
1200 wlock = repo.wlock()
1201 try:
1201 try:
1202 if opts.get('clean'):
1202 if opts.get('clean'):
1203 label = repo[None].p1().branch()
1203 label = repo[None].p1().branch()
1204 repo.dirstate.setbranch(label)
1204 repo.dirstate.setbranch(label)
1205 ui.status(_('reset working directory to branch %s\n') % label)
1205 ui.status(_('reset working directory to branch %s\n') % label)
1206 elif label:
1206 elif label:
1207 if not opts.get('force') and label in repo.branchmap():
1207 if not opts.get('force') and label in repo.branchmap():
1208 if label not in [p.branch() for p in repo[None].parents()]:
1208 if label not in [p.branch() for p in repo[None].parents()]:
1209 raise error.Abort(_('a branch of the same name already'
1209 raise error.Abort(_('a branch of the same name already'
1210 ' exists'),
1210 ' exists'),
1211 # i18n: "it" refers to an existing branch
1211 # i18n: "it" refers to an existing branch
1212 hint=_("use 'hg update' to switch to it"))
1212 hint=_("use 'hg update' to switch to it"))
1213 scmutil.checknewlabel(repo, label, 'branch')
1213 scmutil.checknewlabel(repo, label, 'branch')
1214 repo.dirstate.setbranch(label)
1214 repo.dirstate.setbranch(label)
1215 ui.status(_('marked working directory as branch %s\n') % label)
1215 ui.status(_('marked working directory as branch %s\n') % label)
1216
1216
1217 # find any open named branches aside from default
1217 # find any open named branches aside from default
1218 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1218 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1219 if n != "default" and not c]
1219 if n != "default" and not c]
1220 if not others:
1220 if not others:
1221 ui.status(_('(branches are permanent and global, '
1221 ui.status(_('(branches are permanent and global, '
1222 'did you want a bookmark?)\n'))
1222 'did you want a bookmark?)\n'))
1223 finally:
1223 finally:
1224 wlock.release()
1224 wlock.release()
1225
1225
1226 @command('branches',
1226 @command('branches',
1227 [('a', 'active', False,
1227 [('a', 'active', False,
1228 _('show only branches that have unmerged heads (DEPRECATED)')),
1228 _('show only branches that have unmerged heads (DEPRECATED)')),
1229 ('c', 'closed', False, _('show normal and closed branches')),
1229 ('c', 'closed', False, _('show normal and closed branches')),
1230 ] + formatteropts,
1230 ] + formatteropts,
1231 _('[-ac]'))
1231 _('[-ac]'))
1232 def branches(ui, repo, active=False, closed=False, **opts):
1232 def branches(ui, repo, active=False, closed=False, **opts):
1233 """list repository named branches
1233 """list repository named branches
1234
1234
1235 List the repository's named branches, indicating which ones are
1235 List the repository's named branches, indicating which ones are
1236 inactive. If -c/--closed is specified, also list branches which have
1236 inactive. If -c/--closed is specified, also list branches which have
1237 been marked closed (see :hg:`commit --close-branch`).
1237 been marked closed (see :hg:`commit --close-branch`).
1238
1238
1239 Use the command :hg:`update` to switch to an existing branch.
1239 Use the command :hg:`update` to switch to an existing branch.
1240
1240
1241 Returns 0.
1241 Returns 0.
1242 """
1242 """
1243
1243
1244 fm = ui.formatter('branches', opts)
1244 fm = ui.formatter('branches', opts)
1245 hexfunc = fm.hexfunc
1245 hexfunc = fm.hexfunc
1246
1246
1247 allheads = set(repo.heads())
1247 allheads = set(repo.heads())
1248 branches = []
1248 branches = []
1249 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1249 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1250 isactive = not isclosed and bool(set(heads) & allheads)
1250 isactive = not isclosed and bool(set(heads) & allheads)
1251 branches.append((tag, repo[tip], isactive, not isclosed))
1251 branches.append((tag, repo[tip], isactive, not isclosed))
1252 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1252 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1253 reverse=True)
1253 reverse=True)
1254
1254
1255 for tag, ctx, isactive, isopen in branches:
1255 for tag, ctx, isactive, isopen in branches:
1256 if active and not isactive:
1256 if active and not isactive:
1257 continue
1257 continue
1258 if isactive:
1258 if isactive:
1259 label = 'branches.active'
1259 label = 'branches.active'
1260 notice = ''
1260 notice = ''
1261 elif not isopen:
1261 elif not isopen:
1262 if not closed:
1262 if not closed:
1263 continue
1263 continue
1264 label = 'branches.closed'
1264 label = 'branches.closed'
1265 notice = _(' (closed)')
1265 notice = _(' (closed)')
1266 else:
1266 else:
1267 label = 'branches.inactive'
1267 label = 'branches.inactive'
1268 notice = _(' (inactive)')
1268 notice = _(' (inactive)')
1269 current = (tag == repo.dirstate.branch())
1269 current = (tag == repo.dirstate.branch())
1270 if current:
1270 if current:
1271 label = 'branches.current'
1271 label = 'branches.current'
1272
1272
1273 fm.startitem()
1273 fm.startitem()
1274 fm.write('branch', '%s', tag, label=label)
1274 fm.write('branch', '%s', tag, label=label)
1275 rev = ctx.rev()
1275 rev = ctx.rev()
1276 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1276 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1277 fmt = ' ' * padsize + ' %d:%s'
1277 fmt = ' ' * padsize + ' %d:%s'
1278 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1278 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1279 label='log.changeset changeset.%s' % ctx.phasestr())
1279 label='log.changeset changeset.%s' % ctx.phasestr())
1280 fm.data(active=isactive, closed=not isopen, current=current)
1280 fm.data(active=isactive, closed=not isopen, current=current)
1281 if not ui.quiet:
1281 if not ui.quiet:
1282 fm.plain(notice)
1282 fm.plain(notice)
1283 fm.plain('\n')
1283 fm.plain('\n')
1284 fm.end()
1284 fm.end()
1285
1285
1286 @command('bundle',
1286 @command('bundle',
1287 [('f', 'force', None, _('run even when the destination is unrelated')),
1287 [('f', 'force', None, _('run even when the destination is unrelated')),
1288 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1288 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1289 _('REV')),
1289 _('REV')),
1290 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1290 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1291 _('BRANCH')),
1291 _('BRANCH')),
1292 ('', 'base', [],
1292 ('', 'base', [],
1293 _('a base changeset assumed to be available at the destination'),
1293 _('a base changeset assumed to be available at the destination'),
1294 _('REV')),
1294 _('REV')),
1295 ('a', 'all', None, _('bundle all changesets in the repository')),
1295 ('a', 'all', None, _('bundle all changesets in the repository')),
1296 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1296 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1297 ] + remoteopts,
1297 ] + remoteopts,
1298 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1298 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1299 def bundle(ui, repo, fname, dest=None, **opts):
1299 def bundle(ui, repo, fname, dest=None, **opts):
1300 """create a changegroup file
1300 """create a changegroup file
1301
1301
1302 Generate a changegroup file collecting changesets to be added
1302 Generate a changegroup file collecting changesets to be added
1303 to a repository.
1303 to a repository.
1304
1304
1305 To create a bundle containing all changesets, use -a/--all
1305 To create a bundle containing all changesets, use -a/--all
1306 (or --base null). Otherwise, hg assumes the destination will have
1306 (or --base null). Otherwise, hg assumes the destination will have
1307 all the nodes you specify with --base parameters. Otherwise, hg
1307 all the nodes you specify with --base parameters. Otherwise, hg
1308 will assume the repository has all the nodes in destination, or
1308 will assume the repository has all the nodes in destination, or
1309 default-push/default if no destination is specified.
1309 default-push/default if no destination is specified.
1310
1310
1311 You can change bundle format with the -t/--type option. You can
1311 You can change bundle format with the -t/--type option. You can
1312 specify a compression, a bundle version or both using a dash
1312 specify a compression, a bundle version or both using a dash
1313 (comp-version). The available compression methods are: none, bzip2,
1313 (comp-version). The available compression methods are: none, bzip2,
1314 and gzip (by default, bundles are compressed using bzip2). The
1314 and gzip (by default, bundles are compressed using bzip2). The
1315 available formats are: v1, v2 (default to most suitable).
1315 available formats are: v1, v2 (default to most suitable).
1316
1316
1317 The bundle file can then be transferred using conventional means
1317 The bundle file can then be transferred using conventional means
1318 and applied to another repository with the unbundle or pull
1318 and applied to another repository with the unbundle or pull
1319 command. This is useful when direct push and pull are not
1319 command. This is useful when direct push and pull are not
1320 available or when exporting an entire repository is undesirable.
1320 available or when exporting an entire repository is undesirable.
1321
1321
1322 Applying bundles preserves all changeset contents including
1322 Applying bundles preserves all changeset contents including
1323 permissions, copy/rename information, and revision history.
1323 permissions, copy/rename information, and revision history.
1324
1324
1325 Returns 0 on success, 1 if no changes found.
1325 Returns 0 on success, 1 if no changes found.
1326 """
1326 """
1327 revs = None
1327 revs = None
1328 if 'rev' in opts:
1328 if 'rev' in opts:
1329 revs = scmutil.revrange(repo, opts['rev'])
1329 revs = scmutil.revrange(repo, opts['rev'])
1330
1330
1331 bundletype = opts.get('type', 'bzip2').lower()
1331 bundletype = opts.get('type', 'bzip2').lower()
1332 try:
1332 try:
1333 bcompression, cgversion, params = exchange.parsebundlespec(
1333 bcompression, cgversion, params = exchange.parsebundlespec(
1334 repo, bundletype, strict=False)
1334 repo, bundletype, strict=False)
1335 except error.UnsupportedBundleSpecification as e:
1335 except error.UnsupportedBundleSpecification as e:
1336 raise error.Abort(str(e),
1336 raise error.Abort(str(e),
1337 hint=_('see "hg help bundle" for supported '
1337 hint=_('see "hg help bundle" for supported '
1338 'values for --type'))
1338 'values for --type'))
1339
1339
1340 # Packed bundles are a pseudo bundle format for now.
1340 # Packed bundles are a pseudo bundle format for now.
1341 if cgversion == 's1':
1341 if cgversion == 's1':
1342 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1342 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1343 hint=_('use "hg debugcreatestreamclonebundle"'))
1343 hint=_('use "hg debugcreatestreamclonebundle"'))
1344
1344
1345 if opts.get('all'):
1345 if opts.get('all'):
1346 if dest:
1346 if dest:
1347 raise error.Abort(_("--all is incompatible with specifying "
1347 raise error.Abort(_("--all is incompatible with specifying "
1348 "a destination"))
1348 "a destination"))
1349 if opts.get('base'):
1349 if opts.get('base'):
1350 ui.warn(_("ignoring --base because --all was specified\n"))
1350 ui.warn(_("ignoring --base because --all was specified\n"))
1351 base = ['null']
1351 base = ['null']
1352 else:
1352 else:
1353 base = scmutil.revrange(repo, opts.get('base'))
1353 base = scmutil.revrange(repo, opts.get('base'))
1354 # TODO: get desired bundlecaps from command line.
1354 # TODO: get desired bundlecaps from command line.
1355 bundlecaps = None
1355 bundlecaps = None
1356 if base:
1356 if base:
1357 if dest:
1357 if dest:
1358 raise error.Abort(_("--base is incompatible with specifying "
1358 raise error.Abort(_("--base is incompatible with specifying "
1359 "a destination"))
1359 "a destination"))
1360 common = [repo.lookup(rev) for rev in base]
1360 common = [repo.lookup(rev) for rev in base]
1361 heads = revs and map(repo.lookup, revs) or revs
1361 heads = revs and map(repo.lookup, revs) or revs
1362 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1362 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1363 common=common, bundlecaps=bundlecaps,
1363 common=common, bundlecaps=bundlecaps,
1364 version=cgversion)
1364 version=cgversion)
1365 outgoing = None
1365 outgoing = None
1366 else:
1366 else:
1367 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1367 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1368 dest, branches = hg.parseurl(dest, opts.get('branch'))
1368 dest, branches = hg.parseurl(dest, opts.get('branch'))
1369 other = hg.peer(repo, opts, dest)
1369 other = hg.peer(repo, opts, dest)
1370 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1370 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1371 heads = revs and map(repo.lookup, revs) or revs
1371 heads = revs and map(repo.lookup, revs) or revs
1372 outgoing = discovery.findcommonoutgoing(repo, other,
1372 outgoing = discovery.findcommonoutgoing(repo, other,
1373 onlyheads=heads,
1373 onlyheads=heads,
1374 force=opts.get('force'),
1374 force=opts.get('force'),
1375 portable=True)
1375 portable=True)
1376 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1376 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1377 bundlecaps, version=cgversion)
1377 bundlecaps, version=cgversion)
1378 if not cg:
1378 if not cg:
1379 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1379 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1380 return 1
1380 return 1
1381
1381
1382 if cgversion == '01': #bundle1
1382 if cgversion == '01': #bundle1
1383 if bcompression is None:
1383 if bcompression is None:
1384 bcompression = 'UN'
1384 bcompression = 'UN'
1385 bversion = 'HG10' + bcompression
1385 bversion = 'HG10' + bcompression
1386 bcompression = None
1386 bcompression = None
1387 else:
1387 else:
1388 assert cgversion == '02'
1388 assert cgversion == '02'
1389 bversion = 'HG20'
1389 bversion = 'HG20'
1390
1390
1391
1391
1392 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1392 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1393
1393
1394 @command('cat',
1394 @command('cat',
1395 [('o', 'output', '',
1395 [('o', 'output', '',
1396 _('print output to file with formatted name'), _('FORMAT')),
1396 _('print output to file with formatted name'), _('FORMAT')),
1397 ('r', 'rev', '', _('print the given revision'), _('REV')),
1397 ('r', 'rev', '', _('print the given revision'), _('REV')),
1398 ('', 'decode', None, _('apply any matching decode filter')),
1398 ('', 'decode', None, _('apply any matching decode filter')),
1399 ] + walkopts,
1399 ] + walkopts,
1400 _('[OPTION]... FILE...'),
1400 _('[OPTION]... FILE...'),
1401 inferrepo=True)
1401 inferrepo=True)
1402 def cat(ui, repo, file1, *pats, **opts):
1402 def cat(ui, repo, file1, *pats, **opts):
1403 """output the current or given revision of files
1403 """output the current or given revision of files
1404
1404
1405 Print the specified files as they were at the given revision. If
1405 Print the specified files as they were at the given revision. If
1406 no revision is given, the parent of the working directory is used.
1406 no revision is given, the parent of the working directory is used.
1407
1407
1408 Output may be to a file, in which case the name of the file is
1408 Output may be to a file, in which case the name of the file is
1409 given using a format string. The formatting rules as follows:
1409 given using a format string. The formatting rules as follows:
1410
1410
1411 :``%%``: literal "%" character
1411 :``%%``: literal "%" character
1412 :``%s``: basename of file being printed
1412 :``%s``: basename of file being printed
1413 :``%d``: dirname of file being printed, or '.' if in repository root
1413 :``%d``: dirname of file being printed, or '.' if in repository root
1414 :``%p``: root-relative path name of file being printed
1414 :``%p``: root-relative path name of file being printed
1415 :``%H``: changeset hash (40 hexadecimal digits)
1415 :``%H``: changeset hash (40 hexadecimal digits)
1416 :``%R``: changeset revision number
1416 :``%R``: changeset revision number
1417 :``%h``: short-form changeset hash (12 hexadecimal digits)
1417 :``%h``: short-form changeset hash (12 hexadecimal digits)
1418 :``%r``: zero-padded changeset revision number
1418 :``%r``: zero-padded changeset revision number
1419 :``%b``: basename of the exporting repository
1419 :``%b``: basename of the exporting repository
1420
1420
1421 Returns 0 on success.
1421 Returns 0 on success.
1422 """
1422 """
1423 ctx = scmutil.revsingle(repo, opts.get('rev'))
1423 ctx = scmutil.revsingle(repo, opts.get('rev'))
1424 m = scmutil.match(ctx, (file1,) + pats, opts)
1424 m = scmutil.match(ctx, (file1,) + pats, opts)
1425
1425
1426 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1426 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1427
1427
1428 @command('^clone',
1428 @command('^clone',
1429 [('U', 'noupdate', None, _('the clone will include an empty working '
1429 [('U', 'noupdate', None, _('the clone will include an empty working '
1430 'directory (only a repository)')),
1430 'directory (only a repository)')),
1431 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1431 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1432 _('REV')),
1432 _('REV')),
1433 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1433 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1434 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1434 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1435 ('', 'pull', None, _('use pull protocol to copy metadata')),
1435 ('', 'pull', None, _('use pull protocol to copy metadata')),
1436 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1436 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1437 ] + remoteopts,
1437 ] + remoteopts,
1438 _('[OPTION]... SOURCE [DEST]'),
1438 _('[OPTION]... SOURCE [DEST]'),
1439 norepo=True)
1439 norepo=True)
1440 def clone(ui, source, dest=None, **opts):
1440 def clone(ui, source, dest=None, **opts):
1441 """make a copy of an existing repository
1441 """make a copy of an existing repository
1442
1442
1443 Create a copy of an existing repository in a new directory.
1443 Create a copy of an existing repository in a new directory.
1444
1444
1445 If no destination directory name is specified, it defaults to the
1445 If no destination directory name is specified, it defaults to the
1446 basename of the source.
1446 basename of the source.
1447
1447
1448 The location of the source is added to the new repository's
1448 The location of the source is added to the new repository's
1449 ``.hg/hgrc`` file, as the default to be used for future pulls.
1449 ``.hg/hgrc`` file, as the default to be used for future pulls.
1450
1450
1451 Only local paths and ``ssh://`` URLs are supported as
1451 Only local paths and ``ssh://`` URLs are supported as
1452 destinations. For ``ssh://`` destinations, no working directory or
1452 destinations. For ``ssh://`` destinations, no working directory or
1453 ``.hg/hgrc`` will be created on the remote side.
1453 ``.hg/hgrc`` will be created on the remote side.
1454
1454
1455 If the source repository has a bookmark called '@' set, that
1455 If the source repository has a bookmark called '@' set, that
1456 revision will be checked out in the new repository by default.
1456 revision will be checked out in the new repository by default.
1457
1457
1458 To check out a particular version, use -u/--update, or
1458 To check out a particular version, use -u/--update, or
1459 -U/--noupdate to create a clone with no working directory.
1459 -U/--noupdate to create a clone with no working directory.
1460
1460
1461 To pull only a subset of changesets, specify one or more revisions
1461 To pull only a subset of changesets, specify one or more revisions
1462 identifiers with -r/--rev or branches with -b/--branch. The
1462 identifiers with -r/--rev or branches with -b/--branch. The
1463 resulting clone will contain only the specified changesets and
1463 resulting clone will contain only the specified changesets and
1464 their ancestors. These options (or 'clone src#rev dest') imply
1464 their ancestors. These options (or 'clone src#rev dest') imply
1465 --pull, even for local source repositories.
1465 --pull, even for local source repositories.
1466
1466
1467 .. note::
1467 .. note::
1468
1468
1469 Specifying a tag will include the tagged changeset but not the
1469 Specifying a tag will include the tagged changeset but not the
1470 changeset containing the tag.
1470 changeset containing the tag.
1471
1471
1472 .. container:: verbose
1472 .. container:: verbose
1473
1473
1474 For efficiency, hardlinks are used for cloning whenever the
1474 For efficiency, hardlinks are used for cloning whenever the
1475 source and destination are on the same filesystem (note this
1475 source and destination are on the same filesystem (note this
1476 applies only to the repository data, not to the working
1476 applies only to the repository data, not to the working
1477 directory). Some filesystems, such as AFS, implement hardlinking
1477 directory). Some filesystems, such as AFS, implement hardlinking
1478 incorrectly, but do not report errors. In these cases, use the
1478 incorrectly, but do not report errors. In these cases, use the
1479 --pull option to avoid hardlinking.
1479 --pull option to avoid hardlinking.
1480
1480
1481 In some cases, you can clone repositories and the working
1481 In some cases, you can clone repositories and the working
1482 directory using full hardlinks with ::
1482 directory using full hardlinks with ::
1483
1483
1484 $ cp -al REPO REPOCLONE
1484 $ cp -al REPO REPOCLONE
1485
1485
1486 This is the fastest way to clone, but it is not always safe. The
1486 This is the fastest way to clone, but it is not always safe. The
1487 operation is not atomic (making sure REPO is not modified during
1487 operation is not atomic (making sure REPO is not modified during
1488 the operation is up to you) and you have to make sure your
1488 the operation is up to you) and you have to make sure your
1489 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1489 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1490 so). Also, this is not compatible with certain extensions that
1490 so). Also, this is not compatible with certain extensions that
1491 place their metadata under the .hg directory, such as mq.
1491 place their metadata under the .hg directory, such as mq.
1492
1492
1493 Mercurial will update the working directory to the first applicable
1493 Mercurial will update the working directory to the first applicable
1494 revision from this list:
1494 revision from this list:
1495
1495
1496 a) null if -U or the source repository has no changesets
1496 a) null if -U or the source repository has no changesets
1497 b) if -u . and the source repository is local, the first parent of
1497 b) if -u . and the source repository is local, the first parent of
1498 the source repository's working directory
1498 the source repository's working directory
1499 c) the changeset specified with -u (if a branch name, this means the
1499 c) the changeset specified with -u (if a branch name, this means the
1500 latest head of that branch)
1500 latest head of that branch)
1501 d) the changeset specified with -r
1501 d) the changeset specified with -r
1502 e) the tipmost head specified with -b
1502 e) the tipmost head specified with -b
1503 f) the tipmost head specified with the url#branch source syntax
1503 f) the tipmost head specified with the url#branch source syntax
1504 g) the revision marked with the '@' bookmark, if present
1504 g) the revision marked with the '@' bookmark, if present
1505 h) the tipmost head of the default branch
1505 h) the tipmost head of the default branch
1506 i) tip
1506 i) tip
1507
1507
1508 Examples:
1508 Examples:
1509
1509
1510 - clone a remote repository to a new directory named hg/::
1510 - clone a remote repository to a new directory named hg/::
1511
1511
1512 hg clone http://selenic.com/hg
1512 hg clone http://selenic.com/hg
1513
1513
1514 - create a lightweight local clone::
1514 - create a lightweight local clone::
1515
1515
1516 hg clone project/ project-feature/
1516 hg clone project/ project-feature/
1517
1517
1518 - clone from an absolute path on an ssh server (note double-slash)::
1518 - clone from an absolute path on an ssh server (note double-slash)::
1519
1519
1520 hg clone ssh://user@server//home/projects/alpha/
1520 hg clone ssh://user@server//home/projects/alpha/
1521
1521
1522 - do a high-speed clone over a LAN while checking out a
1522 - do a high-speed clone over a LAN while checking out a
1523 specified version::
1523 specified version::
1524
1524
1525 hg clone --uncompressed http://server/repo -u 1.5
1525 hg clone --uncompressed http://server/repo -u 1.5
1526
1526
1527 - create a repository without changesets after a particular revision::
1527 - create a repository without changesets after a particular revision::
1528
1528
1529 hg clone -r 04e544 experimental/ good/
1529 hg clone -r 04e544 experimental/ good/
1530
1530
1531 - clone (and track) a particular named branch::
1531 - clone (and track) a particular named branch::
1532
1532
1533 hg clone http://selenic.com/hg#stable
1533 hg clone http://selenic.com/hg#stable
1534
1534
1535 See :hg:`help urls` for details on specifying URLs.
1535 See :hg:`help urls` for details on specifying URLs.
1536
1536
1537 Returns 0 on success.
1537 Returns 0 on success.
1538 """
1538 """
1539 if opts.get('noupdate') and opts.get('updaterev'):
1539 if opts.get('noupdate') and opts.get('updaterev'):
1540 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1540 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1541
1541
1542 r = hg.clone(ui, opts, source, dest,
1542 r = hg.clone(ui, opts, source, dest,
1543 pull=opts.get('pull'),
1543 pull=opts.get('pull'),
1544 stream=opts.get('uncompressed'),
1544 stream=opts.get('uncompressed'),
1545 rev=opts.get('rev'),
1545 rev=opts.get('rev'),
1546 update=opts.get('updaterev') or not opts.get('noupdate'),
1546 update=opts.get('updaterev') or not opts.get('noupdate'),
1547 branch=opts.get('branch'),
1547 branch=opts.get('branch'),
1548 shareopts=opts.get('shareopts'))
1548 shareopts=opts.get('shareopts'))
1549
1549
1550 return r is None
1550 return r is None
1551
1551
1552 @command('^commit|ci',
1552 @command('^commit|ci',
1553 [('A', 'addremove', None,
1553 [('A', 'addremove', None,
1554 _('mark new/missing files as added/removed before committing')),
1554 _('mark new/missing files as added/removed before committing')),
1555 ('', 'close-branch', None,
1555 ('', 'close-branch', None,
1556 _('mark a branch head as closed')),
1556 _('mark a branch head as closed')),
1557 ('', 'amend', None, _('amend the parent of the working directory')),
1557 ('', 'amend', None, _('amend the parent of the working directory')),
1558 ('s', 'secret', None, _('use the secret phase for committing')),
1558 ('s', 'secret', None, _('use the secret phase for committing')),
1559 ('e', 'edit', None, _('invoke editor on commit messages')),
1559 ('e', 'edit', None, _('invoke editor on commit messages')),
1560 ('i', 'interactive', None, _('use interactive mode')),
1560 ('i', 'interactive', None, _('use interactive mode')),
1561 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1561 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1562 _('[OPTION]... [FILE]...'),
1562 _('[OPTION]... [FILE]...'),
1563 inferrepo=True)
1563 inferrepo=True)
1564 def commit(ui, repo, *pats, **opts):
1564 def commit(ui, repo, *pats, **opts):
1565 """commit the specified files or all outstanding changes
1565 """commit the specified files or all outstanding changes
1566
1566
1567 Commit changes to the given files into the repository. Unlike a
1567 Commit changes to the given files into the repository. Unlike a
1568 centralized SCM, this operation is a local operation. See
1568 centralized SCM, this operation is a local operation. See
1569 :hg:`push` for a way to actively distribute your changes.
1569 :hg:`push` for a way to actively distribute your changes.
1570
1570
1571 If a list of files is omitted, all changes reported by :hg:`status`
1571 If a list of files is omitted, all changes reported by :hg:`status`
1572 will be committed.
1572 will be committed.
1573
1573
1574 If you are committing the result of a merge, do not provide any
1574 If you are committing the result of a merge, do not provide any
1575 filenames or -I/-X filters.
1575 filenames or -I/-X filters.
1576
1576
1577 If no commit message is specified, Mercurial starts your
1577 If no commit message is specified, Mercurial starts your
1578 configured editor where you can enter a message. In case your
1578 configured editor where you can enter a message. In case your
1579 commit fails, you will find a backup of your message in
1579 commit fails, you will find a backup of your message in
1580 ``.hg/last-message.txt``.
1580 ``.hg/last-message.txt``.
1581
1581
1582 The --close-branch flag can be used to mark the current branch
1582 The --close-branch flag can be used to mark the current branch
1583 head closed. When all heads of a branch are closed, the branch
1583 head closed. When all heads of a branch are closed, the branch
1584 will be considered closed and no longer listed.
1584 will be considered closed and no longer listed.
1585
1585
1586 The --amend flag can be used to amend the parent of the
1586 The --amend flag can be used to amend the parent of the
1587 working directory with a new commit that contains the changes
1587 working directory with a new commit that contains the changes
1588 in the parent in addition to those currently reported by :hg:`status`,
1588 in the parent in addition to those currently reported by :hg:`status`,
1589 if there are any. The old commit is stored in a backup bundle in
1589 if there are any. The old commit is stored in a backup bundle in
1590 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1590 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1591 on how to restore it).
1591 on how to restore it).
1592
1592
1593 Message, user and date are taken from the amended commit unless
1593 Message, user and date are taken from the amended commit unless
1594 specified. When a message isn't specified on the command line,
1594 specified. When a message isn't specified on the command line,
1595 the editor will open with the message of the amended commit.
1595 the editor will open with the message of the amended commit.
1596
1596
1597 It is not possible to amend public changesets (see :hg:`help phases`)
1597 It is not possible to amend public changesets (see :hg:`help phases`)
1598 or changesets that have children.
1598 or changesets that have children.
1599
1599
1600 See :hg:`help dates` for a list of formats valid for -d/--date.
1600 See :hg:`help dates` for a list of formats valid for -d/--date.
1601
1601
1602 Returns 0 on success, 1 if nothing changed.
1602 Returns 0 on success, 1 if nothing changed.
1603
1603
1604 .. container:: verbose
1604 .. container:: verbose
1605
1605
1606 Examples:
1606 Examples:
1607
1607
1608 - commit all files ending in .py::
1608 - commit all files ending in .py::
1609
1609
1610 hg commit --include "set:**.py"
1610 hg commit --include "set:**.py"
1611
1611
1612 - commit all non-binary files::
1612 - commit all non-binary files::
1613
1613
1614 hg commit --exclude "set:binary()"
1614 hg commit --exclude "set:binary()"
1615
1615
1616 - amend the current commit and set the date to now::
1616 - amend the current commit and set the date to now::
1617
1617
1618 hg commit --amend --date now
1618 hg commit --amend --date now
1619 """
1619 """
1620 wlock = lock = None
1620 wlock = lock = None
1621 try:
1621 try:
1622 wlock = repo.wlock()
1622 wlock = repo.wlock()
1623 lock = repo.lock()
1623 lock = repo.lock()
1624 return _docommit(ui, repo, *pats, **opts)
1624 return _docommit(ui, repo, *pats, **opts)
1625 finally:
1625 finally:
1626 release(lock, wlock)
1626 release(lock, wlock)
1627
1627
1628 def _docommit(ui, repo, *pats, **opts):
1628 def _docommit(ui, repo, *pats, **opts):
1629 if opts.get('interactive'):
1629 if opts.get('interactive'):
1630 opts.pop('interactive')
1630 opts.pop('interactive')
1631 cmdutil.dorecord(ui, repo, commit, None, False,
1631 cmdutil.dorecord(ui, repo, commit, None, False,
1632 cmdutil.recordfilter, *pats, **opts)
1632 cmdutil.recordfilter, *pats, **opts)
1633 return
1633 return
1634
1634
1635 if opts.get('subrepos'):
1635 if opts.get('subrepos'):
1636 if opts.get('amend'):
1636 if opts.get('amend'):
1637 raise error.Abort(_('cannot amend with --subrepos'))
1637 raise error.Abort(_('cannot amend with --subrepos'))
1638 # Let --subrepos on the command line override config setting.
1638 # Let --subrepos on the command line override config setting.
1639 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1639 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1640
1640
1641 cmdutil.checkunfinished(repo, commit=True)
1641 cmdutil.checkunfinished(repo, commit=True)
1642
1642
1643 branch = repo[None].branch()
1643 branch = repo[None].branch()
1644 bheads = repo.branchheads(branch)
1644 bheads = repo.branchheads(branch)
1645
1645
1646 extra = {}
1646 extra = {}
1647 if opts.get('close_branch'):
1647 if opts.get('close_branch'):
1648 extra['close'] = 1
1648 extra['close'] = 1
1649
1649
1650 if not bheads:
1650 if not bheads:
1651 raise error.Abort(_('can only close branch heads'))
1651 raise error.Abort(_('can only close branch heads'))
1652 elif opts.get('amend'):
1652 elif opts.get('amend'):
1653 if repo[None].parents()[0].p1().branch() != branch and \
1653 if repo[None].parents()[0].p1().branch() != branch and \
1654 repo[None].parents()[0].p2().branch() != branch:
1654 repo[None].parents()[0].p2().branch() != branch:
1655 raise error.Abort(_('can only close branch heads'))
1655 raise error.Abort(_('can only close branch heads'))
1656
1656
1657 if opts.get('amend'):
1657 if opts.get('amend'):
1658 if ui.configbool('ui', 'commitsubrepos'):
1658 if ui.configbool('ui', 'commitsubrepos'):
1659 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1659 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1660
1660
1661 old = repo['.']
1661 old = repo['.']
1662 if not old.mutable():
1662 if not old.mutable():
1663 raise error.Abort(_('cannot amend public changesets'))
1663 raise error.Abort(_('cannot amend public changesets'))
1664 if len(repo[None].parents()) > 1:
1664 if len(repo[None].parents()) > 1:
1665 raise error.Abort(_('cannot amend while merging'))
1665 raise error.Abort(_('cannot amend while merging'))
1666 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1666 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1667 if not allowunstable and old.children():
1667 if not allowunstable and old.children():
1668 raise error.Abort(_('cannot amend changeset with children'))
1668 raise error.Abort(_('cannot amend changeset with children'))
1669
1669
1670 newextra = extra.copy()
1670 newextra = extra.copy()
1671 newextra['branch'] = branch
1671 newextra['branch'] = branch
1672 extra = newextra
1672 extra = newextra
1673 # commitfunc is used only for temporary amend commit by cmdutil.amend
1673 # commitfunc is used only for temporary amend commit by cmdutil.amend
1674 def commitfunc(ui, repo, message, match, opts):
1674 def commitfunc(ui, repo, message, match, opts):
1675 return repo.commit(message,
1675 return repo.commit(message,
1676 opts.get('user') or old.user(),
1676 opts.get('user') or old.user(),
1677 opts.get('date') or old.date(),
1677 opts.get('date') or old.date(),
1678 match,
1678 match,
1679 extra=extra)
1679 extra=extra)
1680
1680
1681 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1681 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1682 if node == old.node():
1682 if node == old.node():
1683 ui.status(_("nothing changed\n"))
1683 ui.status(_("nothing changed\n"))
1684 return 1
1684 return 1
1685 else:
1685 else:
1686 def commitfunc(ui, repo, message, match, opts):
1686 def commitfunc(ui, repo, message, match, opts):
1687 backup = ui.backupconfig('phases', 'new-commit')
1687 backup = ui.backupconfig('phases', 'new-commit')
1688 baseui = repo.baseui
1688 baseui = repo.baseui
1689 basebackup = baseui.backupconfig('phases', 'new-commit')
1689 basebackup = baseui.backupconfig('phases', 'new-commit')
1690 try:
1690 try:
1691 if opts.get('secret'):
1691 if opts.get('secret'):
1692 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1692 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1693 # Propagate to subrepos
1693 # Propagate to subrepos
1694 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1694 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1695
1695
1696 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1696 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1697 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1697 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1698 return repo.commit(message, opts.get('user'), opts.get('date'),
1698 return repo.commit(message, opts.get('user'), opts.get('date'),
1699 match,
1699 match,
1700 editor=editor,
1700 editor=editor,
1701 extra=extra)
1701 extra=extra)
1702 finally:
1702 finally:
1703 ui.restoreconfig(backup)
1703 ui.restoreconfig(backup)
1704 repo.baseui.restoreconfig(basebackup)
1704 repo.baseui.restoreconfig(basebackup)
1705
1705
1706
1706
1707 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1707 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1708
1708
1709 if not node:
1709 if not node:
1710 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1710 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1711 if stat[3]:
1711 if stat[3]:
1712 ui.status(_("nothing changed (%d missing files, see "
1712 ui.status(_("nothing changed (%d missing files, see "
1713 "'hg status')\n") % len(stat[3]))
1713 "'hg status')\n") % len(stat[3]))
1714 else:
1714 else:
1715 ui.status(_("nothing changed\n"))
1715 ui.status(_("nothing changed\n"))
1716 return 1
1716 return 1
1717
1717
1718 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1718 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1719
1719
1720 @command('config|showconfig|debugconfig',
1720 @command('config|showconfig|debugconfig',
1721 [('u', 'untrusted', None, _('show untrusted configuration options')),
1721 [('u', 'untrusted', None, _('show untrusted configuration options')),
1722 ('e', 'edit', None, _('edit user config')),
1722 ('e', 'edit', None, _('edit user config')),
1723 ('l', 'local', None, _('edit repository config')),
1723 ('l', 'local', None, _('edit repository config')),
1724 ('g', 'global', None, _('edit global config'))],
1724 ('g', 'global', None, _('edit global config'))],
1725 _('[-u] [NAME]...'),
1725 _('[-u] [NAME]...'),
1726 optionalrepo=True)
1726 optionalrepo=True)
1727 def config(ui, repo, *values, **opts):
1727 def config(ui, repo, *values, **opts):
1728 """show combined config settings from all hgrc files
1728 """show combined config settings from all hgrc files
1729
1729
1730 With no arguments, print names and values of all config items.
1730 With no arguments, print names and values of all config items.
1731
1731
1732 With one argument of the form section.name, print just the value
1732 With one argument of the form section.name, print just the value
1733 of that config item.
1733 of that config item.
1734
1734
1735 With multiple arguments, print names and values of all config
1735 With multiple arguments, print names and values of all config
1736 items with matching section names.
1736 items with matching section names.
1737
1737
1738 With --edit, start an editor on the user-level config file. With
1738 With --edit, start an editor on the user-level config file. With
1739 --global, edit the system-wide config file. With --local, edit the
1739 --global, edit the system-wide config file. With --local, edit the
1740 repository-level config file.
1740 repository-level config file.
1741
1741
1742 With --debug, the source (filename and line number) is printed
1742 With --debug, the source (filename and line number) is printed
1743 for each config item.
1743 for each config item.
1744
1744
1745 See :hg:`help config` for more information about config files.
1745 See :hg:`help config` for more information about config files.
1746
1746
1747 Returns 0 on success, 1 if NAME does not exist.
1747 Returns 0 on success, 1 if NAME does not exist.
1748
1748
1749 """
1749 """
1750
1750
1751 if opts.get('edit') or opts.get('local') or opts.get('global'):
1751 if opts.get('edit') or opts.get('local') or opts.get('global'):
1752 if opts.get('local') and opts.get('global'):
1752 if opts.get('local') and opts.get('global'):
1753 raise error.Abort(_("can't use --local and --global together"))
1753 raise error.Abort(_("can't use --local and --global together"))
1754
1754
1755 if opts.get('local'):
1755 if opts.get('local'):
1756 if not repo:
1756 if not repo:
1757 raise error.Abort(_("can't use --local outside a repository"))
1757 raise error.Abort(_("can't use --local outside a repository"))
1758 paths = [repo.join('hgrc')]
1758 paths = [repo.join('hgrc')]
1759 elif opts.get('global'):
1759 elif opts.get('global'):
1760 paths = scmutil.systemrcpath()
1760 paths = scmutil.systemrcpath()
1761 else:
1761 else:
1762 paths = scmutil.userrcpath()
1762 paths = scmutil.userrcpath()
1763
1763
1764 for f in paths:
1764 for f in paths:
1765 if os.path.exists(f):
1765 if os.path.exists(f):
1766 break
1766 break
1767 else:
1767 else:
1768 if opts.get('global'):
1768 if opts.get('global'):
1769 samplehgrc = uimod.samplehgrcs['global']
1769 samplehgrc = uimod.samplehgrcs['global']
1770 elif opts.get('local'):
1770 elif opts.get('local'):
1771 samplehgrc = uimod.samplehgrcs['local']
1771 samplehgrc = uimod.samplehgrcs['local']
1772 else:
1772 else:
1773 samplehgrc = uimod.samplehgrcs['user']
1773 samplehgrc = uimod.samplehgrcs['user']
1774
1774
1775 f = paths[0]
1775 f = paths[0]
1776 fp = open(f, "w")
1776 fp = open(f, "w")
1777 fp.write(samplehgrc)
1777 fp.write(samplehgrc)
1778 fp.close()
1778 fp.close()
1779
1779
1780 editor = ui.geteditor()
1780 editor = ui.geteditor()
1781 ui.system("%s \"%s\"" % (editor, f),
1781 ui.system("%s \"%s\"" % (editor, f),
1782 onerr=error.Abort, errprefix=_("edit failed"))
1782 onerr=error.Abort, errprefix=_("edit failed"))
1783 return
1783 return
1784
1784
1785 for f in scmutil.rcpath():
1785 for f in scmutil.rcpath():
1786 ui.debug('read config from: %s\n' % f)
1786 ui.debug('read config from: %s\n' % f)
1787 untrusted = bool(opts.get('untrusted'))
1787 untrusted = bool(opts.get('untrusted'))
1788 if values:
1788 if values:
1789 sections = [v for v in values if '.' not in v]
1789 sections = [v for v in values if '.' not in v]
1790 items = [v for v in values if '.' in v]
1790 items = [v for v in values if '.' in v]
1791 if len(items) > 1 or items and sections:
1791 if len(items) > 1 or items and sections:
1792 raise error.Abort(_('only one config item permitted'))
1792 raise error.Abort(_('only one config item permitted'))
1793 matched = False
1793 matched = False
1794 for section, name, value in ui.walkconfig(untrusted=untrusted):
1794 for section, name, value in ui.walkconfig(untrusted=untrusted):
1795 value = str(value).replace('\n', '\\n')
1795 value = str(value).replace('\n', '\\n')
1796 sectname = section + '.' + name
1796 sectname = section + '.' + name
1797 if values:
1797 if values:
1798 for v in values:
1798 for v in values:
1799 if v == section:
1799 if v == section:
1800 ui.debug('%s: ' %
1800 ui.debug('%s: ' %
1801 ui.configsource(section, name, untrusted))
1801 ui.configsource(section, name, untrusted))
1802 ui.write('%s=%s\n' % (sectname, value))
1802 ui.write('%s=%s\n' % (sectname, value))
1803 matched = True
1803 matched = True
1804 elif v == sectname:
1804 elif v == sectname:
1805 ui.debug('%s: ' %
1805 ui.debug('%s: ' %
1806 ui.configsource(section, name, untrusted))
1806 ui.configsource(section, name, untrusted))
1807 ui.write(value, '\n')
1807 ui.write(value, '\n')
1808 matched = True
1808 matched = True
1809 else:
1809 else:
1810 ui.debug('%s: ' %
1810 ui.debug('%s: ' %
1811 ui.configsource(section, name, untrusted))
1811 ui.configsource(section, name, untrusted))
1812 ui.write('%s=%s\n' % (sectname, value))
1812 ui.write('%s=%s\n' % (sectname, value))
1813 matched = True
1813 matched = True
1814 if matched:
1814 if matched:
1815 return 0
1815 return 0
1816 return 1
1816 return 1
1817
1817
1818 @command('copy|cp',
1818 @command('copy|cp',
1819 [('A', 'after', None, _('record a copy that has already occurred')),
1819 [('A', 'after', None, _('record a copy that has already occurred')),
1820 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1820 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1821 ] + walkopts + dryrunopts,
1821 ] + walkopts + dryrunopts,
1822 _('[OPTION]... [SOURCE]... DEST'))
1822 _('[OPTION]... [SOURCE]... DEST'))
1823 def copy(ui, repo, *pats, **opts):
1823 def copy(ui, repo, *pats, **opts):
1824 """mark files as copied for the next commit
1824 """mark files as copied for the next commit
1825
1825
1826 Mark dest as having copies of source files. If dest is a
1826 Mark dest as having copies of source files. If dest is a
1827 directory, copies are put in that directory. If dest is a file,
1827 directory, copies are put in that directory. If dest is a file,
1828 the source must be a single file.
1828 the source must be a single file.
1829
1829
1830 By default, this command copies the contents of files as they
1830 By default, this command copies the contents of files as they
1831 exist in the working directory. If invoked with -A/--after, the
1831 exist in the working directory. If invoked with -A/--after, the
1832 operation is recorded, but no copying is performed.
1832 operation is recorded, but no copying is performed.
1833
1833
1834 This command takes effect with the next commit. To undo a copy
1834 This command takes effect with the next commit. To undo a copy
1835 before that, see :hg:`revert`.
1835 before that, see :hg:`revert`.
1836
1836
1837 Returns 0 on success, 1 if errors are encountered.
1837 Returns 0 on success, 1 if errors are encountered.
1838 """
1838 """
1839 wlock = repo.wlock(False)
1839 wlock = repo.wlock(False)
1840 try:
1840 try:
1841 return cmdutil.copy(ui, repo, pats, opts)
1841 return cmdutil.copy(ui, repo, pats, opts)
1842 finally:
1842 finally:
1843 wlock.release()
1843 wlock.release()
1844
1844
1845 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1845 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1846 def debugancestor(ui, repo, *args):
1846 def debugancestor(ui, repo, *args):
1847 """find the ancestor revision of two revisions in a given index"""
1847 """find the ancestor revision of two revisions in a given index"""
1848 if len(args) == 3:
1848 if len(args) == 3:
1849 index, rev1, rev2 = args
1849 index, rev1, rev2 = args
1850 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1850 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1851 lookup = r.lookup
1851 lookup = r.lookup
1852 elif len(args) == 2:
1852 elif len(args) == 2:
1853 if not repo:
1853 if not repo:
1854 raise error.Abort(_("there is no Mercurial repository here "
1854 raise error.Abort(_("there is no Mercurial repository here "
1855 "(.hg not found)"))
1855 "(.hg not found)"))
1856 rev1, rev2 = args
1856 rev1, rev2 = args
1857 r = repo.changelog
1857 r = repo.changelog
1858 lookup = repo.lookup
1858 lookup = repo.lookup
1859 else:
1859 else:
1860 raise error.Abort(_('either two or three arguments required'))
1860 raise error.Abort(_('either two or three arguments required'))
1861 a = r.ancestor(lookup(rev1), lookup(rev2))
1861 a = r.ancestor(lookup(rev1), lookup(rev2))
1862 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1862 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1863
1863
1864 @command('debugbuilddag',
1864 @command('debugbuilddag',
1865 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1865 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1866 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1866 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1867 ('n', 'new-file', None, _('add new file at each rev'))],
1867 ('n', 'new-file', None, _('add new file at each rev'))],
1868 _('[OPTION]... [TEXT]'))
1868 _('[OPTION]... [TEXT]'))
1869 def debugbuilddag(ui, repo, text=None,
1869 def debugbuilddag(ui, repo, text=None,
1870 mergeable_file=False,
1870 mergeable_file=False,
1871 overwritten_file=False,
1871 overwritten_file=False,
1872 new_file=False):
1872 new_file=False):
1873 """builds a repo with a given DAG from scratch in the current empty repo
1873 """builds a repo with a given DAG from scratch in the current empty repo
1874
1874
1875 The description of the DAG is read from stdin if not given on the
1875 The description of the DAG is read from stdin if not given on the
1876 command line.
1876 command line.
1877
1877
1878 Elements:
1878 Elements:
1879
1879
1880 - "+n" is a linear run of n nodes based on the current default parent
1880 - "+n" is a linear run of n nodes based on the current default parent
1881 - "." is a single node based on the current default parent
1881 - "." is a single node based on the current default parent
1882 - "$" resets the default parent to null (implied at the start);
1882 - "$" resets the default parent to null (implied at the start);
1883 otherwise the default parent is always the last node created
1883 otherwise the default parent is always the last node created
1884 - "<p" sets the default parent to the backref p
1884 - "<p" sets the default parent to the backref p
1885 - "*p" is a fork at parent p, which is a backref
1885 - "*p" is a fork at parent p, which is a backref
1886 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1886 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1887 - "/p2" is a merge of the preceding node and p2
1887 - "/p2" is a merge of the preceding node and p2
1888 - ":tag" defines a local tag for the preceding node
1888 - ":tag" defines a local tag for the preceding node
1889 - "@branch" sets the named branch for subsequent nodes
1889 - "@branch" sets the named branch for subsequent nodes
1890 - "#...\\n" is a comment up to the end of the line
1890 - "#...\\n" is a comment up to the end of the line
1891
1891
1892 Whitespace between the above elements is ignored.
1892 Whitespace between the above elements is ignored.
1893
1893
1894 A backref is either
1894 A backref is either
1895
1895
1896 - a number n, which references the node curr-n, where curr is the current
1896 - a number n, which references the node curr-n, where curr is the current
1897 node, or
1897 node, or
1898 - the name of a local tag you placed earlier using ":tag", or
1898 - the name of a local tag you placed earlier using ":tag", or
1899 - empty to denote the default parent.
1899 - empty to denote the default parent.
1900
1900
1901 All string valued-elements are either strictly alphanumeric, or must
1901 All string valued-elements are either strictly alphanumeric, or must
1902 be enclosed in double quotes ("..."), with "\\" as escape character.
1902 be enclosed in double quotes ("..."), with "\\" as escape character.
1903 """
1903 """
1904
1904
1905 if text is None:
1905 if text is None:
1906 ui.status(_("reading DAG from stdin\n"))
1906 ui.status(_("reading DAG from stdin\n"))
1907 text = ui.fin.read()
1907 text = ui.fin.read()
1908
1908
1909 cl = repo.changelog
1909 cl = repo.changelog
1910 if len(cl) > 0:
1910 if len(cl) > 0:
1911 raise error.Abort(_('repository is not empty'))
1911 raise error.Abort(_('repository is not empty'))
1912
1912
1913 # determine number of revs in DAG
1913 # determine number of revs in DAG
1914 total = 0
1914 total = 0
1915 for type, data in dagparser.parsedag(text):
1915 for type, data in dagparser.parsedag(text):
1916 if type == 'n':
1916 if type == 'n':
1917 total += 1
1917 total += 1
1918
1918
1919 if mergeable_file:
1919 if mergeable_file:
1920 linesperrev = 2
1920 linesperrev = 2
1921 # make a file with k lines per rev
1921 # make a file with k lines per rev
1922 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1922 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1923 initialmergedlines.append("")
1923 initialmergedlines.append("")
1924
1924
1925 tags = []
1925 tags = []
1926
1926
1927 lock = tr = None
1927 lock = tr = None
1928 try:
1928 try:
1929 lock = repo.lock()
1929 lock = repo.lock()
1930 tr = repo.transaction("builddag")
1930 tr = repo.transaction("builddag")
1931
1931
1932 at = -1
1932 at = -1
1933 atbranch = 'default'
1933 atbranch = 'default'
1934 nodeids = []
1934 nodeids = []
1935 id = 0
1935 id = 0
1936 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1936 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1937 for type, data in dagparser.parsedag(text):
1937 for type, data in dagparser.parsedag(text):
1938 if type == 'n':
1938 if type == 'n':
1939 ui.note(('node %s\n' % str(data)))
1939 ui.note(('node %s\n' % str(data)))
1940 id, ps = data
1940 id, ps = data
1941
1941
1942 files = []
1942 files = []
1943 fctxs = {}
1943 fctxs = {}
1944
1944
1945 p2 = None
1945 p2 = None
1946 if mergeable_file:
1946 if mergeable_file:
1947 fn = "mf"
1947 fn = "mf"
1948 p1 = repo[ps[0]]
1948 p1 = repo[ps[0]]
1949 if len(ps) > 1:
1949 if len(ps) > 1:
1950 p2 = repo[ps[1]]
1950 p2 = repo[ps[1]]
1951 pa = p1.ancestor(p2)
1951 pa = p1.ancestor(p2)
1952 base, local, other = [x[fn].data() for x in (pa, p1,
1952 base, local, other = [x[fn].data() for x in (pa, p1,
1953 p2)]
1953 p2)]
1954 m3 = simplemerge.Merge3Text(base, local, other)
1954 m3 = simplemerge.Merge3Text(base, local, other)
1955 ml = [l.strip() for l in m3.merge_lines()]
1955 ml = [l.strip() for l in m3.merge_lines()]
1956 ml.append("")
1956 ml.append("")
1957 elif at > 0:
1957 elif at > 0:
1958 ml = p1[fn].data().split("\n")
1958 ml = p1[fn].data().split("\n")
1959 else:
1959 else:
1960 ml = initialmergedlines
1960 ml = initialmergedlines
1961 ml[id * linesperrev] += " r%i" % id
1961 ml[id * linesperrev] += " r%i" % id
1962 mergedtext = "\n".join(ml)
1962 mergedtext = "\n".join(ml)
1963 files.append(fn)
1963 files.append(fn)
1964 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1964 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1965
1965
1966 if overwritten_file:
1966 if overwritten_file:
1967 fn = "of"
1967 fn = "of"
1968 files.append(fn)
1968 files.append(fn)
1969 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1969 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1970
1970
1971 if new_file:
1971 if new_file:
1972 fn = "nf%i" % id
1972 fn = "nf%i" % id
1973 files.append(fn)
1973 files.append(fn)
1974 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1974 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1975 if len(ps) > 1:
1975 if len(ps) > 1:
1976 if not p2:
1976 if not p2:
1977 p2 = repo[ps[1]]
1977 p2 = repo[ps[1]]
1978 for fn in p2:
1978 for fn in p2:
1979 if fn.startswith("nf"):
1979 if fn.startswith("nf"):
1980 files.append(fn)
1980 files.append(fn)
1981 fctxs[fn] = p2[fn]
1981 fctxs[fn] = p2[fn]
1982
1982
1983 def fctxfn(repo, cx, path):
1983 def fctxfn(repo, cx, path):
1984 return fctxs.get(path)
1984 return fctxs.get(path)
1985
1985
1986 if len(ps) == 0 or ps[0] < 0:
1986 if len(ps) == 0 or ps[0] < 0:
1987 pars = [None, None]
1987 pars = [None, None]
1988 elif len(ps) == 1:
1988 elif len(ps) == 1:
1989 pars = [nodeids[ps[0]], None]
1989 pars = [nodeids[ps[0]], None]
1990 else:
1990 else:
1991 pars = [nodeids[p] for p in ps]
1991 pars = [nodeids[p] for p in ps]
1992 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1992 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1993 date=(id, 0),
1993 date=(id, 0),
1994 user="debugbuilddag",
1994 user="debugbuilddag",
1995 extra={'branch': atbranch})
1995 extra={'branch': atbranch})
1996 nodeid = repo.commitctx(cx)
1996 nodeid = repo.commitctx(cx)
1997 nodeids.append(nodeid)
1997 nodeids.append(nodeid)
1998 at = id
1998 at = id
1999 elif type == 'l':
1999 elif type == 'l':
2000 id, name = data
2000 id, name = data
2001 ui.note(('tag %s\n' % name))
2001 ui.note(('tag %s\n' % name))
2002 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2002 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
2003 elif type == 'a':
2003 elif type == 'a':
2004 ui.note(('branch %s\n' % data))
2004 ui.note(('branch %s\n' % data))
2005 atbranch = data
2005 atbranch = data
2006 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2006 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2007 tr.close()
2007 tr.close()
2008
2008
2009 if tags:
2009 if tags:
2010 repo.vfs.write("localtags", "".join(tags))
2010 repo.vfs.write("localtags", "".join(tags))
2011 finally:
2011 finally:
2012 ui.progress(_('building'), None)
2012 ui.progress(_('building'), None)
2013 release(tr, lock)
2013 release(tr, lock)
2014
2014
2015 @command('debugbundle',
2015 @command('debugbundle',
2016 [('a', 'all', None, _('show all details'))],
2016 [('a', 'all', None, _('show all details'))],
2017 _('FILE'),
2017 _('FILE'),
2018 norepo=True)
2018 norepo=True)
2019 def debugbundle(ui, bundlepath, all=None, **opts):
2019 def debugbundle(ui, bundlepath, all=None, **opts):
2020 """lists the contents of a bundle"""
2020 """lists the contents of a bundle"""
2021 f = hg.openpath(ui, bundlepath)
2021 f = hg.openpath(ui, bundlepath)
2022 try:
2022 try:
2023 gen = exchange.readbundle(ui, f, bundlepath)
2023 gen = exchange.readbundle(ui, f, bundlepath)
2024 if isinstance(gen, bundle2.unbundle20):
2024 if isinstance(gen, bundle2.unbundle20):
2025 return _debugbundle2(ui, gen, all=all, **opts)
2025 return _debugbundle2(ui, gen, all=all, **opts)
2026 if all:
2026 if all:
2027 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2027 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2028
2028
2029 def showchunks(named):
2029 def showchunks(named):
2030 ui.write("\n%s\n" % named)
2030 ui.write("\n%s\n" % named)
2031 chain = None
2031 chain = None
2032 while True:
2032 while True:
2033 chunkdata = gen.deltachunk(chain)
2033 chunkdata = gen.deltachunk(chain)
2034 if not chunkdata:
2034 if not chunkdata:
2035 break
2035 break
2036 node = chunkdata['node']
2036 node = chunkdata['node']
2037 p1 = chunkdata['p1']
2037 p1 = chunkdata['p1']
2038 p2 = chunkdata['p2']
2038 p2 = chunkdata['p2']
2039 cs = chunkdata['cs']
2039 cs = chunkdata['cs']
2040 deltabase = chunkdata['deltabase']
2040 deltabase = chunkdata['deltabase']
2041 delta = chunkdata['delta']
2041 delta = chunkdata['delta']
2042 ui.write("%s %s %s %s %s %s\n" %
2042 ui.write("%s %s %s %s %s %s\n" %
2043 (hex(node), hex(p1), hex(p2),
2043 (hex(node), hex(p1), hex(p2),
2044 hex(cs), hex(deltabase), len(delta)))
2044 hex(cs), hex(deltabase), len(delta)))
2045 chain = node
2045 chain = node
2046
2046
2047 chunkdata = gen.changelogheader()
2047 chunkdata = gen.changelogheader()
2048 showchunks("changelog")
2048 showchunks("changelog")
2049 chunkdata = gen.manifestheader()
2049 chunkdata = gen.manifestheader()
2050 showchunks("manifest")
2050 showchunks("manifest")
2051 while True:
2051 while True:
2052 chunkdata = gen.filelogheader()
2052 chunkdata = gen.filelogheader()
2053 if not chunkdata:
2053 if not chunkdata:
2054 break
2054 break
2055 fname = chunkdata['filename']
2055 fname = chunkdata['filename']
2056 showchunks(fname)
2056 showchunks(fname)
2057 else:
2057 else:
2058 if isinstance(gen, bundle2.unbundle20):
2058 if isinstance(gen, bundle2.unbundle20):
2059 raise error.Abort(_('use debugbundle2 for this file'))
2059 raise error.Abort(_('use debugbundle2 for this file'))
2060 chunkdata = gen.changelogheader()
2060 chunkdata = gen.changelogheader()
2061 chain = None
2061 chain = None
2062 while True:
2062 while True:
2063 chunkdata = gen.deltachunk(chain)
2063 chunkdata = gen.deltachunk(chain)
2064 if not chunkdata:
2064 if not chunkdata:
2065 break
2065 break
2066 node = chunkdata['node']
2066 node = chunkdata['node']
2067 ui.write("%s\n" % hex(node))
2067 ui.write("%s\n" % hex(node))
2068 chain = node
2068 chain = node
2069 finally:
2069 finally:
2070 f.close()
2070 f.close()
2071
2071
2072 def _debugbundle2(ui, gen, **opts):
2072 def _debugbundle2(ui, gen, **opts):
2073 """lists the contents of a bundle2"""
2073 """lists the contents of a bundle2"""
2074 if not isinstance(gen, bundle2.unbundle20):
2074 if not isinstance(gen, bundle2.unbundle20):
2075 raise error.Abort(_('not a bundle2 file'))
2075 raise error.Abort(_('not a bundle2 file'))
2076 ui.write(('Stream params: %s\n' % repr(gen.params)))
2076 ui.write(('Stream params: %s\n' % repr(gen.params)))
2077 for part in gen.iterparts():
2077 for part in gen.iterparts():
2078 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2078 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2079 if part.type == 'changegroup':
2079 if part.type == 'changegroup':
2080 version = part.params.get('version', '01')
2080 version = part.params.get('version', '01')
2081 cg = changegroup.packermap[version][1](part, 'UN')
2081 cg = changegroup.packermap[version][1](part, 'UN')
2082 chunkdata = cg.changelogheader()
2082 chunkdata = cg.changelogheader()
2083 chain = None
2083 chain = None
2084 while True:
2084 while True:
2085 chunkdata = cg.deltachunk(chain)
2085 chunkdata = cg.deltachunk(chain)
2086 if not chunkdata:
2086 if not chunkdata:
2087 break
2087 break
2088 node = chunkdata['node']
2088 node = chunkdata['node']
2089 ui.write(" %s\n" % hex(node))
2089 ui.write(" %s\n" % hex(node))
2090 chain = node
2090 chain = node
2091
2091
2092 @command('debugcreatestreamclonebundle', [], 'FILE')
2092 @command('debugcreatestreamclonebundle', [], 'FILE')
2093 def debugcreatestreamclonebundle(ui, repo, fname):
2093 def debugcreatestreamclonebundle(ui, repo, fname):
2094 """create a stream clone bundle file
2094 """create a stream clone bundle file
2095
2095
2096 Stream bundles are special bundles that are essentially archives of
2096 Stream bundles are special bundles that are essentially archives of
2097 revlog files. They are commonly used for cloning very quickly.
2097 revlog files. They are commonly used for cloning very quickly.
2098 """
2098 """
2099 requirements, gen = streamclone.generatebundlev1(repo)
2099 requirements, gen = streamclone.generatebundlev1(repo)
2100 changegroup.writechunks(ui, gen, fname)
2100 changegroup.writechunks(ui, gen, fname)
2101
2101
2102 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2102 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2103
2103
2104 @command('debugapplystreamclonebundle', [], 'FILE')
2104 @command('debugapplystreamclonebundle', [], 'FILE')
2105 def debugapplystreamclonebundle(ui, repo, fname):
2105 def debugapplystreamclonebundle(ui, repo, fname):
2106 """apply a stream clone bundle file"""
2106 """apply a stream clone bundle file"""
2107 f = hg.openpath(ui, fname)
2107 f = hg.openpath(ui, fname)
2108 gen = exchange.readbundle(ui, f, fname)
2108 gen = exchange.readbundle(ui, f, fname)
2109 gen.apply(repo)
2109 gen.apply(repo)
2110
2110
2111 @command('debugcheckstate', [], '')
2111 @command('debugcheckstate', [], '')
2112 def debugcheckstate(ui, repo):
2112 def debugcheckstate(ui, repo):
2113 """validate the correctness of the current dirstate"""
2113 """validate the correctness of the current dirstate"""
2114 parent1, parent2 = repo.dirstate.parents()
2114 parent1, parent2 = repo.dirstate.parents()
2115 m1 = repo[parent1].manifest()
2115 m1 = repo[parent1].manifest()
2116 m2 = repo[parent2].manifest()
2116 m2 = repo[parent2].manifest()
2117 errors = 0
2117 errors = 0
2118 for f in repo.dirstate:
2118 for f in repo.dirstate:
2119 state = repo.dirstate[f]
2119 state = repo.dirstate[f]
2120 if state in "nr" and f not in m1:
2120 if state in "nr" and f not in m1:
2121 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2121 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2122 errors += 1
2122 errors += 1
2123 if state in "a" and f in m1:
2123 if state in "a" and f in m1:
2124 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2124 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2125 errors += 1
2125 errors += 1
2126 if state in "m" and f not in m1 and f not in m2:
2126 if state in "m" and f not in m1 and f not in m2:
2127 ui.warn(_("%s in state %s, but not in either manifest\n") %
2127 ui.warn(_("%s in state %s, but not in either manifest\n") %
2128 (f, state))
2128 (f, state))
2129 errors += 1
2129 errors += 1
2130 for f in m1:
2130 for f in m1:
2131 state = repo.dirstate[f]
2131 state = repo.dirstate[f]
2132 if state not in "nrm":
2132 if state not in "nrm":
2133 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2133 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2134 errors += 1
2134 errors += 1
2135 if errors:
2135 if errors:
2136 error = _(".hg/dirstate inconsistent with current parent's manifest")
2136 error = _(".hg/dirstate inconsistent with current parent's manifest")
2137 raise error.Abort(error)
2137 raise error.Abort(error)
2138
2138
2139 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2139 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2140 def debugcommands(ui, cmd='', *args):
2140 def debugcommands(ui, cmd='', *args):
2141 """list all available commands and options"""
2141 """list all available commands and options"""
2142 for cmd, vals in sorted(table.iteritems()):
2142 for cmd, vals in sorted(table.iteritems()):
2143 cmd = cmd.split('|')[0].strip('^')
2143 cmd = cmd.split('|')[0].strip('^')
2144 opts = ', '.join([i[1] for i in vals[1]])
2144 opts = ', '.join([i[1] for i in vals[1]])
2145 ui.write('%s: %s\n' % (cmd, opts))
2145 ui.write('%s: %s\n' % (cmd, opts))
2146
2146
2147 @command('debugcomplete',
2147 @command('debugcomplete',
2148 [('o', 'options', None, _('show the command options'))],
2148 [('o', 'options', None, _('show the command options'))],
2149 _('[-o] CMD'),
2149 _('[-o] CMD'),
2150 norepo=True)
2150 norepo=True)
2151 def debugcomplete(ui, cmd='', **opts):
2151 def debugcomplete(ui, cmd='', **opts):
2152 """returns the completion list associated with the given command"""
2152 """returns the completion list associated with the given command"""
2153
2153
2154 if opts.get('options'):
2154 if opts.get('options'):
2155 options = []
2155 options = []
2156 otables = [globalopts]
2156 otables = [globalopts]
2157 if cmd:
2157 if cmd:
2158 aliases, entry = cmdutil.findcmd(cmd, table, False)
2158 aliases, entry = cmdutil.findcmd(cmd, table, False)
2159 otables.append(entry[1])
2159 otables.append(entry[1])
2160 for t in otables:
2160 for t in otables:
2161 for o in t:
2161 for o in t:
2162 if "(DEPRECATED)" in o[3]:
2162 if "(DEPRECATED)" in o[3]:
2163 continue
2163 continue
2164 if o[0]:
2164 if o[0]:
2165 options.append('-%s' % o[0])
2165 options.append('-%s' % o[0])
2166 options.append('--%s' % o[1])
2166 options.append('--%s' % o[1])
2167 ui.write("%s\n" % "\n".join(options))
2167 ui.write("%s\n" % "\n".join(options))
2168 return
2168 return
2169
2169
2170 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2170 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2171 if ui.verbose:
2171 if ui.verbose:
2172 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2172 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2173 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2173 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2174
2174
2175 @command('debugdag',
2175 @command('debugdag',
2176 [('t', 'tags', None, _('use tags as labels')),
2176 [('t', 'tags', None, _('use tags as labels')),
2177 ('b', 'branches', None, _('annotate with branch names')),
2177 ('b', 'branches', None, _('annotate with branch names')),
2178 ('', 'dots', None, _('use dots for runs')),
2178 ('', 'dots', None, _('use dots for runs')),
2179 ('s', 'spaces', None, _('separate elements by spaces'))],
2179 ('s', 'spaces', None, _('separate elements by spaces'))],
2180 _('[OPTION]... [FILE [REV]...]'),
2180 _('[OPTION]... [FILE [REV]...]'),
2181 optionalrepo=True)
2181 optionalrepo=True)
2182 def debugdag(ui, repo, file_=None, *revs, **opts):
2182 def debugdag(ui, repo, file_=None, *revs, **opts):
2183 """format the changelog or an index DAG as a concise textual description
2183 """format the changelog or an index DAG as a concise textual description
2184
2184
2185 If you pass a revlog index, the revlog's DAG is emitted. If you list
2185 If you pass a revlog index, the revlog's DAG is emitted. If you list
2186 revision numbers, they get labeled in the output as rN.
2186 revision numbers, they get labeled in the output as rN.
2187
2187
2188 Otherwise, the changelog DAG of the current repo is emitted.
2188 Otherwise, the changelog DAG of the current repo is emitted.
2189 """
2189 """
2190 spaces = opts.get('spaces')
2190 spaces = opts.get('spaces')
2191 dots = opts.get('dots')
2191 dots = opts.get('dots')
2192 if file_:
2192 if file_:
2193 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2193 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2194 revs = set((int(r) for r in revs))
2194 revs = set((int(r) for r in revs))
2195 def events():
2195 def events():
2196 for r in rlog:
2196 for r in rlog:
2197 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2197 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2198 if p != -1))
2198 if p != -1))
2199 if r in revs:
2199 if r in revs:
2200 yield 'l', (r, "r%i" % r)
2200 yield 'l', (r, "r%i" % r)
2201 elif repo:
2201 elif repo:
2202 cl = repo.changelog
2202 cl = repo.changelog
2203 tags = opts.get('tags')
2203 tags = opts.get('tags')
2204 branches = opts.get('branches')
2204 branches = opts.get('branches')
2205 if tags:
2205 if tags:
2206 labels = {}
2206 labels = {}
2207 for l, n in repo.tags().items():
2207 for l, n in repo.tags().items():
2208 labels.setdefault(cl.rev(n), []).append(l)
2208 labels.setdefault(cl.rev(n), []).append(l)
2209 def events():
2209 def events():
2210 b = "default"
2210 b = "default"
2211 for r in cl:
2211 for r in cl:
2212 if branches:
2212 if branches:
2213 newb = cl.read(cl.node(r))[5]['branch']
2213 newb = cl.read(cl.node(r))[5]['branch']
2214 if newb != b:
2214 if newb != b:
2215 yield 'a', newb
2215 yield 'a', newb
2216 b = newb
2216 b = newb
2217 yield 'n', (r, list(p for p in cl.parentrevs(r)
2217 yield 'n', (r, list(p for p in cl.parentrevs(r)
2218 if p != -1))
2218 if p != -1))
2219 if tags:
2219 if tags:
2220 ls = labels.get(r)
2220 ls = labels.get(r)
2221 if ls:
2221 if ls:
2222 for l in ls:
2222 for l in ls:
2223 yield 'l', (r, l)
2223 yield 'l', (r, l)
2224 else:
2224 else:
2225 raise error.Abort(_('need repo for changelog dag'))
2225 raise error.Abort(_('need repo for changelog dag'))
2226
2226
2227 for line in dagparser.dagtextlines(events(),
2227 for line in dagparser.dagtextlines(events(),
2228 addspaces=spaces,
2228 addspaces=spaces,
2229 wraplabels=True,
2229 wraplabels=True,
2230 wrapannotations=True,
2230 wrapannotations=True,
2231 wrapnonlinear=dots,
2231 wrapnonlinear=dots,
2232 usedots=dots,
2232 usedots=dots,
2233 maxlinewidth=70):
2233 maxlinewidth=70):
2234 ui.write(line)
2234 ui.write(line)
2235 ui.write("\n")
2235 ui.write("\n")
2236
2236
2237 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2237 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2238 def debugdata(ui, repo, file_, rev=None, **opts):
2238 def debugdata(ui, repo, file_, rev=None, **opts):
2239 """dump the contents of a data file revision"""
2239 """dump the contents of a data file revision"""
2240 if opts.get('changelog') or opts.get('manifest'):
2240 if opts.get('changelog') or opts.get('manifest'):
2241 file_, rev = None, file_
2241 file_, rev = None, file_
2242 elif rev is None:
2242 elif rev is None:
2243 raise error.CommandError('debugdata', _('invalid arguments'))
2243 raise error.CommandError('debugdata', _('invalid arguments'))
2244 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2244 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2245 try:
2245 try:
2246 ui.write(r.revision(r.lookup(rev)))
2246 ui.write(r.revision(r.lookup(rev)))
2247 except KeyError:
2247 except KeyError:
2248 raise error.Abort(_('invalid revision identifier %s') % rev)
2248 raise error.Abort(_('invalid revision identifier %s') % rev)
2249
2249
2250 @command('debugdate',
2250 @command('debugdate',
2251 [('e', 'extended', None, _('try extended date formats'))],
2251 [('e', 'extended', None, _('try extended date formats'))],
2252 _('[-e] DATE [RANGE]'),
2252 _('[-e] DATE [RANGE]'),
2253 norepo=True, optionalrepo=True)
2253 norepo=True, optionalrepo=True)
2254 def debugdate(ui, date, range=None, **opts):
2254 def debugdate(ui, date, range=None, **opts):
2255 """parse and display a date"""
2255 """parse and display a date"""
2256 if opts["extended"]:
2256 if opts["extended"]:
2257 d = util.parsedate(date, util.extendeddateformats)
2257 d = util.parsedate(date, util.extendeddateformats)
2258 else:
2258 else:
2259 d = util.parsedate(date)
2259 d = util.parsedate(date)
2260 ui.write(("internal: %s %s\n") % d)
2260 ui.write(("internal: %s %s\n") % d)
2261 ui.write(("standard: %s\n") % util.datestr(d))
2261 ui.write(("standard: %s\n") % util.datestr(d))
2262 if range:
2262 if range:
2263 m = util.matchdate(range)
2263 m = util.matchdate(range)
2264 ui.write(("match: %s\n") % m(d[0]))
2264 ui.write(("match: %s\n") % m(d[0]))
2265
2265
2266 @command('debugdiscovery',
2266 @command('debugdiscovery',
2267 [('', 'old', None, _('use old-style discovery')),
2267 [('', 'old', None, _('use old-style discovery')),
2268 ('', 'nonheads', None,
2268 ('', 'nonheads', None,
2269 _('use old-style discovery with non-heads included')),
2269 _('use old-style discovery with non-heads included')),
2270 ] + remoteopts,
2270 ] + remoteopts,
2271 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2271 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2272 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2272 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2273 """runs the changeset discovery protocol in isolation"""
2273 """runs the changeset discovery protocol in isolation"""
2274 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2274 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2275 opts.get('branch'))
2275 opts.get('branch'))
2276 remote = hg.peer(repo, opts, remoteurl)
2276 remote = hg.peer(repo, opts, remoteurl)
2277 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2277 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2278
2278
2279 # make sure tests are repeatable
2279 # make sure tests are repeatable
2280 random.seed(12323)
2280 random.seed(12323)
2281
2281
2282 def doit(localheads, remoteheads, remote=remote):
2282 def doit(localheads, remoteheads, remote=remote):
2283 if opts.get('old'):
2283 if opts.get('old'):
2284 if localheads:
2284 if localheads:
2285 raise error.Abort('cannot use localheads with old style '
2285 raise error.Abort('cannot use localheads with old style '
2286 'discovery')
2286 'discovery')
2287 if not util.safehasattr(remote, 'branches'):
2287 if not util.safehasattr(remote, 'branches'):
2288 # enable in-client legacy support
2288 # enable in-client legacy support
2289 remote = localrepo.locallegacypeer(remote.local())
2289 remote = localrepo.locallegacypeer(remote.local())
2290 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2290 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2291 force=True)
2291 force=True)
2292 common = set(common)
2292 common = set(common)
2293 if not opts.get('nonheads'):
2293 if not opts.get('nonheads'):
2294 ui.write(("unpruned common: %s\n") %
2294 ui.write(("unpruned common: %s\n") %
2295 " ".join(sorted(short(n) for n in common)))
2295 " ".join(sorted(short(n) for n in common)))
2296 dag = dagutil.revlogdag(repo.changelog)
2296 dag = dagutil.revlogdag(repo.changelog)
2297 all = dag.ancestorset(dag.internalizeall(common))
2297 all = dag.ancestorset(dag.internalizeall(common))
2298 common = dag.externalizeall(dag.headsetofconnecteds(all))
2298 common = dag.externalizeall(dag.headsetofconnecteds(all))
2299 else:
2299 else:
2300 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2300 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2301 common = set(common)
2301 common = set(common)
2302 rheads = set(hds)
2302 rheads = set(hds)
2303 lheads = set(repo.heads())
2303 lheads = set(repo.heads())
2304 ui.write(("common heads: %s\n") %
2304 ui.write(("common heads: %s\n") %
2305 " ".join(sorted(short(n) for n in common)))
2305 " ".join(sorted(short(n) for n in common)))
2306 if lheads <= common:
2306 if lheads <= common:
2307 ui.write(("local is subset\n"))
2307 ui.write(("local is subset\n"))
2308 elif rheads <= common:
2308 elif rheads <= common:
2309 ui.write(("remote is subset\n"))
2309 ui.write(("remote is subset\n"))
2310
2310
2311 serverlogs = opts.get('serverlog')
2311 serverlogs = opts.get('serverlog')
2312 if serverlogs:
2312 if serverlogs:
2313 for filename in serverlogs:
2313 for filename in serverlogs:
2314 logfile = open(filename, 'r')
2314 logfile = open(filename, 'r')
2315 try:
2315 try:
2316 line = logfile.readline()
2316 line = logfile.readline()
2317 while line:
2317 while line:
2318 parts = line.strip().split(';')
2318 parts = line.strip().split(';')
2319 op = parts[1]
2319 op = parts[1]
2320 if op == 'cg':
2320 if op == 'cg':
2321 pass
2321 pass
2322 elif op == 'cgss':
2322 elif op == 'cgss':
2323 doit(parts[2].split(' '), parts[3].split(' '))
2323 doit(parts[2].split(' '), parts[3].split(' '))
2324 elif op == 'unb':
2324 elif op == 'unb':
2325 doit(parts[3].split(' '), parts[2].split(' '))
2325 doit(parts[3].split(' '), parts[2].split(' '))
2326 line = logfile.readline()
2326 line = logfile.readline()
2327 finally:
2327 finally:
2328 logfile.close()
2328 logfile.close()
2329
2329
2330 else:
2330 else:
2331 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2331 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2332 opts.get('remote_head'))
2332 opts.get('remote_head'))
2333 localrevs = opts.get('local_head')
2333 localrevs = opts.get('local_head')
2334 doit(localrevs, remoterevs)
2334 doit(localrevs, remoterevs)
2335
2335
2336 @command('debugextensions', formatteropts, [], norepo=True)
2336 @command('debugextensions', formatteropts, [], norepo=True)
2337 def debugextensions(ui, **opts):
2337 def debugextensions(ui, **opts):
2338 '''show information about active extensions'''
2338 '''show information about active extensions'''
2339 exts = extensions.extensions(ui)
2339 exts = extensions.extensions(ui)
2340 fm = ui.formatter('debugextensions', opts)
2340 fm = ui.formatter('debugextensions', opts)
2341 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2341 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2342 extsource = extmod.__file__
2342 extsource = extmod.__file__
2343 exttestedwith = getattr(extmod, 'testedwith', None)
2343 exttestedwith = getattr(extmod, 'testedwith', None)
2344 if exttestedwith is not None:
2344 if exttestedwith is not None:
2345 exttestedwith = exttestedwith.split()
2345 exttestedwith = exttestedwith.split()
2346 extbuglink = getattr(extmod, 'buglink', None)
2346 extbuglink = getattr(extmod, 'buglink', None)
2347
2347
2348 fm.startitem()
2348 fm.startitem()
2349
2349
2350 if ui.quiet or ui.verbose:
2350 if ui.quiet or ui.verbose:
2351 fm.write('name', '%s\n', extname)
2351 fm.write('name', '%s\n', extname)
2352 else:
2352 else:
2353 fm.write('name', '%s', extname)
2353 fm.write('name', '%s', extname)
2354 if not exttestedwith:
2354 if not exttestedwith:
2355 fm.plain(_(' (untested!)\n'))
2355 fm.plain(_(' (untested!)\n'))
2356 else:
2356 else:
2357 if exttestedwith == ['internal'] or \
2357 if exttestedwith == ['internal'] or \
2358 util.version() in exttestedwith:
2358 util.version() in exttestedwith:
2359 fm.plain('\n')
2359 fm.plain('\n')
2360 else:
2360 else:
2361 lasttestedversion = exttestedwith[-1]
2361 lasttestedversion = exttestedwith[-1]
2362 fm.plain(' (%s!)\n' % lasttestedversion)
2362 fm.plain(' (%s!)\n' % lasttestedversion)
2363
2363
2364 fm.condwrite(ui.verbose and extsource, 'source',
2364 fm.condwrite(ui.verbose and extsource, 'source',
2365 _(' location: %s\n'), extsource or "")
2365 _(' location: %s\n'), extsource or "")
2366
2366
2367 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2367 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2368 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2368 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2369
2369
2370 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2370 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2371 _(' bug reporting: %s\n'), extbuglink or "")
2371 _(' bug reporting: %s\n'), extbuglink or "")
2372
2372
2373 fm.end()
2373 fm.end()
2374
2374
2375 @command('debugfileset',
2375 @command('debugfileset',
2376 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2376 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2377 _('[-r REV] FILESPEC'))
2377 _('[-r REV] FILESPEC'))
2378 def debugfileset(ui, repo, expr, **opts):
2378 def debugfileset(ui, repo, expr, **opts):
2379 '''parse and apply a fileset specification'''
2379 '''parse and apply a fileset specification'''
2380 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2380 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2381 if ui.verbose:
2381 if ui.verbose:
2382 tree = fileset.parse(expr)
2382 tree = fileset.parse(expr)
2383 ui.note(fileset.prettyformat(tree), "\n")
2383 ui.note(fileset.prettyformat(tree), "\n")
2384
2384
2385 for f in ctx.getfileset(expr):
2385 for f in ctx.getfileset(expr):
2386 ui.write("%s\n" % f)
2386 ui.write("%s\n" % f)
2387
2387
2388 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2388 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2389 def debugfsinfo(ui, path="."):
2389 def debugfsinfo(ui, path="."):
2390 """show information detected about current filesystem"""
2390 """show information detected about current filesystem"""
2391 util.writefile('.debugfsinfo', '')
2391 util.writefile('.debugfsinfo', '')
2392 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2392 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2393 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2393 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2394 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2394 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2395 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2395 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2396 and 'yes' or 'no'))
2396 and 'yes' or 'no'))
2397 os.unlink('.debugfsinfo')
2397 os.unlink('.debugfsinfo')
2398
2398
2399 @command('debuggetbundle',
2399 @command('debuggetbundle',
2400 [('H', 'head', [], _('id of head node'), _('ID')),
2400 [('H', 'head', [], _('id of head node'), _('ID')),
2401 ('C', 'common', [], _('id of common node'), _('ID')),
2401 ('C', 'common', [], _('id of common node'), _('ID')),
2402 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2402 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2403 _('REPO FILE [-H|-C ID]...'),
2403 _('REPO FILE [-H|-C ID]...'),
2404 norepo=True)
2404 norepo=True)
2405 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2405 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2406 """retrieves a bundle from a repo
2406 """retrieves a bundle from a repo
2407
2407
2408 Every ID must be a full-length hex node id string. Saves the bundle to the
2408 Every ID must be a full-length hex node id string. Saves the bundle to the
2409 given file.
2409 given file.
2410 """
2410 """
2411 repo = hg.peer(ui, opts, repopath)
2411 repo = hg.peer(ui, opts, repopath)
2412 if not repo.capable('getbundle'):
2412 if not repo.capable('getbundle'):
2413 raise error.Abort("getbundle() not supported by target repository")
2413 raise error.Abort("getbundle() not supported by target repository")
2414 args = {}
2414 args = {}
2415 if common:
2415 if common:
2416 args['common'] = [bin(s) for s in common]
2416 args['common'] = [bin(s) for s in common]
2417 if head:
2417 if head:
2418 args['heads'] = [bin(s) for s in head]
2418 args['heads'] = [bin(s) for s in head]
2419 # TODO: get desired bundlecaps from command line.
2419 # TODO: get desired bundlecaps from command line.
2420 args['bundlecaps'] = None
2420 args['bundlecaps'] = None
2421 bundle = repo.getbundle('debug', **args)
2421 bundle = repo.getbundle('debug', **args)
2422
2422
2423 bundletype = opts.get('type', 'bzip2').lower()
2423 bundletype = opts.get('type', 'bzip2').lower()
2424 btypes = {'none': 'HG10UN',
2424 btypes = {'none': 'HG10UN',
2425 'bzip2': 'HG10BZ',
2425 'bzip2': 'HG10BZ',
2426 'gzip': 'HG10GZ',
2426 'gzip': 'HG10GZ',
2427 'bundle2': 'HG20'}
2427 'bundle2': 'HG20'}
2428 bundletype = btypes.get(bundletype)
2428 bundletype = btypes.get(bundletype)
2429 if bundletype not in changegroup.bundletypes:
2429 if bundletype not in changegroup.bundletypes:
2430 raise error.Abort(_('unknown bundle type specified with --type'))
2430 raise error.Abort(_('unknown bundle type specified with --type'))
2431 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2431 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2432
2432
2433 @command('debugignore', [], '[FILE]')
2433 @command('debugignore', [], '[FILE]')
2434 def debugignore(ui, repo, *files, **opts):
2434 def debugignore(ui, repo, *files, **opts):
2435 """display the combined ignore pattern and information about ignored files
2435 """display the combined ignore pattern and information about ignored files
2436
2436
2437 With no argument display the combined ignore pattern.
2437 With no argument display the combined ignore pattern.
2438
2438
2439 Given space separated file names, shows if the given file is ignored and
2439 Given space separated file names, shows if the given file is ignored and
2440 if so, show the ignore rule (file and line number) that matched it.
2440 if so, show the ignore rule (file and line number) that matched it.
2441 """
2441 """
2442 ignore = repo.dirstate._ignore
2442 ignore = repo.dirstate._ignore
2443 if not files:
2443 if not files:
2444 # Show all the patterns
2444 # Show all the patterns
2445 includepat = getattr(ignore, 'includepat', None)
2445 includepat = getattr(ignore, 'includepat', None)
2446 if includepat is not None:
2446 if includepat is not None:
2447 ui.write("%s\n" % includepat)
2447 ui.write("%s\n" % includepat)
2448 else:
2448 else:
2449 raise error.Abort(_("no ignore patterns found"))
2449 raise error.Abort(_("no ignore patterns found"))
2450 else:
2450 else:
2451 for f in files:
2451 for f in files:
2452 ignored = None
2452 ignored = None
2453 ignoredata = None
2453 ignoredata = None
2454 if f != '.':
2454 if f != '.':
2455 if ignore(f):
2455 if ignore(f):
2456 ignored = f
2456 ignored = f
2457 ignoredata = repo.dirstate._ignorefileandline(f)
2457 ignoredata = repo.dirstate._ignorefileandline(f)
2458 else:
2458 else:
2459 for p in util.finddirs(f):
2459 for p in util.finddirs(f):
2460 if ignore(p):
2460 if ignore(p):
2461 ignored = p
2461 ignored = p
2462 ignoredata = repo.dirstate._ignorefileandline(p)
2462 ignoredata = repo.dirstate._ignorefileandline(p)
2463 break
2463 break
2464 if ignored:
2464 if ignored:
2465 if ignored == f:
2465 if ignored == f:
2466 ui.write("%s is ignored\n" % f)
2466 ui.write("%s is ignored\n" % f)
2467 else:
2467 else:
2468 ui.write("%s is ignored because of containing folder %s\n"
2468 ui.write("%s is ignored because of containing folder %s\n"
2469 % (f, ignored))
2469 % (f, ignored))
2470 ignorefile, lineno, line = ignoredata
2470 ignorefile, lineno, line = ignoredata
2471 ui.write("(ignore rule in %s, line %d: '%s')\n"
2471 ui.write("(ignore rule in %s, line %d: '%s')\n"
2472 % (ignorefile, lineno, line))
2472 % (ignorefile, lineno, line))
2473 else:
2473 else:
2474 ui.write("%s is not ignored\n" % f)
2474 ui.write("%s is not ignored\n" % f)
2475
2475
2476 @command('debugindex', debugrevlogopts +
2476 @command('debugindex', debugrevlogopts +
2477 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2477 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2478 _('[-f FORMAT] -c|-m|FILE'),
2478 _('[-f FORMAT] -c|-m|FILE'),
2479 optionalrepo=True)
2479 optionalrepo=True)
2480 def debugindex(ui, repo, file_=None, **opts):
2480 def debugindex(ui, repo, file_=None, **opts):
2481 """dump the contents of an index file"""
2481 """dump the contents of an index file"""
2482 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2482 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2483 format = opts.get('format', 0)
2483 format = opts.get('format', 0)
2484 if format not in (0, 1):
2484 if format not in (0, 1):
2485 raise error.Abort(_("unknown format %d") % format)
2485 raise error.Abort(_("unknown format %d") % format)
2486
2486
2487 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2487 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2488 if generaldelta:
2488 if generaldelta:
2489 basehdr = ' delta'
2489 basehdr = ' delta'
2490 else:
2490 else:
2491 basehdr = ' base'
2491 basehdr = ' base'
2492
2492
2493 if ui.debugflag:
2493 if ui.debugflag:
2494 shortfn = hex
2494 shortfn = hex
2495 else:
2495 else:
2496 shortfn = short
2496 shortfn = short
2497
2497
2498 # There might not be anything in r, so have a sane default
2498 # There might not be anything in r, so have a sane default
2499 idlen = 12
2499 idlen = 12
2500 for i in r:
2500 for i in r:
2501 idlen = len(shortfn(r.node(i)))
2501 idlen = len(shortfn(r.node(i)))
2502 break
2502 break
2503
2503
2504 if format == 0:
2504 if format == 0:
2505 ui.write(" rev offset length " + basehdr + " linkrev"
2505 ui.write(" rev offset length " + basehdr + " linkrev"
2506 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2506 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2507 elif format == 1:
2507 elif format == 1:
2508 ui.write(" rev flag offset length"
2508 ui.write(" rev flag offset length"
2509 " size " + basehdr + " link p1 p2"
2509 " size " + basehdr + " link p1 p2"
2510 " %s\n" % "nodeid".rjust(idlen))
2510 " %s\n" % "nodeid".rjust(idlen))
2511
2511
2512 for i in r:
2512 for i in r:
2513 node = r.node(i)
2513 node = r.node(i)
2514 if generaldelta:
2514 if generaldelta:
2515 base = r.deltaparent(i)
2515 base = r.deltaparent(i)
2516 else:
2516 else:
2517 base = r.chainbase(i)
2517 base = r.chainbase(i)
2518 if format == 0:
2518 if format == 0:
2519 try:
2519 try:
2520 pp = r.parents(node)
2520 pp = r.parents(node)
2521 except Exception:
2521 except Exception:
2522 pp = [nullid, nullid]
2522 pp = [nullid, nullid]
2523 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2523 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2524 i, r.start(i), r.length(i), base, r.linkrev(i),
2524 i, r.start(i), r.length(i), base, r.linkrev(i),
2525 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2525 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2526 elif format == 1:
2526 elif format == 1:
2527 pr = r.parentrevs(i)
2527 pr = r.parentrevs(i)
2528 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2528 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2529 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2529 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2530 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2530 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2531
2531
2532 @command('debugindexdot', debugrevlogopts,
2532 @command('debugindexdot', debugrevlogopts,
2533 _('-c|-m|FILE'), optionalrepo=True)
2533 _('-c|-m|FILE'), optionalrepo=True)
2534 def debugindexdot(ui, repo, file_=None, **opts):
2534 def debugindexdot(ui, repo, file_=None, **opts):
2535 """dump an index DAG as a graphviz dot file"""
2535 """dump an index DAG as a graphviz dot file"""
2536 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2536 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2537 ui.write(("digraph G {\n"))
2537 ui.write(("digraph G {\n"))
2538 for i in r:
2538 for i in r:
2539 node = r.node(i)
2539 node = r.node(i)
2540 pp = r.parents(node)
2540 pp = r.parents(node)
2541 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2541 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2542 if pp[1] != nullid:
2542 if pp[1] != nullid:
2543 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2543 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2544 ui.write("}\n")
2544 ui.write("}\n")
2545
2545
2546 @command('debugdeltachain',
2546 @command('debugdeltachain',
2547 debugrevlogopts + formatteropts,
2547 debugrevlogopts + formatteropts,
2548 _('-c|-m|FILE'),
2548 _('-c|-m|FILE'),
2549 optionalrepo=True)
2549 optionalrepo=True)
2550 def debugdeltachain(ui, repo, file_=None, **opts):
2550 def debugdeltachain(ui, repo, file_=None, **opts):
2551 """dump information about delta chains in a revlog
2551 """dump information about delta chains in a revlog
2552
2552
2553 Output can be templatized. Available template keywords are:
2553 Output can be templatized. Available template keywords are:
2554
2554
2555 rev revision number
2555 rev revision number
2556 chainid delta chain identifier (numbered by unique base)
2556 chainid delta chain identifier (numbered by unique base)
2557 chainlen delta chain length to this revision
2557 chainlen delta chain length to this revision
2558 prevrev previous revision in delta chain
2558 prevrev previous revision in delta chain
2559 deltatype role of delta / how it was computed
2559 deltatype role of delta / how it was computed
2560 compsize compressed size of revision
2560 compsize compressed size of revision
2561 uncompsize uncompressed size of revision
2561 uncompsize uncompressed size of revision
2562 chainsize total size of compressed revisions in chain
2562 chainsize total size of compressed revisions in chain
2563 chainratio total chain size divided by uncompressed revision size
2563 chainratio total chain size divided by uncompressed revision size
2564 (new delta chains typically start at ratio 2.00)
2564 (new delta chains typically start at ratio 2.00)
2565 lindist linear distance from base revision in delta chain to end
2565 lindist linear distance from base revision in delta chain to end
2566 of this revision
2566 of this revision
2567 extradist total size of revisions not part of this delta chain from
2567 extradist total size of revisions not part of this delta chain from
2568 base of delta chain to end of this revision; a measurement
2568 base of delta chain to end of this revision; a measurement
2569 of how much extra data we need to read/seek across to read
2569 of how much extra data we need to read/seek across to read
2570 the delta chain for this revision
2570 the delta chain for this revision
2571 extraratio extradist divided by chainsize; another representation of
2571 extraratio extradist divided by chainsize; another representation of
2572 how much unrelated data is needed to load this delta chain
2572 how much unrelated data is needed to load this delta chain
2573 """
2573 """
2574 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2574 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2575 index = r.index
2575 index = r.index
2576 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2576 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2577
2577
2578 def revinfo(rev):
2578 def revinfo(rev):
2579 e = index[rev]
2579 e = index[rev]
2580 compsize = e[1]
2580 compsize = e[1]
2581 uncompsize = e[2]
2581 uncompsize = e[2]
2582 chainsize = 0
2582 chainsize = 0
2583
2583
2584 if generaldelta:
2584 if generaldelta:
2585 if e[3] == e[5]:
2585 if e[3] == e[5]:
2586 deltatype = 'p1'
2586 deltatype = 'p1'
2587 elif e[3] == e[6]:
2587 elif e[3] == e[6]:
2588 deltatype = 'p2'
2588 deltatype = 'p2'
2589 elif e[3] == rev - 1:
2589 elif e[3] == rev - 1:
2590 deltatype = 'prev'
2590 deltatype = 'prev'
2591 elif e[3] == rev:
2591 elif e[3] == rev:
2592 deltatype = 'base'
2592 deltatype = 'base'
2593 else:
2593 else:
2594 deltatype = 'other'
2594 deltatype = 'other'
2595 else:
2595 else:
2596 if e[3] == rev:
2596 if e[3] == rev:
2597 deltatype = 'base'
2597 deltatype = 'base'
2598 else:
2598 else:
2599 deltatype = 'prev'
2599 deltatype = 'prev'
2600
2600
2601 chain = r._deltachain(rev)[0]
2601 chain = r._deltachain(rev)[0]
2602 for iterrev in chain:
2602 for iterrev in chain:
2603 e = index[iterrev]
2603 e = index[iterrev]
2604 chainsize += e[1]
2604 chainsize += e[1]
2605
2605
2606 return compsize, uncompsize, deltatype, chain, chainsize
2606 return compsize, uncompsize, deltatype, chain, chainsize
2607
2607
2608 fm = ui.formatter('debugdeltachain', opts)
2608 fm = ui.formatter('debugdeltachain', opts)
2609
2609
2610 fm.plain(' rev chain# chainlen prev delta '
2610 fm.plain(' rev chain# chainlen prev delta '
2611 'size rawsize chainsize ratio lindist extradist '
2611 'size rawsize chainsize ratio lindist extradist '
2612 'extraratio\n')
2612 'extraratio\n')
2613
2613
2614 chainbases = {}
2614 chainbases = {}
2615 for rev in r:
2615 for rev in r:
2616 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2616 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2617 chainbase = chain[0]
2617 chainbase = chain[0]
2618 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2618 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2619 basestart = r.start(chainbase)
2619 basestart = r.start(chainbase)
2620 revstart = r.start(rev)
2620 revstart = r.start(rev)
2621 lineardist = revstart + comp - basestart
2621 lineardist = revstart + comp - basestart
2622 extradist = lineardist - chainsize
2622 extradist = lineardist - chainsize
2623 try:
2623 try:
2624 prevrev = chain[-2]
2624 prevrev = chain[-2]
2625 except IndexError:
2625 except IndexError:
2626 prevrev = -1
2626 prevrev = -1
2627
2627
2628 chainratio = float(chainsize) / float(uncomp)
2628 chainratio = float(chainsize) / float(uncomp)
2629 extraratio = float(extradist) / float(chainsize)
2629 extraratio = float(extradist) / float(chainsize)
2630
2630
2631 fm.startitem()
2631 fm.startitem()
2632 fm.write('rev chainid chainlen prevrev deltatype compsize '
2632 fm.write('rev chainid chainlen prevrev deltatype compsize '
2633 'uncompsize chainsize chainratio lindist extradist '
2633 'uncompsize chainsize chainratio lindist extradist '
2634 'extraratio',
2634 'extraratio',
2635 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2635 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2636 rev, chainid, len(chain), prevrev, deltatype, comp,
2636 rev, chainid, len(chain), prevrev, deltatype, comp,
2637 uncomp, chainsize, chainratio, lineardist, extradist,
2637 uncomp, chainsize, chainratio, lineardist, extradist,
2638 extraratio,
2638 extraratio,
2639 rev=rev, chainid=chainid, chainlen=len(chain),
2639 rev=rev, chainid=chainid, chainlen=len(chain),
2640 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2640 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2641 uncompsize=uncomp, chainsize=chainsize,
2641 uncompsize=uncomp, chainsize=chainsize,
2642 chainratio=chainratio, lindist=lineardist,
2642 chainratio=chainratio, lindist=lineardist,
2643 extradist=extradist, extraratio=extraratio)
2643 extradist=extradist, extraratio=extraratio)
2644
2644
2645 fm.end()
2645 fm.end()
2646
2646
2647 @command('debuginstall', [], '', norepo=True)
2647 @command('debuginstall', [], '', norepo=True)
2648 def debuginstall(ui):
2648 def debuginstall(ui):
2649 '''test Mercurial installation
2649 '''test Mercurial installation
2650
2650
2651 Returns 0 on success.
2651 Returns 0 on success.
2652 '''
2652 '''
2653
2653
2654 def writetemp(contents):
2654 def writetemp(contents):
2655 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2655 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2656 f = os.fdopen(fd, "wb")
2656 f = os.fdopen(fd, "wb")
2657 f.write(contents)
2657 f.write(contents)
2658 f.close()
2658 f.close()
2659 return name
2659 return name
2660
2660
2661 problems = 0
2661 problems = 0
2662
2662
2663 # encoding
2663 # encoding
2664 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2664 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2665 try:
2665 try:
2666 encoding.fromlocal("test")
2666 encoding.fromlocal("test")
2667 except error.Abort as inst:
2667 except error.Abort as inst:
2668 ui.write(" %s\n" % inst)
2668 ui.write(" %s\n" % inst)
2669 ui.write(_(" (check that your locale is properly set)\n"))
2669 ui.write(_(" (check that your locale is properly set)\n"))
2670 problems += 1
2670 problems += 1
2671
2671
2672 # Python
2672 # Python
2673 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2673 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2674 ui.status(_("checking Python version (%s)\n")
2674 ui.status(_("checking Python version (%s)\n")
2675 % ("%s.%s.%s" % sys.version_info[:3]))
2675 % ("%s.%s.%s" % sys.version_info[:3]))
2676 ui.status(_("checking Python lib (%s)...\n")
2676 ui.status(_("checking Python lib (%s)...\n")
2677 % os.path.dirname(os.__file__))
2677 % os.path.dirname(os.__file__))
2678
2678
2679 # compiled modules
2679 # compiled modules
2680 ui.status(_("checking installed modules (%s)...\n")
2680 ui.status(_("checking installed modules (%s)...\n")
2681 % os.path.dirname(__file__))
2681 % os.path.dirname(__file__))
2682 try:
2682 try:
2683 import bdiff, mpatch, base85, osutil
2683 import bdiff, mpatch, base85, osutil
2684 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2684 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2685 except Exception as inst:
2685 except Exception as inst:
2686 ui.write(" %s\n" % inst)
2686 ui.write(" %s\n" % inst)
2687 ui.write(_(" One or more extensions could not be found"))
2687 ui.write(_(" One or more extensions could not be found"))
2688 ui.write(_(" (check that you compiled the extensions)\n"))
2688 ui.write(_(" (check that you compiled the extensions)\n"))
2689 problems += 1
2689 problems += 1
2690
2690
2691 # templates
2691 # templates
2692 import templater
2692 import templater
2693 p = templater.templatepaths()
2693 p = templater.templatepaths()
2694 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2694 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2695 if p:
2695 if p:
2696 m = templater.templatepath("map-cmdline.default")
2696 m = templater.templatepath("map-cmdline.default")
2697 if m:
2697 if m:
2698 # template found, check if it is working
2698 # template found, check if it is working
2699 try:
2699 try:
2700 templater.templater(m)
2700 templater.templater(m)
2701 except Exception as inst:
2701 except Exception as inst:
2702 ui.write(" %s\n" % inst)
2702 ui.write(" %s\n" % inst)
2703 p = None
2703 p = None
2704 else:
2704 else:
2705 ui.write(_(" template 'default' not found\n"))
2705 ui.write(_(" template 'default' not found\n"))
2706 p = None
2706 p = None
2707 else:
2707 else:
2708 ui.write(_(" no template directories found\n"))
2708 ui.write(_(" no template directories found\n"))
2709 if not p:
2709 if not p:
2710 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2710 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2711 problems += 1
2711 problems += 1
2712
2712
2713 # editor
2713 # editor
2714 ui.status(_("checking commit editor...\n"))
2714 ui.status(_("checking commit editor...\n"))
2715 editor = ui.geteditor()
2715 editor = ui.geteditor()
2716 editor = util.expandpath(editor)
2716 editor = util.expandpath(editor)
2717 cmdpath = util.findexe(shlex.split(editor)[0])
2717 cmdpath = util.findexe(shlex.split(editor)[0])
2718 if not cmdpath:
2718 if not cmdpath:
2719 if editor == 'vi':
2719 if editor == 'vi':
2720 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2720 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2721 ui.write(_(" (specify a commit editor in your configuration"
2721 ui.write(_(" (specify a commit editor in your configuration"
2722 " file)\n"))
2722 " file)\n"))
2723 else:
2723 else:
2724 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2724 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2725 ui.write(_(" (specify a commit editor in your configuration"
2725 ui.write(_(" (specify a commit editor in your configuration"
2726 " file)\n"))
2726 " file)\n"))
2727 problems += 1
2727 problems += 1
2728
2728
2729 # check username
2729 # check username
2730 ui.status(_("checking username...\n"))
2730 ui.status(_("checking username...\n"))
2731 try:
2731 try:
2732 ui.username()
2732 ui.username()
2733 except error.Abort as e:
2733 except error.Abort as e:
2734 ui.write(" %s\n" % e)
2734 ui.write(" %s\n" % e)
2735 ui.write(_(" (specify a username in your configuration file)\n"))
2735 ui.write(_(" (specify a username in your configuration file)\n"))
2736 problems += 1
2736 problems += 1
2737
2737
2738 if not problems:
2738 if not problems:
2739 ui.status(_("no problems detected\n"))
2739 ui.status(_("no problems detected\n"))
2740 else:
2740 else:
2741 ui.write(_("%s problems detected,"
2741 ui.write(_("%s problems detected,"
2742 " please check your install!\n") % problems)
2742 " please check your install!\n") % problems)
2743
2743
2744 return problems
2744 return problems
2745
2745
2746 @command('debugknown', [], _('REPO ID...'), norepo=True)
2746 @command('debugknown', [], _('REPO ID...'), norepo=True)
2747 def debugknown(ui, repopath, *ids, **opts):
2747 def debugknown(ui, repopath, *ids, **opts):
2748 """test whether node ids are known to a repo
2748 """test whether node ids are known to a repo
2749
2749
2750 Every ID must be a full-length hex node id string. Returns a list of 0s
2750 Every ID must be a full-length hex node id string. Returns a list of 0s
2751 and 1s indicating unknown/known.
2751 and 1s indicating unknown/known.
2752 """
2752 """
2753 repo = hg.peer(ui, opts, repopath)
2753 repo = hg.peer(ui, opts, repopath)
2754 if not repo.capable('known'):
2754 if not repo.capable('known'):
2755 raise error.Abort("known() not supported by target repository")
2755 raise error.Abort("known() not supported by target repository")
2756 flags = repo.known([bin(s) for s in ids])
2756 flags = repo.known([bin(s) for s in ids])
2757 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2757 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2758
2758
2759 @command('debuglabelcomplete', [], _('LABEL...'))
2759 @command('debuglabelcomplete', [], _('LABEL...'))
2760 def debuglabelcomplete(ui, repo, *args):
2760 def debuglabelcomplete(ui, repo, *args):
2761 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2761 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2762 debugnamecomplete(ui, repo, *args)
2762 debugnamecomplete(ui, repo, *args)
2763
2763
2764 @command('debugmergestate', [], '')
2764 @command('debugmergestate', [], '')
2765 def debugmergestate(ui, repo, *args):
2765 def debugmergestate(ui, repo, *args):
2766 """print merge state
2766 """print merge state
2767
2767
2768 Use --verbose to print out information about whether v1 or v2 merge state
2768 Use --verbose to print out information about whether v1 or v2 merge state
2769 was chosen."""
2769 was chosen."""
2770 def _hashornull(h):
2770 def _hashornull(h):
2771 if h == nullhex:
2771 if h == nullhex:
2772 return 'null'
2772 return 'null'
2773 else:
2773 else:
2774 return h
2774 return h
2775
2775
2776 def printrecords(version):
2776 def printrecords(version):
2777 ui.write(('* version %s records\n') % version)
2777 ui.write(('* version %s records\n') % version)
2778 if version == 1:
2778 if version == 1:
2779 records = v1records
2779 records = v1records
2780 else:
2780 else:
2781 records = v2records
2781 records = v2records
2782
2782
2783 for rtype, record in records:
2783 for rtype, record in records:
2784 # pretty print some record types
2784 # pretty print some record types
2785 if rtype == 'L':
2785 if rtype == 'L':
2786 ui.write(('local: %s\n') % record)
2786 ui.write(('local: %s\n') % record)
2787 elif rtype == 'O':
2787 elif rtype == 'O':
2788 ui.write(('other: %s\n') % record)
2788 ui.write(('other: %s\n') % record)
2789 elif rtype == 'm':
2789 elif rtype == 'm':
2790 driver, mdstate = record.split('\0', 1)
2790 driver, mdstate = record.split('\0', 1)
2791 ui.write(('merge driver: %s (state "%s")\n')
2791 ui.write(('merge driver: %s (state "%s")\n')
2792 % (driver, mdstate))
2792 % (driver, mdstate))
2793 elif rtype in 'FDC':
2793 elif rtype in 'FDC':
2794 r = record.split('\0')
2794 r = record.split('\0')
2795 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2795 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2796 if version == 1:
2796 if version == 1:
2797 onode = 'not stored in v1 format'
2797 onode = 'not stored in v1 format'
2798 flags = r[7]
2798 flags = r[7]
2799 else:
2799 else:
2800 onode, flags = r[7:9]
2800 onode, flags = r[7:9]
2801 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2801 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2802 % (f, rtype, state, _hashornull(hash)))
2802 % (f, rtype, state, _hashornull(hash)))
2803 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2803 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2804 ui.write((' ancestor path: %s (node %s)\n')
2804 ui.write((' ancestor path: %s (node %s)\n')
2805 % (afile, _hashornull(anode)))
2805 % (afile, _hashornull(anode)))
2806 ui.write((' other path: %s (node %s)\n')
2806 ui.write((' other path: %s (node %s)\n')
2807 % (ofile, _hashornull(onode)))
2807 % (ofile, _hashornull(onode)))
2808 else:
2808 else:
2809 ui.write(('unrecognized entry: %s\t%s\n')
2809 ui.write(('unrecognized entry: %s\t%s\n')
2810 % (rtype, record.replace('\0', '\t')))
2810 % (rtype, record.replace('\0', '\t')))
2811
2811
2812 # Avoid mergestate.read() since it may raise an exception for unsupported
2812 # Avoid mergestate.read() since it may raise an exception for unsupported
2813 # merge state records. We shouldn't be doing this, but this is OK since this
2813 # merge state records. We shouldn't be doing this, but this is OK since this
2814 # command is pretty low-level.
2814 # command is pretty low-level.
2815 ms = mergemod.mergestate(repo)
2815 ms = mergemod.mergestate(repo)
2816
2816
2817 # sort so that reasonable information is on top
2817 # sort so that reasonable information is on top
2818 v1records = ms._readrecordsv1()
2818 v1records = ms._readrecordsv1()
2819 v2records = ms._readrecordsv2()
2819 v2records = ms._readrecordsv2()
2820 order = 'LOm'
2820 order = 'LOm'
2821 def key(r):
2821 def key(r):
2822 idx = order.find(r[0])
2822 idx = order.find(r[0])
2823 if idx == -1:
2823 if idx == -1:
2824 return (1, r[1])
2824 return (1, r[1])
2825 else:
2825 else:
2826 return (0, idx)
2826 return (0, idx)
2827 v1records.sort(key=key)
2827 v1records.sort(key=key)
2828 v2records.sort(key=key)
2828 v2records.sort(key=key)
2829
2829
2830 if not v1records and not v2records:
2830 if not v1records and not v2records:
2831 ui.write(('no merge state found\n'))
2831 ui.write(('no merge state found\n'))
2832 elif not v2records:
2832 elif not v2records:
2833 ui.note(('no version 2 merge state\n'))
2833 ui.note(('no version 2 merge state\n'))
2834 printrecords(1)
2834 printrecords(1)
2835 elif ms._v1v2match(v1records, v2records):
2835 elif ms._v1v2match(v1records, v2records):
2836 ui.note(('v1 and v2 states match: using v2\n'))
2836 ui.note(('v1 and v2 states match: using v2\n'))
2837 printrecords(2)
2837 printrecords(2)
2838 else:
2838 else:
2839 ui.note(('v1 and v2 states mismatch: using v1\n'))
2839 ui.note(('v1 and v2 states mismatch: using v1\n'))
2840 printrecords(1)
2840 printrecords(1)
2841 if ui.verbose:
2841 if ui.verbose:
2842 printrecords(2)
2842 printrecords(2)
2843
2843
2844 @command('debugnamecomplete', [], _('NAME...'))
2844 @command('debugnamecomplete', [], _('NAME...'))
2845 def debugnamecomplete(ui, repo, *args):
2845 def debugnamecomplete(ui, repo, *args):
2846 '''complete "names" - tags, open branch names, bookmark names'''
2846 '''complete "names" - tags, open branch names, bookmark names'''
2847
2847
2848 names = set()
2848 names = set()
2849 # since we previously only listed open branches, we will handle that
2849 # since we previously only listed open branches, we will handle that
2850 # specially (after this for loop)
2850 # specially (after this for loop)
2851 for name, ns in repo.names.iteritems():
2851 for name, ns in repo.names.iteritems():
2852 if name != 'branches':
2852 if name != 'branches':
2853 names.update(ns.listnames(repo))
2853 names.update(ns.listnames(repo))
2854 names.update(tag for (tag, heads, tip, closed)
2854 names.update(tag for (tag, heads, tip, closed)
2855 in repo.branchmap().iterbranches() if not closed)
2855 in repo.branchmap().iterbranches() if not closed)
2856 completions = set()
2856 completions = set()
2857 if not args:
2857 if not args:
2858 args = ['']
2858 args = ['']
2859 for a in args:
2859 for a in args:
2860 completions.update(n for n in names if n.startswith(a))
2860 completions.update(n for n in names if n.startswith(a))
2861 ui.write('\n'.join(sorted(completions)))
2861 ui.write('\n'.join(sorted(completions)))
2862 ui.write('\n')
2862 ui.write('\n')
2863
2863
2864 @command('debuglocks',
2864 @command('debuglocks',
2865 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2865 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2866 ('W', 'force-wlock', None,
2866 ('W', 'force-wlock', None,
2867 _('free the working state lock (DANGEROUS)'))],
2867 _('free the working state lock (DANGEROUS)'))],
2868 _('[OPTION]...'))
2868 _('[OPTION]...'))
2869 def debuglocks(ui, repo, **opts):
2869 def debuglocks(ui, repo, **opts):
2870 """show or modify state of locks
2870 """show or modify state of locks
2871
2871
2872 By default, this command will show which locks are held. This
2872 By default, this command will show which locks are held. This
2873 includes the user and process holding the lock, the amount of time
2873 includes the user and process holding the lock, the amount of time
2874 the lock has been held, and the machine name where the process is
2874 the lock has been held, and the machine name where the process is
2875 running if it's not local.
2875 running if it's not local.
2876
2876
2877 Locks protect the integrity of Mercurial's data, so should be
2877 Locks protect the integrity of Mercurial's data, so should be
2878 treated with care. System crashes or other interruptions may cause
2878 treated with care. System crashes or other interruptions may cause
2879 locks to not be properly released, though Mercurial will usually
2879 locks to not be properly released, though Mercurial will usually
2880 detect and remove such stale locks automatically.
2880 detect and remove such stale locks automatically.
2881
2881
2882 However, detecting stale locks may not always be possible (for
2882 However, detecting stale locks may not always be possible (for
2883 instance, on a shared filesystem). Removing locks may also be
2883 instance, on a shared filesystem). Removing locks may also be
2884 blocked by filesystem permissions.
2884 blocked by filesystem permissions.
2885
2885
2886 Returns 0 if no locks are held.
2886 Returns 0 if no locks are held.
2887
2887
2888 """
2888 """
2889
2889
2890 if opts.get('force_lock'):
2890 if opts.get('force_lock'):
2891 repo.svfs.unlink('lock')
2891 repo.svfs.unlink('lock')
2892 if opts.get('force_wlock'):
2892 if opts.get('force_wlock'):
2893 repo.vfs.unlink('wlock')
2893 repo.vfs.unlink('wlock')
2894 if opts.get('force_lock') or opts.get('force_lock'):
2894 if opts.get('force_lock') or opts.get('force_lock'):
2895 return 0
2895 return 0
2896
2896
2897 now = time.time()
2897 now = time.time()
2898 held = 0
2898 held = 0
2899
2899
2900 def report(vfs, name, method):
2900 def report(vfs, name, method):
2901 # this causes stale locks to get reaped for more accurate reporting
2901 # this causes stale locks to get reaped for more accurate reporting
2902 try:
2902 try:
2903 l = method(False)
2903 l = method(False)
2904 except error.LockHeld:
2904 except error.LockHeld:
2905 l = None
2905 l = None
2906
2906
2907 if l:
2907 if l:
2908 l.release()
2908 l.release()
2909 else:
2909 else:
2910 try:
2910 try:
2911 stat = vfs.lstat(name)
2911 stat = vfs.lstat(name)
2912 age = now - stat.st_mtime
2912 age = now - stat.st_mtime
2913 user = util.username(stat.st_uid)
2913 user = util.username(stat.st_uid)
2914 locker = vfs.readlock(name)
2914 locker = vfs.readlock(name)
2915 if ":" in locker:
2915 if ":" in locker:
2916 host, pid = locker.split(':')
2916 host, pid = locker.split(':')
2917 if host == socket.gethostname():
2917 if host == socket.gethostname():
2918 locker = 'user %s, process %s' % (user, pid)
2918 locker = 'user %s, process %s' % (user, pid)
2919 else:
2919 else:
2920 locker = 'user %s, process %s, host %s' \
2920 locker = 'user %s, process %s, host %s' \
2921 % (user, pid, host)
2921 % (user, pid, host)
2922 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2922 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2923 return 1
2923 return 1
2924 except OSError as e:
2924 except OSError as e:
2925 if e.errno != errno.ENOENT:
2925 if e.errno != errno.ENOENT:
2926 raise
2926 raise
2927
2927
2928 ui.write("%-6s free\n" % (name + ":"))
2928 ui.write("%-6s free\n" % (name + ":"))
2929 return 0
2929 return 0
2930
2930
2931 held += report(repo.svfs, "lock", repo.lock)
2931 held += report(repo.svfs, "lock", repo.lock)
2932 held += report(repo.vfs, "wlock", repo.wlock)
2932 held += report(repo.vfs, "wlock", repo.wlock)
2933
2933
2934 return held
2934 return held
2935
2935
2936 @command('debugobsolete',
2936 @command('debugobsolete',
2937 [('', 'flags', 0, _('markers flag')),
2937 [('', 'flags', 0, _('markers flag')),
2938 ('', 'record-parents', False,
2938 ('', 'record-parents', False,
2939 _('record parent information for the precursor')),
2939 _('record parent information for the precursor')),
2940 ('r', 'rev', [], _('display markers relevant to REV')),
2940 ('r', 'rev', [], _('display markers relevant to REV')),
2941 ] + commitopts2,
2941 ] + commitopts2,
2942 _('[OBSOLETED [REPLACEMENT ...]]'))
2942 _('[OBSOLETED [REPLACEMENT ...]]'))
2943 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2943 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2944 """create arbitrary obsolete marker
2944 """create arbitrary obsolete marker
2945
2945
2946 With no arguments, displays the list of obsolescence markers."""
2946 With no arguments, displays the list of obsolescence markers."""
2947
2947
2948 def parsenodeid(s):
2948 def parsenodeid(s):
2949 try:
2949 try:
2950 # We do not use revsingle/revrange functions here to accept
2950 # We do not use revsingle/revrange functions here to accept
2951 # arbitrary node identifiers, possibly not present in the
2951 # arbitrary node identifiers, possibly not present in the
2952 # local repository.
2952 # local repository.
2953 n = bin(s)
2953 n = bin(s)
2954 if len(n) != len(nullid):
2954 if len(n) != len(nullid):
2955 raise TypeError()
2955 raise TypeError()
2956 return n
2956 return n
2957 except TypeError:
2957 except TypeError:
2958 raise error.Abort('changeset references must be full hexadecimal '
2958 raise error.Abort('changeset references must be full hexadecimal '
2959 'node identifiers')
2959 'node identifiers')
2960
2960
2961 if precursor is not None:
2961 if precursor is not None:
2962 if opts['rev']:
2962 if opts['rev']:
2963 raise error.Abort('cannot select revision when creating marker')
2963 raise error.Abort('cannot select revision when creating marker')
2964 metadata = {}
2964 metadata = {}
2965 metadata['user'] = opts['user'] or ui.username()
2965 metadata['user'] = opts['user'] or ui.username()
2966 succs = tuple(parsenodeid(succ) for succ in successors)
2966 succs = tuple(parsenodeid(succ) for succ in successors)
2967 l = repo.lock()
2967 l = repo.lock()
2968 try:
2968 try:
2969 tr = repo.transaction('debugobsolete')
2969 tr = repo.transaction('debugobsolete')
2970 try:
2970 try:
2971 date = opts.get('date')
2971 date = opts.get('date')
2972 if date:
2972 if date:
2973 date = util.parsedate(date)
2973 date = util.parsedate(date)
2974 else:
2974 else:
2975 date = None
2975 date = None
2976 prec = parsenodeid(precursor)
2976 prec = parsenodeid(precursor)
2977 parents = None
2977 parents = None
2978 if opts['record_parents']:
2978 if opts['record_parents']:
2979 if prec not in repo.unfiltered():
2979 if prec not in repo.unfiltered():
2980 raise error.Abort('cannot used --record-parents on '
2980 raise error.Abort('cannot used --record-parents on '
2981 'unknown changesets')
2981 'unknown changesets')
2982 parents = repo.unfiltered()[prec].parents()
2982 parents = repo.unfiltered()[prec].parents()
2983 parents = tuple(p.node() for p in parents)
2983 parents = tuple(p.node() for p in parents)
2984 repo.obsstore.create(tr, prec, succs, opts['flags'],
2984 repo.obsstore.create(tr, prec, succs, opts['flags'],
2985 parents=parents, date=date,
2985 parents=parents, date=date,
2986 metadata=metadata)
2986 metadata=metadata)
2987 tr.close()
2987 tr.close()
2988 except ValueError as exc:
2988 except ValueError as exc:
2989 raise error.Abort(_('bad obsmarker input: %s') % exc)
2989 raise error.Abort(_('bad obsmarker input: %s') % exc)
2990 finally:
2990 finally:
2991 tr.release()
2991 tr.release()
2992 finally:
2992 finally:
2993 l.release()
2993 l.release()
2994 else:
2994 else:
2995 if opts['rev']:
2995 if opts['rev']:
2996 revs = scmutil.revrange(repo, opts['rev'])
2996 revs = scmutil.revrange(repo, opts['rev'])
2997 nodes = [repo[r].node() for r in revs]
2997 nodes = [repo[r].node() for r in revs]
2998 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2998 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2999 markers.sort(key=lambda x: x._data)
2999 markers.sort(key=lambda x: x._data)
3000 else:
3000 else:
3001 markers = obsolete.getmarkers(repo)
3001 markers = obsolete.getmarkers(repo)
3002
3002
3003 for m in markers:
3003 for m in markers:
3004 cmdutil.showmarker(ui, m)
3004 cmdutil.showmarker(ui, m)
3005
3005
3006 @command('debugpathcomplete',
3006 @command('debugpathcomplete',
3007 [('f', 'full', None, _('complete an entire path')),
3007 [('f', 'full', None, _('complete an entire path')),
3008 ('n', 'normal', None, _('show only normal files')),
3008 ('n', 'normal', None, _('show only normal files')),
3009 ('a', 'added', None, _('show only added files')),
3009 ('a', 'added', None, _('show only added files')),
3010 ('r', 'removed', None, _('show only removed files'))],
3010 ('r', 'removed', None, _('show only removed files'))],
3011 _('FILESPEC...'))
3011 _('FILESPEC...'))
3012 def debugpathcomplete(ui, repo, *specs, **opts):
3012 def debugpathcomplete(ui, repo, *specs, **opts):
3013 '''complete part or all of a tracked path
3013 '''complete part or all of a tracked path
3014
3014
3015 This command supports shells that offer path name completion. It
3015 This command supports shells that offer path name completion. It
3016 currently completes only files already known to the dirstate.
3016 currently completes only files already known to the dirstate.
3017
3017
3018 Completion extends only to the next path segment unless
3018 Completion extends only to the next path segment unless
3019 --full is specified, in which case entire paths are used.'''
3019 --full is specified, in which case entire paths are used.'''
3020
3020
3021 def complete(path, acceptable):
3021 def complete(path, acceptable):
3022 dirstate = repo.dirstate
3022 dirstate = repo.dirstate
3023 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3023 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3024 rootdir = repo.root + os.sep
3024 rootdir = repo.root + os.sep
3025 if spec != repo.root and not spec.startswith(rootdir):
3025 if spec != repo.root and not spec.startswith(rootdir):
3026 return [], []
3026 return [], []
3027 if os.path.isdir(spec):
3027 if os.path.isdir(spec):
3028 spec += '/'
3028 spec += '/'
3029 spec = spec[len(rootdir):]
3029 spec = spec[len(rootdir):]
3030 fixpaths = os.sep != '/'
3030 fixpaths = os.sep != '/'
3031 if fixpaths:
3031 if fixpaths:
3032 spec = spec.replace(os.sep, '/')
3032 spec = spec.replace(os.sep, '/')
3033 speclen = len(spec)
3033 speclen = len(spec)
3034 fullpaths = opts['full']
3034 fullpaths = opts['full']
3035 files, dirs = set(), set()
3035 files, dirs = set(), set()
3036 adddir, addfile = dirs.add, files.add
3036 adddir, addfile = dirs.add, files.add
3037 for f, st in dirstate.iteritems():
3037 for f, st in dirstate.iteritems():
3038 if f.startswith(spec) and st[0] in acceptable:
3038 if f.startswith(spec) and st[0] in acceptable:
3039 if fixpaths:
3039 if fixpaths:
3040 f = f.replace('/', os.sep)
3040 f = f.replace('/', os.sep)
3041 if fullpaths:
3041 if fullpaths:
3042 addfile(f)
3042 addfile(f)
3043 continue
3043 continue
3044 s = f.find(os.sep, speclen)
3044 s = f.find(os.sep, speclen)
3045 if s >= 0:
3045 if s >= 0:
3046 adddir(f[:s])
3046 adddir(f[:s])
3047 else:
3047 else:
3048 addfile(f)
3048 addfile(f)
3049 return files, dirs
3049 return files, dirs
3050
3050
3051 acceptable = ''
3051 acceptable = ''
3052 if opts['normal']:
3052 if opts['normal']:
3053 acceptable += 'nm'
3053 acceptable += 'nm'
3054 if opts['added']:
3054 if opts['added']:
3055 acceptable += 'a'
3055 acceptable += 'a'
3056 if opts['removed']:
3056 if opts['removed']:
3057 acceptable += 'r'
3057 acceptable += 'r'
3058 cwd = repo.getcwd()
3058 cwd = repo.getcwd()
3059 if not specs:
3059 if not specs:
3060 specs = ['.']
3060 specs = ['.']
3061
3061
3062 files, dirs = set(), set()
3062 files, dirs = set(), set()
3063 for spec in specs:
3063 for spec in specs:
3064 f, d = complete(spec, acceptable or 'nmar')
3064 f, d = complete(spec, acceptable or 'nmar')
3065 files.update(f)
3065 files.update(f)
3066 dirs.update(d)
3066 dirs.update(d)
3067 files.update(dirs)
3067 files.update(dirs)
3068 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3068 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3069 ui.write('\n')
3069 ui.write('\n')
3070
3070
3071 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3071 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3072 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3072 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3073 '''access the pushkey key/value protocol
3073 '''access the pushkey key/value protocol
3074
3074
3075 With two args, list the keys in the given namespace.
3075 With two args, list the keys in the given namespace.
3076
3076
3077 With five args, set a key to new if it currently is set to old.
3077 With five args, set a key to new if it currently is set to old.
3078 Reports success or failure.
3078 Reports success or failure.
3079 '''
3079 '''
3080
3080
3081 target = hg.peer(ui, {}, repopath)
3081 target = hg.peer(ui, {}, repopath)
3082 if keyinfo:
3082 if keyinfo:
3083 key, old, new = keyinfo
3083 key, old, new = keyinfo
3084 r = target.pushkey(namespace, key, old, new)
3084 r = target.pushkey(namespace, key, old, new)
3085 ui.status(str(r) + '\n')
3085 ui.status(str(r) + '\n')
3086 return not r
3086 return not r
3087 else:
3087 else:
3088 for k, v in sorted(target.listkeys(namespace).iteritems()):
3088 for k, v in sorted(target.listkeys(namespace).iteritems()):
3089 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3089 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3090 v.encode('string-escape')))
3090 v.encode('string-escape')))
3091
3091
3092 @command('debugpvec', [], _('A B'))
3092 @command('debugpvec', [], _('A B'))
3093 def debugpvec(ui, repo, a, b=None):
3093 def debugpvec(ui, repo, a, b=None):
3094 ca = scmutil.revsingle(repo, a)
3094 ca = scmutil.revsingle(repo, a)
3095 cb = scmutil.revsingle(repo, b)
3095 cb = scmutil.revsingle(repo, b)
3096 pa = pvec.ctxpvec(ca)
3096 pa = pvec.ctxpvec(ca)
3097 pb = pvec.ctxpvec(cb)
3097 pb = pvec.ctxpvec(cb)
3098 if pa == pb:
3098 if pa == pb:
3099 rel = "="
3099 rel = "="
3100 elif pa > pb:
3100 elif pa > pb:
3101 rel = ">"
3101 rel = ">"
3102 elif pa < pb:
3102 elif pa < pb:
3103 rel = "<"
3103 rel = "<"
3104 elif pa | pb:
3104 elif pa | pb:
3105 rel = "|"
3105 rel = "|"
3106 ui.write(_("a: %s\n") % pa)
3106 ui.write(_("a: %s\n") % pa)
3107 ui.write(_("b: %s\n") % pb)
3107 ui.write(_("b: %s\n") % pb)
3108 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3108 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3109 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3109 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3110 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3110 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3111 pa.distance(pb), rel))
3111 pa.distance(pb), rel))
3112
3112
3113 @command('debugrebuilddirstate|debugrebuildstate',
3113 @command('debugrebuilddirstate|debugrebuildstate',
3114 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3114 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3115 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3115 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3116 'the working copy parent')),
3116 'the working copy parent')),
3117 ],
3117 ],
3118 _('[-r REV]'))
3118 _('[-r REV]'))
3119 def debugrebuilddirstate(ui, repo, rev, **opts):
3119 def debugrebuilddirstate(ui, repo, rev, **opts):
3120 """rebuild the dirstate as it would look like for the given revision
3120 """rebuild the dirstate as it would look like for the given revision
3121
3121
3122 If no revision is specified the first current parent will be used.
3122 If no revision is specified the first current parent will be used.
3123
3123
3124 The dirstate will be set to the files of the given revision.
3124 The dirstate will be set to the files of the given revision.
3125 The actual working directory content or existing dirstate
3125 The actual working directory content or existing dirstate
3126 information such as adds or removes is not considered.
3126 information such as adds or removes is not considered.
3127
3127
3128 ``minimal`` will only rebuild the dirstate status for files that claim to be
3128 ``minimal`` will only rebuild the dirstate status for files that claim to be
3129 tracked but are not in the parent manifest, or that exist in the parent
3129 tracked but are not in the parent manifest, or that exist in the parent
3130 manifest but are not in the dirstate. It will not change adds, removes, or
3130 manifest but are not in the dirstate. It will not change adds, removes, or
3131 modified files that are in the working copy parent.
3131 modified files that are in the working copy parent.
3132
3132
3133 One use of this command is to make the next :hg:`status` invocation
3133 One use of this command is to make the next :hg:`status` invocation
3134 check the actual file content.
3134 check the actual file content.
3135 """
3135 """
3136 ctx = scmutil.revsingle(repo, rev)
3136 ctx = scmutil.revsingle(repo, rev)
3137 wlock = repo.wlock()
3137 wlock = repo.wlock()
3138 try:
3138 try:
3139 dirstate = repo.dirstate
3139 dirstate = repo.dirstate
3140 changedfiles = None
3140 changedfiles = None
3141 # See command doc for what minimal does.
3141 # See command doc for what minimal does.
3142 if opts.get('minimal'):
3142 if opts.get('minimal'):
3143 manifestfiles = set(ctx.manifest().keys())
3143 manifestfiles = set(ctx.manifest().keys())
3144 dirstatefiles = set(dirstate)
3144 dirstatefiles = set(dirstate)
3145 manifestonly = manifestfiles - dirstatefiles
3145 manifestonly = manifestfiles - dirstatefiles
3146 dsonly = dirstatefiles - manifestfiles
3146 dsonly = dirstatefiles - manifestfiles
3147 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3147 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3148 changedfiles = manifestonly | dsnotadded
3148 changedfiles = manifestonly | dsnotadded
3149
3149
3150 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3150 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3151 finally:
3151 finally:
3152 wlock.release()
3152 wlock.release()
3153
3153
3154 @command('debugrebuildfncache', [], '')
3154 @command('debugrebuildfncache', [], '')
3155 def debugrebuildfncache(ui, repo):
3155 def debugrebuildfncache(ui, repo):
3156 """rebuild the fncache file"""
3156 """rebuild the fncache file"""
3157 repair.rebuildfncache(ui, repo)
3157 repair.rebuildfncache(ui, repo)
3158
3158
3159 @command('debugrename',
3159 @command('debugrename',
3160 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3160 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3161 _('[-r REV] FILE'))
3161 _('[-r REV] FILE'))
3162 def debugrename(ui, repo, file1, *pats, **opts):
3162 def debugrename(ui, repo, file1, *pats, **opts):
3163 """dump rename information"""
3163 """dump rename information"""
3164
3164
3165 ctx = scmutil.revsingle(repo, opts.get('rev'))
3165 ctx = scmutil.revsingle(repo, opts.get('rev'))
3166 m = scmutil.match(ctx, (file1,) + pats, opts)
3166 m = scmutil.match(ctx, (file1,) + pats, opts)
3167 for abs in ctx.walk(m):
3167 for abs in ctx.walk(m):
3168 fctx = ctx[abs]
3168 fctx = ctx[abs]
3169 o = fctx.filelog().renamed(fctx.filenode())
3169 o = fctx.filelog().renamed(fctx.filenode())
3170 rel = m.rel(abs)
3170 rel = m.rel(abs)
3171 if o:
3171 if o:
3172 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3172 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3173 else:
3173 else:
3174 ui.write(_("%s not renamed\n") % rel)
3174 ui.write(_("%s not renamed\n") % rel)
3175
3175
3176 @command('debugrevlog', debugrevlogopts +
3176 @command('debugrevlog', debugrevlogopts +
3177 [('d', 'dump', False, _('dump index data'))],
3177 [('d', 'dump', False, _('dump index data'))],
3178 _('-c|-m|FILE'),
3178 _('-c|-m|FILE'),
3179 optionalrepo=True)
3179 optionalrepo=True)
3180 def debugrevlog(ui, repo, file_=None, **opts):
3180 def debugrevlog(ui, repo, file_=None, **opts):
3181 """show data and statistics about a revlog"""
3181 """show data and statistics about a revlog"""
3182 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3182 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3183
3183
3184 if opts.get("dump"):
3184 if opts.get("dump"):
3185 numrevs = len(r)
3185 numrevs = len(r)
3186 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3186 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3187 " rawsize totalsize compression heads chainlen\n")
3187 " rawsize totalsize compression heads chainlen\n")
3188 ts = 0
3188 ts = 0
3189 heads = set()
3189 heads = set()
3190
3190
3191 for rev in xrange(numrevs):
3191 for rev in xrange(numrevs):
3192 dbase = r.deltaparent(rev)
3192 dbase = r.deltaparent(rev)
3193 if dbase == -1:
3193 if dbase == -1:
3194 dbase = rev
3194 dbase = rev
3195 cbase = r.chainbase(rev)
3195 cbase = r.chainbase(rev)
3196 clen = r.chainlen(rev)
3196 clen = r.chainlen(rev)
3197 p1, p2 = r.parentrevs(rev)
3197 p1, p2 = r.parentrevs(rev)
3198 rs = r.rawsize(rev)
3198 rs = r.rawsize(rev)
3199 ts = ts + rs
3199 ts = ts + rs
3200 heads -= set(r.parentrevs(rev))
3200 heads -= set(r.parentrevs(rev))
3201 heads.add(rev)
3201 heads.add(rev)
3202 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3202 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3203 "%11d %5d %8d\n" %
3203 "%11d %5d %8d\n" %
3204 (rev, p1, p2, r.start(rev), r.end(rev),
3204 (rev, p1, p2, r.start(rev), r.end(rev),
3205 r.start(dbase), r.start(cbase),
3205 r.start(dbase), r.start(cbase),
3206 r.start(p1), r.start(p2),
3206 r.start(p1), r.start(p2),
3207 rs, ts, ts / r.end(rev), len(heads), clen))
3207 rs, ts, ts / r.end(rev), len(heads), clen))
3208 return 0
3208 return 0
3209
3209
3210 v = r.version
3210 v = r.version
3211 format = v & 0xFFFF
3211 format = v & 0xFFFF
3212 flags = []
3212 flags = []
3213 gdelta = False
3213 gdelta = False
3214 if v & revlog.REVLOGNGINLINEDATA:
3214 if v & revlog.REVLOGNGINLINEDATA:
3215 flags.append('inline')
3215 flags.append('inline')
3216 if v & revlog.REVLOGGENERALDELTA:
3216 if v & revlog.REVLOGGENERALDELTA:
3217 gdelta = True
3217 gdelta = True
3218 flags.append('generaldelta')
3218 flags.append('generaldelta')
3219 if not flags:
3219 if not flags:
3220 flags = ['(none)']
3220 flags = ['(none)']
3221
3221
3222 nummerges = 0
3222 nummerges = 0
3223 numfull = 0
3223 numfull = 0
3224 numprev = 0
3224 numprev = 0
3225 nump1 = 0
3225 nump1 = 0
3226 nump2 = 0
3226 nump2 = 0
3227 numother = 0
3227 numother = 0
3228 nump1prev = 0
3228 nump1prev = 0
3229 nump2prev = 0
3229 nump2prev = 0
3230 chainlengths = []
3230 chainlengths = []
3231
3231
3232 datasize = [None, 0, 0L]
3232 datasize = [None, 0, 0L]
3233 fullsize = [None, 0, 0L]
3233 fullsize = [None, 0, 0L]
3234 deltasize = [None, 0, 0L]
3234 deltasize = [None, 0, 0L]
3235
3235
3236 def addsize(size, l):
3236 def addsize(size, l):
3237 if l[0] is None or size < l[0]:
3237 if l[0] is None or size < l[0]:
3238 l[0] = size
3238 l[0] = size
3239 if size > l[1]:
3239 if size > l[1]:
3240 l[1] = size
3240 l[1] = size
3241 l[2] += size
3241 l[2] += size
3242
3242
3243 numrevs = len(r)
3243 numrevs = len(r)
3244 for rev in xrange(numrevs):
3244 for rev in xrange(numrevs):
3245 p1, p2 = r.parentrevs(rev)
3245 p1, p2 = r.parentrevs(rev)
3246 delta = r.deltaparent(rev)
3246 delta = r.deltaparent(rev)
3247 if format > 0:
3247 if format > 0:
3248 addsize(r.rawsize(rev), datasize)
3248 addsize(r.rawsize(rev), datasize)
3249 if p2 != nullrev:
3249 if p2 != nullrev:
3250 nummerges += 1
3250 nummerges += 1
3251 size = r.length(rev)
3251 size = r.length(rev)
3252 if delta == nullrev:
3252 if delta == nullrev:
3253 chainlengths.append(0)
3253 chainlengths.append(0)
3254 numfull += 1
3254 numfull += 1
3255 addsize(size, fullsize)
3255 addsize(size, fullsize)
3256 else:
3256 else:
3257 chainlengths.append(chainlengths[delta] + 1)
3257 chainlengths.append(chainlengths[delta] + 1)
3258 addsize(size, deltasize)
3258 addsize(size, deltasize)
3259 if delta == rev - 1:
3259 if delta == rev - 1:
3260 numprev += 1
3260 numprev += 1
3261 if delta == p1:
3261 if delta == p1:
3262 nump1prev += 1
3262 nump1prev += 1
3263 elif delta == p2:
3263 elif delta == p2:
3264 nump2prev += 1
3264 nump2prev += 1
3265 elif delta == p1:
3265 elif delta == p1:
3266 nump1 += 1
3266 nump1 += 1
3267 elif delta == p2:
3267 elif delta == p2:
3268 nump2 += 1
3268 nump2 += 1
3269 elif delta != nullrev:
3269 elif delta != nullrev:
3270 numother += 1
3270 numother += 1
3271
3271
3272 # Adjust size min value for empty cases
3272 # Adjust size min value for empty cases
3273 for size in (datasize, fullsize, deltasize):
3273 for size in (datasize, fullsize, deltasize):
3274 if size[0] is None:
3274 if size[0] is None:
3275 size[0] = 0
3275 size[0] = 0
3276
3276
3277 numdeltas = numrevs - numfull
3277 numdeltas = numrevs - numfull
3278 numoprev = numprev - nump1prev - nump2prev
3278 numoprev = numprev - nump1prev - nump2prev
3279 totalrawsize = datasize[2]
3279 totalrawsize = datasize[2]
3280 datasize[2] /= numrevs
3280 datasize[2] /= numrevs
3281 fulltotal = fullsize[2]
3281 fulltotal = fullsize[2]
3282 fullsize[2] /= numfull
3282 fullsize[2] /= numfull
3283 deltatotal = deltasize[2]
3283 deltatotal = deltasize[2]
3284 if numrevs - numfull > 0:
3284 if numrevs - numfull > 0:
3285 deltasize[2] /= numrevs - numfull
3285 deltasize[2] /= numrevs - numfull
3286 totalsize = fulltotal + deltatotal
3286 totalsize = fulltotal + deltatotal
3287 avgchainlen = sum(chainlengths) / numrevs
3287 avgchainlen = sum(chainlengths) / numrevs
3288 maxchainlen = max(chainlengths)
3288 maxchainlen = max(chainlengths)
3289 compratio = 1
3289 compratio = 1
3290 if totalsize:
3290 if totalsize:
3291 compratio = totalrawsize / totalsize
3291 compratio = totalrawsize / totalsize
3292
3292
3293 basedfmtstr = '%%%dd\n'
3293 basedfmtstr = '%%%dd\n'
3294 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3294 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3295
3295
3296 def dfmtstr(max):
3296 def dfmtstr(max):
3297 return basedfmtstr % len(str(max))
3297 return basedfmtstr % len(str(max))
3298 def pcfmtstr(max, padding=0):
3298 def pcfmtstr(max, padding=0):
3299 return basepcfmtstr % (len(str(max)), ' ' * padding)
3299 return basepcfmtstr % (len(str(max)), ' ' * padding)
3300
3300
3301 def pcfmt(value, total):
3301 def pcfmt(value, total):
3302 if total:
3302 if total:
3303 return (value, 100 * float(value) / total)
3303 return (value, 100 * float(value) / total)
3304 else:
3304 else:
3305 return value, 100.0
3305 return value, 100.0
3306
3306
3307 ui.write(('format : %d\n') % format)
3307 ui.write(('format : %d\n') % format)
3308 ui.write(('flags : %s\n') % ', '.join(flags))
3308 ui.write(('flags : %s\n') % ', '.join(flags))
3309
3309
3310 ui.write('\n')
3310 ui.write('\n')
3311 fmt = pcfmtstr(totalsize)
3311 fmt = pcfmtstr(totalsize)
3312 fmt2 = dfmtstr(totalsize)
3312 fmt2 = dfmtstr(totalsize)
3313 ui.write(('revisions : ') + fmt2 % numrevs)
3313 ui.write(('revisions : ') + fmt2 % numrevs)
3314 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3314 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3315 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3315 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3316 ui.write(('revisions : ') + fmt2 % numrevs)
3316 ui.write(('revisions : ') + fmt2 % numrevs)
3317 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3317 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3318 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3318 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3319 ui.write(('revision size : ') + fmt2 % totalsize)
3319 ui.write(('revision size : ') + fmt2 % totalsize)
3320 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3320 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3321 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3321 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3322
3322
3323 ui.write('\n')
3323 ui.write('\n')
3324 fmt = dfmtstr(max(avgchainlen, compratio))
3324 fmt = dfmtstr(max(avgchainlen, compratio))
3325 ui.write(('avg chain length : ') + fmt % avgchainlen)
3325 ui.write(('avg chain length : ') + fmt % avgchainlen)
3326 ui.write(('max chain length : ') + fmt % maxchainlen)
3326 ui.write(('max chain length : ') + fmt % maxchainlen)
3327 ui.write(('compression ratio : ') + fmt % compratio)
3327 ui.write(('compression ratio : ') + fmt % compratio)
3328
3328
3329 if format > 0:
3329 if format > 0:
3330 ui.write('\n')
3330 ui.write('\n')
3331 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3331 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3332 % tuple(datasize))
3332 % tuple(datasize))
3333 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3333 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3334 % tuple(fullsize))
3334 % tuple(fullsize))
3335 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3335 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3336 % tuple(deltasize))
3336 % tuple(deltasize))
3337
3337
3338 if numdeltas > 0:
3338 if numdeltas > 0:
3339 ui.write('\n')
3339 ui.write('\n')
3340 fmt = pcfmtstr(numdeltas)
3340 fmt = pcfmtstr(numdeltas)
3341 fmt2 = pcfmtstr(numdeltas, 4)
3341 fmt2 = pcfmtstr(numdeltas, 4)
3342 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3342 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3343 if numprev > 0:
3343 if numprev > 0:
3344 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3344 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3345 numprev))
3345 numprev))
3346 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3346 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3347 numprev))
3347 numprev))
3348 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3348 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3349 numprev))
3349 numprev))
3350 if gdelta:
3350 if gdelta:
3351 ui.write(('deltas against p1 : ')
3351 ui.write(('deltas against p1 : ')
3352 + fmt % pcfmt(nump1, numdeltas))
3352 + fmt % pcfmt(nump1, numdeltas))
3353 ui.write(('deltas against p2 : ')
3353 ui.write(('deltas against p2 : ')
3354 + fmt % pcfmt(nump2, numdeltas))
3354 + fmt % pcfmt(nump2, numdeltas))
3355 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3355 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3356 numdeltas))
3356 numdeltas))
3357
3357
3358 @command('debugrevspec',
3358 @command('debugrevspec',
3359 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3359 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3360 ('REVSPEC'))
3360 ('REVSPEC'))
3361 def debugrevspec(ui, repo, expr, **opts):
3361 def debugrevspec(ui, repo, expr, **opts):
3362 """parse and apply a revision specification
3362 """parse and apply a revision specification
3363
3363
3364 Use --verbose to print the parsed tree before and after aliases
3364 Use --verbose to print the parsed tree before and after aliases
3365 expansion.
3365 expansion.
3366 """
3366 """
3367 if ui.verbose:
3367 if ui.verbose:
3368 tree = revset.parse(expr, lookup=repo.__contains__)
3368 tree = revset.parse(expr, lookup=repo.__contains__)
3369 ui.note(revset.prettyformat(tree), "\n")
3369 ui.note(revset.prettyformat(tree), "\n")
3370 newtree = revset.findaliases(ui, tree)
3370 newtree = revset.findaliases(ui, tree)
3371 if newtree != tree:
3371 if newtree != tree:
3372 ui.note(revset.prettyformat(newtree), "\n")
3372 ui.note(revset.prettyformat(newtree), "\n")
3373 tree = newtree
3373 tree = newtree
3374 newtree = revset.foldconcat(tree)
3374 newtree = revset.foldconcat(tree)
3375 if newtree != tree:
3375 if newtree != tree:
3376 ui.note(revset.prettyformat(newtree), "\n")
3376 ui.note(revset.prettyformat(newtree), "\n")
3377 if opts["optimize"]:
3377 if opts["optimize"]:
3378 weight, optimizedtree = revset.optimize(newtree, True)
3378 weight, optimizedtree = revset.optimize(newtree, True)
3379 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3379 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3380 func = revset.match(ui, expr, repo)
3380 func = revset.match(ui, expr, repo)
3381 revs = func(repo)
3381 revs = func(repo)
3382 if ui.verbose:
3382 if ui.verbose:
3383 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3383 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3384 for c in revs:
3384 for c in revs:
3385 ui.write("%s\n" % c)
3385 ui.write("%s\n" % c)
3386
3386
3387 @command('debugsetparents', [], _('REV1 [REV2]'))
3387 @command('debugsetparents', [], _('REV1 [REV2]'))
3388 def debugsetparents(ui, repo, rev1, rev2=None):
3388 def debugsetparents(ui, repo, rev1, rev2=None):
3389 """manually set the parents of the current working directory
3389 """manually set the parents of the current working directory
3390
3390
3391 This is useful for writing repository conversion tools, but should
3391 This is useful for writing repository conversion tools, but should
3392 be used with care. For example, neither the working directory nor the
3392 be used with care. For example, neither the working directory nor the
3393 dirstate is updated, so file status may be incorrect after running this
3393 dirstate is updated, so file status may be incorrect after running this
3394 command.
3394 command.
3395
3395
3396 Returns 0 on success.
3396 Returns 0 on success.
3397 """
3397 """
3398
3398
3399 r1 = scmutil.revsingle(repo, rev1).node()
3399 r1 = scmutil.revsingle(repo, rev1).node()
3400 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3400 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3401
3401
3402 wlock = repo.wlock()
3402 wlock = repo.wlock()
3403 try:
3403 try:
3404 repo.dirstate.beginparentchange()
3404 repo.dirstate.beginparentchange()
3405 repo.setparents(r1, r2)
3405 repo.setparents(r1, r2)
3406 repo.dirstate.endparentchange()
3406 repo.dirstate.endparentchange()
3407 finally:
3407 finally:
3408 wlock.release()
3408 wlock.release()
3409
3409
3410 @command('debugdirstate|debugstate',
3410 @command('debugdirstate|debugstate',
3411 [('', 'nodates', None, _('do not display the saved mtime')),
3411 [('', 'nodates', None, _('do not display the saved mtime')),
3412 ('', 'datesort', None, _('sort by saved mtime'))],
3412 ('', 'datesort', None, _('sort by saved mtime'))],
3413 _('[OPTION]...'))
3413 _('[OPTION]...'))
3414 def debugstate(ui, repo, **opts):
3414 def debugstate(ui, repo, **opts):
3415 """show the contents of the current dirstate"""
3415 """show the contents of the current dirstate"""
3416
3416
3417 nodates = opts.get('nodates')
3417 nodates = opts.get('nodates')
3418 datesort = opts.get('datesort')
3418 datesort = opts.get('datesort')
3419
3419
3420 timestr = ""
3420 timestr = ""
3421 if datesort:
3421 if datesort:
3422 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3422 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3423 else:
3423 else:
3424 keyfunc = None # sort by filename
3424 keyfunc = None # sort by filename
3425 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3425 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3426 if ent[3] == -1:
3426 if ent[3] == -1:
3427 timestr = 'unset '
3427 timestr = 'unset '
3428 elif nodates:
3428 elif nodates:
3429 timestr = 'set '
3429 timestr = 'set '
3430 else:
3430 else:
3431 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3431 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3432 time.localtime(ent[3]))
3432 time.localtime(ent[3]))
3433 if ent[1] & 0o20000:
3433 if ent[1] & 0o20000:
3434 mode = 'lnk'
3434 mode = 'lnk'
3435 else:
3435 else:
3436 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3436 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3437 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3437 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3438 for f in repo.dirstate.copies():
3438 for f in repo.dirstate.copies():
3439 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3439 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3440
3440
3441 @command('debugsub',
3441 @command('debugsub',
3442 [('r', 'rev', '',
3442 [('r', 'rev', '',
3443 _('revision to check'), _('REV'))],
3443 _('revision to check'), _('REV'))],
3444 _('[-r REV] [REV]'))
3444 _('[-r REV] [REV]'))
3445 def debugsub(ui, repo, rev=None):
3445 def debugsub(ui, repo, rev=None):
3446 ctx = scmutil.revsingle(repo, rev, None)
3446 ctx = scmutil.revsingle(repo, rev, None)
3447 for k, v in sorted(ctx.substate.items()):
3447 for k, v in sorted(ctx.substate.items()):
3448 ui.write(('path %s\n') % k)
3448 ui.write(('path %s\n') % k)
3449 ui.write((' source %s\n') % v[0])
3449 ui.write((' source %s\n') % v[0])
3450 ui.write((' revision %s\n') % v[1])
3450 ui.write((' revision %s\n') % v[1])
3451
3451
3452 @command('debugsuccessorssets',
3452 @command('debugsuccessorssets',
3453 [],
3453 [],
3454 _('[REV]'))
3454 _('[REV]'))
3455 def debugsuccessorssets(ui, repo, *revs):
3455 def debugsuccessorssets(ui, repo, *revs):
3456 """show set of successors for revision
3456 """show set of successors for revision
3457
3457
3458 A successors set of changeset A is a consistent group of revisions that
3458 A successors set of changeset A is a consistent group of revisions that
3459 succeed A. It contains non-obsolete changesets only.
3459 succeed A. It contains non-obsolete changesets only.
3460
3460
3461 In most cases a changeset A has a single successors set containing a single
3461 In most cases a changeset A has a single successors set containing a single
3462 successor (changeset A replaced by A').
3462 successor (changeset A replaced by A').
3463
3463
3464 A changeset that is made obsolete with no successors are called "pruned".
3464 A changeset that is made obsolete with no successors are called "pruned".
3465 Such changesets have no successors sets at all.
3465 Such changesets have no successors sets at all.
3466
3466
3467 A changeset that has been "split" will have a successors set containing
3467 A changeset that has been "split" will have a successors set containing
3468 more than one successor.
3468 more than one successor.
3469
3469
3470 A changeset that has been rewritten in multiple different ways is called
3470 A changeset that has been rewritten in multiple different ways is called
3471 "divergent". Such changesets have multiple successor sets (each of which
3471 "divergent". Such changesets have multiple successor sets (each of which
3472 may also be split, i.e. have multiple successors).
3472 may also be split, i.e. have multiple successors).
3473
3473
3474 Results are displayed as follows::
3474 Results are displayed as follows::
3475
3475
3476 <rev1>
3476 <rev1>
3477 <successors-1A>
3477 <successors-1A>
3478 <rev2>
3478 <rev2>
3479 <successors-2A>
3479 <successors-2A>
3480 <successors-2B1> <successors-2B2> <successors-2B3>
3480 <successors-2B1> <successors-2B2> <successors-2B3>
3481
3481
3482 Here rev2 has two possible (i.e. divergent) successors sets. The first
3482 Here rev2 has two possible (i.e. divergent) successors sets. The first
3483 holds one element, whereas the second holds three (i.e. the changeset has
3483 holds one element, whereas the second holds three (i.e. the changeset has
3484 been split).
3484 been split).
3485 """
3485 """
3486 # passed to successorssets caching computation from one call to another
3486 # passed to successorssets caching computation from one call to another
3487 cache = {}
3487 cache = {}
3488 ctx2str = str
3488 ctx2str = str
3489 node2str = short
3489 node2str = short
3490 if ui.debug():
3490 if ui.debug():
3491 def ctx2str(ctx):
3491 def ctx2str(ctx):
3492 return ctx.hex()
3492 return ctx.hex()
3493 node2str = hex
3493 node2str = hex
3494 for rev in scmutil.revrange(repo, revs):
3494 for rev in scmutil.revrange(repo, revs):
3495 ctx = repo[rev]
3495 ctx = repo[rev]
3496 ui.write('%s\n'% ctx2str(ctx))
3496 ui.write('%s\n'% ctx2str(ctx))
3497 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3497 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3498 if succsset:
3498 if succsset:
3499 ui.write(' ')
3499 ui.write(' ')
3500 ui.write(node2str(succsset[0]))
3500 ui.write(node2str(succsset[0]))
3501 for node in succsset[1:]:
3501 for node in succsset[1:]:
3502 ui.write(' ')
3502 ui.write(' ')
3503 ui.write(node2str(node))
3503 ui.write(node2str(node))
3504 ui.write('\n')
3504 ui.write('\n')
3505
3505
3506 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3506 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3507 def debugwalk(ui, repo, *pats, **opts):
3507 def debugwalk(ui, repo, *pats, **opts):
3508 """show how files match on given patterns"""
3508 """show how files match on given patterns"""
3509 m = scmutil.match(repo[None], pats, opts)
3509 m = scmutil.match(repo[None], pats, opts)
3510 items = list(repo.walk(m))
3510 items = list(repo.walk(m))
3511 if not items:
3511 if not items:
3512 return
3512 return
3513 f = lambda fn: fn
3513 f = lambda fn: fn
3514 if ui.configbool('ui', 'slash') and os.sep != '/':
3514 if ui.configbool('ui', 'slash') and os.sep != '/':
3515 f = lambda fn: util.normpath(fn)
3515 f = lambda fn: util.normpath(fn)
3516 fmt = 'f %%-%ds %%-%ds %%s' % (
3516 fmt = 'f %%-%ds %%-%ds %%s' % (
3517 max([len(abs) for abs in items]),
3517 max([len(abs) for abs in items]),
3518 max([len(m.rel(abs)) for abs in items]))
3518 max([len(m.rel(abs)) for abs in items]))
3519 for abs in items:
3519 for abs in items:
3520 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3520 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3521 ui.write("%s\n" % line.rstrip())
3521 ui.write("%s\n" % line.rstrip())
3522
3522
3523 @command('debugwireargs',
3523 @command('debugwireargs',
3524 [('', 'three', '', 'three'),
3524 [('', 'three', '', 'three'),
3525 ('', 'four', '', 'four'),
3525 ('', 'four', '', 'four'),
3526 ('', 'five', '', 'five'),
3526 ('', 'five', '', 'five'),
3527 ] + remoteopts,
3527 ] + remoteopts,
3528 _('REPO [OPTIONS]... [ONE [TWO]]'),
3528 _('REPO [OPTIONS]... [ONE [TWO]]'),
3529 norepo=True)
3529 norepo=True)
3530 def debugwireargs(ui, repopath, *vals, **opts):
3530 def debugwireargs(ui, repopath, *vals, **opts):
3531 repo = hg.peer(ui, opts, repopath)
3531 repo = hg.peer(ui, opts, repopath)
3532 for opt in remoteopts:
3532 for opt in remoteopts:
3533 del opts[opt[1]]
3533 del opts[opt[1]]
3534 args = {}
3534 args = {}
3535 for k, v in opts.iteritems():
3535 for k, v in opts.iteritems():
3536 if v:
3536 if v:
3537 args[k] = v
3537 args[k] = v
3538 # run twice to check that we don't mess up the stream for the next command
3538 # run twice to check that we don't mess up the stream for the next command
3539 res1 = repo.debugwireargs(*vals, **args)
3539 res1 = repo.debugwireargs(*vals, **args)
3540 res2 = repo.debugwireargs(*vals, **args)
3540 res2 = repo.debugwireargs(*vals, **args)
3541 ui.write("%s\n" % res1)
3541 ui.write("%s\n" % res1)
3542 if res1 != res2:
3542 if res1 != res2:
3543 ui.warn("%s\n" % res2)
3543 ui.warn("%s\n" % res2)
3544
3544
3545 @command('^diff',
3545 @command('^diff',
3546 [('r', 'rev', [], _('revision'), _('REV')),
3546 [('r', 'rev', [], _('revision'), _('REV')),
3547 ('c', 'change', '', _('change made by revision'), _('REV'))
3547 ('c', 'change', '', _('change made by revision'), _('REV'))
3548 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3548 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3549 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3549 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3550 inferrepo=True)
3550 inferrepo=True)
3551 def diff(ui, repo, *pats, **opts):
3551 def diff(ui, repo, *pats, **opts):
3552 """diff repository (or selected files)
3552 """diff repository (or selected files)
3553
3553
3554 Show differences between revisions for the specified files.
3554 Show differences between revisions for the specified files.
3555
3555
3556 Differences between files are shown using the unified diff format.
3556 Differences between files are shown using the unified diff format.
3557
3557
3558 .. note::
3558 .. note::
3559
3559
3560 :hg:`diff` may generate unexpected results for merges, as it will
3560 :hg:`diff` may generate unexpected results for merges, as it will
3561 default to comparing against the working directory's first
3561 default to comparing against the working directory's first
3562 parent changeset if no revisions are specified.
3562 parent changeset if no revisions are specified.
3563
3563
3564 When two revision arguments are given, then changes are shown
3564 When two revision arguments are given, then changes are shown
3565 between those revisions. If only one revision is specified then
3565 between those revisions. If only one revision is specified then
3566 that revision is compared to the working directory, and, when no
3566 that revision is compared to the working directory, and, when no
3567 revisions are specified, the working directory files are compared
3567 revisions are specified, the working directory files are compared
3568 to its first parent.
3568 to its first parent.
3569
3569
3570 Alternatively you can specify -c/--change with a revision to see
3570 Alternatively you can specify -c/--change with a revision to see
3571 the changes in that changeset relative to its first parent.
3571 the changes in that changeset relative to its first parent.
3572
3572
3573 Without the -a/--text option, diff will avoid generating diffs of
3573 Without the -a/--text option, diff will avoid generating diffs of
3574 files it detects as binary. With -a, diff will generate a diff
3574 files it detects as binary. With -a, diff will generate a diff
3575 anyway, probably with undesirable results.
3575 anyway, probably with undesirable results.
3576
3576
3577 Use the -g/--git option to generate diffs in the git extended diff
3577 Use the -g/--git option to generate diffs in the git extended diff
3578 format. For more information, read :hg:`help diffs`.
3578 format. For more information, read :hg:`help diffs`.
3579
3579
3580 .. container:: verbose
3580 .. container:: verbose
3581
3581
3582 Examples:
3582 Examples:
3583
3583
3584 - compare a file in the current working directory to its parent::
3584 - compare a file in the current working directory to its parent::
3585
3585
3586 hg diff foo.c
3586 hg diff foo.c
3587
3587
3588 - compare two historical versions of a directory, with rename info::
3588 - compare two historical versions of a directory, with rename info::
3589
3589
3590 hg diff --git -r 1.0:1.2 lib/
3590 hg diff --git -r 1.0:1.2 lib/
3591
3591
3592 - get change stats relative to the last change on some date::
3592 - get change stats relative to the last change on some date::
3593
3593
3594 hg diff --stat -r "date('may 2')"
3594 hg diff --stat -r "date('may 2')"
3595
3595
3596 - diff all newly-added files that contain a keyword::
3596 - diff all newly-added files that contain a keyword::
3597
3597
3598 hg diff "set:added() and grep(GNU)"
3598 hg diff "set:added() and grep(GNU)"
3599
3599
3600 - compare a revision and its parents::
3600 - compare a revision and its parents::
3601
3601
3602 hg diff -c 9353 # compare against first parent
3602 hg diff -c 9353 # compare against first parent
3603 hg diff -r 9353^:9353 # same using revset syntax
3603 hg diff -r 9353^:9353 # same using revset syntax
3604 hg diff -r 9353^2:9353 # compare against the second parent
3604 hg diff -r 9353^2:9353 # compare against the second parent
3605
3605
3606 Returns 0 on success.
3606 Returns 0 on success.
3607 """
3607 """
3608
3608
3609 revs = opts.get('rev')
3609 revs = opts.get('rev')
3610 change = opts.get('change')
3610 change = opts.get('change')
3611 stat = opts.get('stat')
3611 stat = opts.get('stat')
3612 reverse = opts.get('reverse')
3612 reverse = opts.get('reverse')
3613
3613
3614 if revs and change:
3614 if revs and change:
3615 msg = _('cannot specify --rev and --change at the same time')
3615 msg = _('cannot specify --rev and --change at the same time')
3616 raise error.Abort(msg)
3616 raise error.Abort(msg)
3617 elif change:
3617 elif change:
3618 node2 = scmutil.revsingle(repo, change, None).node()
3618 node2 = scmutil.revsingle(repo, change, None).node()
3619 node1 = repo[node2].p1().node()
3619 node1 = repo[node2].p1().node()
3620 else:
3620 else:
3621 node1, node2 = scmutil.revpair(repo, revs)
3621 node1, node2 = scmutil.revpair(repo, revs)
3622
3622
3623 if reverse:
3623 if reverse:
3624 node1, node2 = node2, node1
3624 node1, node2 = node2, node1
3625
3625
3626 diffopts = patch.diffallopts(ui, opts)
3626 diffopts = patch.diffallopts(ui, opts)
3627 m = scmutil.match(repo[node2], pats, opts)
3627 m = scmutil.match(repo[node2], pats, opts)
3628 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3628 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3629 listsubrepos=opts.get('subrepos'),
3629 listsubrepos=opts.get('subrepos'),
3630 root=opts.get('root'))
3630 root=opts.get('root'))
3631
3631
3632 @command('^export',
3632 @command('^export',
3633 [('o', 'output', '',
3633 [('o', 'output', '',
3634 _('print output to file with formatted name'), _('FORMAT')),
3634 _('print output to file with formatted name'), _('FORMAT')),
3635 ('', 'switch-parent', None, _('diff against the second parent')),
3635 ('', 'switch-parent', None, _('diff against the second parent')),
3636 ('r', 'rev', [], _('revisions to export'), _('REV')),
3636 ('r', 'rev', [], _('revisions to export'), _('REV')),
3637 ] + diffopts,
3637 ] + diffopts,
3638 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3638 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3639 def export(ui, repo, *changesets, **opts):
3639 def export(ui, repo, *changesets, **opts):
3640 """dump the header and diffs for one or more changesets
3640 """dump the header and diffs for one or more changesets
3641
3641
3642 Print the changeset header and diffs for one or more revisions.
3642 Print the changeset header and diffs for one or more revisions.
3643 If no revision is given, the parent of the working directory is used.
3643 If no revision is given, the parent of the working directory is used.
3644
3644
3645 The information shown in the changeset header is: author, date,
3645 The information shown in the changeset header is: author, date,
3646 branch name (if non-default), changeset hash, parent(s) and commit
3646 branch name (if non-default), changeset hash, parent(s) and commit
3647 comment.
3647 comment.
3648
3648
3649 .. note::
3649 .. note::
3650
3650
3651 :hg:`export` may generate unexpected diff output for merge
3651 :hg:`export` may generate unexpected diff output for merge
3652 changesets, as it will compare the merge changeset against its
3652 changesets, as it will compare the merge changeset against its
3653 first parent only.
3653 first parent only.
3654
3654
3655 Output may be to a file, in which case the name of the file is
3655 Output may be to a file, in which case the name of the file is
3656 given using a format string. The formatting rules are as follows:
3656 given using a format string. The formatting rules are as follows:
3657
3657
3658 :``%%``: literal "%" character
3658 :``%%``: literal "%" character
3659 :``%H``: changeset hash (40 hexadecimal digits)
3659 :``%H``: changeset hash (40 hexadecimal digits)
3660 :``%N``: number of patches being generated
3660 :``%N``: number of patches being generated
3661 :``%R``: changeset revision number
3661 :``%R``: changeset revision number
3662 :``%b``: basename of the exporting repository
3662 :``%b``: basename of the exporting repository
3663 :``%h``: short-form changeset hash (12 hexadecimal digits)
3663 :``%h``: short-form changeset hash (12 hexadecimal digits)
3664 :``%m``: first line of the commit message (only alphanumeric characters)
3664 :``%m``: first line of the commit message (only alphanumeric characters)
3665 :``%n``: zero-padded sequence number, starting at 1
3665 :``%n``: zero-padded sequence number, starting at 1
3666 :``%r``: zero-padded changeset revision number
3666 :``%r``: zero-padded changeset revision number
3667
3667
3668 Without the -a/--text option, export will avoid generating diffs
3668 Without the -a/--text option, export will avoid generating diffs
3669 of files it detects as binary. With -a, export will generate a
3669 of files it detects as binary. With -a, export will generate a
3670 diff anyway, probably with undesirable results.
3670 diff anyway, probably with undesirable results.
3671
3671
3672 Use the -g/--git option to generate diffs in the git extended diff
3672 Use the -g/--git option to generate diffs in the git extended diff
3673 format. See :hg:`help diffs` for more information.
3673 format. See :hg:`help diffs` for more information.
3674
3674
3675 With the --switch-parent option, the diff will be against the
3675 With the --switch-parent option, the diff will be against the
3676 second parent. It can be useful to review a merge.
3676 second parent. It can be useful to review a merge.
3677
3677
3678 .. container:: verbose
3678 .. container:: verbose
3679
3679
3680 Examples:
3680 Examples:
3681
3681
3682 - use export and import to transplant a bugfix to the current
3682 - use export and import to transplant a bugfix to the current
3683 branch::
3683 branch::
3684
3684
3685 hg export -r 9353 | hg import -
3685 hg export -r 9353 | hg import -
3686
3686
3687 - export all the changesets between two revisions to a file with
3687 - export all the changesets between two revisions to a file with
3688 rename information::
3688 rename information::
3689
3689
3690 hg export --git -r 123:150 > changes.txt
3690 hg export --git -r 123:150 > changes.txt
3691
3691
3692 - split outgoing changes into a series of patches with
3692 - split outgoing changes into a series of patches with
3693 descriptive names::
3693 descriptive names::
3694
3694
3695 hg export -r "outgoing()" -o "%n-%m.patch"
3695 hg export -r "outgoing()" -o "%n-%m.patch"
3696
3696
3697 Returns 0 on success.
3697 Returns 0 on success.
3698 """
3698 """
3699 changesets += tuple(opts.get('rev', []))
3699 changesets += tuple(opts.get('rev', []))
3700 if not changesets:
3700 if not changesets:
3701 changesets = ['.']
3701 changesets = ['.']
3702 revs = scmutil.revrange(repo, changesets)
3702 revs = scmutil.revrange(repo, changesets)
3703 if not revs:
3703 if not revs:
3704 raise error.Abort(_("export requires at least one changeset"))
3704 raise error.Abort(_("export requires at least one changeset"))
3705 if len(revs) > 1:
3705 if len(revs) > 1:
3706 ui.note(_('exporting patches:\n'))
3706 ui.note(_('exporting patches:\n'))
3707 else:
3707 else:
3708 ui.note(_('exporting patch:\n'))
3708 ui.note(_('exporting patch:\n'))
3709 cmdutil.export(repo, revs, template=opts.get('output'),
3709 cmdutil.export(repo, revs, template=opts.get('output'),
3710 switch_parent=opts.get('switch_parent'),
3710 switch_parent=opts.get('switch_parent'),
3711 opts=patch.diffallopts(ui, opts))
3711 opts=patch.diffallopts(ui, opts))
3712
3712
3713 @command('files',
3713 @command('files',
3714 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3714 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3715 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3715 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3716 ] + walkopts + formatteropts + subrepoopts,
3716 ] + walkopts + formatteropts + subrepoopts,
3717 _('[OPTION]... [PATTERN]...'))
3717 _('[OPTION]... [PATTERN]...'))
3718 def files(ui, repo, *pats, **opts):
3718 def files(ui, repo, *pats, **opts):
3719 """list tracked files
3719 """list tracked files
3720
3720
3721 Print files under Mercurial control in the working directory or
3721 Print files under Mercurial control in the working directory or
3722 specified revision whose names match the given patterns (excluding
3722 specified revision whose names match the given patterns (excluding
3723 removed files).
3723 removed files).
3724
3724
3725 If no patterns are given to match, this command prints the names
3725 If no patterns are given to match, this command prints the names
3726 of all files under Mercurial control in the working directory.
3726 of all files under Mercurial control in the working directory.
3727
3727
3728 .. container:: verbose
3728 .. container:: verbose
3729
3729
3730 Examples:
3730 Examples:
3731
3731
3732 - list all files under the current directory::
3732 - list all files under the current directory::
3733
3733
3734 hg files .
3734 hg files .
3735
3735
3736 - shows sizes and flags for current revision::
3736 - shows sizes and flags for current revision::
3737
3737
3738 hg files -vr .
3738 hg files -vr .
3739
3739
3740 - list all files named README::
3740 - list all files named README::
3741
3741
3742 hg files -I "**/README"
3742 hg files -I "**/README"
3743
3743
3744 - list all binary files::
3744 - list all binary files::
3745
3745
3746 hg files "set:binary()"
3746 hg files "set:binary()"
3747
3747
3748 - find files containing a regular expression::
3748 - find files containing a regular expression::
3749
3749
3750 hg files "set:grep('bob')"
3750 hg files "set:grep('bob')"
3751
3751
3752 - search tracked file contents with xargs and grep::
3752 - search tracked file contents with xargs and grep::
3753
3753
3754 hg files -0 | xargs -0 grep foo
3754 hg files -0 | xargs -0 grep foo
3755
3755
3756 See :hg:`help patterns` and :hg:`help filesets` for more information
3756 See :hg:`help patterns` and :hg:`help filesets` for more information
3757 on specifying file patterns.
3757 on specifying file patterns.
3758
3758
3759 Returns 0 if a match is found, 1 otherwise.
3759 Returns 0 if a match is found, 1 otherwise.
3760
3760
3761 """
3761 """
3762 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3762 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3763
3763
3764 end = '\n'
3764 end = '\n'
3765 if opts.get('print0'):
3765 if opts.get('print0'):
3766 end = '\0'
3766 end = '\0'
3767 fm = ui.formatter('files', opts)
3767 fm = ui.formatter('files', opts)
3768 fmt = '%s' + end
3768 fmt = '%s' + end
3769
3769
3770 m = scmutil.match(ctx, pats, opts)
3770 m = scmutil.match(ctx, pats, opts)
3771 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3771 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3772
3772
3773 fm.end()
3773 fm.end()
3774
3774
3775 return ret
3775 return ret
3776
3776
3777 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3777 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3778 def forget(ui, repo, *pats, **opts):
3778 def forget(ui, repo, *pats, **opts):
3779 """forget the specified files on the next commit
3779 """forget the specified files on the next commit
3780
3780
3781 Mark the specified files so they will no longer be tracked
3781 Mark the specified files so they will no longer be tracked
3782 after the next commit.
3782 after the next commit.
3783
3783
3784 This only removes files from the current branch, not from the
3784 This only removes files from the current branch, not from the
3785 entire project history, and it does not delete them from the
3785 entire project history, and it does not delete them from the
3786 working directory.
3786 working directory.
3787
3787
3788 To delete the file from the working directory, see :hg:`remove`.
3788 To delete the file from the working directory, see :hg:`remove`.
3789
3789
3790 To undo a forget before the next commit, see :hg:`add`.
3790 To undo a forget before the next commit, see :hg:`add`.
3791
3791
3792 .. container:: verbose
3792 .. container:: verbose
3793
3793
3794 Examples:
3794 Examples:
3795
3795
3796 - forget newly-added binary files::
3796 - forget newly-added binary files::
3797
3797
3798 hg forget "set:added() and binary()"
3798 hg forget "set:added() and binary()"
3799
3799
3800 - forget files that would be excluded by .hgignore::
3800 - forget files that would be excluded by .hgignore::
3801
3801
3802 hg forget "set:hgignore()"
3802 hg forget "set:hgignore()"
3803
3803
3804 Returns 0 on success.
3804 Returns 0 on success.
3805 """
3805 """
3806
3806
3807 if not pats:
3807 if not pats:
3808 raise error.Abort(_('no files specified'))
3808 raise error.Abort(_('no files specified'))
3809
3809
3810 m = scmutil.match(repo[None], pats, opts)
3810 m = scmutil.match(repo[None], pats, opts)
3811 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3811 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3812 return rejected and 1 or 0
3812 return rejected and 1 or 0
3813
3813
3814 @command(
3814 @command(
3815 'graft',
3815 'graft',
3816 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3816 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3817 ('c', 'continue', False, _('resume interrupted graft')),
3817 ('c', 'continue', False, _('resume interrupted graft')),
3818 ('e', 'edit', False, _('invoke editor on commit messages')),
3818 ('e', 'edit', False, _('invoke editor on commit messages')),
3819 ('', 'log', None, _('append graft info to log message')),
3819 ('', 'log', None, _('append graft info to log message')),
3820 ('f', 'force', False, _('force graft')),
3820 ('f', 'force', False, _('force graft')),
3821 ('D', 'currentdate', False,
3821 ('D', 'currentdate', False,
3822 _('record the current date as commit date')),
3822 _('record the current date as commit date')),
3823 ('U', 'currentuser', False,
3823 ('U', 'currentuser', False,
3824 _('record the current user as committer'), _('DATE'))]
3824 _('record the current user as committer'), _('DATE'))]
3825 + commitopts2 + mergetoolopts + dryrunopts,
3825 + commitopts2 + mergetoolopts + dryrunopts,
3826 _('[OPTION]... [-r] REV...'))
3826 _('[OPTION]... [-r] REV...'))
3827 def graft(ui, repo, *revs, **opts):
3827 def graft(ui, repo, *revs, **opts):
3828 '''copy changes from other branches onto the current branch
3828 '''copy changes from other branches onto the current branch
3829
3829
3830 This command uses Mercurial's merge logic to copy individual
3830 This command uses Mercurial's merge logic to copy individual
3831 changes from other branches without merging branches in the
3831 changes from other branches without merging branches in the
3832 history graph. This is sometimes known as 'backporting' or
3832 history graph. This is sometimes known as 'backporting' or
3833 'cherry-picking'. By default, graft will copy user, date, and
3833 'cherry-picking'. By default, graft will copy user, date, and
3834 description from the source changesets.
3834 description from the source changesets.
3835
3835
3836 Changesets that are ancestors of the current revision, that have
3836 Changesets that are ancestors of the current revision, that have
3837 already been grafted, or that are merges will be skipped.
3837 already been grafted, or that are merges will be skipped.
3838
3838
3839 If --log is specified, log messages will have a comment appended
3839 If --log is specified, log messages will have a comment appended
3840 of the form::
3840 of the form::
3841
3841
3842 (grafted from CHANGESETHASH)
3842 (grafted from CHANGESETHASH)
3843
3843
3844 If --force is specified, revisions will be grafted even if they
3844 If --force is specified, revisions will be grafted even if they
3845 are already ancestors of or have been grafted to the destination.
3845 are already ancestors of or have been grafted to the destination.
3846 This is useful when the revisions have since been backed out.
3846 This is useful when the revisions have since been backed out.
3847
3847
3848 If a graft merge results in conflicts, the graft process is
3848 If a graft merge results in conflicts, the graft process is
3849 interrupted so that the current merge can be manually resolved.
3849 interrupted so that the current merge can be manually resolved.
3850 Once all conflicts are addressed, the graft process can be
3850 Once all conflicts are addressed, the graft process can be
3851 continued with the -c/--continue option.
3851 continued with the -c/--continue option.
3852
3852
3853 .. note::
3853 .. note::
3854
3854
3855 The -c/--continue option does not reapply earlier options, except
3855 The -c/--continue option does not reapply earlier options, except
3856 for --force.
3856 for --force.
3857
3857
3858 .. container:: verbose
3858 .. container:: verbose
3859
3859
3860 Examples:
3860 Examples:
3861
3861
3862 - copy a single change to the stable branch and edit its description::
3862 - copy a single change to the stable branch and edit its description::
3863
3863
3864 hg update stable
3864 hg update stable
3865 hg graft --edit 9393
3865 hg graft --edit 9393
3866
3866
3867 - graft a range of changesets with one exception, updating dates::
3867 - graft a range of changesets with one exception, updating dates::
3868
3868
3869 hg graft -D "2085::2093 and not 2091"
3869 hg graft -D "2085::2093 and not 2091"
3870
3870
3871 - continue a graft after resolving conflicts::
3871 - continue a graft after resolving conflicts::
3872
3872
3873 hg graft -c
3873 hg graft -c
3874
3874
3875 - show the source of a grafted changeset::
3875 - show the source of a grafted changeset::
3876
3876
3877 hg log --debug -r .
3877 hg log --debug -r .
3878
3878
3879 - show revisions sorted by date::
3879 - show revisions sorted by date::
3880
3880
3881 hg log -r 'sort(all(), date)'
3881 hg log -r 'sort(all(), date)'
3882
3882
3883 See :hg:`help revisions` and :hg:`help revsets` for more about
3883 See :hg:`help revisions` and :hg:`help revsets` for more about
3884 specifying revisions.
3884 specifying revisions.
3885
3885
3886 Returns 0 on successful completion.
3886 Returns 0 on successful completion.
3887 '''
3887 '''
3888 wlock = None
3888 wlock = None
3889 try:
3889 try:
3890 wlock = repo.wlock()
3890 wlock = repo.wlock()
3891 return _dograft(ui, repo, *revs, **opts)
3891 return _dograft(ui, repo, *revs, **opts)
3892 finally:
3892 finally:
3893 release(wlock)
3893 release(wlock)
3894
3894
3895 def _dograft(ui, repo, *revs, **opts):
3895 def _dograft(ui, repo, *revs, **opts):
3896 revs = list(revs)
3896 revs = list(revs)
3897 revs.extend(opts['rev'])
3897 revs.extend(opts['rev'])
3898
3898
3899 if not opts.get('user') and opts.get('currentuser'):
3899 if not opts.get('user') and opts.get('currentuser'):
3900 opts['user'] = ui.username()
3900 opts['user'] = ui.username()
3901 if not opts.get('date') and opts.get('currentdate'):
3901 if not opts.get('date') and opts.get('currentdate'):
3902 opts['date'] = "%d %d" % util.makedate()
3902 opts['date'] = "%d %d" % util.makedate()
3903
3903
3904 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3904 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3905
3905
3906 cont = False
3906 cont = False
3907 if opts['continue']:
3907 if opts['continue']:
3908 cont = True
3908 cont = True
3909 if revs:
3909 if revs:
3910 raise error.Abort(_("can't specify --continue and revisions"))
3910 raise error.Abort(_("can't specify --continue and revisions"))
3911 # read in unfinished revisions
3911 # read in unfinished revisions
3912 try:
3912 try:
3913 nodes = repo.vfs.read('graftstate').splitlines()
3913 nodes = repo.vfs.read('graftstate').splitlines()
3914 revs = [repo[node].rev() for node in nodes]
3914 revs = [repo[node].rev() for node in nodes]
3915 except IOError as inst:
3915 except IOError as inst:
3916 if inst.errno != errno.ENOENT:
3916 if inst.errno != errno.ENOENT:
3917 raise
3917 raise
3918 raise error.Abort(_("no graft state found, can't continue"))
3918 raise error.Abort(_("no graft state found, can't continue"))
3919 else:
3919 else:
3920 cmdutil.checkunfinished(repo)
3920 cmdutil.checkunfinished(repo)
3921 cmdutil.bailifchanged(repo)
3921 cmdutil.bailifchanged(repo)
3922 if not revs:
3922 if not revs:
3923 raise error.Abort(_('no revisions specified'))
3923 raise error.Abort(_('no revisions specified'))
3924 revs = scmutil.revrange(repo, revs)
3924 revs = scmutil.revrange(repo, revs)
3925
3925
3926 skipped = set()
3926 skipped = set()
3927 # check for merges
3927 # check for merges
3928 for rev in repo.revs('%ld and merge()', revs):
3928 for rev in repo.revs('%ld and merge()', revs):
3929 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3929 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3930 skipped.add(rev)
3930 skipped.add(rev)
3931 revs = [r for r in revs if r not in skipped]
3931 revs = [r for r in revs if r not in skipped]
3932 if not revs:
3932 if not revs:
3933 return -1
3933 return -1
3934
3934
3935 # Don't check in the --continue case, in effect retaining --force across
3935 # Don't check in the --continue case, in effect retaining --force across
3936 # --continues. That's because without --force, any revisions we decided to
3936 # --continues. That's because without --force, any revisions we decided to
3937 # skip would have been filtered out here, so they wouldn't have made their
3937 # skip would have been filtered out here, so they wouldn't have made their
3938 # way to the graftstate. With --force, any revisions we would have otherwise
3938 # way to the graftstate. With --force, any revisions we would have otherwise
3939 # skipped would not have been filtered out, and if they hadn't been applied
3939 # skipped would not have been filtered out, and if they hadn't been applied
3940 # already, they'd have been in the graftstate.
3940 # already, they'd have been in the graftstate.
3941 if not (cont or opts.get('force')):
3941 if not (cont or opts.get('force')):
3942 # check for ancestors of dest branch
3942 # check for ancestors of dest branch
3943 crev = repo['.'].rev()
3943 crev = repo['.'].rev()
3944 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3944 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3945 # Cannot use x.remove(y) on smart set, this has to be a list.
3945 # Cannot use x.remove(y) on smart set, this has to be a list.
3946 # XXX make this lazy in the future
3946 # XXX make this lazy in the future
3947 revs = list(revs)
3947 revs = list(revs)
3948 # don't mutate while iterating, create a copy
3948 # don't mutate while iterating, create a copy
3949 for rev in list(revs):
3949 for rev in list(revs):
3950 if rev in ancestors:
3950 if rev in ancestors:
3951 ui.warn(_('skipping ancestor revision %d:%s\n') %
3951 ui.warn(_('skipping ancestor revision %d:%s\n') %
3952 (rev, repo[rev]))
3952 (rev, repo[rev]))
3953 # XXX remove on list is slow
3953 # XXX remove on list is slow
3954 revs.remove(rev)
3954 revs.remove(rev)
3955 if not revs:
3955 if not revs:
3956 return -1
3956 return -1
3957
3957
3958 # analyze revs for earlier grafts
3958 # analyze revs for earlier grafts
3959 ids = {}
3959 ids = {}
3960 for ctx in repo.set("%ld", revs):
3960 for ctx in repo.set("%ld", revs):
3961 ids[ctx.hex()] = ctx.rev()
3961 ids[ctx.hex()] = ctx.rev()
3962 n = ctx.extra().get('source')
3962 n = ctx.extra().get('source')
3963 if n:
3963 if n:
3964 ids[n] = ctx.rev()
3964 ids[n] = ctx.rev()
3965
3965
3966 # check ancestors for earlier grafts
3966 # check ancestors for earlier grafts
3967 ui.debug('scanning for duplicate grafts\n')
3967 ui.debug('scanning for duplicate grafts\n')
3968
3968
3969 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3969 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3970 ctx = repo[rev]
3970 ctx = repo[rev]
3971 n = ctx.extra().get('source')
3971 n = ctx.extra().get('source')
3972 if n in ids:
3972 if n in ids:
3973 try:
3973 try:
3974 r = repo[n].rev()
3974 r = repo[n].rev()
3975 except error.RepoLookupError:
3975 except error.RepoLookupError:
3976 r = None
3976 r = None
3977 if r in revs:
3977 if r in revs:
3978 ui.warn(_('skipping revision %d:%s '
3978 ui.warn(_('skipping revision %d:%s '
3979 '(already grafted to %d:%s)\n')
3979 '(already grafted to %d:%s)\n')
3980 % (r, repo[r], rev, ctx))
3980 % (r, repo[r], rev, ctx))
3981 revs.remove(r)
3981 revs.remove(r)
3982 elif ids[n] in revs:
3982 elif ids[n] in revs:
3983 if r is None:
3983 if r is None:
3984 ui.warn(_('skipping already grafted revision %d:%s '
3984 ui.warn(_('skipping already grafted revision %d:%s '
3985 '(%d:%s also has unknown origin %s)\n')
3985 '(%d:%s also has unknown origin %s)\n')
3986 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3986 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3987 else:
3987 else:
3988 ui.warn(_('skipping already grafted revision %d:%s '
3988 ui.warn(_('skipping already grafted revision %d:%s '
3989 '(%d:%s also has origin %d:%s)\n')
3989 '(%d:%s also has origin %d:%s)\n')
3990 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3990 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3991 revs.remove(ids[n])
3991 revs.remove(ids[n])
3992 elif ctx.hex() in ids:
3992 elif ctx.hex() in ids:
3993 r = ids[ctx.hex()]
3993 r = ids[ctx.hex()]
3994 ui.warn(_('skipping already grafted revision %d:%s '
3994 ui.warn(_('skipping already grafted revision %d:%s '
3995 '(was grafted from %d:%s)\n') %
3995 '(was grafted from %d:%s)\n') %
3996 (r, repo[r], rev, ctx))
3996 (r, repo[r], rev, ctx))
3997 revs.remove(r)
3997 revs.remove(r)
3998 if not revs:
3998 if not revs:
3999 return -1
3999 return -1
4000
4000
4001 for pos, ctx in enumerate(repo.set("%ld", revs)):
4001 for pos, ctx in enumerate(repo.set("%ld", revs)):
4002 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4002 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
4003 ctx.description().split('\n', 1)[0])
4003 ctx.description().split('\n', 1)[0])
4004 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4004 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
4005 if names:
4005 if names:
4006 desc += ' (%s)' % ' '.join(names)
4006 desc += ' (%s)' % ' '.join(names)
4007 ui.status(_('grafting %s\n') % desc)
4007 ui.status(_('grafting %s\n') % desc)
4008 if opts.get('dry_run'):
4008 if opts.get('dry_run'):
4009 continue
4009 continue
4010
4010
4011 extra = ctx.extra().copy()
4011 extra = ctx.extra().copy()
4012 del extra['branch']
4012 del extra['branch']
4013 source = extra.get('source')
4013 source = extra.get('source')
4014 if source:
4014 if source:
4015 extra['intermediate-source'] = ctx.hex()
4015 extra['intermediate-source'] = ctx.hex()
4016 else:
4016 else:
4017 extra['source'] = ctx.hex()
4017 extra['source'] = ctx.hex()
4018 user = ctx.user()
4018 user = ctx.user()
4019 if opts.get('user'):
4019 if opts.get('user'):
4020 user = opts['user']
4020 user = opts['user']
4021 date = ctx.date()
4021 date = ctx.date()
4022 if opts.get('date'):
4022 if opts.get('date'):
4023 date = opts['date']
4023 date = opts['date']
4024 message = ctx.description()
4024 message = ctx.description()
4025 if opts.get('log'):
4025 if opts.get('log'):
4026 message += '\n(grafted from %s)' % ctx.hex()
4026 message += '\n(grafted from %s)' % ctx.hex()
4027
4027
4028 # we don't merge the first commit when continuing
4028 # we don't merge the first commit when continuing
4029 if not cont:
4029 if not cont:
4030 # perform the graft merge with p1(rev) as 'ancestor'
4030 # perform the graft merge with p1(rev) as 'ancestor'
4031 try:
4031 try:
4032 # ui.forcemerge is an internal variable, do not document
4032 # ui.forcemerge is an internal variable, do not document
4033 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4033 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4034 'graft')
4034 'graft')
4035 stats = mergemod.graft(repo, ctx, ctx.p1(),
4035 stats = mergemod.graft(repo, ctx, ctx.p1(),
4036 ['local', 'graft'])
4036 ['local', 'graft'])
4037 finally:
4037 finally:
4038 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4038 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4039 # report any conflicts
4039 # report any conflicts
4040 if stats and stats[3] > 0:
4040 if stats and stats[3] > 0:
4041 # write out state for --continue
4041 # write out state for --continue
4042 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4042 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4043 repo.vfs.write('graftstate', ''.join(nodelines))
4043 repo.vfs.write('graftstate', ''.join(nodelines))
4044 extra = ''
4044 extra = ''
4045 if opts.get('user'):
4045 if opts.get('user'):
4046 extra += ' --user %s' % opts['user']
4046 extra += ' --user %s' % opts['user']
4047 if opts.get('date'):
4047 if opts.get('date'):
4048 extra += ' --date %s' % opts['date']
4048 extra += ' --date %s' % opts['date']
4049 if opts.get('log'):
4049 if opts.get('log'):
4050 extra += ' --log'
4050 extra += ' --log'
4051 hint=_('use hg resolve and hg graft --continue%s') % extra
4051 hint=_('use hg resolve and hg graft --continue%s') % extra
4052 raise error.Abort(
4052 raise error.Abort(
4053 _("unresolved conflicts, can't continue"),
4053 _("unresolved conflicts, can't continue"),
4054 hint=hint)
4054 hint=hint)
4055 else:
4055 else:
4056 cont = False
4056 cont = False
4057
4057
4058 # commit
4058 # commit
4059 node = repo.commit(text=message, user=user,
4059 node = repo.commit(text=message, user=user,
4060 date=date, extra=extra, editor=editor)
4060 date=date, extra=extra, editor=editor)
4061 if node is None:
4061 if node is None:
4062 ui.warn(
4062 ui.warn(
4063 _('note: graft of %d:%s created no changes to commit\n') %
4063 _('note: graft of %d:%s created no changes to commit\n') %
4064 (ctx.rev(), ctx))
4064 (ctx.rev(), ctx))
4065
4065
4066 # remove state when we complete successfully
4066 # remove state when we complete successfully
4067 if not opts.get('dry_run'):
4067 if not opts.get('dry_run'):
4068 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4068 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4069
4069
4070 return 0
4070 return 0
4071
4071
4072 @command('grep',
4072 @command('grep',
4073 [('0', 'print0', None, _('end fields with NUL')),
4073 [('0', 'print0', None, _('end fields with NUL')),
4074 ('', 'all', None, _('print all revisions that match')),
4074 ('', 'all', None, _('print all revisions that match')),
4075 ('a', 'text', None, _('treat all files as text')),
4075 ('a', 'text', None, _('treat all files as text')),
4076 ('f', 'follow', None,
4076 ('f', 'follow', None,
4077 _('follow changeset history,'
4077 _('follow changeset history,'
4078 ' or file history across copies and renames')),
4078 ' or file history across copies and renames')),
4079 ('i', 'ignore-case', None, _('ignore case when matching')),
4079 ('i', 'ignore-case', None, _('ignore case when matching')),
4080 ('l', 'files-with-matches', None,
4080 ('l', 'files-with-matches', None,
4081 _('print only filenames and revisions that match')),
4081 _('print only filenames and revisions that match')),
4082 ('n', 'line-number', None, _('print matching line numbers')),
4082 ('n', 'line-number', None, _('print matching line numbers')),
4083 ('r', 'rev', [],
4083 ('r', 'rev', [],
4084 _('only search files changed within revision range'), _('REV')),
4084 _('only search files changed within revision range'), _('REV')),
4085 ('u', 'user', None, _('list the author (long with -v)')),
4085 ('u', 'user', None, _('list the author (long with -v)')),
4086 ('d', 'date', None, _('list the date (short with -q)')),
4086 ('d', 'date', None, _('list the date (short with -q)')),
4087 ] + walkopts,
4087 ] + walkopts,
4088 _('[OPTION]... PATTERN [FILE]...'),
4088 _('[OPTION]... PATTERN [FILE]...'),
4089 inferrepo=True)
4089 inferrepo=True)
4090 def grep(ui, repo, pattern, *pats, **opts):
4090 def grep(ui, repo, pattern, *pats, **opts):
4091 """search for a pattern in specified files and revisions
4091 """search for a pattern in specified files and revisions
4092
4092
4093 Search revisions of files for a regular expression.
4093 Search revisions of files for a regular expression.
4094
4094
4095 This command behaves differently than Unix grep. It only accepts
4095 This command behaves differently than Unix grep. It only accepts
4096 Python/Perl regexps. It searches repository history, not the
4096 Python/Perl regexps. It searches repository history, not the
4097 working directory. It always prints the revision number in which a
4097 working directory. It always prints the revision number in which a
4098 match appears.
4098 match appears.
4099
4099
4100 By default, grep only prints output for the first revision of a
4100 By default, grep only prints output for the first revision of a
4101 file in which it finds a match. To get it to print every revision
4101 file in which it finds a match. To get it to print every revision
4102 that contains a change in match status ("-" for a match that
4102 that contains a change in match status ("-" for a match that
4103 becomes a non-match, or "+" for a non-match that becomes a match),
4103 becomes a non-match, or "+" for a non-match that becomes a match),
4104 use the --all flag.
4104 use the --all flag.
4105
4105
4106 Returns 0 if a match is found, 1 otherwise.
4106 Returns 0 if a match is found, 1 otherwise.
4107 """
4107 """
4108 reflags = re.M
4108 reflags = re.M
4109 if opts.get('ignore_case'):
4109 if opts.get('ignore_case'):
4110 reflags |= re.I
4110 reflags |= re.I
4111 try:
4111 try:
4112 regexp = util.re.compile(pattern, reflags)
4112 regexp = util.re.compile(pattern, reflags)
4113 except re.error as inst:
4113 except re.error as inst:
4114 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4114 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4115 return 1
4115 return 1
4116 sep, eol = ':', '\n'
4116 sep, eol = ':', '\n'
4117 if opts.get('print0'):
4117 if opts.get('print0'):
4118 sep = eol = '\0'
4118 sep = eol = '\0'
4119
4119
4120 getfile = util.lrucachefunc(repo.file)
4120 getfile = util.lrucachefunc(repo.file)
4121
4121
4122 def matchlines(body):
4122 def matchlines(body):
4123 begin = 0
4123 begin = 0
4124 linenum = 0
4124 linenum = 0
4125 while begin < len(body):
4125 while begin < len(body):
4126 match = regexp.search(body, begin)
4126 match = regexp.search(body, begin)
4127 if not match:
4127 if not match:
4128 break
4128 break
4129 mstart, mend = match.span()
4129 mstart, mend = match.span()
4130 linenum += body.count('\n', begin, mstart) + 1
4130 linenum += body.count('\n', begin, mstart) + 1
4131 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4131 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4132 begin = body.find('\n', mend) + 1 or len(body) + 1
4132 begin = body.find('\n', mend) + 1 or len(body) + 1
4133 lend = begin - 1
4133 lend = begin - 1
4134 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4134 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4135
4135
4136 class linestate(object):
4136 class linestate(object):
4137 def __init__(self, line, linenum, colstart, colend):
4137 def __init__(self, line, linenum, colstart, colend):
4138 self.line = line
4138 self.line = line
4139 self.linenum = linenum
4139 self.linenum = linenum
4140 self.colstart = colstart
4140 self.colstart = colstart
4141 self.colend = colend
4141 self.colend = colend
4142
4142
4143 def __hash__(self):
4143 def __hash__(self):
4144 return hash((self.linenum, self.line))
4144 return hash((self.linenum, self.line))
4145
4145
4146 def __eq__(self, other):
4146 def __eq__(self, other):
4147 return self.line == other.line
4147 return self.line == other.line
4148
4148
4149 def __iter__(self):
4149 def __iter__(self):
4150 yield (self.line[:self.colstart], '')
4150 yield (self.line[:self.colstart], '')
4151 yield (self.line[self.colstart:self.colend], 'grep.match')
4151 yield (self.line[self.colstart:self.colend], 'grep.match')
4152 rest = self.line[self.colend:]
4152 rest = self.line[self.colend:]
4153 while rest != '':
4153 while rest != '':
4154 match = regexp.search(rest)
4154 match = regexp.search(rest)
4155 if not match:
4155 if not match:
4156 yield (rest, '')
4156 yield (rest, '')
4157 break
4157 break
4158 mstart, mend = match.span()
4158 mstart, mend = match.span()
4159 yield (rest[:mstart], '')
4159 yield (rest[:mstart], '')
4160 yield (rest[mstart:mend], 'grep.match')
4160 yield (rest[mstart:mend], 'grep.match')
4161 rest = rest[mend:]
4161 rest = rest[mend:]
4162
4162
4163 matches = {}
4163 matches = {}
4164 copies = {}
4164 copies = {}
4165 def grepbody(fn, rev, body):
4165 def grepbody(fn, rev, body):
4166 matches[rev].setdefault(fn, [])
4166 matches[rev].setdefault(fn, [])
4167 m = matches[rev][fn]
4167 m = matches[rev][fn]
4168 for lnum, cstart, cend, line in matchlines(body):
4168 for lnum, cstart, cend, line in matchlines(body):
4169 s = linestate(line, lnum, cstart, cend)
4169 s = linestate(line, lnum, cstart, cend)
4170 m.append(s)
4170 m.append(s)
4171
4171
4172 def difflinestates(a, b):
4172 def difflinestates(a, b):
4173 sm = difflib.SequenceMatcher(None, a, b)
4173 sm = difflib.SequenceMatcher(None, a, b)
4174 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4174 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4175 if tag == 'insert':
4175 if tag == 'insert':
4176 for i in xrange(blo, bhi):
4176 for i in xrange(blo, bhi):
4177 yield ('+', b[i])
4177 yield ('+', b[i])
4178 elif tag == 'delete':
4178 elif tag == 'delete':
4179 for i in xrange(alo, ahi):
4179 for i in xrange(alo, ahi):
4180 yield ('-', a[i])
4180 yield ('-', a[i])
4181 elif tag == 'replace':
4181 elif tag == 'replace':
4182 for i in xrange(alo, ahi):
4182 for i in xrange(alo, ahi):
4183 yield ('-', a[i])
4183 yield ('-', a[i])
4184 for i in xrange(blo, bhi):
4184 for i in xrange(blo, bhi):
4185 yield ('+', b[i])
4185 yield ('+', b[i])
4186
4186
4187 def display(fn, ctx, pstates, states):
4187 def display(fn, ctx, pstates, states):
4188 rev = ctx.rev()
4188 rev = ctx.rev()
4189 if ui.quiet:
4189 if ui.quiet:
4190 datefunc = util.shortdate
4190 datefunc = util.shortdate
4191 else:
4191 else:
4192 datefunc = util.datestr
4192 datefunc = util.datestr
4193 found = False
4193 found = False
4194 @util.cachefunc
4194 @util.cachefunc
4195 def binary():
4195 def binary():
4196 flog = getfile(fn)
4196 flog = getfile(fn)
4197 return util.binary(flog.read(ctx.filenode(fn)))
4197 return util.binary(flog.read(ctx.filenode(fn)))
4198
4198
4199 if opts.get('all'):
4199 if opts.get('all'):
4200 iter = difflinestates(pstates, states)
4200 iter = difflinestates(pstates, states)
4201 else:
4201 else:
4202 iter = [('', l) for l in states]
4202 iter = [('', l) for l in states]
4203 for change, l in iter:
4203 for change, l in iter:
4204 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4204 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4205
4205
4206 if opts.get('line_number'):
4206 if opts.get('line_number'):
4207 cols.append((str(l.linenum), 'grep.linenumber'))
4207 cols.append((str(l.linenum), 'grep.linenumber'))
4208 if opts.get('all'):
4208 if opts.get('all'):
4209 cols.append((change, 'grep.change'))
4209 cols.append((change, 'grep.change'))
4210 if opts.get('user'):
4210 if opts.get('user'):
4211 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4211 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4212 if opts.get('date'):
4212 if opts.get('date'):
4213 cols.append((datefunc(ctx.date()), 'grep.date'))
4213 cols.append((datefunc(ctx.date()), 'grep.date'))
4214 for col, label in cols[:-1]:
4214 for col, label in cols[:-1]:
4215 ui.write(col, label=label)
4215 ui.write(col, label=label)
4216 ui.write(sep, label='grep.sep')
4216 ui.write(sep, label='grep.sep')
4217 ui.write(cols[-1][0], label=cols[-1][1])
4217 ui.write(cols[-1][0], label=cols[-1][1])
4218 if not opts.get('files_with_matches'):
4218 if not opts.get('files_with_matches'):
4219 ui.write(sep, label='grep.sep')
4219 ui.write(sep, label='grep.sep')
4220 if not opts.get('text') and binary():
4220 if not opts.get('text') and binary():
4221 ui.write(" Binary file matches")
4221 ui.write(" Binary file matches")
4222 else:
4222 else:
4223 for s, label in l:
4223 for s, label in l:
4224 ui.write(s, label=label)
4224 ui.write(s, label=label)
4225 ui.write(eol)
4225 ui.write(eol)
4226 found = True
4226 found = True
4227 if opts.get('files_with_matches'):
4227 if opts.get('files_with_matches'):
4228 break
4228 break
4229 return found
4229 return found
4230
4230
4231 skip = {}
4231 skip = {}
4232 revfiles = {}
4232 revfiles = {}
4233 matchfn = scmutil.match(repo[None], pats, opts)
4233 matchfn = scmutil.match(repo[None], pats, opts)
4234 found = False
4234 found = False
4235 follow = opts.get('follow')
4235 follow = opts.get('follow')
4236
4236
4237 def prep(ctx, fns):
4237 def prep(ctx, fns):
4238 rev = ctx.rev()
4238 rev = ctx.rev()
4239 pctx = ctx.p1()
4239 pctx = ctx.p1()
4240 parent = pctx.rev()
4240 parent = pctx.rev()
4241 matches.setdefault(rev, {})
4241 matches.setdefault(rev, {})
4242 matches.setdefault(parent, {})
4242 matches.setdefault(parent, {})
4243 files = revfiles.setdefault(rev, [])
4243 files = revfiles.setdefault(rev, [])
4244 for fn in fns:
4244 for fn in fns:
4245 flog = getfile(fn)
4245 flog = getfile(fn)
4246 try:
4246 try:
4247 fnode = ctx.filenode(fn)
4247 fnode = ctx.filenode(fn)
4248 except error.LookupError:
4248 except error.LookupError:
4249 continue
4249 continue
4250
4250
4251 copied = flog.renamed(fnode)
4251 copied = flog.renamed(fnode)
4252 copy = follow and copied and copied[0]
4252 copy = follow and copied and copied[0]
4253 if copy:
4253 if copy:
4254 copies.setdefault(rev, {})[fn] = copy
4254 copies.setdefault(rev, {})[fn] = copy
4255 if fn in skip:
4255 if fn in skip:
4256 if copy:
4256 if copy:
4257 skip[copy] = True
4257 skip[copy] = True
4258 continue
4258 continue
4259 files.append(fn)
4259 files.append(fn)
4260
4260
4261 if fn not in matches[rev]:
4261 if fn not in matches[rev]:
4262 grepbody(fn, rev, flog.read(fnode))
4262 grepbody(fn, rev, flog.read(fnode))
4263
4263
4264 pfn = copy or fn
4264 pfn = copy or fn
4265 if pfn not in matches[parent]:
4265 if pfn not in matches[parent]:
4266 try:
4266 try:
4267 fnode = pctx.filenode(pfn)
4267 fnode = pctx.filenode(pfn)
4268 grepbody(pfn, parent, flog.read(fnode))
4268 grepbody(pfn, parent, flog.read(fnode))
4269 except error.LookupError:
4269 except error.LookupError:
4270 pass
4270 pass
4271
4271
4272 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4272 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4273 rev = ctx.rev()
4273 rev = ctx.rev()
4274 parent = ctx.p1().rev()
4274 parent = ctx.p1().rev()
4275 for fn in sorted(revfiles.get(rev, [])):
4275 for fn in sorted(revfiles.get(rev, [])):
4276 states = matches[rev][fn]
4276 states = matches[rev][fn]
4277 copy = copies.get(rev, {}).get(fn)
4277 copy = copies.get(rev, {}).get(fn)
4278 if fn in skip:
4278 if fn in skip:
4279 if copy:
4279 if copy:
4280 skip[copy] = True
4280 skip[copy] = True
4281 continue
4281 continue
4282 pstates = matches.get(parent, {}).get(copy or fn, [])
4282 pstates = matches.get(parent, {}).get(copy or fn, [])
4283 if pstates or states:
4283 if pstates or states:
4284 r = display(fn, ctx, pstates, states)
4284 r = display(fn, ctx, pstates, states)
4285 found = found or r
4285 found = found or r
4286 if r and not opts.get('all'):
4286 if r and not opts.get('all'):
4287 skip[fn] = True
4287 skip[fn] = True
4288 if copy:
4288 if copy:
4289 skip[copy] = True
4289 skip[copy] = True
4290 del matches[rev]
4290 del matches[rev]
4291 del revfiles[rev]
4291 del revfiles[rev]
4292
4292
4293 return not found
4293 return not found
4294
4294
4295 @command('heads',
4295 @command('heads',
4296 [('r', 'rev', '',
4296 [('r', 'rev', '',
4297 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4297 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4298 ('t', 'topo', False, _('show topological heads only')),
4298 ('t', 'topo', False, _('show topological heads only')),
4299 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4299 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4300 ('c', 'closed', False, _('show normal and closed branch heads')),
4300 ('c', 'closed', False, _('show normal and closed branch heads')),
4301 ] + templateopts,
4301 ] + templateopts,
4302 _('[-ct] [-r STARTREV] [REV]...'))
4302 _('[-ct] [-r STARTREV] [REV]...'))
4303 def heads(ui, repo, *branchrevs, **opts):
4303 def heads(ui, repo, *branchrevs, **opts):
4304 """show branch heads
4304 """show branch heads
4305
4305
4306 With no arguments, show all open branch heads in the repository.
4306 With no arguments, show all open branch heads in the repository.
4307 Branch heads are changesets that have no descendants on the
4307 Branch heads are changesets that have no descendants on the
4308 same branch. They are where development generally takes place and
4308 same branch. They are where development generally takes place and
4309 are the usual targets for update and merge operations.
4309 are the usual targets for update and merge operations.
4310
4310
4311 If one or more REVs are given, only open branch heads on the
4311 If one or more REVs are given, only open branch heads on the
4312 branches associated with the specified changesets are shown. This
4312 branches associated with the specified changesets are shown. This
4313 means that you can use :hg:`heads .` to see the heads on the
4313 means that you can use :hg:`heads .` to see the heads on the
4314 currently checked-out branch.
4314 currently checked-out branch.
4315
4315
4316 If -c/--closed is specified, also show branch heads marked closed
4316 If -c/--closed is specified, also show branch heads marked closed
4317 (see :hg:`commit --close-branch`).
4317 (see :hg:`commit --close-branch`).
4318
4318
4319 If STARTREV is specified, only those heads that are descendants of
4319 If STARTREV is specified, only those heads that are descendants of
4320 STARTREV will be displayed.
4320 STARTREV will be displayed.
4321
4321
4322 If -t/--topo is specified, named branch mechanics will be ignored and only
4322 If -t/--topo is specified, named branch mechanics will be ignored and only
4323 topological heads (changesets with no children) will be shown.
4323 topological heads (changesets with no children) will be shown.
4324
4324
4325 Returns 0 if matching heads are found, 1 if not.
4325 Returns 0 if matching heads are found, 1 if not.
4326 """
4326 """
4327
4327
4328 start = None
4328 start = None
4329 if 'rev' in opts:
4329 if 'rev' in opts:
4330 start = scmutil.revsingle(repo, opts['rev'], None).node()
4330 start = scmutil.revsingle(repo, opts['rev'], None).node()
4331
4331
4332 if opts.get('topo'):
4332 if opts.get('topo'):
4333 heads = [repo[h] for h in repo.heads(start)]
4333 heads = [repo[h] for h in repo.heads(start)]
4334 else:
4334 else:
4335 heads = []
4335 heads = []
4336 for branch in repo.branchmap():
4336 for branch in repo.branchmap():
4337 heads += repo.branchheads(branch, start, opts.get('closed'))
4337 heads += repo.branchheads(branch, start, opts.get('closed'))
4338 heads = [repo[h] for h in heads]
4338 heads = [repo[h] for h in heads]
4339
4339
4340 if branchrevs:
4340 if branchrevs:
4341 branches = set(repo[br].branch() for br in branchrevs)
4341 branches = set(repo[br].branch() for br in branchrevs)
4342 heads = [h for h in heads if h.branch() in branches]
4342 heads = [h for h in heads if h.branch() in branches]
4343
4343
4344 if opts.get('active') and branchrevs:
4344 if opts.get('active') and branchrevs:
4345 dagheads = repo.heads(start)
4345 dagheads = repo.heads(start)
4346 heads = [h for h in heads if h.node() in dagheads]
4346 heads = [h for h in heads if h.node() in dagheads]
4347
4347
4348 if branchrevs:
4348 if branchrevs:
4349 haveheads = set(h.branch() for h in heads)
4349 haveheads = set(h.branch() for h in heads)
4350 if branches - haveheads:
4350 if branches - haveheads:
4351 headless = ', '.join(b for b in branches - haveheads)
4351 headless = ', '.join(b for b in branches - haveheads)
4352 msg = _('no open branch heads found on branches %s')
4352 msg = _('no open branch heads found on branches %s')
4353 if opts.get('rev'):
4353 if opts.get('rev'):
4354 msg += _(' (started at %s)') % opts['rev']
4354 msg += _(' (started at %s)') % opts['rev']
4355 ui.warn((msg + '\n') % headless)
4355 ui.warn((msg + '\n') % headless)
4356
4356
4357 if not heads:
4357 if not heads:
4358 return 1
4358 return 1
4359
4359
4360 heads = sorted(heads, key=lambda x: -x.rev())
4360 heads = sorted(heads, key=lambda x: -x.rev())
4361 displayer = cmdutil.show_changeset(ui, repo, opts)
4361 displayer = cmdutil.show_changeset(ui, repo, opts)
4362 for ctx in heads:
4362 for ctx in heads:
4363 displayer.show(ctx)
4363 displayer.show(ctx)
4364 displayer.close()
4364 displayer.close()
4365
4365
4366 @command('help',
4366 @command('help',
4367 [('e', 'extension', None, _('show only help for extensions')),
4367 [('e', 'extension', None, _('show only help for extensions')),
4368 ('c', 'command', None, _('show only help for commands')),
4368 ('c', 'command', None, _('show only help for commands')),
4369 ('k', 'keyword', None, _('show topics matching keyword')),
4369 ('k', 'keyword', None, _('show topics matching keyword')),
4370 ],
4370 ],
4371 _('[-eck] [TOPIC]'),
4371 _('[-eck] [TOPIC]'),
4372 norepo=True)
4372 norepo=True)
4373 def help_(ui, name=None, **opts):
4373 def help_(ui, name=None, **opts):
4374 """show help for a given topic or a help overview
4374 """show help for a given topic or a help overview
4375
4375
4376 With no arguments, print a list of commands with short help messages.
4376 With no arguments, print a list of commands with short help messages.
4377
4377
4378 Given a topic, extension, or command name, print help for that
4378 Given a topic, extension, or command name, print help for that
4379 topic.
4379 topic.
4380
4380
4381 Returns 0 if successful.
4381 Returns 0 if successful.
4382 """
4382 """
4383
4383
4384 textwidth = min(ui.termwidth(), 80) - 2
4384 textwidth = min(ui.termwidth(), 80) - 2
4385
4385
4386 keep = []
4386 keep = []
4387 if ui.verbose:
4387 if ui.verbose:
4388 keep.append('verbose')
4388 keep.append('verbose')
4389 if sys.platform.startswith('win'):
4389 if sys.platform.startswith('win'):
4390 keep.append('windows')
4390 keep.append('windows')
4391 elif sys.platform == 'OpenVMS':
4391 elif sys.platform == 'OpenVMS':
4392 keep.append('vms')
4392 keep.append('vms')
4393 elif sys.platform == 'plan9':
4393 elif sys.platform == 'plan9':
4394 keep.append('plan9')
4394 keep.append('plan9')
4395 else:
4395 else:
4396 keep.append('unix')
4396 keep.append('unix')
4397 keep.append(sys.platform.lower())
4397 keep.append(sys.platform.lower())
4398
4398
4399 section = None
4399 section = None
4400 subtopic = None
4400 subtopic = None
4401 if name and '.' in name:
4401 if name and '.' in name:
4402 name, section = name.split('.', 1)
4402 name, section = name.split('.', 1)
4403 section = section.lower()
4403 section = section.lower()
4404 if '.' in section:
4404 if '.' in section:
4405 subtopic, section = section.split('.', 1)
4405 subtopic, section = section.split('.', 1)
4406 else:
4406 else:
4407 subtopic = section
4407 subtopic = section
4408
4408
4409 text = help.help_(ui, name, subtopic=subtopic, **opts)
4409 text = help.help_(ui, name, subtopic=subtopic, **opts)
4410
4410
4411 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4411 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4412 section=section)
4412 section=section)
4413
4413
4414 # We could have been given a weird ".foo" section without a name
4414 # We could have been given a weird ".foo" section without a name
4415 # to look for, or we could have simply failed to found "foo.bar"
4415 # to look for, or we could have simply failed to found "foo.bar"
4416 # because bar isn't a section of foo
4416 # because bar isn't a section of foo
4417 if section and not (formatted and name):
4417 if section and not (formatted and name):
4418 raise error.Abort(_("help section not found"))
4418 raise error.Abort(_("help section not found"))
4419
4419
4420 if 'verbose' in pruned:
4420 if 'verbose' in pruned:
4421 keep.append('omitted')
4421 keep.append('omitted')
4422 else:
4422 else:
4423 keep.append('notomitted')
4423 keep.append('notomitted')
4424 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4424 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4425 section=section)
4425 section=section)
4426 ui.write(formatted)
4426 ui.write(formatted)
4427
4427
4428
4428
4429 @command('identify|id',
4429 @command('identify|id',
4430 [('r', 'rev', '',
4430 [('r', 'rev', '',
4431 _('identify the specified revision'), _('REV')),
4431 _('identify the specified revision'), _('REV')),
4432 ('n', 'num', None, _('show local revision number')),
4432 ('n', 'num', None, _('show local revision number')),
4433 ('i', 'id', None, _('show global revision id')),
4433 ('i', 'id', None, _('show global revision id')),
4434 ('b', 'branch', None, _('show branch')),
4434 ('b', 'branch', None, _('show branch')),
4435 ('t', 'tags', None, _('show tags')),
4435 ('t', 'tags', None, _('show tags')),
4436 ('B', 'bookmarks', None, _('show bookmarks')),
4436 ('B', 'bookmarks', None, _('show bookmarks')),
4437 ] + remoteopts,
4437 ] + remoteopts,
4438 _('[-nibtB] [-r REV] [SOURCE]'),
4438 _('[-nibtB] [-r REV] [SOURCE]'),
4439 optionalrepo=True)
4439 optionalrepo=True)
4440 def identify(ui, repo, source=None, rev=None,
4440 def identify(ui, repo, source=None, rev=None,
4441 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4441 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4442 """identify the working directory or specified revision
4442 """identify the working directory or specified revision
4443
4443
4444 Print a summary identifying the repository state at REV using one or
4444 Print a summary identifying the repository state at REV using one or
4445 two parent hash identifiers, followed by a "+" if the working
4445 two parent hash identifiers, followed by a "+" if the working
4446 directory has uncommitted changes, the branch name (if not default),
4446 directory has uncommitted changes, the branch name (if not default),
4447 a list of tags, and a list of bookmarks.
4447 a list of tags, and a list of bookmarks.
4448
4448
4449 When REV is not given, print a summary of the current state of the
4449 When REV is not given, print a summary of the current state of the
4450 repository.
4450 repository.
4451
4451
4452 Specifying a path to a repository root or Mercurial bundle will
4452 Specifying a path to a repository root or Mercurial bundle will
4453 cause lookup to operate on that repository/bundle.
4453 cause lookup to operate on that repository/bundle.
4454
4454
4455 .. container:: verbose
4455 .. container:: verbose
4456
4456
4457 Examples:
4457 Examples:
4458
4458
4459 - generate a build identifier for the working directory::
4459 - generate a build identifier for the working directory::
4460
4460
4461 hg id --id > build-id.dat
4461 hg id --id > build-id.dat
4462
4462
4463 - find the revision corresponding to a tag::
4463 - find the revision corresponding to a tag::
4464
4464
4465 hg id -n -r 1.3
4465 hg id -n -r 1.3
4466
4466
4467 - check the most recent revision of a remote repository::
4467 - check the most recent revision of a remote repository::
4468
4468
4469 hg id -r tip http://selenic.com/hg/
4469 hg id -r tip http://selenic.com/hg/
4470
4470
4471 See :hg:`log` for generating more information about specific revisions,
4471 See :hg:`log` for generating more information about specific revisions,
4472 including full hash identifiers.
4472 including full hash identifiers.
4473
4473
4474 Returns 0 if successful.
4474 Returns 0 if successful.
4475 """
4475 """
4476
4476
4477 if not repo and not source:
4477 if not repo and not source:
4478 raise error.Abort(_("there is no Mercurial repository here "
4478 raise error.Abort(_("there is no Mercurial repository here "
4479 "(.hg not found)"))
4479 "(.hg not found)"))
4480
4480
4481 if ui.debugflag:
4481 if ui.debugflag:
4482 hexfunc = hex
4482 hexfunc = hex
4483 else:
4483 else:
4484 hexfunc = short
4484 hexfunc = short
4485 default = not (num or id or branch or tags or bookmarks)
4485 default = not (num or id or branch or tags or bookmarks)
4486 output = []
4486 output = []
4487 revs = []
4487 revs = []
4488
4488
4489 if source:
4489 if source:
4490 source, branches = hg.parseurl(ui.expandpath(source))
4490 source, branches = hg.parseurl(ui.expandpath(source))
4491 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4491 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4492 repo = peer.local()
4492 repo = peer.local()
4493 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4493 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4494
4494
4495 if not repo:
4495 if not repo:
4496 if num or branch or tags:
4496 if num or branch or tags:
4497 raise error.Abort(
4497 raise error.Abort(
4498 _("can't query remote revision number, branch, or tags"))
4498 _("can't query remote revision number, branch, or tags"))
4499 if not rev and revs:
4499 if not rev and revs:
4500 rev = revs[0]
4500 rev = revs[0]
4501 if not rev:
4501 if not rev:
4502 rev = "tip"
4502 rev = "tip"
4503
4503
4504 remoterev = peer.lookup(rev)
4504 remoterev = peer.lookup(rev)
4505 if default or id:
4505 if default or id:
4506 output = [hexfunc(remoterev)]
4506 output = [hexfunc(remoterev)]
4507
4507
4508 def getbms():
4508 def getbms():
4509 bms = []
4509 bms = []
4510
4510
4511 if 'bookmarks' in peer.listkeys('namespaces'):
4511 if 'bookmarks' in peer.listkeys('namespaces'):
4512 hexremoterev = hex(remoterev)
4512 hexremoterev = hex(remoterev)
4513 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4513 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4514 if bmr == hexremoterev]
4514 if bmr == hexremoterev]
4515
4515
4516 return sorted(bms)
4516 return sorted(bms)
4517
4517
4518 if bookmarks:
4518 if bookmarks:
4519 output.extend(getbms())
4519 output.extend(getbms())
4520 elif default and not ui.quiet:
4520 elif default and not ui.quiet:
4521 # multiple bookmarks for a single parent separated by '/'
4521 # multiple bookmarks for a single parent separated by '/'
4522 bm = '/'.join(getbms())
4522 bm = '/'.join(getbms())
4523 if bm:
4523 if bm:
4524 output.append(bm)
4524 output.append(bm)
4525 else:
4525 else:
4526 ctx = scmutil.revsingle(repo, rev, None)
4526 ctx = scmutil.revsingle(repo, rev, None)
4527
4527
4528 if ctx.rev() is None:
4528 if ctx.rev() is None:
4529 ctx = repo[None]
4529 ctx = repo[None]
4530 parents = ctx.parents()
4530 parents = ctx.parents()
4531 taglist = []
4531 taglist = []
4532 for p in parents:
4532 for p in parents:
4533 taglist.extend(p.tags())
4533 taglist.extend(p.tags())
4534
4534
4535 changed = ""
4535 changed = ""
4536 if default or id or num:
4536 if default or id or num:
4537 if (any(repo.status())
4537 if (any(repo.status())
4538 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4538 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4539 changed = '+'
4539 changed = '+'
4540 if default or id:
4540 if default or id:
4541 output = ["%s%s" %
4541 output = ["%s%s" %
4542 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4542 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4543 if num:
4543 if num:
4544 output.append("%s%s" %
4544 output.append("%s%s" %
4545 ('+'.join([str(p.rev()) for p in parents]), changed))
4545 ('+'.join([str(p.rev()) for p in parents]), changed))
4546 else:
4546 else:
4547 if default or id:
4547 if default or id:
4548 output = [hexfunc(ctx.node())]
4548 output = [hexfunc(ctx.node())]
4549 if num:
4549 if num:
4550 output.append(str(ctx.rev()))
4550 output.append(str(ctx.rev()))
4551 taglist = ctx.tags()
4551 taglist = ctx.tags()
4552
4552
4553 if default and not ui.quiet:
4553 if default and not ui.quiet:
4554 b = ctx.branch()
4554 b = ctx.branch()
4555 if b != 'default':
4555 if b != 'default':
4556 output.append("(%s)" % b)
4556 output.append("(%s)" % b)
4557
4557
4558 # multiple tags for a single parent separated by '/'
4558 # multiple tags for a single parent separated by '/'
4559 t = '/'.join(taglist)
4559 t = '/'.join(taglist)
4560 if t:
4560 if t:
4561 output.append(t)
4561 output.append(t)
4562
4562
4563 # multiple bookmarks for a single parent separated by '/'
4563 # multiple bookmarks for a single parent separated by '/'
4564 bm = '/'.join(ctx.bookmarks())
4564 bm = '/'.join(ctx.bookmarks())
4565 if bm:
4565 if bm:
4566 output.append(bm)
4566 output.append(bm)
4567 else:
4567 else:
4568 if branch:
4568 if branch:
4569 output.append(ctx.branch())
4569 output.append(ctx.branch())
4570
4570
4571 if tags:
4571 if tags:
4572 output.extend(taglist)
4572 output.extend(taglist)
4573
4573
4574 if bookmarks:
4574 if bookmarks:
4575 output.extend(ctx.bookmarks())
4575 output.extend(ctx.bookmarks())
4576
4576
4577 ui.write("%s\n" % ' '.join(output))
4577 ui.write("%s\n" % ' '.join(output))
4578
4578
4579 @command('import|patch',
4579 @command('import|patch',
4580 [('p', 'strip', 1,
4580 [('p', 'strip', 1,
4581 _('directory strip option for patch. This has the same '
4581 _('directory strip option for patch. This has the same '
4582 'meaning as the corresponding patch option'), _('NUM')),
4582 'meaning as the corresponding patch option'), _('NUM')),
4583 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4583 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4584 ('e', 'edit', False, _('invoke editor on commit messages')),
4584 ('e', 'edit', False, _('invoke editor on commit messages')),
4585 ('f', 'force', None,
4585 ('f', 'force', None,
4586 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4586 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4587 ('', 'no-commit', None,
4587 ('', 'no-commit', None,
4588 _("don't commit, just update the working directory")),
4588 _("don't commit, just update the working directory")),
4589 ('', 'bypass', None,
4589 ('', 'bypass', None,
4590 _("apply patch without touching the working directory")),
4590 _("apply patch without touching the working directory")),
4591 ('', 'partial', None,
4591 ('', 'partial', None,
4592 _('commit even if some hunks fail')),
4592 _('commit even if some hunks fail')),
4593 ('', 'exact', None,
4593 ('', 'exact', None,
4594 _('apply patch to the nodes from which it was generated')),
4594 _('apply patch to the nodes from which it was generated')),
4595 ('', 'prefix', '',
4595 ('', 'prefix', '',
4596 _('apply patch to subdirectory'), _('DIR')),
4596 _('apply patch to subdirectory'), _('DIR')),
4597 ('', 'import-branch', None,
4597 ('', 'import-branch', None,
4598 _('use any branch information in patch (implied by --exact)'))] +
4598 _('use any branch information in patch (implied by --exact)'))] +
4599 commitopts + commitopts2 + similarityopts,
4599 commitopts + commitopts2 + similarityopts,
4600 _('[OPTION]... PATCH...'))
4600 _('[OPTION]... PATCH...'))
4601 def import_(ui, repo, patch1=None, *patches, **opts):
4601 def import_(ui, repo, patch1=None, *patches, **opts):
4602 """import an ordered set of patches
4602 """import an ordered set of patches
4603
4603
4604 Import a list of patches and commit them individually (unless
4604 Import a list of patches and commit them individually (unless
4605 --no-commit is specified).
4605 --no-commit is specified).
4606
4606
4607 To read a patch from standard input, use "-" as the patch name. If
4607 To read a patch from standard input, use "-" as the patch name. If
4608 a URL is specified, the patch will be downloaded from there.
4608 a URL is specified, the patch will be downloaded from there.
4609
4609
4610 Import first applies changes to the working directory (unless
4610 Import first applies changes to the working directory (unless
4611 --bypass is specified), import will abort if there are outstanding
4611 --bypass is specified), import will abort if there are outstanding
4612 changes.
4612 changes.
4613
4613
4614 Use --bypass to apply and commit patches directly to the
4614 Use --bypass to apply and commit patches directly to the
4615 repository, without affecting the working directory. Without
4615 repository, without affecting the working directory. Without
4616 --exact, patches will be applied on top of the working directory
4616 --exact, patches will be applied on top of the working directory
4617 parent revision.
4617 parent revision.
4618
4618
4619 You can import a patch straight from a mail message. Even patches
4619 You can import a patch straight from a mail message. Even patches
4620 as attachments work (to use the body part, it must have type
4620 as attachments work (to use the body part, it must have type
4621 text/plain or text/x-patch). From and Subject headers of email
4621 text/plain or text/x-patch). From and Subject headers of email
4622 message are used as default committer and commit message. All
4622 message are used as default committer and commit message. All
4623 text/plain body parts before first diff are added to the commit
4623 text/plain body parts before first diff are added to the commit
4624 message.
4624 message.
4625
4625
4626 If the imported patch was generated by :hg:`export`, user and
4626 If the imported patch was generated by :hg:`export`, user and
4627 description from patch override values from message headers and
4627 description from patch override values from message headers and
4628 body. Values given on command line with -m/--message and -u/--user
4628 body. Values given on command line with -m/--message and -u/--user
4629 override these.
4629 override these.
4630
4630
4631 If --exact is specified, import will set the working directory to
4631 If --exact is specified, import will set the working directory to
4632 the parent of each patch before applying it, and will abort if the
4632 the parent of each patch before applying it, and will abort if the
4633 resulting changeset has a different ID than the one recorded in
4633 resulting changeset has a different ID than the one recorded in
4634 the patch. This may happen due to character set problems or other
4634 the patch. This may happen due to character set problems or other
4635 deficiencies in the text patch format.
4635 deficiencies in the text patch format.
4636
4636
4637 Use --partial to ensure a changeset will be created from the patch
4637 Use --partial to ensure a changeset will be created from the patch
4638 even if some hunks fail to apply. Hunks that fail to apply will be
4638 even if some hunks fail to apply. Hunks that fail to apply will be
4639 written to a <target-file>.rej file. Conflicts can then be resolved
4639 written to a <target-file>.rej file. Conflicts can then be resolved
4640 by hand before :hg:`commit --amend` is run to update the created
4640 by hand before :hg:`commit --amend` is run to update the created
4641 changeset. This flag exists to let people import patches that
4641 changeset. This flag exists to let people import patches that
4642 partially apply without losing the associated metadata (author,
4642 partially apply without losing the associated metadata (author,
4643 date, description, ...).
4643 date, description, ...).
4644
4644
4645 .. note::
4645 .. note::
4646
4646
4647 When no hunks apply cleanly, :hg:`import --partial` will create
4647 When no hunks apply cleanly, :hg:`import --partial` will create
4648 an empty changeset, importing only the patch metadata.
4648 an empty changeset, importing only the patch metadata.
4649
4649
4650 With -s/--similarity, hg will attempt to discover renames and
4650 With -s/--similarity, hg will attempt to discover renames and
4651 copies in the patch in the same way as :hg:`addremove`.
4651 copies in the patch in the same way as :hg:`addremove`.
4652
4652
4653 It is possible to use external patch programs to perform the patch
4653 It is possible to use external patch programs to perform the patch
4654 by setting the ``ui.patch`` configuration option. For the default
4654 by setting the ``ui.patch`` configuration option. For the default
4655 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4655 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4656 See :hg:`help config` for more information about configuration
4656 See :hg:`help config` for more information about configuration
4657 files and how to use these options.
4657 files and how to use these options.
4658
4658
4659 See :hg:`help dates` for a list of formats valid for -d/--date.
4659 See :hg:`help dates` for a list of formats valid for -d/--date.
4660
4660
4661 .. container:: verbose
4661 .. container:: verbose
4662
4662
4663 Examples:
4663 Examples:
4664
4664
4665 - import a traditional patch from a website and detect renames::
4665 - import a traditional patch from a website and detect renames::
4666
4666
4667 hg import -s 80 http://example.com/bugfix.patch
4667 hg import -s 80 http://example.com/bugfix.patch
4668
4668
4669 - import a changeset from an hgweb server::
4669 - import a changeset from an hgweb server::
4670
4670
4671 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4671 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4672
4672
4673 - import all the patches in an Unix-style mbox::
4673 - import all the patches in an Unix-style mbox::
4674
4674
4675 hg import incoming-patches.mbox
4675 hg import incoming-patches.mbox
4676
4676
4677 - attempt to exactly restore an exported changeset (not always
4677 - attempt to exactly restore an exported changeset (not always
4678 possible)::
4678 possible)::
4679
4679
4680 hg import --exact proposed-fix.patch
4680 hg import --exact proposed-fix.patch
4681
4681
4682 - use an external tool to apply a patch which is too fuzzy for
4682 - use an external tool to apply a patch which is too fuzzy for
4683 the default internal tool.
4683 the default internal tool.
4684
4684
4685 hg import --config ui.patch="patch --merge" fuzzy.patch
4685 hg import --config ui.patch="patch --merge" fuzzy.patch
4686
4686
4687 - change the default fuzzing from 2 to a less strict 7
4687 - change the default fuzzing from 2 to a less strict 7
4688
4688
4689 hg import --config ui.fuzz=7 fuzz.patch
4689 hg import --config ui.fuzz=7 fuzz.patch
4690
4690
4691 Returns 0 on success, 1 on partial success (see --partial).
4691 Returns 0 on success, 1 on partial success (see --partial).
4692 """
4692 """
4693
4693
4694 if not patch1:
4694 if not patch1:
4695 raise error.Abort(_('need at least one patch to import'))
4695 raise error.Abort(_('need at least one patch to import'))
4696
4696
4697 patches = (patch1,) + patches
4697 patches = (patch1,) + patches
4698
4698
4699 date = opts.get('date')
4699 date = opts.get('date')
4700 if date:
4700 if date:
4701 opts['date'] = util.parsedate(date)
4701 opts['date'] = util.parsedate(date)
4702
4702
4703 exact = opts.get('exact')
4703 exact = opts.get('exact')
4704 update = not opts.get('bypass')
4704 update = not opts.get('bypass')
4705 if not update and opts.get('no_commit'):
4705 if not update and opts.get('no_commit'):
4706 raise error.Abort(_('cannot use --no-commit with --bypass'))
4706 raise error.Abort(_('cannot use --no-commit with --bypass'))
4707 try:
4707 try:
4708 sim = float(opts.get('similarity') or 0)
4708 sim = float(opts.get('similarity') or 0)
4709 except ValueError:
4709 except ValueError:
4710 raise error.Abort(_('similarity must be a number'))
4710 raise error.Abort(_('similarity must be a number'))
4711 if sim < 0 or sim > 100:
4711 if sim < 0 or sim > 100:
4712 raise error.Abort(_('similarity must be between 0 and 100'))
4712 raise error.Abort(_('similarity must be between 0 and 100'))
4713 if sim and not update:
4713 if sim and not update:
4714 raise error.Abort(_('cannot use --similarity with --bypass'))
4714 raise error.Abort(_('cannot use --similarity with --bypass'))
4715 if exact:
4715 if exact:
4716 if opts.get('edit'):
4716 if opts.get('edit'):
4717 raise error.Abort(_('cannot use --exact with --edit'))
4717 raise error.Abort(_('cannot use --exact with --edit'))
4718 if opts.get('prefix'):
4718 if opts.get('prefix'):
4719 raise error.Abort(_('cannot use --exact with --prefix'))
4719 raise error.Abort(_('cannot use --exact with --prefix'))
4720
4720
4721 base = opts["base"]
4721 base = opts["base"]
4722 wlock = dsguard = lock = tr = None
4722 wlock = dsguard = lock = tr = None
4723 msgs = []
4723 msgs = []
4724 ret = 0
4724 ret = 0
4725
4725
4726
4726
4727 try:
4727 try:
4728 wlock = repo.wlock()
4728 wlock = repo.wlock()
4729
4729
4730 if update:
4730 if update:
4731 cmdutil.checkunfinished(repo)
4731 cmdutil.checkunfinished(repo)
4732 if (exact or not opts.get('force')):
4732 if (exact or not opts.get('force')):
4733 cmdutil.bailifchanged(repo)
4733 cmdutil.bailifchanged(repo)
4734
4734
4735 if not opts.get('no_commit'):
4735 if not opts.get('no_commit'):
4736 lock = repo.lock()
4736 lock = repo.lock()
4737 tr = repo.transaction('import')
4737 tr = repo.transaction('import')
4738 else:
4738 else:
4739 dsguard = cmdutil.dirstateguard(repo, 'import')
4739 dsguard = cmdutil.dirstateguard(repo, 'import')
4740 parents = repo[None].parents()
4740 parents = repo[None].parents()
4741 for patchurl in patches:
4741 for patchurl in patches:
4742 if patchurl == '-':
4742 if patchurl == '-':
4743 ui.status(_('applying patch from stdin\n'))
4743 ui.status(_('applying patch from stdin\n'))
4744 patchfile = ui.fin
4744 patchfile = ui.fin
4745 patchurl = 'stdin' # for error message
4745 patchurl = 'stdin' # for error message
4746 else:
4746 else:
4747 patchurl = os.path.join(base, patchurl)
4747 patchurl = os.path.join(base, patchurl)
4748 ui.status(_('applying %s\n') % patchurl)
4748 ui.status(_('applying %s\n') % patchurl)
4749 patchfile = hg.openpath(ui, patchurl)
4749 patchfile = hg.openpath(ui, patchurl)
4750
4750
4751 haspatch = False
4751 haspatch = False
4752 for hunk in patch.split(patchfile):
4752 for hunk in patch.split(patchfile):
4753 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4753 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4754 parents, opts,
4754 parents, opts,
4755 msgs, hg.clean)
4755 msgs, hg.clean)
4756 if msg:
4756 if msg:
4757 haspatch = True
4757 haspatch = True
4758 ui.note(msg + '\n')
4758 ui.note(msg + '\n')
4759 if update or exact:
4759 if update or exact:
4760 parents = repo[None].parents()
4760 parents = repo[None].parents()
4761 else:
4761 else:
4762 parents = [repo[node]]
4762 parents = [repo[node]]
4763 if rej:
4763 if rej:
4764 ui.write_err(_("patch applied partially\n"))
4764 ui.write_err(_("patch applied partially\n"))
4765 ui.write_err(_("(fix the .rej files and run "
4765 ui.write_err(_("(fix the .rej files and run "
4766 "`hg commit --amend`)\n"))
4766 "`hg commit --amend`)\n"))
4767 ret = 1
4767 ret = 1
4768 break
4768 break
4769
4769
4770 if not haspatch:
4770 if not haspatch:
4771 raise error.Abort(_('%s: no diffs found') % patchurl)
4771 raise error.Abort(_('%s: no diffs found') % patchurl)
4772
4772
4773 if tr:
4773 if tr:
4774 tr.close()
4774 tr.close()
4775 if msgs:
4775 if msgs:
4776 repo.savecommitmessage('\n* * *\n'.join(msgs))
4776 repo.savecommitmessage('\n* * *\n'.join(msgs))
4777 if dsguard:
4777 if dsguard:
4778 dsguard.close()
4778 dsguard.close()
4779 return ret
4779 return ret
4780 finally:
4780 finally:
4781 if tr:
4781 if tr:
4782 tr.release()
4782 tr.release()
4783 release(lock, dsguard, wlock)
4783 release(lock, dsguard, wlock)
4784
4784
4785 @command('incoming|in',
4785 @command('incoming|in',
4786 [('f', 'force', None,
4786 [('f', 'force', None,
4787 _('run even if remote repository is unrelated')),
4787 _('run even if remote repository is unrelated')),
4788 ('n', 'newest-first', None, _('show newest record first')),
4788 ('n', 'newest-first', None, _('show newest record first')),
4789 ('', 'bundle', '',
4789 ('', 'bundle', '',
4790 _('file to store the bundles into'), _('FILE')),
4790 _('file to store the bundles into'), _('FILE')),
4791 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4791 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4792 ('B', 'bookmarks', False, _("compare bookmarks")),
4792 ('B', 'bookmarks', False, _("compare bookmarks")),
4793 ('b', 'branch', [],
4793 ('b', 'branch', [],
4794 _('a specific branch you would like to pull'), _('BRANCH')),
4794 _('a specific branch you would like to pull'), _('BRANCH')),
4795 ] + logopts + remoteopts + subrepoopts,
4795 ] + logopts + remoteopts + subrepoopts,
4796 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4796 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4797 def incoming(ui, repo, source="default", **opts):
4797 def incoming(ui, repo, source="default", **opts):
4798 """show new changesets found in source
4798 """show new changesets found in source
4799
4799
4800 Show new changesets found in the specified path/URL or the default
4800 Show new changesets found in the specified path/URL or the default
4801 pull location. These are the changesets that would have been pulled
4801 pull location. These are the changesets that would have been pulled
4802 if a pull at the time you issued this command.
4802 if a pull at the time you issued this command.
4803
4803
4804 See pull for valid source format details.
4804 See pull for valid source format details.
4805
4805
4806 .. container:: verbose
4806 .. container:: verbose
4807
4807
4808 With -B/--bookmarks, the result of bookmark comparison between
4808 With -B/--bookmarks, the result of bookmark comparison between
4809 local and remote repositories is displayed. With -v/--verbose,
4809 local and remote repositories is displayed. With -v/--verbose,
4810 status is also displayed for each bookmark like below::
4810 status is also displayed for each bookmark like below::
4811
4811
4812 BM1 01234567890a added
4812 BM1 01234567890a added
4813 BM2 1234567890ab advanced
4813 BM2 1234567890ab advanced
4814 BM3 234567890abc diverged
4814 BM3 234567890abc diverged
4815 BM4 34567890abcd changed
4815 BM4 34567890abcd changed
4816
4816
4817 The action taken locally when pulling depends on the
4817 The action taken locally when pulling depends on the
4818 status of each bookmark:
4818 status of each bookmark:
4819
4819
4820 :``added``: pull will create it
4820 :``added``: pull will create it
4821 :``advanced``: pull will update it
4821 :``advanced``: pull will update it
4822 :``diverged``: pull will create a divergent bookmark
4822 :``diverged``: pull will create a divergent bookmark
4823 :``changed``: result depends on remote changesets
4823 :``changed``: result depends on remote changesets
4824
4824
4825 From the point of view of pulling behavior, bookmark
4825 From the point of view of pulling behavior, bookmark
4826 existing only in the remote repository are treated as ``added``,
4826 existing only in the remote repository are treated as ``added``,
4827 even if it is in fact locally deleted.
4827 even if it is in fact locally deleted.
4828
4828
4829 .. container:: verbose
4829 .. container:: verbose
4830
4830
4831 For remote repository, using --bundle avoids downloading the
4831 For remote repository, using --bundle avoids downloading the
4832 changesets twice if the incoming is followed by a pull.
4832 changesets twice if the incoming is followed by a pull.
4833
4833
4834 Examples:
4834 Examples:
4835
4835
4836 - show incoming changes with patches and full description::
4836 - show incoming changes with patches and full description::
4837
4837
4838 hg incoming -vp
4838 hg incoming -vp
4839
4839
4840 - show incoming changes excluding merges, store a bundle::
4840 - show incoming changes excluding merges, store a bundle::
4841
4841
4842 hg in -vpM --bundle incoming.hg
4842 hg in -vpM --bundle incoming.hg
4843 hg pull incoming.hg
4843 hg pull incoming.hg
4844
4844
4845 - briefly list changes inside a bundle::
4845 - briefly list changes inside a bundle::
4846
4846
4847 hg in changes.hg -T "{desc|firstline}\\n"
4847 hg in changes.hg -T "{desc|firstline}\\n"
4848
4848
4849 Returns 0 if there are incoming changes, 1 otherwise.
4849 Returns 0 if there are incoming changes, 1 otherwise.
4850 """
4850 """
4851 if opts.get('graph'):
4851 if opts.get('graph'):
4852 cmdutil.checkunsupportedgraphflags([], opts)
4852 cmdutil.checkunsupportedgraphflags([], opts)
4853 def display(other, chlist, displayer):
4853 def display(other, chlist, displayer):
4854 revdag = cmdutil.graphrevs(other, chlist, opts)
4854 revdag = cmdutil.graphrevs(other, chlist, opts)
4855 cmdutil.displaygraph(ui, repo, revdag, displayer,
4855 cmdutil.displaygraph(ui, repo, revdag, displayer,
4856 graphmod.asciiedges)
4856 graphmod.asciiedges)
4857
4857
4858 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4858 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4859 return 0
4859 return 0
4860
4860
4861 if opts.get('bundle') and opts.get('subrepos'):
4861 if opts.get('bundle') and opts.get('subrepos'):
4862 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4862 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4863
4863
4864 if opts.get('bookmarks'):
4864 if opts.get('bookmarks'):
4865 source, branches = hg.parseurl(ui.expandpath(source),
4865 source, branches = hg.parseurl(ui.expandpath(source),
4866 opts.get('branch'))
4866 opts.get('branch'))
4867 other = hg.peer(repo, opts, source)
4867 other = hg.peer(repo, opts, source)
4868 if 'bookmarks' not in other.listkeys('namespaces'):
4868 if 'bookmarks' not in other.listkeys('namespaces'):
4869 ui.warn(_("remote doesn't support bookmarks\n"))
4869 ui.warn(_("remote doesn't support bookmarks\n"))
4870 return 0
4870 return 0
4871 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4871 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4872 return bookmarks.incoming(ui, repo, other)
4872 return bookmarks.incoming(ui, repo, other)
4873
4873
4874 repo._subtoppath = ui.expandpath(source)
4874 repo._subtoppath = ui.expandpath(source)
4875 try:
4875 try:
4876 return hg.incoming(ui, repo, source, opts)
4876 return hg.incoming(ui, repo, source, opts)
4877 finally:
4877 finally:
4878 del repo._subtoppath
4878 del repo._subtoppath
4879
4879
4880
4880
4881 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4881 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4882 norepo=True)
4882 norepo=True)
4883 def init(ui, dest=".", **opts):
4883 def init(ui, dest=".", **opts):
4884 """create a new repository in the given directory
4884 """create a new repository in the given directory
4885
4885
4886 Initialize a new repository in the given directory. If the given
4886 Initialize a new repository in the given directory. If the given
4887 directory does not exist, it will be created.
4887 directory does not exist, it will be created.
4888
4888
4889 If no directory is given, the current directory is used.
4889 If no directory is given, the current directory is used.
4890
4890
4891 It is possible to specify an ``ssh://`` URL as the destination.
4891 It is possible to specify an ``ssh://`` URL as the destination.
4892 See :hg:`help urls` for more information.
4892 See :hg:`help urls` for more information.
4893
4893
4894 Returns 0 on success.
4894 Returns 0 on success.
4895 """
4895 """
4896 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4896 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4897
4897
4898 @command('locate',
4898 @command('locate',
4899 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4899 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4900 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4900 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4901 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4901 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4902 ] + walkopts,
4902 ] + walkopts,
4903 _('[OPTION]... [PATTERN]...'))
4903 _('[OPTION]... [PATTERN]...'))
4904 def locate(ui, repo, *pats, **opts):
4904 def locate(ui, repo, *pats, **opts):
4905 """locate files matching specific patterns (DEPRECATED)
4905 """locate files matching specific patterns (DEPRECATED)
4906
4906
4907 Print files under Mercurial control in the working directory whose
4907 Print files under Mercurial control in the working directory whose
4908 names match the given patterns.
4908 names match the given patterns.
4909
4909
4910 By default, this command searches all directories in the working
4910 By default, this command searches all directories in the working
4911 directory. To search just the current directory and its
4911 directory. To search just the current directory and its
4912 subdirectories, use "--include .".
4912 subdirectories, use "--include .".
4913
4913
4914 If no patterns are given to match, this command prints the names
4914 If no patterns are given to match, this command prints the names
4915 of all files under Mercurial control in the working directory.
4915 of all files under Mercurial control in the working directory.
4916
4916
4917 If you want to feed the output of this command into the "xargs"
4917 If you want to feed the output of this command into the "xargs"
4918 command, use the -0 option to both this command and "xargs". This
4918 command, use the -0 option to both this command and "xargs". This
4919 will avoid the problem of "xargs" treating single filenames that
4919 will avoid the problem of "xargs" treating single filenames that
4920 contain whitespace as multiple filenames.
4920 contain whitespace as multiple filenames.
4921
4921
4922 See :hg:`help files` for a more versatile command.
4922 See :hg:`help files` for a more versatile command.
4923
4923
4924 Returns 0 if a match is found, 1 otherwise.
4924 Returns 0 if a match is found, 1 otherwise.
4925 """
4925 """
4926 if opts.get('print0'):
4926 if opts.get('print0'):
4927 end = '\0'
4927 end = '\0'
4928 else:
4928 else:
4929 end = '\n'
4929 end = '\n'
4930 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4930 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4931
4931
4932 ret = 1
4932 ret = 1
4933 ctx = repo[rev]
4933 ctx = repo[rev]
4934 m = scmutil.match(ctx, pats, opts, default='relglob',
4934 m = scmutil.match(ctx, pats, opts, default='relglob',
4935 badfn=lambda x, y: False)
4935 badfn=lambda x, y: False)
4936
4936
4937 for abs in ctx.matches(m):
4937 for abs in ctx.matches(m):
4938 if opts.get('fullpath'):
4938 if opts.get('fullpath'):
4939 ui.write(repo.wjoin(abs), end)
4939 ui.write(repo.wjoin(abs), end)
4940 else:
4940 else:
4941 ui.write(((pats and m.rel(abs)) or abs), end)
4941 ui.write(((pats and m.rel(abs)) or abs), end)
4942 ret = 0
4942 ret = 0
4943
4943
4944 return ret
4944 return ret
4945
4945
4946 @command('^log|history',
4946 @command('^log|history',
4947 [('f', 'follow', None,
4947 [('f', 'follow', None,
4948 _('follow changeset history, or file history across copies and renames')),
4948 _('follow changeset history, or file history across copies and renames')),
4949 ('', 'follow-first', None,
4949 ('', 'follow-first', None,
4950 _('only follow the first parent of merge changesets (DEPRECATED)')),
4950 _('only follow the first parent of merge changesets (DEPRECATED)')),
4951 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4951 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4952 ('C', 'copies', None, _('show copied files')),
4952 ('C', 'copies', None, _('show copied files')),
4953 ('k', 'keyword', [],
4953 ('k', 'keyword', [],
4954 _('do case-insensitive search for a given text'), _('TEXT')),
4954 _('do case-insensitive search for a given text'), _('TEXT')),
4955 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4955 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4956 ('', 'removed', None, _('include revisions where files were removed')),
4956 ('', 'removed', None, _('include revisions where files were removed')),
4957 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4957 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4958 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4958 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4959 ('', 'only-branch', [],
4959 ('', 'only-branch', [],
4960 _('show only changesets within the given named branch (DEPRECATED)'),
4960 _('show only changesets within the given named branch (DEPRECATED)'),
4961 _('BRANCH')),
4961 _('BRANCH')),
4962 ('b', 'branch', [],
4962 ('b', 'branch', [],
4963 _('show changesets within the given named branch'), _('BRANCH')),
4963 _('show changesets within the given named branch'), _('BRANCH')),
4964 ('P', 'prune', [],
4964 ('P', 'prune', [],
4965 _('do not display revision or any of its ancestors'), _('REV')),
4965 _('do not display revision or any of its ancestors'), _('REV')),
4966 ] + logopts + walkopts,
4966 ] + logopts + walkopts,
4967 _('[OPTION]... [FILE]'),
4967 _('[OPTION]... [FILE]'),
4968 inferrepo=True)
4968 inferrepo=True)
4969 def log(ui, repo, *pats, **opts):
4969 def log(ui, repo, *pats, **opts):
4970 """show revision history of entire repository or files
4970 """show revision history of entire repository or files
4971
4971
4972 Print the revision history of the specified files or the entire
4972 Print the revision history of the specified files or the entire
4973 project.
4973 project.
4974
4974
4975 If no revision range is specified, the default is ``tip:0`` unless
4975 If no revision range is specified, the default is ``tip:0`` unless
4976 --follow is set, in which case the working directory parent is
4976 --follow is set, in which case the working directory parent is
4977 used as the starting revision.
4977 used as the starting revision.
4978
4978
4979 File history is shown without following rename or copy history of
4979 File history is shown without following rename or copy history of
4980 files. Use -f/--follow with a filename to follow history across
4980 files. Use -f/--follow with a filename to follow history across
4981 renames and copies. --follow without a filename will only show
4981 renames and copies. --follow without a filename will only show
4982 ancestors or descendants of the starting revision.
4982 ancestors or descendants of the starting revision.
4983
4983
4984 By default this command prints revision number and changeset id,
4984 By default this command prints revision number and changeset id,
4985 tags, non-trivial parents, user, date and time, and a summary for
4985 tags, non-trivial parents, user, date and time, and a summary for
4986 each commit. When the -v/--verbose switch is used, the list of
4986 each commit. When the -v/--verbose switch is used, the list of
4987 changed files and full commit message are shown.
4987 changed files and full commit message are shown.
4988
4988
4989 With --graph the revisions are shown as an ASCII art DAG with the most
4989 With --graph the revisions are shown as an ASCII art DAG with the most
4990 recent changeset at the top.
4990 recent changeset at the top.
4991 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4991 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4992 and '+' represents a fork where the changeset from the lines below is a
4992 and '+' represents a fork where the changeset from the lines below is a
4993 parent of the 'o' merge on the same line.
4993 parent of the 'o' merge on the same line.
4994
4994
4995 .. note::
4995 .. note::
4996
4996
4997 :hg:`log --patch` may generate unexpected diff output for merge
4997 :hg:`log --patch` may generate unexpected diff output for merge
4998 changesets, as it will only compare the merge changeset against
4998 changesets, as it will only compare the merge changeset against
4999 its first parent. Also, only files different from BOTH parents
4999 its first parent. Also, only files different from BOTH parents
5000 will appear in files:.
5000 will appear in files:.
5001
5001
5002 .. note::
5002 .. note::
5003
5003
5004 For performance reasons, :hg:`log FILE` may omit duplicate changes
5004 For performance reasons, :hg:`log FILE` may omit duplicate changes
5005 made on branches and will not show removals or mode changes. To
5005 made on branches and will not show removals or mode changes. To
5006 see all such changes, use the --removed switch.
5006 see all such changes, use the --removed switch.
5007
5007
5008 .. container:: verbose
5008 .. container:: verbose
5009
5009
5010 Some examples:
5010 Some examples:
5011
5011
5012 - changesets with full descriptions and file lists::
5012 - changesets with full descriptions and file lists::
5013
5013
5014 hg log -v
5014 hg log -v
5015
5015
5016 - changesets ancestral to the working directory::
5016 - changesets ancestral to the working directory::
5017
5017
5018 hg log -f
5018 hg log -f
5019
5019
5020 - last 10 commits on the current branch::
5020 - last 10 commits on the current branch::
5021
5021
5022 hg log -l 10 -b .
5022 hg log -l 10 -b .
5023
5023
5024 - changesets showing all modifications of a file, including removals::
5024 - changesets showing all modifications of a file, including removals::
5025
5025
5026 hg log --removed file.c
5026 hg log --removed file.c
5027
5027
5028 - all changesets that touch a directory, with diffs, excluding merges::
5028 - all changesets that touch a directory, with diffs, excluding merges::
5029
5029
5030 hg log -Mp lib/
5030 hg log -Mp lib/
5031
5031
5032 - all revision numbers that match a keyword::
5032 - all revision numbers that match a keyword::
5033
5033
5034 hg log -k bug --template "{rev}\\n"
5034 hg log -k bug --template "{rev}\\n"
5035
5035
5036 - the full hash identifier of the working directory parent::
5036 - the full hash identifier of the working directory parent::
5037
5037
5038 hg log -r . --template "{node}\\n"
5038 hg log -r . --template "{node}\\n"
5039
5039
5040 - list available log templates::
5040 - list available log templates::
5041
5041
5042 hg log -T list
5042 hg log -T list
5043
5043
5044 - check if a given changeset is included in a tagged release::
5044 - check if a given changeset is included in a tagged release::
5045
5045
5046 hg log -r "a21ccf and ancestor(1.9)"
5046 hg log -r "a21ccf and ancestor(1.9)"
5047
5047
5048 - find all changesets by some user in a date range::
5048 - find all changesets by some user in a date range::
5049
5049
5050 hg log -k alice -d "may 2008 to jul 2008"
5050 hg log -k alice -d "may 2008 to jul 2008"
5051
5051
5052 - summary of all changesets after the last tag::
5052 - summary of all changesets after the last tag::
5053
5053
5054 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5054 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5055
5055
5056 See :hg:`help dates` for a list of formats valid for -d/--date.
5056 See :hg:`help dates` for a list of formats valid for -d/--date.
5057
5057
5058 See :hg:`help revisions` and :hg:`help revsets` for more about
5058 See :hg:`help revisions` and :hg:`help revsets` for more about
5059 specifying and ordering revisions.
5059 specifying and ordering revisions.
5060
5060
5061 See :hg:`help templates` for more about pre-packaged styles and
5061 See :hg:`help templates` for more about pre-packaged styles and
5062 specifying custom templates.
5062 specifying custom templates.
5063
5063
5064 Returns 0 on success.
5064 Returns 0 on success.
5065
5065
5066 """
5066 """
5067 if opts.get('follow') and opts.get('rev'):
5067 if opts.get('follow') and opts.get('rev'):
5068 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5068 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5069 del opts['follow']
5069 del opts['follow']
5070
5070
5071 if opts.get('graph'):
5071 if opts.get('graph'):
5072 return cmdutil.graphlog(ui, repo, *pats, **opts)
5072 return cmdutil.graphlog(ui, repo, *pats, **opts)
5073
5073
5074 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5074 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5075 limit = cmdutil.loglimit(opts)
5075 limit = cmdutil.loglimit(opts)
5076 count = 0
5076 count = 0
5077
5077
5078 getrenamed = None
5078 getrenamed = None
5079 if opts.get('copies'):
5079 if opts.get('copies'):
5080 endrev = None
5080 endrev = None
5081 if opts.get('rev'):
5081 if opts.get('rev'):
5082 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5082 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5083 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5083 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5084
5084
5085 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5085 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5086 for rev in revs:
5086 for rev in revs:
5087 if count == limit:
5087 if count == limit:
5088 break
5088 break
5089 ctx = repo[rev]
5089 ctx = repo[rev]
5090 copies = None
5090 copies = None
5091 if getrenamed is not None and rev:
5091 if getrenamed is not None and rev:
5092 copies = []
5092 copies = []
5093 for fn in ctx.files():
5093 for fn in ctx.files():
5094 rename = getrenamed(fn, rev)
5094 rename = getrenamed(fn, rev)
5095 if rename:
5095 if rename:
5096 copies.append((fn, rename[0]))
5096 copies.append((fn, rename[0]))
5097 if filematcher:
5097 if filematcher:
5098 revmatchfn = filematcher(ctx.rev())
5098 revmatchfn = filematcher(ctx.rev())
5099 else:
5099 else:
5100 revmatchfn = None
5100 revmatchfn = None
5101 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5101 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5102 if displayer.flush(ctx):
5102 if displayer.flush(ctx):
5103 count += 1
5103 count += 1
5104
5104
5105 displayer.close()
5105 displayer.close()
5106
5106
5107 @command('manifest',
5107 @command('manifest',
5108 [('r', 'rev', '', _('revision to display'), _('REV')),
5108 [('r', 'rev', '', _('revision to display'), _('REV')),
5109 ('', 'all', False, _("list files from all revisions"))]
5109 ('', 'all', False, _("list files from all revisions"))]
5110 + formatteropts,
5110 + formatteropts,
5111 _('[-r REV]'))
5111 _('[-r REV]'))
5112 def manifest(ui, repo, node=None, rev=None, **opts):
5112 def manifest(ui, repo, node=None, rev=None, **opts):
5113 """output the current or given revision of the project manifest
5113 """output the current or given revision of the project manifest
5114
5114
5115 Print a list of version controlled files for the given revision.
5115 Print a list of version controlled files for the given revision.
5116 If no revision is given, the first parent of the working directory
5116 If no revision is given, the first parent of the working directory
5117 is used, or the null revision if no revision is checked out.
5117 is used, or the null revision if no revision is checked out.
5118
5118
5119 With -v, print file permissions, symlink and executable bits.
5119 With -v, print file permissions, symlink and executable bits.
5120 With --debug, print file revision hashes.
5120 With --debug, print file revision hashes.
5121
5121
5122 If option --all is specified, the list of all files from all revisions
5122 If option --all is specified, the list of all files from all revisions
5123 is printed. This includes deleted and renamed files.
5123 is printed. This includes deleted and renamed files.
5124
5124
5125 Returns 0 on success.
5125 Returns 0 on success.
5126 """
5126 """
5127
5127
5128 fm = ui.formatter('manifest', opts)
5128 fm = ui.formatter('manifest', opts)
5129
5129
5130 if opts.get('all'):
5130 if opts.get('all'):
5131 if rev or node:
5131 if rev or node:
5132 raise error.Abort(_("can't specify a revision with --all"))
5132 raise error.Abort(_("can't specify a revision with --all"))
5133
5133
5134 res = []
5134 res = []
5135 prefix = "data/"
5135 prefix = "data/"
5136 suffix = ".i"
5136 suffix = ".i"
5137 plen = len(prefix)
5137 plen = len(prefix)
5138 slen = len(suffix)
5138 slen = len(suffix)
5139 lock = repo.lock()
5139 lock = repo.lock()
5140 try:
5140 try:
5141 for fn, b, size in repo.store.datafiles():
5141 for fn, b, size in repo.store.datafiles():
5142 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5142 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5143 res.append(fn[plen:-slen])
5143 res.append(fn[plen:-slen])
5144 finally:
5144 finally:
5145 lock.release()
5145 lock.release()
5146 for f in res:
5146 for f in res:
5147 fm.startitem()
5147 fm.startitem()
5148 fm.write("path", '%s\n', f)
5148 fm.write("path", '%s\n', f)
5149 fm.end()
5149 fm.end()
5150 return
5150 return
5151
5151
5152 if rev and node:
5152 if rev and node:
5153 raise error.Abort(_("please specify just one revision"))
5153 raise error.Abort(_("please specify just one revision"))
5154
5154
5155 if not node:
5155 if not node:
5156 node = rev
5156 node = rev
5157
5157
5158 char = {'l': '@', 'x': '*', '': ''}
5158 char = {'l': '@', 'x': '*', '': ''}
5159 mode = {'l': '644', 'x': '755', '': '644'}
5159 mode = {'l': '644', 'x': '755', '': '644'}
5160 ctx = scmutil.revsingle(repo, node)
5160 ctx = scmutil.revsingle(repo, node)
5161 mf = ctx.manifest()
5161 mf = ctx.manifest()
5162 for f in ctx:
5162 for f in ctx:
5163 fm.startitem()
5163 fm.startitem()
5164 fl = ctx[f].flags()
5164 fl = ctx[f].flags()
5165 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5165 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5166 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5166 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5167 fm.write('path', '%s\n', f)
5167 fm.write('path', '%s\n', f)
5168 fm.end()
5168 fm.end()
5169
5169
5170 @command('^merge',
5170 @command('^merge',
5171 [('f', 'force', None,
5171 [('f', 'force', None,
5172 _('force a merge including outstanding changes (DEPRECATED)')),
5172 _('force a merge including outstanding changes (DEPRECATED)')),
5173 ('r', 'rev', '', _('revision to merge'), _('REV')),
5173 ('r', 'rev', '', _('revision to merge'), _('REV')),
5174 ('P', 'preview', None,
5174 ('P', 'preview', None,
5175 _('review revisions to merge (no merge is performed)'))
5175 _('review revisions to merge (no merge is performed)'))
5176 ] + mergetoolopts,
5176 ] + mergetoolopts,
5177 _('[-P] [-f] [[-r] REV]'))
5177 _('[-P] [-f] [[-r] REV]'))
5178 def merge(ui, repo, node=None, **opts):
5178 def merge(ui, repo, node=None, **opts):
5179 """merge another revision into working directory
5179 """merge another revision into working directory
5180
5180
5181 The current working directory is updated with all changes made in
5181 The current working directory is updated with all changes made in
5182 the requested revision since the last common predecessor revision.
5182 the requested revision since the last common predecessor revision.
5183
5183
5184 Files that changed between either parent are marked as changed for
5184 Files that changed between either parent are marked as changed for
5185 the next commit and a commit must be performed before any further
5185 the next commit and a commit must be performed before any further
5186 updates to the repository are allowed. The next commit will have
5186 updates to the repository are allowed. The next commit will have
5187 two parents.
5187 two parents.
5188
5188
5189 ``--tool`` can be used to specify the merge tool used for file
5189 ``--tool`` can be used to specify the merge tool used for file
5190 merges. It overrides the HGMERGE environment variable and your
5190 merges. It overrides the HGMERGE environment variable and your
5191 configuration files. See :hg:`help merge-tools` for options.
5191 configuration files. See :hg:`help merge-tools` for options.
5192
5192
5193 If no revision is specified, the working directory's parent is a
5193 If no revision is specified, the working directory's parent is a
5194 head revision, and the current branch contains exactly one other
5194 head revision, and the current branch contains exactly one other
5195 head, the other head is merged with by default. Otherwise, an
5195 head, the other head is merged with by default. Otherwise, an
5196 explicit revision with which to merge with must be provided.
5196 explicit revision with which to merge with must be provided.
5197
5197
5198 See :hg:`help resolve` for information on handling file conflicts.
5198 See :hg:`help resolve` for information on handling file conflicts.
5199
5199
5200 To undo an uncommitted merge, use :hg:`update --clean .` which
5200 To undo an uncommitted merge, use :hg:`update --clean .` which
5201 will check out a clean copy of the original merge parent, losing
5201 will check out a clean copy of the original merge parent, losing
5202 all changes.
5202 all changes.
5203
5203
5204 Returns 0 on success, 1 if there are unresolved files.
5204 Returns 0 on success, 1 if there are unresolved files.
5205 """
5205 """
5206
5206
5207 if opts.get('rev') and node:
5207 if opts.get('rev') and node:
5208 raise error.Abort(_("please specify just one revision"))
5208 raise error.Abort(_("please specify just one revision"))
5209 if not node:
5209 if not node:
5210 node = opts.get('rev')
5210 node = opts.get('rev')
5211
5211
5212 if node:
5212 if node:
5213 node = scmutil.revsingle(repo, node).node()
5213 node = scmutil.revsingle(repo, node).node()
5214
5214
5215 if not node:
5215 if not node:
5216 node = repo[destutil.destmerge(repo)].node()
5216 node = repo[destutil.destmerge(repo)].node()
5217
5217
5218 if opts.get('preview'):
5218 if opts.get('preview'):
5219 # find nodes that are ancestors of p2 but not of p1
5219 # find nodes that are ancestors of p2 but not of p1
5220 p1 = repo.lookup('.')
5220 p1 = repo.lookup('.')
5221 p2 = repo.lookup(node)
5221 p2 = repo.lookup(node)
5222 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5222 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5223
5223
5224 displayer = cmdutil.show_changeset(ui, repo, opts)
5224 displayer = cmdutil.show_changeset(ui, repo, opts)
5225 for node in nodes:
5225 for node in nodes:
5226 displayer.show(repo[node])
5226 displayer.show(repo[node])
5227 displayer.close()
5227 displayer.close()
5228 return 0
5228 return 0
5229
5229
5230 try:
5230 try:
5231 # ui.forcemerge is an internal variable, do not document
5231 # ui.forcemerge is an internal variable, do not document
5232 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5232 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5233 return hg.merge(repo, node, force=opts.get('force'))
5233 return hg.merge(repo, node, force=opts.get('force'))
5234 finally:
5234 finally:
5235 ui.setconfig('ui', 'forcemerge', '', 'merge')
5235 ui.setconfig('ui', 'forcemerge', '', 'merge')
5236
5236
5237 @command('outgoing|out',
5237 @command('outgoing|out',
5238 [('f', 'force', None, _('run even when the destination is unrelated')),
5238 [('f', 'force', None, _('run even when the destination is unrelated')),
5239 ('r', 'rev', [],
5239 ('r', 'rev', [],
5240 _('a changeset intended to be included in the destination'), _('REV')),
5240 _('a changeset intended to be included in the destination'), _('REV')),
5241 ('n', 'newest-first', None, _('show newest record first')),
5241 ('n', 'newest-first', None, _('show newest record first')),
5242 ('B', 'bookmarks', False, _('compare bookmarks')),
5242 ('B', 'bookmarks', False, _('compare bookmarks')),
5243 ('b', 'branch', [], _('a specific branch you would like to push'),
5243 ('b', 'branch', [], _('a specific branch you would like to push'),
5244 _('BRANCH')),
5244 _('BRANCH')),
5245 ] + logopts + remoteopts + subrepoopts,
5245 ] + logopts + remoteopts + subrepoopts,
5246 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5246 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5247 def outgoing(ui, repo, dest=None, **opts):
5247 def outgoing(ui, repo, dest=None, **opts):
5248 """show changesets not found in the destination
5248 """show changesets not found in the destination
5249
5249
5250 Show changesets not found in the specified destination repository
5250 Show changesets not found in the specified destination repository
5251 or the default push location. These are the changesets that would
5251 or the default push location. These are the changesets that would
5252 be pushed if a push was requested.
5252 be pushed if a push was requested.
5253
5253
5254 See pull for details of valid destination formats.
5254 See pull for details of valid destination formats.
5255
5255
5256 .. container:: verbose
5256 .. container:: verbose
5257
5257
5258 With -B/--bookmarks, the result of bookmark comparison between
5258 With -B/--bookmarks, the result of bookmark comparison between
5259 local and remote repositories is displayed. With -v/--verbose,
5259 local and remote repositories is displayed. With -v/--verbose,
5260 status is also displayed for each bookmark like below::
5260 status is also displayed for each bookmark like below::
5261
5261
5262 BM1 01234567890a added
5262 BM1 01234567890a added
5263 BM2 deleted
5263 BM2 deleted
5264 BM3 234567890abc advanced
5264 BM3 234567890abc advanced
5265 BM4 34567890abcd diverged
5265 BM4 34567890abcd diverged
5266 BM5 4567890abcde changed
5266 BM5 4567890abcde changed
5267
5267
5268 The action taken when pushing depends on the
5268 The action taken when pushing depends on the
5269 status of each bookmark:
5269 status of each bookmark:
5270
5270
5271 :``added``: push with ``-B`` will create it
5271 :``added``: push with ``-B`` will create it
5272 :``deleted``: push with ``-B`` will delete it
5272 :``deleted``: push with ``-B`` will delete it
5273 :``advanced``: push will update it
5273 :``advanced``: push will update it
5274 :``diverged``: push with ``-B`` will update it
5274 :``diverged``: push with ``-B`` will update it
5275 :``changed``: push with ``-B`` will update it
5275 :``changed``: push with ``-B`` will update it
5276
5276
5277 From the point of view of pushing behavior, bookmarks
5277 From the point of view of pushing behavior, bookmarks
5278 existing only in the remote repository are treated as
5278 existing only in the remote repository are treated as
5279 ``deleted``, even if it is in fact added remotely.
5279 ``deleted``, even if it is in fact added remotely.
5280
5280
5281 Returns 0 if there are outgoing changes, 1 otherwise.
5281 Returns 0 if there are outgoing changes, 1 otherwise.
5282 """
5282 """
5283 if opts.get('graph'):
5283 if opts.get('graph'):
5284 cmdutil.checkunsupportedgraphflags([], opts)
5284 cmdutil.checkunsupportedgraphflags([], opts)
5285 o, other = hg._outgoing(ui, repo, dest, opts)
5285 o, other = hg._outgoing(ui, repo, dest, opts)
5286 if not o:
5286 if not o:
5287 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5287 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5288 return
5288 return
5289
5289
5290 revdag = cmdutil.graphrevs(repo, o, opts)
5290 revdag = cmdutil.graphrevs(repo, o, opts)
5291 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5291 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5292 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5292 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5293 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5293 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5294 return 0
5294 return 0
5295
5295
5296 if opts.get('bookmarks'):
5296 if opts.get('bookmarks'):
5297 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5297 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5298 dest, branches = hg.parseurl(dest, opts.get('branch'))
5298 dest, branches = hg.parseurl(dest, opts.get('branch'))
5299 other = hg.peer(repo, opts, dest)
5299 other = hg.peer(repo, opts, dest)
5300 if 'bookmarks' not in other.listkeys('namespaces'):
5300 if 'bookmarks' not in other.listkeys('namespaces'):
5301 ui.warn(_("remote doesn't support bookmarks\n"))
5301 ui.warn(_("remote doesn't support bookmarks\n"))
5302 return 0
5302 return 0
5303 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5303 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5304 return bookmarks.outgoing(ui, repo, other)
5304 return bookmarks.outgoing(ui, repo, other)
5305
5305
5306 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5306 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5307 try:
5307 try:
5308 return hg.outgoing(ui, repo, dest, opts)
5308 return hg.outgoing(ui, repo, dest, opts)
5309 finally:
5309 finally:
5310 del repo._subtoppath
5310 del repo._subtoppath
5311
5311
5312 @command('parents',
5312 @command('parents',
5313 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5313 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5314 ] + templateopts,
5314 ] + templateopts,
5315 _('[-r REV] [FILE]'),
5315 _('[-r REV] [FILE]'),
5316 inferrepo=True)
5316 inferrepo=True)
5317 def parents(ui, repo, file_=None, **opts):
5317 def parents(ui, repo, file_=None, **opts):
5318 """show the parents of the working directory or revision (DEPRECATED)
5318 """show the parents of the working directory or revision (DEPRECATED)
5319
5319
5320 Print the working directory's parent revisions. If a revision is
5320 Print the working directory's parent revisions. If a revision is
5321 given via -r/--rev, the parent of that revision will be printed.
5321 given via -r/--rev, the parent of that revision will be printed.
5322 If a file argument is given, the revision in which the file was
5322 If a file argument is given, the revision in which the file was
5323 last changed (before the working directory revision or the
5323 last changed (before the working directory revision or the
5324 argument to --rev if given) is printed.
5324 argument to --rev if given) is printed.
5325
5325
5326 This command is equivalent to::
5326 This command is equivalent to::
5327
5327
5328 hg log -r "p1()+p2()" or
5328 hg log -r "p1()+p2()" or
5329 hg log -r "p1(REV)+p2(REV)" or
5329 hg log -r "p1(REV)+p2(REV)" or
5330 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5330 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5331 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5331 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5332
5332
5333 See :hg:`summary` and :hg:`help revsets` for related information.
5333 See :hg:`summary` and :hg:`help revsets` for related information.
5334
5334
5335 Returns 0 on success.
5335 Returns 0 on success.
5336 """
5336 """
5337
5337
5338 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5338 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5339
5339
5340 if file_:
5340 if file_:
5341 m = scmutil.match(ctx, (file_,), opts)
5341 m = scmutil.match(ctx, (file_,), opts)
5342 if m.anypats() or len(m.files()) != 1:
5342 if m.anypats() or len(m.files()) != 1:
5343 raise error.Abort(_('can only specify an explicit filename'))
5343 raise error.Abort(_('can only specify an explicit filename'))
5344 file_ = m.files()[0]
5344 file_ = m.files()[0]
5345 filenodes = []
5345 filenodes = []
5346 for cp in ctx.parents():
5346 for cp in ctx.parents():
5347 if not cp:
5347 if not cp:
5348 continue
5348 continue
5349 try:
5349 try:
5350 filenodes.append(cp.filenode(file_))
5350 filenodes.append(cp.filenode(file_))
5351 except error.LookupError:
5351 except error.LookupError:
5352 pass
5352 pass
5353 if not filenodes:
5353 if not filenodes:
5354 raise error.Abort(_("'%s' not found in manifest!") % file_)
5354 raise error.Abort(_("'%s' not found in manifest!") % file_)
5355 p = []
5355 p = []
5356 for fn in filenodes:
5356 for fn in filenodes:
5357 fctx = repo.filectx(file_, fileid=fn)
5357 fctx = repo.filectx(file_, fileid=fn)
5358 p.append(fctx.node())
5358 p.append(fctx.node())
5359 else:
5359 else:
5360 p = [cp.node() for cp in ctx.parents()]
5360 p = [cp.node() for cp in ctx.parents()]
5361
5361
5362 displayer = cmdutil.show_changeset(ui, repo, opts)
5362 displayer = cmdutil.show_changeset(ui, repo, opts)
5363 for n in p:
5363 for n in p:
5364 if n != nullid:
5364 if n != nullid:
5365 displayer.show(repo[n])
5365 displayer.show(repo[n])
5366 displayer.close()
5366 displayer.close()
5367
5367
5368 @command('paths', [], _('[NAME]'), optionalrepo=True)
5368 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5369 def paths(ui, repo, search=None):
5369 def paths(ui, repo, search=None, **opts):
5370 """show aliases for remote repositories
5370 """show aliases for remote repositories
5371
5371
5372 Show definition of symbolic path name NAME. If no name is given,
5372 Show definition of symbolic path name NAME. If no name is given,
5373 show definition of all available names.
5373 show definition of all available names.
5374
5374
5375 Option -q/--quiet suppresses all output when searching for NAME
5375 Option -q/--quiet suppresses all output when searching for NAME
5376 and shows only the path names when listing all definitions.
5376 and shows only the path names when listing all definitions.
5377
5377
5378 Path names are defined in the [paths] section of your
5378 Path names are defined in the [paths] section of your
5379 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5379 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5380 repository, ``.hg/hgrc`` is used, too.
5380 repository, ``.hg/hgrc`` is used, too.
5381
5381
5382 The path names ``default`` and ``default-push`` have a special
5382 The path names ``default`` and ``default-push`` have a special
5383 meaning. When performing a push or pull operation, they are used
5383 meaning. When performing a push or pull operation, they are used
5384 as fallbacks if no location is specified on the command-line.
5384 as fallbacks if no location is specified on the command-line.
5385 When ``default-push`` is set, it will be used for push and
5385 When ``default-push`` is set, it will be used for push and
5386 ``default`` will be used for pull; otherwise ``default`` is used
5386 ``default`` will be used for pull; otherwise ``default`` is used
5387 as the fallback for both. When cloning a repository, the clone
5387 as the fallback for both. When cloning a repository, the clone
5388 source is written as ``default`` in ``.hg/hgrc``.
5388 source is written as ``default`` in ``.hg/hgrc``.
5389
5389
5390 .. note::
5390 .. note::
5391
5391
5392 ``default`` and ``default-push`` apply to all inbound (e.g.
5392 ``default`` and ``default-push`` apply to all inbound (e.g.
5393 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5393 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5394 and :hg:`bundle`) operations.
5394 and :hg:`bundle`) operations.
5395
5395
5396 See :hg:`help urls` for more information.
5396 See :hg:`help urls` for more information.
5397
5397
5398 Returns 0 on success.
5398 Returns 0 on success.
5399 """
5399 """
5400 if search:
5400 if search:
5401 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5401 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5402 if name == search]
5402 if name == search]
5403 else:
5403 else:
5404 pathitems = sorted(ui.paths.iteritems())
5404 pathitems = sorted(ui.paths.iteritems())
5405
5405
5406 fm = ui.formatter('paths', opts)
5407 if fm:
5408 hidepassword = str
5409 else:
5410 hidepassword = util.hidepassword
5406 if ui.quiet:
5411 if ui.quiet:
5407 namefmt = '%s\n'
5412 namefmt = '%s\n'
5408 else:
5413 else:
5409 namefmt = '%s = '
5414 namefmt = '%s = '
5410 showsubopts = not search and not ui.quiet
5415 showsubopts = not search and not ui.quiet
5411
5416
5412 for name, path in pathitems:
5417 for name, path in pathitems:
5413 if not search:
5418 fm.startitem()
5414 ui.write(namefmt % name)
5419 fm.condwrite(not search, 'name', namefmt, name)
5415 if not ui.quiet:
5420 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5416 ui.write("%s\n" % util.hidepassword(path.rawloc))
5417 for subopt, value in sorted(path.suboptions.items()):
5421 for subopt, value in sorted(path.suboptions.items()):
5422 assert subopt not in ('name', 'url')
5418 if showsubopts:
5423 if showsubopts:
5419 ui.write('%s:%s = %s\n' % (name, subopt, value))
5424 fm.plain('%s:%s = ' % (name, subopt))
5425 fm.condwrite(showsubopts, subopt, '%s\n', value)
5426
5427 fm.end()
5420
5428
5421 if search and not pathitems:
5429 if search and not pathitems:
5422 if not ui.quiet:
5430 if not ui.quiet:
5423 ui.warn(_("not found!\n"))
5431 ui.warn(_("not found!\n"))
5424 return 1
5432 return 1
5425 else:
5433 else:
5426 return 0
5434 return 0
5427
5435
5428 @command('phase',
5436 @command('phase',
5429 [('p', 'public', False, _('set changeset phase to public')),
5437 [('p', 'public', False, _('set changeset phase to public')),
5430 ('d', 'draft', False, _('set changeset phase to draft')),
5438 ('d', 'draft', False, _('set changeset phase to draft')),
5431 ('s', 'secret', False, _('set changeset phase to secret')),
5439 ('s', 'secret', False, _('set changeset phase to secret')),
5432 ('f', 'force', False, _('allow to move boundary backward')),
5440 ('f', 'force', False, _('allow to move boundary backward')),
5433 ('r', 'rev', [], _('target revision'), _('REV')),
5441 ('r', 'rev', [], _('target revision'), _('REV')),
5434 ],
5442 ],
5435 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5443 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5436 def phase(ui, repo, *revs, **opts):
5444 def phase(ui, repo, *revs, **opts):
5437 """set or show the current phase name
5445 """set or show the current phase name
5438
5446
5439 With no argument, show the phase name of the current revision(s).
5447 With no argument, show the phase name of the current revision(s).
5440
5448
5441 With one of -p/--public, -d/--draft or -s/--secret, change the
5449 With one of -p/--public, -d/--draft or -s/--secret, change the
5442 phase value of the specified revisions.
5450 phase value of the specified revisions.
5443
5451
5444 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5452 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5445 lower phase to an higher phase. Phases are ordered as follows::
5453 lower phase to an higher phase. Phases are ordered as follows::
5446
5454
5447 public < draft < secret
5455 public < draft < secret
5448
5456
5449 Returns 0 on success, 1 if some phases could not be changed.
5457 Returns 0 on success, 1 if some phases could not be changed.
5450
5458
5451 (For more information about the phases concept, see :hg:`help phases`.)
5459 (For more information about the phases concept, see :hg:`help phases`.)
5452 """
5460 """
5453 # search for a unique phase argument
5461 # search for a unique phase argument
5454 targetphase = None
5462 targetphase = None
5455 for idx, name in enumerate(phases.phasenames):
5463 for idx, name in enumerate(phases.phasenames):
5456 if opts[name]:
5464 if opts[name]:
5457 if targetphase is not None:
5465 if targetphase is not None:
5458 raise error.Abort(_('only one phase can be specified'))
5466 raise error.Abort(_('only one phase can be specified'))
5459 targetphase = idx
5467 targetphase = idx
5460
5468
5461 # look for specified revision
5469 # look for specified revision
5462 revs = list(revs)
5470 revs = list(revs)
5463 revs.extend(opts['rev'])
5471 revs.extend(opts['rev'])
5464 if not revs:
5472 if not revs:
5465 # display both parents as the second parent phase can influence
5473 # display both parents as the second parent phase can influence
5466 # the phase of a merge commit
5474 # the phase of a merge commit
5467 revs = [c.rev() for c in repo[None].parents()]
5475 revs = [c.rev() for c in repo[None].parents()]
5468
5476
5469 revs = scmutil.revrange(repo, revs)
5477 revs = scmutil.revrange(repo, revs)
5470
5478
5471 lock = None
5479 lock = None
5472 ret = 0
5480 ret = 0
5473 if targetphase is None:
5481 if targetphase is None:
5474 # display
5482 # display
5475 for r in revs:
5483 for r in revs:
5476 ctx = repo[r]
5484 ctx = repo[r]
5477 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5485 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5478 else:
5486 else:
5479 tr = None
5487 tr = None
5480 lock = repo.lock()
5488 lock = repo.lock()
5481 try:
5489 try:
5482 tr = repo.transaction("phase")
5490 tr = repo.transaction("phase")
5483 # set phase
5491 # set phase
5484 if not revs:
5492 if not revs:
5485 raise error.Abort(_('empty revision set'))
5493 raise error.Abort(_('empty revision set'))
5486 nodes = [repo[r].node() for r in revs]
5494 nodes = [repo[r].node() for r in revs]
5487 # moving revision from public to draft may hide them
5495 # moving revision from public to draft may hide them
5488 # We have to check result on an unfiltered repository
5496 # We have to check result on an unfiltered repository
5489 unfi = repo.unfiltered()
5497 unfi = repo.unfiltered()
5490 getphase = unfi._phasecache.phase
5498 getphase = unfi._phasecache.phase
5491 olddata = [getphase(unfi, r) for r in unfi]
5499 olddata = [getphase(unfi, r) for r in unfi]
5492 phases.advanceboundary(repo, tr, targetphase, nodes)
5500 phases.advanceboundary(repo, tr, targetphase, nodes)
5493 if opts['force']:
5501 if opts['force']:
5494 phases.retractboundary(repo, tr, targetphase, nodes)
5502 phases.retractboundary(repo, tr, targetphase, nodes)
5495 tr.close()
5503 tr.close()
5496 finally:
5504 finally:
5497 if tr is not None:
5505 if tr is not None:
5498 tr.release()
5506 tr.release()
5499 lock.release()
5507 lock.release()
5500 getphase = unfi._phasecache.phase
5508 getphase = unfi._phasecache.phase
5501 newdata = [getphase(unfi, r) for r in unfi]
5509 newdata = [getphase(unfi, r) for r in unfi]
5502 changes = sum(newdata[r] != olddata[r] for r in unfi)
5510 changes = sum(newdata[r] != olddata[r] for r in unfi)
5503 cl = unfi.changelog
5511 cl = unfi.changelog
5504 rejected = [n for n in nodes
5512 rejected = [n for n in nodes
5505 if newdata[cl.rev(n)] < targetphase]
5513 if newdata[cl.rev(n)] < targetphase]
5506 if rejected:
5514 if rejected:
5507 ui.warn(_('cannot move %i changesets to a higher '
5515 ui.warn(_('cannot move %i changesets to a higher '
5508 'phase, use --force\n') % len(rejected))
5516 'phase, use --force\n') % len(rejected))
5509 ret = 1
5517 ret = 1
5510 if changes:
5518 if changes:
5511 msg = _('phase changed for %i changesets\n') % changes
5519 msg = _('phase changed for %i changesets\n') % changes
5512 if ret:
5520 if ret:
5513 ui.status(msg)
5521 ui.status(msg)
5514 else:
5522 else:
5515 ui.note(msg)
5523 ui.note(msg)
5516 else:
5524 else:
5517 ui.warn(_('no phases changed\n'))
5525 ui.warn(_('no phases changed\n'))
5518 return ret
5526 return ret
5519
5527
5520 def postincoming(ui, repo, modheads, optupdate, checkout):
5528 def postincoming(ui, repo, modheads, optupdate, checkout):
5521 if modheads == 0:
5529 if modheads == 0:
5522 return
5530 return
5523 if optupdate:
5531 if optupdate:
5524 try:
5532 try:
5525 brev = checkout
5533 brev = checkout
5526 movemarkfrom = None
5534 movemarkfrom = None
5527 if not checkout:
5535 if not checkout:
5528 updata = destutil.destupdate(repo)
5536 updata = destutil.destupdate(repo)
5529 checkout, movemarkfrom, brev = updata
5537 checkout, movemarkfrom, brev = updata
5530 ret = hg.update(repo, checkout)
5538 ret = hg.update(repo, checkout)
5531 except error.UpdateAbort as inst:
5539 except error.UpdateAbort as inst:
5532 msg = _("not updating: %s") % str(inst)
5540 msg = _("not updating: %s") % str(inst)
5533 hint = inst.hint
5541 hint = inst.hint
5534 raise error.UpdateAbort(msg, hint=hint)
5542 raise error.UpdateAbort(msg, hint=hint)
5535 if not ret and not checkout:
5543 if not ret and not checkout:
5536 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5544 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5537 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5545 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5538 return ret
5546 return ret
5539 if modheads > 1:
5547 if modheads > 1:
5540 currentbranchheads = len(repo.branchheads())
5548 currentbranchheads = len(repo.branchheads())
5541 if currentbranchheads == modheads:
5549 if currentbranchheads == modheads:
5542 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5550 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5543 elif currentbranchheads > 1:
5551 elif currentbranchheads > 1:
5544 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5552 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5545 "merge)\n"))
5553 "merge)\n"))
5546 else:
5554 else:
5547 ui.status(_("(run 'hg heads' to see heads)\n"))
5555 ui.status(_("(run 'hg heads' to see heads)\n"))
5548 else:
5556 else:
5549 ui.status(_("(run 'hg update' to get a working copy)\n"))
5557 ui.status(_("(run 'hg update' to get a working copy)\n"))
5550
5558
5551 @command('^pull',
5559 @command('^pull',
5552 [('u', 'update', None,
5560 [('u', 'update', None,
5553 _('update to new branch head if changesets were pulled')),
5561 _('update to new branch head if changesets were pulled')),
5554 ('f', 'force', None, _('run even when remote repository is unrelated')),
5562 ('f', 'force', None, _('run even when remote repository is unrelated')),
5555 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5563 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5556 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5564 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5557 ('b', 'branch', [], _('a specific branch you would like to pull'),
5565 ('b', 'branch', [], _('a specific branch you would like to pull'),
5558 _('BRANCH')),
5566 _('BRANCH')),
5559 ] + remoteopts,
5567 ] + remoteopts,
5560 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5568 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5561 def pull(ui, repo, source="default", **opts):
5569 def pull(ui, repo, source="default", **opts):
5562 """pull changes from the specified source
5570 """pull changes from the specified source
5563
5571
5564 Pull changes from a remote repository to a local one.
5572 Pull changes from a remote repository to a local one.
5565
5573
5566 This finds all changes from the repository at the specified path
5574 This finds all changes from the repository at the specified path
5567 or URL and adds them to a local repository (the current one unless
5575 or URL and adds them to a local repository (the current one unless
5568 -R is specified). By default, this does not update the copy of the
5576 -R is specified). By default, this does not update the copy of the
5569 project in the working directory.
5577 project in the working directory.
5570
5578
5571 Use :hg:`incoming` if you want to see what would have been added
5579 Use :hg:`incoming` if you want to see what would have been added
5572 by a pull at the time you issued this command. If you then decide
5580 by a pull at the time you issued this command. If you then decide
5573 to add those changes to the repository, you should use :hg:`pull
5581 to add those changes to the repository, you should use :hg:`pull
5574 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5582 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5575
5583
5576 If SOURCE is omitted, the 'default' path will be used.
5584 If SOURCE is omitted, the 'default' path will be used.
5577 See :hg:`help urls` for more information.
5585 See :hg:`help urls` for more information.
5578
5586
5579 Returns 0 on success, 1 if an update had unresolved files.
5587 Returns 0 on success, 1 if an update had unresolved files.
5580 """
5588 """
5581 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5589 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5582 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5590 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5583 other = hg.peer(repo, opts, source)
5591 other = hg.peer(repo, opts, source)
5584 try:
5592 try:
5585 revs, checkout = hg.addbranchrevs(repo, other, branches,
5593 revs, checkout = hg.addbranchrevs(repo, other, branches,
5586 opts.get('rev'))
5594 opts.get('rev'))
5587
5595
5588
5596
5589 pullopargs = {}
5597 pullopargs = {}
5590 if opts.get('bookmark'):
5598 if opts.get('bookmark'):
5591 if not revs:
5599 if not revs:
5592 revs = []
5600 revs = []
5593 # The list of bookmark used here is not the one used to actually
5601 # The list of bookmark used here is not the one used to actually
5594 # update the bookmark name. This can result in the revision pulled
5602 # update the bookmark name. This can result in the revision pulled
5595 # not ending up with the name of the bookmark because of a race
5603 # not ending up with the name of the bookmark because of a race
5596 # condition on the server. (See issue 4689 for details)
5604 # condition on the server. (See issue 4689 for details)
5597 remotebookmarks = other.listkeys('bookmarks')
5605 remotebookmarks = other.listkeys('bookmarks')
5598 pullopargs['remotebookmarks'] = remotebookmarks
5606 pullopargs['remotebookmarks'] = remotebookmarks
5599 for b in opts['bookmark']:
5607 for b in opts['bookmark']:
5600 if b not in remotebookmarks:
5608 if b not in remotebookmarks:
5601 raise error.Abort(_('remote bookmark %s not found!') % b)
5609 raise error.Abort(_('remote bookmark %s not found!') % b)
5602 revs.append(remotebookmarks[b])
5610 revs.append(remotebookmarks[b])
5603
5611
5604 if revs:
5612 if revs:
5605 try:
5613 try:
5606 # When 'rev' is a bookmark name, we cannot guarantee that it
5614 # When 'rev' is a bookmark name, we cannot guarantee that it
5607 # will be updated with that name because of a race condition
5615 # will be updated with that name because of a race condition
5608 # server side. (See issue 4689 for details)
5616 # server side. (See issue 4689 for details)
5609 oldrevs = revs
5617 oldrevs = revs
5610 revs = [] # actually, nodes
5618 revs = [] # actually, nodes
5611 for r in oldrevs:
5619 for r in oldrevs:
5612 node = other.lookup(r)
5620 node = other.lookup(r)
5613 revs.append(node)
5621 revs.append(node)
5614 if r == checkout:
5622 if r == checkout:
5615 checkout = node
5623 checkout = node
5616 except error.CapabilityError:
5624 except error.CapabilityError:
5617 err = _("other repository doesn't support revision lookup, "
5625 err = _("other repository doesn't support revision lookup, "
5618 "so a rev cannot be specified.")
5626 "so a rev cannot be specified.")
5619 raise error.Abort(err)
5627 raise error.Abort(err)
5620
5628
5621 pullopargs.update(opts.get('opargs', {}))
5629 pullopargs.update(opts.get('opargs', {}))
5622 modheads = exchange.pull(repo, other, heads=revs,
5630 modheads = exchange.pull(repo, other, heads=revs,
5623 force=opts.get('force'),
5631 force=opts.get('force'),
5624 bookmarks=opts.get('bookmark', ()),
5632 bookmarks=opts.get('bookmark', ()),
5625 opargs=pullopargs).cgresult
5633 opargs=pullopargs).cgresult
5626 if checkout:
5634 if checkout:
5627 checkout = str(repo.changelog.rev(checkout))
5635 checkout = str(repo.changelog.rev(checkout))
5628 repo._subtoppath = source
5636 repo._subtoppath = source
5629 try:
5637 try:
5630 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5638 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5631
5639
5632 finally:
5640 finally:
5633 del repo._subtoppath
5641 del repo._subtoppath
5634
5642
5635 finally:
5643 finally:
5636 other.close()
5644 other.close()
5637 return ret
5645 return ret
5638
5646
5639 @command('^push',
5647 @command('^push',
5640 [('f', 'force', None, _('force push')),
5648 [('f', 'force', None, _('force push')),
5641 ('r', 'rev', [],
5649 ('r', 'rev', [],
5642 _('a changeset intended to be included in the destination'),
5650 _('a changeset intended to be included in the destination'),
5643 _('REV')),
5651 _('REV')),
5644 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5652 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5645 ('b', 'branch', [],
5653 ('b', 'branch', [],
5646 _('a specific branch you would like to push'), _('BRANCH')),
5654 _('a specific branch you would like to push'), _('BRANCH')),
5647 ('', 'new-branch', False, _('allow pushing a new branch')),
5655 ('', 'new-branch', False, _('allow pushing a new branch')),
5648 ] + remoteopts,
5656 ] + remoteopts,
5649 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5657 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5650 def push(ui, repo, dest=None, **opts):
5658 def push(ui, repo, dest=None, **opts):
5651 """push changes to the specified destination
5659 """push changes to the specified destination
5652
5660
5653 Push changesets from the local repository to the specified
5661 Push changesets from the local repository to the specified
5654 destination.
5662 destination.
5655
5663
5656 This operation is symmetrical to pull: it is identical to a pull
5664 This operation is symmetrical to pull: it is identical to a pull
5657 in the destination repository from the current one.
5665 in the destination repository from the current one.
5658
5666
5659 By default, push will not allow creation of new heads at the
5667 By default, push will not allow creation of new heads at the
5660 destination, since multiple heads would make it unclear which head
5668 destination, since multiple heads would make it unclear which head
5661 to use. In this situation, it is recommended to pull and merge
5669 to use. In this situation, it is recommended to pull and merge
5662 before pushing.
5670 before pushing.
5663
5671
5664 Use --new-branch if you want to allow push to create a new named
5672 Use --new-branch if you want to allow push to create a new named
5665 branch that is not present at the destination. This allows you to
5673 branch that is not present at the destination. This allows you to
5666 only create a new branch without forcing other changes.
5674 only create a new branch without forcing other changes.
5667
5675
5668 .. note::
5676 .. note::
5669
5677
5670 Extra care should be taken with the -f/--force option,
5678 Extra care should be taken with the -f/--force option,
5671 which will push all new heads on all branches, an action which will
5679 which will push all new heads on all branches, an action which will
5672 almost always cause confusion for collaborators.
5680 almost always cause confusion for collaborators.
5673
5681
5674 If -r/--rev is used, the specified revision and all its ancestors
5682 If -r/--rev is used, the specified revision and all its ancestors
5675 will be pushed to the remote repository.
5683 will be pushed to the remote repository.
5676
5684
5677 If -B/--bookmark is used, the specified bookmarked revision, its
5685 If -B/--bookmark is used, the specified bookmarked revision, its
5678 ancestors, and the bookmark will be pushed to the remote
5686 ancestors, and the bookmark will be pushed to the remote
5679 repository.
5687 repository.
5680
5688
5681 Please see :hg:`help urls` for important details about ``ssh://``
5689 Please see :hg:`help urls` for important details about ``ssh://``
5682 URLs. If DESTINATION is omitted, a default path will be used.
5690 URLs. If DESTINATION is omitted, a default path will be used.
5683
5691
5684 Returns 0 if push was successful, 1 if nothing to push.
5692 Returns 0 if push was successful, 1 if nothing to push.
5685 """
5693 """
5686
5694
5687 if opts.get('bookmark'):
5695 if opts.get('bookmark'):
5688 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5696 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5689 for b in opts['bookmark']:
5697 for b in opts['bookmark']:
5690 # translate -B options to -r so changesets get pushed
5698 # translate -B options to -r so changesets get pushed
5691 if b in repo._bookmarks:
5699 if b in repo._bookmarks:
5692 opts.setdefault('rev', []).append(b)
5700 opts.setdefault('rev', []).append(b)
5693 else:
5701 else:
5694 # if we try to push a deleted bookmark, translate it to null
5702 # if we try to push a deleted bookmark, translate it to null
5695 # this lets simultaneous -r, -b options continue working
5703 # this lets simultaneous -r, -b options continue working
5696 opts.setdefault('rev', []).append("null")
5704 opts.setdefault('rev', []).append("null")
5697
5705
5698 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5706 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5699 if not path:
5707 if not path:
5700 raise error.Abort(_('default repository not configured!'),
5708 raise error.Abort(_('default repository not configured!'),
5701 hint=_('see the "path" section in "hg help config"'))
5709 hint=_('see the "path" section in "hg help config"'))
5702 dest = path.pushloc or path.loc
5710 dest = path.pushloc or path.loc
5703 branches = (path.branch, opts.get('branch') or [])
5711 branches = (path.branch, opts.get('branch') or [])
5704 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5712 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5705 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5713 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5706 other = hg.peer(repo, opts, dest)
5714 other = hg.peer(repo, opts, dest)
5707
5715
5708 if revs:
5716 if revs:
5709 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5717 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5710 if not revs:
5718 if not revs:
5711 raise error.Abort(_("specified revisions evaluate to an empty set"),
5719 raise error.Abort(_("specified revisions evaluate to an empty set"),
5712 hint=_("use different revision arguments"))
5720 hint=_("use different revision arguments"))
5713
5721
5714 repo._subtoppath = dest
5722 repo._subtoppath = dest
5715 try:
5723 try:
5716 # push subrepos depth-first for coherent ordering
5724 # push subrepos depth-first for coherent ordering
5717 c = repo['']
5725 c = repo['']
5718 subs = c.substate # only repos that are committed
5726 subs = c.substate # only repos that are committed
5719 for s in sorted(subs):
5727 for s in sorted(subs):
5720 result = c.sub(s).push(opts)
5728 result = c.sub(s).push(opts)
5721 if result == 0:
5729 if result == 0:
5722 return not result
5730 return not result
5723 finally:
5731 finally:
5724 del repo._subtoppath
5732 del repo._subtoppath
5725 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5733 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5726 newbranch=opts.get('new_branch'),
5734 newbranch=opts.get('new_branch'),
5727 bookmarks=opts.get('bookmark', ()),
5735 bookmarks=opts.get('bookmark', ()),
5728 opargs=opts.get('opargs'))
5736 opargs=opts.get('opargs'))
5729
5737
5730 result = not pushop.cgresult
5738 result = not pushop.cgresult
5731
5739
5732 if pushop.bkresult is not None:
5740 if pushop.bkresult is not None:
5733 if pushop.bkresult == 2:
5741 if pushop.bkresult == 2:
5734 result = 2
5742 result = 2
5735 elif not result and pushop.bkresult:
5743 elif not result and pushop.bkresult:
5736 result = 2
5744 result = 2
5737
5745
5738 return result
5746 return result
5739
5747
5740 @command('recover', [])
5748 @command('recover', [])
5741 def recover(ui, repo):
5749 def recover(ui, repo):
5742 """roll back an interrupted transaction
5750 """roll back an interrupted transaction
5743
5751
5744 Recover from an interrupted commit or pull.
5752 Recover from an interrupted commit or pull.
5745
5753
5746 This command tries to fix the repository status after an
5754 This command tries to fix the repository status after an
5747 interrupted operation. It should only be necessary when Mercurial
5755 interrupted operation. It should only be necessary when Mercurial
5748 suggests it.
5756 suggests it.
5749
5757
5750 Returns 0 if successful, 1 if nothing to recover or verify fails.
5758 Returns 0 if successful, 1 if nothing to recover or verify fails.
5751 """
5759 """
5752 if repo.recover():
5760 if repo.recover():
5753 return hg.verify(repo)
5761 return hg.verify(repo)
5754 return 1
5762 return 1
5755
5763
5756 @command('^remove|rm',
5764 @command('^remove|rm',
5757 [('A', 'after', None, _('record delete for missing files')),
5765 [('A', 'after', None, _('record delete for missing files')),
5758 ('f', 'force', None,
5766 ('f', 'force', None,
5759 _('remove (and delete) file even if added or modified')),
5767 _('remove (and delete) file even if added or modified')),
5760 ] + subrepoopts + walkopts,
5768 ] + subrepoopts + walkopts,
5761 _('[OPTION]... FILE...'),
5769 _('[OPTION]... FILE...'),
5762 inferrepo=True)
5770 inferrepo=True)
5763 def remove(ui, repo, *pats, **opts):
5771 def remove(ui, repo, *pats, **opts):
5764 """remove the specified files on the next commit
5772 """remove the specified files on the next commit
5765
5773
5766 Schedule the indicated files for removal from the current branch.
5774 Schedule the indicated files for removal from the current branch.
5767
5775
5768 This command schedules the files to be removed at the next commit.
5776 This command schedules the files to be removed at the next commit.
5769 To undo a remove before that, see :hg:`revert`. To undo added
5777 To undo a remove before that, see :hg:`revert`. To undo added
5770 files, see :hg:`forget`.
5778 files, see :hg:`forget`.
5771
5779
5772 .. container:: verbose
5780 .. container:: verbose
5773
5781
5774 -A/--after can be used to remove only files that have already
5782 -A/--after can be used to remove only files that have already
5775 been deleted, -f/--force can be used to force deletion, and -Af
5783 been deleted, -f/--force can be used to force deletion, and -Af
5776 can be used to remove files from the next revision without
5784 can be used to remove files from the next revision without
5777 deleting them from the working directory.
5785 deleting them from the working directory.
5778
5786
5779 The following table details the behavior of remove for different
5787 The following table details the behavior of remove for different
5780 file states (columns) and option combinations (rows). The file
5788 file states (columns) and option combinations (rows). The file
5781 states are Added [A], Clean [C], Modified [M] and Missing [!]
5789 states are Added [A], Clean [C], Modified [M] and Missing [!]
5782 (as reported by :hg:`status`). The actions are Warn, Remove
5790 (as reported by :hg:`status`). The actions are Warn, Remove
5783 (from branch) and Delete (from disk):
5791 (from branch) and Delete (from disk):
5784
5792
5785 ========= == == == ==
5793 ========= == == == ==
5786 opt/state A C M !
5794 opt/state A C M !
5787 ========= == == == ==
5795 ========= == == == ==
5788 none W RD W R
5796 none W RD W R
5789 -f R RD RD R
5797 -f R RD RD R
5790 -A W W W R
5798 -A W W W R
5791 -Af R R R R
5799 -Af R R R R
5792 ========= == == == ==
5800 ========= == == == ==
5793
5801
5794 .. note::
5802 .. note::
5795
5803
5796 :hg:`remove` never deletes files in Added [A] state from the
5804 :hg:`remove` never deletes files in Added [A] state from the
5797 working directory, not even if ``--force`` is specified.
5805 working directory, not even if ``--force`` is specified.
5798
5806
5799 Returns 0 on success, 1 if any warnings encountered.
5807 Returns 0 on success, 1 if any warnings encountered.
5800 """
5808 """
5801
5809
5802 after, force = opts.get('after'), opts.get('force')
5810 after, force = opts.get('after'), opts.get('force')
5803 if not pats and not after:
5811 if not pats and not after:
5804 raise error.Abort(_('no files specified'))
5812 raise error.Abort(_('no files specified'))
5805
5813
5806 m = scmutil.match(repo[None], pats, opts)
5814 m = scmutil.match(repo[None], pats, opts)
5807 subrepos = opts.get('subrepos')
5815 subrepos = opts.get('subrepos')
5808 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5816 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5809
5817
5810 @command('rename|move|mv',
5818 @command('rename|move|mv',
5811 [('A', 'after', None, _('record a rename that has already occurred')),
5819 [('A', 'after', None, _('record a rename that has already occurred')),
5812 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5820 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5813 ] + walkopts + dryrunopts,
5821 ] + walkopts + dryrunopts,
5814 _('[OPTION]... SOURCE... DEST'))
5822 _('[OPTION]... SOURCE... DEST'))
5815 def rename(ui, repo, *pats, **opts):
5823 def rename(ui, repo, *pats, **opts):
5816 """rename files; equivalent of copy + remove
5824 """rename files; equivalent of copy + remove
5817
5825
5818 Mark dest as copies of sources; mark sources for deletion. If dest
5826 Mark dest as copies of sources; mark sources for deletion. If dest
5819 is a directory, copies are put in that directory. If dest is a
5827 is a directory, copies are put in that directory. If dest is a
5820 file, there can only be one source.
5828 file, there can only be one source.
5821
5829
5822 By default, this command copies the contents of files as they
5830 By default, this command copies the contents of files as they
5823 exist in the working directory. If invoked with -A/--after, the
5831 exist in the working directory. If invoked with -A/--after, the
5824 operation is recorded, but no copying is performed.
5832 operation is recorded, but no copying is performed.
5825
5833
5826 This command takes effect at the next commit. To undo a rename
5834 This command takes effect at the next commit. To undo a rename
5827 before that, see :hg:`revert`.
5835 before that, see :hg:`revert`.
5828
5836
5829 Returns 0 on success, 1 if errors are encountered.
5837 Returns 0 on success, 1 if errors are encountered.
5830 """
5838 """
5831 wlock = repo.wlock(False)
5839 wlock = repo.wlock(False)
5832 try:
5840 try:
5833 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5841 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5834 finally:
5842 finally:
5835 wlock.release()
5843 wlock.release()
5836
5844
5837 @command('resolve',
5845 @command('resolve',
5838 [('a', 'all', None, _('select all unresolved files')),
5846 [('a', 'all', None, _('select all unresolved files')),
5839 ('l', 'list', None, _('list state of files needing merge')),
5847 ('l', 'list', None, _('list state of files needing merge')),
5840 ('m', 'mark', None, _('mark files as resolved')),
5848 ('m', 'mark', None, _('mark files as resolved')),
5841 ('u', 'unmark', None, _('mark files as unresolved')),
5849 ('u', 'unmark', None, _('mark files as unresolved')),
5842 ('n', 'no-status', None, _('hide status prefix'))]
5850 ('n', 'no-status', None, _('hide status prefix'))]
5843 + mergetoolopts + walkopts + formatteropts,
5851 + mergetoolopts + walkopts + formatteropts,
5844 _('[OPTION]... [FILE]...'),
5852 _('[OPTION]... [FILE]...'),
5845 inferrepo=True)
5853 inferrepo=True)
5846 def resolve(ui, repo, *pats, **opts):
5854 def resolve(ui, repo, *pats, **opts):
5847 """redo merges or set/view the merge status of files
5855 """redo merges or set/view the merge status of files
5848
5856
5849 Merges with unresolved conflicts are often the result of
5857 Merges with unresolved conflicts are often the result of
5850 non-interactive merging using the ``internal:merge`` configuration
5858 non-interactive merging using the ``internal:merge`` configuration
5851 setting, or a command-line merge tool like ``diff3``. The resolve
5859 setting, or a command-line merge tool like ``diff3``. The resolve
5852 command is used to manage the files involved in a merge, after
5860 command is used to manage the files involved in a merge, after
5853 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5861 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5854 working directory must have two parents). See :hg:`help
5862 working directory must have two parents). See :hg:`help
5855 merge-tools` for information on configuring merge tools.
5863 merge-tools` for information on configuring merge tools.
5856
5864
5857 The resolve command can be used in the following ways:
5865 The resolve command can be used in the following ways:
5858
5866
5859 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5867 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5860 files, discarding any previous merge attempts. Re-merging is not
5868 files, discarding any previous merge attempts. Re-merging is not
5861 performed for files already marked as resolved. Use ``--all/-a``
5869 performed for files already marked as resolved. Use ``--all/-a``
5862 to select all unresolved files. ``--tool`` can be used to specify
5870 to select all unresolved files. ``--tool`` can be used to specify
5863 the merge tool used for the given files. It overrides the HGMERGE
5871 the merge tool used for the given files. It overrides the HGMERGE
5864 environment variable and your configuration files. Previous file
5872 environment variable and your configuration files. Previous file
5865 contents are saved with a ``.orig`` suffix.
5873 contents are saved with a ``.orig`` suffix.
5866
5874
5867 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5875 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5868 (e.g. after having manually fixed-up the files). The default is
5876 (e.g. after having manually fixed-up the files). The default is
5869 to mark all unresolved files.
5877 to mark all unresolved files.
5870
5878
5871 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5879 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5872 default is to mark all resolved files.
5880 default is to mark all resolved files.
5873
5881
5874 - :hg:`resolve -l`: list files which had or still have conflicts.
5882 - :hg:`resolve -l`: list files which had or still have conflicts.
5875 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5883 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5876
5884
5877 .. note::
5885 .. note::
5878
5886
5879 Mercurial will not let you commit files with unresolved merge
5887 Mercurial will not let you commit files with unresolved merge
5880 conflicts. You must use :hg:`resolve -m ...` before you can
5888 conflicts. You must use :hg:`resolve -m ...` before you can
5881 commit after a conflicting merge.
5889 commit after a conflicting merge.
5882
5890
5883 Returns 0 on success, 1 if any files fail a resolve attempt.
5891 Returns 0 on success, 1 if any files fail a resolve attempt.
5884 """
5892 """
5885
5893
5886 all, mark, unmark, show, nostatus = \
5894 all, mark, unmark, show, nostatus = \
5887 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5895 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5888
5896
5889 if (show and (mark or unmark)) or (mark and unmark):
5897 if (show and (mark or unmark)) or (mark and unmark):
5890 raise error.Abort(_("too many options specified"))
5898 raise error.Abort(_("too many options specified"))
5891 if pats and all:
5899 if pats and all:
5892 raise error.Abort(_("can't specify --all and patterns"))
5900 raise error.Abort(_("can't specify --all and patterns"))
5893 if not (all or pats or show or mark or unmark):
5901 if not (all or pats or show or mark or unmark):
5894 raise error.Abort(_('no files or directories specified'),
5902 raise error.Abort(_('no files or directories specified'),
5895 hint=('use --all to re-merge all unresolved files'))
5903 hint=('use --all to re-merge all unresolved files'))
5896
5904
5897 if show:
5905 if show:
5898 fm = ui.formatter('resolve', opts)
5906 fm = ui.formatter('resolve', opts)
5899 ms = mergemod.mergestate.read(repo)
5907 ms = mergemod.mergestate.read(repo)
5900 m = scmutil.match(repo[None], pats, opts)
5908 m = scmutil.match(repo[None], pats, opts)
5901 for f in ms:
5909 for f in ms:
5902 if not m(f):
5910 if not m(f):
5903 continue
5911 continue
5904 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5912 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5905 'd': 'driverresolved'}[ms[f]]
5913 'd': 'driverresolved'}[ms[f]]
5906 fm.startitem()
5914 fm.startitem()
5907 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5915 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5908 fm.write('path', '%s\n', f, label=l)
5916 fm.write('path', '%s\n', f, label=l)
5909 fm.end()
5917 fm.end()
5910 return 0
5918 return 0
5911
5919
5912 wlock = repo.wlock()
5920 wlock = repo.wlock()
5913 try:
5921 try:
5914 ms = mergemod.mergestate.read(repo)
5922 ms = mergemod.mergestate.read(repo)
5915
5923
5916 if not (ms.active() or repo.dirstate.p2() != nullid):
5924 if not (ms.active() or repo.dirstate.p2() != nullid):
5917 raise error.Abort(
5925 raise error.Abort(
5918 _('resolve command not applicable when not merging'))
5926 _('resolve command not applicable when not merging'))
5919
5927
5920 wctx = repo[None]
5928 wctx = repo[None]
5921
5929
5922 if ms.mergedriver and ms.mdstate() == 'u':
5930 if ms.mergedriver and ms.mdstate() == 'u':
5923 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5931 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5924 ms.commit()
5932 ms.commit()
5925 # allow mark and unmark to go through
5933 # allow mark and unmark to go through
5926 if not mark and not unmark and not proceed:
5934 if not mark and not unmark and not proceed:
5927 return 1
5935 return 1
5928
5936
5929 m = scmutil.match(wctx, pats, opts)
5937 m = scmutil.match(wctx, pats, opts)
5930 ret = 0
5938 ret = 0
5931 didwork = False
5939 didwork = False
5932 runconclude = False
5940 runconclude = False
5933
5941
5934 tocomplete = []
5942 tocomplete = []
5935 for f in ms:
5943 for f in ms:
5936 if not m(f):
5944 if not m(f):
5937 continue
5945 continue
5938
5946
5939 didwork = True
5947 didwork = True
5940
5948
5941 # don't let driver-resolved files be marked, and run the conclude
5949 # don't let driver-resolved files be marked, and run the conclude
5942 # step if asked to resolve
5950 # step if asked to resolve
5943 if ms[f] == "d":
5951 if ms[f] == "d":
5944 exact = m.exact(f)
5952 exact = m.exact(f)
5945 if mark:
5953 if mark:
5946 if exact:
5954 if exact:
5947 ui.warn(_('not marking %s as it is driver-resolved\n')
5955 ui.warn(_('not marking %s as it is driver-resolved\n')
5948 % f)
5956 % f)
5949 elif unmark:
5957 elif unmark:
5950 if exact:
5958 if exact:
5951 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5959 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5952 % f)
5960 % f)
5953 else:
5961 else:
5954 runconclude = True
5962 runconclude = True
5955 continue
5963 continue
5956
5964
5957 if mark:
5965 if mark:
5958 ms.mark(f, "r")
5966 ms.mark(f, "r")
5959 elif unmark:
5967 elif unmark:
5960 ms.mark(f, "u")
5968 ms.mark(f, "u")
5961 else:
5969 else:
5962 # backup pre-resolve (merge uses .orig for its own purposes)
5970 # backup pre-resolve (merge uses .orig for its own purposes)
5963 a = repo.wjoin(f)
5971 a = repo.wjoin(f)
5964 try:
5972 try:
5965 util.copyfile(a, a + ".resolve")
5973 util.copyfile(a, a + ".resolve")
5966 except (IOError, OSError) as inst:
5974 except (IOError, OSError) as inst:
5967 if inst.errno != errno.ENOENT:
5975 if inst.errno != errno.ENOENT:
5968 raise
5976 raise
5969
5977
5970 try:
5978 try:
5971 # preresolve file
5979 # preresolve file
5972 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5980 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5973 'resolve')
5981 'resolve')
5974 complete, r = ms.preresolve(f, wctx)
5982 complete, r = ms.preresolve(f, wctx)
5975 if not complete:
5983 if not complete:
5976 tocomplete.append(f)
5984 tocomplete.append(f)
5977 elif r:
5985 elif r:
5978 ret = 1
5986 ret = 1
5979 finally:
5987 finally:
5980 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5988 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5981 ms.commit()
5989 ms.commit()
5982
5990
5983 # replace filemerge's .orig file with our resolve file, but only
5991 # replace filemerge's .orig file with our resolve file, but only
5984 # for merges that are complete
5992 # for merges that are complete
5985 if complete:
5993 if complete:
5986 try:
5994 try:
5987 util.rename(a + ".resolve",
5995 util.rename(a + ".resolve",
5988 scmutil.origpath(ui, repo, a))
5996 scmutil.origpath(ui, repo, a))
5989 except OSError as inst:
5997 except OSError as inst:
5990 if inst.errno != errno.ENOENT:
5998 if inst.errno != errno.ENOENT:
5991 raise
5999 raise
5992
6000
5993 for f in tocomplete:
6001 for f in tocomplete:
5994 try:
6002 try:
5995 # resolve file
6003 # resolve file
5996 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
6004 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5997 'resolve')
6005 'resolve')
5998 r = ms.resolve(f, wctx)
6006 r = ms.resolve(f, wctx)
5999 if r:
6007 if r:
6000 ret = 1
6008 ret = 1
6001 finally:
6009 finally:
6002 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6010 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6003 ms.commit()
6011 ms.commit()
6004
6012
6005 # replace filemerge's .orig file with our resolve file
6013 # replace filemerge's .orig file with our resolve file
6006 a = repo.wjoin(f)
6014 a = repo.wjoin(f)
6007 try:
6015 try:
6008 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6016 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6009 except OSError as inst:
6017 except OSError as inst:
6010 if inst.errno != errno.ENOENT:
6018 if inst.errno != errno.ENOENT:
6011 raise
6019 raise
6012
6020
6013 ms.commit()
6021 ms.commit()
6014 ms.recordactions()
6022 ms.recordactions()
6015
6023
6016 if not didwork and pats:
6024 if not didwork and pats:
6017 ui.warn(_("arguments do not match paths that need resolving\n"))
6025 ui.warn(_("arguments do not match paths that need resolving\n"))
6018 elif ms.mergedriver and ms.mdstate() != 's':
6026 elif ms.mergedriver and ms.mdstate() != 's':
6019 # run conclude step when either a driver-resolved file is requested
6027 # run conclude step when either a driver-resolved file is requested
6020 # or there are no driver-resolved files
6028 # or there are no driver-resolved files
6021 # we can't use 'ret' to determine whether any files are unresolved
6029 # we can't use 'ret' to determine whether any files are unresolved
6022 # because we might not have tried to resolve some
6030 # because we might not have tried to resolve some
6023 if ((runconclude or not list(ms.driverresolved()))
6031 if ((runconclude or not list(ms.driverresolved()))
6024 and not list(ms.unresolved())):
6032 and not list(ms.unresolved())):
6025 proceed = mergemod.driverconclude(repo, ms, wctx)
6033 proceed = mergemod.driverconclude(repo, ms, wctx)
6026 ms.commit()
6034 ms.commit()
6027 if not proceed:
6035 if not proceed:
6028 return 1
6036 return 1
6029
6037
6030 finally:
6038 finally:
6031 wlock.release()
6039 wlock.release()
6032
6040
6033 # Nudge users into finishing an unfinished operation
6041 # Nudge users into finishing an unfinished operation
6034 unresolvedf = list(ms.unresolved())
6042 unresolvedf = list(ms.unresolved())
6035 driverresolvedf = list(ms.driverresolved())
6043 driverresolvedf = list(ms.driverresolved())
6036 if not unresolvedf and not driverresolvedf:
6044 if not unresolvedf and not driverresolvedf:
6037 ui.status(_('(no more unresolved files)\n'))
6045 ui.status(_('(no more unresolved files)\n'))
6038 cmdutil.checkafterresolved(repo)
6046 cmdutil.checkafterresolved(repo)
6039 elif not unresolvedf:
6047 elif not unresolvedf:
6040 ui.status(_('(no more unresolved files -- '
6048 ui.status(_('(no more unresolved files -- '
6041 'run "hg resolve --all" to conclude)\n'))
6049 'run "hg resolve --all" to conclude)\n'))
6042
6050
6043 return ret
6051 return ret
6044
6052
6045 @command('revert',
6053 @command('revert',
6046 [('a', 'all', None, _('revert all changes when no arguments given')),
6054 [('a', 'all', None, _('revert all changes when no arguments given')),
6047 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6055 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6048 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6056 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6049 ('C', 'no-backup', None, _('do not save backup copies of files')),
6057 ('C', 'no-backup', None, _('do not save backup copies of files')),
6050 ('i', 'interactive', None,
6058 ('i', 'interactive', None,
6051 _('interactively select the changes (EXPERIMENTAL)')),
6059 _('interactively select the changes (EXPERIMENTAL)')),
6052 ] + walkopts + dryrunopts,
6060 ] + walkopts + dryrunopts,
6053 _('[OPTION]... [-r REV] [NAME]...'))
6061 _('[OPTION]... [-r REV] [NAME]...'))
6054 def revert(ui, repo, *pats, **opts):
6062 def revert(ui, repo, *pats, **opts):
6055 """restore files to their checkout state
6063 """restore files to their checkout state
6056
6064
6057 .. note::
6065 .. note::
6058
6066
6059 To check out earlier revisions, you should use :hg:`update REV`.
6067 To check out earlier revisions, you should use :hg:`update REV`.
6060 To cancel an uncommitted merge (and lose your changes),
6068 To cancel an uncommitted merge (and lose your changes),
6061 use :hg:`update --clean .`.
6069 use :hg:`update --clean .`.
6062
6070
6063 With no revision specified, revert the specified files or directories
6071 With no revision specified, revert the specified files or directories
6064 to the contents they had in the parent of the working directory.
6072 to the contents they had in the parent of the working directory.
6065 This restores the contents of files to an unmodified
6073 This restores the contents of files to an unmodified
6066 state and unschedules adds, removes, copies, and renames. If the
6074 state and unschedules adds, removes, copies, and renames. If the
6067 working directory has two parents, you must explicitly specify a
6075 working directory has two parents, you must explicitly specify a
6068 revision.
6076 revision.
6069
6077
6070 Using the -r/--rev or -d/--date options, revert the given files or
6078 Using the -r/--rev or -d/--date options, revert the given files or
6071 directories to their states as of a specific revision. Because
6079 directories to their states as of a specific revision. Because
6072 revert does not change the working directory parents, this will
6080 revert does not change the working directory parents, this will
6073 cause these files to appear modified. This can be helpful to "back
6081 cause these files to appear modified. This can be helpful to "back
6074 out" some or all of an earlier change. See :hg:`backout` for a
6082 out" some or all of an earlier change. See :hg:`backout` for a
6075 related method.
6083 related method.
6076
6084
6077 Modified files are saved with a .orig suffix before reverting.
6085 Modified files are saved with a .orig suffix before reverting.
6078 To disable these backups, use --no-backup.
6086 To disable these backups, use --no-backup.
6079
6087
6080 See :hg:`help dates` for a list of formats valid for -d/--date.
6088 See :hg:`help dates` for a list of formats valid for -d/--date.
6081
6089
6082 See :hg:`help backout` for a way to reverse the effect of an
6090 See :hg:`help backout` for a way to reverse the effect of an
6083 earlier changeset.
6091 earlier changeset.
6084
6092
6085 Returns 0 on success.
6093 Returns 0 on success.
6086 """
6094 """
6087
6095
6088 if opts.get("date"):
6096 if opts.get("date"):
6089 if opts.get("rev"):
6097 if opts.get("rev"):
6090 raise error.Abort(_("you can't specify a revision and a date"))
6098 raise error.Abort(_("you can't specify a revision and a date"))
6091 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6099 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6092
6100
6093 parent, p2 = repo.dirstate.parents()
6101 parent, p2 = repo.dirstate.parents()
6094 if not opts.get('rev') and p2 != nullid:
6102 if not opts.get('rev') and p2 != nullid:
6095 # revert after merge is a trap for new users (issue2915)
6103 # revert after merge is a trap for new users (issue2915)
6096 raise error.Abort(_('uncommitted merge with no revision specified'),
6104 raise error.Abort(_('uncommitted merge with no revision specified'),
6097 hint=_('use "hg update" or see "hg help revert"'))
6105 hint=_('use "hg update" or see "hg help revert"'))
6098
6106
6099 ctx = scmutil.revsingle(repo, opts.get('rev'))
6107 ctx = scmutil.revsingle(repo, opts.get('rev'))
6100
6108
6101 if (not (pats or opts.get('include') or opts.get('exclude') or
6109 if (not (pats or opts.get('include') or opts.get('exclude') or
6102 opts.get('all') or opts.get('interactive'))):
6110 opts.get('all') or opts.get('interactive'))):
6103 msg = _("no files or directories specified")
6111 msg = _("no files or directories specified")
6104 if p2 != nullid:
6112 if p2 != nullid:
6105 hint = _("uncommitted merge, use --all to discard all changes,"
6113 hint = _("uncommitted merge, use --all to discard all changes,"
6106 " or 'hg update -C .' to abort the merge")
6114 " or 'hg update -C .' to abort the merge")
6107 raise error.Abort(msg, hint=hint)
6115 raise error.Abort(msg, hint=hint)
6108 dirty = any(repo.status())
6116 dirty = any(repo.status())
6109 node = ctx.node()
6117 node = ctx.node()
6110 if node != parent:
6118 if node != parent:
6111 if dirty:
6119 if dirty:
6112 hint = _("uncommitted changes, use --all to discard all"
6120 hint = _("uncommitted changes, use --all to discard all"
6113 " changes, or 'hg update %s' to update") % ctx.rev()
6121 " changes, or 'hg update %s' to update") % ctx.rev()
6114 else:
6122 else:
6115 hint = _("use --all to revert all files,"
6123 hint = _("use --all to revert all files,"
6116 " or 'hg update %s' to update") % ctx.rev()
6124 " or 'hg update %s' to update") % ctx.rev()
6117 elif dirty:
6125 elif dirty:
6118 hint = _("uncommitted changes, use --all to discard all changes")
6126 hint = _("uncommitted changes, use --all to discard all changes")
6119 else:
6127 else:
6120 hint = _("use --all to revert all files")
6128 hint = _("use --all to revert all files")
6121 raise error.Abort(msg, hint=hint)
6129 raise error.Abort(msg, hint=hint)
6122
6130
6123 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6131 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6124
6132
6125 @command('rollback', dryrunopts +
6133 @command('rollback', dryrunopts +
6126 [('f', 'force', False, _('ignore safety measures'))])
6134 [('f', 'force', False, _('ignore safety measures'))])
6127 def rollback(ui, repo, **opts):
6135 def rollback(ui, repo, **opts):
6128 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6136 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6129
6137
6130 Please use :hg:`commit --amend` instead of rollback to correct
6138 Please use :hg:`commit --amend` instead of rollback to correct
6131 mistakes in the last commit.
6139 mistakes in the last commit.
6132
6140
6133 This command should be used with care. There is only one level of
6141 This command should be used with care. There is only one level of
6134 rollback, and there is no way to undo a rollback. It will also
6142 rollback, and there is no way to undo a rollback. It will also
6135 restore the dirstate at the time of the last transaction, losing
6143 restore the dirstate at the time of the last transaction, losing
6136 any dirstate changes since that time. This command does not alter
6144 any dirstate changes since that time. This command does not alter
6137 the working directory.
6145 the working directory.
6138
6146
6139 Transactions are used to encapsulate the effects of all commands
6147 Transactions are used to encapsulate the effects of all commands
6140 that create new changesets or propagate existing changesets into a
6148 that create new changesets or propagate existing changesets into a
6141 repository.
6149 repository.
6142
6150
6143 .. container:: verbose
6151 .. container:: verbose
6144
6152
6145 For example, the following commands are transactional, and their
6153 For example, the following commands are transactional, and their
6146 effects can be rolled back:
6154 effects can be rolled back:
6147
6155
6148 - commit
6156 - commit
6149 - import
6157 - import
6150 - pull
6158 - pull
6151 - push (with this repository as the destination)
6159 - push (with this repository as the destination)
6152 - unbundle
6160 - unbundle
6153
6161
6154 To avoid permanent data loss, rollback will refuse to rollback a
6162 To avoid permanent data loss, rollback will refuse to rollback a
6155 commit transaction if it isn't checked out. Use --force to
6163 commit transaction if it isn't checked out. Use --force to
6156 override this protection.
6164 override this protection.
6157
6165
6158 This command is not intended for use on public repositories. Once
6166 This command is not intended for use on public repositories. Once
6159 changes are visible for pull by other users, rolling a transaction
6167 changes are visible for pull by other users, rolling a transaction
6160 back locally is ineffective (someone else may already have pulled
6168 back locally is ineffective (someone else may already have pulled
6161 the changes). Furthermore, a race is possible with readers of the
6169 the changes). Furthermore, a race is possible with readers of the
6162 repository; for example an in-progress pull from the repository
6170 repository; for example an in-progress pull from the repository
6163 may fail if a rollback is performed.
6171 may fail if a rollback is performed.
6164
6172
6165 Returns 0 on success, 1 if no rollback data is available.
6173 Returns 0 on success, 1 if no rollback data is available.
6166 """
6174 """
6167 return repo.rollback(dryrun=opts.get('dry_run'),
6175 return repo.rollback(dryrun=opts.get('dry_run'),
6168 force=opts.get('force'))
6176 force=opts.get('force'))
6169
6177
6170 @command('root', [])
6178 @command('root', [])
6171 def root(ui, repo):
6179 def root(ui, repo):
6172 """print the root (top) of the current working directory
6180 """print the root (top) of the current working directory
6173
6181
6174 Print the root directory of the current repository.
6182 Print the root directory of the current repository.
6175
6183
6176 Returns 0 on success.
6184 Returns 0 on success.
6177 """
6185 """
6178 ui.write(repo.root + "\n")
6186 ui.write(repo.root + "\n")
6179
6187
6180 @command('^serve',
6188 @command('^serve',
6181 [('A', 'accesslog', '', _('name of access log file to write to'),
6189 [('A', 'accesslog', '', _('name of access log file to write to'),
6182 _('FILE')),
6190 _('FILE')),
6183 ('d', 'daemon', None, _('run server in background')),
6191 ('d', 'daemon', None, _('run server in background')),
6184 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6192 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6185 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6193 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6186 # use string type, then we can check if something was passed
6194 # use string type, then we can check if something was passed
6187 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6195 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6188 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6196 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6189 _('ADDR')),
6197 _('ADDR')),
6190 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6198 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6191 _('PREFIX')),
6199 _('PREFIX')),
6192 ('n', 'name', '',
6200 ('n', 'name', '',
6193 _('name to show in web pages (default: working directory)'), _('NAME')),
6201 _('name to show in web pages (default: working directory)'), _('NAME')),
6194 ('', 'web-conf', '',
6202 ('', 'web-conf', '',
6195 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6203 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6196 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6204 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6197 _('FILE')),
6205 _('FILE')),
6198 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6206 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6199 ('', 'stdio', None, _('for remote clients')),
6207 ('', 'stdio', None, _('for remote clients')),
6200 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6208 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6201 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6209 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6202 ('', 'style', '', _('template style to use'), _('STYLE')),
6210 ('', 'style', '', _('template style to use'), _('STYLE')),
6203 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6211 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6204 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6212 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6205 _('[OPTION]...'),
6213 _('[OPTION]...'),
6206 optionalrepo=True)
6214 optionalrepo=True)
6207 def serve(ui, repo, **opts):
6215 def serve(ui, repo, **opts):
6208 """start stand-alone webserver
6216 """start stand-alone webserver
6209
6217
6210 Start a local HTTP repository browser and pull server. You can use
6218 Start a local HTTP repository browser and pull server. You can use
6211 this for ad-hoc sharing and browsing of repositories. It is
6219 this for ad-hoc sharing and browsing of repositories. It is
6212 recommended to use a real web server to serve a repository for
6220 recommended to use a real web server to serve a repository for
6213 longer periods of time.
6221 longer periods of time.
6214
6222
6215 Please note that the server does not implement access control.
6223 Please note that the server does not implement access control.
6216 This means that, by default, anybody can read from the server and
6224 This means that, by default, anybody can read from the server and
6217 nobody can write to it by default. Set the ``web.allow_push``
6225 nobody can write to it by default. Set the ``web.allow_push``
6218 option to ``*`` to allow everybody to push to the server. You
6226 option to ``*`` to allow everybody to push to the server. You
6219 should use a real web server if you need to authenticate users.
6227 should use a real web server if you need to authenticate users.
6220
6228
6221 By default, the server logs accesses to stdout and errors to
6229 By default, the server logs accesses to stdout and errors to
6222 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6230 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6223 files.
6231 files.
6224
6232
6225 To have the server choose a free port number to listen on, specify
6233 To have the server choose a free port number to listen on, specify
6226 a port number of 0; in this case, the server will print the port
6234 a port number of 0; in this case, the server will print the port
6227 number it uses.
6235 number it uses.
6228
6236
6229 Returns 0 on success.
6237 Returns 0 on success.
6230 """
6238 """
6231
6239
6232 if opts["stdio"] and opts["cmdserver"]:
6240 if opts["stdio"] and opts["cmdserver"]:
6233 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6241 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6234
6242
6235 if opts["stdio"]:
6243 if opts["stdio"]:
6236 if repo is None:
6244 if repo is None:
6237 raise error.RepoError(_("there is no Mercurial repository here"
6245 raise error.RepoError(_("there is no Mercurial repository here"
6238 " (.hg not found)"))
6246 " (.hg not found)"))
6239 s = sshserver.sshserver(ui, repo)
6247 s = sshserver.sshserver(ui, repo)
6240 s.serve_forever()
6248 s.serve_forever()
6241
6249
6242 if opts["cmdserver"]:
6250 if opts["cmdserver"]:
6243 service = commandserver.createservice(ui, repo, opts)
6251 service = commandserver.createservice(ui, repo, opts)
6244 else:
6252 else:
6245 service = hgweb.createservice(ui, repo, opts)
6253 service = hgweb.createservice(ui, repo, opts)
6246 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6254 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6247
6255
6248 @command('^status|st',
6256 @command('^status|st',
6249 [('A', 'all', None, _('show status of all files')),
6257 [('A', 'all', None, _('show status of all files')),
6250 ('m', 'modified', None, _('show only modified files')),
6258 ('m', 'modified', None, _('show only modified files')),
6251 ('a', 'added', None, _('show only added files')),
6259 ('a', 'added', None, _('show only added files')),
6252 ('r', 'removed', None, _('show only removed files')),
6260 ('r', 'removed', None, _('show only removed files')),
6253 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6261 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6254 ('c', 'clean', None, _('show only files without changes')),
6262 ('c', 'clean', None, _('show only files without changes')),
6255 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6263 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6256 ('i', 'ignored', None, _('show only ignored files')),
6264 ('i', 'ignored', None, _('show only ignored files')),
6257 ('n', 'no-status', None, _('hide status prefix')),
6265 ('n', 'no-status', None, _('hide status prefix')),
6258 ('C', 'copies', None, _('show source of copied files')),
6266 ('C', 'copies', None, _('show source of copied files')),
6259 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6267 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6260 ('', 'rev', [], _('show difference from revision'), _('REV')),
6268 ('', 'rev', [], _('show difference from revision'), _('REV')),
6261 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6269 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6262 ] + walkopts + subrepoopts + formatteropts,
6270 ] + walkopts + subrepoopts + formatteropts,
6263 _('[OPTION]... [FILE]...'),
6271 _('[OPTION]... [FILE]...'),
6264 inferrepo=True)
6272 inferrepo=True)
6265 def status(ui, repo, *pats, **opts):
6273 def status(ui, repo, *pats, **opts):
6266 """show changed files in the working directory
6274 """show changed files in the working directory
6267
6275
6268 Show status of files in the repository. If names are given, only
6276 Show status of files in the repository. If names are given, only
6269 files that match are shown. Files that are clean or ignored or
6277 files that match are shown. Files that are clean or ignored or
6270 the source of a copy/move operation, are not listed unless
6278 the source of a copy/move operation, are not listed unless
6271 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6279 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6272 Unless options described with "show only ..." are given, the
6280 Unless options described with "show only ..." are given, the
6273 options -mardu are used.
6281 options -mardu are used.
6274
6282
6275 Option -q/--quiet hides untracked (unknown and ignored) files
6283 Option -q/--quiet hides untracked (unknown and ignored) files
6276 unless explicitly requested with -u/--unknown or -i/--ignored.
6284 unless explicitly requested with -u/--unknown or -i/--ignored.
6277
6285
6278 .. note::
6286 .. note::
6279
6287
6280 :hg:`status` may appear to disagree with diff if permissions have
6288 :hg:`status` may appear to disagree with diff if permissions have
6281 changed or a merge has occurred. The standard diff format does
6289 changed or a merge has occurred. The standard diff format does
6282 not report permission changes and diff only reports changes
6290 not report permission changes and diff only reports changes
6283 relative to one merge parent.
6291 relative to one merge parent.
6284
6292
6285 If one revision is given, it is used as the base revision.
6293 If one revision is given, it is used as the base revision.
6286 If two revisions are given, the differences between them are
6294 If two revisions are given, the differences between them are
6287 shown. The --change option can also be used as a shortcut to list
6295 shown. The --change option can also be used as a shortcut to list
6288 the changed files of a revision from its first parent.
6296 the changed files of a revision from its first parent.
6289
6297
6290 The codes used to show the status of files are::
6298 The codes used to show the status of files are::
6291
6299
6292 M = modified
6300 M = modified
6293 A = added
6301 A = added
6294 R = removed
6302 R = removed
6295 C = clean
6303 C = clean
6296 ! = missing (deleted by non-hg command, but still tracked)
6304 ! = missing (deleted by non-hg command, but still tracked)
6297 ? = not tracked
6305 ? = not tracked
6298 I = ignored
6306 I = ignored
6299 = origin of the previous file (with --copies)
6307 = origin of the previous file (with --copies)
6300
6308
6301 .. container:: verbose
6309 .. container:: verbose
6302
6310
6303 Examples:
6311 Examples:
6304
6312
6305 - show changes in the working directory relative to a
6313 - show changes in the working directory relative to a
6306 changeset::
6314 changeset::
6307
6315
6308 hg status --rev 9353
6316 hg status --rev 9353
6309
6317
6310 - show changes in the working directory relative to the
6318 - show changes in the working directory relative to the
6311 current directory (see :hg:`help patterns` for more information)::
6319 current directory (see :hg:`help patterns` for more information)::
6312
6320
6313 hg status re:
6321 hg status re:
6314
6322
6315 - show all changes including copies in an existing changeset::
6323 - show all changes including copies in an existing changeset::
6316
6324
6317 hg status --copies --change 9353
6325 hg status --copies --change 9353
6318
6326
6319 - get a NUL separated list of added files, suitable for xargs::
6327 - get a NUL separated list of added files, suitable for xargs::
6320
6328
6321 hg status -an0
6329 hg status -an0
6322
6330
6323 Returns 0 on success.
6331 Returns 0 on success.
6324 """
6332 """
6325
6333
6326 revs = opts.get('rev')
6334 revs = opts.get('rev')
6327 change = opts.get('change')
6335 change = opts.get('change')
6328
6336
6329 if revs and change:
6337 if revs and change:
6330 msg = _('cannot specify --rev and --change at the same time')
6338 msg = _('cannot specify --rev and --change at the same time')
6331 raise error.Abort(msg)
6339 raise error.Abort(msg)
6332 elif change:
6340 elif change:
6333 node2 = scmutil.revsingle(repo, change, None).node()
6341 node2 = scmutil.revsingle(repo, change, None).node()
6334 node1 = repo[node2].p1().node()
6342 node1 = repo[node2].p1().node()
6335 else:
6343 else:
6336 node1, node2 = scmutil.revpair(repo, revs)
6344 node1, node2 = scmutil.revpair(repo, revs)
6337
6345
6338 if pats:
6346 if pats:
6339 cwd = repo.getcwd()
6347 cwd = repo.getcwd()
6340 else:
6348 else:
6341 cwd = ''
6349 cwd = ''
6342
6350
6343 if opts.get('print0'):
6351 if opts.get('print0'):
6344 end = '\0'
6352 end = '\0'
6345 else:
6353 else:
6346 end = '\n'
6354 end = '\n'
6347 copy = {}
6355 copy = {}
6348 states = 'modified added removed deleted unknown ignored clean'.split()
6356 states = 'modified added removed deleted unknown ignored clean'.split()
6349 show = [k for k in states if opts.get(k)]
6357 show = [k for k in states if opts.get(k)]
6350 if opts.get('all'):
6358 if opts.get('all'):
6351 show += ui.quiet and (states[:4] + ['clean']) or states
6359 show += ui.quiet and (states[:4] + ['clean']) or states
6352 if not show:
6360 if not show:
6353 if ui.quiet:
6361 if ui.quiet:
6354 show = states[:4]
6362 show = states[:4]
6355 else:
6363 else:
6356 show = states[:5]
6364 show = states[:5]
6357
6365
6358 m = scmutil.match(repo[node2], pats, opts)
6366 m = scmutil.match(repo[node2], pats, opts)
6359 stat = repo.status(node1, node2, m,
6367 stat = repo.status(node1, node2, m,
6360 'ignored' in show, 'clean' in show, 'unknown' in show,
6368 'ignored' in show, 'clean' in show, 'unknown' in show,
6361 opts.get('subrepos'))
6369 opts.get('subrepos'))
6362 changestates = zip(states, 'MAR!?IC', stat)
6370 changestates = zip(states, 'MAR!?IC', stat)
6363
6371
6364 if (opts.get('all') or opts.get('copies')
6372 if (opts.get('all') or opts.get('copies')
6365 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6373 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6366 copy = copies.pathcopies(repo[node1], repo[node2], m)
6374 copy = copies.pathcopies(repo[node1], repo[node2], m)
6367
6375
6368 fm = ui.formatter('status', opts)
6376 fm = ui.formatter('status', opts)
6369 fmt = '%s' + end
6377 fmt = '%s' + end
6370 showchar = not opts.get('no_status')
6378 showchar = not opts.get('no_status')
6371
6379
6372 for state, char, files in changestates:
6380 for state, char, files in changestates:
6373 if state in show:
6381 if state in show:
6374 label = 'status.' + state
6382 label = 'status.' + state
6375 for f in files:
6383 for f in files:
6376 fm.startitem()
6384 fm.startitem()
6377 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6385 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6378 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6386 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6379 if f in copy:
6387 if f in copy:
6380 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6388 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6381 label='status.copied')
6389 label='status.copied')
6382 fm.end()
6390 fm.end()
6383
6391
6384 @command('^summary|sum',
6392 @command('^summary|sum',
6385 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6393 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6386 def summary(ui, repo, **opts):
6394 def summary(ui, repo, **opts):
6387 """summarize working directory state
6395 """summarize working directory state
6388
6396
6389 This generates a brief summary of the working directory state,
6397 This generates a brief summary of the working directory state,
6390 including parents, branch, commit status, phase and available updates.
6398 including parents, branch, commit status, phase and available updates.
6391
6399
6392 With the --remote option, this will check the default paths for
6400 With the --remote option, this will check the default paths for
6393 incoming and outgoing changes. This can be time-consuming.
6401 incoming and outgoing changes. This can be time-consuming.
6394
6402
6395 Returns 0 on success.
6403 Returns 0 on success.
6396 """
6404 """
6397
6405
6398 ctx = repo[None]
6406 ctx = repo[None]
6399 parents = ctx.parents()
6407 parents = ctx.parents()
6400 pnode = parents[0].node()
6408 pnode = parents[0].node()
6401 marks = []
6409 marks = []
6402
6410
6403 for p in parents:
6411 for p in parents:
6404 # label with log.changeset (instead of log.parent) since this
6412 # label with log.changeset (instead of log.parent) since this
6405 # shows a working directory parent *changeset*:
6413 # shows a working directory parent *changeset*:
6406 # i18n: column positioning for "hg summary"
6414 # i18n: column positioning for "hg summary"
6407 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6415 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6408 label='log.changeset changeset.%s' % p.phasestr())
6416 label='log.changeset changeset.%s' % p.phasestr())
6409 ui.write(' '.join(p.tags()), label='log.tag')
6417 ui.write(' '.join(p.tags()), label='log.tag')
6410 if p.bookmarks():
6418 if p.bookmarks():
6411 marks.extend(p.bookmarks())
6419 marks.extend(p.bookmarks())
6412 if p.rev() == -1:
6420 if p.rev() == -1:
6413 if not len(repo):
6421 if not len(repo):
6414 ui.write(_(' (empty repository)'))
6422 ui.write(_(' (empty repository)'))
6415 else:
6423 else:
6416 ui.write(_(' (no revision checked out)'))
6424 ui.write(_(' (no revision checked out)'))
6417 ui.write('\n')
6425 ui.write('\n')
6418 if p.description():
6426 if p.description():
6419 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6427 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6420 label='log.summary')
6428 label='log.summary')
6421
6429
6422 branch = ctx.branch()
6430 branch = ctx.branch()
6423 bheads = repo.branchheads(branch)
6431 bheads = repo.branchheads(branch)
6424 # i18n: column positioning for "hg summary"
6432 # i18n: column positioning for "hg summary"
6425 m = _('branch: %s\n') % branch
6433 m = _('branch: %s\n') % branch
6426 if branch != 'default':
6434 if branch != 'default':
6427 ui.write(m, label='log.branch')
6435 ui.write(m, label='log.branch')
6428 else:
6436 else:
6429 ui.status(m, label='log.branch')
6437 ui.status(m, label='log.branch')
6430
6438
6431 if marks:
6439 if marks:
6432 active = repo._activebookmark
6440 active = repo._activebookmark
6433 # i18n: column positioning for "hg summary"
6441 # i18n: column positioning for "hg summary"
6434 ui.write(_('bookmarks:'), label='log.bookmark')
6442 ui.write(_('bookmarks:'), label='log.bookmark')
6435 if active is not None:
6443 if active is not None:
6436 if active in marks:
6444 if active in marks:
6437 ui.write(' *' + active, label=activebookmarklabel)
6445 ui.write(' *' + active, label=activebookmarklabel)
6438 marks.remove(active)
6446 marks.remove(active)
6439 else:
6447 else:
6440 ui.write(' [%s]' % active, label=activebookmarklabel)
6448 ui.write(' [%s]' % active, label=activebookmarklabel)
6441 for m in marks:
6449 for m in marks:
6442 ui.write(' ' + m, label='log.bookmark')
6450 ui.write(' ' + m, label='log.bookmark')
6443 ui.write('\n', label='log.bookmark')
6451 ui.write('\n', label='log.bookmark')
6444
6452
6445 status = repo.status(unknown=True)
6453 status = repo.status(unknown=True)
6446
6454
6447 c = repo.dirstate.copies()
6455 c = repo.dirstate.copies()
6448 copied, renamed = [], []
6456 copied, renamed = [], []
6449 for d, s in c.iteritems():
6457 for d, s in c.iteritems():
6450 if s in status.removed:
6458 if s in status.removed:
6451 status.removed.remove(s)
6459 status.removed.remove(s)
6452 renamed.append(d)
6460 renamed.append(d)
6453 else:
6461 else:
6454 copied.append(d)
6462 copied.append(d)
6455 if d in status.added:
6463 if d in status.added:
6456 status.added.remove(d)
6464 status.added.remove(d)
6457
6465
6458 try:
6466 try:
6459 ms = mergemod.mergestate.read(repo)
6467 ms = mergemod.mergestate.read(repo)
6460 except error.UnsupportedMergeRecords as e:
6468 except error.UnsupportedMergeRecords as e:
6461 s = ' '.join(e.recordtypes)
6469 s = ' '.join(e.recordtypes)
6462 ui.warn(
6470 ui.warn(
6463 _('warning: merge state has unsupported record types: %s\n') % s)
6471 _('warning: merge state has unsupported record types: %s\n') % s)
6464 unresolved = 0
6472 unresolved = 0
6465 else:
6473 else:
6466 unresolved = [f for f in ms if ms[f] == 'u']
6474 unresolved = [f for f in ms if ms[f] == 'u']
6467
6475
6468 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6476 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6469
6477
6470 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6478 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6471 (ui.label(_('%d added'), 'status.added'), status.added),
6479 (ui.label(_('%d added'), 'status.added'), status.added),
6472 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6480 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6473 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6481 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6474 (ui.label(_('%d copied'), 'status.copied'), copied),
6482 (ui.label(_('%d copied'), 'status.copied'), copied),
6475 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6483 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6476 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6484 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6477 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6485 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6478 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6486 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6479 t = []
6487 t = []
6480 for l, s in labels:
6488 for l, s in labels:
6481 if s:
6489 if s:
6482 t.append(l % len(s))
6490 t.append(l % len(s))
6483
6491
6484 t = ', '.join(t)
6492 t = ', '.join(t)
6485 cleanworkdir = False
6493 cleanworkdir = False
6486
6494
6487 if repo.vfs.exists('graftstate'):
6495 if repo.vfs.exists('graftstate'):
6488 t += _(' (graft in progress)')
6496 t += _(' (graft in progress)')
6489 if repo.vfs.exists('updatestate'):
6497 if repo.vfs.exists('updatestate'):
6490 t += _(' (interrupted update)')
6498 t += _(' (interrupted update)')
6491 elif len(parents) > 1:
6499 elif len(parents) > 1:
6492 t += _(' (merge)')
6500 t += _(' (merge)')
6493 elif branch != parents[0].branch():
6501 elif branch != parents[0].branch():
6494 t += _(' (new branch)')
6502 t += _(' (new branch)')
6495 elif (parents[0].closesbranch() and
6503 elif (parents[0].closesbranch() and
6496 pnode in repo.branchheads(branch, closed=True)):
6504 pnode in repo.branchheads(branch, closed=True)):
6497 t += _(' (head closed)')
6505 t += _(' (head closed)')
6498 elif not (status.modified or status.added or status.removed or renamed or
6506 elif not (status.modified or status.added or status.removed or renamed or
6499 copied or subs):
6507 copied or subs):
6500 t += _(' (clean)')
6508 t += _(' (clean)')
6501 cleanworkdir = True
6509 cleanworkdir = True
6502 elif pnode not in bheads:
6510 elif pnode not in bheads:
6503 t += _(' (new branch head)')
6511 t += _(' (new branch head)')
6504
6512
6505 if parents:
6513 if parents:
6506 pendingphase = max(p.phase() for p in parents)
6514 pendingphase = max(p.phase() for p in parents)
6507 else:
6515 else:
6508 pendingphase = phases.public
6516 pendingphase = phases.public
6509
6517
6510 if pendingphase > phases.newcommitphase(ui):
6518 if pendingphase > phases.newcommitphase(ui):
6511 t += ' (%s)' % phases.phasenames[pendingphase]
6519 t += ' (%s)' % phases.phasenames[pendingphase]
6512
6520
6513 if cleanworkdir:
6521 if cleanworkdir:
6514 # i18n: column positioning for "hg summary"
6522 # i18n: column positioning for "hg summary"
6515 ui.status(_('commit: %s\n') % t.strip())
6523 ui.status(_('commit: %s\n') % t.strip())
6516 else:
6524 else:
6517 # i18n: column positioning for "hg summary"
6525 # i18n: column positioning for "hg summary"
6518 ui.write(_('commit: %s\n') % t.strip())
6526 ui.write(_('commit: %s\n') % t.strip())
6519
6527
6520 # all ancestors of branch heads - all ancestors of parent = new csets
6528 # all ancestors of branch heads - all ancestors of parent = new csets
6521 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6529 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6522 bheads))
6530 bheads))
6523
6531
6524 if new == 0:
6532 if new == 0:
6525 # i18n: column positioning for "hg summary"
6533 # i18n: column positioning for "hg summary"
6526 ui.status(_('update: (current)\n'))
6534 ui.status(_('update: (current)\n'))
6527 elif pnode not in bheads:
6535 elif pnode not in bheads:
6528 # i18n: column positioning for "hg summary"
6536 # i18n: column positioning for "hg summary"
6529 ui.write(_('update: %d new changesets (update)\n') % new)
6537 ui.write(_('update: %d new changesets (update)\n') % new)
6530 else:
6538 else:
6531 # i18n: column positioning for "hg summary"
6539 # i18n: column positioning for "hg summary"
6532 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6540 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6533 (new, len(bheads)))
6541 (new, len(bheads)))
6534
6542
6535 t = []
6543 t = []
6536 draft = len(repo.revs('draft()'))
6544 draft = len(repo.revs('draft()'))
6537 if draft:
6545 if draft:
6538 t.append(_('%d draft') % draft)
6546 t.append(_('%d draft') % draft)
6539 secret = len(repo.revs('secret()'))
6547 secret = len(repo.revs('secret()'))
6540 if secret:
6548 if secret:
6541 t.append(_('%d secret') % secret)
6549 t.append(_('%d secret') % secret)
6542
6550
6543 if draft or secret:
6551 if draft or secret:
6544 ui.status(_('phases: %s\n') % ', '.join(t))
6552 ui.status(_('phases: %s\n') % ', '.join(t))
6545
6553
6546 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6554 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6547 for trouble in ("unstable", "divergent", "bumped"):
6555 for trouble in ("unstable", "divergent", "bumped"):
6548 numtrouble = len(repo.revs(trouble + "()"))
6556 numtrouble = len(repo.revs(trouble + "()"))
6549 # We write all the possibilities to ease translation
6557 # We write all the possibilities to ease translation
6550 troublemsg = {
6558 troublemsg = {
6551 "unstable": _("unstable: %d changesets"),
6559 "unstable": _("unstable: %d changesets"),
6552 "divergent": _("divergent: %d changesets"),
6560 "divergent": _("divergent: %d changesets"),
6553 "bumped": _("bumped: %d changesets"),
6561 "bumped": _("bumped: %d changesets"),
6554 }
6562 }
6555 if numtrouble > 0:
6563 if numtrouble > 0:
6556 ui.status(troublemsg[trouble] % numtrouble + "\n")
6564 ui.status(troublemsg[trouble] % numtrouble + "\n")
6557
6565
6558 cmdutil.summaryhooks(ui, repo)
6566 cmdutil.summaryhooks(ui, repo)
6559
6567
6560 if opts.get('remote'):
6568 if opts.get('remote'):
6561 needsincoming, needsoutgoing = True, True
6569 needsincoming, needsoutgoing = True, True
6562 else:
6570 else:
6563 needsincoming, needsoutgoing = False, False
6571 needsincoming, needsoutgoing = False, False
6564 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6572 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6565 if i:
6573 if i:
6566 needsincoming = True
6574 needsincoming = True
6567 if o:
6575 if o:
6568 needsoutgoing = True
6576 needsoutgoing = True
6569 if not needsincoming and not needsoutgoing:
6577 if not needsincoming and not needsoutgoing:
6570 return
6578 return
6571
6579
6572 def getincoming():
6580 def getincoming():
6573 source, branches = hg.parseurl(ui.expandpath('default'))
6581 source, branches = hg.parseurl(ui.expandpath('default'))
6574 sbranch = branches[0]
6582 sbranch = branches[0]
6575 try:
6583 try:
6576 other = hg.peer(repo, {}, source)
6584 other = hg.peer(repo, {}, source)
6577 except error.RepoError:
6585 except error.RepoError:
6578 if opts.get('remote'):
6586 if opts.get('remote'):
6579 raise
6587 raise
6580 return source, sbranch, None, None, None
6588 return source, sbranch, None, None, None
6581 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6589 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6582 if revs:
6590 if revs:
6583 revs = [other.lookup(rev) for rev in revs]
6591 revs = [other.lookup(rev) for rev in revs]
6584 ui.debug('comparing with %s\n' % util.hidepassword(source))
6592 ui.debug('comparing with %s\n' % util.hidepassword(source))
6585 repo.ui.pushbuffer()
6593 repo.ui.pushbuffer()
6586 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6594 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6587 repo.ui.popbuffer()
6595 repo.ui.popbuffer()
6588 return source, sbranch, other, commoninc, commoninc[1]
6596 return source, sbranch, other, commoninc, commoninc[1]
6589
6597
6590 if needsincoming:
6598 if needsincoming:
6591 source, sbranch, sother, commoninc, incoming = getincoming()
6599 source, sbranch, sother, commoninc, incoming = getincoming()
6592 else:
6600 else:
6593 source = sbranch = sother = commoninc = incoming = None
6601 source = sbranch = sother = commoninc = incoming = None
6594
6602
6595 def getoutgoing():
6603 def getoutgoing():
6596 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6604 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6597 dbranch = branches[0]
6605 dbranch = branches[0]
6598 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6606 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6599 if source != dest:
6607 if source != dest:
6600 try:
6608 try:
6601 dother = hg.peer(repo, {}, dest)
6609 dother = hg.peer(repo, {}, dest)
6602 except error.RepoError:
6610 except error.RepoError:
6603 if opts.get('remote'):
6611 if opts.get('remote'):
6604 raise
6612 raise
6605 return dest, dbranch, None, None
6613 return dest, dbranch, None, None
6606 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6614 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6607 elif sother is None:
6615 elif sother is None:
6608 # there is no explicit destination peer, but source one is invalid
6616 # there is no explicit destination peer, but source one is invalid
6609 return dest, dbranch, None, None
6617 return dest, dbranch, None, None
6610 else:
6618 else:
6611 dother = sother
6619 dother = sother
6612 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6620 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6613 common = None
6621 common = None
6614 else:
6622 else:
6615 common = commoninc
6623 common = commoninc
6616 if revs:
6624 if revs:
6617 revs = [repo.lookup(rev) for rev in revs]
6625 revs = [repo.lookup(rev) for rev in revs]
6618 repo.ui.pushbuffer()
6626 repo.ui.pushbuffer()
6619 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6627 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6620 commoninc=common)
6628 commoninc=common)
6621 repo.ui.popbuffer()
6629 repo.ui.popbuffer()
6622 return dest, dbranch, dother, outgoing
6630 return dest, dbranch, dother, outgoing
6623
6631
6624 if needsoutgoing:
6632 if needsoutgoing:
6625 dest, dbranch, dother, outgoing = getoutgoing()
6633 dest, dbranch, dother, outgoing = getoutgoing()
6626 else:
6634 else:
6627 dest = dbranch = dother = outgoing = None
6635 dest = dbranch = dother = outgoing = None
6628
6636
6629 if opts.get('remote'):
6637 if opts.get('remote'):
6630 t = []
6638 t = []
6631 if incoming:
6639 if incoming:
6632 t.append(_('1 or more incoming'))
6640 t.append(_('1 or more incoming'))
6633 o = outgoing.missing
6641 o = outgoing.missing
6634 if o:
6642 if o:
6635 t.append(_('%d outgoing') % len(o))
6643 t.append(_('%d outgoing') % len(o))
6636 other = dother or sother
6644 other = dother or sother
6637 if 'bookmarks' in other.listkeys('namespaces'):
6645 if 'bookmarks' in other.listkeys('namespaces'):
6638 counts = bookmarks.summary(repo, other)
6646 counts = bookmarks.summary(repo, other)
6639 if counts[0] > 0:
6647 if counts[0] > 0:
6640 t.append(_('%d incoming bookmarks') % counts[0])
6648 t.append(_('%d incoming bookmarks') % counts[0])
6641 if counts[1] > 0:
6649 if counts[1] > 0:
6642 t.append(_('%d outgoing bookmarks') % counts[1])
6650 t.append(_('%d outgoing bookmarks') % counts[1])
6643
6651
6644 if t:
6652 if t:
6645 # i18n: column positioning for "hg summary"
6653 # i18n: column positioning for "hg summary"
6646 ui.write(_('remote: %s\n') % (', '.join(t)))
6654 ui.write(_('remote: %s\n') % (', '.join(t)))
6647 else:
6655 else:
6648 # i18n: column positioning for "hg summary"
6656 # i18n: column positioning for "hg summary"
6649 ui.status(_('remote: (synced)\n'))
6657 ui.status(_('remote: (synced)\n'))
6650
6658
6651 cmdutil.summaryremotehooks(ui, repo, opts,
6659 cmdutil.summaryremotehooks(ui, repo, opts,
6652 ((source, sbranch, sother, commoninc),
6660 ((source, sbranch, sother, commoninc),
6653 (dest, dbranch, dother, outgoing)))
6661 (dest, dbranch, dother, outgoing)))
6654
6662
6655 @command('tag',
6663 @command('tag',
6656 [('f', 'force', None, _('force tag')),
6664 [('f', 'force', None, _('force tag')),
6657 ('l', 'local', None, _('make the tag local')),
6665 ('l', 'local', None, _('make the tag local')),
6658 ('r', 'rev', '', _('revision to tag'), _('REV')),
6666 ('r', 'rev', '', _('revision to tag'), _('REV')),
6659 ('', 'remove', None, _('remove a tag')),
6667 ('', 'remove', None, _('remove a tag')),
6660 # -l/--local is already there, commitopts cannot be used
6668 # -l/--local is already there, commitopts cannot be used
6661 ('e', 'edit', None, _('invoke editor on commit messages')),
6669 ('e', 'edit', None, _('invoke editor on commit messages')),
6662 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6670 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6663 ] + commitopts2,
6671 ] + commitopts2,
6664 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6672 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6665 def tag(ui, repo, name1, *names, **opts):
6673 def tag(ui, repo, name1, *names, **opts):
6666 """add one or more tags for the current or given revision
6674 """add one or more tags for the current or given revision
6667
6675
6668 Name a particular revision using <name>.
6676 Name a particular revision using <name>.
6669
6677
6670 Tags are used to name particular revisions of the repository and are
6678 Tags are used to name particular revisions of the repository and are
6671 very useful to compare different revisions, to go back to significant
6679 very useful to compare different revisions, to go back to significant
6672 earlier versions or to mark branch points as releases, etc. Changing
6680 earlier versions or to mark branch points as releases, etc. Changing
6673 an existing tag is normally disallowed; use -f/--force to override.
6681 an existing tag is normally disallowed; use -f/--force to override.
6674
6682
6675 If no revision is given, the parent of the working directory is
6683 If no revision is given, the parent of the working directory is
6676 used.
6684 used.
6677
6685
6678 To facilitate version control, distribution, and merging of tags,
6686 To facilitate version control, distribution, and merging of tags,
6679 they are stored as a file named ".hgtags" which is managed similarly
6687 they are stored as a file named ".hgtags" which is managed similarly
6680 to other project files and can be hand-edited if necessary. This
6688 to other project files and can be hand-edited if necessary. This
6681 also means that tagging creates a new commit. The file
6689 also means that tagging creates a new commit. The file
6682 ".hg/localtags" is used for local tags (not shared among
6690 ".hg/localtags" is used for local tags (not shared among
6683 repositories).
6691 repositories).
6684
6692
6685 Tag commits are usually made at the head of a branch. If the parent
6693 Tag commits are usually made at the head of a branch. If the parent
6686 of the working directory is not a branch head, :hg:`tag` aborts; use
6694 of the working directory is not a branch head, :hg:`tag` aborts; use
6687 -f/--force to force the tag commit to be based on a non-head
6695 -f/--force to force the tag commit to be based on a non-head
6688 changeset.
6696 changeset.
6689
6697
6690 See :hg:`help dates` for a list of formats valid for -d/--date.
6698 See :hg:`help dates` for a list of formats valid for -d/--date.
6691
6699
6692 Since tag names have priority over branch names during revision
6700 Since tag names have priority over branch names during revision
6693 lookup, using an existing branch name as a tag name is discouraged.
6701 lookup, using an existing branch name as a tag name is discouraged.
6694
6702
6695 Returns 0 on success.
6703 Returns 0 on success.
6696 """
6704 """
6697 wlock = lock = None
6705 wlock = lock = None
6698 try:
6706 try:
6699 wlock = repo.wlock()
6707 wlock = repo.wlock()
6700 lock = repo.lock()
6708 lock = repo.lock()
6701 rev_ = "."
6709 rev_ = "."
6702 names = [t.strip() for t in (name1,) + names]
6710 names = [t.strip() for t in (name1,) + names]
6703 if len(names) != len(set(names)):
6711 if len(names) != len(set(names)):
6704 raise error.Abort(_('tag names must be unique'))
6712 raise error.Abort(_('tag names must be unique'))
6705 for n in names:
6713 for n in names:
6706 scmutil.checknewlabel(repo, n, 'tag')
6714 scmutil.checknewlabel(repo, n, 'tag')
6707 if not n:
6715 if not n:
6708 raise error.Abort(_('tag names cannot consist entirely of '
6716 raise error.Abort(_('tag names cannot consist entirely of '
6709 'whitespace'))
6717 'whitespace'))
6710 if opts.get('rev') and opts.get('remove'):
6718 if opts.get('rev') and opts.get('remove'):
6711 raise error.Abort(_("--rev and --remove are incompatible"))
6719 raise error.Abort(_("--rev and --remove are incompatible"))
6712 if opts.get('rev'):
6720 if opts.get('rev'):
6713 rev_ = opts['rev']
6721 rev_ = opts['rev']
6714 message = opts.get('message')
6722 message = opts.get('message')
6715 if opts.get('remove'):
6723 if opts.get('remove'):
6716 if opts.get('local'):
6724 if opts.get('local'):
6717 expectedtype = 'local'
6725 expectedtype = 'local'
6718 else:
6726 else:
6719 expectedtype = 'global'
6727 expectedtype = 'global'
6720
6728
6721 for n in names:
6729 for n in names:
6722 if not repo.tagtype(n):
6730 if not repo.tagtype(n):
6723 raise error.Abort(_("tag '%s' does not exist") % n)
6731 raise error.Abort(_("tag '%s' does not exist") % n)
6724 if repo.tagtype(n) != expectedtype:
6732 if repo.tagtype(n) != expectedtype:
6725 if expectedtype == 'global':
6733 if expectedtype == 'global':
6726 raise error.Abort(_("tag '%s' is not a global tag") % n)
6734 raise error.Abort(_("tag '%s' is not a global tag") % n)
6727 else:
6735 else:
6728 raise error.Abort(_("tag '%s' is not a local tag") % n)
6736 raise error.Abort(_("tag '%s' is not a local tag") % n)
6729 rev_ = 'null'
6737 rev_ = 'null'
6730 if not message:
6738 if not message:
6731 # we don't translate commit messages
6739 # we don't translate commit messages
6732 message = 'Removed tag %s' % ', '.join(names)
6740 message = 'Removed tag %s' % ', '.join(names)
6733 elif not opts.get('force'):
6741 elif not opts.get('force'):
6734 for n in names:
6742 for n in names:
6735 if n in repo.tags():
6743 if n in repo.tags():
6736 raise error.Abort(_("tag '%s' already exists "
6744 raise error.Abort(_("tag '%s' already exists "
6737 "(use -f to force)") % n)
6745 "(use -f to force)") % n)
6738 if not opts.get('local'):
6746 if not opts.get('local'):
6739 p1, p2 = repo.dirstate.parents()
6747 p1, p2 = repo.dirstate.parents()
6740 if p2 != nullid:
6748 if p2 != nullid:
6741 raise error.Abort(_('uncommitted merge'))
6749 raise error.Abort(_('uncommitted merge'))
6742 bheads = repo.branchheads()
6750 bheads = repo.branchheads()
6743 if not opts.get('force') and bheads and p1 not in bheads:
6751 if not opts.get('force') and bheads and p1 not in bheads:
6744 raise error.Abort(_('not at a branch head (use -f to force)'))
6752 raise error.Abort(_('not at a branch head (use -f to force)'))
6745 r = scmutil.revsingle(repo, rev_).node()
6753 r = scmutil.revsingle(repo, rev_).node()
6746
6754
6747 if not message:
6755 if not message:
6748 # we don't translate commit messages
6756 # we don't translate commit messages
6749 message = ('Added tag %s for changeset %s' %
6757 message = ('Added tag %s for changeset %s' %
6750 (', '.join(names), short(r)))
6758 (', '.join(names), short(r)))
6751
6759
6752 date = opts.get('date')
6760 date = opts.get('date')
6753 if date:
6761 if date:
6754 date = util.parsedate(date)
6762 date = util.parsedate(date)
6755
6763
6756 if opts.get('remove'):
6764 if opts.get('remove'):
6757 editform = 'tag.remove'
6765 editform = 'tag.remove'
6758 else:
6766 else:
6759 editform = 'tag.add'
6767 editform = 'tag.add'
6760 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6768 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6761
6769
6762 # don't allow tagging the null rev
6770 # don't allow tagging the null rev
6763 if (not opts.get('remove') and
6771 if (not opts.get('remove') and
6764 scmutil.revsingle(repo, rev_).rev() == nullrev):
6772 scmutil.revsingle(repo, rev_).rev() == nullrev):
6765 raise error.Abort(_("cannot tag null revision"))
6773 raise error.Abort(_("cannot tag null revision"))
6766
6774
6767 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6775 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6768 editor=editor)
6776 editor=editor)
6769 finally:
6777 finally:
6770 release(lock, wlock)
6778 release(lock, wlock)
6771
6779
6772 @command('tags', formatteropts, '')
6780 @command('tags', formatteropts, '')
6773 def tags(ui, repo, **opts):
6781 def tags(ui, repo, **opts):
6774 """list repository tags
6782 """list repository tags
6775
6783
6776 This lists both regular and local tags. When the -v/--verbose
6784 This lists both regular and local tags. When the -v/--verbose
6777 switch is used, a third column "local" is printed for local tags.
6785 switch is used, a third column "local" is printed for local tags.
6778 When the -q/--quiet switch is used, only the tag name is printed.
6786 When the -q/--quiet switch is used, only the tag name is printed.
6779
6787
6780 Returns 0 on success.
6788 Returns 0 on success.
6781 """
6789 """
6782
6790
6783 fm = ui.formatter('tags', opts)
6791 fm = ui.formatter('tags', opts)
6784 hexfunc = fm.hexfunc
6792 hexfunc = fm.hexfunc
6785 tagtype = ""
6793 tagtype = ""
6786
6794
6787 for t, n in reversed(repo.tagslist()):
6795 for t, n in reversed(repo.tagslist()):
6788 hn = hexfunc(n)
6796 hn = hexfunc(n)
6789 label = 'tags.normal'
6797 label = 'tags.normal'
6790 tagtype = ''
6798 tagtype = ''
6791 if repo.tagtype(t) == 'local':
6799 if repo.tagtype(t) == 'local':
6792 label = 'tags.local'
6800 label = 'tags.local'
6793 tagtype = 'local'
6801 tagtype = 'local'
6794
6802
6795 fm.startitem()
6803 fm.startitem()
6796 fm.write('tag', '%s', t, label=label)
6804 fm.write('tag', '%s', t, label=label)
6797 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6805 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6798 fm.condwrite(not ui.quiet, 'rev node', fmt,
6806 fm.condwrite(not ui.quiet, 'rev node', fmt,
6799 repo.changelog.rev(n), hn, label=label)
6807 repo.changelog.rev(n), hn, label=label)
6800 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6808 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6801 tagtype, label=label)
6809 tagtype, label=label)
6802 fm.plain('\n')
6810 fm.plain('\n')
6803 fm.end()
6811 fm.end()
6804
6812
6805 @command('tip',
6813 @command('tip',
6806 [('p', 'patch', None, _('show patch')),
6814 [('p', 'patch', None, _('show patch')),
6807 ('g', 'git', None, _('use git extended diff format')),
6815 ('g', 'git', None, _('use git extended diff format')),
6808 ] + templateopts,
6816 ] + templateopts,
6809 _('[-p] [-g]'))
6817 _('[-p] [-g]'))
6810 def tip(ui, repo, **opts):
6818 def tip(ui, repo, **opts):
6811 """show the tip revision (DEPRECATED)
6819 """show the tip revision (DEPRECATED)
6812
6820
6813 The tip revision (usually just called the tip) is the changeset
6821 The tip revision (usually just called the tip) is the changeset
6814 most recently added to the repository (and therefore the most
6822 most recently added to the repository (and therefore the most
6815 recently changed head).
6823 recently changed head).
6816
6824
6817 If you have just made a commit, that commit will be the tip. If
6825 If you have just made a commit, that commit will be the tip. If
6818 you have just pulled changes from another repository, the tip of
6826 you have just pulled changes from another repository, the tip of
6819 that repository becomes the current tip. The "tip" tag is special
6827 that repository becomes the current tip. The "tip" tag is special
6820 and cannot be renamed or assigned to a different changeset.
6828 and cannot be renamed or assigned to a different changeset.
6821
6829
6822 This command is deprecated, please use :hg:`heads` instead.
6830 This command is deprecated, please use :hg:`heads` instead.
6823
6831
6824 Returns 0 on success.
6832 Returns 0 on success.
6825 """
6833 """
6826 displayer = cmdutil.show_changeset(ui, repo, opts)
6834 displayer = cmdutil.show_changeset(ui, repo, opts)
6827 displayer.show(repo['tip'])
6835 displayer.show(repo['tip'])
6828 displayer.close()
6836 displayer.close()
6829
6837
6830 @command('unbundle',
6838 @command('unbundle',
6831 [('u', 'update', None,
6839 [('u', 'update', None,
6832 _('update to new branch head if changesets were unbundled'))],
6840 _('update to new branch head if changesets were unbundled'))],
6833 _('[-u] FILE...'))
6841 _('[-u] FILE...'))
6834 def unbundle(ui, repo, fname1, *fnames, **opts):
6842 def unbundle(ui, repo, fname1, *fnames, **opts):
6835 """apply one or more changegroup files
6843 """apply one or more changegroup files
6836
6844
6837 Apply one or more compressed changegroup files generated by the
6845 Apply one or more compressed changegroup files generated by the
6838 bundle command.
6846 bundle command.
6839
6847
6840 Returns 0 on success, 1 if an update has unresolved files.
6848 Returns 0 on success, 1 if an update has unresolved files.
6841 """
6849 """
6842 fnames = (fname1,) + fnames
6850 fnames = (fname1,) + fnames
6843
6851
6844 lock = repo.lock()
6852 lock = repo.lock()
6845 try:
6853 try:
6846 for fname in fnames:
6854 for fname in fnames:
6847 f = hg.openpath(ui, fname)
6855 f = hg.openpath(ui, fname)
6848 gen = exchange.readbundle(ui, f, fname)
6856 gen = exchange.readbundle(ui, f, fname)
6849 if isinstance(gen, bundle2.unbundle20):
6857 if isinstance(gen, bundle2.unbundle20):
6850 tr = repo.transaction('unbundle')
6858 tr = repo.transaction('unbundle')
6851 try:
6859 try:
6852 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6860 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6853 url='bundle:' + fname)
6861 url='bundle:' + fname)
6854 tr.close()
6862 tr.close()
6855 except error.BundleUnknownFeatureError as exc:
6863 except error.BundleUnknownFeatureError as exc:
6856 raise error.Abort(_('%s: unknown bundle feature, %s')
6864 raise error.Abort(_('%s: unknown bundle feature, %s')
6857 % (fname, exc),
6865 % (fname, exc),
6858 hint=_("see https://mercurial-scm.org/"
6866 hint=_("see https://mercurial-scm.org/"
6859 "wiki/BundleFeature for more "
6867 "wiki/BundleFeature for more "
6860 "information"))
6868 "information"))
6861 finally:
6869 finally:
6862 if tr:
6870 if tr:
6863 tr.release()
6871 tr.release()
6864 changes = [r.get('return', 0)
6872 changes = [r.get('return', 0)
6865 for r in op.records['changegroup']]
6873 for r in op.records['changegroup']]
6866 modheads = changegroup.combineresults(changes)
6874 modheads = changegroup.combineresults(changes)
6867 elif isinstance(gen, streamclone.streamcloneapplier):
6875 elif isinstance(gen, streamclone.streamcloneapplier):
6868 raise error.Abort(
6876 raise error.Abort(
6869 _('packed bundles cannot be applied with '
6877 _('packed bundles cannot be applied with '
6870 '"hg unbundle"'),
6878 '"hg unbundle"'),
6871 hint=_('use "hg debugapplystreamclonebundle"'))
6879 hint=_('use "hg debugapplystreamclonebundle"'))
6872 else:
6880 else:
6873 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6881 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6874 finally:
6882 finally:
6875 lock.release()
6883 lock.release()
6876
6884
6877 return postincoming(ui, repo, modheads, opts.get('update'), None)
6885 return postincoming(ui, repo, modheads, opts.get('update'), None)
6878
6886
6879 @command('^update|up|checkout|co',
6887 @command('^update|up|checkout|co',
6880 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6888 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6881 ('c', 'check', None,
6889 ('c', 'check', None,
6882 _('update across branches if no uncommitted changes')),
6890 _('update across branches if no uncommitted changes')),
6883 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6891 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6884 ('r', 'rev', '', _('revision'), _('REV'))
6892 ('r', 'rev', '', _('revision'), _('REV'))
6885 ] + mergetoolopts,
6893 ] + mergetoolopts,
6886 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6894 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6887 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6895 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6888 tool=None):
6896 tool=None):
6889 """update working directory (or switch revisions)
6897 """update working directory (or switch revisions)
6890
6898
6891 Update the repository's working directory to the specified
6899 Update the repository's working directory to the specified
6892 changeset. If no changeset is specified, update to the tip of the
6900 changeset. If no changeset is specified, update to the tip of the
6893 current named branch and move the active bookmark (see :hg:`help
6901 current named branch and move the active bookmark (see :hg:`help
6894 bookmarks`).
6902 bookmarks`).
6895
6903
6896 Update sets the working directory's parent revision to the specified
6904 Update sets the working directory's parent revision to the specified
6897 changeset (see :hg:`help parents`).
6905 changeset (see :hg:`help parents`).
6898
6906
6899 If the changeset is not a descendant or ancestor of the working
6907 If the changeset is not a descendant or ancestor of the working
6900 directory's parent, the update is aborted. With the -c/--check
6908 directory's parent, the update is aborted. With the -c/--check
6901 option, the working directory is checked for uncommitted changes; if
6909 option, the working directory is checked for uncommitted changes; if
6902 none are found, the working directory is updated to the specified
6910 none are found, the working directory is updated to the specified
6903 changeset.
6911 changeset.
6904
6912
6905 .. container:: verbose
6913 .. container:: verbose
6906
6914
6907 The following rules apply when the working directory contains
6915 The following rules apply when the working directory contains
6908 uncommitted changes:
6916 uncommitted changes:
6909
6917
6910 1. If neither -c/--check nor -C/--clean is specified, and if
6918 1. If neither -c/--check nor -C/--clean is specified, and if
6911 the requested changeset is an ancestor or descendant of
6919 the requested changeset is an ancestor or descendant of
6912 the working directory's parent, the uncommitted changes
6920 the working directory's parent, the uncommitted changes
6913 are merged into the requested changeset and the merged
6921 are merged into the requested changeset and the merged
6914 result is left uncommitted. If the requested changeset is
6922 result is left uncommitted. If the requested changeset is
6915 not an ancestor or descendant (that is, it is on another
6923 not an ancestor or descendant (that is, it is on another
6916 branch), the update is aborted and the uncommitted changes
6924 branch), the update is aborted and the uncommitted changes
6917 are preserved.
6925 are preserved.
6918
6926
6919 2. With the -c/--check option, the update is aborted and the
6927 2. With the -c/--check option, the update is aborted and the
6920 uncommitted changes are preserved.
6928 uncommitted changes are preserved.
6921
6929
6922 3. With the -C/--clean option, uncommitted changes are discarded and
6930 3. With the -C/--clean option, uncommitted changes are discarded and
6923 the working directory is updated to the requested changeset.
6931 the working directory is updated to the requested changeset.
6924
6932
6925 To cancel an uncommitted merge (and lose your changes), use
6933 To cancel an uncommitted merge (and lose your changes), use
6926 :hg:`update --clean .`.
6934 :hg:`update --clean .`.
6927
6935
6928 Use null as the changeset to remove the working directory (like
6936 Use null as the changeset to remove the working directory (like
6929 :hg:`clone -U`).
6937 :hg:`clone -U`).
6930
6938
6931 If you want to revert just one file to an older revision, use
6939 If you want to revert just one file to an older revision, use
6932 :hg:`revert [-r REV] NAME`.
6940 :hg:`revert [-r REV] NAME`.
6933
6941
6934 See :hg:`help dates` for a list of formats valid for -d/--date.
6942 See :hg:`help dates` for a list of formats valid for -d/--date.
6935
6943
6936 Returns 0 on success, 1 if there are unresolved files.
6944 Returns 0 on success, 1 if there are unresolved files.
6937 """
6945 """
6938 movemarkfrom = None
6946 movemarkfrom = None
6939 if rev and node:
6947 if rev and node:
6940 raise error.Abort(_("please specify just one revision"))
6948 raise error.Abort(_("please specify just one revision"))
6941
6949
6942 if rev is None or rev == '':
6950 if rev is None or rev == '':
6943 rev = node
6951 rev = node
6944
6952
6945 wlock = repo.wlock()
6953 wlock = repo.wlock()
6946 try:
6954 try:
6947 cmdutil.clearunfinished(repo)
6955 cmdutil.clearunfinished(repo)
6948
6956
6949 if date:
6957 if date:
6950 if rev is not None:
6958 if rev is not None:
6951 raise error.Abort(_("you can't specify a revision and a date"))
6959 raise error.Abort(_("you can't specify a revision and a date"))
6952 rev = cmdutil.finddate(ui, repo, date)
6960 rev = cmdutil.finddate(ui, repo, date)
6953
6961
6954 # if we defined a bookmark, we have to remember the original name
6962 # if we defined a bookmark, we have to remember the original name
6955 brev = rev
6963 brev = rev
6956 rev = scmutil.revsingle(repo, rev, rev).rev()
6964 rev = scmutil.revsingle(repo, rev, rev).rev()
6957
6965
6958 if check and clean:
6966 if check and clean:
6959 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6967 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6960 )
6968 )
6961
6969
6962 if check:
6970 if check:
6963 cmdutil.bailifchanged(repo, merge=False)
6971 cmdutil.bailifchanged(repo, merge=False)
6964 if rev is None:
6972 if rev is None:
6965 updata = destutil.destupdate(repo, clean=clean, check=check)
6973 updata = destutil.destupdate(repo, clean=clean, check=check)
6966 rev, movemarkfrom, brev = updata
6974 rev, movemarkfrom, brev = updata
6967
6975
6968 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6976 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6969
6977
6970 if clean:
6978 if clean:
6971 ret = hg.clean(repo, rev)
6979 ret = hg.clean(repo, rev)
6972 else:
6980 else:
6973 ret = hg.update(repo, rev)
6981 ret = hg.update(repo, rev)
6974
6982
6975 if not ret and movemarkfrom:
6983 if not ret and movemarkfrom:
6976 if movemarkfrom == repo['.'].node():
6984 if movemarkfrom == repo['.'].node():
6977 pass # no-op update
6985 pass # no-op update
6978 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6986 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6979 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6987 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6980 else:
6988 else:
6981 # this can happen with a non-linear update
6989 # this can happen with a non-linear update
6982 ui.status(_("(leaving bookmark %s)\n") %
6990 ui.status(_("(leaving bookmark %s)\n") %
6983 repo._activebookmark)
6991 repo._activebookmark)
6984 bookmarks.deactivate(repo)
6992 bookmarks.deactivate(repo)
6985 elif brev in repo._bookmarks:
6993 elif brev in repo._bookmarks:
6986 bookmarks.activate(repo, brev)
6994 bookmarks.activate(repo, brev)
6987 ui.status(_("(activating bookmark %s)\n") % brev)
6995 ui.status(_("(activating bookmark %s)\n") % brev)
6988 elif brev:
6996 elif brev:
6989 if repo._activebookmark:
6997 if repo._activebookmark:
6990 ui.status(_("(leaving bookmark %s)\n") %
6998 ui.status(_("(leaving bookmark %s)\n") %
6991 repo._activebookmark)
6999 repo._activebookmark)
6992 bookmarks.deactivate(repo)
7000 bookmarks.deactivate(repo)
6993 finally:
7001 finally:
6994 wlock.release()
7002 wlock.release()
6995
7003
6996 return ret
7004 return ret
6997
7005
6998 @command('verify', [])
7006 @command('verify', [])
6999 def verify(ui, repo):
7007 def verify(ui, repo):
7000 """verify the integrity of the repository
7008 """verify the integrity of the repository
7001
7009
7002 Verify the integrity of the current repository.
7010 Verify the integrity of the current repository.
7003
7011
7004 This will perform an extensive check of the repository's
7012 This will perform an extensive check of the repository's
7005 integrity, validating the hashes and checksums of each entry in
7013 integrity, validating the hashes and checksums of each entry in
7006 the changelog, manifest, and tracked files, as well as the
7014 the changelog, manifest, and tracked files, as well as the
7007 integrity of their crosslinks and indices.
7015 integrity of their crosslinks and indices.
7008
7016
7009 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7017 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7010 for more information about recovery from corruption of the
7018 for more information about recovery from corruption of the
7011 repository.
7019 repository.
7012
7020
7013 Returns 0 on success, 1 if errors are encountered.
7021 Returns 0 on success, 1 if errors are encountered.
7014 """
7022 """
7015 return hg.verify(repo)
7023 return hg.verify(repo)
7016
7024
7017 @command('version', [], norepo=True)
7025 @command('version', [], norepo=True)
7018 def version_(ui):
7026 def version_(ui):
7019 """output version and copyright information"""
7027 """output version and copyright information"""
7020 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7028 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7021 % util.version())
7029 % util.version())
7022 ui.status(_(
7030 ui.status(_(
7023 "(see https://mercurial-scm.org for more information)\n"
7031 "(see https://mercurial-scm.org for more information)\n"
7024 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7032 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7025 "This is free software; see the source for copying conditions. "
7033 "This is free software; see the source for copying conditions. "
7026 "There is NO\nwarranty; "
7034 "There is NO\nwarranty; "
7027 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7035 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7028 ))
7036 ))
7029
7037
7030 ui.note(_("\nEnabled extensions:\n\n"))
7038 ui.note(_("\nEnabled extensions:\n\n"))
7031 if ui.verbose:
7039 if ui.verbose:
7032 # format names and versions into columns
7040 # format names and versions into columns
7033 names = []
7041 names = []
7034 vers = []
7042 vers = []
7035 for name, module in extensions.extensions():
7043 for name, module in extensions.extensions():
7036 names.append(name)
7044 names.append(name)
7037 vers.append(extensions.moduleversion(module))
7045 vers.append(extensions.moduleversion(module))
7038 if names:
7046 if names:
7039 maxnamelen = max(len(n) for n in names)
7047 maxnamelen = max(len(n) for n in names)
7040 for i, name in enumerate(names):
7048 for i, name in enumerate(names):
7041 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7049 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
@@ -1,350 +1,350 b''
1 Show all commands except debug commands
1 Show all commands except debug commands
2 $ hg debugcomplete
2 $ hg debugcomplete
3 add
3 add
4 addremove
4 addremove
5 annotate
5 annotate
6 archive
6 archive
7 backout
7 backout
8 bisect
8 bisect
9 bookmarks
9 bookmarks
10 branch
10 branch
11 branches
11 branches
12 bundle
12 bundle
13 cat
13 cat
14 clone
14 clone
15 commit
15 commit
16 config
16 config
17 copy
17 copy
18 diff
18 diff
19 export
19 export
20 files
20 files
21 forget
21 forget
22 graft
22 graft
23 grep
23 grep
24 heads
24 heads
25 help
25 help
26 identify
26 identify
27 import
27 import
28 incoming
28 incoming
29 init
29 init
30 locate
30 locate
31 log
31 log
32 manifest
32 manifest
33 merge
33 merge
34 outgoing
34 outgoing
35 parents
35 parents
36 paths
36 paths
37 phase
37 phase
38 pull
38 pull
39 push
39 push
40 recover
40 recover
41 remove
41 remove
42 rename
42 rename
43 resolve
43 resolve
44 revert
44 revert
45 rollback
45 rollback
46 root
46 root
47 serve
47 serve
48 status
48 status
49 summary
49 summary
50 tag
50 tag
51 tags
51 tags
52 tip
52 tip
53 unbundle
53 unbundle
54 update
54 update
55 verify
55 verify
56 version
56 version
57
57
58 Show all commands that start with "a"
58 Show all commands that start with "a"
59 $ hg debugcomplete a
59 $ hg debugcomplete a
60 add
60 add
61 addremove
61 addremove
62 annotate
62 annotate
63 archive
63 archive
64
64
65 Do not show debug commands if there are other candidates
65 Do not show debug commands if there are other candidates
66 $ hg debugcomplete d
66 $ hg debugcomplete d
67 diff
67 diff
68
68
69 Show debug commands if there are no other candidates
69 Show debug commands if there are no other candidates
70 $ hg debugcomplete debug
70 $ hg debugcomplete debug
71 debugancestor
71 debugancestor
72 debugapplystreamclonebundle
72 debugapplystreamclonebundle
73 debugbuilddag
73 debugbuilddag
74 debugbundle
74 debugbundle
75 debugcheckstate
75 debugcheckstate
76 debugcommands
76 debugcommands
77 debugcomplete
77 debugcomplete
78 debugconfig
78 debugconfig
79 debugcreatestreamclonebundle
79 debugcreatestreamclonebundle
80 debugdag
80 debugdag
81 debugdata
81 debugdata
82 debugdate
82 debugdate
83 debugdeltachain
83 debugdeltachain
84 debugdirstate
84 debugdirstate
85 debugdiscovery
85 debugdiscovery
86 debugextensions
86 debugextensions
87 debugfileset
87 debugfileset
88 debugfsinfo
88 debugfsinfo
89 debuggetbundle
89 debuggetbundle
90 debugignore
90 debugignore
91 debugindex
91 debugindex
92 debugindexdot
92 debugindexdot
93 debuginstall
93 debuginstall
94 debugknown
94 debugknown
95 debuglabelcomplete
95 debuglabelcomplete
96 debuglocks
96 debuglocks
97 debugmergestate
97 debugmergestate
98 debugnamecomplete
98 debugnamecomplete
99 debugobsolete
99 debugobsolete
100 debugpathcomplete
100 debugpathcomplete
101 debugpushkey
101 debugpushkey
102 debugpvec
102 debugpvec
103 debugrebuilddirstate
103 debugrebuilddirstate
104 debugrebuildfncache
104 debugrebuildfncache
105 debugrename
105 debugrename
106 debugrevlog
106 debugrevlog
107 debugrevspec
107 debugrevspec
108 debugsetparents
108 debugsetparents
109 debugsub
109 debugsub
110 debugsuccessorssets
110 debugsuccessorssets
111 debugwalk
111 debugwalk
112 debugwireargs
112 debugwireargs
113
113
114 Do not show the alias of a debug command if there are other candidates
114 Do not show the alias of a debug command if there are other candidates
115 (this should hide rawcommit)
115 (this should hide rawcommit)
116 $ hg debugcomplete r
116 $ hg debugcomplete r
117 recover
117 recover
118 remove
118 remove
119 rename
119 rename
120 resolve
120 resolve
121 revert
121 revert
122 rollback
122 rollback
123 root
123 root
124 Show the alias of a debug command if there are no other candidates
124 Show the alias of a debug command if there are no other candidates
125 $ hg debugcomplete rawc
125 $ hg debugcomplete rawc
126
126
127
127
128 Show the global options
128 Show the global options
129 $ hg debugcomplete --options | sort
129 $ hg debugcomplete --options | sort
130 --config
130 --config
131 --cwd
131 --cwd
132 --debug
132 --debug
133 --debugger
133 --debugger
134 --encoding
134 --encoding
135 --encodingmode
135 --encodingmode
136 --help
136 --help
137 --hidden
137 --hidden
138 --noninteractive
138 --noninteractive
139 --profile
139 --profile
140 --quiet
140 --quiet
141 --repository
141 --repository
142 --time
142 --time
143 --traceback
143 --traceback
144 --verbose
144 --verbose
145 --version
145 --version
146 -R
146 -R
147 -h
147 -h
148 -q
148 -q
149 -v
149 -v
150 -y
150 -y
151
151
152 Show the options for the "serve" command
152 Show the options for the "serve" command
153 $ hg debugcomplete --options serve | sort
153 $ hg debugcomplete --options serve | sort
154 --accesslog
154 --accesslog
155 --address
155 --address
156 --certificate
156 --certificate
157 --cmdserver
157 --cmdserver
158 --config
158 --config
159 --cwd
159 --cwd
160 --daemon
160 --daemon
161 --daemon-pipefds
161 --daemon-pipefds
162 --debug
162 --debug
163 --debugger
163 --debugger
164 --encoding
164 --encoding
165 --encodingmode
165 --encodingmode
166 --errorlog
166 --errorlog
167 --help
167 --help
168 --hidden
168 --hidden
169 --ipv6
169 --ipv6
170 --name
170 --name
171 --noninteractive
171 --noninteractive
172 --pid-file
172 --pid-file
173 --port
173 --port
174 --prefix
174 --prefix
175 --profile
175 --profile
176 --quiet
176 --quiet
177 --repository
177 --repository
178 --stdio
178 --stdio
179 --style
179 --style
180 --templates
180 --templates
181 --time
181 --time
182 --traceback
182 --traceback
183 --verbose
183 --verbose
184 --version
184 --version
185 --web-conf
185 --web-conf
186 -6
186 -6
187 -A
187 -A
188 -E
188 -E
189 -R
189 -R
190 -a
190 -a
191 -d
191 -d
192 -h
192 -h
193 -n
193 -n
194 -p
194 -p
195 -q
195 -q
196 -t
196 -t
197 -v
197 -v
198 -y
198 -y
199
199
200 Show an error if we use --options with an ambiguous abbreviation
200 Show an error if we use --options with an ambiguous abbreviation
201 $ hg debugcomplete --options s
201 $ hg debugcomplete --options s
202 hg: command 's' is ambiguous:
202 hg: command 's' is ambiguous:
203 serve showconfig status summary
203 serve showconfig status summary
204 [255]
204 [255]
205
205
206 Show all commands + options
206 Show all commands + options
207 $ hg debugcommands
207 $ hg debugcommands
208 add: include, exclude, subrepos, dry-run
208 add: include, exclude, subrepos, dry-run
209 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
209 annotate: rev, follow, no-follow, text, user, file, date, number, changeset, line-number, ignore-all-space, ignore-space-change, ignore-blank-lines, include, exclude, template
210 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
210 clone: noupdate, updaterev, rev, branch, pull, uncompressed, ssh, remotecmd, insecure
211 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
211 commit: addremove, close-branch, amend, secret, edit, interactive, include, exclude, message, logfile, date, user, subrepos
212 diff: rev, change, text, git, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, root, include, exclude, subrepos
212 diff: rev, change, text, git, nodates, noprefix, show-function, reverse, ignore-all-space, ignore-space-change, ignore-blank-lines, unified, stat, root, include, exclude, subrepos
213 export: output, switch-parent, rev, text, git, nodates
213 export: output, switch-parent, rev, text, git, nodates
214 forget: include, exclude
214 forget: include, exclude
215 init: ssh, remotecmd, insecure
215 init: ssh, remotecmd, insecure
216 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
216 log: follow, follow-first, date, copies, keyword, rev, removed, only-merges, user, only-branch, branch, prune, patch, git, limit, no-merges, stat, graph, style, template, include, exclude
217 merge: force, rev, preview, tool
217 merge: force, rev, preview, tool
218 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
218 pull: update, force, rev, bookmark, branch, ssh, remotecmd, insecure
219 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
219 push: force, rev, bookmark, branch, new-branch, ssh, remotecmd, insecure
220 remove: after, force, subrepos, include, exclude
220 remove: after, force, subrepos, include, exclude
221 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
221 serve: accesslog, daemon, daemon-pipefds, errorlog, port, address, prefix, name, web-conf, webdir-conf, pid-file, stdio, cmdserver, templates, style, ipv6, certificate
222 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
222 status: all, modified, added, removed, deleted, clean, unknown, ignored, no-status, copies, print0, rev, change, include, exclude, subrepos, template
223 summary: remote
223 summary: remote
224 update: clean, check, date, rev, tool
224 update: clean, check, date, rev, tool
225 addremove: similarity, subrepos, include, exclude, dry-run
225 addremove: similarity, subrepos, include, exclude, dry-run
226 archive: no-decode, prefix, rev, type, subrepos, include, exclude
226 archive: no-decode, prefix, rev, type, subrepos, include, exclude
227 backout: merge, commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
227 backout: merge, commit, parent, rev, edit, tool, include, exclude, message, logfile, date, user
228 bisect: reset, good, bad, skip, extend, command, noupdate
228 bisect: reset, good, bad, skip, extend, command, noupdate
229 bookmarks: force, rev, delete, rename, inactive, template
229 bookmarks: force, rev, delete, rename, inactive, template
230 branch: force, clean
230 branch: force, clean
231 branches: active, closed, template
231 branches: active, closed, template
232 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
232 bundle: force, rev, branch, base, all, type, ssh, remotecmd, insecure
233 cat: output, rev, decode, include, exclude
233 cat: output, rev, decode, include, exclude
234 config: untrusted, edit, local, global
234 config: untrusted, edit, local, global
235 copy: after, force, include, exclude, dry-run
235 copy: after, force, include, exclude, dry-run
236 debugancestor:
236 debugancestor:
237 debugapplystreamclonebundle:
237 debugapplystreamclonebundle:
238 debugbuilddag: mergeable-file, overwritten-file, new-file
238 debugbuilddag: mergeable-file, overwritten-file, new-file
239 debugbundle: all
239 debugbundle: all
240 debugcheckstate:
240 debugcheckstate:
241 debugcommands:
241 debugcommands:
242 debugcomplete: options
242 debugcomplete: options
243 debugcreatestreamclonebundle:
243 debugcreatestreamclonebundle:
244 debugdag: tags, branches, dots, spaces
244 debugdag: tags, branches, dots, spaces
245 debugdata: changelog, manifest, dir
245 debugdata: changelog, manifest, dir
246 debugdate: extended
246 debugdate: extended
247 debugdeltachain: changelog, manifest, dir, template
247 debugdeltachain: changelog, manifest, dir, template
248 debugdirstate: nodates, datesort
248 debugdirstate: nodates, datesort
249 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
249 debugdiscovery: old, nonheads, ssh, remotecmd, insecure
250 debugextensions: template
250 debugextensions: template
251 debugfileset: rev
251 debugfileset: rev
252 debugfsinfo:
252 debugfsinfo:
253 debuggetbundle: head, common, type
253 debuggetbundle: head, common, type
254 debugignore:
254 debugignore:
255 debugindex: changelog, manifest, dir, format
255 debugindex: changelog, manifest, dir, format
256 debugindexdot: changelog, manifest, dir
256 debugindexdot: changelog, manifest, dir
257 debuginstall:
257 debuginstall:
258 debugknown:
258 debugknown:
259 debuglabelcomplete:
259 debuglabelcomplete:
260 debuglocks: force-lock, force-wlock
260 debuglocks: force-lock, force-wlock
261 debugmergestate:
261 debugmergestate:
262 debugnamecomplete:
262 debugnamecomplete:
263 debugobsolete: flags, record-parents, rev, date, user
263 debugobsolete: flags, record-parents, rev, date, user
264 debugpathcomplete: full, normal, added, removed
264 debugpathcomplete: full, normal, added, removed
265 debugpushkey:
265 debugpushkey:
266 debugpvec:
266 debugpvec:
267 debugrebuilddirstate: rev, minimal
267 debugrebuilddirstate: rev, minimal
268 debugrebuildfncache:
268 debugrebuildfncache:
269 debugrename: rev
269 debugrename: rev
270 debugrevlog: changelog, manifest, dir, dump
270 debugrevlog: changelog, manifest, dir, dump
271 debugrevspec: optimize
271 debugrevspec: optimize
272 debugsetparents:
272 debugsetparents:
273 debugsub: rev
273 debugsub: rev
274 debugsuccessorssets:
274 debugsuccessorssets:
275 debugwalk: include, exclude
275 debugwalk: include, exclude
276 debugwireargs: three, four, five, ssh, remotecmd, insecure
276 debugwireargs: three, four, five, ssh, remotecmd, insecure
277 files: rev, print0, include, exclude, template, subrepos
277 files: rev, print0, include, exclude, template, subrepos
278 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
278 graft: rev, continue, edit, log, force, currentdate, currentuser, date, user, tool, dry-run
279 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
279 grep: print0, all, text, follow, ignore-case, files-with-matches, line-number, rev, user, date, include, exclude
280 heads: rev, topo, active, closed, style, template
280 heads: rev, topo, active, closed, style, template
281 help: extension, command, keyword
281 help: extension, command, keyword
282 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
282 identify: rev, num, id, branch, tags, bookmarks, ssh, remotecmd, insecure
283 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
283 import: strip, base, edit, force, no-commit, bypass, partial, exact, prefix, import-branch, message, logfile, date, user, similarity
284 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
284 incoming: force, newest-first, bundle, rev, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
285 locate: rev, print0, fullpath, include, exclude
285 locate: rev, print0, fullpath, include, exclude
286 manifest: rev, all, template
286 manifest: rev, all, template
287 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
287 outgoing: force, rev, newest-first, bookmarks, branch, patch, git, limit, no-merges, stat, graph, style, template, ssh, remotecmd, insecure, subrepos
288 parents: rev, style, template
288 parents: rev, style, template
289 paths:
289 paths: template
290 phase: public, draft, secret, force, rev
290 phase: public, draft, secret, force, rev
291 recover:
291 recover:
292 rename: after, force, include, exclude, dry-run
292 rename: after, force, include, exclude, dry-run
293 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
293 resolve: all, list, mark, unmark, no-status, tool, include, exclude, template
294 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
294 revert: all, date, rev, no-backup, interactive, include, exclude, dry-run
295 rollback: dry-run, force
295 rollback: dry-run, force
296 root:
296 root:
297 tag: force, local, rev, remove, edit, message, date, user
297 tag: force, local, rev, remove, edit, message, date, user
298 tags: template
298 tags: template
299 tip: patch, git, style, template
299 tip: patch, git, style, template
300 unbundle: update
300 unbundle: update
301 verify:
301 verify:
302 version:
302 version:
303
303
304 $ hg init a
304 $ hg init a
305 $ cd a
305 $ cd a
306 $ echo fee > fee
306 $ echo fee > fee
307 $ hg ci -q -Amfee
307 $ hg ci -q -Amfee
308 $ hg tag fee
308 $ hg tag fee
309 $ mkdir fie
309 $ mkdir fie
310 $ echo dead > fie/dead
310 $ echo dead > fie/dead
311 $ echo live > fie/live
311 $ echo live > fie/live
312 $ hg bookmark fo
312 $ hg bookmark fo
313 $ hg branch -q fie
313 $ hg branch -q fie
314 $ hg ci -q -Amfie
314 $ hg ci -q -Amfie
315 $ echo fo > fo
315 $ echo fo > fo
316 $ hg branch -qf default
316 $ hg branch -qf default
317 $ hg ci -q -Amfo
317 $ hg ci -q -Amfo
318 $ echo Fum > Fum
318 $ echo Fum > Fum
319 $ hg ci -q -AmFum
319 $ hg ci -q -AmFum
320 $ hg bookmark Fum
320 $ hg bookmark Fum
321
321
322 Test debugpathcomplete
322 Test debugpathcomplete
323
323
324 $ hg debugpathcomplete f
324 $ hg debugpathcomplete f
325 fee
325 fee
326 fie
326 fie
327 fo
327 fo
328 $ hg debugpathcomplete -f f
328 $ hg debugpathcomplete -f f
329 fee
329 fee
330 fie/dead
330 fie/dead
331 fie/live
331 fie/live
332 fo
332 fo
333
333
334 $ hg rm Fum
334 $ hg rm Fum
335 $ hg debugpathcomplete -r F
335 $ hg debugpathcomplete -r F
336 Fum
336 Fum
337
337
338 Test debugnamecomplete
338 Test debugnamecomplete
339
339
340 $ hg debugnamecomplete
340 $ hg debugnamecomplete
341 Fum
341 Fum
342 default
342 default
343 fee
343 fee
344 fie
344 fie
345 fo
345 fo
346 tip
346 tip
347 $ hg debugnamecomplete f
347 $ hg debugnamecomplete f
348 fee
348 fee
349 fie
349 fie
350 fo
350 fo
@@ -1,128 +1,173 b''
1 $ hg init a
1 $ hg init a
2 $ hg clone a b
2 $ hg clone a b
3 updating to branch default
3 updating to branch default
4 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
4 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
5 $ cd a
5 $ cd a
6
6
7 with no paths:
7 with no paths:
8
8
9 $ hg paths
9 $ hg paths
10 $ hg paths unknown
10 $ hg paths unknown
11 not found!
11 not found!
12 [1]
12 [1]
13 $ hg paths -Tjson
14 [
15 ]
13
16
14 with paths:
17 with paths:
15
18
16 $ echo '[paths]' >> .hg/hgrc
19 $ echo '[paths]' >> .hg/hgrc
17 $ echo 'dupe = ../b#tip' >> .hg/hgrc
20 $ echo 'dupe = ../b#tip' >> .hg/hgrc
18 $ echo 'expand = $SOMETHING/bar' >> .hg/hgrc
21 $ echo 'expand = $SOMETHING/bar' >> .hg/hgrc
19 $ hg in dupe
22 $ hg in dupe
20 comparing with $TESTTMP/b (glob)
23 comparing with $TESTTMP/b (glob)
21 no changes found
24 no changes found
22 [1]
25 [1]
23 $ cd ..
26 $ cd ..
24 $ hg -R a in dupe
27 $ hg -R a in dupe
25 comparing with $TESTTMP/b (glob)
28 comparing with $TESTTMP/b (glob)
26 no changes found
29 no changes found
27 [1]
30 [1]
28 $ cd a
31 $ cd a
29 $ hg paths
32 $ hg paths
30 dupe = $TESTTMP/b#tip (glob)
33 dupe = $TESTTMP/b#tip (glob)
31 expand = $TESTTMP/a/$SOMETHING/bar (glob)
34 expand = $TESTTMP/a/$SOMETHING/bar (glob)
32 $ SOMETHING=foo hg paths
35 $ SOMETHING=foo hg paths
33 dupe = $TESTTMP/b#tip (glob)
36 dupe = $TESTTMP/b#tip (glob)
34 expand = $TESTTMP/a/foo/bar (glob)
37 expand = $TESTTMP/a/foo/bar (glob)
35 #if msys
38 #if msys
36 $ SOMETHING=//foo hg paths
39 $ SOMETHING=//foo hg paths
37 dupe = $TESTTMP/b#tip (glob)
40 dupe = $TESTTMP/b#tip (glob)
38 expand = /foo/bar
41 expand = /foo/bar
39 #else
42 #else
40 $ SOMETHING=/foo hg paths
43 $ SOMETHING=/foo hg paths
41 dupe = $TESTTMP/b#tip (glob)
44 dupe = $TESTTMP/b#tip (glob)
42 expand = /foo/bar
45 expand = /foo/bar
43 #endif
46 #endif
44 $ hg paths -q
47 $ hg paths -q
45 dupe
48 dupe
46 expand
49 expand
47 $ hg paths dupe
50 $ hg paths dupe
48 $TESTTMP/b#tip (glob)
51 $TESTTMP/b#tip (glob)
49 $ hg paths -q dupe
52 $ hg paths -q dupe
50 $ hg paths unknown
53 $ hg paths unknown
51 not found!
54 not found!
52 [1]
55 [1]
53 $ hg paths -q unknown
56 $ hg paths -q unknown
54 [1]
57 [1]
58
59 formatter output with paths:
60
61 $ echo 'dupe:pushurl = https://example.com/dupe' >> .hg/hgrc
62 $ hg paths -Tjson
63 [
64 {
65 "name": "dupe",
66 "pushurl": "https://example.com/dupe",
67 "url": "$TESTTMP/b#tip"
68 },
69 {
70 "name": "expand",
71 "url": "$TESTTMP/a/$SOMETHING/bar"
72 }
73 ]
74 $ hg paths -Tjson dupe
75 [
76 {
77 "name": "dupe",
78 "pushurl": "https://example.com/dupe",
79 "url": "$TESTTMP/b#tip"
80 }
81 ]
82 $ hg paths -Tjson -q unknown
83 [
84 ]
85 [1]
86
87 password should be masked in plain output, but not in machine-readable output:
88
89 $ echo 'insecure = http://foo:insecure@example.com/' >> .hg/hgrc
90 $ hg paths insecure
91 http://foo:***@example.com/
92 $ hg paths -Tjson insecure
93 [
94 {
95 "name": "insecure",
96 "url": "http://foo:insecure@example.com/"
97 }
98 ]
99
55 $ cd ..
100 $ cd ..
56
101
57 sub-options for an undeclared path are ignored
102 sub-options for an undeclared path are ignored
58
103
59 $ hg init suboptions
104 $ hg init suboptions
60 $ cd suboptions
105 $ cd suboptions
61
106
62 $ cat > .hg/hgrc << EOF
107 $ cat > .hg/hgrc << EOF
63 > [paths]
108 > [paths]
64 > path0 = https://example.com/path0
109 > path0 = https://example.com/path0
65 > path1:pushurl = https://example.com/path1
110 > path1:pushurl = https://example.com/path1
66 > EOF
111 > EOF
67 $ hg paths
112 $ hg paths
68 path0 = https://example.com/path0
113 path0 = https://example.com/path0
69
114
70 unknown sub-options aren't displayed
115 unknown sub-options aren't displayed
71
116
72 $ cat > .hg/hgrc << EOF
117 $ cat > .hg/hgrc << EOF
73 > [paths]
118 > [paths]
74 > path0 = https://example.com/path0
119 > path0 = https://example.com/path0
75 > path0:foo = https://example.com/path1
120 > path0:foo = https://example.com/path1
76 > EOF
121 > EOF
77
122
78 $ hg paths
123 $ hg paths
79 path0 = https://example.com/path0
124 path0 = https://example.com/path0
80
125
81 :pushurl must be a URL
126 :pushurl must be a URL
82
127
83 $ cat > .hg/hgrc << EOF
128 $ cat > .hg/hgrc << EOF
84 > [paths]
129 > [paths]
85 > default = /path/to/nothing
130 > default = /path/to/nothing
86 > default:pushurl = /not/a/url
131 > default:pushurl = /not/a/url
87 > EOF
132 > EOF
88
133
89 $ hg paths
134 $ hg paths
90 (paths.default:pushurl not a URL; ignoring)
135 (paths.default:pushurl not a URL; ignoring)
91 default = /path/to/nothing
136 default = /path/to/nothing
92
137
93 #fragment is not allowed in :pushurl
138 #fragment is not allowed in :pushurl
94
139
95 $ cat > .hg/hgrc << EOF
140 $ cat > .hg/hgrc << EOF
96 > [paths]
141 > [paths]
97 > default = https://example.com/repo
142 > default = https://example.com/repo
98 > invalid = https://example.com/repo
143 > invalid = https://example.com/repo
99 > invalid:pushurl = https://example.com/repo#branch
144 > invalid:pushurl = https://example.com/repo#branch
100 > EOF
145 > EOF
101
146
102 $ hg paths
147 $ hg paths
103 ("#fragment" in paths.invalid:pushurl not supported; ignoring)
148 ("#fragment" in paths.invalid:pushurl not supported; ignoring)
104 default = https://example.com/repo
149 default = https://example.com/repo
105 invalid = https://example.com/repo
150 invalid = https://example.com/repo
106 invalid:pushurl = https://example.com/repo
151 invalid:pushurl = https://example.com/repo
107
152
108 $ cd ..
153 $ cd ..
109
154
110 'file:' disables [paths] entries for clone destination
155 'file:' disables [paths] entries for clone destination
111
156
112 $ cat >> $HGRCPATH <<EOF
157 $ cat >> $HGRCPATH <<EOF
113 > [paths]
158 > [paths]
114 > gpath1 = http://hg.example.com
159 > gpath1 = http://hg.example.com
115 > EOF
160 > EOF
116
161
117 $ hg clone a gpath1
162 $ hg clone a gpath1
118 abort: cannot create new http repository
163 abort: cannot create new http repository
119 [255]
164 [255]
120
165
121 $ hg clone a file:gpath1
166 $ hg clone a file:gpath1
122 updating to branch default
167 updating to branch default
123 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
168 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
124 $ cd gpath1
169 $ cd gpath1
125 $ hg -q id
170 $ hg -q id
126 000000000000
171 000000000000
127
172
128 $ cd ..
173 $ cd ..
General Comments 0
You need to be logged in to leave comments. Login now