##// END OF EJS Templates
with: use context manager for wlock in graft
Bryan O'Sullivan -
r27808:0c48c566 default
parent child Browse files
Show More
@@ -1,7035 +1,7031 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 with repo.wlock():
1200 with repo.wlock():
1201 if opts.get('clean'):
1201 if opts.get('clean'):
1202 label = repo[None].p1().branch()
1202 label = repo[None].p1().branch()
1203 repo.dirstate.setbranch(label)
1203 repo.dirstate.setbranch(label)
1204 ui.status(_('reset working directory to branch %s\n') % label)
1204 ui.status(_('reset working directory to branch %s\n') % label)
1205 elif label:
1205 elif label:
1206 if not opts.get('force') and label in repo.branchmap():
1206 if not opts.get('force') and label in repo.branchmap():
1207 if label not in [p.branch() for p in repo[None].parents()]:
1207 if label not in [p.branch() for p in repo[None].parents()]:
1208 raise error.Abort(_('a branch of the same name already'
1208 raise error.Abort(_('a branch of the same name already'
1209 ' exists'),
1209 ' exists'),
1210 # i18n: "it" refers to an existing branch
1210 # i18n: "it" refers to an existing branch
1211 hint=_("use 'hg update' to switch to it"))
1211 hint=_("use 'hg update' to switch to it"))
1212 scmutil.checknewlabel(repo, label, 'branch')
1212 scmutil.checknewlabel(repo, label, 'branch')
1213 repo.dirstate.setbranch(label)
1213 repo.dirstate.setbranch(label)
1214 ui.status(_('marked working directory as branch %s\n') % label)
1214 ui.status(_('marked working directory as branch %s\n') % label)
1215
1215
1216 # find any open named branches aside from default
1216 # find any open named branches aside from default
1217 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1217 others = [n for n, h, t, c in repo.branchmap().iterbranches()
1218 if n != "default" and not c]
1218 if n != "default" and not c]
1219 if not others:
1219 if not others:
1220 ui.status(_('(branches are permanent and global, '
1220 ui.status(_('(branches are permanent and global, '
1221 'did you want a bookmark?)\n'))
1221 'did you want a bookmark?)\n'))
1222
1222
1223 @command('branches',
1223 @command('branches',
1224 [('a', 'active', False,
1224 [('a', 'active', False,
1225 _('show only branches that have unmerged heads (DEPRECATED)')),
1225 _('show only branches that have unmerged heads (DEPRECATED)')),
1226 ('c', 'closed', False, _('show normal and closed branches')),
1226 ('c', 'closed', False, _('show normal and closed branches')),
1227 ] + formatteropts,
1227 ] + formatteropts,
1228 _('[-ac]'))
1228 _('[-ac]'))
1229 def branches(ui, repo, active=False, closed=False, **opts):
1229 def branches(ui, repo, active=False, closed=False, **opts):
1230 """list repository named branches
1230 """list repository named branches
1231
1231
1232 List the repository's named branches, indicating which ones are
1232 List the repository's named branches, indicating which ones are
1233 inactive. If -c/--closed is specified, also list branches which have
1233 inactive. If -c/--closed is specified, also list branches which have
1234 been marked closed (see :hg:`commit --close-branch`).
1234 been marked closed (see :hg:`commit --close-branch`).
1235
1235
1236 Use the command :hg:`update` to switch to an existing branch.
1236 Use the command :hg:`update` to switch to an existing branch.
1237
1237
1238 Returns 0.
1238 Returns 0.
1239 """
1239 """
1240
1240
1241 fm = ui.formatter('branches', opts)
1241 fm = ui.formatter('branches', opts)
1242 hexfunc = fm.hexfunc
1242 hexfunc = fm.hexfunc
1243
1243
1244 allheads = set(repo.heads())
1244 allheads = set(repo.heads())
1245 branches = []
1245 branches = []
1246 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1246 for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
1247 isactive = not isclosed and bool(set(heads) & allheads)
1247 isactive = not isclosed and bool(set(heads) & allheads)
1248 branches.append((tag, repo[tip], isactive, not isclosed))
1248 branches.append((tag, repo[tip], isactive, not isclosed))
1249 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1249 branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
1250 reverse=True)
1250 reverse=True)
1251
1251
1252 for tag, ctx, isactive, isopen in branches:
1252 for tag, ctx, isactive, isopen in branches:
1253 if active and not isactive:
1253 if active and not isactive:
1254 continue
1254 continue
1255 if isactive:
1255 if isactive:
1256 label = 'branches.active'
1256 label = 'branches.active'
1257 notice = ''
1257 notice = ''
1258 elif not isopen:
1258 elif not isopen:
1259 if not closed:
1259 if not closed:
1260 continue
1260 continue
1261 label = 'branches.closed'
1261 label = 'branches.closed'
1262 notice = _(' (closed)')
1262 notice = _(' (closed)')
1263 else:
1263 else:
1264 label = 'branches.inactive'
1264 label = 'branches.inactive'
1265 notice = _(' (inactive)')
1265 notice = _(' (inactive)')
1266 current = (tag == repo.dirstate.branch())
1266 current = (tag == repo.dirstate.branch())
1267 if current:
1267 if current:
1268 label = 'branches.current'
1268 label = 'branches.current'
1269
1269
1270 fm.startitem()
1270 fm.startitem()
1271 fm.write('branch', '%s', tag, label=label)
1271 fm.write('branch', '%s', tag, label=label)
1272 rev = ctx.rev()
1272 rev = ctx.rev()
1273 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1273 padsize = max(31 - len(str(rev)) - encoding.colwidth(tag), 0)
1274 fmt = ' ' * padsize + ' %d:%s'
1274 fmt = ' ' * padsize + ' %d:%s'
1275 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1275 fm.condwrite(not ui.quiet, 'rev node', fmt, rev, hexfunc(ctx.node()),
1276 label='log.changeset changeset.%s' % ctx.phasestr())
1276 label='log.changeset changeset.%s' % ctx.phasestr())
1277 fm.data(active=isactive, closed=not isopen, current=current)
1277 fm.data(active=isactive, closed=not isopen, current=current)
1278 if not ui.quiet:
1278 if not ui.quiet:
1279 fm.plain(notice)
1279 fm.plain(notice)
1280 fm.plain('\n')
1280 fm.plain('\n')
1281 fm.end()
1281 fm.end()
1282
1282
1283 @command('bundle',
1283 @command('bundle',
1284 [('f', 'force', None, _('run even when the destination is unrelated')),
1284 [('f', 'force', None, _('run even when the destination is unrelated')),
1285 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1285 ('r', 'rev', [], _('a changeset intended to be added to the destination'),
1286 _('REV')),
1286 _('REV')),
1287 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1287 ('b', 'branch', [], _('a specific branch you would like to bundle'),
1288 _('BRANCH')),
1288 _('BRANCH')),
1289 ('', 'base', [],
1289 ('', 'base', [],
1290 _('a base changeset assumed to be available at the destination'),
1290 _('a base changeset assumed to be available at the destination'),
1291 _('REV')),
1291 _('REV')),
1292 ('a', 'all', None, _('bundle all changesets in the repository')),
1292 ('a', 'all', None, _('bundle all changesets in the repository')),
1293 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1293 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE')),
1294 ] + remoteopts,
1294 ] + remoteopts,
1295 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1295 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]'))
1296 def bundle(ui, repo, fname, dest=None, **opts):
1296 def bundle(ui, repo, fname, dest=None, **opts):
1297 """create a changegroup file
1297 """create a changegroup file
1298
1298
1299 Generate a changegroup file collecting changesets to be added
1299 Generate a changegroup file collecting changesets to be added
1300 to a repository.
1300 to a repository.
1301
1301
1302 To create a bundle containing all changesets, use -a/--all
1302 To create a bundle containing all changesets, use -a/--all
1303 (or --base null). Otherwise, hg assumes the destination will have
1303 (or --base null). Otherwise, hg assumes the destination will have
1304 all the nodes you specify with --base parameters. Otherwise, hg
1304 all the nodes you specify with --base parameters. Otherwise, hg
1305 will assume the repository has all the nodes in destination, or
1305 will assume the repository has all the nodes in destination, or
1306 default-push/default if no destination is specified.
1306 default-push/default if no destination is specified.
1307
1307
1308 You can change bundle format with the -t/--type option. You can
1308 You can change bundle format with the -t/--type option. You can
1309 specify a compression, a bundle version or both using a dash
1309 specify a compression, a bundle version or both using a dash
1310 (comp-version). The available compression methods are: none, bzip2,
1310 (comp-version). The available compression methods are: none, bzip2,
1311 and gzip (by default, bundles are compressed using bzip2). The
1311 and gzip (by default, bundles are compressed using bzip2). The
1312 available formats are: v1, v2 (default to most suitable).
1312 available formats are: v1, v2 (default to most suitable).
1313
1313
1314 The bundle file can then be transferred using conventional means
1314 The bundle file can then be transferred using conventional means
1315 and applied to another repository with the unbundle or pull
1315 and applied to another repository with the unbundle or pull
1316 command. This is useful when direct push and pull are not
1316 command. This is useful when direct push and pull are not
1317 available or when exporting an entire repository is undesirable.
1317 available or when exporting an entire repository is undesirable.
1318
1318
1319 Applying bundles preserves all changeset contents including
1319 Applying bundles preserves all changeset contents including
1320 permissions, copy/rename information, and revision history.
1320 permissions, copy/rename information, and revision history.
1321
1321
1322 Returns 0 on success, 1 if no changes found.
1322 Returns 0 on success, 1 if no changes found.
1323 """
1323 """
1324 revs = None
1324 revs = None
1325 if 'rev' in opts:
1325 if 'rev' in opts:
1326 revs = scmutil.revrange(repo, opts['rev'])
1326 revs = scmutil.revrange(repo, opts['rev'])
1327
1327
1328 bundletype = opts.get('type', 'bzip2').lower()
1328 bundletype = opts.get('type', 'bzip2').lower()
1329 try:
1329 try:
1330 bcompression, cgversion, params = exchange.parsebundlespec(
1330 bcompression, cgversion, params = exchange.parsebundlespec(
1331 repo, bundletype, strict=False)
1331 repo, bundletype, strict=False)
1332 except error.UnsupportedBundleSpecification as e:
1332 except error.UnsupportedBundleSpecification as e:
1333 raise error.Abort(str(e),
1333 raise error.Abort(str(e),
1334 hint=_('see "hg help bundle" for supported '
1334 hint=_('see "hg help bundle" for supported '
1335 'values for --type'))
1335 'values for --type'))
1336
1336
1337 # Packed bundles are a pseudo bundle format for now.
1337 # Packed bundles are a pseudo bundle format for now.
1338 if cgversion == 's1':
1338 if cgversion == 's1':
1339 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1339 raise error.Abort(_('packed bundles cannot be produced by "hg bundle"'),
1340 hint=_('use "hg debugcreatestreamclonebundle"'))
1340 hint=_('use "hg debugcreatestreamclonebundle"'))
1341
1341
1342 if opts.get('all'):
1342 if opts.get('all'):
1343 if dest:
1343 if dest:
1344 raise error.Abort(_("--all is incompatible with specifying "
1344 raise error.Abort(_("--all is incompatible with specifying "
1345 "a destination"))
1345 "a destination"))
1346 if opts.get('base'):
1346 if opts.get('base'):
1347 ui.warn(_("ignoring --base because --all was specified\n"))
1347 ui.warn(_("ignoring --base because --all was specified\n"))
1348 base = ['null']
1348 base = ['null']
1349 else:
1349 else:
1350 base = scmutil.revrange(repo, opts.get('base'))
1350 base = scmutil.revrange(repo, opts.get('base'))
1351 # TODO: get desired bundlecaps from command line.
1351 # TODO: get desired bundlecaps from command line.
1352 bundlecaps = None
1352 bundlecaps = None
1353 if base:
1353 if base:
1354 if dest:
1354 if dest:
1355 raise error.Abort(_("--base is incompatible with specifying "
1355 raise error.Abort(_("--base is incompatible with specifying "
1356 "a destination"))
1356 "a destination"))
1357 common = [repo.lookup(rev) for rev in base]
1357 common = [repo.lookup(rev) for rev in base]
1358 heads = revs and map(repo.lookup, revs) or revs
1358 heads = revs and map(repo.lookup, revs) or revs
1359 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1359 cg = changegroup.getchangegroup(repo, 'bundle', heads=heads,
1360 common=common, bundlecaps=bundlecaps,
1360 common=common, bundlecaps=bundlecaps,
1361 version=cgversion)
1361 version=cgversion)
1362 outgoing = None
1362 outgoing = None
1363 else:
1363 else:
1364 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1364 dest = ui.expandpath(dest or 'default-push', dest or 'default')
1365 dest, branches = hg.parseurl(dest, opts.get('branch'))
1365 dest, branches = hg.parseurl(dest, opts.get('branch'))
1366 other = hg.peer(repo, opts, dest)
1366 other = hg.peer(repo, opts, dest)
1367 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1367 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
1368 heads = revs and map(repo.lookup, revs) or revs
1368 heads = revs and map(repo.lookup, revs) or revs
1369 outgoing = discovery.findcommonoutgoing(repo, other,
1369 outgoing = discovery.findcommonoutgoing(repo, other,
1370 onlyheads=heads,
1370 onlyheads=heads,
1371 force=opts.get('force'),
1371 force=opts.get('force'),
1372 portable=True)
1372 portable=True)
1373 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1373 cg = changegroup.getlocalchangegroup(repo, 'bundle', outgoing,
1374 bundlecaps, version=cgversion)
1374 bundlecaps, version=cgversion)
1375 if not cg:
1375 if not cg:
1376 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1376 scmutil.nochangesfound(ui, repo, outgoing and outgoing.excluded)
1377 return 1
1377 return 1
1378
1378
1379 if cgversion == '01': #bundle1
1379 if cgversion == '01': #bundle1
1380 if bcompression is None:
1380 if bcompression is None:
1381 bcompression = 'UN'
1381 bcompression = 'UN'
1382 bversion = 'HG10' + bcompression
1382 bversion = 'HG10' + bcompression
1383 bcompression = None
1383 bcompression = None
1384 else:
1384 else:
1385 assert cgversion == '02'
1385 assert cgversion == '02'
1386 bversion = 'HG20'
1386 bversion = 'HG20'
1387
1387
1388
1388
1389 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1389 changegroup.writebundle(ui, cg, fname, bversion, compression=bcompression)
1390
1390
1391 @command('cat',
1391 @command('cat',
1392 [('o', 'output', '',
1392 [('o', 'output', '',
1393 _('print output to file with formatted name'), _('FORMAT')),
1393 _('print output to file with formatted name'), _('FORMAT')),
1394 ('r', 'rev', '', _('print the given revision'), _('REV')),
1394 ('r', 'rev', '', _('print the given revision'), _('REV')),
1395 ('', 'decode', None, _('apply any matching decode filter')),
1395 ('', 'decode', None, _('apply any matching decode filter')),
1396 ] + walkopts,
1396 ] + walkopts,
1397 _('[OPTION]... FILE...'),
1397 _('[OPTION]... FILE...'),
1398 inferrepo=True)
1398 inferrepo=True)
1399 def cat(ui, repo, file1, *pats, **opts):
1399 def cat(ui, repo, file1, *pats, **opts):
1400 """output the current or given revision of files
1400 """output the current or given revision of files
1401
1401
1402 Print the specified files as they were at the given revision. If
1402 Print the specified files as they were at the given revision. If
1403 no revision is given, the parent of the working directory is used.
1403 no revision is given, the parent of the working directory is used.
1404
1404
1405 Output may be to a file, in which case the name of the file is
1405 Output may be to a file, in which case the name of the file is
1406 given using a format string. The formatting rules as follows:
1406 given using a format string. The formatting rules as follows:
1407
1407
1408 :``%%``: literal "%" character
1408 :``%%``: literal "%" character
1409 :``%s``: basename of file being printed
1409 :``%s``: basename of file being printed
1410 :``%d``: dirname of file being printed, or '.' if in repository root
1410 :``%d``: dirname of file being printed, or '.' if in repository root
1411 :``%p``: root-relative path name of file being printed
1411 :``%p``: root-relative path name of file being printed
1412 :``%H``: changeset hash (40 hexadecimal digits)
1412 :``%H``: changeset hash (40 hexadecimal digits)
1413 :``%R``: changeset revision number
1413 :``%R``: changeset revision number
1414 :``%h``: short-form changeset hash (12 hexadecimal digits)
1414 :``%h``: short-form changeset hash (12 hexadecimal digits)
1415 :``%r``: zero-padded changeset revision number
1415 :``%r``: zero-padded changeset revision number
1416 :``%b``: basename of the exporting repository
1416 :``%b``: basename of the exporting repository
1417
1417
1418 Returns 0 on success.
1418 Returns 0 on success.
1419 """
1419 """
1420 ctx = scmutil.revsingle(repo, opts.get('rev'))
1420 ctx = scmutil.revsingle(repo, opts.get('rev'))
1421 m = scmutil.match(ctx, (file1,) + pats, opts)
1421 m = scmutil.match(ctx, (file1,) + pats, opts)
1422
1422
1423 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1423 return cmdutil.cat(ui, repo, ctx, m, '', **opts)
1424
1424
1425 @command('^clone',
1425 @command('^clone',
1426 [('U', 'noupdate', None, _('the clone will include an empty working '
1426 [('U', 'noupdate', None, _('the clone will include an empty working '
1427 'directory (only a repository)')),
1427 'directory (only a repository)')),
1428 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1428 ('u', 'updaterev', '', _('revision, tag, or branch to check out'),
1429 _('REV')),
1429 _('REV')),
1430 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1430 ('r', 'rev', [], _('include the specified changeset'), _('REV')),
1431 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1431 ('b', 'branch', [], _('clone only the specified branch'), _('BRANCH')),
1432 ('', 'pull', None, _('use pull protocol to copy metadata')),
1432 ('', 'pull', None, _('use pull protocol to copy metadata')),
1433 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1433 ('', 'uncompressed', None, _('use uncompressed transfer (fast over LAN)')),
1434 ] + remoteopts,
1434 ] + remoteopts,
1435 _('[OPTION]... SOURCE [DEST]'),
1435 _('[OPTION]... SOURCE [DEST]'),
1436 norepo=True)
1436 norepo=True)
1437 def clone(ui, source, dest=None, **opts):
1437 def clone(ui, source, dest=None, **opts):
1438 """make a copy of an existing repository
1438 """make a copy of an existing repository
1439
1439
1440 Create a copy of an existing repository in a new directory.
1440 Create a copy of an existing repository in a new directory.
1441
1441
1442 If no destination directory name is specified, it defaults to the
1442 If no destination directory name is specified, it defaults to the
1443 basename of the source.
1443 basename of the source.
1444
1444
1445 The location of the source is added to the new repository's
1445 The location of the source is added to the new repository's
1446 ``.hg/hgrc`` file, as the default to be used for future pulls.
1446 ``.hg/hgrc`` file, as the default to be used for future pulls.
1447
1447
1448 Only local paths and ``ssh://`` URLs are supported as
1448 Only local paths and ``ssh://`` URLs are supported as
1449 destinations. For ``ssh://`` destinations, no working directory or
1449 destinations. For ``ssh://`` destinations, no working directory or
1450 ``.hg/hgrc`` will be created on the remote side.
1450 ``.hg/hgrc`` will be created on the remote side.
1451
1451
1452 If the source repository has a bookmark called '@' set, that
1452 If the source repository has a bookmark called '@' set, that
1453 revision will be checked out in the new repository by default.
1453 revision will be checked out in the new repository by default.
1454
1454
1455 To check out a particular version, use -u/--update, or
1455 To check out a particular version, use -u/--update, or
1456 -U/--noupdate to create a clone with no working directory.
1456 -U/--noupdate to create a clone with no working directory.
1457
1457
1458 To pull only a subset of changesets, specify one or more revisions
1458 To pull only a subset of changesets, specify one or more revisions
1459 identifiers with -r/--rev or branches with -b/--branch. The
1459 identifiers with -r/--rev or branches with -b/--branch. The
1460 resulting clone will contain only the specified changesets and
1460 resulting clone will contain only the specified changesets and
1461 their ancestors. These options (or 'clone src#rev dest') imply
1461 their ancestors. These options (or 'clone src#rev dest') imply
1462 --pull, even for local source repositories.
1462 --pull, even for local source repositories.
1463
1463
1464 .. note::
1464 .. note::
1465
1465
1466 Specifying a tag will include the tagged changeset but not the
1466 Specifying a tag will include the tagged changeset but not the
1467 changeset containing the tag.
1467 changeset containing the tag.
1468
1468
1469 .. container:: verbose
1469 .. container:: verbose
1470
1470
1471 For efficiency, hardlinks are used for cloning whenever the
1471 For efficiency, hardlinks are used for cloning whenever the
1472 source and destination are on the same filesystem (note this
1472 source and destination are on the same filesystem (note this
1473 applies only to the repository data, not to the working
1473 applies only to the repository data, not to the working
1474 directory). Some filesystems, such as AFS, implement hardlinking
1474 directory). Some filesystems, such as AFS, implement hardlinking
1475 incorrectly, but do not report errors. In these cases, use the
1475 incorrectly, but do not report errors. In these cases, use the
1476 --pull option to avoid hardlinking.
1476 --pull option to avoid hardlinking.
1477
1477
1478 In some cases, you can clone repositories and the working
1478 In some cases, you can clone repositories and the working
1479 directory using full hardlinks with ::
1479 directory using full hardlinks with ::
1480
1480
1481 $ cp -al REPO REPOCLONE
1481 $ cp -al REPO REPOCLONE
1482
1482
1483 This is the fastest way to clone, but it is not always safe. The
1483 This is the fastest way to clone, but it is not always safe. The
1484 operation is not atomic (making sure REPO is not modified during
1484 operation is not atomic (making sure REPO is not modified during
1485 the operation is up to you) and you have to make sure your
1485 the operation is up to you) and you have to make sure your
1486 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1486 editor breaks hardlinks (Emacs and most Linux Kernel tools do
1487 so). Also, this is not compatible with certain extensions that
1487 so). Also, this is not compatible with certain extensions that
1488 place their metadata under the .hg directory, such as mq.
1488 place their metadata under the .hg directory, such as mq.
1489
1489
1490 Mercurial will update the working directory to the first applicable
1490 Mercurial will update the working directory to the first applicable
1491 revision from this list:
1491 revision from this list:
1492
1492
1493 a) null if -U or the source repository has no changesets
1493 a) null if -U or the source repository has no changesets
1494 b) if -u . and the source repository is local, the first parent of
1494 b) if -u . and the source repository is local, the first parent of
1495 the source repository's working directory
1495 the source repository's working directory
1496 c) the changeset specified with -u (if a branch name, this means the
1496 c) the changeset specified with -u (if a branch name, this means the
1497 latest head of that branch)
1497 latest head of that branch)
1498 d) the changeset specified with -r
1498 d) the changeset specified with -r
1499 e) the tipmost head specified with -b
1499 e) the tipmost head specified with -b
1500 f) the tipmost head specified with the url#branch source syntax
1500 f) the tipmost head specified with the url#branch source syntax
1501 g) the revision marked with the '@' bookmark, if present
1501 g) the revision marked with the '@' bookmark, if present
1502 h) the tipmost head of the default branch
1502 h) the tipmost head of the default branch
1503 i) tip
1503 i) tip
1504
1504
1505 Examples:
1505 Examples:
1506
1506
1507 - clone a remote repository to a new directory named hg/::
1507 - clone a remote repository to a new directory named hg/::
1508
1508
1509 hg clone http://selenic.com/hg
1509 hg clone http://selenic.com/hg
1510
1510
1511 - create a lightweight local clone::
1511 - create a lightweight local clone::
1512
1512
1513 hg clone project/ project-feature/
1513 hg clone project/ project-feature/
1514
1514
1515 - clone from an absolute path on an ssh server (note double-slash)::
1515 - clone from an absolute path on an ssh server (note double-slash)::
1516
1516
1517 hg clone ssh://user@server//home/projects/alpha/
1517 hg clone ssh://user@server//home/projects/alpha/
1518
1518
1519 - do a high-speed clone over a LAN while checking out a
1519 - do a high-speed clone over a LAN while checking out a
1520 specified version::
1520 specified version::
1521
1521
1522 hg clone --uncompressed http://server/repo -u 1.5
1522 hg clone --uncompressed http://server/repo -u 1.5
1523
1523
1524 - create a repository without changesets after a particular revision::
1524 - create a repository without changesets after a particular revision::
1525
1525
1526 hg clone -r 04e544 experimental/ good/
1526 hg clone -r 04e544 experimental/ good/
1527
1527
1528 - clone (and track) a particular named branch::
1528 - clone (and track) a particular named branch::
1529
1529
1530 hg clone http://selenic.com/hg#stable
1530 hg clone http://selenic.com/hg#stable
1531
1531
1532 See :hg:`help urls` for details on specifying URLs.
1532 See :hg:`help urls` for details on specifying URLs.
1533
1533
1534 Returns 0 on success.
1534 Returns 0 on success.
1535 """
1535 """
1536 if opts.get('noupdate') and opts.get('updaterev'):
1536 if opts.get('noupdate') and opts.get('updaterev'):
1537 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1537 raise error.Abort(_("cannot specify both --noupdate and --updaterev"))
1538
1538
1539 r = hg.clone(ui, opts, source, dest,
1539 r = hg.clone(ui, opts, source, dest,
1540 pull=opts.get('pull'),
1540 pull=opts.get('pull'),
1541 stream=opts.get('uncompressed'),
1541 stream=opts.get('uncompressed'),
1542 rev=opts.get('rev'),
1542 rev=opts.get('rev'),
1543 update=opts.get('updaterev') or not opts.get('noupdate'),
1543 update=opts.get('updaterev') or not opts.get('noupdate'),
1544 branch=opts.get('branch'),
1544 branch=opts.get('branch'),
1545 shareopts=opts.get('shareopts'))
1545 shareopts=opts.get('shareopts'))
1546
1546
1547 return r is None
1547 return r is None
1548
1548
1549 @command('^commit|ci',
1549 @command('^commit|ci',
1550 [('A', 'addremove', None,
1550 [('A', 'addremove', None,
1551 _('mark new/missing files as added/removed before committing')),
1551 _('mark new/missing files as added/removed before committing')),
1552 ('', 'close-branch', None,
1552 ('', 'close-branch', None,
1553 _('mark a branch head as closed')),
1553 _('mark a branch head as closed')),
1554 ('', 'amend', None, _('amend the parent of the working directory')),
1554 ('', 'amend', None, _('amend the parent of the working directory')),
1555 ('s', 'secret', None, _('use the secret phase for committing')),
1555 ('s', 'secret', None, _('use the secret phase for committing')),
1556 ('e', 'edit', None, _('invoke editor on commit messages')),
1556 ('e', 'edit', None, _('invoke editor on commit messages')),
1557 ('i', 'interactive', None, _('use interactive mode')),
1557 ('i', 'interactive', None, _('use interactive mode')),
1558 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1558 ] + walkopts + commitopts + commitopts2 + subrepoopts,
1559 _('[OPTION]... [FILE]...'),
1559 _('[OPTION]... [FILE]...'),
1560 inferrepo=True)
1560 inferrepo=True)
1561 def commit(ui, repo, *pats, **opts):
1561 def commit(ui, repo, *pats, **opts):
1562 """commit the specified files or all outstanding changes
1562 """commit the specified files or all outstanding changes
1563
1563
1564 Commit changes to the given files into the repository. Unlike a
1564 Commit changes to the given files into the repository. Unlike a
1565 centralized SCM, this operation is a local operation. See
1565 centralized SCM, this operation is a local operation. See
1566 :hg:`push` for a way to actively distribute your changes.
1566 :hg:`push` for a way to actively distribute your changes.
1567
1567
1568 If a list of files is omitted, all changes reported by :hg:`status`
1568 If a list of files is omitted, all changes reported by :hg:`status`
1569 will be committed.
1569 will be committed.
1570
1570
1571 If you are committing the result of a merge, do not provide any
1571 If you are committing the result of a merge, do not provide any
1572 filenames or -I/-X filters.
1572 filenames or -I/-X filters.
1573
1573
1574 If no commit message is specified, Mercurial starts your
1574 If no commit message is specified, Mercurial starts your
1575 configured editor where you can enter a message. In case your
1575 configured editor where you can enter a message. In case your
1576 commit fails, you will find a backup of your message in
1576 commit fails, you will find a backup of your message in
1577 ``.hg/last-message.txt``.
1577 ``.hg/last-message.txt``.
1578
1578
1579 The --close-branch flag can be used to mark the current branch
1579 The --close-branch flag can be used to mark the current branch
1580 head closed. When all heads of a branch are closed, the branch
1580 head closed. When all heads of a branch are closed, the branch
1581 will be considered closed and no longer listed.
1581 will be considered closed and no longer listed.
1582
1582
1583 The --amend flag can be used to amend the parent of the
1583 The --amend flag can be used to amend the parent of the
1584 working directory with a new commit that contains the changes
1584 working directory with a new commit that contains the changes
1585 in the parent in addition to those currently reported by :hg:`status`,
1585 in the parent in addition to those currently reported by :hg:`status`,
1586 if there are any. The old commit is stored in a backup bundle in
1586 if there are any. The old commit is stored in a backup bundle in
1587 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1587 ``.hg/strip-backup`` (see :hg:`help bundle` and :hg:`help unbundle`
1588 on how to restore it).
1588 on how to restore it).
1589
1589
1590 Message, user and date are taken from the amended commit unless
1590 Message, user and date are taken from the amended commit unless
1591 specified. When a message isn't specified on the command line,
1591 specified. When a message isn't specified on the command line,
1592 the editor will open with the message of the amended commit.
1592 the editor will open with the message of the amended commit.
1593
1593
1594 It is not possible to amend public changesets (see :hg:`help phases`)
1594 It is not possible to amend public changesets (see :hg:`help phases`)
1595 or changesets that have children.
1595 or changesets that have children.
1596
1596
1597 See :hg:`help dates` for a list of formats valid for -d/--date.
1597 See :hg:`help dates` for a list of formats valid for -d/--date.
1598
1598
1599 Returns 0 on success, 1 if nothing changed.
1599 Returns 0 on success, 1 if nothing changed.
1600
1600
1601 .. container:: verbose
1601 .. container:: verbose
1602
1602
1603 Examples:
1603 Examples:
1604
1604
1605 - commit all files ending in .py::
1605 - commit all files ending in .py::
1606
1606
1607 hg commit --include "set:**.py"
1607 hg commit --include "set:**.py"
1608
1608
1609 - commit all non-binary files::
1609 - commit all non-binary files::
1610
1610
1611 hg commit --exclude "set:binary()"
1611 hg commit --exclude "set:binary()"
1612
1612
1613 - amend the current commit and set the date to now::
1613 - amend the current commit and set the date to now::
1614
1614
1615 hg commit --amend --date now
1615 hg commit --amend --date now
1616 """
1616 """
1617 wlock = lock = None
1617 wlock = lock = None
1618 try:
1618 try:
1619 wlock = repo.wlock()
1619 wlock = repo.wlock()
1620 lock = repo.lock()
1620 lock = repo.lock()
1621 return _docommit(ui, repo, *pats, **opts)
1621 return _docommit(ui, repo, *pats, **opts)
1622 finally:
1622 finally:
1623 release(lock, wlock)
1623 release(lock, wlock)
1624
1624
1625 def _docommit(ui, repo, *pats, **opts):
1625 def _docommit(ui, repo, *pats, **opts):
1626 if opts.get('interactive'):
1626 if opts.get('interactive'):
1627 opts.pop('interactive')
1627 opts.pop('interactive')
1628 cmdutil.dorecord(ui, repo, commit, None, False,
1628 cmdutil.dorecord(ui, repo, commit, None, False,
1629 cmdutil.recordfilter, *pats, **opts)
1629 cmdutil.recordfilter, *pats, **opts)
1630 return
1630 return
1631
1631
1632 if opts.get('subrepos'):
1632 if opts.get('subrepos'):
1633 if opts.get('amend'):
1633 if opts.get('amend'):
1634 raise error.Abort(_('cannot amend with --subrepos'))
1634 raise error.Abort(_('cannot amend with --subrepos'))
1635 # Let --subrepos on the command line override config setting.
1635 # Let --subrepos on the command line override config setting.
1636 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1636 ui.setconfig('ui', 'commitsubrepos', True, 'commit')
1637
1637
1638 cmdutil.checkunfinished(repo, commit=True)
1638 cmdutil.checkunfinished(repo, commit=True)
1639
1639
1640 branch = repo[None].branch()
1640 branch = repo[None].branch()
1641 bheads = repo.branchheads(branch)
1641 bheads = repo.branchheads(branch)
1642
1642
1643 extra = {}
1643 extra = {}
1644 if opts.get('close_branch'):
1644 if opts.get('close_branch'):
1645 extra['close'] = 1
1645 extra['close'] = 1
1646
1646
1647 if not bheads:
1647 if not bheads:
1648 raise error.Abort(_('can only close branch heads'))
1648 raise error.Abort(_('can only close branch heads'))
1649 elif opts.get('amend'):
1649 elif opts.get('amend'):
1650 if repo[None].parents()[0].p1().branch() != branch and \
1650 if repo[None].parents()[0].p1().branch() != branch and \
1651 repo[None].parents()[0].p2().branch() != branch:
1651 repo[None].parents()[0].p2().branch() != branch:
1652 raise error.Abort(_('can only close branch heads'))
1652 raise error.Abort(_('can only close branch heads'))
1653
1653
1654 if opts.get('amend'):
1654 if opts.get('amend'):
1655 if ui.configbool('ui', 'commitsubrepos'):
1655 if ui.configbool('ui', 'commitsubrepos'):
1656 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1656 raise error.Abort(_('cannot amend with ui.commitsubrepos enabled'))
1657
1657
1658 old = repo['.']
1658 old = repo['.']
1659 if not old.mutable():
1659 if not old.mutable():
1660 raise error.Abort(_('cannot amend public changesets'))
1660 raise error.Abort(_('cannot amend public changesets'))
1661 if len(repo[None].parents()) > 1:
1661 if len(repo[None].parents()) > 1:
1662 raise error.Abort(_('cannot amend while merging'))
1662 raise error.Abort(_('cannot amend while merging'))
1663 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1663 allowunstable = obsolete.isenabled(repo, obsolete.allowunstableopt)
1664 if not allowunstable and old.children():
1664 if not allowunstable and old.children():
1665 raise error.Abort(_('cannot amend changeset with children'))
1665 raise error.Abort(_('cannot amend changeset with children'))
1666
1666
1667 newextra = extra.copy()
1667 newextra = extra.copy()
1668 newextra['branch'] = branch
1668 newextra['branch'] = branch
1669 extra = newextra
1669 extra = newextra
1670 # commitfunc is used only for temporary amend commit by cmdutil.amend
1670 # commitfunc is used only for temporary amend commit by cmdutil.amend
1671 def commitfunc(ui, repo, message, match, opts):
1671 def commitfunc(ui, repo, message, match, opts):
1672 return repo.commit(message,
1672 return repo.commit(message,
1673 opts.get('user') or old.user(),
1673 opts.get('user') or old.user(),
1674 opts.get('date') or old.date(),
1674 opts.get('date') or old.date(),
1675 match,
1675 match,
1676 extra=extra)
1676 extra=extra)
1677
1677
1678 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1678 node = cmdutil.amend(ui, repo, commitfunc, old, extra, pats, opts)
1679 if node == old.node():
1679 if node == old.node():
1680 ui.status(_("nothing changed\n"))
1680 ui.status(_("nothing changed\n"))
1681 return 1
1681 return 1
1682 else:
1682 else:
1683 def commitfunc(ui, repo, message, match, opts):
1683 def commitfunc(ui, repo, message, match, opts):
1684 backup = ui.backupconfig('phases', 'new-commit')
1684 backup = ui.backupconfig('phases', 'new-commit')
1685 baseui = repo.baseui
1685 baseui = repo.baseui
1686 basebackup = baseui.backupconfig('phases', 'new-commit')
1686 basebackup = baseui.backupconfig('phases', 'new-commit')
1687 try:
1687 try:
1688 if opts.get('secret'):
1688 if opts.get('secret'):
1689 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1689 ui.setconfig('phases', 'new-commit', 'secret', 'commit')
1690 # Propagate to subrepos
1690 # Propagate to subrepos
1691 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1691 baseui.setconfig('phases', 'new-commit', 'secret', 'commit')
1692
1692
1693 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1693 editform = cmdutil.mergeeditform(repo[None], 'commit.normal')
1694 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1694 editor = cmdutil.getcommiteditor(editform=editform, **opts)
1695 return repo.commit(message, opts.get('user'), opts.get('date'),
1695 return repo.commit(message, opts.get('user'), opts.get('date'),
1696 match,
1696 match,
1697 editor=editor,
1697 editor=editor,
1698 extra=extra)
1698 extra=extra)
1699 finally:
1699 finally:
1700 ui.restoreconfig(backup)
1700 ui.restoreconfig(backup)
1701 repo.baseui.restoreconfig(basebackup)
1701 repo.baseui.restoreconfig(basebackup)
1702
1702
1703
1703
1704 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1704 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
1705
1705
1706 if not node:
1706 if not node:
1707 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1707 stat = repo.status(match=scmutil.match(repo[None], pats, opts))
1708 if stat[3]:
1708 if stat[3]:
1709 ui.status(_("nothing changed (%d missing files, see "
1709 ui.status(_("nothing changed (%d missing files, see "
1710 "'hg status')\n") % len(stat[3]))
1710 "'hg status')\n") % len(stat[3]))
1711 else:
1711 else:
1712 ui.status(_("nothing changed\n"))
1712 ui.status(_("nothing changed\n"))
1713 return 1
1713 return 1
1714
1714
1715 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1715 cmdutil.commitstatus(repo, node, branch, bheads, opts)
1716
1716
1717 @command('config|showconfig|debugconfig',
1717 @command('config|showconfig|debugconfig',
1718 [('u', 'untrusted', None, _('show untrusted configuration options')),
1718 [('u', 'untrusted', None, _('show untrusted configuration options')),
1719 ('e', 'edit', None, _('edit user config')),
1719 ('e', 'edit', None, _('edit user config')),
1720 ('l', 'local', None, _('edit repository config')),
1720 ('l', 'local', None, _('edit repository config')),
1721 ('g', 'global', None, _('edit global config'))],
1721 ('g', 'global', None, _('edit global config'))],
1722 _('[-u] [NAME]...'),
1722 _('[-u] [NAME]...'),
1723 optionalrepo=True)
1723 optionalrepo=True)
1724 def config(ui, repo, *values, **opts):
1724 def config(ui, repo, *values, **opts):
1725 """show combined config settings from all hgrc files
1725 """show combined config settings from all hgrc files
1726
1726
1727 With no arguments, print names and values of all config items.
1727 With no arguments, print names and values of all config items.
1728
1728
1729 With one argument of the form section.name, print just the value
1729 With one argument of the form section.name, print just the value
1730 of that config item.
1730 of that config item.
1731
1731
1732 With multiple arguments, print names and values of all config
1732 With multiple arguments, print names and values of all config
1733 items with matching section names.
1733 items with matching section names.
1734
1734
1735 With --edit, start an editor on the user-level config file. With
1735 With --edit, start an editor on the user-level config file. With
1736 --global, edit the system-wide config file. With --local, edit the
1736 --global, edit the system-wide config file. With --local, edit the
1737 repository-level config file.
1737 repository-level config file.
1738
1738
1739 With --debug, the source (filename and line number) is printed
1739 With --debug, the source (filename and line number) is printed
1740 for each config item.
1740 for each config item.
1741
1741
1742 See :hg:`help config` for more information about config files.
1742 See :hg:`help config` for more information about config files.
1743
1743
1744 Returns 0 on success, 1 if NAME does not exist.
1744 Returns 0 on success, 1 if NAME does not exist.
1745
1745
1746 """
1746 """
1747
1747
1748 if opts.get('edit') or opts.get('local') or opts.get('global'):
1748 if opts.get('edit') or opts.get('local') or opts.get('global'):
1749 if opts.get('local') and opts.get('global'):
1749 if opts.get('local') and opts.get('global'):
1750 raise error.Abort(_("can't use --local and --global together"))
1750 raise error.Abort(_("can't use --local and --global together"))
1751
1751
1752 if opts.get('local'):
1752 if opts.get('local'):
1753 if not repo:
1753 if not repo:
1754 raise error.Abort(_("can't use --local outside a repository"))
1754 raise error.Abort(_("can't use --local outside a repository"))
1755 paths = [repo.join('hgrc')]
1755 paths = [repo.join('hgrc')]
1756 elif opts.get('global'):
1756 elif opts.get('global'):
1757 paths = scmutil.systemrcpath()
1757 paths = scmutil.systemrcpath()
1758 else:
1758 else:
1759 paths = scmutil.userrcpath()
1759 paths = scmutil.userrcpath()
1760
1760
1761 for f in paths:
1761 for f in paths:
1762 if os.path.exists(f):
1762 if os.path.exists(f):
1763 break
1763 break
1764 else:
1764 else:
1765 if opts.get('global'):
1765 if opts.get('global'):
1766 samplehgrc = uimod.samplehgrcs['global']
1766 samplehgrc = uimod.samplehgrcs['global']
1767 elif opts.get('local'):
1767 elif opts.get('local'):
1768 samplehgrc = uimod.samplehgrcs['local']
1768 samplehgrc = uimod.samplehgrcs['local']
1769 else:
1769 else:
1770 samplehgrc = uimod.samplehgrcs['user']
1770 samplehgrc = uimod.samplehgrcs['user']
1771
1771
1772 f = paths[0]
1772 f = paths[0]
1773 fp = open(f, "w")
1773 fp = open(f, "w")
1774 fp.write(samplehgrc)
1774 fp.write(samplehgrc)
1775 fp.close()
1775 fp.close()
1776
1776
1777 editor = ui.geteditor()
1777 editor = ui.geteditor()
1778 ui.system("%s \"%s\"" % (editor, f),
1778 ui.system("%s \"%s\"" % (editor, f),
1779 onerr=error.Abort, errprefix=_("edit failed"))
1779 onerr=error.Abort, errprefix=_("edit failed"))
1780 return
1780 return
1781
1781
1782 for f in scmutil.rcpath():
1782 for f in scmutil.rcpath():
1783 ui.debug('read config from: %s\n' % f)
1783 ui.debug('read config from: %s\n' % f)
1784 untrusted = bool(opts.get('untrusted'))
1784 untrusted = bool(opts.get('untrusted'))
1785 if values:
1785 if values:
1786 sections = [v for v in values if '.' not in v]
1786 sections = [v for v in values if '.' not in v]
1787 items = [v for v in values if '.' in v]
1787 items = [v for v in values if '.' in v]
1788 if len(items) > 1 or items and sections:
1788 if len(items) > 1 or items and sections:
1789 raise error.Abort(_('only one config item permitted'))
1789 raise error.Abort(_('only one config item permitted'))
1790 matched = False
1790 matched = False
1791 for section, name, value in ui.walkconfig(untrusted=untrusted):
1791 for section, name, value in ui.walkconfig(untrusted=untrusted):
1792 value = str(value).replace('\n', '\\n')
1792 value = str(value).replace('\n', '\\n')
1793 sectname = section + '.' + name
1793 sectname = section + '.' + name
1794 if values:
1794 if values:
1795 for v in values:
1795 for v in values:
1796 if v == section:
1796 if v == section:
1797 ui.debug('%s: ' %
1797 ui.debug('%s: ' %
1798 ui.configsource(section, name, untrusted))
1798 ui.configsource(section, name, untrusted))
1799 ui.write('%s=%s\n' % (sectname, value))
1799 ui.write('%s=%s\n' % (sectname, value))
1800 matched = True
1800 matched = True
1801 elif v == sectname:
1801 elif v == sectname:
1802 ui.debug('%s: ' %
1802 ui.debug('%s: ' %
1803 ui.configsource(section, name, untrusted))
1803 ui.configsource(section, name, untrusted))
1804 ui.write(value, '\n')
1804 ui.write(value, '\n')
1805 matched = True
1805 matched = True
1806 else:
1806 else:
1807 ui.debug('%s: ' %
1807 ui.debug('%s: ' %
1808 ui.configsource(section, name, untrusted))
1808 ui.configsource(section, name, untrusted))
1809 ui.write('%s=%s\n' % (sectname, value))
1809 ui.write('%s=%s\n' % (sectname, value))
1810 matched = True
1810 matched = True
1811 if matched:
1811 if matched:
1812 return 0
1812 return 0
1813 return 1
1813 return 1
1814
1814
1815 @command('copy|cp',
1815 @command('copy|cp',
1816 [('A', 'after', None, _('record a copy that has already occurred')),
1816 [('A', 'after', None, _('record a copy that has already occurred')),
1817 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1817 ('f', 'force', None, _('forcibly copy over an existing managed file')),
1818 ] + walkopts + dryrunopts,
1818 ] + walkopts + dryrunopts,
1819 _('[OPTION]... [SOURCE]... DEST'))
1819 _('[OPTION]... [SOURCE]... DEST'))
1820 def copy(ui, repo, *pats, **opts):
1820 def copy(ui, repo, *pats, **opts):
1821 """mark files as copied for the next commit
1821 """mark files as copied for the next commit
1822
1822
1823 Mark dest as having copies of source files. If dest is a
1823 Mark dest as having copies of source files. If dest is a
1824 directory, copies are put in that directory. If dest is a file,
1824 directory, copies are put in that directory. If dest is a file,
1825 the source must be a single file.
1825 the source must be a single file.
1826
1826
1827 By default, this command copies the contents of files as they
1827 By default, this command copies the contents of files as they
1828 exist in the working directory. If invoked with -A/--after, the
1828 exist in the working directory. If invoked with -A/--after, the
1829 operation is recorded, but no copying is performed.
1829 operation is recorded, but no copying is performed.
1830
1830
1831 This command takes effect with the next commit. To undo a copy
1831 This command takes effect with the next commit. To undo a copy
1832 before that, see :hg:`revert`.
1832 before that, see :hg:`revert`.
1833
1833
1834 Returns 0 on success, 1 if errors are encountered.
1834 Returns 0 on success, 1 if errors are encountered.
1835 """
1835 """
1836 with repo.wlock(False):
1836 with repo.wlock(False):
1837 return cmdutil.copy(ui, repo, pats, opts)
1837 return cmdutil.copy(ui, repo, pats, opts)
1838
1838
1839 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1839 @command('debugancestor', [], _('[INDEX] REV1 REV2'), optionalrepo=True)
1840 def debugancestor(ui, repo, *args):
1840 def debugancestor(ui, repo, *args):
1841 """find the ancestor revision of two revisions in a given index"""
1841 """find the ancestor revision of two revisions in a given index"""
1842 if len(args) == 3:
1842 if len(args) == 3:
1843 index, rev1, rev2 = args
1843 index, rev1, rev2 = args
1844 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1844 r = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), index)
1845 lookup = r.lookup
1845 lookup = r.lookup
1846 elif len(args) == 2:
1846 elif len(args) == 2:
1847 if not repo:
1847 if not repo:
1848 raise error.Abort(_("there is no Mercurial repository here "
1848 raise error.Abort(_("there is no Mercurial repository here "
1849 "(.hg not found)"))
1849 "(.hg not found)"))
1850 rev1, rev2 = args
1850 rev1, rev2 = args
1851 r = repo.changelog
1851 r = repo.changelog
1852 lookup = repo.lookup
1852 lookup = repo.lookup
1853 else:
1853 else:
1854 raise error.Abort(_('either two or three arguments required'))
1854 raise error.Abort(_('either two or three arguments required'))
1855 a = r.ancestor(lookup(rev1), lookup(rev2))
1855 a = r.ancestor(lookup(rev1), lookup(rev2))
1856 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1856 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1857
1857
1858 @command('debugbuilddag',
1858 @command('debugbuilddag',
1859 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1859 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
1860 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1860 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
1861 ('n', 'new-file', None, _('add new file at each rev'))],
1861 ('n', 'new-file', None, _('add new file at each rev'))],
1862 _('[OPTION]... [TEXT]'))
1862 _('[OPTION]... [TEXT]'))
1863 def debugbuilddag(ui, repo, text=None,
1863 def debugbuilddag(ui, repo, text=None,
1864 mergeable_file=False,
1864 mergeable_file=False,
1865 overwritten_file=False,
1865 overwritten_file=False,
1866 new_file=False):
1866 new_file=False):
1867 """builds a repo with a given DAG from scratch in the current empty repo
1867 """builds a repo with a given DAG from scratch in the current empty repo
1868
1868
1869 The description of the DAG is read from stdin if not given on the
1869 The description of the DAG is read from stdin if not given on the
1870 command line.
1870 command line.
1871
1871
1872 Elements:
1872 Elements:
1873
1873
1874 - "+n" is a linear run of n nodes based on the current default parent
1874 - "+n" is a linear run of n nodes based on the current default parent
1875 - "." is a single node based on the current default parent
1875 - "." is a single node based on the current default parent
1876 - "$" resets the default parent to null (implied at the start);
1876 - "$" resets the default parent to null (implied at the start);
1877 otherwise the default parent is always the last node created
1877 otherwise the default parent is always the last node created
1878 - "<p" sets the default parent to the backref p
1878 - "<p" sets the default parent to the backref p
1879 - "*p" is a fork at parent p, which is a backref
1879 - "*p" is a fork at parent p, which is a backref
1880 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1880 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
1881 - "/p2" is a merge of the preceding node and p2
1881 - "/p2" is a merge of the preceding node and p2
1882 - ":tag" defines a local tag for the preceding node
1882 - ":tag" defines a local tag for the preceding node
1883 - "@branch" sets the named branch for subsequent nodes
1883 - "@branch" sets the named branch for subsequent nodes
1884 - "#...\\n" is a comment up to the end of the line
1884 - "#...\\n" is a comment up to the end of the line
1885
1885
1886 Whitespace between the above elements is ignored.
1886 Whitespace between the above elements is ignored.
1887
1887
1888 A backref is either
1888 A backref is either
1889
1889
1890 - a number n, which references the node curr-n, where curr is the current
1890 - a number n, which references the node curr-n, where curr is the current
1891 node, or
1891 node, or
1892 - the name of a local tag you placed earlier using ":tag", or
1892 - the name of a local tag you placed earlier using ":tag", or
1893 - empty to denote the default parent.
1893 - empty to denote the default parent.
1894
1894
1895 All string valued-elements are either strictly alphanumeric, or must
1895 All string valued-elements are either strictly alphanumeric, or must
1896 be enclosed in double quotes ("..."), with "\\" as escape character.
1896 be enclosed in double quotes ("..."), with "\\" as escape character.
1897 """
1897 """
1898
1898
1899 if text is None:
1899 if text is None:
1900 ui.status(_("reading DAG from stdin\n"))
1900 ui.status(_("reading DAG from stdin\n"))
1901 text = ui.fin.read()
1901 text = ui.fin.read()
1902
1902
1903 cl = repo.changelog
1903 cl = repo.changelog
1904 if len(cl) > 0:
1904 if len(cl) > 0:
1905 raise error.Abort(_('repository is not empty'))
1905 raise error.Abort(_('repository is not empty'))
1906
1906
1907 # determine number of revs in DAG
1907 # determine number of revs in DAG
1908 total = 0
1908 total = 0
1909 for type, data in dagparser.parsedag(text):
1909 for type, data in dagparser.parsedag(text):
1910 if type == 'n':
1910 if type == 'n':
1911 total += 1
1911 total += 1
1912
1912
1913 if mergeable_file:
1913 if mergeable_file:
1914 linesperrev = 2
1914 linesperrev = 2
1915 # make a file with k lines per rev
1915 # make a file with k lines per rev
1916 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1916 initialmergedlines = [str(i) for i in xrange(0, total * linesperrev)]
1917 initialmergedlines.append("")
1917 initialmergedlines.append("")
1918
1918
1919 tags = []
1919 tags = []
1920
1920
1921 lock = tr = None
1921 lock = tr = None
1922 try:
1922 try:
1923 lock = repo.lock()
1923 lock = repo.lock()
1924 tr = repo.transaction("builddag")
1924 tr = repo.transaction("builddag")
1925
1925
1926 at = -1
1926 at = -1
1927 atbranch = 'default'
1927 atbranch = 'default'
1928 nodeids = []
1928 nodeids = []
1929 id = 0
1929 id = 0
1930 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1930 ui.progress(_('building'), id, unit=_('revisions'), total=total)
1931 for type, data in dagparser.parsedag(text):
1931 for type, data in dagparser.parsedag(text):
1932 if type == 'n':
1932 if type == 'n':
1933 ui.note(('node %s\n' % str(data)))
1933 ui.note(('node %s\n' % str(data)))
1934 id, ps = data
1934 id, ps = data
1935
1935
1936 files = []
1936 files = []
1937 fctxs = {}
1937 fctxs = {}
1938
1938
1939 p2 = None
1939 p2 = None
1940 if mergeable_file:
1940 if mergeable_file:
1941 fn = "mf"
1941 fn = "mf"
1942 p1 = repo[ps[0]]
1942 p1 = repo[ps[0]]
1943 if len(ps) > 1:
1943 if len(ps) > 1:
1944 p2 = repo[ps[1]]
1944 p2 = repo[ps[1]]
1945 pa = p1.ancestor(p2)
1945 pa = p1.ancestor(p2)
1946 base, local, other = [x[fn].data() for x in (pa, p1,
1946 base, local, other = [x[fn].data() for x in (pa, p1,
1947 p2)]
1947 p2)]
1948 m3 = simplemerge.Merge3Text(base, local, other)
1948 m3 = simplemerge.Merge3Text(base, local, other)
1949 ml = [l.strip() for l in m3.merge_lines()]
1949 ml = [l.strip() for l in m3.merge_lines()]
1950 ml.append("")
1950 ml.append("")
1951 elif at > 0:
1951 elif at > 0:
1952 ml = p1[fn].data().split("\n")
1952 ml = p1[fn].data().split("\n")
1953 else:
1953 else:
1954 ml = initialmergedlines
1954 ml = initialmergedlines
1955 ml[id * linesperrev] += " r%i" % id
1955 ml[id * linesperrev] += " r%i" % id
1956 mergedtext = "\n".join(ml)
1956 mergedtext = "\n".join(ml)
1957 files.append(fn)
1957 files.append(fn)
1958 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1958 fctxs[fn] = context.memfilectx(repo, fn, mergedtext)
1959
1959
1960 if overwritten_file:
1960 if overwritten_file:
1961 fn = "of"
1961 fn = "of"
1962 files.append(fn)
1962 files.append(fn)
1963 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1963 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1964
1964
1965 if new_file:
1965 if new_file:
1966 fn = "nf%i" % id
1966 fn = "nf%i" % id
1967 files.append(fn)
1967 files.append(fn)
1968 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1968 fctxs[fn] = context.memfilectx(repo, fn, "r%i\n" % id)
1969 if len(ps) > 1:
1969 if len(ps) > 1:
1970 if not p2:
1970 if not p2:
1971 p2 = repo[ps[1]]
1971 p2 = repo[ps[1]]
1972 for fn in p2:
1972 for fn in p2:
1973 if fn.startswith("nf"):
1973 if fn.startswith("nf"):
1974 files.append(fn)
1974 files.append(fn)
1975 fctxs[fn] = p2[fn]
1975 fctxs[fn] = p2[fn]
1976
1976
1977 def fctxfn(repo, cx, path):
1977 def fctxfn(repo, cx, path):
1978 return fctxs.get(path)
1978 return fctxs.get(path)
1979
1979
1980 if len(ps) == 0 or ps[0] < 0:
1980 if len(ps) == 0 or ps[0] < 0:
1981 pars = [None, None]
1981 pars = [None, None]
1982 elif len(ps) == 1:
1982 elif len(ps) == 1:
1983 pars = [nodeids[ps[0]], None]
1983 pars = [nodeids[ps[0]], None]
1984 else:
1984 else:
1985 pars = [nodeids[p] for p in ps]
1985 pars = [nodeids[p] for p in ps]
1986 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1986 cx = context.memctx(repo, pars, "r%i" % id, files, fctxfn,
1987 date=(id, 0),
1987 date=(id, 0),
1988 user="debugbuilddag",
1988 user="debugbuilddag",
1989 extra={'branch': atbranch})
1989 extra={'branch': atbranch})
1990 nodeid = repo.commitctx(cx)
1990 nodeid = repo.commitctx(cx)
1991 nodeids.append(nodeid)
1991 nodeids.append(nodeid)
1992 at = id
1992 at = id
1993 elif type == 'l':
1993 elif type == 'l':
1994 id, name = data
1994 id, name = data
1995 ui.note(('tag %s\n' % name))
1995 ui.note(('tag %s\n' % name))
1996 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1996 tags.append("%s %s\n" % (hex(repo.changelog.node(id)), name))
1997 elif type == 'a':
1997 elif type == 'a':
1998 ui.note(('branch %s\n' % data))
1998 ui.note(('branch %s\n' % data))
1999 atbranch = data
1999 atbranch = data
2000 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2000 ui.progress(_('building'), id, unit=_('revisions'), total=total)
2001 tr.close()
2001 tr.close()
2002
2002
2003 if tags:
2003 if tags:
2004 repo.vfs.write("localtags", "".join(tags))
2004 repo.vfs.write("localtags", "".join(tags))
2005 finally:
2005 finally:
2006 ui.progress(_('building'), None)
2006 ui.progress(_('building'), None)
2007 release(tr, lock)
2007 release(tr, lock)
2008
2008
2009 @command('debugbundle',
2009 @command('debugbundle',
2010 [('a', 'all', None, _('show all details'))],
2010 [('a', 'all', None, _('show all details'))],
2011 _('FILE'),
2011 _('FILE'),
2012 norepo=True)
2012 norepo=True)
2013 def debugbundle(ui, bundlepath, all=None, **opts):
2013 def debugbundle(ui, bundlepath, all=None, **opts):
2014 """lists the contents of a bundle"""
2014 """lists the contents of a bundle"""
2015 f = hg.openpath(ui, bundlepath)
2015 f = hg.openpath(ui, bundlepath)
2016 try:
2016 try:
2017 gen = exchange.readbundle(ui, f, bundlepath)
2017 gen = exchange.readbundle(ui, f, bundlepath)
2018 if isinstance(gen, bundle2.unbundle20):
2018 if isinstance(gen, bundle2.unbundle20):
2019 return _debugbundle2(ui, gen, all=all, **opts)
2019 return _debugbundle2(ui, gen, all=all, **opts)
2020 if all:
2020 if all:
2021 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2021 ui.write(("format: id, p1, p2, cset, delta base, len(delta)\n"))
2022
2022
2023 def showchunks(named):
2023 def showchunks(named):
2024 ui.write("\n%s\n" % named)
2024 ui.write("\n%s\n" % named)
2025 chain = None
2025 chain = None
2026 while True:
2026 while True:
2027 chunkdata = gen.deltachunk(chain)
2027 chunkdata = gen.deltachunk(chain)
2028 if not chunkdata:
2028 if not chunkdata:
2029 break
2029 break
2030 node = chunkdata['node']
2030 node = chunkdata['node']
2031 p1 = chunkdata['p1']
2031 p1 = chunkdata['p1']
2032 p2 = chunkdata['p2']
2032 p2 = chunkdata['p2']
2033 cs = chunkdata['cs']
2033 cs = chunkdata['cs']
2034 deltabase = chunkdata['deltabase']
2034 deltabase = chunkdata['deltabase']
2035 delta = chunkdata['delta']
2035 delta = chunkdata['delta']
2036 ui.write("%s %s %s %s %s %s\n" %
2036 ui.write("%s %s %s %s %s %s\n" %
2037 (hex(node), hex(p1), hex(p2),
2037 (hex(node), hex(p1), hex(p2),
2038 hex(cs), hex(deltabase), len(delta)))
2038 hex(cs), hex(deltabase), len(delta)))
2039 chain = node
2039 chain = node
2040
2040
2041 chunkdata = gen.changelogheader()
2041 chunkdata = gen.changelogheader()
2042 showchunks("changelog")
2042 showchunks("changelog")
2043 chunkdata = gen.manifestheader()
2043 chunkdata = gen.manifestheader()
2044 showchunks("manifest")
2044 showchunks("manifest")
2045 while True:
2045 while True:
2046 chunkdata = gen.filelogheader()
2046 chunkdata = gen.filelogheader()
2047 if not chunkdata:
2047 if not chunkdata:
2048 break
2048 break
2049 fname = chunkdata['filename']
2049 fname = chunkdata['filename']
2050 showchunks(fname)
2050 showchunks(fname)
2051 else:
2051 else:
2052 if isinstance(gen, bundle2.unbundle20):
2052 if isinstance(gen, bundle2.unbundle20):
2053 raise error.Abort(_('use debugbundle2 for this file'))
2053 raise error.Abort(_('use debugbundle2 for this file'))
2054 chunkdata = gen.changelogheader()
2054 chunkdata = gen.changelogheader()
2055 chain = None
2055 chain = None
2056 while True:
2056 while True:
2057 chunkdata = gen.deltachunk(chain)
2057 chunkdata = gen.deltachunk(chain)
2058 if not chunkdata:
2058 if not chunkdata:
2059 break
2059 break
2060 node = chunkdata['node']
2060 node = chunkdata['node']
2061 ui.write("%s\n" % hex(node))
2061 ui.write("%s\n" % hex(node))
2062 chain = node
2062 chain = node
2063 finally:
2063 finally:
2064 f.close()
2064 f.close()
2065
2065
2066 def _debugbundle2(ui, gen, **opts):
2066 def _debugbundle2(ui, gen, **opts):
2067 """lists the contents of a bundle2"""
2067 """lists the contents of a bundle2"""
2068 if not isinstance(gen, bundle2.unbundle20):
2068 if not isinstance(gen, bundle2.unbundle20):
2069 raise error.Abort(_('not a bundle2 file'))
2069 raise error.Abort(_('not a bundle2 file'))
2070 ui.write(('Stream params: %s\n' % repr(gen.params)))
2070 ui.write(('Stream params: %s\n' % repr(gen.params)))
2071 for part in gen.iterparts():
2071 for part in gen.iterparts():
2072 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2072 ui.write('%s -- %r\n' % (part.type, repr(part.params)))
2073 if part.type == 'changegroup':
2073 if part.type == 'changegroup':
2074 version = part.params.get('version', '01')
2074 version = part.params.get('version', '01')
2075 cg = changegroup.getunbundler(version, part, 'UN')
2075 cg = changegroup.getunbundler(version, part, 'UN')
2076 chunkdata = cg.changelogheader()
2076 chunkdata = cg.changelogheader()
2077 chain = None
2077 chain = None
2078 while True:
2078 while True:
2079 chunkdata = cg.deltachunk(chain)
2079 chunkdata = cg.deltachunk(chain)
2080 if not chunkdata:
2080 if not chunkdata:
2081 break
2081 break
2082 node = chunkdata['node']
2082 node = chunkdata['node']
2083 ui.write(" %s\n" % hex(node))
2083 ui.write(" %s\n" % hex(node))
2084 chain = node
2084 chain = node
2085
2085
2086 @command('debugcreatestreamclonebundle', [], 'FILE')
2086 @command('debugcreatestreamclonebundle', [], 'FILE')
2087 def debugcreatestreamclonebundle(ui, repo, fname):
2087 def debugcreatestreamclonebundle(ui, repo, fname):
2088 """create a stream clone bundle file
2088 """create a stream clone bundle file
2089
2089
2090 Stream bundles are special bundles that are essentially archives of
2090 Stream bundles are special bundles that are essentially archives of
2091 revlog files. They are commonly used for cloning very quickly.
2091 revlog files. They are commonly used for cloning very quickly.
2092 """
2092 """
2093 requirements, gen = streamclone.generatebundlev1(repo)
2093 requirements, gen = streamclone.generatebundlev1(repo)
2094 changegroup.writechunks(ui, gen, fname)
2094 changegroup.writechunks(ui, gen, fname)
2095
2095
2096 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2096 ui.write(_('bundle requirements: %s\n') % ', '.join(sorted(requirements)))
2097
2097
2098 @command('debugapplystreamclonebundle', [], 'FILE')
2098 @command('debugapplystreamclonebundle', [], 'FILE')
2099 def debugapplystreamclonebundle(ui, repo, fname):
2099 def debugapplystreamclonebundle(ui, repo, fname):
2100 """apply a stream clone bundle file"""
2100 """apply a stream clone bundle file"""
2101 f = hg.openpath(ui, fname)
2101 f = hg.openpath(ui, fname)
2102 gen = exchange.readbundle(ui, f, fname)
2102 gen = exchange.readbundle(ui, f, fname)
2103 gen.apply(repo)
2103 gen.apply(repo)
2104
2104
2105 @command('debugcheckstate', [], '')
2105 @command('debugcheckstate', [], '')
2106 def debugcheckstate(ui, repo):
2106 def debugcheckstate(ui, repo):
2107 """validate the correctness of the current dirstate"""
2107 """validate the correctness of the current dirstate"""
2108 parent1, parent2 = repo.dirstate.parents()
2108 parent1, parent2 = repo.dirstate.parents()
2109 m1 = repo[parent1].manifest()
2109 m1 = repo[parent1].manifest()
2110 m2 = repo[parent2].manifest()
2110 m2 = repo[parent2].manifest()
2111 errors = 0
2111 errors = 0
2112 for f in repo.dirstate:
2112 for f in repo.dirstate:
2113 state = repo.dirstate[f]
2113 state = repo.dirstate[f]
2114 if state in "nr" and f not in m1:
2114 if state in "nr" and f not in m1:
2115 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2115 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
2116 errors += 1
2116 errors += 1
2117 if state in "a" and f in m1:
2117 if state in "a" and f in m1:
2118 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2118 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
2119 errors += 1
2119 errors += 1
2120 if state in "m" and f not in m1 and f not in m2:
2120 if state in "m" and f not in m1 and f not in m2:
2121 ui.warn(_("%s in state %s, but not in either manifest\n") %
2121 ui.warn(_("%s in state %s, but not in either manifest\n") %
2122 (f, state))
2122 (f, state))
2123 errors += 1
2123 errors += 1
2124 for f in m1:
2124 for f in m1:
2125 state = repo.dirstate[f]
2125 state = repo.dirstate[f]
2126 if state not in "nrm":
2126 if state not in "nrm":
2127 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2127 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
2128 errors += 1
2128 errors += 1
2129 if errors:
2129 if errors:
2130 error = _(".hg/dirstate inconsistent with current parent's manifest")
2130 error = _(".hg/dirstate inconsistent with current parent's manifest")
2131 raise error.Abort(error)
2131 raise error.Abort(error)
2132
2132
2133 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2133 @command('debugcommands', [], _('[COMMAND]'), norepo=True)
2134 def debugcommands(ui, cmd='', *args):
2134 def debugcommands(ui, cmd='', *args):
2135 """list all available commands and options"""
2135 """list all available commands and options"""
2136 for cmd, vals in sorted(table.iteritems()):
2136 for cmd, vals in sorted(table.iteritems()):
2137 cmd = cmd.split('|')[0].strip('^')
2137 cmd = cmd.split('|')[0].strip('^')
2138 opts = ', '.join([i[1] for i in vals[1]])
2138 opts = ', '.join([i[1] for i in vals[1]])
2139 ui.write('%s: %s\n' % (cmd, opts))
2139 ui.write('%s: %s\n' % (cmd, opts))
2140
2140
2141 @command('debugcomplete',
2141 @command('debugcomplete',
2142 [('o', 'options', None, _('show the command options'))],
2142 [('o', 'options', None, _('show the command options'))],
2143 _('[-o] CMD'),
2143 _('[-o] CMD'),
2144 norepo=True)
2144 norepo=True)
2145 def debugcomplete(ui, cmd='', **opts):
2145 def debugcomplete(ui, cmd='', **opts):
2146 """returns the completion list associated with the given command"""
2146 """returns the completion list associated with the given command"""
2147
2147
2148 if opts.get('options'):
2148 if opts.get('options'):
2149 options = []
2149 options = []
2150 otables = [globalopts]
2150 otables = [globalopts]
2151 if cmd:
2151 if cmd:
2152 aliases, entry = cmdutil.findcmd(cmd, table, False)
2152 aliases, entry = cmdutil.findcmd(cmd, table, False)
2153 otables.append(entry[1])
2153 otables.append(entry[1])
2154 for t in otables:
2154 for t in otables:
2155 for o in t:
2155 for o in t:
2156 if "(DEPRECATED)" in o[3]:
2156 if "(DEPRECATED)" in o[3]:
2157 continue
2157 continue
2158 if o[0]:
2158 if o[0]:
2159 options.append('-%s' % o[0])
2159 options.append('-%s' % o[0])
2160 options.append('--%s' % o[1])
2160 options.append('--%s' % o[1])
2161 ui.write("%s\n" % "\n".join(options))
2161 ui.write("%s\n" % "\n".join(options))
2162 return
2162 return
2163
2163
2164 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2164 cmdlist, unused_allcmds = cmdutil.findpossible(cmd, table)
2165 if ui.verbose:
2165 if ui.verbose:
2166 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2166 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
2167 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2167 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
2168
2168
2169 @command('debugdag',
2169 @command('debugdag',
2170 [('t', 'tags', None, _('use tags as labels')),
2170 [('t', 'tags', None, _('use tags as labels')),
2171 ('b', 'branches', None, _('annotate with branch names')),
2171 ('b', 'branches', None, _('annotate with branch names')),
2172 ('', 'dots', None, _('use dots for runs')),
2172 ('', 'dots', None, _('use dots for runs')),
2173 ('s', 'spaces', None, _('separate elements by spaces'))],
2173 ('s', 'spaces', None, _('separate elements by spaces'))],
2174 _('[OPTION]... [FILE [REV]...]'),
2174 _('[OPTION]... [FILE [REV]...]'),
2175 optionalrepo=True)
2175 optionalrepo=True)
2176 def debugdag(ui, repo, file_=None, *revs, **opts):
2176 def debugdag(ui, repo, file_=None, *revs, **opts):
2177 """format the changelog or an index DAG as a concise textual description
2177 """format the changelog or an index DAG as a concise textual description
2178
2178
2179 If you pass a revlog index, the revlog's DAG is emitted. If you list
2179 If you pass a revlog index, the revlog's DAG is emitted. If you list
2180 revision numbers, they get labeled in the output as rN.
2180 revision numbers, they get labeled in the output as rN.
2181
2181
2182 Otherwise, the changelog DAG of the current repo is emitted.
2182 Otherwise, the changelog DAG of the current repo is emitted.
2183 """
2183 """
2184 spaces = opts.get('spaces')
2184 spaces = opts.get('spaces')
2185 dots = opts.get('dots')
2185 dots = opts.get('dots')
2186 if file_:
2186 if file_:
2187 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2187 rlog = revlog.revlog(scmutil.opener(os.getcwd(), audit=False), file_)
2188 revs = set((int(r) for r in revs))
2188 revs = set((int(r) for r in revs))
2189 def events():
2189 def events():
2190 for r in rlog:
2190 for r in rlog:
2191 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2191 yield 'n', (r, list(p for p in rlog.parentrevs(r)
2192 if p != -1))
2192 if p != -1))
2193 if r in revs:
2193 if r in revs:
2194 yield 'l', (r, "r%i" % r)
2194 yield 'l', (r, "r%i" % r)
2195 elif repo:
2195 elif repo:
2196 cl = repo.changelog
2196 cl = repo.changelog
2197 tags = opts.get('tags')
2197 tags = opts.get('tags')
2198 branches = opts.get('branches')
2198 branches = opts.get('branches')
2199 if tags:
2199 if tags:
2200 labels = {}
2200 labels = {}
2201 for l, n in repo.tags().items():
2201 for l, n in repo.tags().items():
2202 labels.setdefault(cl.rev(n), []).append(l)
2202 labels.setdefault(cl.rev(n), []).append(l)
2203 def events():
2203 def events():
2204 b = "default"
2204 b = "default"
2205 for r in cl:
2205 for r in cl:
2206 if branches:
2206 if branches:
2207 newb = cl.read(cl.node(r))[5]['branch']
2207 newb = cl.read(cl.node(r))[5]['branch']
2208 if newb != b:
2208 if newb != b:
2209 yield 'a', newb
2209 yield 'a', newb
2210 b = newb
2210 b = newb
2211 yield 'n', (r, list(p for p in cl.parentrevs(r)
2211 yield 'n', (r, list(p for p in cl.parentrevs(r)
2212 if p != -1))
2212 if p != -1))
2213 if tags:
2213 if tags:
2214 ls = labels.get(r)
2214 ls = labels.get(r)
2215 if ls:
2215 if ls:
2216 for l in ls:
2216 for l in ls:
2217 yield 'l', (r, l)
2217 yield 'l', (r, l)
2218 else:
2218 else:
2219 raise error.Abort(_('need repo for changelog dag'))
2219 raise error.Abort(_('need repo for changelog dag'))
2220
2220
2221 for line in dagparser.dagtextlines(events(),
2221 for line in dagparser.dagtextlines(events(),
2222 addspaces=spaces,
2222 addspaces=spaces,
2223 wraplabels=True,
2223 wraplabels=True,
2224 wrapannotations=True,
2224 wrapannotations=True,
2225 wrapnonlinear=dots,
2225 wrapnonlinear=dots,
2226 usedots=dots,
2226 usedots=dots,
2227 maxlinewidth=70):
2227 maxlinewidth=70):
2228 ui.write(line)
2228 ui.write(line)
2229 ui.write("\n")
2229 ui.write("\n")
2230
2230
2231 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2231 @command('debugdata', debugrevlogopts, _('-c|-m|FILE REV'))
2232 def debugdata(ui, repo, file_, rev=None, **opts):
2232 def debugdata(ui, repo, file_, rev=None, **opts):
2233 """dump the contents of a data file revision"""
2233 """dump the contents of a data file revision"""
2234 if opts.get('changelog') or opts.get('manifest'):
2234 if opts.get('changelog') or opts.get('manifest'):
2235 file_, rev = None, file_
2235 file_, rev = None, file_
2236 elif rev is None:
2236 elif rev is None:
2237 raise error.CommandError('debugdata', _('invalid arguments'))
2237 raise error.CommandError('debugdata', _('invalid arguments'))
2238 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2238 r = cmdutil.openrevlog(repo, 'debugdata', file_, opts)
2239 try:
2239 try:
2240 ui.write(r.revision(r.lookup(rev)))
2240 ui.write(r.revision(r.lookup(rev)))
2241 except KeyError:
2241 except KeyError:
2242 raise error.Abort(_('invalid revision identifier %s') % rev)
2242 raise error.Abort(_('invalid revision identifier %s') % rev)
2243
2243
2244 @command('debugdate',
2244 @command('debugdate',
2245 [('e', 'extended', None, _('try extended date formats'))],
2245 [('e', 'extended', None, _('try extended date formats'))],
2246 _('[-e] DATE [RANGE]'),
2246 _('[-e] DATE [RANGE]'),
2247 norepo=True, optionalrepo=True)
2247 norepo=True, optionalrepo=True)
2248 def debugdate(ui, date, range=None, **opts):
2248 def debugdate(ui, date, range=None, **opts):
2249 """parse and display a date"""
2249 """parse and display a date"""
2250 if opts["extended"]:
2250 if opts["extended"]:
2251 d = util.parsedate(date, util.extendeddateformats)
2251 d = util.parsedate(date, util.extendeddateformats)
2252 else:
2252 else:
2253 d = util.parsedate(date)
2253 d = util.parsedate(date)
2254 ui.write(("internal: %s %s\n") % d)
2254 ui.write(("internal: %s %s\n") % d)
2255 ui.write(("standard: %s\n") % util.datestr(d))
2255 ui.write(("standard: %s\n") % util.datestr(d))
2256 if range:
2256 if range:
2257 m = util.matchdate(range)
2257 m = util.matchdate(range)
2258 ui.write(("match: %s\n") % m(d[0]))
2258 ui.write(("match: %s\n") % m(d[0]))
2259
2259
2260 @command('debugdiscovery',
2260 @command('debugdiscovery',
2261 [('', 'old', None, _('use old-style discovery')),
2261 [('', 'old', None, _('use old-style discovery')),
2262 ('', 'nonheads', None,
2262 ('', 'nonheads', None,
2263 _('use old-style discovery with non-heads included')),
2263 _('use old-style discovery with non-heads included')),
2264 ] + remoteopts,
2264 ] + remoteopts,
2265 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2265 _('[-l REV] [-r REV] [-b BRANCH]... [OTHER]'))
2266 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2266 def debugdiscovery(ui, repo, remoteurl="default", **opts):
2267 """runs the changeset discovery protocol in isolation"""
2267 """runs the changeset discovery protocol in isolation"""
2268 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2268 remoteurl, branches = hg.parseurl(ui.expandpath(remoteurl),
2269 opts.get('branch'))
2269 opts.get('branch'))
2270 remote = hg.peer(repo, opts, remoteurl)
2270 remote = hg.peer(repo, opts, remoteurl)
2271 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2271 ui.status(_('comparing with %s\n') % util.hidepassword(remoteurl))
2272
2272
2273 # make sure tests are repeatable
2273 # make sure tests are repeatable
2274 random.seed(12323)
2274 random.seed(12323)
2275
2275
2276 def doit(localheads, remoteheads, remote=remote):
2276 def doit(localheads, remoteheads, remote=remote):
2277 if opts.get('old'):
2277 if opts.get('old'):
2278 if localheads:
2278 if localheads:
2279 raise error.Abort('cannot use localheads with old style '
2279 raise error.Abort('cannot use localheads with old style '
2280 'discovery')
2280 'discovery')
2281 if not util.safehasattr(remote, 'branches'):
2281 if not util.safehasattr(remote, 'branches'):
2282 # enable in-client legacy support
2282 # enable in-client legacy support
2283 remote = localrepo.locallegacypeer(remote.local())
2283 remote = localrepo.locallegacypeer(remote.local())
2284 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2284 common, _in, hds = treediscovery.findcommonincoming(repo, remote,
2285 force=True)
2285 force=True)
2286 common = set(common)
2286 common = set(common)
2287 if not opts.get('nonheads'):
2287 if not opts.get('nonheads'):
2288 ui.write(("unpruned common: %s\n") %
2288 ui.write(("unpruned common: %s\n") %
2289 " ".join(sorted(short(n) for n in common)))
2289 " ".join(sorted(short(n) for n in common)))
2290 dag = dagutil.revlogdag(repo.changelog)
2290 dag = dagutil.revlogdag(repo.changelog)
2291 all = dag.ancestorset(dag.internalizeall(common))
2291 all = dag.ancestorset(dag.internalizeall(common))
2292 common = dag.externalizeall(dag.headsetofconnecteds(all))
2292 common = dag.externalizeall(dag.headsetofconnecteds(all))
2293 else:
2293 else:
2294 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2294 common, any, hds = setdiscovery.findcommonheads(ui, repo, remote)
2295 common = set(common)
2295 common = set(common)
2296 rheads = set(hds)
2296 rheads = set(hds)
2297 lheads = set(repo.heads())
2297 lheads = set(repo.heads())
2298 ui.write(("common heads: %s\n") %
2298 ui.write(("common heads: %s\n") %
2299 " ".join(sorted(short(n) for n in common)))
2299 " ".join(sorted(short(n) for n in common)))
2300 if lheads <= common:
2300 if lheads <= common:
2301 ui.write(("local is subset\n"))
2301 ui.write(("local is subset\n"))
2302 elif rheads <= common:
2302 elif rheads <= common:
2303 ui.write(("remote is subset\n"))
2303 ui.write(("remote is subset\n"))
2304
2304
2305 serverlogs = opts.get('serverlog')
2305 serverlogs = opts.get('serverlog')
2306 if serverlogs:
2306 if serverlogs:
2307 for filename in serverlogs:
2307 for filename in serverlogs:
2308 with open(filename, 'r') as logfile:
2308 with open(filename, 'r') as logfile:
2309 line = logfile.readline()
2309 line = logfile.readline()
2310 while line:
2310 while line:
2311 parts = line.strip().split(';')
2311 parts = line.strip().split(';')
2312 op = parts[1]
2312 op = parts[1]
2313 if op == 'cg':
2313 if op == 'cg':
2314 pass
2314 pass
2315 elif op == 'cgss':
2315 elif op == 'cgss':
2316 doit(parts[2].split(' '), parts[3].split(' '))
2316 doit(parts[2].split(' '), parts[3].split(' '))
2317 elif op == 'unb':
2317 elif op == 'unb':
2318 doit(parts[3].split(' '), parts[2].split(' '))
2318 doit(parts[3].split(' '), parts[2].split(' '))
2319 line = logfile.readline()
2319 line = logfile.readline()
2320 else:
2320 else:
2321 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2321 remoterevs, _checkout = hg.addbranchrevs(repo, remote, branches,
2322 opts.get('remote_head'))
2322 opts.get('remote_head'))
2323 localrevs = opts.get('local_head')
2323 localrevs = opts.get('local_head')
2324 doit(localrevs, remoterevs)
2324 doit(localrevs, remoterevs)
2325
2325
2326 @command('debugextensions', formatteropts, [], norepo=True)
2326 @command('debugextensions', formatteropts, [], norepo=True)
2327 def debugextensions(ui, **opts):
2327 def debugextensions(ui, **opts):
2328 '''show information about active extensions'''
2328 '''show information about active extensions'''
2329 exts = extensions.extensions(ui)
2329 exts = extensions.extensions(ui)
2330 fm = ui.formatter('debugextensions', opts)
2330 fm = ui.formatter('debugextensions', opts)
2331 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2331 for extname, extmod in sorted(exts, key=operator.itemgetter(0)):
2332 extsource = extmod.__file__
2332 extsource = extmod.__file__
2333 exttestedwith = getattr(extmod, 'testedwith', None)
2333 exttestedwith = getattr(extmod, 'testedwith', None)
2334 if exttestedwith is not None:
2334 if exttestedwith is not None:
2335 exttestedwith = exttestedwith.split()
2335 exttestedwith = exttestedwith.split()
2336 extbuglink = getattr(extmod, 'buglink', None)
2336 extbuglink = getattr(extmod, 'buglink', None)
2337
2337
2338 fm.startitem()
2338 fm.startitem()
2339
2339
2340 if ui.quiet or ui.verbose:
2340 if ui.quiet or ui.verbose:
2341 fm.write('name', '%s\n', extname)
2341 fm.write('name', '%s\n', extname)
2342 else:
2342 else:
2343 fm.write('name', '%s', extname)
2343 fm.write('name', '%s', extname)
2344 if not exttestedwith:
2344 if not exttestedwith:
2345 fm.plain(_(' (untested!)\n'))
2345 fm.plain(_(' (untested!)\n'))
2346 else:
2346 else:
2347 if exttestedwith == ['internal'] or \
2347 if exttestedwith == ['internal'] or \
2348 util.version() in exttestedwith:
2348 util.version() in exttestedwith:
2349 fm.plain('\n')
2349 fm.plain('\n')
2350 else:
2350 else:
2351 lasttestedversion = exttestedwith[-1]
2351 lasttestedversion = exttestedwith[-1]
2352 fm.plain(' (%s!)\n' % lasttestedversion)
2352 fm.plain(' (%s!)\n' % lasttestedversion)
2353
2353
2354 fm.condwrite(ui.verbose and extsource, 'source',
2354 fm.condwrite(ui.verbose and extsource, 'source',
2355 _(' location: %s\n'), extsource or "")
2355 _(' location: %s\n'), extsource or "")
2356
2356
2357 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2357 fm.condwrite(ui.verbose and exttestedwith, 'testedwith',
2358 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2358 _(' tested with: %s\n'), ' '.join(exttestedwith or []))
2359
2359
2360 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2360 fm.condwrite(ui.verbose and extbuglink, 'buglink',
2361 _(' bug reporting: %s\n'), extbuglink or "")
2361 _(' bug reporting: %s\n'), extbuglink or "")
2362
2362
2363 fm.end()
2363 fm.end()
2364
2364
2365 @command('debugfileset',
2365 @command('debugfileset',
2366 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2366 [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
2367 _('[-r REV] FILESPEC'))
2367 _('[-r REV] FILESPEC'))
2368 def debugfileset(ui, repo, expr, **opts):
2368 def debugfileset(ui, repo, expr, **opts):
2369 '''parse and apply a fileset specification'''
2369 '''parse and apply a fileset specification'''
2370 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2370 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
2371 if ui.verbose:
2371 if ui.verbose:
2372 tree = fileset.parse(expr)
2372 tree = fileset.parse(expr)
2373 ui.note(fileset.prettyformat(tree), "\n")
2373 ui.note(fileset.prettyformat(tree), "\n")
2374
2374
2375 for f in ctx.getfileset(expr):
2375 for f in ctx.getfileset(expr):
2376 ui.write("%s\n" % f)
2376 ui.write("%s\n" % f)
2377
2377
2378 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2378 @command('debugfsinfo', [], _('[PATH]'), norepo=True)
2379 def debugfsinfo(ui, path="."):
2379 def debugfsinfo(ui, path="."):
2380 """show information detected about current filesystem"""
2380 """show information detected about current filesystem"""
2381 util.writefile('.debugfsinfo', '')
2381 util.writefile('.debugfsinfo', '')
2382 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2382 ui.write(('exec: %s\n') % (util.checkexec(path) and 'yes' or 'no'))
2383 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2383 ui.write(('symlink: %s\n') % (util.checklink(path) and 'yes' or 'no'))
2384 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2384 ui.write(('hardlink: %s\n') % (util.checknlink(path) and 'yes' or 'no'))
2385 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2385 ui.write(('case-sensitive: %s\n') % (util.checkcase('.debugfsinfo')
2386 and 'yes' or 'no'))
2386 and 'yes' or 'no'))
2387 os.unlink('.debugfsinfo')
2387 os.unlink('.debugfsinfo')
2388
2388
2389 @command('debuggetbundle',
2389 @command('debuggetbundle',
2390 [('H', 'head', [], _('id of head node'), _('ID')),
2390 [('H', 'head', [], _('id of head node'), _('ID')),
2391 ('C', 'common', [], _('id of common node'), _('ID')),
2391 ('C', 'common', [], _('id of common node'), _('ID')),
2392 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2392 ('t', 'type', 'bzip2', _('bundle compression type to use'), _('TYPE'))],
2393 _('REPO FILE [-H|-C ID]...'),
2393 _('REPO FILE [-H|-C ID]...'),
2394 norepo=True)
2394 norepo=True)
2395 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2395 def debuggetbundle(ui, repopath, bundlepath, head=None, common=None, **opts):
2396 """retrieves a bundle from a repo
2396 """retrieves a bundle from a repo
2397
2397
2398 Every ID must be a full-length hex node id string. Saves the bundle to the
2398 Every ID must be a full-length hex node id string. Saves the bundle to the
2399 given file.
2399 given file.
2400 """
2400 """
2401 repo = hg.peer(ui, opts, repopath)
2401 repo = hg.peer(ui, opts, repopath)
2402 if not repo.capable('getbundle'):
2402 if not repo.capable('getbundle'):
2403 raise error.Abort("getbundle() not supported by target repository")
2403 raise error.Abort("getbundle() not supported by target repository")
2404 args = {}
2404 args = {}
2405 if common:
2405 if common:
2406 args['common'] = [bin(s) for s in common]
2406 args['common'] = [bin(s) for s in common]
2407 if head:
2407 if head:
2408 args['heads'] = [bin(s) for s in head]
2408 args['heads'] = [bin(s) for s in head]
2409 # TODO: get desired bundlecaps from command line.
2409 # TODO: get desired bundlecaps from command line.
2410 args['bundlecaps'] = None
2410 args['bundlecaps'] = None
2411 bundle = repo.getbundle('debug', **args)
2411 bundle = repo.getbundle('debug', **args)
2412
2412
2413 bundletype = opts.get('type', 'bzip2').lower()
2413 bundletype = opts.get('type', 'bzip2').lower()
2414 btypes = {'none': 'HG10UN',
2414 btypes = {'none': 'HG10UN',
2415 'bzip2': 'HG10BZ',
2415 'bzip2': 'HG10BZ',
2416 'gzip': 'HG10GZ',
2416 'gzip': 'HG10GZ',
2417 'bundle2': 'HG20'}
2417 'bundle2': 'HG20'}
2418 bundletype = btypes.get(bundletype)
2418 bundletype = btypes.get(bundletype)
2419 if bundletype not in changegroup.bundletypes:
2419 if bundletype not in changegroup.bundletypes:
2420 raise error.Abort(_('unknown bundle type specified with --type'))
2420 raise error.Abort(_('unknown bundle type specified with --type'))
2421 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2421 changegroup.writebundle(ui, bundle, bundlepath, bundletype)
2422
2422
2423 @command('debugignore', [], '[FILE]')
2423 @command('debugignore', [], '[FILE]')
2424 def debugignore(ui, repo, *files, **opts):
2424 def debugignore(ui, repo, *files, **opts):
2425 """display the combined ignore pattern and information about ignored files
2425 """display the combined ignore pattern and information about ignored files
2426
2426
2427 With no argument display the combined ignore pattern.
2427 With no argument display the combined ignore pattern.
2428
2428
2429 Given space separated file names, shows if the given file is ignored and
2429 Given space separated file names, shows if the given file is ignored and
2430 if so, show the ignore rule (file and line number) that matched it.
2430 if so, show the ignore rule (file and line number) that matched it.
2431 """
2431 """
2432 ignore = repo.dirstate._ignore
2432 ignore = repo.dirstate._ignore
2433 if not files:
2433 if not files:
2434 # Show all the patterns
2434 # Show all the patterns
2435 includepat = getattr(ignore, 'includepat', None)
2435 includepat = getattr(ignore, 'includepat', None)
2436 if includepat is not None:
2436 if includepat is not None:
2437 ui.write("%s\n" % includepat)
2437 ui.write("%s\n" % includepat)
2438 else:
2438 else:
2439 raise error.Abort(_("no ignore patterns found"))
2439 raise error.Abort(_("no ignore patterns found"))
2440 else:
2440 else:
2441 for f in files:
2441 for f in files:
2442 ignored = None
2442 ignored = None
2443 ignoredata = None
2443 ignoredata = None
2444 if f != '.':
2444 if f != '.':
2445 if ignore(f):
2445 if ignore(f):
2446 ignored = f
2446 ignored = f
2447 ignoredata = repo.dirstate._ignorefileandline(f)
2447 ignoredata = repo.dirstate._ignorefileandline(f)
2448 else:
2448 else:
2449 for p in util.finddirs(f):
2449 for p in util.finddirs(f):
2450 if ignore(p):
2450 if ignore(p):
2451 ignored = p
2451 ignored = p
2452 ignoredata = repo.dirstate._ignorefileandline(p)
2452 ignoredata = repo.dirstate._ignorefileandline(p)
2453 break
2453 break
2454 if ignored:
2454 if ignored:
2455 if ignored == f:
2455 if ignored == f:
2456 ui.write("%s is ignored\n" % f)
2456 ui.write("%s is ignored\n" % f)
2457 else:
2457 else:
2458 ui.write("%s is ignored because of containing folder %s\n"
2458 ui.write("%s is ignored because of containing folder %s\n"
2459 % (f, ignored))
2459 % (f, ignored))
2460 ignorefile, lineno, line = ignoredata
2460 ignorefile, lineno, line = ignoredata
2461 ui.write("(ignore rule in %s, line %d: '%s')\n"
2461 ui.write("(ignore rule in %s, line %d: '%s')\n"
2462 % (ignorefile, lineno, line))
2462 % (ignorefile, lineno, line))
2463 else:
2463 else:
2464 ui.write("%s is not ignored\n" % f)
2464 ui.write("%s is not ignored\n" % f)
2465
2465
2466 @command('debugindex', debugrevlogopts +
2466 @command('debugindex', debugrevlogopts +
2467 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2467 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
2468 _('[-f FORMAT] -c|-m|FILE'),
2468 _('[-f FORMAT] -c|-m|FILE'),
2469 optionalrepo=True)
2469 optionalrepo=True)
2470 def debugindex(ui, repo, file_=None, **opts):
2470 def debugindex(ui, repo, file_=None, **opts):
2471 """dump the contents of an index file"""
2471 """dump the contents of an index file"""
2472 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2472 r = cmdutil.openrevlog(repo, 'debugindex', file_, opts)
2473 format = opts.get('format', 0)
2473 format = opts.get('format', 0)
2474 if format not in (0, 1):
2474 if format not in (0, 1):
2475 raise error.Abort(_("unknown format %d") % format)
2475 raise error.Abort(_("unknown format %d") % format)
2476
2476
2477 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2477 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2478 if generaldelta:
2478 if generaldelta:
2479 basehdr = ' delta'
2479 basehdr = ' delta'
2480 else:
2480 else:
2481 basehdr = ' base'
2481 basehdr = ' base'
2482
2482
2483 if ui.debugflag:
2483 if ui.debugflag:
2484 shortfn = hex
2484 shortfn = hex
2485 else:
2485 else:
2486 shortfn = short
2486 shortfn = short
2487
2487
2488 # There might not be anything in r, so have a sane default
2488 # There might not be anything in r, so have a sane default
2489 idlen = 12
2489 idlen = 12
2490 for i in r:
2490 for i in r:
2491 idlen = len(shortfn(r.node(i)))
2491 idlen = len(shortfn(r.node(i)))
2492 break
2492 break
2493
2493
2494 if format == 0:
2494 if format == 0:
2495 ui.write(" rev offset length " + basehdr + " linkrev"
2495 ui.write(" rev offset length " + basehdr + " linkrev"
2496 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2496 " %s %s p2\n" % ("nodeid".ljust(idlen), "p1".ljust(idlen)))
2497 elif format == 1:
2497 elif format == 1:
2498 ui.write(" rev flag offset length"
2498 ui.write(" rev flag offset length"
2499 " size " + basehdr + " link p1 p2"
2499 " size " + basehdr + " link p1 p2"
2500 " %s\n" % "nodeid".rjust(idlen))
2500 " %s\n" % "nodeid".rjust(idlen))
2501
2501
2502 for i in r:
2502 for i in r:
2503 node = r.node(i)
2503 node = r.node(i)
2504 if generaldelta:
2504 if generaldelta:
2505 base = r.deltaparent(i)
2505 base = r.deltaparent(i)
2506 else:
2506 else:
2507 base = r.chainbase(i)
2507 base = r.chainbase(i)
2508 if format == 0:
2508 if format == 0:
2509 try:
2509 try:
2510 pp = r.parents(node)
2510 pp = r.parents(node)
2511 except Exception:
2511 except Exception:
2512 pp = [nullid, nullid]
2512 pp = [nullid, nullid]
2513 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2513 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
2514 i, r.start(i), r.length(i), base, r.linkrev(i),
2514 i, r.start(i), r.length(i), base, r.linkrev(i),
2515 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2515 shortfn(node), shortfn(pp[0]), shortfn(pp[1])))
2516 elif format == 1:
2516 elif format == 1:
2517 pr = r.parentrevs(i)
2517 pr = r.parentrevs(i)
2518 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2518 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
2519 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2519 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
2520 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2520 base, r.linkrev(i), pr[0], pr[1], shortfn(node)))
2521
2521
2522 @command('debugindexdot', debugrevlogopts,
2522 @command('debugindexdot', debugrevlogopts,
2523 _('-c|-m|FILE'), optionalrepo=True)
2523 _('-c|-m|FILE'), optionalrepo=True)
2524 def debugindexdot(ui, repo, file_=None, **opts):
2524 def debugindexdot(ui, repo, file_=None, **opts):
2525 """dump an index DAG as a graphviz dot file"""
2525 """dump an index DAG as a graphviz dot file"""
2526 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2526 r = cmdutil.openrevlog(repo, 'debugindexdot', file_, opts)
2527 ui.write(("digraph G {\n"))
2527 ui.write(("digraph G {\n"))
2528 for i in r:
2528 for i in r:
2529 node = r.node(i)
2529 node = r.node(i)
2530 pp = r.parents(node)
2530 pp = r.parents(node)
2531 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2531 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
2532 if pp[1] != nullid:
2532 if pp[1] != nullid:
2533 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2533 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
2534 ui.write("}\n")
2534 ui.write("}\n")
2535
2535
2536 @command('debugdeltachain',
2536 @command('debugdeltachain',
2537 debugrevlogopts + formatteropts,
2537 debugrevlogopts + formatteropts,
2538 _('-c|-m|FILE'),
2538 _('-c|-m|FILE'),
2539 optionalrepo=True)
2539 optionalrepo=True)
2540 def debugdeltachain(ui, repo, file_=None, **opts):
2540 def debugdeltachain(ui, repo, file_=None, **opts):
2541 """dump information about delta chains in a revlog
2541 """dump information about delta chains in a revlog
2542
2542
2543 Output can be templatized. Available template keywords are:
2543 Output can be templatized. Available template keywords are:
2544
2544
2545 rev revision number
2545 rev revision number
2546 chainid delta chain identifier (numbered by unique base)
2546 chainid delta chain identifier (numbered by unique base)
2547 chainlen delta chain length to this revision
2547 chainlen delta chain length to this revision
2548 prevrev previous revision in delta chain
2548 prevrev previous revision in delta chain
2549 deltatype role of delta / how it was computed
2549 deltatype role of delta / how it was computed
2550 compsize compressed size of revision
2550 compsize compressed size of revision
2551 uncompsize uncompressed size of revision
2551 uncompsize uncompressed size of revision
2552 chainsize total size of compressed revisions in chain
2552 chainsize total size of compressed revisions in chain
2553 chainratio total chain size divided by uncompressed revision size
2553 chainratio total chain size divided by uncompressed revision size
2554 (new delta chains typically start at ratio 2.00)
2554 (new delta chains typically start at ratio 2.00)
2555 lindist linear distance from base revision in delta chain to end
2555 lindist linear distance from base revision in delta chain to end
2556 of this revision
2556 of this revision
2557 extradist total size of revisions not part of this delta chain from
2557 extradist total size of revisions not part of this delta chain from
2558 base of delta chain to end of this revision; a measurement
2558 base of delta chain to end of this revision; a measurement
2559 of how much extra data we need to read/seek across to read
2559 of how much extra data we need to read/seek across to read
2560 the delta chain for this revision
2560 the delta chain for this revision
2561 extraratio extradist divided by chainsize; another representation of
2561 extraratio extradist divided by chainsize; another representation of
2562 how much unrelated data is needed to load this delta chain
2562 how much unrelated data is needed to load this delta chain
2563 """
2563 """
2564 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2564 r = cmdutil.openrevlog(repo, 'debugdeltachain', file_, opts)
2565 index = r.index
2565 index = r.index
2566 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2566 generaldelta = r.version & revlog.REVLOGGENERALDELTA
2567
2567
2568 def revinfo(rev):
2568 def revinfo(rev):
2569 e = index[rev]
2569 e = index[rev]
2570 compsize = e[1]
2570 compsize = e[1]
2571 uncompsize = e[2]
2571 uncompsize = e[2]
2572 chainsize = 0
2572 chainsize = 0
2573
2573
2574 if generaldelta:
2574 if generaldelta:
2575 if e[3] == e[5]:
2575 if e[3] == e[5]:
2576 deltatype = 'p1'
2576 deltatype = 'p1'
2577 elif e[3] == e[6]:
2577 elif e[3] == e[6]:
2578 deltatype = 'p2'
2578 deltatype = 'p2'
2579 elif e[3] == rev - 1:
2579 elif e[3] == rev - 1:
2580 deltatype = 'prev'
2580 deltatype = 'prev'
2581 elif e[3] == rev:
2581 elif e[3] == rev:
2582 deltatype = 'base'
2582 deltatype = 'base'
2583 else:
2583 else:
2584 deltatype = 'other'
2584 deltatype = 'other'
2585 else:
2585 else:
2586 if e[3] == rev:
2586 if e[3] == rev:
2587 deltatype = 'base'
2587 deltatype = 'base'
2588 else:
2588 else:
2589 deltatype = 'prev'
2589 deltatype = 'prev'
2590
2590
2591 chain = r._deltachain(rev)[0]
2591 chain = r._deltachain(rev)[0]
2592 for iterrev in chain:
2592 for iterrev in chain:
2593 e = index[iterrev]
2593 e = index[iterrev]
2594 chainsize += e[1]
2594 chainsize += e[1]
2595
2595
2596 return compsize, uncompsize, deltatype, chain, chainsize
2596 return compsize, uncompsize, deltatype, chain, chainsize
2597
2597
2598 fm = ui.formatter('debugdeltachain', opts)
2598 fm = ui.formatter('debugdeltachain', opts)
2599
2599
2600 fm.plain(' rev chain# chainlen prev delta '
2600 fm.plain(' rev chain# chainlen prev delta '
2601 'size rawsize chainsize ratio lindist extradist '
2601 'size rawsize chainsize ratio lindist extradist '
2602 'extraratio\n')
2602 'extraratio\n')
2603
2603
2604 chainbases = {}
2604 chainbases = {}
2605 for rev in r:
2605 for rev in r:
2606 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2606 comp, uncomp, deltatype, chain, chainsize = revinfo(rev)
2607 chainbase = chain[0]
2607 chainbase = chain[0]
2608 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2608 chainid = chainbases.setdefault(chainbase, len(chainbases) + 1)
2609 basestart = r.start(chainbase)
2609 basestart = r.start(chainbase)
2610 revstart = r.start(rev)
2610 revstart = r.start(rev)
2611 lineardist = revstart + comp - basestart
2611 lineardist = revstart + comp - basestart
2612 extradist = lineardist - chainsize
2612 extradist = lineardist - chainsize
2613 try:
2613 try:
2614 prevrev = chain[-2]
2614 prevrev = chain[-2]
2615 except IndexError:
2615 except IndexError:
2616 prevrev = -1
2616 prevrev = -1
2617
2617
2618 chainratio = float(chainsize) / float(uncomp)
2618 chainratio = float(chainsize) / float(uncomp)
2619 extraratio = float(extradist) / float(chainsize)
2619 extraratio = float(extradist) / float(chainsize)
2620
2620
2621 fm.startitem()
2621 fm.startitem()
2622 fm.write('rev chainid chainlen prevrev deltatype compsize '
2622 fm.write('rev chainid chainlen prevrev deltatype compsize '
2623 'uncompsize chainsize chainratio lindist extradist '
2623 'uncompsize chainsize chainratio lindist extradist '
2624 'extraratio',
2624 'extraratio',
2625 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2625 '%7d %7d %8d %8d %7s %10d %10d %10d %9.5f %9d %9d %10.5f\n',
2626 rev, chainid, len(chain), prevrev, deltatype, comp,
2626 rev, chainid, len(chain), prevrev, deltatype, comp,
2627 uncomp, chainsize, chainratio, lineardist, extradist,
2627 uncomp, chainsize, chainratio, lineardist, extradist,
2628 extraratio,
2628 extraratio,
2629 rev=rev, chainid=chainid, chainlen=len(chain),
2629 rev=rev, chainid=chainid, chainlen=len(chain),
2630 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2630 prevrev=prevrev, deltatype=deltatype, compsize=comp,
2631 uncompsize=uncomp, chainsize=chainsize,
2631 uncompsize=uncomp, chainsize=chainsize,
2632 chainratio=chainratio, lindist=lineardist,
2632 chainratio=chainratio, lindist=lineardist,
2633 extradist=extradist, extraratio=extraratio)
2633 extradist=extradist, extraratio=extraratio)
2634
2634
2635 fm.end()
2635 fm.end()
2636
2636
2637 @command('debuginstall', [], '', norepo=True)
2637 @command('debuginstall', [], '', norepo=True)
2638 def debuginstall(ui):
2638 def debuginstall(ui):
2639 '''test Mercurial installation
2639 '''test Mercurial installation
2640
2640
2641 Returns 0 on success.
2641 Returns 0 on success.
2642 '''
2642 '''
2643
2643
2644 def writetemp(contents):
2644 def writetemp(contents):
2645 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2645 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
2646 f = os.fdopen(fd, "wb")
2646 f = os.fdopen(fd, "wb")
2647 f.write(contents)
2647 f.write(contents)
2648 f.close()
2648 f.close()
2649 return name
2649 return name
2650
2650
2651 problems = 0
2651 problems = 0
2652
2652
2653 # encoding
2653 # encoding
2654 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2654 ui.status(_("checking encoding (%s)...\n") % encoding.encoding)
2655 try:
2655 try:
2656 encoding.fromlocal("test")
2656 encoding.fromlocal("test")
2657 except error.Abort as inst:
2657 except error.Abort as inst:
2658 ui.write(" %s\n" % inst)
2658 ui.write(" %s\n" % inst)
2659 ui.write(_(" (check that your locale is properly set)\n"))
2659 ui.write(_(" (check that your locale is properly set)\n"))
2660 problems += 1
2660 problems += 1
2661
2661
2662 # Python
2662 # Python
2663 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2663 ui.status(_("checking Python executable (%s)\n") % sys.executable)
2664 ui.status(_("checking Python version (%s)\n")
2664 ui.status(_("checking Python version (%s)\n")
2665 % ("%s.%s.%s" % sys.version_info[:3]))
2665 % ("%s.%s.%s" % sys.version_info[:3]))
2666 ui.status(_("checking Python lib (%s)...\n")
2666 ui.status(_("checking Python lib (%s)...\n")
2667 % os.path.dirname(os.__file__))
2667 % os.path.dirname(os.__file__))
2668
2668
2669 # compiled modules
2669 # compiled modules
2670 ui.status(_("checking installed modules (%s)...\n")
2670 ui.status(_("checking installed modules (%s)...\n")
2671 % os.path.dirname(__file__))
2671 % os.path.dirname(__file__))
2672 try:
2672 try:
2673 import bdiff, mpatch, base85, osutil
2673 import bdiff, mpatch, base85, osutil
2674 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2674 dir(bdiff), dir(mpatch), dir(base85), dir(osutil) # quiet pyflakes
2675 except Exception as inst:
2675 except Exception as inst:
2676 ui.write(" %s\n" % inst)
2676 ui.write(" %s\n" % inst)
2677 ui.write(_(" One or more extensions could not be found"))
2677 ui.write(_(" One or more extensions could not be found"))
2678 ui.write(_(" (check that you compiled the extensions)\n"))
2678 ui.write(_(" (check that you compiled the extensions)\n"))
2679 problems += 1
2679 problems += 1
2680
2680
2681 # templates
2681 # templates
2682 import templater
2682 import templater
2683 p = templater.templatepaths()
2683 p = templater.templatepaths()
2684 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2684 ui.status(_("checking templates (%s)...\n") % ' '.join(p))
2685 if p:
2685 if p:
2686 m = templater.templatepath("map-cmdline.default")
2686 m = templater.templatepath("map-cmdline.default")
2687 if m:
2687 if m:
2688 # template found, check if it is working
2688 # template found, check if it is working
2689 try:
2689 try:
2690 templater.templater(m)
2690 templater.templater(m)
2691 except Exception as inst:
2691 except Exception as inst:
2692 ui.write(" %s\n" % inst)
2692 ui.write(" %s\n" % inst)
2693 p = None
2693 p = None
2694 else:
2694 else:
2695 ui.write(_(" template 'default' not found\n"))
2695 ui.write(_(" template 'default' not found\n"))
2696 p = None
2696 p = None
2697 else:
2697 else:
2698 ui.write(_(" no template directories found\n"))
2698 ui.write(_(" no template directories found\n"))
2699 if not p:
2699 if not p:
2700 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2700 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
2701 problems += 1
2701 problems += 1
2702
2702
2703 # editor
2703 # editor
2704 ui.status(_("checking commit editor...\n"))
2704 ui.status(_("checking commit editor...\n"))
2705 editor = ui.geteditor()
2705 editor = ui.geteditor()
2706 editor = util.expandpath(editor)
2706 editor = util.expandpath(editor)
2707 cmdpath = util.findexe(shlex.split(editor)[0])
2707 cmdpath = util.findexe(shlex.split(editor)[0])
2708 if not cmdpath:
2708 if not cmdpath:
2709 if editor == 'vi':
2709 if editor == 'vi':
2710 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2710 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
2711 ui.write(_(" (specify a commit editor in your configuration"
2711 ui.write(_(" (specify a commit editor in your configuration"
2712 " file)\n"))
2712 " file)\n"))
2713 else:
2713 else:
2714 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2714 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
2715 ui.write(_(" (specify a commit editor in your configuration"
2715 ui.write(_(" (specify a commit editor in your configuration"
2716 " file)\n"))
2716 " file)\n"))
2717 problems += 1
2717 problems += 1
2718
2718
2719 # check username
2719 # check username
2720 ui.status(_("checking username...\n"))
2720 ui.status(_("checking username...\n"))
2721 try:
2721 try:
2722 ui.username()
2722 ui.username()
2723 except error.Abort as e:
2723 except error.Abort as e:
2724 ui.write(" %s\n" % e)
2724 ui.write(" %s\n" % e)
2725 ui.write(_(" (specify a username in your configuration file)\n"))
2725 ui.write(_(" (specify a username in your configuration file)\n"))
2726 problems += 1
2726 problems += 1
2727
2727
2728 if not problems:
2728 if not problems:
2729 ui.status(_("no problems detected\n"))
2729 ui.status(_("no problems detected\n"))
2730 else:
2730 else:
2731 ui.write(_("%s problems detected,"
2731 ui.write(_("%s problems detected,"
2732 " please check your install!\n") % problems)
2732 " please check your install!\n") % problems)
2733
2733
2734 return problems
2734 return problems
2735
2735
2736 @command('debugknown', [], _('REPO ID...'), norepo=True)
2736 @command('debugknown', [], _('REPO ID...'), norepo=True)
2737 def debugknown(ui, repopath, *ids, **opts):
2737 def debugknown(ui, repopath, *ids, **opts):
2738 """test whether node ids are known to a repo
2738 """test whether node ids are known to a repo
2739
2739
2740 Every ID must be a full-length hex node id string. Returns a list of 0s
2740 Every ID must be a full-length hex node id string. Returns a list of 0s
2741 and 1s indicating unknown/known.
2741 and 1s indicating unknown/known.
2742 """
2742 """
2743 repo = hg.peer(ui, opts, repopath)
2743 repo = hg.peer(ui, opts, repopath)
2744 if not repo.capable('known'):
2744 if not repo.capable('known'):
2745 raise error.Abort("known() not supported by target repository")
2745 raise error.Abort("known() not supported by target repository")
2746 flags = repo.known([bin(s) for s in ids])
2746 flags = repo.known([bin(s) for s in ids])
2747 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2747 ui.write("%s\n" % ("".join([f and "1" or "0" for f in flags])))
2748
2748
2749 @command('debuglabelcomplete', [], _('LABEL...'))
2749 @command('debuglabelcomplete', [], _('LABEL...'))
2750 def debuglabelcomplete(ui, repo, *args):
2750 def debuglabelcomplete(ui, repo, *args):
2751 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2751 '''backwards compatibility with old bash completion scripts (DEPRECATED)'''
2752 debugnamecomplete(ui, repo, *args)
2752 debugnamecomplete(ui, repo, *args)
2753
2753
2754 @command('debugmergestate', [], '')
2754 @command('debugmergestate', [], '')
2755 def debugmergestate(ui, repo, *args):
2755 def debugmergestate(ui, repo, *args):
2756 """print merge state
2756 """print merge state
2757
2757
2758 Use --verbose to print out information about whether v1 or v2 merge state
2758 Use --verbose to print out information about whether v1 or v2 merge state
2759 was chosen."""
2759 was chosen."""
2760 def _hashornull(h):
2760 def _hashornull(h):
2761 if h == nullhex:
2761 if h == nullhex:
2762 return 'null'
2762 return 'null'
2763 else:
2763 else:
2764 return h
2764 return h
2765
2765
2766 def printrecords(version):
2766 def printrecords(version):
2767 ui.write(('* version %s records\n') % version)
2767 ui.write(('* version %s records\n') % version)
2768 if version == 1:
2768 if version == 1:
2769 records = v1records
2769 records = v1records
2770 else:
2770 else:
2771 records = v2records
2771 records = v2records
2772
2772
2773 for rtype, record in records:
2773 for rtype, record in records:
2774 # pretty print some record types
2774 # pretty print some record types
2775 if rtype == 'L':
2775 if rtype == 'L':
2776 ui.write(('local: %s\n') % record)
2776 ui.write(('local: %s\n') % record)
2777 elif rtype == 'O':
2777 elif rtype == 'O':
2778 ui.write(('other: %s\n') % record)
2778 ui.write(('other: %s\n') % record)
2779 elif rtype == 'm':
2779 elif rtype == 'm':
2780 driver, mdstate = record.split('\0', 1)
2780 driver, mdstate = record.split('\0', 1)
2781 ui.write(('merge driver: %s (state "%s")\n')
2781 ui.write(('merge driver: %s (state "%s")\n')
2782 % (driver, mdstate))
2782 % (driver, mdstate))
2783 elif rtype in 'FDC':
2783 elif rtype in 'FDC':
2784 r = record.split('\0')
2784 r = record.split('\0')
2785 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2785 f, state, hash, lfile, afile, anode, ofile = r[0:7]
2786 if version == 1:
2786 if version == 1:
2787 onode = 'not stored in v1 format'
2787 onode = 'not stored in v1 format'
2788 flags = r[7]
2788 flags = r[7]
2789 else:
2789 else:
2790 onode, flags = r[7:9]
2790 onode, flags = r[7:9]
2791 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2791 ui.write(('file: %s (record type "%s", state "%s", hash %s)\n')
2792 % (f, rtype, state, _hashornull(hash)))
2792 % (f, rtype, state, _hashornull(hash)))
2793 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2793 ui.write((' local path: %s (flags "%s")\n') % (lfile, flags))
2794 ui.write((' ancestor path: %s (node %s)\n')
2794 ui.write((' ancestor path: %s (node %s)\n')
2795 % (afile, _hashornull(anode)))
2795 % (afile, _hashornull(anode)))
2796 ui.write((' other path: %s (node %s)\n')
2796 ui.write((' other path: %s (node %s)\n')
2797 % (ofile, _hashornull(onode)))
2797 % (ofile, _hashornull(onode)))
2798 else:
2798 else:
2799 ui.write(('unrecognized entry: %s\t%s\n')
2799 ui.write(('unrecognized entry: %s\t%s\n')
2800 % (rtype, record.replace('\0', '\t')))
2800 % (rtype, record.replace('\0', '\t')))
2801
2801
2802 # Avoid mergestate.read() since it may raise an exception for unsupported
2802 # Avoid mergestate.read() since it may raise an exception for unsupported
2803 # merge state records. We shouldn't be doing this, but this is OK since this
2803 # merge state records. We shouldn't be doing this, but this is OK since this
2804 # command is pretty low-level.
2804 # command is pretty low-level.
2805 ms = mergemod.mergestate(repo)
2805 ms = mergemod.mergestate(repo)
2806
2806
2807 # sort so that reasonable information is on top
2807 # sort so that reasonable information is on top
2808 v1records = ms._readrecordsv1()
2808 v1records = ms._readrecordsv1()
2809 v2records = ms._readrecordsv2()
2809 v2records = ms._readrecordsv2()
2810 order = 'LOm'
2810 order = 'LOm'
2811 def key(r):
2811 def key(r):
2812 idx = order.find(r[0])
2812 idx = order.find(r[0])
2813 if idx == -1:
2813 if idx == -1:
2814 return (1, r[1])
2814 return (1, r[1])
2815 else:
2815 else:
2816 return (0, idx)
2816 return (0, idx)
2817 v1records.sort(key=key)
2817 v1records.sort(key=key)
2818 v2records.sort(key=key)
2818 v2records.sort(key=key)
2819
2819
2820 if not v1records and not v2records:
2820 if not v1records and not v2records:
2821 ui.write(('no merge state found\n'))
2821 ui.write(('no merge state found\n'))
2822 elif not v2records:
2822 elif not v2records:
2823 ui.note(('no version 2 merge state\n'))
2823 ui.note(('no version 2 merge state\n'))
2824 printrecords(1)
2824 printrecords(1)
2825 elif ms._v1v2match(v1records, v2records):
2825 elif ms._v1v2match(v1records, v2records):
2826 ui.note(('v1 and v2 states match: using v2\n'))
2826 ui.note(('v1 and v2 states match: using v2\n'))
2827 printrecords(2)
2827 printrecords(2)
2828 else:
2828 else:
2829 ui.note(('v1 and v2 states mismatch: using v1\n'))
2829 ui.note(('v1 and v2 states mismatch: using v1\n'))
2830 printrecords(1)
2830 printrecords(1)
2831 if ui.verbose:
2831 if ui.verbose:
2832 printrecords(2)
2832 printrecords(2)
2833
2833
2834 @command('debugnamecomplete', [], _('NAME...'))
2834 @command('debugnamecomplete', [], _('NAME...'))
2835 def debugnamecomplete(ui, repo, *args):
2835 def debugnamecomplete(ui, repo, *args):
2836 '''complete "names" - tags, open branch names, bookmark names'''
2836 '''complete "names" - tags, open branch names, bookmark names'''
2837
2837
2838 names = set()
2838 names = set()
2839 # since we previously only listed open branches, we will handle that
2839 # since we previously only listed open branches, we will handle that
2840 # specially (after this for loop)
2840 # specially (after this for loop)
2841 for name, ns in repo.names.iteritems():
2841 for name, ns in repo.names.iteritems():
2842 if name != 'branches':
2842 if name != 'branches':
2843 names.update(ns.listnames(repo))
2843 names.update(ns.listnames(repo))
2844 names.update(tag for (tag, heads, tip, closed)
2844 names.update(tag for (tag, heads, tip, closed)
2845 in repo.branchmap().iterbranches() if not closed)
2845 in repo.branchmap().iterbranches() if not closed)
2846 completions = set()
2846 completions = set()
2847 if not args:
2847 if not args:
2848 args = ['']
2848 args = ['']
2849 for a in args:
2849 for a in args:
2850 completions.update(n for n in names if n.startswith(a))
2850 completions.update(n for n in names if n.startswith(a))
2851 ui.write('\n'.join(sorted(completions)))
2851 ui.write('\n'.join(sorted(completions)))
2852 ui.write('\n')
2852 ui.write('\n')
2853
2853
2854 @command('debuglocks',
2854 @command('debuglocks',
2855 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2855 [('L', 'force-lock', None, _('free the store lock (DANGEROUS)')),
2856 ('W', 'force-wlock', None,
2856 ('W', 'force-wlock', None,
2857 _('free the working state lock (DANGEROUS)'))],
2857 _('free the working state lock (DANGEROUS)'))],
2858 _('[OPTION]...'))
2858 _('[OPTION]...'))
2859 def debuglocks(ui, repo, **opts):
2859 def debuglocks(ui, repo, **opts):
2860 """show or modify state of locks
2860 """show or modify state of locks
2861
2861
2862 By default, this command will show which locks are held. This
2862 By default, this command will show which locks are held. This
2863 includes the user and process holding the lock, the amount of time
2863 includes the user and process holding the lock, the amount of time
2864 the lock has been held, and the machine name where the process is
2864 the lock has been held, and the machine name where the process is
2865 running if it's not local.
2865 running if it's not local.
2866
2866
2867 Locks protect the integrity of Mercurial's data, so should be
2867 Locks protect the integrity of Mercurial's data, so should be
2868 treated with care. System crashes or other interruptions may cause
2868 treated with care. System crashes or other interruptions may cause
2869 locks to not be properly released, though Mercurial will usually
2869 locks to not be properly released, though Mercurial will usually
2870 detect and remove such stale locks automatically.
2870 detect and remove such stale locks automatically.
2871
2871
2872 However, detecting stale locks may not always be possible (for
2872 However, detecting stale locks may not always be possible (for
2873 instance, on a shared filesystem). Removing locks may also be
2873 instance, on a shared filesystem). Removing locks may also be
2874 blocked by filesystem permissions.
2874 blocked by filesystem permissions.
2875
2875
2876 Returns 0 if no locks are held.
2876 Returns 0 if no locks are held.
2877
2877
2878 """
2878 """
2879
2879
2880 if opts.get('force_lock'):
2880 if opts.get('force_lock'):
2881 repo.svfs.unlink('lock')
2881 repo.svfs.unlink('lock')
2882 if opts.get('force_wlock'):
2882 if opts.get('force_wlock'):
2883 repo.vfs.unlink('wlock')
2883 repo.vfs.unlink('wlock')
2884 if opts.get('force_lock') or opts.get('force_lock'):
2884 if opts.get('force_lock') or opts.get('force_lock'):
2885 return 0
2885 return 0
2886
2886
2887 now = time.time()
2887 now = time.time()
2888 held = 0
2888 held = 0
2889
2889
2890 def report(vfs, name, method):
2890 def report(vfs, name, method):
2891 # this causes stale locks to get reaped for more accurate reporting
2891 # this causes stale locks to get reaped for more accurate reporting
2892 try:
2892 try:
2893 l = method(False)
2893 l = method(False)
2894 except error.LockHeld:
2894 except error.LockHeld:
2895 l = None
2895 l = None
2896
2896
2897 if l:
2897 if l:
2898 l.release()
2898 l.release()
2899 else:
2899 else:
2900 try:
2900 try:
2901 stat = vfs.lstat(name)
2901 stat = vfs.lstat(name)
2902 age = now - stat.st_mtime
2902 age = now - stat.st_mtime
2903 user = util.username(stat.st_uid)
2903 user = util.username(stat.st_uid)
2904 locker = vfs.readlock(name)
2904 locker = vfs.readlock(name)
2905 if ":" in locker:
2905 if ":" in locker:
2906 host, pid = locker.split(':')
2906 host, pid = locker.split(':')
2907 if host == socket.gethostname():
2907 if host == socket.gethostname():
2908 locker = 'user %s, process %s' % (user, pid)
2908 locker = 'user %s, process %s' % (user, pid)
2909 else:
2909 else:
2910 locker = 'user %s, process %s, host %s' \
2910 locker = 'user %s, process %s, host %s' \
2911 % (user, pid, host)
2911 % (user, pid, host)
2912 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2912 ui.write("%-6s %s (%ds)\n" % (name + ":", locker, age))
2913 return 1
2913 return 1
2914 except OSError as e:
2914 except OSError as e:
2915 if e.errno != errno.ENOENT:
2915 if e.errno != errno.ENOENT:
2916 raise
2916 raise
2917
2917
2918 ui.write("%-6s free\n" % (name + ":"))
2918 ui.write("%-6s free\n" % (name + ":"))
2919 return 0
2919 return 0
2920
2920
2921 held += report(repo.svfs, "lock", repo.lock)
2921 held += report(repo.svfs, "lock", repo.lock)
2922 held += report(repo.vfs, "wlock", repo.wlock)
2922 held += report(repo.vfs, "wlock", repo.wlock)
2923
2923
2924 return held
2924 return held
2925
2925
2926 @command('debugobsolete',
2926 @command('debugobsolete',
2927 [('', 'flags', 0, _('markers flag')),
2927 [('', 'flags', 0, _('markers flag')),
2928 ('', 'record-parents', False,
2928 ('', 'record-parents', False,
2929 _('record parent information for the precursor')),
2929 _('record parent information for the precursor')),
2930 ('r', 'rev', [], _('display markers relevant to REV')),
2930 ('r', 'rev', [], _('display markers relevant to REV')),
2931 ] + commitopts2,
2931 ] + commitopts2,
2932 _('[OBSOLETED [REPLACEMENT ...]]'))
2932 _('[OBSOLETED [REPLACEMENT ...]]'))
2933 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2933 def debugobsolete(ui, repo, precursor=None, *successors, **opts):
2934 """create arbitrary obsolete marker
2934 """create arbitrary obsolete marker
2935
2935
2936 With no arguments, displays the list of obsolescence markers."""
2936 With no arguments, displays the list of obsolescence markers."""
2937
2937
2938 def parsenodeid(s):
2938 def parsenodeid(s):
2939 try:
2939 try:
2940 # We do not use revsingle/revrange functions here to accept
2940 # We do not use revsingle/revrange functions here to accept
2941 # arbitrary node identifiers, possibly not present in the
2941 # arbitrary node identifiers, possibly not present in the
2942 # local repository.
2942 # local repository.
2943 n = bin(s)
2943 n = bin(s)
2944 if len(n) != len(nullid):
2944 if len(n) != len(nullid):
2945 raise TypeError()
2945 raise TypeError()
2946 return n
2946 return n
2947 except TypeError:
2947 except TypeError:
2948 raise error.Abort('changeset references must be full hexadecimal '
2948 raise error.Abort('changeset references must be full hexadecimal '
2949 'node identifiers')
2949 'node identifiers')
2950
2950
2951 if precursor is not None:
2951 if precursor is not None:
2952 if opts['rev']:
2952 if opts['rev']:
2953 raise error.Abort('cannot select revision when creating marker')
2953 raise error.Abort('cannot select revision when creating marker')
2954 metadata = {}
2954 metadata = {}
2955 metadata['user'] = opts['user'] or ui.username()
2955 metadata['user'] = opts['user'] or ui.username()
2956 succs = tuple(parsenodeid(succ) for succ in successors)
2956 succs = tuple(parsenodeid(succ) for succ in successors)
2957 l = repo.lock()
2957 l = repo.lock()
2958 try:
2958 try:
2959 tr = repo.transaction('debugobsolete')
2959 tr = repo.transaction('debugobsolete')
2960 try:
2960 try:
2961 date = opts.get('date')
2961 date = opts.get('date')
2962 if date:
2962 if date:
2963 date = util.parsedate(date)
2963 date = util.parsedate(date)
2964 else:
2964 else:
2965 date = None
2965 date = None
2966 prec = parsenodeid(precursor)
2966 prec = parsenodeid(precursor)
2967 parents = None
2967 parents = None
2968 if opts['record_parents']:
2968 if opts['record_parents']:
2969 if prec not in repo.unfiltered():
2969 if prec not in repo.unfiltered():
2970 raise error.Abort('cannot used --record-parents on '
2970 raise error.Abort('cannot used --record-parents on '
2971 'unknown changesets')
2971 'unknown changesets')
2972 parents = repo.unfiltered()[prec].parents()
2972 parents = repo.unfiltered()[prec].parents()
2973 parents = tuple(p.node() for p in parents)
2973 parents = tuple(p.node() for p in parents)
2974 repo.obsstore.create(tr, prec, succs, opts['flags'],
2974 repo.obsstore.create(tr, prec, succs, opts['flags'],
2975 parents=parents, date=date,
2975 parents=parents, date=date,
2976 metadata=metadata)
2976 metadata=metadata)
2977 tr.close()
2977 tr.close()
2978 except ValueError as exc:
2978 except ValueError as exc:
2979 raise error.Abort(_('bad obsmarker input: %s') % exc)
2979 raise error.Abort(_('bad obsmarker input: %s') % exc)
2980 finally:
2980 finally:
2981 tr.release()
2981 tr.release()
2982 finally:
2982 finally:
2983 l.release()
2983 l.release()
2984 else:
2984 else:
2985 if opts['rev']:
2985 if opts['rev']:
2986 revs = scmutil.revrange(repo, opts['rev'])
2986 revs = scmutil.revrange(repo, opts['rev'])
2987 nodes = [repo[r].node() for r in revs]
2987 nodes = [repo[r].node() for r in revs]
2988 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2988 markers = list(obsolete.getmarkers(repo, nodes=nodes))
2989 markers.sort(key=lambda x: x._data)
2989 markers.sort(key=lambda x: x._data)
2990 else:
2990 else:
2991 markers = obsolete.getmarkers(repo)
2991 markers = obsolete.getmarkers(repo)
2992
2992
2993 for m in markers:
2993 for m in markers:
2994 cmdutil.showmarker(ui, m)
2994 cmdutil.showmarker(ui, m)
2995
2995
2996 @command('debugpathcomplete',
2996 @command('debugpathcomplete',
2997 [('f', 'full', None, _('complete an entire path')),
2997 [('f', 'full', None, _('complete an entire path')),
2998 ('n', 'normal', None, _('show only normal files')),
2998 ('n', 'normal', None, _('show only normal files')),
2999 ('a', 'added', None, _('show only added files')),
2999 ('a', 'added', None, _('show only added files')),
3000 ('r', 'removed', None, _('show only removed files'))],
3000 ('r', 'removed', None, _('show only removed files'))],
3001 _('FILESPEC...'))
3001 _('FILESPEC...'))
3002 def debugpathcomplete(ui, repo, *specs, **opts):
3002 def debugpathcomplete(ui, repo, *specs, **opts):
3003 '''complete part or all of a tracked path
3003 '''complete part or all of a tracked path
3004
3004
3005 This command supports shells that offer path name completion. It
3005 This command supports shells that offer path name completion. It
3006 currently completes only files already known to the dirstate.
3006 currently completes only files already known to the dirstate.
3007
3007
3008 Completion extends only to the next path segment unless
3008 Completion extends only to the next path segment unless
3009 --full is specified, in which case entire paths are used.'''
3009 --full is specified, in which case entire paths are used.'''
3010
3010
3011 def complete(path, acceptable):
3011 def complete(path, acceptable):
3012 dirstate = repo.dirstate
3012 dirstate = repo.dirstate
3013 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3013 spec = os.path.normpath(os.path.join(os.getcwd(), path))
3014 rootdir = repo.root + os.sep
3014 rootdir = repo.root + os.sep
3015 if spec != repo.root and not spec.startswith(rootdir):
3015 if spec != repo.root and not spec.startswith(rootdir):
3016 return [], []
3016 return [], []
3017 if os.path.isdir(spec):
3017 if os.path.isdir(spec):
3018 spec += '/'
3018 spec += '/'
3019 spec = spec[len(rootdir):]
3019 spec = spec[len(rootdir):]
3020 fixpaths = os.sep != '/'
3020 fixpaths = os.sep != '/'
3021 if fixpaths:
3021 if fixpaths:
3022 spec = spec.replace(os.sep, '/')
3022 spec = spec.replace(os.sep, '/')
3023 speclen = len(spec)
3023 speclen = len(spec)
3024 fullpaths = opts['full']
3024 fullpaths = opts['full']
3025 files, dirs = set(), set()
3025 files, dirs = set(), set()
3026 adddir, addfile = dirs.add, files.add
3026 adddir, addfile = dirs.add, files.add
3027 for f, st in dirstate.iteritems():
3027 for f, st in dirstate.iteritems():
3028 if f.startswith(spec) and st[0] in acceptable:
3028 if f.startswith(spec) and st[0] in acceptable:
3029 if fixpaths:
3029 if fixpaths:
3030 f = f.replace('/', os.sep)
3030 f = f.replace('/', os.sep)
3031 if fullpaths:
3031 if fullpaths:
3032 addfile(f)
3032 addfile(f)
3033 continue
3033 continue
3034 s = f.find(os.sep, speclen)
3034 s = f.find(os.sep, speclen)
3035 if s >= 0:
3035 if s >= 0:
3036 adddir(f[:s])
3036 adddir(f[:s])
3037 else:
3037 else:
3038 addfile(f)
3038 addfile(f)
3039 return files, dirs
3039 return files, dirs
3040
3040
3041 acceptable = ''
3041 acceptable = ''
3042 if opts['normal']:
3042 if opts['normal']:
3043 acceptable += 'nm'
3043 acceptable += 'nm'
3044 if opts['added']:
3044 if opts['added']:
3045 acceptable += 'a'
3045 acceptable += 'a'
3046 if opts['removed']:
3046 if opts['removed']:
3047 acceptable += 'r'
3047 acceptable += 'r'
3048 cwd = repo.getcwd()
3048 cwd = repo.getcwd()
3049 if not specs:
3049 if not specs:
3050 specs = ['.']
3050 specs = ['.']
3051
3051
3052 files, dirs = set(), set()
3052 files, dirs = set(), set()
3053 for spec in specs:
3053 for spec in specs:
3054 f, d = complete(spec, acceptable or 'nmar')
3054 f, d = complete(spec, acceptable or 'nmar')
3055 files.update(f)
3055 files.update(f)
3056 dirs.update(d)
3056 dirs.update(d)
3057 files.update(dirs)
3057 files.update(dirs)
3058 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3058 ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
3059 ui.write('\n')
3059 ui.write('\n')
3060
3060
3061 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3061 @command('debugpushkey', [], _('REPO NAMESPACE [KEY OLD NEW]'), norepo=True)
3062 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3062 def debugpushkey(ui, repopath, namespace, *keyinfo, **opts):
3063 '''access the pushkey key/value protocol
3063 '''access the pushkey key/value protocol
3064
3064
3065 With two args, list the keys in the given namespace.
3065 With two args, list the keys in the given namespace.
3066
3066
3067 With five args, set a key to new if it currently is set to old.
3067 With five args, set a key to new if it currently is set to old.
3068 Reports success or failure.
3068 Reports success or failure.
3069 '''
3069 '''
3070
3070
3071 target = hg.peer(ui, {}, repopath)
3071 target = hg.peer(ui, {}, repopath)
3072 if keyinfo:
3072 if keyinfo:
3073 key, old, new = keyinfo
3073 key, old, new = keyinfo
3074 r = target.pushkey(namespace, key, old, new)
3074 r = target.pushkey(namespace, key, old, new)
3075 ui.status(str(r) + '\n')
3075 ui.status(str(r) + '\n')
3076 return not r
3076 return not r
3077 else:
3077 else:
3078 for k, v in sorted(target.listkeys(namespace).iteritems()):
3078 for k, v in sorted(target.listkeys(namespace).iteritems()):
3079 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3079 ui.write("%s\t%s\n" % (k.encode('string-escape'),
3080 v.encode('string-escape')))
3080 v.encode('string-escape')))
3081
3081
3082 @command('debugpvec', [], _('A B'))
3082 @command('debugpvec', [], _('A B'))
3083 def debugpvec(ui, repo, a, b=None):
3083 def debugpvec(ui, repo, a, b=None):
3084 ca = scmutil.revsingle(repo, a)
3084 ca = scmutil.revsingle(repo, a)
3085 cb = scmutil.revsingle(repo, b)
3085 cb = scmutil.revsingle(repo, b)
3086 pa = pvec.ctxpvec(ca)
3086 pa = pvec.ctxpvec(ca)
3087 pb = pvec.ctxpvec(cb)
3087 pb = pvec.ctxpvec(cb)
3088 if pa == pb:
3088 if pa == pb:
3089 rel = "="
3089 rel = "="
3090 elif pa > pb:
3090 elif pa > pb:
3091 rel = ">"
3091 rel = ">"
3092 elif pa < pb:
3092 elif pa < pb:
3093 rel = "<"
3093 rel = "<"
3094 elif pa | pb:
3094 elif pa | pb:
3095 rel = "|"
3095 rel = "|"
3096 ui.write(_("a: %s\n") % pa)
3096 ui.write(_("a: %s\n") % pa)
3097 ui.write(_("b: %s\n") % pb)
3097 ui.write(_("b: %s\n") % pb)
3098 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3098 ui.write(_("depth(a): %d depth(b): %d\n") % (pa._depth, pb._depth))
3099 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3099 ui.write(_("delta: %d hdist: %d distance: %d relation: %s\n") %
3100 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3100 (abs(pa._depth - pb._depth), pvec._hamming(pa._vec, pb._vec),
3101 pa.distance(pb), rel))
3101 pa.distance(pb), rel))
3102
3102
3103 @command('debugrebuilddirstate|debugrebuildstate',
3103 @command('debugrebuilddirstate|debugrebuildstate',
3104 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3104 [('r', 'rev', '', _('revision to rebuild to'), _('REV')),
3105 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3105 ('', 'minimal', None, _('only rebuild files that are inconsistent with '
3106 'the working copy parent')),
3106 'the working copy parent')),
3107 ],
3107 ],
3108 _('[-r REV]'))
3108 _('[-r REV]'))
3109 def debugrebuilddirstate(ui, repo, rev, **opts):
3109 def debugrebuilddirstate(ui, repo, rev, **opts):
3110 """rebuild the dirstate as it would look like for the given revision
3110 """rebuild the dirstate as it would look like for the given revision
3111
3111
3112 If no revision is specified the first current parent will be used.
3112 If no revision is specified the first current parent will be used.
3113
3113
3114 The dirstate will be set to the files of the given revision.
3114 The dirstate will be set to the files of the given revision.
3115 The actual working directory content or existing dirstate
3115 The actual working directory content or existing dirstate
3116 information such as adds or removes is not considered.
3116 information such as adds or removes is not considered.
3117
3117
3118 ``minimal`` will only rebuild the dirstate status for files that claim to be
3118 ``minimal`` will only rebuild the dirstate status for files that claim to be
3119 tracked but are not in the parent manifest, or that exist in the parent
3119 tracked but are not in the parent manifest, or that exist in the parent
3120 manifest but are not in the dirstate. It will not change adds, removes, or
3120 manifest but are not in the dirstate. It will not change adds, removes, or
3121 modified files that are in the working copy parent.
3121 modified files that are in the working copy parent.
3122
3122
3123 One use of this command is to make the next :hg:`status` invocation
3123 One use of this command is to make the next :hg:`status` invocation
3124 check the actual file content.
3124 check the actual file content.
3125 """
3125 """
3126 ctx = scmutil.revsingle(repo, rev)
3126 ctx = scmutil.revsingle(repo, rev)
3127 with repo.wlock():
3127 with repo.wlock():
3128 dirstate = repo.dirstate
3128 dirstate = repo.dirstate
3129 changedfiles = None
3129 changedfiles = None
3130 # See command doc for what minimal does.
3130 # See command doc for what minimal does.
3131 if opts.get('minimal'):
3131 if opts.get('minimal'):
3132 manifestfiles = set(ctx.manifest().keys())
3132 manifestfiles = set(ctx.manifest().keys())
3133 dirstatefiles = set(dirstate)
3133 dirstatefiles = set(dirstate)
3134 manifestonly = manifestfiles - dirstatefiles
3134 manifestonly = manifestfiles - dirstatefiles
3135 dsonly = dirstatefiles - manifestfiles
3135 dsonly = dirstatefiles - manifestfiles
3136 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3136 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3137 changedfiles = manifestonly | dsnotadded
3137 changedfiles = manifestonly | dsnotadded
3138
3138
3139 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3139 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3140
3140
3141 @command('debugrebuildfncache', [], '')
3141 @command('debugrebuildfncache', [], '')
3142 def debugrebuildfncache(ui, repo):
3142 def debugrebuildfncache(ui, repo):
3143 """rebuild the fncache file"""
3143 """rebuild the fncache file"""
3144 repair.rebuildfncache(ui, repo)
3144 repair.rebuildfncache(ui, repo)
3145
3145
3146 @command('debugrename',
3146 @command('debugrename',
3147 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3147 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3148 _('[-r REV] FILE'))
3148 _('[-r REV] FILE'))
3149 def debugrename(ui, repo, file1, *pats, **opts):
3149 def debugrename(ui, repo, file1, *pats, **opts):
3150 """dump rename information"""
3150 """dump rename information"""
3151
3151
3152 ctx = scmutil.revsingle(repo, opts.get('rev'))
3152 ctx = scmutil.revsingle(repo, opts.get('rev'))
3153 m = scmutil.match(ctx, (file1,) + pats, opts)
3153 m = scmutil.match(ctx, (file1,) + pats, opts)
3154 for abs in ctx.walk(m):
3154 for abs in ctx.walk(m):
3155 fctx = ctx[abs]
3155 fctx = ctx[abs]
3156 o = fctx.filelog().renamed(fctx.filenode())
3156 o = fctx.filelog().renamed(fctx.filenode())
3157 rel = m.rel(abs)
3157 rel = m.rel(abs)
3158 if o:
3158 if o:
3159 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3159 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
3160 else:
3160 else:
3161 ui.write(_("%s not renamed\n") % rel)
3161 ui.write(_("%s not renamed\n") % rel)
3162
3162
3163 @command('debugrevlog', debugrevlogopts +
3163 @command('debugrevlog', debugrevlogopts +
3164 [('d', 'dump', False, _('dump index data'))],
3164 [('d', 'dump', False, _('dump index data'))],
3165 _('-c|-m|FILE'),
3165 _('-c|-m|FILE'),
3166 optionalrepo=True)
3166 optionalrepo=True)
3167 def debugrevlog(ui, repo, file_=None, **opts):
3167 def debugrevlog(ui, repo, file_=None, **opts):
3168 """show data and statistics about a revlog"""
3168 """show data and statistics about a revlog"""
3169 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3169 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3170
3170
3171 if opts.get("dump"):
3171 if opts.get("dump"):
3172 numrevs = len(r)
3172 numrevs = len(r)
3173 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3173 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3174 " rawsize totalsize compression heads chainlen\n")
3174 " rawsize totalsize compression heads chainlen\n")
3175 ts = 0
3175 ts = 0
3176 heads = set()
3176 heads = set()
3177
3177
3178 for rev in xrange(numrevs):
3178 for rev in xrange(numrevs):
3179 dbase = r.deltaparent(rev)
3179 dbase = r.deltaparent(rev)
3180 if dbase == -1:
3180 if dbase == -1:
3181 dbase = rev
3181 dbase = rev
3182 cbase = r.chainbase(rev)
3182 cbase = r.chainbase(rev)
3183 clen = r.chainlen(rev)
3183 clen = r.chainlen(rev)
3184 p1, p2 = r.parentrevs(rev)
3184 p1, p2 = r.parentrevs(rev)
3185 rs = r.rawsize(rev)
3185 rs = r.rawsize(rev)
3186 ts = ts + rs
3186 ts = ts + rs
3187 heads -= set(r.parentrevs(rev))
3187 heads -= set(r.parentrevs(rev))
3188 heads.add(rev)
3188 heads.add(rev)
3189 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3189 ui.write("%5d %5d %5d %5d %5d %10d %4d %4d %4d %7d %9d "
3190 "%11d %5d %8d\n" %
3190 "%11d %5d %8d\n" %
3191 (rev, p1, p2, r.start(rev), r.end(rev),
3191 (rev, p1, p2, r.start(rev), r.end(rev),
3192 r.start(dbase), r.start(cbase),
3192 r.start(dbase), r.start(cbase),
3193 r.start(p1), r.start(p2),
3193 r.start(p1), r.start(p2),
3194 rs, ts, ts / r.end(rev), len(heads), clen))
3194 rs, ts, ts / r.end(rev), len(heads), clen))
3195 return 0
3195 return 0
3196
3196
3197 v = r.version
3197 v = r.version
3198 format = v & 0xFFFF
3198 format = v & 0xFFFF
3199 flags = []
3199 flags = []
3200 gdelta = False
3200 gdelta = False
3201 if v & revlog.REVLOGNGINLINEDATA:
3201 if v & revlog.REVLOGNGINLINEDATA:
3202 flags.append('inline')
3202 flags.append('inline')
3203 if v & revlog.REVLOGGENERALDELTA:
3203 if v & revlog.REVLOGGENERALDELTA:
3204 gdelta = True
3204 gdelta = True
3205 flags.append('generaldelta')
3205 flags.append('generaldelta')
3206 if not flags:
3206 if not flags:
3207 flags = ['(none)']
3207 flags = ['(none)']
3208
3208
3209 nummerges = 0
3209 nummerges = 0
3210 numfull = 0
3210 numfull = 0
3211 numprev = 0
3211 numprev = 0
3212 nump1 = 0
3212 nump1 = 0
3213 nump2 = 0
3213 nump2 = 0
3214 numother = 0
3214 numother = 0
3215 nump1prev = 0
3215 nump1prev = 0
3216 nump2prev = 0
3216 nump2prev = 0
3217 chainlengths = []
3217 chainlengths = []
3218
3218
3219 datasize = [None, 0, 0L]
3219 datasize = [None, 0, 0L]
3220 fullsize = [None, 0, 0L]
3220 fullsize = [None, 0, 0L]
3221 deltasize = [None, 0, 0L]
3221 deltasize = [None, 0, 0L]
3222
3222
3223 def addsize(size, l):
3223 def addsize(size, l):
3224 if l[0] is None or size < l[0]:
3224 if l[0] is None or size < l[0]:
3225 l[0] = size
3225 l[0] = size
3226 if size > l[1]:
3226 if size > l[1]:
3227 l[1] = size
3227 l[1] = size
3228 l[2] += size
3228 l[2] += size
3229
3229
3230 numrevs = len(r)
3230 numrevs = len(r)
3231 for rev in xrange(numrevs):
3231 for rev in xrange(numrevs):
3232 p1, p2 = r.parentrevs(rev)
3232 p1, p2 = r.parentrevs(rev)
3233 delta = r.deltaparent(rev)
3233 delta = r.deltaparent(rev)
3234 if format > 0:
3234 if format > 0:
3235 addsize(r.rawsize(rev), datasize)
3235 addsize(r.rawsize(rev), datasize)
3236 if p2 != nullrev:
3236 if p2 != nullrev:
3237 nummerges += 1
3237 nummerges += 1
3238 size = r.length(rev)
3238 size = r.length(rev)
3239 if delta == nullrev:
3239 if delta == nullrev:
3240 chainlengths.append(0)
3240 chainlengths.append(0)
3241 numfull += 1
3241 numfull += 1
3242 addsize(size, fullsize)
3242 addsize(size, fullsize)
3243 else:
3243 else:
3244 chainlengths.append(chainlengths[delta] + 1)
3244 chainlengths.append(chainlengths[delta] + 1)
3245 addsize(size, deltasize)
3245 addsize(size, deltasize)
3246 if delta == rev - 1:
3246 if delta == rev - 1:
3247 numprev += 1
3247 numprev += 1
3248 if delta == p1:
3248 if delta == p1:
3249 nump1prev += 1
3249 nump1prev += 1
3250 elif delta == p2:
3250 elif delta == p2:
3251 nump2prev += 1
3251 nump2prev += 1
3252 elif delta == p1:
3252 elif delta == p1:
3253 nump1 += 1
3253 nump1 += 1
3254 elif delta == p2:
3254 elif delta == p2:
3255 nump2 += 1
3255 nump2 += 1
3256 elif delta != nullrev:
3256 elif delta != nullrev:
3257 numother += 1
3257 numother += 1
3258
3258
3259 # Adjust size min value for empty cases
3259 # Adjust size min value for empty cases
3260 for size in (datasize, fullsize, deltasize):
3260 for size in (datasize, fullsize, deltasize):
3261 if size[0] is None:
3261 if size[0] is None:
3262 size[0] = 0
3262 size[0] = 0
3263
3263
3264 numdeltas = numrevs - numfull
3264 numdeltas = numrevs - numfull
3265 numoprev = numprev - nump1prev - nump2prev
3265 numoprev = numprev - nump1prev - nump2prev
3266 totalrawsize = datasize[2]
3266 totalrawsize = datasize[2]
3267 datasize[2] /= numrevs
3267 datasize[2] /= numrevs
3268 fulltotal = fullsize[2]
3268 fulltotal = fullsize[2]
3269 fullsize[2] /= numfull
3269 fullsize[2] /= numfull
3270 deltatotal = deltasize[2]
3270 deltatotal = deltasize[2]
3271 if numrevs - numfull > 0:
3271 if numrevs - numfull > 0:
3272 deltasize[2] /= numrevs - numfull
3272 deltasize[2] /= numrevs - numfull
3273 totalsize = fulltotal + deltatotal
3273 totalsize = fulltotal + deltatotal
3274 avgchainlen = sum(chainlengths) / numrevs
3274 avgchainlen = sum(chainlengths) / numrevs
3275 maxchainlen = max(chainlengths)
3275 maxchainlen = max(chainlengths)
3276 compratio = 1
3276 compratio = 1
3277 if totalsize:
3277 if totalsize:
3278 compratio = totalrawsize / totalsize
3278 compratio = totalrawsize / totalsize
3279
3279
3280 basedfmtstr = '%%%dd\n'
3280 basedfmtstr = '%%%dd\n'
3281 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3281 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3282
3282
3283 def dfmtstr(max):
3283 def dfmtstr(max):
3284 return basedfmtstr % len(str(max))
3284 return basedfmtstr % len(str(max))
3285 def pcfmtstr(max, padding=0):
3285 def pcfmtstr(max, padding=0):
3286 return basepcfmtstr % (len(str(max)), ' ' * padding)
3286 return basepcfmtstr % (len(str(max)), ' ' * padding)
3287
3287
3288 def pcfmt(value, total):
3288 def pcfmt(value, total):
3289 if total:
3289 if total:
3290 return (value, 100 * float(value) / total)
3290 return (value, 100 * float(value) / total)
3291 else:
3291 else:
3292 return value, 100.0
3292 return value, 100.0
3293
3293
3294 ui.write(('format : %d\n') % format)
3294 ui.write(('format : %d\n') % format)
3295 ui.write(('flags : %s\n') % ', '.join(flags))
3295 ui.write(('flags : %s\n') % ', '.join(flags))
3296
3296
3297 ui.write('\n')
3297 ui.write('\n')
3298 fmt = pcfmtstr(totalsize)
3298 fmt = pcfmtstr(totalsize)
3299 fmt2 = dfmtstr(totalsize)
3299 fmt2 = dfmtstr(totalsize)
3300 ui.write(('revisions : ') + fmt2 % numrevs)
3300 ui.write(('revisions : ') + fmt2 % numrevs)
3301 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3301 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3302 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3302 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3303 ui.write(('revisions : ') + fmt2 % numrevs)
3303 ui.write(('revisions : ') + fmt2 % numrevs)
3304 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3304 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3305 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3305 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3306 ui.write(('revision size : ') + fmt2 % totalsize)
3306 ui.write(('revision size : ') + fmt2 % totalsize)
3307 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3307 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3308 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3308 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3309
3309
3310 ui.write('\n')
3310 ui.write('\n')
3311 fmt = dfmtstr(max(avgchainlen, compratio))
3311 fmt = dfmtstr(max(avgchainlen, compratio))
3312 ui.write(('avg chain length : ') + fmt % avgchainlen)
3312 ui.write(('avg chain length : ') + fmt % avgchainlen)
3313 ui.write(('max chain length : ') + fmt % maxchainlen)
3313 ui.write(('max chain length : ') + fmt % maxchainlen)
3314 ui.write(('compression ratio : ') + fmt % compratio)
3314 ui.write(('compression ratio : ') + fmt % compratio)
3315
3315
3316 if format > 0:
3316 if format > 0:
3317 ui.write('\n')
3317 ui.write('\n')
3318 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3318 ui.write(('uncompressed data size (min/max/avg) : %d / %d / %d\n')
3319 % tuple(datasize))
3319 % tuple(datasize))
3320 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3320 ui.write(('full revision size (min/max/avg) : %d / %d / %d\n')
3321 % tuple(fullsize))
3321 % tuple(fullsize))
3322 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3322 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3323 % tuple(deltasize))
3323 % tuple(deltasize))
3324
3324
3325 if numdeltas > 0:
3325 if numdeltas > 0:
3326 ui.write('\n')
3326 ui.write('\n')
3327 fmt = pcfmtstr(numdeltas)
3327 fmt = pcfmtstr(numdeltas)
3328 fmt2 = pcfmtstr(numdeltas, 4)
3328 fmt2 = pcfmtstr(numdeltas, 4)
3329 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3329 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3330 if numprev > 0:
3330 if numprev > 0:
3331 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3331 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3332 numprev))
3332 numprev))
3333 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3333 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3334 numprev))
3334 numprev))
3335 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3335 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3336 numprev))
3336 numprev))
3337 if gdelta:
3337 if gdelta:
3338 ui.write(('deltas against p1 : ')
3338 ui.write(('deltas against p1 : ')
3339 + fmt % pcfmt(nump1, numdeltas))
3339 + fmt % pcfmt(nump1, numdeltas))
3340 ui.write(('deltas against p2 : ')
3340 ui.write(('deltas against p2 : ')
3341 + fmt % pcfmt(nump2, numdeltas))
3341 + fmt % pcfmt(nump2, numdeltas))
3342 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3342 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3343 numdeltas))
3343 numdeltas))
3344
3344
3345 @command('debugrevspec',
3345 @command('debugrevspec',
3346 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3346 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3347 ('REVSPEC'))
3347 ('REVSPEC'))
3348 def debugrevspec(ui, repo, expr, **opts):
3348 def debugrevspec(ui, repo, expr, **opts):
3349 """parse and apply a revision specification
3349 """parse and apply a revision specification
3350
3350
3351 Use --verbose to print the parsed tree before and after aliases
3351 Use --verbose to print the parsed tree before and after aliases
3352 expansion.
3352 expansion.
3353 """
3353 """
3354 if ui.verbose:
3354 if ui.verbose:
3355 tree = revset.parse(expr, lookup=repo.__contains__)
3355 tree = revset.parse(expr, lookup=repo.__contains__)
3356 ui.note(revset.prettyformat(tree), "\n")
3356 ui.note(revset.prettyformat(tree), "\n")
3357 newtree = revset.findaliases(ui, tree)
3357 newtree = revset.findaliases(ui, tree)
3358 if newtree != tree:
3358 if newtree != tree:
3359 ui.note(revset.prettyformat(newtree), "\n")
3359 ui.note(revset.prettyformat(newtree), "\n")
3360 tree = newtree
3360 tree = newtree
3361 newtree = revset.foldconcat(tree)
3361 newtree = revset.foldconcat(tree)
3362 if newtree != tree:
3362 if newtree != tree:
3363 ui.note(revset.prettyformat(newtree), "\n")
3363 ui.note(revset.prettyformat(newtree), "\n")
3364 if opts["optimize"]:
3364 if opts["optimize"]:
3365 weight, optimizedtree = revset.optimize(newtree, True)
3365 weight, optimizedtree = revset.optimize(newtree, True)
3366 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3366 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3367 func = revset.match(ui, expr, repo)
3367 func = revset.match(ui, expr, repo)
3368 revs = func(repo)
3368 revs = func(repo)
3369 if ui.verbose:
3369 if ui.verbose:
3370 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3370 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3371 for c in revs:
3371 for c in revs:
3372 ui.write("%s\n" % c)
3372 ui.write("%s\n" % c)
3373
3373
3374 @command('debugsetparents', [], _('REV1 [REV2]'))
3374 @command('debugsetparents', [], _('REV1 [REV2]'))
3375 def debugsetparents(ui, repo, rev1, rev2=None):
3375 def debugsetparents(ui, repo, rev1, rev2=None):
3376 """manually set the parents of the current working directory
3376 """manually set the parents of the current working directory
3377
3377
3378 This is useful for writing repository conversion tools, but should
3378 This is useful for writing repository conversion tools, but should
3379 be used with care. For example, neither the working directory nor the
3379 be used with care. For example, neither the working directory nor the
3380 dirstate is updated, so file status may be incorrect after running this
3380 dirstate is updated, so file status may be incorrect after running this
3381 command.
3381 command.
3382
3382
3383 Returns 0 on success.
3383 Returns 0 on success.
3384 """
3384 """
3385
3385
3386 r1 = scmutil.revsingle(repo, rev1).node()
3386 r1 = scmutil.revsingle(repo, rev1).node()
3387 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3387 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3388
3388
3389 with repo.wlock():
3389 with repo.wlock():
3390 repo.dirstate.beginparentchange()
3390 repo.dirstate.beginparentchange()
3391 repo.setparents(r1, r2)
3391 repo.setparents(r1, r2)
3392 repo.dirstate.endparentchange()
3392 repo.dirstate.endparentchange()
3393
3393
3394 @command('debugdirstate|debugstate',
3394 @command('debugdirstate|debugstate',
3395 [('', 'nodates', None, _('do not display the saved mtime')),
3395 [('', 'nodates', None, _('do not display the saved mtime')),
3396 ('', 'datesort', None, _('sort by saved mtime'))],
3396 ('', 'datesort', None, _('sort by saved mtime'))],
3397 _('[OPTION]...'))
3397 _('[OPTION]...'))
3398 def debugstate(ui, repo, **opts):
3398 def debugstate(ui, repo, **opts):
3399 """show the contents of the current dirstate"""
3399 """show the contents of the current dirstate"""
3400
3400
3401 nodates = opts.get('nodates')
3401 nodates = opts.get('nodates')
3402 datesort = opts.get('datesort')
3402 datesort = opts.get('datesort')
3403
3403
3404 timestr = ""
3404 timestr = ""
3405 if datesort:
3405 if datesort:
3406 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3406 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3407 else:
3407 else:
3408 keyfunc = None # sort by filename
3408 keyfunc = None # sort by filename
3409 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3409 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3410 if ent[3] == -1:
3410 if ent[3] == -1:
3411 timestr = 'unset '
3411 timestr = 'unset '
3412 elif nodates:
3412 elif nodates:
3413 timestr = 'set '
3413 timestr = 'set '
3414 else:
3414 else:
3415 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3415 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3416 time.localtime(ent[3]))
3416 time.localtime(ent[3]))
3417 if ent[1] & 0o20000:
3417 if ent[1] & 0o20000:
3418 mode = 'lnk'
3418 mode = 'lnk'
3419 else:
3419 else:
3420 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3420 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3421 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3421 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3422 for f in repo.dirstate.copies():
3422 for f in repo.dirstate.copies():
3423 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3423 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3424
3424
3425 @command('debugsub',
3425 @command('debugsub',
3426 [('r', 'rev', '',
3426 [('r', 'rev', '',
3427 _('revision to check'), _('REV'))],
3427 _('revision to check'), _('REV'))],
3428 _('[-r REV] [REV]'))
3428 _('[-r REV] [REV]'))
3429 def debugsub(ui, repo, rev=None):
3429 def debugsub(ui, repo, rev=None):
3430 ctx = scmutil.revsingle(repo, rev, None)
3430 ctx = scmutil.revsingle(repo, rev, None)
3431 for k, v in sorted(ctx.substate.items()):
3431 for k, v in sorted(ctx.substate.items()):
3432 ui.write(('path %s\n') % k)
3432 ui.write(('path %s\n') % k)
3433 ui.write((' source %s\n') % v[0])
3433 ui.write((' source %s\n') % v[0])
3434 ui.write((' revision %s\n') % v[1])
3434 ui.write((' revision %s\n') % v[1])
3435
3435
3436 @command('debugsuccessorssets',
3436 @command('debugsuccessorssets',
3437 [],
3437 [],
3438 _('[REV]'))
3438 _('[REV]'))
3439 def debugsuccessorssets(ui, repo, *revs):
3439 def debugsuccessorssets(ui, repo, *revs):
3440 """show set of successors for revision
3440 """show set of successors for revision
3441
3441
3442 A successors set of changeset A is a consistent group of revisions that
3442 A successors set of changeset A is a consistent group of revisions that
3443 succeed A. It contains non-obsolete changesets only.
3443 succeed A. It contains non-obsolete changesets only.
3444
3444
3445 In most cases a changeset A has a single successors set containing a single
3445 In most cases a changeset A has a single successors set containing a single
3446 successor (changeset A replaced by A').
3446 successor (changeset A replaced by A').
3447
3447
3448 A changeset that is made obsolete with no successors are called "pruned".
3448 A changeset that is made obsolete with no successors are called "pruned".
3449 Such changesets have no successors sets at all.
3449 Such changesets have no successors sets at all.
3450
3450
3451 A changeset that has been "split" will have a successors set containing
3451 A changeset that has been "split" will have a successors set containing
3452 more than one successor.
3452 more than one successor.
3453
3453
3454 A changeset that has been rewritten in multiple different ways is called
3454 A changeset that has been rewritten in multiple different ways is called
3455 "divergent". Such changesets have multiple successor sets (each of which
3455 "divergent". Such changesets have multiple successor sets (each of which
3456 may also be split, i.e. have multiple successors).
3456 may also be split, i.e. have multiple successors).
3457
3457
3458 Results are displayed as follows::
3458 Results are displayed as follows::
3459
3459
3460 <rev1>
3460 <rev1>
3461 <successors-1A>
3461 <successors-1A>
3462 <rev2>
3462 <rev2>
3463 <successors-2A>
3463 <successors-2A>
3464 <successors-2B1> <successors-2B2> <successors-2B3>
3464 <successors-2B1> <successors-2B2> <successors-2B3>
3465
3465
3466 Here rev2 has two possible (i.e. divergent) successors sets. The first
3466 Here rev2 has two possible (i.e. divergent) successors sets. The first
3467 holds one element, whereas the second holds three (i.e. the changeset has
3467 holds one element, whereas the second holds three (i.e. the changeset has
3468 been split).
3468 been split).
3469 """
3469 """
3470 # passed to successorssets caching computation from one call to another
3470 # passed to successorssets caching computation from one call to another
3471 cache = {}
3471 cache = {}
3472 ctx2str = str
3472 ctx2str = str
3473 node2str = short
3473 node2str = short
3474 if ui.debug():
3474 if ui.debug():
3475 def ctx2str(ctx):
3475 def ctx2str(ctx):
3476 return ctx.hex()
3476 return ctx.hex()
3477 node2str = hex
3477 node2str = hex
3478 for rev in scmutil.revrange(repo, revs):
3478 for rev in scmutil.revrange(repo, revs):
3479 ctx = repo[rev]
3479 ctx = repo[rev]
3480 ui.write('%s\n'% ctx2str(ctx))
3480 ui.write('%s\n'% ctx2str(ctx))
3481 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3481 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3482 if succsset:
3482 if succsset:
3483 ui.write(' ')
3483 ui.write(' ')
3484 ui.write(node2str(succsset[0]))
3484 ui.write(node2str(succsset[0]))
3485 for node in succsset[1:]:
3485 for node in succsset[1:]:
3486 ui.write(' ')
3486 ui.write(' ')
3487 ui.write(node2str(node))
3487 ui.write(node2str(node))
3488 ui.write('\n')
3488 ui.write('\n')
3489
3489
3490 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3490 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3491 def debugwalk(ui, repo, *pats, **opts):
3491 def debugwalk(ui, repo, *pats, **opts):
3492 """show how files match on given patterns"""
3492 """show how files match on given patterns"""
3493 m = scmutil.match(repo[None], pats, opts)
3493 m = scmutil.match(repo[None], pats, opts)
3494 items = list(repo.walk(m))
3494 items = list(repo.walk(m))
3495 if not items:
3495 if not items:
3496 return
3496 return
3497 f = lambda fn: fn
3497 f = lambda fn: fn
3498 if ui.configbool('ui', 'slash') and os.sep != '/':
3498 if ui.configbool('ui', 'slash') and os.sep != '/':
3499 f = lambda fn: util.normpath(fn)
3499 f = lambda fn: util.normpath(fn)
3500 fmt = 'f %%-%ds %%-%ds %%s' % (
3500 fmt = 'f %%-%ds %%-%ds %%s' % (
3501 max([len(abs) for abs in items]),
3501 max([len(abs) for abs in items]),
3502 max([len(m.rel(abs)) for abs in items]))
3502 max([len(m.rel(abs)) for abs in items]))
3503 for abs in items:
3503 for abs in items:
3504 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3504 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3505 ui.write("%s\n" % line.rstrip())
3505 ui.write("%s\n" % line.rstrip())
3506
3506
3507 @command('debugwireargs',
3507 @command('debugwireargs',
3508 [('', 'three', '', 'three'),
3508 [('', 'three', '', 'three'),
3509 ('', 'four', '', 'four'),
3509 ('', 'four', '', 'four'),
3510 ('', 'five', '', 'five'),
3510 ('', 'five', '', 'five'),
3511 ] + remoteopts,
3511 ] + remoteopts,
3512 _('REPO [OPTIONS]... [ONE [TWO]]'),
3512 _('REPO [OPTIONS]... [ONE [TWO]]'),
3513 norepo=True)
3513 norepo=True)
3514 def debugwireargs(ui, repopath, *vals, **opts):
3514 def debugwireargs(ui, repopath, *vals, **opts):
3515 repo = hg.peer(ui, opts, repopath)
3515 repo = hg.peer(ui, opts, repopath)
3516 for opt in remoteopts:
3516 for opt in remoteopts:
3517 del opts[opt[1]]
3517 del opts[opt[1]]
3518 args = {}
3518 args = {}
3519 for k, v in opts.iteritems():
3519 for k, v in opts.iteritems():
3520 if v:
3520 if v:
3521 args[k] = v
3521 args[k] = v
3522 # run twice to check that we don't mess up the stream for the next command
3522 # run twice to check that we don't mess up the stream for the next command
3523 res1 = repo.debugwireargs(*vals, **args)
3523 res1 = repo.debugwireargs(*vals, **args)
3524 res2 = repo.debugwireargs(*vals, **args)
3524 res2 = repo.debugwireargs(*vals, **args)
3525 ui.write("%s\n" % res1)
3525 ui.write("%s\n" % res1)
3526 if res1 != res2:
3526 if res1 != res2:
3527 ui.warn("%s\n" % res2)
3527 ui.warn("%s\n" % res2)
3528
3528
3529 @command('^diff',
3529 @command('^diff',
3530 [('r', 'rev', [], _('revision'), _('REV')),
3530 [('r', 'rev', [], _('revision'), _('REV')),
3531 ('c', 'change', '', _('change made by revision'), _('REV'))
3531 ('c', 'change', '', _('change made by revision'), _('REV'))
3532 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3532 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3533 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3533 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3534 inferrepo=True)
3534 inferrepo=True)
3535 def diff(ui, repo, *pats, **opts):
3535 def diff(ui, repo, *pats, **opts):
3536 """diff repository (or selected files)
3536 """diff repository (or selected files)
3537
3537
3538 Show differences between revisions for the specified files.
3538 Show differences between revisions for the specified files.
3539
3539
3540 Differences between files are shown using the unified diff format.
3540 Differences between files are shown using the unified diff format.
3541
3541
3542 .. note::
3542 .. note::
3543
3543
3544 :hg:`diff` may generate unexpected results for merges, as it will
3544 :hg:`diff` may generate unexpected results for merges, as it will
3545 default to comparing against the working directory's first
3545 default to comparing against the working directory's first
3546 parent changeset if no revisions are specified.
3546 parent changeset if no revisions are specified.
3547
3547
3548 When two revision arguments are given, then changes are shown
3548 When two revision arguments are given, then changes are shown
3549 between those revisions. If only one revision is specified then
3549 between those revisions. If only one revision is specified then
3550 that revision is compared to the working directory, and, when no
3550 that revision is compared to the working directory, and, when no
3551 revisions are specified, the working directory files are compared
3551 revisions are specified, the working directory files are compared
3552 to its first parent.
3552 to its first parent.
3553
3553
3554 Alternatively you can specify -c/--change with a revision to see
3554 Alternatively you can specify -c/--change with a revision to see
3555 the changes in that changeset relative to its first parent.
3555 the changes in that changeset relative to its first parent.
3556
3556
3557 Without the -a/--text option, diff will avoid generating diffs of
3557 Without the -a/--text option, diff will avoid generating diffs of
3558 files it detects as binary. With -a, diff will generate a diff
3558 files it detects as binary. With -a, diff will generate a diff
3559 anyway, probably with undesirable results.
3559 anyway, probably with undesirable results.
3560
3560
3561 Use the -g/--git option to generate diffs in the git extended diff
3561 Use the -g/--git option to generate diffs in the git extended diff
3562 format. For more information, read :hg:`help diffs`.
3562 format. For more information, read :hg:`help diffs`.
3563
3563
3564 .. container:: verbose
3564 .. container:: verbose
3565
3565
3566 Examples:
3566 Examples:
3567
3567
3568 - compare a file in the current working directory to its parent::
3568 - compare a file in the current working directory to its parent::
3569
3569
3570 hg diff foo.c
3570 hg diff foo.c
3571
3571
3572 - compare two historical versions of a directory, with rename info::
3572 - compare two historical versions of a directory, with rename info::
3573
3573
3574 hg diff --git -r 1.0:1.2 lib/
3574 hg diff --git -r 1.0:1.2 lib/
3575
3575
3576 - get change stats relative to the last change on some date::
3576 - get change stats relative to the last change on some date::
3577
3577
3578 hg diff --stat -r "date('may 2')"
3578 hg diff --stat -r "date('may 2')"
3579
3579
3580 - diff all newly-added files that contain a keyword::
3580 - diff all newly-added files that contain a keyword::
3581
3581
3582 hg diff "set:added() and grep(GNU)"
3582 hg diff "set:added() and grep(GNU)"
3583
3583
3584 - compare a revision and its parents::
3584 - compare a revision and its parents::
3585
3585
3586 hg diff -c 9353 # compare against first parent
3586 hg diff -c 9353 # compare against first parent
3587 hg diff -r 9353^:9353 # same using revset syntax
3587 hg diff -r 9353^:9353 # same using revset syntax
3588 hg diff -r 9353^2:9353 # compare against the second parent
3588 hg diff -r 9353^2:9353 # compare against the second parent
3589
3589
3590 Returns 0 on success.
3590 Returns 0 on success.
3591 """
3591 """
3592
3592
3593 revs = opts.get('rev')
3593 revs = opts.get('rev')
3594 change = opts.get('change')
3594 change = opts.get('change')
3595 stat = opts.get('stat')
3595 stat = opts.get('stat')
3596 reverse = opts.get('reverse')
3596 reverse = opts.get('reverse')
3597
3597
3598 if revs and change:
3598 if revs and change:
3599 msg = _('cannot specify --rev and --change at the same time')
3599 msg = _('cannot specify --rev and --change at the same time')
3600 raise error.Abort(msg)
3600 raise error.Abort(msg)
3601 elif change:
3601 elif change:
3602 node2 = scmutil.revsingle(repo, change, None).node()
3602 node2 = scmutil.revsingle(repo, change, None).node()
3603 node1 = repo[node2].p1().node()
3603 node1 = repo[node2].p1().node()
3604 else:
3604 else:
3605 node1, node2 = scmutil.revpair(repo, revs)
3605 node1, node2 = scmutil.revpair(repo, revs)
3606
3606
3607 if reverse:
3607 if reverse:
3608 node1, node2 = node2, node1
3608 node1, node2 = node2, node1
3609
3609
3610 diffopts = patch.diffallopts(ui, opts)
3610 diffopts = patch.diffallopts(ui, opts)
3611 m = scmutil.match(repo[node2], pats, opts)
3611 m = scmutil.match(repo[node2], pats, opts)
3612 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3612 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3613 listsubrepos=opts.get('subrepos'),
3613 listsubrepos=opts.get('subrepos'),
3614 root=opts.get('root'))
3614 root=opts.get('root'))
3615
3615
3616 @command('^export',
3616 @command('^export',
3617 [('o', 'output', '',
3617 [('o', 'output', '',
3618 _('print output to file with formatted name'), _('FORMAT')),
3618 _('print output to file with formatted name'), _('FORMAT')),
3619 ('', 'switch-parent', None, _('diff against the second parent')),
3619 ('', 'switch-parent', None, _('diff against the second parent')),
3620 ('r', 'rev', [], _('revisions to export'), _('REV')),
3620 ('r', 'rev', [], _('revisions to export'), _('REV')),
3621 ] + diffopts,
3621 ] + diffopts,
3622 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3622 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3623 def export(ui, repo, *changesets, **opts):
3623 def export(ui, repo, *changesets, **opts):
3624 """dump the header and diffs for one or more changesets
3624 """dump the header and diffs for one or more changesets
3625
3625
3626 Print the changeset header and diffs for one or more revisions.
3626 Print the changeset header and diffs for one or more revisions.
3627 If no revision is given, the parent of the working directory is used.
3627 If no revision is given, the parent of the working directory is used.
3628
3628
3629 The information shown in the changeset header is: author, date,
3629 The information shown in the changeset header is: author, date,
3630 branch name (if non-default), changeset hash, parent(s) and commit
3630 branch name (if non-default), changeset hash, parent(s) and commit
3631 comment.
3631 comment.
3632
3632
3633 .. note::
3633 .. note::
3634
3634
3635 :hg:`export` may generate unexpected diff output for merge
3635 :hg:`export` may generate unexpected diff output for merge
3636 changesets, as it will compare the merge changeset against its
3636 changesets, as it will compare the merge changeset against its
3637 first parent only.
3637 first parent only.
3638
3638
3639 Output may be to a file, in which case the name of the file is
3639 Output may be to a file, in which case the name of the file is
3640 given using a format string. The formatting rules are as follows:
3640 given using a format string. The formatting rules are as follows:
3641
3641
3642 :``%%``: literal "%" character
3642 :``%%``: literal "%" character
3643 :``%H``: changeset hash (40 hexadecimal digits)
3643 :``%H``: changeset hash (40 hexadecimal digits)
3644 :``%N``: number of patches being generated
3644 :``%N``: number of patches being generated
3645 :``%R``: changeset revision number
3645 :``%R``: changeset revision number
3646 :``%b``: basename of the exporting repository
3646 :``%b``: basename of the exporting repository
3647 :``%h``: short-form changeset hash (12 hexadecimal digits)
3647 :``%h``: short-form changeset hash (12 hexadecimal digits)
3648 :``%m``: first line of the commit message (only alphanumeric characters)
3648 :``%m``: first line of the commit message (only alphanumeric characters)
3649 :``%n``: zero-padded sequence number, starting at 1
3649 :``%n``: zero-padded sequence number, starting at 1
3650 :``%r``: zero-padded changeset revision number
3650 :``%r``: zero-padded changeset revision number
3651
3651
3652 Without the -a/--text option, export will avoid generating diffs
3652 Without the -a/--text option, export will avoid generating diffs
3653 of files it detects as binary. With -a, export will generate a
3653 of files it detects as binary. With -a, export will generate a
3654 diff anyway, probably with undesirable results.
3654 diff anyway, probably with undesirable results.
3655
3655
3656 Use the -g/--git option to generate diffs in the git extended diff
3656 Use the -g/--git option to generate diffs in the git extended diff
3657 format. See :hg:`help diffs` for more information.
3657 format. See :hg:`help diffs` for more information.
3658
3658
3659 With the --switch-parent option, the diff will be against the
3659 With the --switch-parent option, the diff will be against the
3660 second parent. It can be useful to review a merge.
3660 second parent. It can be useful to review a merge.
3661
3661
3662 .. container:: verbose
3662 .. container:: verbose
3663
3663
3664 Examples:
3664 Examples:
3665
3665
3666 - use export and import to transplant a bugfix to the current
3666 - use export and import to transplant a bugfix to the current
3667 branch::
3667 branch::
3668
3668
3669 hg export -r 9353 | hg import -
3669 hg export -r 9353 | hg import -
3670
3670
3671 - export all the changesets between two revisions to a file with
3671 - export all the changesets between two revisions to a file with
3672 rename information::
3672 rename information::
3673
3673
3674 hg export --git -r 123:150 > changes.txt
3674 hg export --git -r 123:150 > changes.txt
3675
3675
3676 - split outgoing changes into a series of patches with
3676 - split outgoing changes into a series of patches with
3677 descriptive names::
3677 descriptive names::
3678
3678
3679 hg export -r "outgoing()" -o "%n-%m.patch"
3679 hg export -r "outgoing()" -o "%n-%m.patch"
3680
3680
3681 Returns 0 on success.
3681 Returns 0 on success.
3682 """
3682 """
3683 changesets += tuple(opts.get('rev', []))
3683 changesets += tuple(opts.get('rev', []))
3684 if not changesets:
3684 if not changesets:
3685 changesets = ['.']
3685 changesets = ['.']
3686 revs = scmutil.revrange(repo, changesets)
3686 revs = scmutil.revrange(repo, changesets)
3687 if not revs:
3687 if not revs:
3688 raise error.Abort(_("export requires at least one changeset"))
3688 raise error.Abort(_("export requires at least one changeset"))
3689 if len(revs) > 1:
3689 if len(revs) > 1:
3690 ui.note(_('exporting patches:\n'))
3690 ui.note(_('exporting patches:\n'))
3691 else:
3691 else:
3692 ui.note(_('exporting patch:\n'))
3692 ui.note(_('exporting patch:\n'))
3693 cmdutil.export(repo, revs, template=opts.get('output'),
3693 cmdutil.export(repo, revs, template=opts.get('output'),
3694 switch_parent=opts.get('switch_parent'),
3694 switch_parent=opts.get('switch_parent'),
3695 opts=patch.diffallopts(ui, opts))
3695 opts=patch.diffallopts(ui, opts))
3696
3696
3697 @command('files',
3697 @command('files',
3698 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3698 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3699 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3699 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3700 ] + walkopts + formatteropts + subrepoopts,
3700 ] + walkopts + formatteropts + subrepoopts,
3701 _('[OPTION]... [PATTERN]...'))
3701 _('[OPTION]... [PATTERN]...'))
3702 def files(ui, repo, *pats, **opts):
3702 def files(ui, repo, *pats, **opts):
3703 """list tracked files
3703 """list tracked files
3704
3704
3705 Print files under Mercurial control in the working directory or
3705 Print files under Mercurial control in the working directory or
3706 specified revision whose names match the given patterns (excluding
3706 specified revision whose names match the given patterns (excluding
3707 removed files).
3707 removed files).
3708
3708
3709 If no patterns are given to match, this command prints the names
3709 If no patterns are given to match, this command prints the names
3710 of all files under Mercurial control in the working directory.
3710 of all files under Mercurial control in the working directory.
3711
3711
3712 .. container:: verbose
3712 .. container:: verbose
3713
3713
3714 Examples:
3714 Examples:
3715
3715
3716 - list all files under the current directory::
3716 - list all files under the current directory::
3717
3717
3718 hg files .
3718 hg files .
3719
3719
3720 - shows sizes and flags for current revision::
3720 - shows sizes and flags for current revision::
3721
3721
3722 hg files -vr .
3722 hg files -vr .
3723
3723
3724 - list all files named README::
3724 - list all files named README::
3725
3725
3726 hg files -I "**/README"
3726 hg files -I "**/README"
3727
3727
3728 - list all binary files::
3728 - list all binary files::
3729
3729
3730 hg files "set:binary()"
3730 hg files "set:binary()"
3731
3731
3732 - find files containing a regular expression::
3732 - find files containing a regular expression::
3733
3733
3734 hg files "set:grep('bob')"
3734 hg files "set:grep('bob')"
3735
3735
3736 - search tracked file contents with xargs and grep::
3736 - search tracked file contents with xargs and grep::
3737
3737
3738 hg files -0 | xargs -0 grep foo
3738 hg files -0 | xargs -0 grep foo
3739
3739
3740 See :hg:`help patterns` and :hg:`help filesets` for more information
3740 See :hg:`help patterns` and :hg:`help filesets` for more information
3741 on specifying file patterns.
3741 on specifying file patterns.
3742
3742
3743 Returns 0 if a match is found, 1 otherwise.
3743 Returns 0 if a match is found, 1 otherwise.
3744
3744
3745 """
3745 """
3746 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3746 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3747
3747
3748 end = '\n'
3748 end = '\n'
3749 if opts.get('print0'):
3749 if opts.get('print0'):
3750 end = '\0'
3750 end = '\0'
3751 fm = ui.formatter('files', opts)
3751 fm = ui.formatter('files', opts)
3752 fmt = '%s' + end
3752 fmt = '%s' + end
3753
3753
3754 m = scmutil.match(ctx, pats, opts)
3754 m = scmutil.match(ctx, pats, opts)
3755 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3755 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3756
3756
3757 fm.end()
3757 fm.end()
3758
3758
3759 return ret
3759 return ret
3760
3760
3761 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3761 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3762 def forget(ui, repo, *pats, **opts):
3762 def forget(ui, repo, *pats, **opts):
3763 """forget the specified files on the next commit
3763 """forget the specified files on the next commit
3764
3764
3765 Mark the specified files so they will no longer be tracked
3765 Mark the specified files so they will no longer be tracked
3766 after the next commit.
3766 after the next commit.
3767
3767
3768 This only removes files from the current branch, not from the
3768 This only removes files from the current branch, not from the
3769 entire project history, and it does not delete them from the
3769 entire project history, and it does not delete them from the
3770 working directory.
3770 working directory.
3771
3771
3772 To delete the file from the working directory, see :hg:`remove`.
3772 To delete the file from the working directory, see :hg:`remove`.
3773
3773
3774 To undo a forget before the next commit, see :hg:`add`.
3774 To undo a forget before the next commit, see :hg:`add`.
3775
3775
3776 .. container:: verbose
3776 .. container:: verbose
3777
3777
3778 Examples:
3778 Examples:
3779
3779
3780 - forget newly-added binary files::
3780 - forget newly-added binary files::
3781
3781
3782 hg forget "set:added() and binary()"
3782 hg forget "set:added() and binary()"
3783
3783
3784 - forget files that would be excluded by .hgignore::
3784 - forget files that would be excluded by .hgignore::
3785
3785
3786 hg forget "set:hgignore()"
3786 hg forget "set:hgignore()"
3787
3787
3788 Returns 0 on success.
3788 Returns 0 on success.
3789 """
3789 """
3790
3790
3791 if not pats:
3791 if not pats:
3792 raise error.Abort(_('no files specified'))
3792 raise error.Abort(_('no files specified'))
3793
3793
3794 m = scmutil.match(repo[None], pats, opts)
3794 m = scmutil.match(repo[None], pats, opts)
3795 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3795 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3796 return rejected and 1 or 0
3796 return rejected and 1 or 0
3797
3797
3798 @command(
3798 @command(
3799 'graft',
3799 'graft',
3800 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3800 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3801 ('c', 'continue', False, _('resume interrupted graft')),
3801 ('c', 'continue', False, _('resume interrupted graft')),
3802 ('e', 'edit', False, _('invoke editor on commit messages')),
3802 ('e', 'edit', False, _('invoke editor on commit messages')),
3803 ('', 'log', None, _('append graft info to log message')),
3803 ('', 'log', None, _('append graft info to log message')),
3804 ('f', 'force', False, _('force graft')),
3804 ('f', 'force', False, _('force graft')),
3805 ('D', 'currentdate', False,
3805 ('D', 'currentdate', False,
3806 _('record the current date as commit date')),
3806 _('record the current date as commit date')),
3807 ('U', 'currentuser', False,
3807 ('U', 'currentuser', False,
3808 _('record the current user as committer'), _('DATE'))]
3808 _('record the current user as committer'), _('DATE'))]
3809 + commitopts2 + mergetoolopts + dryrunopts,
3809 + commitopts2 + mergetoolopts + dryrunopts,
3810 _('[OPTION]... [-r] REV...'))
3810 _('[OPTION]... [-r] REV...'))
3811 def graft(ui, repo, *revs, **opts):
3811 def graft(ui, repo, *revs, **opts):
3812 '''copy changes from other branches onto the current branch
3812 '''copy changes from other branches onto the current branch
3813
3813
3814 This command uses Mercurial's merge logic to copy individual
3814 This command uses Mercurial's merge logic to copy individual
3815 changes from other branches without merging branches in the
3815 changes from other branches without merging branches in the
3816 history graph. This is sometimes known as 'backporting' or
3816 history graph. This is sometimes known as 'backporting' or
3817 'cherry-picking'. By default, graft will copy user, date, and
3817 'cherry-picking'. By default, graft will copy user, date, and
3818 description from the source changesets.
3818 description from the source changesets.
3819
3819
3820 Changesets that are ancestors of the current revision, that have
3820 Changesets that are ancestors of the current revision, that have
3821 already been grafted, or that are merges will be skipped.
3821 already been grafted, or that are merges will be skipped.
3822
3822
3823 If --log is specified, log messages will have a comment appended
3823 If --log is specified, log messages will have a comment appended
3824 of the form::
3824 of the form::
3825
3825
3826 (grafted from CHANGESETHASH)
3826 (grafted from CHANGESETHASH)
3827
3827
3828 If --force is specified, revisions will be grafted even if they
3828 If --force is specified, revisions will be grafted even if they
3829 are already ancestors of or have been grafted to the destination.
3829 are already ancestors of or have been grafted to the destination.
3830 This is useful when the revisions have since been backed out.
3830 This is useful when the revisions have since been backed out.
3831
3831
3832 If a graft merge results in conflicts, the graft process is
3832 If a graft merge results in conflicts, the graft process is
3833 interrupted so that the current merge can be manually resolved.
3833 interrupted so that the current merge can be manually resolved.
3834 Once all conflicts are addressed, the graft process can be
3834 Once all conflicts are addressed, the graft process can be
3835 continued with the -c/--continue option.
3835 continued with the -c/--continue option.
3836
3836
3837 .. note::
3837 .. note::
3838
3838
3839 The -c/--continue option does not reapply earlier options, except
3839 The -c/--continue option does not reapply earlier options, except
3840 for --force.
3840 for --force.
3841
3841
3842 .. container:: verbose
3842 .. container:: verbose
3843
3843
3844 Examples:
3844 Examples:
3845
3845
3846 - copy a single change to the stable branch and edit its description::
3846 - copy a single change to the stable branch and edit its description::
3847
3847
3848 hg update stable
3848 hg update stable
3849 hg graft --edit 9393
3849 hg graft --edit 9393
3850
3850
3851 - graft a range of changesets with one exception, updating dates::
3851 - graft a range of changesets with one exception, updating dates::
3852
3852
3853 hg graft -D "2085::2093 and not 2091"
3853 hg graft -D "2085::2093 and not 2091"
3854
3854
3855 - continue a graft after resolving conflicts::
3855 - continue a graft after resolving conflicts::
3856
3856
3857 hg graft -c
3857 hg graft -c
3858
3858
3859 - show the source of a grafted changeset::
3859 - show the source of a grafted changeset::
3860
3860
3861 hg log --debug -r .
3861 hg log --debug -r .
3862
3862
3863 - show revisions sorted by date::
3863 - show revisions sorted by date::
3864
3864
3865 hg log -r 'sort(all(), date)'
3865 hg log -r 'sort(all(), date)'
3866
3866
3867 See :hg:`help revisions` and :hg:`help revsets` for more about
3867 See :hg:`help revisions` and :hg:`help revsets` for more about
3868 specifying revisions.
3868 specifying revisions.
3869
3869
3870 Returns 0 on successful completion.
3870 Returns 0 on successful completion.
3871 '''
3871 '''
3872 wlock = None
3872 with repo.wlock():
3873 try:
3874 wlock = repo.wlock()
3875 return _dograft(ui, repo, *revs, **opts)
3873 return _dograft(ui, repo, *revs, **opts)
3876 finally:
3877 release(wlock)
3878
3874
3879 def _dograft(ui, repo, *revs, **opts):
3875 def _dograft(ui, repo, *revs, **opts):
3880 revs = list(revs)
3876 revs = list(revs)
3881 revs.extend(opts['rev'])
3877 revs.extend(opts['rev'])
3882
3878
3883 if not opts.get('user') and opts.get('currentuser'):
3879 if not opts.get('user') and opts.get('currentuser'):
3884 opts['user'] = ui.username()
3880 opts['user'] = ui.username()
3885 if not opts.get('date') and opts.get('currentdate'):
3881 if not opts.get('date') and opts.get('currentdate'):
3886 opts['date'] = "%d %d" % util.makedate()
3882 opts['date'] = "%d %d" % util.makedate()
3887
3883
3888 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3884 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3889
3885
3890 cont = False
3886 cont = False
3891 if opts['continue']:
3887 if opts['continue']:
3892 cont = True
3888 cont = True
3893 if revs:
3889 if revs:
3894 raise error.Abort(_("can't specify --continue and revisions"))
3890 raise error.Abort(_("can't specify --continue and revisions"))
3895 # read in unfinished revisions
3891 # read in unfinished revisions
3896 try:
3892 try:
3897 nodes = repo.vfs.read('graftstate').splitlines()
3893 nodes = repo.vfs.read('graftstate').splitlines()
3898 revs = [repo[node].rev() for node in nodes]
3894 revs = [repo[node].rev() for node in nodes]
3899 except IOError as inst:
3895 except IOError as inst:
3900 if inst.errno != errno.ENOENT:
3896 if inst.errno != errno.ENOENT:
3901 raise
3897 raise
3902 raise error.Abort(_("no graft state found, can't continue"))
3898 raise error.Abort(_("no graft state found, can't continue"))
3903 else:
3899 else:
3904 cmdutil.checkunfinished(repo)
3900 cmdutil.checkunfinished(repo)
3905 cmdutil.bailifchanged(repo)
3901 cmdutil.bailifchanged(repo)
3906 if not revs:
3902 if not revs:
3907 raise error.Abort(_('no revisions specified'))
3903 raise error.Abort(_('no revisions specified'))
3908 revs = scmutil.revrange(repo, revs)
3904 revs = scmutil.revrange(repo, revs)
3909
3905
3910 skipped = set()
3906 skipped = set()
3911 # check for merges
3907 # check for merges
3912 for rev in repo.revs('%ld and merge()', revs):
3908 for rev in repo.revs('%ld and merge()', revs):
3913 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3909 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3914 skipped.add(rev)
3910 skipped.add(rev)
3915 revs = [r for r in revs if r not in skipped]
3911 revs = [r for r in revs if r not in skipped]
3916 if not revs:
3912 if not revs:
3917 return -1
3913 return -1
3918
3914
3919 # Don't check in the --continue case, in effect retaining --force across
3915 # Don't check in the --continue case, in effect retaining --force across
3920 # --continues. That's because without --force, any revisions we decided to
3916 # --continues. That's because without --force, any revisions we decided to
3921 # skip would have been filtered out here, so they wouldn't have made their
3917 # skip would have been filtered out here, so they wouldn't have made their
3922 # way to the graftstate. With --force, any revisions we would have otherwise
3918 # way to the graftstate. With --force, any revisions we would have otherwise
3923 # skipped would not have been filtered out, and if they hadn't been applied
3919 # skipped would not have been filtered out, and if they hadn't been applied
3924 # already, they'd have been in the graftstate.
3920 # already, they'd have been in the graftstate.
3925 if not (cont or opts.get('force')):
3921 if not (cont or opts.get('force')):
3926 # check for ancestors of dest branch
3922 # check for ancestors of dest branch
3927 crev = repo['.'].rev()
3923 crev = repo['.'].rev()
3928 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3924 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3929 # Cannot use x.remove(y) on smart set, this has to be a list.
3925 # Cannot use x.remove(y) on smart set, this has to be a list.
3930 # XXX make this lazy in the future
3926 # XXX make this lazy in the future
3931 revs = list(revs)
3927 revs = list(revs)
3932 # don't mutate while iterating, create a copy
3928 # don't mutate while iterating, create a copy
3933 for rev in list(revs):
3929 for rev in list(revs):
3934 if rev in ancestors:
3930 if rev in ancestors:
3935 ui.warn(_('skipping ancestor revision %d:%s\n') %
3931 ui.warn(_('skipping ancestor revision %d:%s\n') %
3936 (rev, repo[rev]))
3932 (rev, repo[rev]))
3937 # XXX remove on list is slow
3933 # XXX remove on list is slow
3938 revs.remove(rev)
3934 revs.remove(rev)
3939 if not revs:
3935 if not revs:
3940 return -1
3936 return -1
3941
3937
3942 # analyze revs for earlier grafts
3938 # analyze revs for earlier grafts
3943 ids = {}
3939 ids = {}
3944 for ctx in repo.set("%ld", revs):
3940 for ctx in repo.set("%ld", revs):
3945 ids[ctx.hex()] = ctx.rev()
3941 ids[ctx.hex()] = ctx.rev()
3946 n = ctx.extra().get('source')
3942 n = ctx.extra().get('source')
3947 if n:
3943 if n:
3948 ids[n] = ctx.rev()
3944 ids[n] = ctx.rev()
3949
3945
3950 # check ancestors for earlier grafts
3946 # check ancestors for earlier grafts
3951 ui.debug('scanning for duplicate grafts\n')
3947 ui.debug('scanning for duplicate grafts\n')
3952
3948
3953 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3949 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3954 ctx = repo[rev]
3950 ctx = repo[rev]
3955 n = ctx.extra().get('source')
3951 n = ctx.extra().get('source')
3956 if n in ids:
3952 if n in ids:
3957 try:
3953 try:
3958 r = repo[n].rev()
3954 r = repo[n].rev()
3959 except error.RepoLookupError:
3955 except error.RepoLookupError:
3960 r = None
3956 r = None
3961 if r in revs:
3957 if r in revs:
3962 ui.warn(_('skipping revision %d:%s '
3958 ui.warn(_('skipping revision %d:%s '
3963 '(already grafted to %d:%s)\n')
3959 '(already grafted to %d:%s)\n')
3964 % (r, repo[r], rev, ctx))
3960 % (r, repo[r], rev, ctx))
3965 revs.remove(r)
3961 revs.remove(r)
3966 elif ids[n] in revs:
3962 elif ids[n] in revs:
3967 if r is None:
3963 if r is None:
3968 ui.warn(_('skipping already grafted revision %d:%s '
3964 ui.warn(_('skipping already grafted revision %d:%s '
3969 '(%d:%s also has unknown origin %s)\n')
3965 '(%d:%s also has unknown origin %s)\n')
3970 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3966 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3971 else:
3967 else:
3972 ui.warn(_('skipping already grafted revision %d:%s '
3968 ui.warn(_('skipping already grafted revision %d:%s '
3973 '(%d:%s also has origin %d:%s)\n')
3969 '(%d:%s also has origin %d:%s)\n')
3974 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3970 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3975 revs.remove(ids[n])
3971 revs.remove(ids[n])
3976 elif ctx.hex() in ids:
3972 elif ctx.hex() in ids:
3977 r = ids[ctx.hex()]
3973 r = ids[ctx.hex()]
3978 ui.warn(_('skipping already grafted revision %d:%s '
3974 ui.warn(_('skipping already grafted revision %d:%s '
3979 '(was grafted from %d:%s)\n') %
3975 '(was grafted from %d:%s)\n') %
3980 (r, repo[r], rev, ctx))
3976 (r, repo[r], rev, ctx))
3981 revs.remove(r)
3977 revs.remove(r)
3982 if not revs:
3978 if not revs:
3983 return -1
3979 return -1
3984
3980
3985 for pos, ctx in enumerate(repo.set("%ld", revs)):
3981 for pos, ctx in enumerate(repo.set("%ld", revs)):
3986 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3982 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3987 ctx.description().split('\n', 1)[0])
3983 ctx.description().split('\n', 1)[0])
3988 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3984 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3989 if names:
3985 if names:
3990 desc += ' (%s)' % ' '.join(names)
3986 desc += ' (%s)' % ' '.join(names)
3991 ui.status(_('grafting %s\n') % desc)
3987 ui.status(_('grafting %s\n') % desc)
3992 if opts.get('dry_run'):
3988 if opts.get('dry_run'):
3993 continue
3989 continue
3994
3990
3995 extra = ctx.extra().copy()
3991 extra = ctx.extra().copy()
3996 del extra['branch']
3992 del extra['branch']
3997 source = extra.get('source')
3993 source = extra.get('source')
3998 if source:
3994 if source:
3999 extra['intermediate-source'] = ctx.hex()
3995 extra['intermediate-source'] = ctx.hex()
4000 else:
3996 else:
4001 extra['source'] = ctx.hex()
3997 extra['source'] = ctx.hex()
4002 user = ctx.user()
3998 user = ctx.user()
4003 if opts.get('user'):
3999 if opts.get('user'):
4004 user = opts['user']
4000 user = opts['user']
4005 date = ctx.date()
4001 date = ctx.date()
4006 if opts.get('date'):
4002 if opts.get('date'):
4007 date = opts['date']
4003 date = opts['date']
4008 message = ctx.description()
4004 message = ctx.description()
4009 if opts.get('log'):
4005 if opts.get('log'):
4010 message += '\n(grafted from %s)' % ctx.hex()
4006 message += '\n(grafted from %s)' % ctx.hex()
4011
4007
4012 # we don't merge the first commit when continuing
4008 # we don't merge the first commit when continuing
4013 if not cont:
4009 if not cont:
4014 # perform the graft merge with p1(rev) as 'ancestor'
4010 # perform the graft merge with p1(rev) as 'ancestor'
4015 try:
4011 try:
4016 # ui.forcemerge is an internal variable, do not document
4012 # ui.forcemerge is an internal variable, do not document
4017 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4013 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4018 'graft')
4014 'graft')
4019 stats = mergemod.graft(repo, ctx, ctx.p1(),
4015 stats = mergemod.graft(repo, ctx, ctx.p1(),
4020 ['local', 'graft'])
4016 ['local', 'graft'])
4021 finally:
4017 finally:
4022 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4018 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4023 # report any conflicts
4019 # report any conflicts
4024 if stats and stats[3] > 0:
4020 if stats and stats[3] > 0:
4025 # write out state for --continue
4021 # write out state for --continue
4026 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4022 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4027 repo.vfs.write('graftstate', ''.join(nodelines))
4023 repo.vfs.write('graftstate', ''.join(nodelines))
4028 extra = ''
4024 extra = ''
4029 if opts.get('user'):
4025 if opts.get('user'):
4030 extra += ' --user %s' % opts['user']
4026 extra += ' --user %s' % opts['user']
4031 if opts.get('date'):
4027 if opts.get('date'):
4032 extra += ' --date %s' % opts['date']
4028 extra += ' --date %s' % opts['date']
4033 if opts.get('log'):
4029 if opts.get('log'):
4034 extra += ' --log'
4030 extra += ' --log'
4035 hint=_('use hg resolve and hg graft --continue%s') % extra
4031 hint=_('use hg resolve and hg graft --continue%s') % extra
4036 raise error.Abort(
4032 raise error.Abort(
4037 _("unresolved conflicts, can't continue"),
4033 _("unresolved conflicts, can't continue"),
4038 hint=hint)
4034 hint=hint)
4039 else:
4035 else:
4040 cont = False
4036 cont = False
4041
4037
4042 # commit
4038 # commit
4043 node = repo.commit(text=message, user=user,
4039 node = repo.commit(text=message, user=user,
4044 date=date, extra=extra, editor=editor)
4040 date=date, extra=extra, editor=editor)
4045 if node is None:
4041 if node is None:
4046 ui.warn(
4042 ui.warn(
4047 _('note: graft of %d:%s created no changes to commit\n') %
4043 _('note: graft of %d:%s created no changes to commit\n') %
4048 (ctx.rev(), ctx))
4044 (ctx.rev(), ctx))
4049
4045
4050 # remove state when we complete successfully
4046 # remove state when we complete successfully
4051 if not opts.get('dry_run'):
4047 if not opts.get('dry_run'):
4052 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4048 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4053
4049
4054 return 0
4050 return 0
4055
4051
4056 @command('grep',
4052 @command('grep',
4057 [('0', 'print0', None, _('end fields with NUL')),
4053 [('0', 'print0', None, _('end fields with NUL')),
4058 ('', 'all', None, _('print all revisions that match')),
4054 ('', 'all', None, _('print all revisions that match')),
4059 ('a', 'text', None, _('treat all files as text')),
4055 ('a', 'text', None, _('treat all files as text')),
4060 ('f', 'follow', None,
4056 ('f', 'follow', None,
4061 _('follow changeset history,'
4057 _('follow changeset history,'
4062 ' or file history across copies and renames')),
4058 ' or file history across copies and renames')),
4063 ('i', 'ignore-case', None, _('ignore case when matching')),
4059 ('i', 'ignore-case', None, _('ignore case when matching')),
4064 ('l', 'files-with-matches', None,
4060 ('l', 'files-with-matches', None,
4065 _('print only filenames and revisions that match')),
4061 _('print only filenames and revisions that match')),
4066 ('n', 'line-number', None, _('print matching line numbers')),
4062 ('n', 'line-number', None, _('print matching line numbers')),
4067 ('r', 'rev', [],
4063 ('r', 'rev', [],
4068 _('only search files changed within revision range'), _('REV')),
4064 _('only search files changed within revision range'), _('REV')),
4069 ('u', 'user', None, _('list the author (long with -v)')),
4065 ('u', 'user', None, _('list the author (long with -v)')),
4070 ('d', 'date', None, _('list the date (short with -q)')),
4066 ('d', 'date', None, _('list the date (short with -q)')),
4071 ] + walkopts,
4067 ] + walkopts,
4072 _('[OPTION]... PATTERN [FILE]...'),
4068 _('[OPTION]... PATTERN [FILE]...'),
4073 inferrepo=True)
4069 inferrepo=True)
4074 def grep(ui, repo, pattern, *pats, **opts):
4070 def grep(ui, repo, pattern, *pats, **opts):
4075 """search for a pattern in specified files and revisions
4071 """search for a pattern in specified files and revisions
4076
4072
4077 Search revisions of files for a regular expression.
4073 Search revisions of files for a regular expression.
4078
4074
4079 This command behaves differently than Unix grep. It only accepts
4075 This command behaves differently than Unix grep. It only accepts
4080 Python/Perl regexps. It searches repository history, not the
4076 Python/Perl regexps. It searches repository history, not the
4081 working directory. It always prints the revision number in which a
4077 working directory. It always prints the revision number in which a
4082 match appears.
4078 match appears.
4083
4079
4084 By default, grep only prints output for the first revision of a
4080 By default, grep only prints output for the first revision of a
4085 file in which it finds a match. To get it to print every revision
4081 file in which it finds a match. To get it to print every revision
4086 that contains a change in match status ("-" for a match that
4082 that contains a change in match status ("-" for a match that
4087 becomes a non-match, or "+" for a non-match that becomes a match),
4083 becomes a non-match, or "+" for a non-match that becomes a match),
4088 use the --all flag.
4084 use the --all flag.
4089
4085
4090 Returns 0 if a match is found, 1 otherwise.
4086 Returns 0 if a match is found, 1 otherwise.
4091 """
4087 """
4092 reflags = re.M
4088 reflags = re.M
4093 if opts.get('ignore_case'):
4089 if opts.get('ignore_case'):
4094 reflags |= re.I
4090 reflags |= re.I
4095 try:
4091 try:
4096 regexp = util.re.compile(pattern, reflags)
4092 regexp = util.re.compile(pattern, reflags)
4097 except re.error as inst:
4093 except re.error as inst:
4098 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4094 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4099 return 1
4095 return 1
4100 sep, eol = ':', '\n'
4096 sep, eol = ':', '\n'
4101 if opts.get('print0'):
4097 if opts.get('print0'):
4102 sep = eol = '\0'
4098 sep = eol = '\0'
4103
4099
4104 getfile = util.lrucachefunc(repo.file)
4100 getfile = util.lrucachefunc(repo.file)
4105
4101
4106 def matchlines(body):
4102 def matchlines(body):
4107 begin = 0
4103 begin = 0
4108 linenum = 0
4104 linenum = 0
4109 while begin < len(body):
4105 while begin < len(body):
4110 match = regexp.search(body, begin)
4106 match = regexp.search(body, begin)
4111 if not match:
4107 if not match:
4112 break
4108 break
4113 mstart, mend = match.span()
4109 mstart, mend = match.span()
4114 linenum += body.count('\n', begin, mstart) + 1
4110 linenum += body.count('\n', begin, mstart) + 1
4115 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4111 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4116 begin = body.find('\n', mend) + 1 or len(body) + 1
4112 begin = body.find('\n', mend) + 1 or len(body) + 1
4117 lend = begin - 1
4113 lend = begin - 1
4118 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4114 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4119
4115
4120 class linestate(object):
4116 class linestate(object):
4121 def __init__(self, line, linenum, colstart, colend):
4117 def __init__(self, line, linenum, colstart, colend):
4122 self.line = line
4118 self.line = line
4123 self.linenum = linenum
4119 self.linenum = linenum
4124 self.colstart = colstart
4120 self.colstart = colstart
4125 self.colend = colend
4121 self.colend = colend
4126
4122
4127 def __hash__(self):
4123 def __hash__(self):
4128 return hash((self.linenum, self.line))
4124 return hash((self.linenum, self.line))
4129
4125
4130 def __eq__(self, other):
4126 def __eq__(self, other):
4131 return self.line == other.line
4127 return self.line == other.line
4132
4128
4133 def __iter__(self):
4129 def __iter__(self):
4134 yield (self.line[:self.colstart], '')
4130 yield (self.line[:self.colstart], '')
4135 yield (self.line[self.colstart:self.colend], 'grep.match')
4131 yield (self.line[self.colstart:self.colend], 'grep.match')
4136 rest = self.line[self.colend:]
4132 rest = self.line[self.colend:]
4137 while rest != '':
4133 while rest != '':
4138 match = regexp.search(rest)
4134 match = regexp.search(rest)
4139 if not match:
4135 if not match:
4140 yield (rest, '')
4136 yield (rest, '')
4141 break
4137 break
4142 mstart, mend = match.span()
4138 mstart, mend = match.span()
4143 yield (rest[:mstart], '')
4139 yield (rest[:mstart], '')
4144 yield (rest[mstart:mend], 'grep.match')
4140 yield (rest[mstart:mend], 'grep.match')
4145 rest = rest[mend:]
4141 rest = rest[mend:]
4146
4142
4147 matches = {}
4143 matches = {}
4148 copies = {}
4144 copies = {}
4149 def grepbody(fn, rev, body):
4145 def grepbody(fn, rev, body):
4150 matches[rev].setdefault(fn, [])
4146 matches[rev].setdefault(fn, [])
4151 m = matches[rev][fn]
4147 m = matches[rev][fn]
4152 for lnum, cstart, cend, line in matchlines(body):
4148 for lnum, cstart, cend, line in matchlines(body):
4153 s = linestate(line, lnum, cstart, cend)
4149 s = linestate(line, lnum, cstart, cend)
4154 m.append(s)
4150 m.append(s)
4155
4151
4156 def difflinestates(a, b):
4152 def difflinestates(a, b):
4157 sm = difflib.SequenceMatcher(None, a, b)
4153 sm = difflib.SequenceMatcher(None, a, b)
4158 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4154 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4159 if tag == 'insert':
4155 if tag == 'insert':
4160 for i in xrange(blo, bhi):
4156 for i in xrange(blo, bhi):
4161 yield ('+', b[i])
4157 yield ('+', b[i])
4162 elif tag == 'delete':
4158 elif tag == 'delete':
4163 for i in xrange(alo, ahi):
4159 for i in xrange(alo, ahi):
4164 yield ('-', a[i])
4160 yield ('-', a[i])
4165 elif tag == 'replace':
4161 elif tag == 'replace':
4166 for i in xrange(alo, ahi):
4162 for i in xrange(alo, ahi):
4167 yield ('-', a[i])
4163 yield ('-', a[i])
4168 for i in xrange(blo, bhi):
4164 for i in xrange(blo, bhi):
4169 yield ('+', b[i])
4165 yield ('+', b[i])
4170
4166
4171 def display(fn, ctx, pstates, states):
4167 def display(fn, ctx, pstates, states):
4172 rev = ctx.rev()
4168 rev = ctx.rev()
4173 if ui.quiet:
4169 if ui.quiet:
4174 datefunc = util.shortdate
4170 datefunc = util.shortdate
4175 else:
4171 else:
4176 datefunc = util.datestr
4172 datefunc = util.datestr
4177 found = False
4173 found = False
4178 @util.cachefunc
4174 @util.cachefunc
4179 def binary():
4175 def binary():
4180 flog = getfile(fn)
4176 flog = getfile(fn)
4181 return util.binary(flog.read(ctx.filenode(fn)))
4177 return util.binary(flog.read(ctx.filenode(fn)))
4182
4178
4183 if opts.get('all'):
4179 if opts.get('all'):
4184 iter = difflinestates(pstates, states)
4180 iter = difflinestates(pstates, states)
4185 else:
4181 else:
4186 iter = [('', l) for l in states]
4182 iter = [('', l) for l in states]
4187 for change, l in iter:
4183 for change, l in iter:
4188 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4184 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4189
4185
4190 if opts.get('line_number'):
4186 if opts.get('line_number'):
4191 cols.append((str(l.linenum), 'grep.linenumber'))
4187 cols.append((str(l.linenum), 'grep.linenumber'))
4192 if opts.get('all'):
4188 if opts.get('all'):
4193 cols.append((change, 'grep.change'))
4189 cols.append((change, 'grep.change'))
4194 if opts.get('user'):
4190 if opts.get('user'):
4195 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4191 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4196 if opts.get('date'):
4192 if opts.get('date'):
4197 cols.append((datefunc(ctx.date()), 'grep.date'))
4193 cols.append((datefunc(ctx.date()), 'grep.date'))
4198 for col, label in cols[:-1]:
4194 for col, label in cols[:-1]:
4199 ui.write(col, label=label)
4195 ui.write(col, label=label)
4200 ui.write(sep, label='grep.sep')
4196 ui.write(sep, label='grep.sep')
4201 ui.write(cols[-1][0], label=cols[-1][1])
4197 ui.write(cols[-1][0], label=cols[-1][1])
4202 if not opts.get('files_with_matches'):
4198 if not opts.get('files_with_matches'):
4203 ui.write(sep, label='grep.sep')
4199 ui.write(sep, label='grep.sep')
4204 if not opts.get('text') and binary():
4200 if not opts.get('text') and binary():
4205 ui.write(" Binary file matches")
4201 ui.write(" Binary file matches")
4206 else:
4202 else:
4207 for s, label in l:
4203 for s, label in l:
4208 ui.write(s, label=label)
4204 ui.write(s, label=label)
4209 ui.write(eol)
4205 ui.write(eol)
4210 found = True
4206 found = True
4211 if opts.get('files_with_matches'):
4207 if opts.get('files_with_matches'):
4212 break
4208 break
4213 return found
4209 return found
4214
4210
4215 skip = {}
4211 skip = {}
4216 revfiles = {}
4212 revfiles = {}
4217 matchfn = scmutil.match(repo[None], pats, opts)
4213 matchfn = scmutil.match(repo[None], pats, opts)
4218 found = False
4214 found = False
4219 follow = opts.get('follow')
4215 follow = opts.get('follow')
4220
4216
4221 def prep(ctx, fns):
4217 def prep(ctx, fns):
4222 rev = ctx.rev()
4218 rev = ctx.rev()
4223 pctx = ctx.p1()
4219 pctx = ctx.p1()
4224 parent = pctx.rev()
4220 parent = pctx.rev()
4225 matches.setdefault(rev, {})
4221 matches.setdefault(rev, {})
4226 matches.setdefault(parent, {})
4222 matches.setdefault(parent, {})
4227 files = revfiles.setdefault(rev, [])
4223 files = revfiles.setdefault(rev, [])
4228 for fn in fns:
4224 for fn in fns:
4229 flog = getfile(fn)
4225 flog = getfile(fn)
4230 try:
4226 try:
4231 fnode = ctx.filenode(fn)
4227 fnode = ctx.filenode(fn)
4232 except error.LookupError:
4228 except error.LookupError:
4233 continue
4229 continue
4234
4230
4235 copied = flog.renamed(fnode)
4231 copied = flog.renamed(fnode)
4236 copy = follow and copied and copied[0]
4232 copy = follow and copied and copied[0]
4237 if copy:
4233 if copy:
4238 copies.setdefault(rev, {})[fn] = copy
4234 copies.setdefault(rev, {})[fn] = copy
4239 if fn in skip:
4235 if fn in skip:
4240 if copy:
4236 if copy:
4241 skip[copy] = True
4237 skip[copy] = True
4242 continue
4238 continue
4243 files.append(fn)
4239 files.append(fn)
4244
4240
4245 if fn not in matches[rev]:
4241 if fn not in matches[rev]:
4246 grepbody(fn, rev, flog.read(fnode))
4242 grepbody(fn, rev, flog.read(fnode))
4247
4243
4248 pfn = copy or fn
4244 pfn = copy or fn
4249 if pfn not in matches[parent]:
4245 if pfn not in matches[parent]:
4250 try:
4246 try:
4251 fnode = pctx.filenode(pfn)
4247 fnode = pctx.filenode(pfn)
4252 grepbody(pfn, parent, flog.read(fnode))
4248 grepbody(pfn, parent, flog.read(fnode))
4253 except error.LookupError:
4249 except error.LookupError:
4254 pass
4250 pass
4255
4251
4256 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4252 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4257 rev = ctx.rev()
4253 rev = ctx.rev()
4258 parent = ctx.p1().rev()
4254 parent = ctx.p1().rev()
4259 for fn in sorted(revfiles.get(rev, [])):
4255 for fn in sorted(revfiles.get(rev, [])):
4260 states = matches[rev][fn]
4256 states = matches[rev][fn]
4261 copy = copies.get(rev, {}).get(fn)
4257 copy = copies.get(rev, {}).get(fn)
4262 if fn in skip:
4258 if fn in skip:
4263 if copy:
4259 if copy:
4264 skip[copy] = True
4260 skip[copy] = True
4265 continue
4261 continue
4266 pstates = matches.get(parent, {}).get(copy or fn, [])
4262 pstates = matches.get(parent, {}).get(copy or fn, [])
4267 if pstates or states:
4263 if pstates or states:
4268 r = display(fn, ctx, pstates, states)
4264 r = display(fn, ctx, pstates, states)
4269 found = found or r
4265 found = found or r
4270 if r and not opts.get('all'):
4266 if r and not opts.get('all'):
4271 skip[fn] = True
4267 skip[fn] = True
4272 if copy:
4268 if copy:
4273 skip[copy] = True
4269 skip[copy] = True
4274 del matches[rev]
4270 del matches[rev]
4275 del revfiles[rev]
4271 del revfiles[rev]
4276
4272
4277 return not found
4273 return not found
4278
4274
4279 @command('heads',
4275 @command('heads',
4280 [('r', 'rev', '',
4276 [('r', 'rev', '',
4281 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4277 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4282 ('t', 'topo', False, _('show topological heads only')),
4278 ('t', 'topo', False, _('show topological heads only')),
4283 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4279 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4284 ('c', 'closed', False, _('show normal and closed branch heads')),
4280 ('c', 'closed', False, _('show normal and closed branch heads')),
4285 ] + templateopts,
4281 ] + templateopts,
4286 _('[-ct] [-r STARTREV] [REV]...'))
4282 _('[-ct] [-r STARTREV] [REV]...'))
4287 def heads(ui, repo, *branchrevs, **opts):
4283 def heads(ui, repo, *branchrevs, **opts):
4288 """show branch heads
4284 """show branch heads
4289
4285
4290 With no arguments, show all open branch heads in the repository.
4286 With no arguments, show all open branch heads in the repository.
4291 Branch heads are changesets that have no descendants on the
4287 Branch heads are changesets that have no descendants on the
4292 same branch. They are where development generally takes place and
4288 same branch. They are where development generally takes place and
4293 are the usual targets for update and merge operations.
4289 are the usual targets for update and merge operations.
4294
4290
4295 If one or more REVs are given, only open branch heads on the
4291 If one or more REVs are given, only open branch heads on the
4296 branches associated with the specified changesets are shown. This
4292 branches associated with the specified changesets are shown. This
4297 means that you can use :hg:`heads .` to see the heads on the
4293 means that you can use :hg:`heads .` to see the heads on the
4298 currently checked-out branch.
4294 currently checked-out branch.
4299
4295
4300 If -c/--closed is specified, also show branch heads marked closed
4296 If -c/--closed is specified, also show branch heads marked closed
4301 (see :hg:`commit --close-branch`).
4297 (see :hg:`commit --close-branch`).
4302
4298
4303 If STARTREV is specified, only those heads that are descendants of
4299 If STARTREV is specified, only those heads that are descendants of
4304 STARTREV will be displayed.
4300 STARTREV will be displayed.
4305
4301
4306 If -t/--topo is specified, named branch mechanics will be ignored and only
4302 If -t/--topo is specified, named branch mechanics will be ignored and only
4307 topological heads (changesets with no children) will be shown.
4303 topological heads (changesets with no children) will be shown.
4308
4304
4309 Returns 0 if matching heads are found, 1 if not.
4305 Returns 0 if matching heads are found, 1 if not.
4310 """
4306 """
4311
4307
4312 start = None
4308 start = None
4313 if 'rev' in opts:
4309 if 'rev' in opts:
4314 start = scmutil.revsingle(repo, opts['rev'], None).node()
4310 start = scmutil.revsingle(repo, opts['rev'], None).node()
4315
4311
4316 if opts.get('topo'):
4312 if opts.get('topo'):
4317 heads = [repo[h] for h in repo.heads(start)]
4313 heads = [repo[h] for h in repo.heads(start)]
4318 else:
4314 else:
4319 heads = []
4315 heads = []
4320 for branch in repo.branchmap():
4316 for branch in repo.branchmap():
4321 heads += repo.branchheads(branch, start, opts.get('closed'))
4317 heads += repo.branchheads(branch, start, opts.get('closed'))
4322 heads = [repo[h] for h in heads]
4318 heads = [repo[h] for h in heads]
4323
4319
4324 if branchrevs:
4320 if branchrevs:
4325 branches = set(repo[br].branch() for br in branchrevs)
4321 branches = set(repo[br].branch() for br in branchrevs)
4326 heads = [h for h in heads if h.branch() in branches]
4322 heads = [h for h in heads if h.branch() in branches]
4327
4323
4328 if opts.get('active') and branchrevs:
4324 if opts.get('active') and branchrevs:
4329 dagheads = repo.heads(start)
4325 dagheads = repo.heads(start)
4330 heads = [h for h in heads if h.node() in dagheads]
4326 heads = [h for h in heads if h.node() in dagheads]
4331
4327
4332 if branchrevs:
4328 if branchrevs:
4333 haveheads = set(h.branch() for h in heads)
4329 haveheads = set(h.branch() for h in heads)
4334 if branches - haveheads:
4330 if branches - haveheads:
4335 headless = ', '.join(b for b in branches - haveheads)
4331 headless = ', '.join(b for b in branches - haveheads)
4336 msg = _('no open branch heads found on branches %s')
4332 msg = _('no open branch heads found on branches %s')
4337 if opts.get('rev'):
4333 if opts.get('rev'):
4338 msg += _(' (started at %s)') % opts['rev']
4334 msg += _(' (started at %s)') % opts['rev']
4339 ui.warn((msg + '\n') % headless)
4335 ui.warn((msg + '\n') % headless)
4340
4336
4341 if not heads:
4337 if not heads:
4342 return 1
4338 return 1
4343
4339
4344 heads = sorted(heads, key=lambda x: -x.rev())
4340 heads = sorted(heads, key=lambda x: -x.rev())
4345 displayer = cmdutil.show_changeset(ui, repo, opts)
4341 displayer = cmdutil.show_changeset(ui, repo, opts)
4346 for ctx in heads:
4342 for ctx in heads:
4347 displayer.show(ctx)
4343 displayer.show(ctx)
4348 displayer.close()
4344 displayer.close()
4349
4345
4350 @command('help',
4346 @command('help',
4351 [('e', 'extension', None, _('show only help for extensions')),
4347 [('e', 'extension', None, _('show only help for extensions')),
4352 ('c', 'command', None, _('show only help for commands')),
4348 ('c', 'command', None, _('show only help for commands')),
4353 ('k', 'keyword', None, _('show topics matching keyword')),
4349 ('k', 'keyword', None, _('show topics matching keyword')),
4354 ('s', 'system', [], _('show help for specific platform(s)')),
4350 ('s', 'system', [], _('show help for specific platform(s)')),
4355 ],
4351 ],
4356 _('[-ecks] [TOPIC]'),
4352 _('[-ecks] [TOPIC]'),
4357 norepo=True)
4353 norepo=True)
4358 def help_(ui, name=None, **opts):
4354 def help_(ui, name=None, **opts):
4359 """show help for a given topic or a help overview
4355 """show help for a given topic or a help overview
4360
4356
4361 With no arguments, print a list of commands with short help messages.
4357 With no arguments, print a list of commands with short help messages.
4362
4358
4363 Given a topic, extension, or command name, print help for that
4359 Given a topic, extension, or command name, print help for that
4364 topic.
4360 topic.
4365
4361
4366 Returns 0 if successful.
4362 Returns 0 if successful.
4367 """
4363 """
4368
4364
4369 textwidth = min(ui.termwidth(), 80) - 2
4365 textwidth = min(ui.termwidth(), 80) - 2
4370
4366
4371 keep = opts.get('system') or []
4367 keep = opts.get('system') or []
4372 if len(keep) == 0:
4368 if len(keep) == 0:
4373 if sys.platform.startswith('win'):
4369 if sys.platform.startswith('win'):
4374 keep.append('windows')
4370 keep.append('windows')
4375 elif sys.platform == 'OpenVMS':
4371 elif sys.platform == 'OpenVMS':
4376 keep.append('vms')
4372 keep.append('vms')
4377 elif sys.platform == 'plan9':
4373 elif sys.platform == 'plan9':
4378 keep.append('plan9')
4374 keep.append('plan9')
4379 else:
4375 else:
4380 keep.append('unix')
4376 keep.append('unix')
4381 keep.append(sys.platform.lower())
4377 keep.append(sys.platform.lower())
4382 if ui.verbose:
4378 if ui.verbose:
4383 keep.append('verbose')
4379 keep.append('verbose')
4384
4380
4385 section = None
4381 section = None
4386 subtopic = None
4382 subtopic = None
4387 if name and '.' in name:
4383 if name and '.' in name:
4388 name, section = name.split('.', 1)
4384 name, section = name.split('.', 1)
4389 section = section.lower()
4385 section = section.lower()
4390 if '.' in section:
4386 if '.' in section:
4391 subtopic, section = section.split('.', 1)
4387 subtopic, section = section.split('.', 1)
4392 else:
4388 else:
4393 subtopic = section
4389 subtopic = section
4394
4390
4395 text = help.help_(ui, name, subtopic=subtopic, **opts)
4391 text = help.help_(ui, name, subtopic=subtopic, **opts)
4396
4392
4397 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4393 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4398 section=section)
4394 section=section)
4399
4395
4400 # We could have been given a weird ".foo" section without a name
4396 # We could have been given a weird ".foo" section without a name
4401 # to look for, or we could have simply failed to found "foo.bar"
4397 # to look for, or we could have simply failed to found "foo.bar"
4402 # because bar isn't a section of foo
4398 # because bar isn't a section of foo
4403 if section and not (formatted and name):
4399 if section and not (formatted and name):
4404 raise error.Abort(_("help section not found"))
4400 raise error.Abort(_("help section not found"))
4405
4401
4406 if 'verbose' in pruned:
4402 if 'verbose' in pruned:
4407 keep.append('omitted')
4403 keep.append('omitted')
4408 else:
4404 else:
4409 keep.append('notomitted')
4405 keep.append('notomitted')
4410 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4406 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4411 section=section)
4407 section=section)
4412 ui.write(formatted)
4408 ui.write(formatted)
4413
4409
4414
4410
4415 @command('identify|id',
4411 @command('identify|id',
4416 [('r', 'rev', '',
4412 [('r', 'rev', '',
4417 _('identify the specified revision'), _('REV')),
4413 _('identify the specified revision'), _('REV')),
4418 ('n', 'num', None, _('show local revision number')),
4414 ('n', 'num', None, _('show local revision number')),
4419 ('i', 'id', None, _('show global revision id')),
4415 ('i', 'id', None, _('show global revision id')),
4420 ('b', 'branch', None, _('show branch')),
4416 ('b', 'branch', None, _('show branch')),
4421 ('t', 'tags', None, _('show tags')),
4417 ('t', 'tags', None, _('show tags')),
4422 ('B', 'bookmarks', None, _('show bookmarks')),
4418 ('B', 'bookmarks', None, _('show bookmarks')),
4423 ] + remoteopts,
4419 ] + remoteopts,
4424 _('[-nibtB] [-r REV] [SOURCE]'),
4420 _('[-nibtB] [-r REV] [SOURCE]'),
4425 optionalrepo=True)
4421 optionalrepo=True)
4426 def identify(ui, repo, source=None, rev=None,
4422 def identify(ui, repo, source=None, rev=None,
4427 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4423 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4428 """identify the working directory or specified revision
4424 """identify the working directory or specified revision
4429
4425
4430 Print a summary identifying the repository state at REV using one or
4426 Print a summary identifying the repository state at REV using one or
4431 two parent hash identifiers, followed by a "+" if the working
4427 two parent hash identifiers, followed by a "+" if the working
4432 directory has uncommitted changes, the branch name (if not default),
4428 directory has uncommitted changes, the branch name (if not default),
4433 a list of tags, and a list of bookmarks.
4429 a list of tags, and a list of bookmarks.
4434
4430
4435 When REV is not given, print a summary of the current state of the
4431 When REV is not given, print a summary of the current state of the
4436 repository.
4432 repository.
4437
4433
4438 Specifying a path to a repository root or Mercurial bundle will
4434 Specifying a path to a repository root or Mercurial bundle will
4439 cause lookup to operate on that repository/bundle.
4435 cause lookup to operate on that repository/bundle.
4440
4436
4441 .. container:: verbose
4437 .. container:: verbose
4442
4438
4443 Examples:
4439 Examples:
4444
4440
4445 - generate a build identifier for the working directory::
4441 - generate a build identifier for the working directory::
4446
4442
4447 hg id --id > build-id.dat
4443 hg id --id > build-id.dat
4448
4444
4449 - find the revision corresponding to a tag::
4445 - find the revision corresponding to a tag::
4450
4446
4451 hg id -n -r 1.3
4447 hg id -n -r 1.3
4452
4448
4453 - check the most recent revision of a remote repository::
4449 - check the most recent revision of a remote repository::
4454
4450
4455 hg id -r tip http://selenic.com/hg/
4451 hg id -r tip http://selenic.com/hg/
4456
4452
4457 See :hg:`log` for generating more information about specific revisions,
4453 See :hg:`log` for generating more information about specific revisions,
4458 including full hash identifiers.
4454 including full hash identifiers.
4459
4455
4460 Returns 0 if successful.
4456 Returns 0 if successful.
4461 """
4457 """
4462
4458
4463 if not repo and not source:
4459 if not repo and not source:
4464 raise error.Abort(_("there is no Mercurial repository here "
4460 raise error.Abort(_("there is no Mercurial repository here "
4465 "(.hg not found)"))
4461 "(.hg not found)"))
4466
4462
4467 if ui.debugflag:
4463 if ui.debugflag:
4468 hexfunc = hex
4464 hexfunc = hex
4469 else:
4465 else:
4470 hexfunc = short
4466 hexfunc = short
4471 default = not (num or id or branch or tags or bookmarks)
4467 default = not (num or id or branch or tags or bookmarks)
4472 output = []
4468 output = []
4473 revs = []
4469 revs = []
4474
4470
4475 if source:
4471 if source:
4476 source, branches = hg.parseurl(ui.expandpath(source))
4472 source, branches = hg.parseurl(ui.expandpath(source))
4477 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4473 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4478 repo = peer.local()
4474 repo = peer.local()
4479 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4475 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4480
4476
4481 if not repo:
4477 if not repo:
4482 if num or branch or tags:
4478 if num or branch or tags:
4483 raise error.Abort(
4479 raise error.Abort(
4484 _("can't query remote revision number, branch, or tags"))
4480 _("can't query remote revision number, branch, or tags"))
4485 if not rev and revs:
4481 if not rev and revs:
4486 rev = revs[0]
4482 rev = revs[0]
4487 if not rev:
4483 if not rev:
4488 rev = "tip"
4484 rev = "tip"
4489
4485
4490 remoterev = peer.lookup(rev)
4486 remoterev = peer.lookup(rev)
4491 if default or id:
4487 if default or id:
4492 output = [hexfunc(remoterev)]
4488 output = [hexfunc(remoterev)]
4493
4489
4494 def getbms():
4490 def getbms():
4495 bms = []
4491 bms = []
4496
4492
4497 if 'bookmarks' in peer.listkeys('namespaces'):
4493 if 'bookmarks' in peer.listkeys('namespaces'):
4498 hexremoterev = hex(remoterev)
4494 hexremoterev = hex(remoterev)
4499 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4495 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4500 if bmr == hexremoterev]
4496 if bmr == hexremoterev]
4501
4497
4502 return sorted(bms)
4498 return sorted(bms)
4503
4499
4504 if bookmarks:
4500 if bookmarks:
4505 output.extend(getbms())
4501 output.extend(getbms())
4506 elif default and not ui.quiet:
4502 elif default and not ui.quiet:
4507 # multiple bookmarks for a single parent separated by '/'
4503 # multiple bookmarks for a single parent separated by '/'
4508 bm = '/'.join(getbms())
4504 bm = '/'.join(getbms())
4509 if bm:
4505 if bm:
4510 output.append(bm)
4506 output.append(bm)
4511 else:
4507 else:
4512 ctx = scmutil.revsingle(repo, rev, None)
4508 ctx = scmutil.revsingle(repo, rev, None)
4513
4509
4514 if ctx.rev() is None:
4510 if ctx.rev() is None:
4515 ctx = repo[None]
4511 ctx = repo[None]
4516 parents = ctx.parents()
4512 parents = ctx.parents()
4517 taglist = []
4513 taglist = []
4518 for p in parents:
4514 for p in parents:
4519 taglist.extend(p.tags())
4515 taglist.extend(p.tags())
4520
4516
4521 changed = ""
4517 changed = ""
4522 if default or id or num:
4518 if default or id or num:
4523 if (any(repo.status())
4519 if (any(repo.status())
4524 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4520 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4525 changed = '+'
4521 changed = '+'
4526 if default or id:
4522 if default or id:
4527 output = ["%s%s" %
4523 output = ["%s%s" %
4528 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4524 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4529 if num:
4525 if num:
4530 output.append("%s%s" %
4526 output.append("%s%s" %
4531 ('+'.join([str(p.rev()) for p in parents]), changed))
4527 ('+'.join([str(p.rev()) for p in parents]), changed))
4532 else:
4528 else:
4533 if default or id:
4529 if default or id:
4534 output = [hexfunc(ctx.node())]
4530 output = [hexfunc(ctx.node())]
4535 if num:
4531 if num:
4536 output.append(str(ctx.rev()))
4532 output.append(str(ctx.rev()))
4537 taglist = ctx.tags()
4533 taglist = ctx.tags()
4538
4534
4539 if default and not ui.quiet:
4535 if default and not ui.quiet:
4540 b = ctx.branch()
4536 b = ctx.branch()
4541 if b != 'default':
4537 if b != 'default':
4542 output.append("(%s)" % b)
4538 output.append("(%s)" % b)
4543
4539
4544 # multiple tags for a single parent separated by '/'
4540 # multiple tags for a single parent separated by '/'
4545 t = '/'.join(taglist)
4541 t = '/'.join(taglist)
4546 if t:
4542 if t:
4547 output.append(t)
4543 output.append(t)
4548
4544
4549 # multiple bookmarks for a single parent separated by '/'
4545 # multiple bookmarks for a single parent separated by '/'
4550 bm = '/'.join(ctx.bookmarks())
4546 bm = '/'.join(ctx.bookmarks())
4551 if bm:
4547 if bm:
4552 output.append(bm)
4548 output.append(bm)
4553 else:
4549 else:
4554 if branch:
4550 if branch:
4555 output.append(ctx.branch())
4551 output.append(ctx.branch())
4556
4552
4557 if tags:
4553 if tags:
4558 output.extend(taglist)
4554 output.extend(taglist)
4559
4555
4560 if bookmarks:
4556 if bookmarks:
4561 output.extend(ctx.bookmarks())
4557 output.extend(ctx.bookmarks())
4562
4558
4563 ui.write("%s\n" % ' '.join(output))
4559 ui.write("%s\n" % ' '.join(output))
4564
4560
4565 @command('import|patch',
4561 @command('import|patch',
4566 [('p', 'strip', 1,
4562 [('p', 'strip', 1,
4567 _('directory strip option for patch. This has the same '
4563 _('directory strip option for patch. This has the same '
4568 'meaning as the corresponding patch option'), _('NUM')),
4564 'meaning as the corresponding patch option'), _('NUM')),
4569 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4565 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4570 ('e', 'edit', False, _('invoke editor on commit messages')),
4566 ('e', 'edit', False, _('invoke editor on commit messages')),
4571 ('f', 'force', None,
4567 ('f', 'force', None,
4572 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4568 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4573 ('', 'no-commit', None,
4569 ('', 'no-commit', None,
4574 _("don't commit, just update the working directory")),
4570 _("don't commit, just update the working directory")),
4575 ('', 'bypass', None,
4571 ('', 'bypass', None,
4576 _("apply patch without touching the working directory")),
4572 _("apply patch without touching the working directory")),
4577 ('', 'partial', None,
4573 ('', 'partial', None,
4578 _('commit even if some hunks fail')),
4574 _('commit even if some hunks fail')),
4579 ('', 'exact', None,
4575 ('', 'exact', None,
4580 _('apply patch to the nodes from which it was generated')),
4576 _('apply patch to the nodes from which it was generated')),
4581 ('', 'prefix', '',
4577 ('', 'prefix', '',
4582 _('apply patch to subdirectory'), _('DIR')),
4578 _('apply patch to subdirectory'), _('DIR')),
4583 ('', 'import-branch', None,
4579 ('', 'import-branch', None,
4584 _('use any branch information in patch (implied by --exact)'))] +
4580 _('use any branch information in patch (implied by --exact)'))] +
4585 commitopts + commitopts2 + similarityopts,
4581 commitopts + commitopts2 + similarityopts,
4586 _('[OPTION]... PATCH...'))
4582 _('[OPTION]... PATCH...'))
4587 def import_(ui, repo, patch1=None, *patches, **opts):
4583 def import_(ui, repo, patch1=None, *patches, **opts):
4588 """import an ordered set of patches
4584 """import an ordered set of patches
4589
4585
4590 Import a list of patches and commit them individually (unless
4586 Import a list of patches and commit them individually (unless
4591 --no-commit is specified).
4587 --no-commit is specified).
4592
4588
4593 To read a patch from standard input, use "-" as the patch name. If
4589 To read a patch from standard input, use "-" as the patch name. If
4594 a URL is specified, the patch will be downloaded from there.
4590 a URL is specified, the patch will be downloaded from there.
4595
4591
4596 Import first applies changes to the working directory (unless
4592 Import first applies changes to the working directory (unless
4597 --bypass is specified), import will abort if there are outstanding
4593 --bypass is specified), import will abort if there are outstanding
4598 changes.
4594 changes.
4599
4595
4600 Use --bypass to apply and commit patches directly to the
4596 Use --bypass to apply and commit patches directly to the
4601 repository, without affecting the working directory. Without
4597 repository, without affecting the working directory. Without
4602 --exact, patches will be applied on top of the working directory
4598 --exact, patches will be applied on top of the working directory
4603 parent revision.
4599 parent revision.
4604
4600
4605 You can import a patch straight from a mail message. Even patches
4601 You can import a patch straight from a mail message. Even patches
4606 as attachments work (to use the body part, it must have type
4602 as attachments work (to use the body part, it must have type
4607 text/plain or text/x-patch). From and Subject headers of email
4603 text/plain or text/x-patch). From and Subject headers of email
4608 message are used as default committer and commit message. All
4604 message are used as default committer and commit message. All
4609 text/plain body parts before first diff are added to the commit
4605 text/plain body parts before first diff are added to the commit
4610 message.
4606 message.
4611
4607
4612 If the imported patch was generated by :hg:`export`, user and
4608 If the imported patch was generated by :hg:`export`, user and
4613 description from patch override values from message headers and
4609 description from patch override values from message headers and
4614 body. Values given on command line with -m/--message and -u/--user
4610 body. Values given on command line with -m/--message and -u/--user
4615 override these.
4611 override these.
4616
4612
4617 If --exact is specified, import will set the working directory to
4613 If --exact is specified, import will set the working directory to
4618 the parent of each patch before applying it, and will abort if the
4614 the parent of each patch before applying it, and will abort if the
4619 resulting changeset has a different ID than the one recorded in
4615 resulting changeset has a different ID than the one recorded in
4620 the patch. This may happen due to character set problems or other
4616 the patch. This may happen due to character set problems or other
4621 deficiencies in the text patch format.
4617 deficiencies in the text patch format.
4622
4618
4623 Use --partial to ensure a changeset will be created from the patch
4619 Use --partial to ensure a changeset will be created from the patch
4624 even if some hunks fail to apply. Hunks that fail to apply will be
4620 even if some hunks fail to apply. Hunks that fail to apply will be
4625 written to a <target-file>.rej file. Conflicts can then be resolved
4621 written to a <target-file>.rej file. Conflicts can then be resolved
4626 by hand before :hg:`commit --amend` is run to update the created
4622 by hand before :hg:`commit --amend` is run to update the created
4627 changeset. This flag exists to let people import patches that
4623 changeset. This flag exists to let people import patches that
4628 partially apply without losing the associated metadata (author,
4624 partially apply without losing the associated metadata (author,
4629 date, description, ...).
4625 date, description, ...).
4630
4626
4631 .. note::
4627 .. note::
4632
4628
4633 When no hunks apply cleanly, :hg:`import --partial` will create
4629 When no hunks apply cleanly, :hg:`import --partial` will create
4634 an empty changeset, importing only the patch metadata.
4630 an empty changeset, importing only the patch metadata.
4635
4631
4636 With -s/--similarity, hg will attempt to discover renames and
4632 With -s/--similarity, hg will attempt to discover renames and
4637 copies in the patch in the same way as :hg:`addremove`.
4633 copies in the patch in the same way as :hg:`addremove`.
4638
4634
4639 It is possible to use external patch programs to perform the patch
4635 It is possible to use external patch programs to perform the patch
4640 by setting the ``ui.patch`` configuration option. For the default
4636 by setting the ``ui.patch`` configuration option. For the default
4641 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4637 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4642 See :hg:`help config` for more information about configuration
4638 See :hg:`help config` for more information about configuration
4643 files and how to use these options.
4639 files and how to use these options.
4644
4640
4645 See :hg:`help dates` for a list of formats valid for -d/--date.
4641 See :hg:`help dates` for a list of formats valid for -d/--date.
4646
4642
4647 .. container:: verbose
4643 .. container:: verbose
4648
4644
4649 Examples:
4645 Examples:
4650
4646
4651 - import a traditional patch from a website and detect renames::
4647 - import a traditional patch from a website and detect renames::
4652
4648
4653 hg import -s 80 http://example.com/bugfix.patch
4649 hg import -s 80 http://example.com/bugfix.patch
4654
4650
4655 - import a changeset from an hgweb server::
4651 - import a changeset from an hgweb server::
4656
4652
4657 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4653 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4658
4654
4659 - import all the patches in an Unix-style mbox::
4655 - import all the patches in an Unix-style mbox::
4660
4656
4661 hg import incoming-patches.mbox
4657 hg import incoming-patches.mbox
4662
4658
4663 - attempt to exactly restore an exported changeset (not always
4659 - attempt to exactly restore an exported changeset (not always
4664 possible)::
4660 possible)::
4665
4661
4666 hg import --exact proposed-fix.patch
4662 hg import --exact proposed-fix.patch
4667
4663
4668 - use an external tool to apply a patch which is too fuzzy for
4664 - use an external tool to apply a patch which is too fuzzy for
4669 the default internal tool.
4665 the default internal tool.
4670
4666
4671 hg import --config ui.patch="patch --merge" fuzzy.patch
4667 hg import --config ui.patch="patch --merge" fuzzy.patch
4672
4668
4673 - change the default fuzzing from 2 to a less strict 7
4669 - change the default fuzzing from 2 to a less strict 7
4674
4670
4675 hg import --config ui.fuzz=7 fuzz.patch
4671 hg import --config ui.fuzz=7 fuzz.patch
4676
4672
4677 Returns 0 on success, 1 on partial success (see --partial).
4673 Returns 0 on success, 1 on partial success (see --partial).
4678 """
4674 """
4679
4675
4680 if not patch1:
4676 if not patch1:
4681 raise error.Abort(_('need at least one patch to import'))
4677 raise error.Abort(_('need at least one patch to import'))
4682
4678
4683 patches = (patch1,) + patches
4679 patches = (patch1,) + patches
4684
4680
4685 date = opts.get('date')
4681 date = opts.get('date')
4686 if date:
4682 if date:
4687 opts['date'] = util.parsedate(date)
4683 opts['date'] = util.parsedate(date)
4688
4684
4689 exact = opts.get('exact')
4685 exact = opts.get('exact')
4690 update = not opts.get('bypass')
4686 update = not opts.get('bypass')
4691 if not update and opts.get('no_commit'):
4687 if not update and opts.get('no_commit'):
4692 raise error.Abort(_('cannot use --no-commit with --bypass'))
4688 raise error.Abort(_('cannot use --no-commit with --bypass'))
4693 try:
4689 try:
4694 sim = float(opts.get('similarity') or 0)
4690 sim = float(opts.get('similarity') or 0)
4695 except ValueError:
4691 except ValueError:
4696 raise error.Abort(_('similarity must be a number'))
4692 raise error.Abort(_('similarity must be a number'))
4697 if sim < 0 or sim > 100:
4693 if sim < 0 or sim > 100:
4698 raise error.Abort(_('similarity must be between 0 and 100'))
4694 raise error.Abort(_('similarity must be between 0 and 100'))
4699 if sim and not update:
4695 if sim and not update:
4700 raise error.Abort(_('cannot use --similarity with --bypass'))
4696 raise error.Abort(_('cannot use --similarity with --bypass'))
4701 if exact:
4697 if exact:
4702 if opts.get('edit'):
4698 if opts.get('edit'):
4703 raise error.Abort(_('cannot use --exact with --edit'))
4699 raise error.Abort(_('cannot use --exact with --edit'))
4704 if opts.get('prefix'):
4700 if opts.get('prefix'):
4705 raise error.Abort(_('cannot use --exact with --prefix'))
4701 raise error.Abort(_('cannot use --exact with --prefix'))
4706
4702
4707 base = opts["base"]
4703 base = opts["base"]
4708 wlock = dsguard = lock = tr = None
4704 wlock = dsguard = lock = tr = None
4709 msgs = []
4705 msgs = []
4710 ret = 0
4706 ret = 0
4711
4707
4712
4708
4713 try:
4709 try:
4714 wlock = repo.wlock()
4710 wlock = repo.wlock()
4715
4711
4716 if update:
4712 if update:
4717 cmdutil.checkunfinished(repo)
4713 cmdutil.checkunfinished(repo)
4718 if (exact or not opts.get('force')):
4714 if (exact or not opts.get('force')):
4719 cmdutil.bailifchanged(repo)
4715 cmdutil.bailifchanged(repo)
4720
4716
4721 if not opts.get('no_commit'):
4717 if not opts.get('no_commit'):
4722 lock = repo.lock()
4718 lock = repo.lock()
4723 tr = repo.transaction('import')
4719 tr = repo.transaction('import')
4724 else:
4720 else:
4725 dsguard = cmdutil.dirstateguard(repo, 'import')
4721 dsguard = cmdutil.dirstateguard(repo, 'import')
4726 parents = repo[None].parents()
4722 parents = repo[None].parents()
4727 for patchurl in patches:
4723 for patchurl in patches:
4728 if patchurl == '-':
4724 if patchurl == '-':
4729 ui.status(_('applying patch from stdin\n'))
4725 ui.status(_('applying patch from stdin\n'))
4730 patchfile = ui.fin
4726 patchfile = ui.fin
4731 patchurl = 'stdin' # for error message
4727 patchurl = 'stdin' # for error message
4732 else:
4728 else:
4733 patchurl = os.path.join(base, patchurl)
4729 patchurl = os.path.join(base, patchurl)
4734 ui.status(_('applying %s\n') % patchurl)
4730 ui.status(_('applying %s\n') % patchurl)
4735 patchfile = hg.openpath(ui, patchurl)
4731 patchfile = hg.openpath(ui, patchurl)
4736
4732
4737 haspatch = False
4733 haspatch = False
4738 for hunk in patch.split(patchfile):
4734 for hunk in patch.split(patchfile):
4739 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4735 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4740 parents, opts,
4736 parents, opts,
4741 msgs, hg.clean)
4737 msgs, hg.clean)
4742 if msg:
4738 if msg:
4743 haspatch = True
4739 haspatch = True
4744 ui.note(msg + '\n')
4740 ui.note(msg + '\n')
4745 if update or exact:
4741 if update or exact:
4746 parents = repo[None].parents()
4742 parents = repo[None].parents()
4747 else:
4743 else:
4748 parents = [repo[node]]
4744 parents = [repo[node]]
4749 if rej:
4745 if rej:
4750 ui.write_err(_("patch applied partially\n"))
4746 ui.write_err(_("patch applied partially\n"))
4751 ui.write_err(_("(fix the .rej files and run "
4747 ui.write_err(_("(fix the .rej files and run "
4752 "`hg commit --amend`)\n"))
4748 "`hg commit --amend`)\n"))
4753 ret = 1
4749 ret = 1
4754 break
4750 break
4755
4751
4756 if not haspatch:
4752 if not haspatch:
4757 raise error.Abort(_('%s: no diffs found') % patchurl)
4753 raise error.Abort(_('%s: no diffs found') % patchurl)
4758
4754
4759 if tr:
4755 if tr:
4760 tr.close()
4756 tr.close()
4761 if msgs:
4757 if msgs:
4762 repo.savecommitmessage('\n* * *\n'.join(msgs))
4758 repo.savecommitmessage('\n* * *\n'.join(msgs))
4763 if dsguard:
4759 if dsguard:
4764 dsguard.close()
4760 dsguard.close()
4765 return ret
4761 return ret
4766 finally:
4762 finally:
4767 if tr:
4763 if tr:
4768 tr.release()
4764 tr.release()
4769 release(lock, dsguard, wlock)
4765 release(lock, dsguard, wlock)
4770
4766
4771 @command('incoming|in',
4767 @command('incoming|in',
4772 [('f', 'force', None,
4768 [('f', 'force', None,
4773 _('run even if remote repository is unrelated')),
4769 _('run even if remote repository is unrelated')),
4774 ('n', 'newest-first', None, _('show newest record first')),
4770 ('n', 'newest-first', None, _('show newest record first')),
4775 ('', 'bundle', '',
4771 ('', 'bundle', '',
4776 _('file to store the bundles into'), _('FILE')),
4772 _('file to store the bundles into'), _('FILE')),
4777 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4773 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4778 ('B', 'bookmarks', False, _("compare bookmarks")),
4774 ('B', 'bookmarks', False, _("compare bookmarks")),
4779 ('b', 'branch', [],
4775 ('b', 'branch', [],
4780 _('a specific branch you would like to pull'), _('BRANCH')),
4776 _('a specific branch you would like to pull'), _('BRANCH')),
4781 ] + logopts + remoteopts + subrepoopts,
4777 ] + logopts + remoteopts + subrepoopts,
4782 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4778 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4783 def incoming(ui, repo, source="default", **opts):
4779 def incoming(ui, repo, source="default", **opts):
4784 """show new changesets found in source
4780 """show new changesets found in source
4785
4781
4786 Show new changesets found in the specified path/URL or the default
4782 Show new changesets found in the specified path/URL or the default
4787 pull location. These are the changesets that would have been pulled
4783 pull location. These are the changesets that would have been pulled
4788 if a pull at the time you issued this command.
4784 if a pull at the time you issued this command.
4789
4785
4790 See pull for valid source format details.
4786 See pull for valid source format details.
4791
4787
4792 .. container:: verbose
4788 .. container:: verbose
4793
4789
4794 With -B/--bookmarks, the result of bookmark comparison between
4790 With -B/--bookmarks, the result of bookmark comparison between
4795 local and remote repositories is displayed. With -v/--verbose,
4791 local and remote repositories is displayed. With -v/--verbose,
4796 status is also displayed for each bookmark like below::
4792 status is also displayed for each bookmark like below::
4797
4793
4798 BM1 01234567890a added
4794 BM1 01234567890a added
4799 BM2 1234567890ab advanced
4795 BM2 1234567890ab advanced
4800 BM3 234567890abc diverged
4796 BM3 234567890abc diverged
4801 BM4 34567890abcd changed
4797 BM4 34567890abcd changed
4802
4798
4803 The action taken locally when pulling depends on the
4799 The action taken locally when pulling depends on the
4804 status of each bookmark:
4800 status of each bookmark:
4805
4801
4806 :``added``: pull will create it
4802 :``added``: pull will create it
4807 :``advanced``: pull will update it
4803 :``advanced``: pull will update it
4808 :``diverged``: pull will create a divergent bookmark
4804 :``diverged``: pull will create a divergent bookmark
4809 :``changed``: result depends on remote changesets
4805 :``changed``: result depends on remote changesets
4810
4806
4811 From the point of view of pulling behavior, bookmark
4807 From the point of view of pulling behavior, bookmark
4812 existing only in the remote repository are treated as ``added``,
4808 existing only in the remote repository are treated as ``added``,
4813 even if it is in fact locally deleted.
4809 even if it is in fact locally deleted.
4814
4810
4815 .. container:: verbose
4811 .. container:: verbose
4816
4812
4817 For remote repository, using --bundle avoids downloading the
4813 For remote repository, using --bundle avoids downloading the
4818 changesets twice if the incoming is followed by a pull.
4814 changesets twice if the incoming is followed by a pull.
4819
4815
4820 Examples:
4816 Examples:
4821
4817
4822 - show incoming changes with patches and full description::
4818 - show incoming changes with patches and full description::
4823
4819
4824 hg incoming -vp
4820 hg incoming -vp
4825
4821
4826 - show incoming changes excluding merges, store a bundle::
4822 - show incoming changes excluding merges, store a bundle::
4827
4823
4828 hg in -vpM --bundle incoming.hg
4824 hg in -vpM --bundle incoming.hg
4829 hg pull incoming.hg
4825 hg pull incoming.hg
4830
4826
4831 - briefly list changes inside a bundle::
4827 - briefly list changes inside a bundle::
4832
4828
4833 hg in changes.hg -T "{desc|firstline}\\n"
4829 hg in changes.hg -T "{desc|firstline}\\n"
4834
4830
4835 Returns 0 if there are incoming changes, 1 otherwise.
4831 Returns 0 if there are incoming changes, 1 otherwise.
4836 """
4832 """
4837 if opts.get('graph'):
4833 if opts.get('graph'):
4838 cmdutil.checkunsupportedgraphflags([], opts)
4834 cmdutil.checkunsupportedgraphflags([], opts)
4839 def display(other, chlist, displayer):
4835 def display(other, chlist, displayer):
4840 revdag = cmdutil.graphrevs(other, chlist, opts)
4836 revdag = cmdutil.graphrevs(other, chlist, opts)
4841 cmdutil.displaygraph(ui, repo, revdag, displayer,
4837 cmdutil.displaygraph(ui, repo, revdag, displayer,
4842 graphmod.asciiedges)
4838 graphmod.asciiedges)
4843
4839
4844 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4840 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4845 return 0
4841 return 0
4846
4842
4847 if opts.get('bundle') and opts.get('subrepos'):
4843 if opts.get('bundle') and opts.get('subrepos'):
4848 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4844 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4849
4845
4850 if opts.get('bookmarks'):
4846 if opts.get('bookmarks'):
4851 source, branches = hg.parseurl(ui.expandpath(source),
4847 source, branches = hg.parseurl(ui.expandpath(source),
4852 opts.get('branch'))
4848 opts.get('branch'))
4853 other = hg.peer(repo, opts, source)
4849 other = hg.peer(repo, opts, source)
4854 if 'bookmarks' not in other.listkeys('namespaces'):
4850 if 'bookmarks' not in other.listkeys('namespaces'):
4855 ui.warn(_("remote doesn't support bookmarks\n"))
4851 ui.warn(_("remote doesn't support bookmarks\n"))
4856 return 0
4852 return 0
4857 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4853 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4858 return bookmarks.incoming(ui, repo, other)
4854 return bookmarks.incoming(ui, repo, other)
4859
4855
4860 repo._subtoppath = ui.expandpath(source)
4856 repo._subtoppath = ui.expandpath(source)
4861 try:
4857 try:
4862 return hg.incoming(ui, repo, source, opts)
4858 return hg.incoming(ui, repo, source, opts)
4863 finally:
4859 finally:
4864 del repo._subtoppath
4860 del repo._subtoppath
4865
4861
4866
4862
4867 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4863 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4868 norepo=True)
4864 norepo=True)
4869 def init(ui, dest=".", **opts):
4865 def init(ui, dest=".", **opts):
4870 """create a new repository in the given directory
4866 """create a new repository in the given directory
4871
4867
4872 Initialize a new repository in the given directory. If the given
4868 Initialize a new repository in the given directory. If the given
4873 directory does not exist, it will be created.
4869 directory does not exist, it will be created.
4874
4870
4875 If no directory is given, the current directory is used.
4871 If no directory is given, the current directory is used.
4876
4872
4877 It is possible to specify an ``ssh://`` URL as the destination.
4873 It is possible to specify an ``ssh://`` URL as the destination.
4878 See :hg:`help urls` for more information.
4874 See :hg:`help urls` for more information.
4879
4875
4880 Returns 0 on success.
4876 Returns 0 on success.
4881 """
4877 """
4882 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4878 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4883
4879
4884 @command('locate',
4880 @command('locate',
4885 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4881 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4886 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4882 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4887 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4883 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4888 ] + walkopts,
4884 ] + walkopts,
4889 _('[OPTION]... [PATTERN]...'))
4885 _('[OPTION]... [PATTERN]...'))
4890 def locate(ui, repo, *pats, **opts):
4886 def locate(ui, repo, *pats, **opts):
4891 """locate files matching specific patterns (DEPRECATED)
4887 """locate files matching specific patterns (DEPRECATED)
4892
4888
4893 Print files under Mercurial control in the working directory whose
4889 Print files under Mercurial control in the working directory whose
4894 names match the given patterns.
4890 names match the given patterns.
4895
4891
4896 By default, this command searches all directories in the working
4892 By default, this command searches all directories in the working
4897 directory. To search just the current directory and its
4893 directory. To search just the current directory and its
4898 subdirectories, use "--include .".
4894 subdirectories, use "--include .".
4899
4895
4900 If no patterns are given to match, this command prints the names
4896 If no patterns are given to match, this command prints the names
4901 of all files under Mercurial control in the working directory.
4897 of all files under Mercurial control in the working directory.
4902
4898
4903 If you want to feed the output of this command into the "xargs"
4899 If you want to feed the output of this command into the "xargs"
4904 command, use the -0 option to both this command and "xargs". This
4900 command, use the -0 option to both this command and "xargs". This
4905 will avoid the problem of "xargs" treating single filenames that
4901 will avoid the problem of "xargs" treating single filenames that
4906 contain whitespace as multiple filenames.
4902 contain whitespace as multiple filenames.
4907
4903
4908 See :hg:`help files` for a more versatile command.
4904 See :hg:`help files` for a more versatile command.
4909
4905
4910 Returns 0 if a match is found, 1 otherwise.
4906 Returns 0 if a match is found, 1 otherwise.
4911 """
4907 """
4912 if opts.get('print0'):
4908 if opts.get('print0'):
4913 end = '\0'
4909 end = '\0'
4914 else:
4910 else:
4915 end = '\n'
4911 end = '\n'
4916 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4912 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4917
4913
4918 ret = 1
4914 ret = 1
4919 ctx = repo[rev]
4915 ctx = repo[rev]
4920 m = scmutil.match(ctx, pats, opts, default='relglob',
4916 m = scmutil.match(ctx, pats, opts, default='relglob',
4921 badfn=lambda x, y: False)
4917 badfn=lambda x, y: False)
4922
4918
4923 for abs in ctx.matches(m):
4919 for abs in ctx.matches(m):
4924 if opts.get('fullpath'):
4920 if opts.get('fullpath'):
4925 ui.write(repo.wjoin(abs), end)
4921 ui.write(repo.wjoin(abs), end)
4926 else:
4922 else:
4927 ui.write(((pats and m.rel(abs)) or abs), end)
4923 ui.write(((pats and m.rel(abs)) or abs), end)
4928 ret = 0
4924 ret = 0
4929
4925
4930 return ret
4926 return ret
4931
4927
4932 @command('^log|history',
4928 @command('^log|history',
4933 [('f', 'follow', None,
4929 [('f', 'follow', None,
4934 _('follow changeset history, or file history across copies and renames')),
4930 _('follow changeset history, or file history across copies and renames')),
4935 ('', 'follow-first', None,
4931 ('', 'follow-first', None,
4936 _('only follow the first parent of merge changesets (DEPRECATED)')),
4932 _('only follow the first parent of merge changesets (DEPRECATED)')),
4937 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4933 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4938 ('C', 'copies', None, _('show copied files')),
4934 ('C', 'copies', None, _('show copied files')),
4939 ('k', 'keyword', [],
4935 ('k', 'keyword', [],
4940 _('do case-insensitive search for a given text'), _('TEXT')),
4936 _('do case-insensitive search for a given text'), _('TEXT')),
4941 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4937 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4942 ('', 'removed', None, _('include revisions where files were removed')),
4938 ('', 'removed', None, _('include revisions where files were removed')),
4943 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4939 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4944 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4940 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4945 ('', 'only-branch', [],
4941 ('', 'only-branch', [],
4946 _('show only changesets within the given named branch (DEPRECATED)'),
4942 _('show only changesets within the given named branch (DEPRECATED)'),
4947 _('BRANCH')),
4943 _('BRANCH')),
4948 ('b', 'branch', [],
4944 ('b', 'branch', [],
4949 _('show changesets within the given named branch'), _('BRANCH')),
4945 _('show changesets within the given named branch'), _('BRANCH')),
4950 ('P', 'prune', [],
4946 ('P', 'prune', [],
4951 _('do not display revision or any of its ancestors'), _('REV')),
4947 _('do not display revision or any of its ancestors'), _('REV')),
4952 ] + logopts + walkopts,
4948 ] + logopts + walkopts,
4953 _('[OPTION]... [FILE]'),
4949 _('[OPTION]... [FILE]'),
4954 inferrepo=True)
4950 inferrepo=True)
4955 def log(ui, repo, *pats, **opts):
4951 def log(ui, repo, *pats, **opts):
4956 """show revision history of entire repository or files
4952 """show revision history of entire repository or files
4957
4953
4958 Print the revision history of the specified files or the entire
4954 Print the revision history of the specified files or the entire
4959 project.
4955 project.
4960
4956
4961 If no revision range is specified, the default is ``tip:0`` unless
4957 If no revision range is specified, the default is ``tip:0`` unless
4962 --follow is set, in which case the working directory parent is
4958 --follow is set, in which case the working directory parent is
4963 used as the starting revision.
4959 used as the starting revision.
4964
4960
4965 File history is shown without following rename or copy history of
4961 File history is shown without following rename or copy history of
4966 files. Use -f/--follow with a filename to follow history across
4962 files. Use -f/--follow with a filename to follow history across
4967 renames and copies. --follow without a filename will only show
4963 renames and copies. --follow without a filename will only show
4968 ancestors or descendants of the starting revision.
4964 ancestors or descendants of the starting revision.
4969
4965
4970 By default this command prints revision number and changeset id,
4966 By default this command prints revision number and changeset id,
4971 tags, non-trivial parents, user, date and time, and a summary for
4967 tags, non-trivial parents, user, date and time, and a summary for
4972 each commit. When the -v/--verbose switch is used, the list of
4968 each commit. When the -v/--verbose switch is used, the list of
4973 changed files and full commit message are shown.
4969 changed files and full commit message are shown.
4974
4970
4975 With --graph the revisions are shown as an ASCII art DAG with the most
4971 With --graph the revisions are shown as an ASCII art DAG with the most
4976 recent changeset at the top.
4972 recent changeset at the top.
4977 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4973 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4978 and '+' represents a fork where the changeset from the lines below is a
4974 and '+' represents a fork where the changeset from the lines below is a
4979 parent of the 'o' merge on the same line.
4975 parent of the 'o' merge on the same line.
4980
4976
4981 .. note::
4977 .. note::
4982
4978
4983 :hg:`log --patch` may generate unexpected diff output for merge
4979 :hg:`log --patch` may generate unexpected diff output for merge
4984 changesets, as it will only compare the merge changeset against
4980 changesets, as it will only compare the merge changeset against
4985 its first parent. Also, only files different from BOTH parents
4981 its first parent. Also, only files different from BOTH parents
4986 will appear in files:.
4982 will appear in files:.
4987
4983
4988 .. note::
4984 .. note::
4989
4985
4990 For performance reasons, :hg:`log FILE` may omit duplicate changes
4986 For performance reasons, :hg:`log FILE` may omit duplicate changes
4991 made on branches and will not show removals or mode changes. To
4987 made on branches and will not show removals or mode changes. To
4992 see all such changes, use the --removed switch.
4988 see all such changes, use the --removed switch.
4993
4989
4994 .. container:: verbose
4990 .. container:: verbose
4995
4991
4996 Some examples:
4992 Some examples:
4997
4993
4998 - changesets with full descriptions and file lists::
4994 - changesets with full descriptions and file lists::
4999
4995
5000 hg log -v
4996 hg log -v
5001
4997
5002 - changesets ancestral to the working directory::
4998 - changesets ancestral to the working directory::
5003
4999
5004 hg log -f
5000 hg log -f
5005
5001
5006 - last 10 commits on the current branch::
5002 - last 10 commits on the current branch::
5007
5003
5008 hg log -l 10 -b .
5004 hg log -l 10 -b .
5009
5005
5010 - changesets showing all modifications of a file, including removals::
5006 - changesets showing all modifications of a file, including removals::
5011
5007
5012 hg log --removed file.c
5008 hg log --removed file.c
5013
5009
5014 - all changesets that touch a directory, with diffs, excluding merges::
5010 - all changesets that touch a directory, with diffs, excluding merges::
5015
5011
5016 hg log -Mp lib/
5012 hg log -Mp lib/
5017
5013
5018 - all revision numbers that match a keyword::
5014 - all revision numbers that match a keyword::
5019
5015
5020 hg log -k bug --template "{rev}\\n"
5016 hg log -k bug --template "{rev}\\n"
5021
5017
5022 - the full hash identifier of the working directory parent::
5018 - the full hash identifier of the working directory parent::
5023
5019
5024 hg log -r . --template "{node}\\n"
5020 hg log -r . --template "{node}\\n"
5025
5021
5026 - list available log templates::
5022 - list available log templates::
5027
5023
5028 hg log -T list
5024 hg log -T list
5029
5025
5030 - check if a given changeset is included in a tagged release::
5026 - check if a given changeset is included in a tagged release::
5031
5027
5032 hg log -r "a21ccf and ancestor(1.9)"
5028 hg log -r "a21ccf and ancestor(1.9)"
5033
5029
5034 - find all changesets by some user in a date range::
5030 - find all changesets by some user in a date range::
5035
5031
5036 hg log -k alice -d "may 2008 to jul 2008"
5032 hg log -k alice -d "may 2008 to jul 2008"
5037
5033
5038 - summary of all changesets after the last tag::
5034 - summary of all changesets after the last tag::
5039
5035
5040 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5036 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5041
5037
5042 See :hg:`help dates` for a list of formats valid for -d/--date.
5038 See :hg:`help dates` for a list of formats valid for -d/--date.
5043
5039
5044 See :hg:`help revisions` and :hg:`help revsets` for more about
5040 See :hg:`help revisions` and :hg:`help revsets` for more about
5045 specifying and ordering revisions.
5041 specifying and ordering revisions.
5046
5042
5047 See :hg:`help templates` for more about pre-packaged styles and
5043 See :hg:`help templates` for more about pre-packaged styles and
5048 specifying custom templates.
5044 specifying custom templates.
5049
5045
5050 Returns 0 on success.
5046 Returns 0 on success.
5051
5047
5052 """
5048 """
5053 if opts.get('follow') and opts.get('rev'):
5049 if opts.get('follow') and opts.get('rev'):
5054 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5050 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5055 del opts['follow']
5051 del opts['follow']
5056
5052
5057 if opts.get('graph'):
5053 if opts.get('graph'):
5058 return cmdutil.graphlog(ui, repo, *pats, **opts)
5054 return cmdutil.graphlog(ui, repo, *pats, **opts)
5059
5055
5060 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5056 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5061 limit = cmdutil.loglimit(opts)
5057 limit = cmdutil.loglimit(opts)
5062 count = 0
5058 count = 0
5063
5059
5064 getrenamed = None
5060 getrenamed = None
5065 if opts.get('copies'):
5061 if opts.get('copies'):
5066 endrev = None
5062 endrev = None
5067 if opts.get('rev'):
5063 if opts.get('rev'):
5068 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5064 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5069 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5065 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5070
5066
5071 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5067 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5072 for rev in revs:
5068 for rev in revs:
5073 if count == limit:
5069 if count == limit:
5074 break
5070 break
5075 ctx = repo[rev]
5071 ctx = repo[rev]
5076 copies = None
5072 copies = None
5077 if getrenamed is not None and rev:
5073 if getrenamed is not None and rev:
5078 copies = []
5074 copies = []
5079 for fn in ctx.files():
5075 for fn in ctx.files():
5080 rename = getrenamed(fn, rev)
5076 rename = getrenamed(fn, rev)
5081 if rename:
5077 if rename:
5082 copies.append((fn, rename[0]))
5078 copies.append((fn, rename[0]))
5083 if filematcher:
5079 if filematcher:
5084 revmatchfn = filematcher(ctx.rev())
5080 revmatchfn = filematcher(ctx.rev())
5085 else:
5081 else:
5086 revmatchfn = None
5082 revmatchfn = None
5087 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5083 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5088 if displayer.flush(ctx):
5084 if displayer.flush(ctx):
5089 count += 1
5085 count += 1
5090
5086
5091 displayer.close()
5087 displayer.close()
5092
5088
5093 @command('manifest',
5089 @command('manifest',
5094 [('r', 'rev', '', _('revision to display'), _('REV')),
5090 [('r', 'rev', '', _('revision to display'), _('REV')),
5095 ('', 'all', False, _("list files from all revisions"))]
5091 ('', 'all', False, _("list files from all revisions"))]
5096 + formatteropts,
5092 + formatteropts,
5097 _('[-r REV]'))
5093 _('[-r REV]'))
5098 def manifest(ui, repo, node=None, rev=None, **opts):
5094 def manifest(ui, repo, node=None, rev=None, **opts):
5099 """output the current or given revision of the project manifest
5095 """output the current or given revision of the project manifest
5100
5096
5101 Print a list of version controlled files for the given revision.
5097 Print a list of version controlled files for the given revision.
5102 If no revision is given, the first parent of the working directory
5098 If no revision is given, the first parent of the working directory
5103 is used, or the null revision if no revision is checked out.
5099 is used, or the null revision if no revision is checked out.
5104
5100
5105 With -v, print file permissions, symlink and executable bits.
5101 With -v, print file permissions, symlink and executable bits.
5106 With --debug, print file revision hashes.
5102 With --debug, print file revision hashes.
5107
5103
5108 If option --all is specified, the list of all files from all revisions
5104 If option --all is specified, the list of all files from all revisions
5109 is printed. This includes deleted and renamed files.
5105 is printed. This includes deleted and renamed files.
5110
5106
5111 Returns 0 on success.
5107 Returns 0 on success.
5112 """
5108 """
5113
5109
5114 fm = ui.formatter('manifest', opts)
5110 fm = ui.formatter('manifest', opts)
5115
5111
5116 if opts.get('all'):
5112 if opts.get('all'):
5117 if rev or node:
5113 if rev or node:
5118 raise error.Abort(_("can't specify a revision with --all"))
5114 raise error.Abort(_("can't specify a revision with --all"))
5119
5115
5120 res = []
5116 res = []
5121 prefix = "data/"
5117 prefix = "data/"
5122 suffix = ".i"
5118 suffix = ".i"
5123 plen = len(prefix)
5119 plen = len(prefix)
5124 slen = len(suffix)
5120 slen = len(suffix)
5125 lock = repo.lock()
5121 lock = repo.lock()
5126 try:
5122 try:
5127 for fn, b, size in repo.store.datafiles():
5123 for fn, b, size in repo.store.datafiles():
5128 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5124 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5129 res.append(fn[plen:-slen])
5125 res.append(fn[plen:-slen])
5130 finally:
5126 finally:
5131 lock.release()
5127 lock.release()
5132 for f in res:
5128 for f in res:
5133 fm.startitem()
5129 fm.startitem()
5134 fm.write("path", '%s\n', f)
5130 fm.write("path", '%s\n', f)
5135 fm.end()
5131 fm.end()
5136 return
5132 return
5137
5133
5138 if rev and node:
5134 if rev and node:
5139 raise error.Abort(_("please specify just one revision"))
5135 raise error.Abort(_("please specify just one revision"))
5140
5136
5141 if not node:
5137 if not node:
5142 node = rev
5138 node = rev
5143
5139
5144 char = {'l': '@', 'x': '*', '': ''}
5140 char = {'l': '@', 'x': '*', '': ''}
5145 mode = {'l': '644', 'x': '755', '': '644'}
5141 mode = {'l': '644', 'x': '755', '': '644'}
5146 ctx = scmutil.revsingle(repo, node)
5142 ctx = scmutil.revsingle(repo, node)
5147 mf = ctx.manifest()
5143 mf = ctx.manifest()
5148 for f in ctx:
5144 for f in ctx:
5149 fm.startitem()
5145 fm.startitem()
5150 fl = ctx[f].flags()
5146 fl = ctx[f].flags()
5151 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5147 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5152 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5148 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5153 fm.write('path', '%s\n', f)
5149 fm.write('path', '%s\n', f)
5154 fm.end()
5150 fm.end()
5155
5151
5156 @command('^merge',
5152 @command('^merge',
5157 [('f', 'force', None,
5153 [('f', 'force', None,
5158 _('force a merge including outstanding changes (DEPRECATED)')),
5154 _('force a merge including outstanding changes (DEPRECATED)')),
5159 ('r', 'rev', '', _('revision to merge'), _('REV')),
5155 ('r', 'rev', '', _('revision to merge'), _('REV')),
5160 ('P', 'preview', None,
5156 ('P', 'preview', None,
5161 _('review revisions to merge (no merge is performed)'))
5157 _('review revisions to merge (no merge is performed)'))
5162 ] + mergetoolopts,
5158 ] + mergetoolopts,
5163 _('[-P] [-f] [[-r] REV]'))
5159 _('[-P] [-f] [[-r] REV]'))
5164 def merge(ui, repo, node=None, **opts):
5160 def merge(ui, repo, node=None, **opts):
5165 """merge another revision into working directory
5161 """merge another revision into working directory
5166
5162
5167 The current working directory is updated with all changes made in
5163 The current working directory is updated with all changes made in
5168 the requested revision since the last common predecessor revision.
5164 the requested revision since the last common predecessor revision.
5169
5165
5170 Files that changed between either parent are marked as changed for
5166 Files that changed between either parent are marked as changed for
5171 the next commit and a commit must be performed before any further
5167 the next commit and a commit must be performed before any further
5172 updates to the repository are allowed. The next commit will have
5168 updates to the repository are allowed. The next commit will have
5173 two parents.
5169 two parents.
5174
5170
5175 ``--tool`` can be used to specify the merge tool used for file
5171 ``--tool`` can be used to specify the merge tool used for file
5176 merges. It overrides the HGMERGE environment variable and your
5172 merges. It overrides the HGMERGE environment variable and your
5177 configuration files. See :hg:`help merge-tools` for options.
5173 configuration files. See :hg:`help merge-tools` for options.
5178
5174
5179 If no revision is specified, the working directory's parent is a
5175 If no revision is specified, the working directory's parent is a
5180 head revision, and the current branch contains exactly one other
5176 head revision, and the current branch contains exactly one other
5181 head, the other head is merged with by default. Otherwise, an
5177 head, the other head is merged with by default. Otherwise, an
5182 explicit revision with which to merge with must be provided.
5178 explicit revision with which to merge with must be provided.
5183
5179
5184 See :hg:`help resolve` for information on handling file conflicts.
5180 See :hg:`help resolve` for information on handling file conflicts.
5185
5181
5186 To undo an uncommitted merge, use :hg:`update --clean .` which
5182 To undo an uncommitted merge, use :hg:`update --clean .` which
5187 will check out a clean copy of the original merge parent, losing
5183 will check out a clean copy of the original merge parent, losing
5188 all changes.
5184 all changes.
5189
5185
5190 Returns 0 on success, 1 if there are unresolved files.
5186 Returns 0 on success, 1 if there are unresolved files.
5191 """
5187 """
5192
5188
5193 if opts.get('rev') and node:
5189 if opts.get('rev') and node:
5194 raise error.Abort(_("please specify just one revision"))
5190 raise error.Abort(_("please specify just one revision"))
5195 if not node:
5191 if not node:
5196 node = opts.get('rev')
5192 node = opts.get('rev')
5197
5193
5198 if node:
5194 if node:
5199 node = scmutil.revsingle(repo, node).node()
5195 node = scmutil.revsingle(repo, node).node()
5200
5196
5201 if not node:
5197 if not node:
5202 node = repo[destutil.destmerge(repo)].node()
5198 node = repo[destutil.destmerge(repo)].node()
5203
5199
5204 if opts.get('preview'):
5200 if opts.get('preview'):
5205 # find nodes that are ancestors of p2 but not of p1
5201 # find nodes that are ancestors of p2 but not of p1
5206 p1 = repo.lookup('.')
5202 p1 = repo.lookup('.')
5207 p2 = repo.lookup(node)
5203 p2 = repo.lookup(node)
5208 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5204 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5209
5205
5210 displayer = cmdutil.show_changeset(ui, repo, opts)
5206 displayer = cmdutil.show_changeset(ui, repo, opts)
5211 for node in nodes:
5207 for node in nodes:
5212 displayer.show(repo[node])
5208 displayer.show(repo[node])
5213 displayer.close()
5209 displayer.close()
5214 return 0
5210 return 0
5215
5211
5216 try:
5212 try:
5217 # ui.forcemerge is an internal variable, do not document
5213 # ui.forcemerge is an internal variable, do not document
5218 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5214 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5219 return hg.merge(repo, node, force=opts.get('force'))
5215 return hg.merge(repo, node, force=opts.get('force'))
5220 finally:
5216 finally:
5221 ui.setconfig('ui', 'forcemerge', '', 'merge')
5217 ui.setconfig('ui', 'forcemerge', '', 'merge')
5222
5218
5223 @command('outgoing|out',
5219 @command('outgoing|out',
5224 [('f', 'force', None, _('run even when the destination is unrelated')),
5220 [('f', 'force', None, _('run even when the destination is unrelated')),
5225 ('r', 'rev', [],
5221 ('r', 'rev', [],
5226 _('a changeset intended to be included in the destination'), _('REV')),
5222 _('a changeset intended to be included in the destination'), _('REV')),
5227 ('n', 'newest-first', None, _('show newest record first')),
5223 ('n', 'newest-first', None, _('show newest record first')),
5228 ('B', 'bookmarks', False, _('compare bookmarks')),
5224 ('B', 'bookmarks', False, _('compare bookmarks')),
5229 ('b', 'branch', [], _('a specific branch you would like to push'),
5225 ('b', 'branch', [], _('a specific branch you would like to push'),
5230 _('BRANCH')),
5226 _('BRANCH')),
5231 ] + logopts + remoteopts + subrepoopts,
5227 ] + logopts + remoteopts + subrepoopts,
5232 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5228 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5233 def outgoing(ui, repo, dest=None, **opts):
5229 def outgoing(ui, repo, dest=None, **opts):
5234 """show changesets not found in the destination
5230 """show changesets not found in the destination
5235
5231
5236 Show changesets not found in the specified destination repository
5232 Show changesets not found in the specified destination repository
5237 or the default push location. These are the changesets that would
5233 or the default push location. These are the changesets that would
5238 be pushed if a push was requested.
5234 be pushed if a push was requested.
5239
5235
5240 See pull for details of valid destination formats.
5236 See pull for details of valid destination formats.
5241
5237
5242 .. container:: verbose
5238 .. container:: verbose
5243
5239
5244 With -B/--bookmarks, the result of bookmark comparison between
5240 With -B/--bookmarks, the result of bookmark comparison between
5245 local and remote repositories is displayed. With -v/--verbose,
5241 local and remote repositories is displayed. With -v/--verbose,
5246 status is also displayed for each bookmark like below::
5242 status is also displayed for each bookmark like below::
5247
5243
5248 BM1 01234567890a added
5244 BM1 01234567890a added
5249 BM2 deleted
5245 BM2 deleted
5250 BM3 234567890abc advanced
5246 BM3 234567890abc advanced
5251 BM4 34567890abcd diverged
5247 BM4 34567890abcd diverged
5252 BM5 4567890abcde changed
5248 BM5 4567890abcde changed
5253
5249
5254 The action taken when pushing depends on the
5250 The action taken when pushing depends on the
5255 status of each bookmark:
5251 status of each bookmark:
5256
5252
5257 :``added``: push with ``-B`` will create it
5253 :``added``: push with ``-B`` will create it
5258 :``deleted``: push with ``-B`` will delete it
5254 :``deleted``: push with ``-B`` will delete it
5259 :``advanced``: push will update it
5255 :``advanced``: push will update it
5260 :``diverged``: push with ``-B`` will update it
5256 :``diverged``: push with ``-B`` will update it
5261 :``changed``: push with ``-B`` will update it
5257 :``changed``: push with ``-B`` will update it
5262
5258
5263 From the point of view of pushing behavior, bookmarks
5259 From the point of view of pushing behavior, bookmarks
5264 existing only in the remote repository are treated as
5260 existing only in the remote repository are treated as
5265 ``deleted``, even if it is in fact added remotely.
5261 ``deleted``, even if it is in fact added remotely.
5266
5262
5267 Returns 0 if there are outgoing changes, 1 otherwise.
5263 Returns 0 if there are outgoing changes, 1 otherwise.
5268 """
5264 """
5269 if opts.get('graph'):
5265 if opts.get('graph'):
5270 cmdutil.checkunsupportedgraphflags([], opts)
5266 cmdutil.checkunsupportedgraphflags([], opts)
5271 o, other = hg._outgoing(ui, repo, dest, opts)
5267 o, other = hg._outgoing(ui, repo, dest, opts)
5272 if not o:
5268 if not o:
5273 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5269 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5274 return
5270 return
5275
5271
5276 revdag = cmdutil.graphrevs(repo, o, opts)
5272 revdag = cmdutil.graphrevs(repo, o, opts)
5277 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5273 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5278 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5274 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5279 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5275 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5280 return 0
5276 return 0
5281
5277
5282 if opts.get('bookmarks'):
5278 if opts.get('bookmarks'):
5283 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5279 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5284 dest, branches = hg.parseurl(dest, opts.get('branch'))
5280 dest, branches = hg.parseurl(dest, opts.get('branch'))
5285 other = hg.peer(repo, opts, dest)
5281 other = hg.peer(repo, opts, dest)
5286 if 'bookmarks' not in other.listkeys('namespaces'):
5282 if 'bookmarks' not in other.listkeys('namespaces'):
5287 ui.warn(_("remote doesn't support bookmarks\n"))
5283 ui.warn(_("remote doesn't support bookmarks\n"))
5288 return 0
5284 return 0
5289 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5285 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5290 return bookmarks.outgoing(ui, repo, other)
5286 return bookmarks.outgoing(ui, repo, other)
5291
5287
5292 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5288 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5293 try:
5289 try:
5294 return hg.outgoing(ui, repo, dest, opts)
5290 return hg.outgoing(ui, repo, dest, opts)
5295 finally:
5291 finally:
5296 del repo._subtoppath
5292 del repo._subtoppath
5297
5293
5298 @command('parents',
5294 @command('parents',
5299 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5295 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5300 ] + templateopts,
5296 ] + templateopts,
5301 _('[-r REV] [FILE]'),
5297 _('[-r REV] [FILE]'),
5302 inferrepo=True)
5298 inferrepo=True)
5303 def parents(ui, repo, file_=None, **opts):
5299 def parents(ui, repo, file_=None, **opts):
5304 """show the parents of the working directory or revision (DEPRECATED)
5300 """show the parents of the working directory or revision (DEPRECATED)
5305
5301
5306 Print the working directory's parent revisions. If a revision is
5302 Print the working directory's parent revisions. If a revision is
5307 given via -r/--rev, the parent of that revision will be printed.
5303 given via -r/--rev, the parent of that revision will be printed.
5308 If a file argument is given, the revision in which the file was
5304 If a file argument is given, the revision in which the file was
5309 last changed (before the working directory revision or the
5305 last changed (before the working directory revision or the
5310 argument to --rev if given) is printed.
5306 argument to --rev if given) is printed.
5311
5307
5312 This command is equivalent to::
5308 This command is equivalent to::
5313
5309
5314 hg log -r "p1()+p2()" or
5310 hg log -r "p1()+p2()" or
5315 hg log -r "p1(REV)+p2(REV)" or
5311 hg log -r "p1(REV)+p2(REV)" or
5316 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5312 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5317 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5313 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5318
5314
5319 See :hg:`summary` and :hg:`help revsets` for related information.
5315 See :hg:`summary` and :hg:`help revsets` for related information.
5320
5316
5321 Returns 0 on success.
5317 Returns 0 on success.
5322 """
5318 """
5323
5319
5324 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5320 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5325
5321
5326 if file_:
5322 if file_:
5327 m = scmutil.match(ctx, (file_,), opts)
5323 m = scmutil.match(ctx, (file_,), opts)
5328 if m.anypats() or len(m.files()) != 1:
5324 if m.anypats() or len(m.files()) != 1:
5329 raise error.Abort(_('can only specify an explicit filename'))
5325 raise error.Abort(_('can only specify an explicit filename'))
5330 file_ = m.files()[0]
5326 file_ = m.files()[0]
5331 filenodes = []
5327 filenodes = []
5332 for cp in ctx.parents():
5328 for cp in ctx.parents():
5333 if not cp:
5329 if not cp:
5334 continue
5330 continue
5335 try:
5331 try:
5336 filenodes.append(cp.filenode(file_))
5332 filenodes.append(cp.filenode(file_))
5337 except error.LookupError:
5333 except error.LookupError:
5338 pass
5334 pass
5339 if not filenodes:
5335 if not filenodes:
5340 raise error.Abort(_("'%s' not found in manifest!") % file_)
5336 raise error.Abort(_("'%s' not found in manifest!") % file_)
5341 p = []
5337 p = []
5342 for fn in filenodes:
5338 for fn in filenodes:
5343 fctx = repo.filectx(file_, fileid=fn)
5339 fctx = repo.filectx(file_, fileid=fn)
5344 p.append(fctx.node())
5340 p.append(fctx.node())
5345 else:
5341 else:
5346 p = [cp.node() for cp in ctx.parents()]
5342 p = [cp.node() for cp in ctx.parents()]
5347
5343
5348 displayer = cmdutil.show_changeset(ui, repo, opts)
5344 displayer = cmdutil.show_changeset(ui, repo, opts)
5349 for n in p:
5345 for n in p:
5350 if n != nullid:
5346 if n != nullid:
5351 displayer.show(repo[n])
5347 displayer.show(repo[n])
5352 displayer.close()
5348 displayer.close()
5353
5349
5354 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5350 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5355 def paths(ui, repo, search=None, **opts):
5351 def paths(ui, repo, search=None, **opts):
5356 """show aliases for remote repositories
5352 """show aliases for remote repositories
5357
5353
5358 Show definition of symbolic path name NAME. If no name is given,
5354 Show definition of symbolic path name NAME. If no name is given,
5359 show definition of all available names.
5355 show definition of all available names.
5360
5356
5361 Option -q/--quiet suppresses all output when searching for NAME
5357 Option -q/--quiet suppresses all output when searching for NAME
5362 and shows only the path names when listing all definitions.
5358 and shows only the path names when listing all definitions.
5363
5359
5364 Path names are defined in the [paths] section of your
5360 Path names are defined in the [paths] section of your
5365 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5361 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5366 repository, ``.hg/hgrc`` is used, too.
5362 repository, ``.hg/hgrc`` is used, too.
5367
5363
5368 The path names ``default`` and ``default-push`` have a special
5364 The path names ``default`` and ``default-push`` have a special
5369 meaning. When performing a push or pull operation, they are used
5365 meaning. When performing a push or pull operation, they are used
5370 as fallbacks if no location is specified on the command-line.
5366 as fallbacks if no location is specified on the command-line.
5371 When ``default-push`` is set, it will be used for push and
5367 When ``default-push`` is set, it will be used for push and
5372 ``default`` will be used for pull; otherwise ``default`` is used
5368 ``default`` will be used for pull; otherwise ``default`` is used
5373 as the fallback for both. When cloning a repository, the clone
5369 as the fallback for both. When cloning a repository, the clone
5374 source is written as ``default`` in ``.hg/hgrc``.
5370 source is written as ``default`` in ``.hg/hgrc``.
5375
5371
5376 .. note::
5372 .. note::
5377
5373
5378 ``default`` and ``default-push`` apply to all inbound (e.g.
5374 ``default`` and ``default-push`` apply to all inbound (e.g.
5379 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5375 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5380 and :hg:`bundle`) operations.
5376 and :hg:`bundle`) operations.
5381
5377
5382 See :hg:`help urls` for more information.
5378 See :hg:`help urls` for more information.
5383
5379
5384 Returns 0 on success.
5380 Returns 0 on success.
5385 """
5381 """
5386 if search:
5382 if search:
5387 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5383 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5388 if name == search]
5384 if name == search]
5389 else:
5385 else:
5390 pathitems = sorted(ui.paths.iteritems())
5386 pathitems = sorted(ui.paths.iteritems())
5391
5387
5392 fm = ui.formatter('paths', opts)
5388 fm = ui.formatter('paths', opts)
5393 if fm:
5389 if fm:
5394 hidepassword = str
5390 hidepassword = str
5395 else:
5391 else:
5396 hidepassword = util.hidepassword
5392 hidepassword = util.hidepassword
5397 if ui.quiet:
5393 if ui.quiet:
5398 namefmt = '%s\n'
5394 namefmt = '%s\n'
5399 else:
5395 else:
5400 namefmt = '%s = '
5396 namefmt = '%s = '
5401 showsubopts = not search and not ui.quiet
5397 showsubopts = not search and not ui.quiet
5402
5398
5403 for name, path in pathitems:
5399 for name, path in pathitems:
5404 fm.startitem()
5400 fm.startitem()
5405 fm.condwrite(not search, 'name', namefmt, name)
5401 fm.condwrite(not search, 'name', namefmt, name)
5406 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5402 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5407 for subopt, value in sorted(path.suboptions.items()):
5403 for subopt, value in sorted(path.suboptions.items()):
5408 assert subopt not in ('name', 'url')
5404 assert subopt not in ('name', 'url')
5409 if showsubopts:
5405 if showsubopts:
5410 fm.plain('%s:%s = ' % (name, subopt))
5406 fm.plain('%s:%s = ' % (name, subopt))
5411 fm.condwrite(showsubopts, subopt, '%s\n', value)
5407 fm.condwrite(showsubopts, subopt, '%s\n', value)
5412
5408
5413 fm.end()
5409 fm.end()
5414
5410
5415 if search and not pathitems:
5411 if search and not pathitems:
5416 if not ui.quiet:
5412 if not ui.quiet:
5417 ui.warn(_("not found!\n"))
5413 ui.warn(_("not found!\n"))
5418 return 1
5414 return 1
5419 else:
5415 else:
5420 return 0
5416 return 0
5421
5417
5422 @command('phase',
5418 @command('phase',
5423 [('p', 'public', False, _('set changeset phase to public')),
5419 [('p', 'public', False, _('set changeset phase to public')),
5424 ('d', 'draft', False, _('set changeset phase to draft')),
5420 ('d', 'draft', False, _('set changeset phase to draft')),
5425 ('s', 'secret', False, _('set changeset phase to secret')),
5421 ('s', 'secret', False, _('set changeset phase to secret')),
5426 ('f', 'force', False, _('allow to move boundary backward')),
5422 ('f', 'force', False, _('allow to move boundary backward')),
5427 ('r', 'rev', [], _('target revision'), _('REV')),
5423 ('r', 'rev', [], _('target revision'), _('REV')),
5428 ],
5424 ],
5429 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5425 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5430 def phase(ui, repo, *revs, **opts):
5426 def phase(ui, repo, *revs, **opts):
5431 """set or show the current phase name
5427 """set or show the current phase name
5432
5428
5433 With no argument, show the phase name of the current revision(s).
5429 With no argument, show the phase name of the current revision(s).
5434
5430
5435 With one of -p/--public, -d/--draft or -s/--secret, change the
5431 With one of -p/--public, -d/--draft or -s/--secret, change the
5436 phase value of the specified revisions.
5432 phase value of the specified revisions.
5437
5433
5438 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5434 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5439 lower phase to an higher phase. Phases are ordered as follows::
5435 lower phase to an higher phase. Phases are ordered as follows::
5440
5436
5441 public < draft < secret
5437 public < draft < secret
5442
5438
5443 Returns 0 on success, 1 if some phases could not be changed.
5439 Returns 0 on success, 1 if some phases could not be changed.
5444
5440
5445 (For more information about the phases concept, see :hg:`help phases`.)
5441 (For more information about the phases concept, see :hg:`help phases`.)
5446 """
5442 """
5447 # search for a unique phase argument
5443 # search for a unique phase argument
5448 targetphase = None
5444 targetphase = None
5449 for idx, name in enumerate(phases.phasenames):
5445 for idx, name in enumerate(phases.phasenames):
5450 if opts[name]:
5446 if opts[name]:
5451 if targetphase is not None:
5447 if targetphase is not None:
5452 raise error.Abort(_('only one phase can be specified'))
5448 raise error.Abort(_('only one phase can be specified'))
5453 targetphase = idx
5449 targetphase = idx
5454
5450
5455 # look for specified revision
5451 # look for specified revision
5456 revs = list(revs)
5452 revs = list(revs)
5457 revs.extend(opts['rev'])
5453 revs.extend(opts['rev'])
5458 if not revs:
5454 if not revs:
5459 # display both parents as the second parent phase can influence
5455 # display both parents as the second parent phase can influence
5460 # the phase of a merge commit
5456 # the phase of a merge commit
5461 revs = [c.rev() for c in repo[None].parents()]
5457 revs = [c.rev() for c in repo[None].parents()]
5462
5458
5463 revs = scmutil.revrange(repo, revs)
5459 revs = scmutil.revrange(repo, revs)
5464
5460
5465 lock = None
5461 lock = None
5466 ret = 0
5462 ret = 0
5467 if targetphase is None:
5463 if targetphase is None:
5468 # display
5464 # display
5469 for r in revs:
5465 for r in revs:
5470 ctx = repo[r]
5466 ctx = repo[r]
5471 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5467 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5472 else:
5468 else:
5473 tr = None
5469 tr = None
5474 lock = repo.lock()
5470 lock = repo.lock()
5475 try:
5471 try:
5476 tr = repo.transaction("phase")
5472 tr = repo.transaction("phase")
5477 # set phase
5473 # set phase
5478 if not revs:
5474 if not revs:
5479 raise error.Abort(_('empty revision set'))
5475 raise error.Abort(_('empty revision set'))
5480 nodes = [repo[r].node() for r in revs]
5476 nodes = [repo[r].node() for r in revs]
5481 # moving revision from public to draft may hide them
5477 # moving revision from public to draft may hide them
5482 # We have to check result on an unfiltered repository
5478 # We have to check result on an unfiltered repository
5483 unfi = repo.unfiltered()
5479 unfi = repo.unfiltered()
5484 getphase = unfi._phasecache.phase
5480 getphase = unfi._phasecache.phase
5485 olddata = [getphase(unfi, r) for r in unfi]
5481 olddata = [getphase(unfi, r) for r in unfi]
5486 phases.advanceboundary(repo, tr, targetphase, nodes)
5482 phases.advanceboundary(repo, tr, targetphase, nodes)
5487 if opts['force']:
5483 if opts['force']:
5488 phases.retractboundary(repo, tr, targetphase, nodes)
5484 phases.retractboundary(repo, tr, targetphase, nodes)
5489 tr.close()
5485 tr.close()
5490 finally:
5486 finally:
5491 if tr is not None:
5487 if tr is not None:
5492 tr.release()
5488 tr.release()
5493 lock.release()
5489 lock.release()
5494 getphase = unfi._phasecache.phase
5490 getphase = unfi._phasecache.phase
5495 newdata = [getphase(unfi, r) for r in unfi]
5491 newdata = [getphase(unfi, r) for r in unfi]
5496 changes = sum(newdata[r] != olddata[r] for r in unfi)
5492 changes = sum(newdata[r] != olddata[r] for r in unfi)
5497 cl = unfi.changelog
5493 cl = unfi.changelog
5498 rejected = [n for n in nodes
5494 rejected = [n for n in nodes
5499 if newdata[cl.rev(n)] < targetphase]
5495 if newdata[cl.rev(n)] < targetphase]
5500 if rejected:
5496 if rejected:
5501 ui.warn(_('cannot move %i changesets to a higher '
5497 ui.warn(_('cannot move %i changesets to a higher '
5502 'phase, use --force\n') % len(rejected))
5498 'phase, use --force\n') % len(rejected))
5503 ret = 1
5499 ret = 1
5504 if changes:
5500 if changes:
5505 msg = _('phase changed for %i changesets\n') % changes
5501 msg = _('phase changed for %i changesets\n') % changes
5506 if ret:
5502 if ret:
5507 ui.status(msg)
5503 ui.status(msg)
5508 else:
5504 else:
5509 ui.note(msg)
5505 ui.note(msg)
5510 else:
5506 else:
5511 ui.warn(_('no phases changed\n'))
5507 ui.warn(_('no phases changed\n'))
5512 return ret
5508 return ret
5513
5509
5514 def postincoming(ui, repo, modheads, optupdate, checkout):
5510 def postincoming(ui, repo, modheads, optupdate, checkout):
5515 if modheads == 0:
5511 if modheads == 0:
5516 return
5512 return
5517 if optupdate:
5513 if optupdate:
5518 try:
5514 try:
5519 brev = checkout
5515 brev = checkout
5520 movemarkfrom = None
5516 movemarkfrom = None
5521 if not checkout:
5517 if not checkout:
5522 updata = destutil.destupdate(repo)
5518 updata = destutil.destupdate(repo)
5523 checkout, movemarkfrom, brev = updata
5519 checkout, movemarkfrom, brev = updata
5524 ret = hg.update(repo, checkout)
5520 ret = hg.update(repo, checkout)
5525 except error.UpdateAbort as inst:
5521 except error.UpdateAbort as inst:
5526 msg = _("not updating: %s") % str(inst)
5522 msg = _("not updating: %s") % str(inst)
5527 hint = inst.hint
5523 hint = inst.hint
5528 raise error.UpdateAbort(msg, hint=hint)
5524 raise error.UpdateAbort(msg, hint=hint)
5529 if not ret and not checkout:
5525 if not ret and not checkout:
5530 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5526 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5531 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5527 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5532 return ret
5528 return ret
5533 if modheads > 1:
5529 if modheads > 1:
5534 currentbranchheads = len(repo.branchheads())
5530 currentbranchheads = len(repo.branchheads())
5535 if currentbranchheads == modheads:
5531 if currentbranchheads == modheads:
5536 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5532 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5537 elif currentbranchheads > 1:
5533 elif currentbranchheads > 1:
5538 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5534 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5539 "merge)\n"))
5535 "merge)\n"))
5540 else:
5536 else:
5541 ui.status(_("(run 'hg heads' to see heads)\n"))
5537 ui.status(_("(run 'hg heads' to see heads)\n"))
5542 else:
5538 else:
5543 ui.status(_("(run 'hg update' to get a working copy)\n"))
5539 ui.status(_("(run 'hg update' to get a working copy)\n"))
5544
5540
5545 @command('^pull',
5541 @command('^pull',
5546 [('u', 'update', None,
5542 [('u', 'update', None,
5547 _('update to new branch head if changesets were pulled')),
5543 _('update to new branch head if changesets were pulled')),
5548 ('f', 'force', None, _('run even when remote repository is unrelated')),
5544 ('f', 'force', None, _('run even when remote repository is unrelated')),
5549 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5545 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5550 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5546 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5551 ('b', 'branch', [], _('a specific branch you would like to pull'),
5547 ('b', 'branch', [], _('a specific branch you would like to pull'),
5552 _('BRANCH')),
5548 _('BRANCH')),
5553 ] + remoteopts,
5549 ] + remoteopts,
5554 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5550 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5555 def pull(ui, repo, source="default", **opts):
5551 def pull(ui, repo, source="default", **opts):
5556 """pull changes from the specified source
5552 """pull changes from the specified source
5557
5553
5558 Pull changes from a remote repository to a local one.
5554 Pull changes from a remote repository to a local one.
5559
5555
5560 This finds all changes from the repository at the specified path
5556 This finds all changes from the repository at the specified path
5561 or URL and adds them to a local repository (the current one unless
5557 or URL and adds them to a local repository (the current one unless
5562 -R is specified). By default, this does not update the copy of the
5558 -R is specified). By default, this does not update the copy of the
5563 project in the working directory.
5559 project in the working directory.
5564
5560
5565 Use :hg:`incoming` if you want to see what would have been added
5561 Use :hg:`incoming` if you want to see what would have been added
5566 by a pull at the time you issued this command. If you then decide
5562 by a pull at the time you issued this command. If you then decide
5567 to add those changes to the repository, you should use :hg:`pull
5563 to add those changes to the repository, you should use :hg:`pull
5568 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5564 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5569
5565
5570 If SOURCE is omitted, the 'default' path will be used.
5566 If SOURCE is omitted, the 'default' path will be used.
5571 See :hg:`help urls` for more information.
5567 See :hg:`help urls` for more information.
5572
5568
5573 Returns 0 on success, 1 if an update had unresolved files.
5569 Returns 0 on success, 1 if an update had unresolved files.
5574 """
5570 """
5575 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5571 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5576 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5572 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5577 other = hg.peer(repo, opts, source)
5573 other = hg.peer(repo, opts, source)
5578 try:
5574 try:
5579 revs, checkout = hg.addbranchrevs(repo, other, branches,
5575 revs, checkout = hg.addbranchrevs(repo, other, branches,
5580 opts.get('rev'))
5576 opts.get('rev'))
5581
5577
5582
5578
5583 pullopargs = {}
5579 pullopargs = {}
5584 if opts.get('bookmark'):
5580 if opts.get('bookmark'):
5585 if not revs:
5581 if not revs:
5586 revs = []
5582 revs = []
5587 # The list of bookmark used here is not the one used to actually
5583 # The list of bookmark used here is not the one used to actually
5588 # update the bookmark name. This can result in the revision pulled
5584 # update the bookmark name. This can result in the revision pulled
5589 # not ending up with the name of the bookmark because of a race
5585 # not ending up with the name of the bookmark because of a race
5590 # condition on the server. (See issue 4689 for details)
5586 # condition on the server. (See issue 4689 for details)
5591 remotebookmarks = other.listkeys('bookmarks')
5587 remotebookmarks = other.listkeys('bookmarks')
5592 pullopargs['remotebookmarks'] = remotebookmarks
5588 pullopargs['remotebookmarks'] = remotebookmarks
5593 for b in opts['bookmark']:
5589 for b in opts['bookmark']:
5594 if b not in remotebookmarks:
5590 if b not in remotebookmarks:
5595 raise error.Abort(_('remote bookmark %s not found!') % b)
5591 raise error.Abort(_('remote bookmark %s not found!') % b)
5596 revs.append(remotebookmarks[b])
5592 revs.append(remotebookmarks[b])
5597
5593
5598 if revs:
5594 if revs:
5599 try:
5595 try:
5600 # When 'rev' is a bookmark name, we cannot guarantee that it
5596 # When 'rev' is a bookmark name, we cannot guarantee that it
5601 # will be updated with that name because of a race condition
5597 # will be updated with that name because of a race condition
5602 # server side. (See issue 4689 for details)
5598 # server side. (See issue 4689 for details)
5603 oldrevs = revs
5599 oldrevs = revs
5604 revs = [] # actually, nodes
5600 revs = [] # actually, nodes
5605 for r in oldrevs:
5601 for r in oldrevs:
5606 node = other.lookup(r)
5602 node = other.lookup(r)
5607 revs.append(node)
5603 revs.append(node)
5608 if r == checkout:
5604 if r == checkout:
5609 checkout = node
5605 checkout = node
5610 except error.CapabilityError:
5606 except error.CapabilityError:
5611 err = _("other repository doesn't support revision lookup, "
5607 err = _("other repository doesn't support revision lookup, "
5612 "so a rev cannot be specified.")
5608 "so a rev cannot be specified.")
5613 raise error.Abort(err)
5609 raise error.Abort(err)
5614
5610
5615 pullopargs.update(opts.get('opargs', {}))
5611 pullopargs.update(opts.get('opargs', {}))
5616 modheads = exchange.pull(repo, other, heads=revs,
5612 modheads = exchange.pull(repo, other, heads=revs,
5617 force=opts.get('force'),
5613 force=opts.get('force'),
5618 bookmarks=opts.get('bookmark', ()),
5614 bookmarks=opts.get('bookmark', ()),
5619 opargs=pullopargs).cgresult
5615 opargs=pullopargs).cgresult
5620 if checkout:
5616 if checkout:
5621 checkout = str(repo.changelog.rev(checkout))
5617 checkout = str(repo.changelog.rev(checkout))
5622 repo._subtoppath = source
5618 repo._subtoppath = source
5623 try:
5619 try:
5624 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5620 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5625
5621
5626 finally:
5622 finally:
5627 del repo._subtoppath
5623 del repo._subtoppath
5628
5624
5629 finally:
5625 finally:
5630 other.close()
5626 other.close()
5631 return ret
5627 return ret
5632
5628
5633 @command('^push',
5629 @command('^push',
5634 [('f', 'force', None, _('force push')),
5630 [('f', 'force', None, _('force push')),
5635 ('r', 'rev', [],
5631 ('r', 'rev', [],
5636 _('a changeset intended to be included in the destination'),
5632 _('a changeset intended to be included in the destination'),
5637 _('REV')),
5633 _('REV')),
5638 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5634 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5639 ('b', 'branch', [],
5635 ('b', 'branch', [],
5640 _('a specific branch you would like to push'), _('BRANCH')),
5636 _('a specific branch you would like to push'), _('BRANCH')),
5641 ('', 'new-branch', False, _('allow pushing a new branch')),
5637 ('', 'new-branch', False, _('allow pushing a new branch')),
5642 ] + remoteopts,
5638 ] + remoteopts,
5643 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5639 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5644 def push(ui, repo, dest=None, **opts):
5640 def push(ui, repo, dest=None, **opts):
5645 """push changes to the specified destination
5641 """push changes to the specified destination
5646
5642
5647 Push changesets from the local repository to the specified
5643 Push changesets from the local repository to the specified
5648 destination.
5644 destination.
5649
5645
5650 This operation is symmetrical to pull: it is identical to a pull
5646 This operation is symmetrical to pull: it is identical to a pull
5651 in the destination repository from the current one.
5647 in the destination repository from the current one.
5652
5648
5653 By default, push will not allow creation of new heads at the
5649 By default, push will not allow creation of new heads at the
5654 destination, since multiple heads would make it unclear which head
5650 destination, since multiple heads would make it unclear which head
5655 to use. In this situation, it is recommended to pull and merge
5651 to use. In this situation, it is recommended to pull and merge
5656 before pushing.
5652 before pushing.
5657
5653
5658 Use --new-branch if you want to allow push to create a new named
5654 Use --new-branch if you want to allow push to create a new named
5659 branch that is not present at the destination. This allows you to
5655 branch that is not present at the destination. This allows you to
5660 only create a new branch without forcing other changes.
5656 only create a new branch without forcing other changes.
5661
5657
5662 .. note::
5658 .. note::
5663
5659
5664 Extra care should be taken with the -f/--force option,
5660 Extra care should be taken with the -f/--force option,
5665 which will push all new heads on all branches, an action which will
5661 which will push all new heads on all branches, an action which will
5666 almost always cause confusion for collaborators.
5662 almost always cause confusion for collaborators.
5667
5663
5668 If -r/--rev is used, the specified revision and all its ancestors
5664 If -r/--rev is used, the specified revision and all its ancestors
5669 will be pushed to the remote repository.
5665 will be pushed to the remote repository.
5670
5666
5671 If -B/--bookmark is used, the specified bookmarked revision, its
5667 If -B/--bookmark is used, the specified bookmarked revision, its
5672 ancestors, and the bookmark will be pushed to the remote
5668 ancestors, and the bookmark will be pushed to the remote
5673 repository.
5669 repository.
5674
5670
5675 Please see :hg:`help urls` for important details about ``ssh://``
5671 Please see :hg:`help urls` for important details about ``ssh://``
5676 URLs. If DESTINATION is omitted, a default path will be used.
5672 URLs. If DESTINATION is omitted, a default path will be used.
5677
5673
5678 Returns 0 if push was successful, 1 if nothing to push.
5674 Returns 0 if push was successful, 1 if nothing to push.
5679 """
5675 """
5680
5676
5681 if opts.get('bookmark'):
5677 if opts.get('bookmark'):
5682 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5678 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5683 for b in opts['bookmark']:
5679 for b in opts['bookmark']:
5684 # translate -B options to -r so changesets get pushed
5680 # translate -B options to -r so changesets get pushed
5685 if b in repo._bookmarks:
5681 if b in repo._bookmarks:
5686 opts.setdefault('rev', []).append(b)
5682 opts.setdefault('rev', []).append(b)
5687 else:
5683 else:
5688 # if we try to push a deleted bookmark, translate it to null
5684 # if we try to push a deleted bookmark, translate it to null
5689 # this lets simultaneous -r, -b options continue working
5685 # this lets simultaneous -r, -b options continue working
5690 opts.setdefault('rev', []).append("null")
5686 opts.setdefault('rev', []).append("null")
5691
5687
5692 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5688 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5693 if not path:
5689 if not path:
5694 raise error.Abort(_('default repository not configured!'),
5690 raise error.Abort(_('default repository not configured!'),
5695 hint=_('see the "path" section in "hg help config"'))
5691 hint=_('see the "path" section in "hg help config"'))
5696 dest = path.pushloc or path.loc
5692 dest = path.pushloc or path.loc
5697 branches = (path.branch, opts.get('branch') or [])
5693 branches = (path.branch, opts.get('branch') or [])
5698 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5694 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5699 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5695 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5700 other = hg.peer(repo, opts, dest)
5696 other = hg.peer(repo, opts, dest)
5701
5697
5702 if revs:
5698 if revs:
5703 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5699 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5704 if not revs:
5700 if not revs:
5705 raise error.Abort(_("specified revisions evaluate to an empty set"),
5701 raise error.Abort(_("specified revisions evaluate to an empty set"),
5706 hint=_("use different revision arguments"))
5702 hint=_("use different revision arguments"))
5707
5703
5708 repo._subtoppath = dest
5704 repo._subtoppath = dest
5709 try:
5705 try:
5710 # push subrepos depth-first for coherent ordering
5706 # push subrepos depth-first for coherent ordering
5711 c = repo['']
5707 c = repo['']
5712 subs = c.substate # only repos that are committed
5708 subs = c.substate # only repos that are committed
5713 for s in sorted(subs):
5709 for s in sorted(subs):
5714 result = c.sub(s).push(opts)
5710 result = c.sub(s).push(opts)
5715 if result == 0:
5711 if result == 0:
5716 return not result
5712 return not result
5717 finally:
5713 finally:
5718 del repo._subtoppath
5714 del repo._subtoppath
5719 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5715 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5720 newbranch=opts.get('new_branch'),
5716 newbranch=opts.get('new_branch'),
5721 bookmarks=opts.get('bookmark', ()),
5717 bookmarks=opts.get('bookmark', ()),
5722 opargs=opts.get('opargs'))
5718 opargs=opts.get('opargs'))
5723
5719
5724 result = not pushop.cgresult
5720 result = not pushop.cgresult
5725
5721
5726 if pushop.bkresult is not None:
5722 if pushop.bkresult is not None:
5727 if pushop.bkresult == 2:
5723 if pushop.bkresult == 2:
5728 result = 2
5724 result = 2
5729 elif not result and pushop.bkresult:
5725 elif not result and pushop.bkresult:
5730 result = 2
5726 result = 2
5731
5727
5732 return result
5728 return result
5733
5729
5734 @command('recover', [])
5730 @command('recover', [])
5735 def recover(ui, repo):
5731 def recover(ui, repo):
5736 """roll back an interrupted transaction
5732 """roll back an interrupted transaction
5737
5733
5738 Recover from an interrupted commit or pull.
5734 Recover from an interrupted commit or pull.
5739
5735
5740 This command tries to fix the repository status after an
5736 This command tries to fix the repository status after an
5741 interrupted operation. It should only be necessary when Mercurial
5737 interrupted operation. It should only be necessary when Mercurial
5742 suggests it.
5738 suggests it.
5743
5739
5744 Returns 0 if successful, 1 if nothing to recover or verify fails.
5740 Returns 0 if successful, 1 if nothing to recover or verify fails.
5745 """
5741 """
5746 if repo.recover():
5742 if repo.recover():
5747 return hg.verify(repo)
5743 return hg.verify(repo)
5748 return 1
5744 return 1
5749
5745
5750 @command('^remove|rm',
5746 @command('^remove|rm',
5751 [('A', 'after', None, _('record delete for missing files')),
5747 [('A', 'after', None, _('record delete for missing files')),
5752 ('f', 'force', None,
5748 ('f', 'force', None,
5753 _('remove (and delete) file even if added or modified')),
5749 _('remove (and delete) file even if added or modified')),
5754 ] + subrepoopts + walkopts,
5750 ] + subrepoopts + walkopts,
5755 _('[OPTION]... FILE...'),
5751 _('[OPTION]... FILE...'),
5756 inferrepo=True)
5752 inferrepo=True)
5757 def remove(ui, repo, *pats, **opts):
5753 def remove(ui, repo, *pats, **opts):
5758 """remove the specified files on the next commit
5754 """remove the specified files on the next commit
5759
5755
5760 Schedule the indicated files for removal from the current branch.
5756 Schedule the indicated files for removal from the current branch.
5761
5757
5762 This command schedules the files to be removed at the next commit.
5758 This command schedules the files to be removed at the next commit.
5763 To undo a remove before that, see :hg:`revert`. To undo added
5759 To undo a remove before that, see :hg:`revert`. To undo added
5764 files, see :hg:`forget`.
5760 files, see :hg:`forget`.
5765
5761
5766 .. container:: verbose
5762 .. container:: verbose
5767
5763
5768 -A/--after can be used to remove only files that have already
5764 -A/--after can be used to remove only files that have already
5769 been deleted, -f/--force can be used to force deletion, and -Af
5765 been deleted, -f/--force can be used to force deletion, and -Af
5770 can be used to remove files from the next revision without
5766 can be used to remove files from the next revision without
5771 deleting them from the working directory.
5767 deleting them from the working directory.
5772
5768
5773 The following table details the behavior of remove for different
5769 The following table details the behavior of remove for different
5774 file states (columns) and option combinations (rows). The file
5770 file states (columns) and option combinations (rows). The file
5775 states are Added [A], Clean [C], Modified [M] and Missing [!]
5771 states are Added [A], Clean [C], Modified [M] and Missing [!]
5776 (as reported by :hg:`status`). The actions are Warn, Remove
5772 (as reported by :hg:`status`). The actions are Warn, Remove
5777 (from branch) and Delete (from disk):
5773 (from branch) and Delete (from disk):
5778
5774
5779 ========= == == == ==
5775 ========= == == == ==
5780 opt/state A C M !
5776 opt/state A C M !
5781 ========= == == == ==
5777 ========= == == == ==
5782 none W RD W R
5778 none W RD W R
5783 -f R RD RD R
5779 -f R RD RD R
5784 -A W W W R
5780 -A W W W R
5785 -Af R R R R
5781 -Af R R R R
5786 ========= == == == ==
5782 ========= == == == ==
5787
5783
5788 .. note::
5784 .. note::
5789
5785
5790 :hg:`remove` never deletes files in Added [A] state from the
5786 :hg:`remove` never deletes files in Added [A] state from the
5791 working directory, not even if ``--force`` is specified.
5787 working directory, not even if ``--force`` is specified.
5792
5788
5793 Returns 0 on success, 1 if any warnings encountered.
5789 Returns 0 on success, 1 if any warnings encountered.
5794 """
5790 """
5795
5791
5796 after, force = opts.get('after'), opts.get('force')
5792 after, force = opts.get('after'), opts.get('force')
5797 if not pats and not after:
5793 if not pats and not after:
5798 raise error.Abort(_('no files specified'))
5794 raise error.Abort(_('no files specified'))
5799
5795
5800 m = scmutil.match(repo[None], pats, opts)
5796 m = scmutil.match(repo[None], pats, opts)
5801 subrepos = opts.get('subrepos')
5797 subrepos = opts.get('subrepos')
5802 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5798 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5803
5799
5804 @command('rename|move|mv',
5800 @command('rename|move|mv',
5805 [('A', 'after', None, _('record a rename that has already occurred')),
5801 [('A', 'after', None, _('record a rename that has already occurred')),
5806 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5802 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5807 ] + walkopts + dryrunopts,
5803 ] + walkopts + dryrunopts,
5808 _('[OPTION]... SOURCE... DEST'))
5804 _('[OPTION]... SOURCE... DEST'))
5809 def rename(ui, repo, *pats, **opts):
5805 def rename(ui, repo, *pats, **opts):
5810 """rename files; equivalent of copy + remove
5806 """rename files; equivalent of copy + remove
5811
5807
5812 Mark dest as copies of sources; mark sources for deletion. If dest
5808 Mark dest as copies of sources; mark sources for deletion. If dest
5813 is a directory, copies are put in that directory. If dest is a
5809 is a directory, copies are put in that directory. If dest is a
5814 file, there can only be one source.
5810 file, there can only be one source.
5815
5811
5816 By default, this command copies the contents of files as they
5812 By default, this command copies the contents of files as they
5817 exist in the working directory. If invoked with -A/--after, the
5813 exist in the working directory. If invoked with -A/--after, the
5818 operation is recorded, but no copying is performed.
5814 operation is recorded, but no copying is performed.
5819
5815
5820 This command takes effect at the next commit. To undo a rename
5816 This command takes effect at the next commit. To undo a rename
5821 before that, see :hg:`revert`.
5817 before that, see :hg:`revert`.
5822
5818
5823 Returns 0 on success, 1 if errors are encountered.
5819 Returns 0 on success, 1 if errors are encountered.
5824 """
5820 """
5825 wlock = repo.wlock(False)
5821 wlock = repo.wlock(False)
5826 try:
5822 try:
5827 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5823 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5828 finally:
5824 finally:
5829 wlock.release()
5825 wlock.release()
5830
5826
5831 @command('resolve',
5827 @command('resolve',
5832 [('a', 'all', None, _('select all unresolved files')),
5828 [('a', 'all', None, _('select all unresolved files')),
5833 ('l', 'list', None, _('list state of files needing merge')),
5829 ('l', 'list', None, _('list state of files needing merge')),
5834 ('m', 'mark', None, _('mark files as resolved')),
5830 ('m', 'mark', None, _('mark files as resolved')),
5835 ('u', 'unmark', None, _('mark files as unresolved')),
5831 ('u', 'unmark', None, _('mark files as unresolved')),
5836 ('n', 'no-status', None, _('hide status prefix'))]
5832 ('n', 'no-status', None, _('hide status prefix'))]
5837 + mergetoolopts + walkopts + formatteropts,
5833 + mergetoolopts + walkopts + formatteropts,
5838 _('[OPTION]... [FILE]...'),
5834 _('[OPTION]... [FILE]...'),
5839 inferrepo=True)
5835 inferrepo=True)
5840 def resolve(ui, repo, *pats, **opts):
5836 def resolve(ui, repo, *pats, **opts):
5841 """redo merges or set/view the merge status of files
5837 """redo merges or set/view the merge status of files
5842
5838
5843 Merges with unresolved conflicts are often the result of
5839 Merges with unresolved conflicts are often the result of
5844 non-interactive merging using the ``internal:merge`` configuration
5840 non-interactive merging using the ``internal:merge`` configuration
5845 setting, or a command-line merge tool like ``diff3``. The resolve
5841 setting, or a command-line merge tool like ``diff3``. The resolve
5846 command is used to manage the files involved in a merge, after
5842 command is used to manage the files involved in a merge, after
5847 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5843 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5848 working directory must have two parents). See :hg:`help
5844 working directory must have two parents). See :hg:`help
5849 merge-tools` for information on configuring merge tools.
5845 merge-tools` for information on configuring merge tools.
5850
5846
5851 The resolve command can be used in the following ways:
5847 The resolve command can be used in the following ways:
5852
5848
5853 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5849 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5854 files, discarding any previous merge attempts. Re-merging is not
5850 files, discarding any previous merge attempts. Re-merging is not
5855 performed for files already marked as resolved. Use ``--all/-a``
5851 performed for files already marked as resolved. Use ``--all/-a``
5856 to select all unresolved files. ``--tool`` can be used to specify
5852 to select all unresolved files. ``--tool`` can be used to specify
5857 the merge tool used for the given files. It overrides the HGMERGE
5853 the merge tool used for the given files. It overrides the HGMERGE
5858 environment variable and your configuration files. Previous file
5854 environment variable and your configuration files. Previous file
5859 contents are saved with a ``.orig`` suffix.
5855 contents are saved with a ``.orig`` suffix.
5860
5856
5861 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5857 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5862 (e.g. after having manually fixed-up the files). The default is
5858 (e.g. after having manually fixed-up the files). The default is
5863 to mark all unresolved files.
5859 to mark all unresolved files.
5864
5860
5865 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5861 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5866 default is to mark all resolved files.
5862 default is to mark all resolved files.
5867
5863
5868 - :hg:`resolve -l`: list files which had or still have conflicts.
5864 - :hg:`resolve -l`: list files which had or still have conflicts.
5869 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5865 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5870
5866
5871 .. note::
5867 .. note::
5872
5868
5873 Mercurial will not let you commit files with unresolved merge
5869 Mercurial will not let you commit files with unresolved merge
5874 conflicts. You must use :hg:`resolve -m ...` before you can
5870 conflicts. You must use :hg:`resolve -m ...` before you can
5875 commit after a conflicting merge.
5871 commit after a conflicting merge.
5876
5872
5877 Returns 0 on success, 1 if any files fail a resolve attempt.
5873 Returns 0 on success, 1 if any files fail a resolve attempt.
5878 """
5874 """
5879
5875
5880 all, mark, unmark, show, nostatus = \
5876 all, mark, unmark, show, nostatus = \
5881 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5877 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5882
5878
5883 if (show and (mark or unmark)) or (mark and unmark):
5879 if (show and (mark or unmark)) or (mark and unmark):
5884 raise error.Abort(_("too many options specified"))
5880 raise error.Abort(_("too many options specified"))
5885 if pats and all:
5881 if pats and all:
5886 raise error.Abort(_("can't specify --all and patterns"))
5882 raise error.Abort(_("can't specify --all and patterns"))
5887 if not (all or pats or show or mark or unmark):
5883 if not (all or pats or show or mark or unmark):
5888 raise error.Abort(_('no files or directories specified'),
5884 raise error.Abort(_('no files or directories specified'),
5889 hint=('use --all to re-merge all unresolved files'))
5885 hint=('use --all to re-merge all unresolved files'))
5890
5886
5891 if show:
5887 if show:
5892 fm = ui.formatter('resolve', opts)
5888 fm = ui.formatter('resolve', opts)
5893 ms = mergemod.mergestate.read(repo)
5889 ms = mergemod.mergestate.read(repo)
5894 m = scmutil.match(repo[None], pats, opts)
5890 m = scmutil.match(repo[None], pats, opts)
5895 for f in ms:
5891 for f in ms:
5896 if not m(f):
5892 if not m(f):
5897 continue
5893 continue
5898 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5894 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5899 'd': 'driverresolved'}[ms[f]]
5895 'd': 'driverresolved'}[ms[f]]
5900 fm.startitem()
5896 fm.startitem()
5901 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5897 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5902 fm.write('path', '%s\n', f, label=l)
5898 fm.write('path', '%s\n', f, label=l)
5903 fm.end()
5899 fm.end()
5904 return 0
5900 return 0
5905
5901
5906 wlock = repo.wlock()
5902 wlock = repo.wlock()
5907 try:
5903 try:
5908 ms = mergemod.mergestate.read(repo)
5904 ms = mergemod.mergestate.read(repo)
5909
5905
5910 if not (ms.active() or repo.dirstate.p2() != nullid):
5906 if not (ms.active() or repo.dirstate.p2() != nullid):
5911 raise error.Abort(
5907 raise error.Abort(
5912 _('resolve command not applicable when not merging'))
5908 _('resolve command not applicable when not merging'))
5913
5909
5914 wctx = repo[None]
5910 wctx = repo[None]
5915
5911
5916 if ms.mergedriver and ms.mdstate() == 'u':
5912 if ms.mergedriver and ms.mdstate() == 'u':
5917 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5913 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5918 ms.commit()
5914 ms.commit()
5919 # allow mark and unmark to go through
5915 # allow mark and unmark to go through
5920 if not mark and not unmark and not proceed:
5916 if not mark and not unmark and not proceed:
5921 return 1
5917 return 1
5922
5918
5923 m = scmutil.match(wctx, pats, opts)
5919 m = scmutil.match(wctx, pats, opts)
5924 ret = 0
5920 ret = 0
5925 didwork = False
5921 didwork = False
5926 runconclude = False
5922 runconclude = False
5927
5923
5928 tocomplete = []
5924 tocomplete = []
5929 for f in ms:
5925 for f in ms:
5930 if not m(f):
5926 if not m(f):
5931 continue
5927 continue
5932
5928
5933 didwork = True
5929 didwork = True
5934
5930
5935 # don't let driver-resolved files be marked, and run the conclude
5931 # don't let driver-resolved files be marked, and run the conclude
5936 # step if asked to resolve
5932 # step if asked to resolve
5937 if ms[f] == "d":
5933 if ms[f] == "d":
5938 exact = m.exact(f)
5934 exact = m.exact(f)
5939 if mark:
5935 if mark:
5940 if exact:
5936 if exact:
5941 ui.warn(_('not marking %s as it is driver-resolved\n')
5937 ui.warn(_('not marking %s as it is driver-resolved\n')
5942 % f)
5938 % f)
5943 elif unmark:
5939 elif unmark:
5944 if exact:
5940 if exact:
5945 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5941 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5946 % f)
5942 % f)
5947 else:
5943 else:
5948 runconclude = True
5944 runconclude = True
5949 continue
5945 continue
5950
5946
5951 if mark:
5947 if mark:
5952 ms.mark(f, "r")
5948 ms.mark(f, "r")
5953 elif unmark:
5949 elif unmark:
5954 ms.mark(f, "u")
5950 ms.mark(f, "u")
5955 else:
5951 else:
5956 # backup pre-resolve (merge uses .orig for its own purposes)
5952 # backup pre-resolve (merge uses .orig for its own purposes)
5957 a = repo.wjoin(f)
5953 a = repo.wjoin(f)
5958 try:
5954 try:
5959 util.copyfile(a, a + ".resolve")
5955 util.copyfile(a, a + ".resolve")
5960 except (IOError, OSError) as inst:
5956 except (IOError, OSError) as inst:
5961 if inst.errno != errno.ENOENT:
5957 if inst.errno != errno.ENOENT:
5962 raise
5958 raise
5963
5959
5964 try:
5960 try:
5965 # preresolve file
5961 # preresolve file
5966 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5962 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5967 'resolve')
5963 'resolve')
5968 complete, r = ms.preresolve(f, wctx)
5964 complete, r = ms.preresolve(f, wctx)
5969 if not complete:
5965 if not complete:
5970 tocomplete.append(f)
5966 tocomplete.append(f)
5971 elif r:
5967 elif r:
5972 ret = 1
5968 ret = 1
5973 finally:
5969 finally:
5974 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5970 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5975 ms.commit()
5971 ms.commit()
5976
5972
5977 # replace filemerge's .orig file with our resolve file, but only
5973 # replace filemerge's .orig file with our resolve file, but only
5978 # for merges that are complete
5974 # for merges that are complete
5979 if complete:
5975 if complete:
5980 try:
5976 try:
5981 util.rename(a + ".resolve",
5977 util.rename(a + ".resolve",
5982 scmutil.origpath(ui, repo, a))
5978 scmutil.origpath(ui, repo, a))
5983 except OSError as inst:
5979 except OSError as inst:
5984 if inst.errno != errno.ENOENT:
5980 if inst.errno != errno.ENOENT:
5985 raise
5981 raise
5986
5982
5987 for f in tocomplete:
5983 for f in tocomplete:
5988 try:
5984 try:
5989 # resolve file
5985 # resolve file
5990 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5986 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5991 'resolve')
5987 'resolve')
5992 r = ms.resolve(f, wctx)
5988 r = ms.resolve(f, wctx)
5993 if r:
5989 if r:
5994 ret = 1
5990 ret = 1
5995 finally:
5991 finally:
5996 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5992 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5997 ms.commit()
5993 ms.commit()
5998
5994
5999 # replace filemerge's .orig file with our resolve file
5995 # replace filemerge's .orig file with our resolve file
6000 a = repo.wjoin(f)
5996 a = repo.wjoin(f)
6001 try:
5997 try:
6002 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
5998 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6003 except OSError as inst:
5999 except OSError as inst:
6004 if inst.errno != errno.ENOENT:
6000 if inst.errno != errno.ENOENT:
6005 raise
6001 raise
6006
6002
6007 ms.commit()
6003 ms.commit()
6008 ms.recordactions()
6004 ms.recordactions()
6009
6005
6010 if not didwork and pats:
6006 if not didwork and pats:
6011 ui.warn(_("arguments do not match paths that need resolving\n"))
6007 ui.warn(_("arguments do not match paths that need resolving\n"))
6012 elif ms.mergedriver and ms.mdstate() != 's':
6008 elif ms.mergedriver and ms.mdstate() != 's':
6013 # run conclude step when either a driver-resolved file is requested
6009 # run conclude step when either a driver-resolved file is requested
6014 # or there are no driver-resolved files
6010 # or there are no driver-resolved files
6015 # we can't use 'ret' to determine whether any files are unresolved
6011 # we can't use 'ret' to determine whether any files are unresolved
6016 # because we might not have tried to resolve some
6012 # because we might not have tried to resolve some
6017 if ((runconclude or not list(ms.driverresolved()))
6013 if ((runconclude or not list(ms.driverresolved()))
6018 and not list(ms.unresolved())):
6014 and not list(ms.unresolved())):
6019 proceed = mergemod.driverconclude(repo, ms, wctx)
6015 proceed = mergemod.driverconclude(repo, ms, wctx)
6020 ms.commit()
6016 ms.commit()
6021 if not proceed:
6017 if not proceed:
6022 return 1
6018 return 1
6023
6019
6024 finally:
6020 finally:
6025 wlock.release()
6021 wlock.release()
6026
6022
6027 # Nudge users into finishing an unfinished operation
6023 # Nudge users into finishing an unfinished operation
6028 unresolvedf = list(ms.unresolved())
6024 unresolvedf = list(ms.unresolved())
6029 driverresolvedf = list(ms.driverresolved())
6025 driverresolvedf = list(ms.driverresolved())
6030 if not unresolvedf and not driverresolvedf:
6026 if not unresolvedf and not driverresolvedf:
6031 ui.status(_('(no more unresolved files)\n'))
6027 ui.status(_('(no more unresolved files)\n'))
6032 cmdutil.checkafterresolved(repo)
6028 cmdutil.checkafterresolved(repo)
6033 elif not unresolvedf:
6029 elif not unresolvedf:
6034 ui.status(_('(no more unresolved files -- '
6030 ui.status(_('(no more unresolved files -- '
6035 'run "hg resolve --all" to conclude)\n'))
6031 'run "hg resolve --all" to conclude)\n'))
6036
6032
6037 return ret
6033 return ret
6038
6034
6039 @command('revert',
6035 @command('revert',
6040 [('a', 'all', None, _('revert all changes when no arguments given')),
6036 [('a', 'all', None, _('revert all changes when no arguments given')),
6041 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6037 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6042 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6038 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6043 ('C', 'no-backup', None, _('do not save backup copies of files')),
6039 ('C', 'no-backup', None, _('do not save backup copies of files')),
6044 ('i', 'interactive', None,
6040 ('i', 'interactive', None,
6045 _('interactively select the changes (EXPERIMENTAL)')),
6041 _('interactively select the changes (EXPERIMENTAL)')),
6046 ] + walkopts + dryrunopts,
6042 ] + walkopts + dryrunopts,
6047 _('[OPTION]... [-r REV] [NAME]...'))
6043 _('[OPTION]... [-r REV] [NAME]...'))
6048 def revert(ui, repo, *pats, **opts):
6044 def revert(ui, repo, *pats, **opts):
6049 """restore files to their checkout state
6045 """restore files to their checkout state
6050
6046
6051 .. note::
6047 .. note::
6052
6048
6053 To check out earlier revisions, you should use :hg:`update REV`.
6049 To check out earlier revisions, you should use :hg:`update REV`.
6054 To cancel an uncommitted merge (and lose your changes),
6050 To cancel an uncommitted merge (and lose your changes),
6055 use :hg:`update --clean .`.
6051 use :hg:`update --clean .`.
6056
6052
6057 With no revision specified, revert the specified files or directories
6053 With no revision specified, revert the specified files or directories
6058 to the contents they had in the parent of the working directory.
6054 to the contents they had in the parent of the working directory.
6059 This restores the contents of files to an unmodified
6055 This restores the contents of files to an unmodified
6060 state and unschedules adds, removes, copies, and renames. If the
6056 state and unschedules adds, removes, copies, and renames. If the
6061 working directory has two parents, you must explicitly specify a
6057 working directory has two parents, you must explicitly specify a
6062 revision.
6058 revision.
6063
6059
6064 Using the -r/--rev or -d/--date options, revert the given files or
6060 Using the -r/--rev or -d/--date options, revert the given files or
6065 directories to their states as of a specific revision. Because
6061 directories to their states as of a specific revision. Because
6066 revert does not change the working directory parents, this will
6062 revert does not change the working directory parents, this will
6067 cause these files to appear modified. This can be helpful to "back
6063 cause these files to appear modified. This can be helpful to "back
6068 out" some or all of an earlier change. See :hg:`backout` for a
6064 out" some or all of an earlier change. See :hg:`backout` for a
6069 related method.
6065 related method.
6070
6066
6071 Modified files are saved with a .orig suffix before reverting.
6067 Modified files are saved with a .orig suffix before reverting.
6072 To disable these backups, use --no-backup.
6068 To disable these backups, use --no-backup.
6073
6069
6074 See :hg:`help dates` for a list of formats valid for -d/--date.
6070 See :hg:`help dates` for a list of formats valid for -d/--date.
6075
6071
6076 See :hg:`help backout` for a way to reverse the effect of an
6072 See :hg:`help backout` for a way to reverse the effect of an
6077 earlier changeset.
6073 earlier changeset.
6078
6074
6079 Returns 0 on success.
6075 Returns 0 on success.
6080 """
6076 """
6081
6077
6082 if opts.get("date"):
6078 if opts.get("date"):
6083 if opts.get("rev"):
6079 if opts.get("rev"):
6084 raise error.Abort(_("you can't specify a revision and a date"))
6080 raise error.Abort(_("you can't specify a revision and a date"))
6085 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6081 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6086
6082
6087 parent, p2 = repo.dirstate.parents()
6083 parent, p2 = repo.dirstate.parents()
6088 if not opts.get('rev') and p2 != nullid:
6084 if not opts.get('rev') and p2 != nullid:
6089 # revert after merge is a trap for new users (issue2915)
6085 # revert after merge is a trap for new users (issue2915)
6090 raise error.Abort(_('uncommitted merge with no revision specified'),
6086 raise error.Abort(_('uncommitted merge with no revision specified'),
6091 hint=_('use "hg update" or see "hg help revert"'))
6087 hint=_('use "hg update" or see "hg help revert"'))
6092
6088
6093 ctx = scmutil.revsingle(repo, opts.get('rev'))
6089 ctx = scmutil.revsingle(repo, opts.get('rev'))
6094
6090
6095 if (not (pats or opts.get('include') or opts.get('exclude') or
6091 if (not (pats or opts.get('include') or opts.get('exclude') or
6096 opts.get('all') or opts.get('interactive'))):
6092 opts.get('all') or opts.get('interactive'))):
6097 msg = _("no files or directories specified")
6093 msg = _("no files or directories specified")
6098 if p2 != nullid:
6094 if p2 != nullid:
6099 hint = _("uncommitted merge, use --all to discard all changes,"
6095 hint = _("uncommitted merge, use --all to discard all changes,"
6100 " or 'hg update -C .' to abort the merge")
6096 " or 'hg update -C .' to abort the merge")
6101 raise error.Abort(msg, hint=hint)
6097 raise error.Abort(msg, hint=hint)
6102 dirty = any(repo.status())
6098 dirty = any(repo.status())
6103 node = ctx.node()
6099 node = ctx.node()
6104 if node != parent:
6100 if node != parent:
6105 if dirty:
6101 if dirty:
6106 hint = _("uncommitted changes, use --all to discard all"
6102 hint = _("uncommitted changes, use --all to discard all"
6107 " changes, or 'hg update %s' to update") % ctx.rev()
6103 " changes, or 'hg update %s' to update") % ctx.rev()
6108 else:
6104 else:
6109 hint = _("use --all to revert all files,"
6105 hint = _("use --all to revert all files,"
6110 " or 'hg update %s' to update") % ctx.rev()
6106 " or 'hg update %s' to update") % ctx.rev()
6111 elif dirty:
6107 elif dirty:
6112 hint = _("uncommitted changes, use --all to discard all changes")
6108 hint = _("uncommitted changes, use --all to discard all changes")
6113 else:
6109 else:
6114 hint = _("use --all to revert all files")
6110 hint = _("use --all to revert all files")
6115 raise error.Abort(msg, hint=hint)
6111 raise error.Abort(msg, hint=hint)
6116
6112
6117 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6113 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6118
6114
6119 @command('rollback', dryrunopts +
6115 @command('rollback', dryrunopts +
6120 [('f', 'force', False, _('ignore safety measures'))])
6116 [('f', 'force', False, _('ignore safety measures'))])
6121 def rollback(ui, repo, **opts):
6117 def rollback(ui, repo, **opts):
6122 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6118 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6123
6119
6124 Please use :hg:`commit --amend` instead of rollback to correct
6120 Please use :hg:`commit --amend` instead of rollback to correct
6125 mistakes in the last commit.
6121 mistakes in the last commit.
6126
6122
6127 This command should be used with care. There is only one level of
6123 This command should be used with care. There is only one level of
6128 rollback, and there is no way to undo a rollback. It will also
6124 rollback, and there is no way to undo a rollback. It will also
6129 restore the dirstate at the time of the last transaction, losing
6125 restore the dirstate at the time of the last transaction, losing
6130 any dirstate changes since that time. This command does not alter
6126 any dirstate changes since that time. This command does not alter
6131 the working directory.
6127 the working directory.
6132
6128
6133 Transactions are used to encapsulate the effects of all commands
6129 Transactions are used to encapsulate the effects of all commands
6134 that create new changesets or propagate existing changesets into a
6130 that create new changesets or propagate existing changesets into a
6135 repository.
6131 repository.
6136
6132
6137 .. container:: verbose
6133 .. container:: verbose
6138
6134
6139 For example, the following commands are transactional, and their
6135 For example, the following commands are transactional, and their
6140 effects can be rolled back:
6136 effects can be rolled back:
6141
6137
6142 - commit
6138 - commit
6143 - import
6139 - import
6144 - pull
6140 - pull
6145 - push (with this repository as the destination)
6141 - push (with this repository as the destination)
6146 - unbundle
6142 - unbundle
6147
6143
6148 To avoid permanent data loss, rollback will refuse to rollback a
6144 To avoid permanent data loss, rollback will refuse to rollback a
6149 commit transaction if it isn't checked out. Use --force to
6145 commit transaction if it isn't checked out. Use --force to
6150 override this protection.
6146 override this protection.
6151
6147
6152 This command is not intended for use on public repositories. Once
6148 This command is not intended for use on public repositories. Once
6153 changes are visible for pull by other users, rolling a transaction
6149 changes are visible for pull by other users, rolling a transaction
6154 back locally is ineffective (someone else may already have pulled
6150 back locally is ineffective (someone else may already have pulled
6155 the changes). Furthermore, a race is possible with readers of the
6151 the changes). Furthermore, a race is possible with readers of the
6156 repository; for example an in-progress pull from the repository
6152 repository; for example an in-progress pull from the repository
6157 may fail if a rollback is performed.
6153 may fail if a rollback is performed.
6158
6154
6159 Returns 0 on success, 1 if no rollback data is available.
6155 Returns 0 on success, 1 if no rollback data is available.
6160 """
6156 """
6161 return repo.rollback(dryrun=opts.get('dry_run'),
6157 return repo.rollback(dryrun=opts.get('dry_run'),
6162 force=opts.get('force'))
6158 force=opts.get('force'))
6163
6159
6164 @command('root', [])
6160 @command('root', [])
6165 def root(ui, repo):
6161 def root(ui, repo):
6166 """print the root (top) of the current working directory
6162 """print the root (top) of the current working directory
6167
6163
6168 Print the root directory of the current repository.
6164 Print the root directory of the current repository.
6169
6165
6170 Returns 0 on success.
6166 Returns 0 on success.
6171 """
6167 """
6172 ui.write(repo.root + "\n")
6168 ui.write(repo.root + "\n")
6173
6169
6174 @command('^serve',
6170 @command('^serve',
6175 [('A', 'accesslog', '', _('name of access log file to write to'),
6171 [('A', 'accesslog', '', _('name of access log file to write to'),
6176 _('FILE')),
6172 _('FILE')),
6177 ('d', 'daemon', None, _('run server in background')),
6173 ('d', 'daemon', None, _('run server in background')),
6178 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6174 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6179 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6175 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6180 # use string type, then we can check if something was passed
6176 # use string type, then we can check if something was passed
6181 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6177 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6182 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6178 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6183 _('ADDR')),
6179 _('ADDR')),
6184 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6180 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6185 _('PREFIX')),
6181 _('PREFIX')),
6186 ('n', 'name', '',
6182 ('n', 'name', '',
6187 _('name to show in web pages (default: working directory)'), _('NAME')),
6183 _('name to show in web pages (default: working directory)'), _('NAME')),
6188 ('', 'web-conf', '',
6184 ('', 'web-conf', '',
6189 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6185 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6190 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6186 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6191 _('FILE')),
6187 _('FILE')),
6192 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6188 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6193 ('', 'stdio', None, _('for remote clients')),
6189 ('', 'stdio', None, _('for remote clients')),
6194 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6190 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6195 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6191 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6196 ('', 'style', '', _('template style to use'), _('STYLE')),
6192 ('', 'style', '', _('template style to use'), _('STYLE')),
6197 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6193 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6198 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6194 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6199 _('[OPTION]...'),
6195 _('[OPTION]...'),
6200 optionalrepo=True)
6196 optionalrepo=True)
6201 def serve(ui, repo, **opts):
6197 def serve(ui, repo, **opts):
6202 """start stand-alone webserver
6198 """start stand-alone webserver
6203
6199
6204 Start a local HTTP repository browser and pull server. You can use
6200 Start a local HTTP repository browser and pull server. You can use
6205 this for ad-hoc sharing and browsing of repositories. It is
6201 this for ad-hoc sharing and browsing of repositories. It is
6206 recommended to use a real web server to serve a repository for
6202 recommended to use a real web server to serve a repository for
6207 longer periods of time.
6203 longer periods of time.
6208
6204
6209 Please note that the server does not implement access control.
6205 Please note that the server does not implement access control.
6210 This means that, by default, anybody can read from the server and
6206 This means that, by default, anybody can read from the server and
6211 nobody can write to it by default. Set the ``web.allow_push``
6207 nobody can write to it by default. Set the ``web.allow_push``
6212 option to ``*`` to allow everybody to push to the server. You
6208 option to ``*`` to allow everybody to push to the server. You
6213 should use a real web server if you need to authenticate users.
6209 should use a real web server if you need to authenticate users.
6214
6210
6215 By default, the server logs accesses to stdout and errors to
6211 By default, the server logs accesses to stdout and errors to
6216 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6212 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6217 files.
6213 files.
6218
6214
6219 To have the server choose a free port number to listen on, specify
6215 To have the server choose a free port number to listen on, specify
6220 a port number of 0; in this case, the server will print the port
6216 a port number of 0; in this case, the server will print the port
6221 number it uses.
6217 number it uses.
6222
6218
6223 Returns 0 on success.
6219 Returns 0 on success.
6224 """
6220 """
6225
6221
6226 if opts["stdio"] and opts["cmdserver"]:
6222 if opts["stdio"] and opts["cmdserver"]:
6227 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6223 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6228
6224
6229 if opts["stdio"]:
6225 if opts["stdio"]:
6230 if repo is None:
6226 if repo is None:
6231 raise error.RepoError(_("there is no Mercurial repository here"
6227 raise error.RepoError(_("there is no Mercurial repository here"
6232 " (.hg not found)"))
6228 " (.hg not found)"))
6233 s = sshserver.sshserver(ui, repo)
6229 s = sshserver.sshserver(ui, repo)
6234 s.serve_forever()
6230 s.serve_forever()
6235
6231
6236 if opts["cmdserver"]:
6232 if opts["cmdserver"]:
6237 service = commandserver.createservice(ui, repo, opts)
6233 service = commandserver.createservice(ui, repo, opts)
6238 else:
6234 else:
6239 service = hgweb.createservice(ui, repo, opts)
6235 service = hgweb.createservice(ui, repo, opts)
6240 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6236 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6241
6237
6242 @command('^status|st',
6238 @command('^status|st',
6243 [('A', 'all', None, _('show status of all files')),
6239 [('A', 'all', None, _('show status of all files')),
6244 ('m', 'modified', None, _('show only modified files')),
6240 ('m', 'modified', None, _('show only modified files')),
6245 ('a', 'added', None, _('show only added files')),
6241 ('a', 'added', None, _('show only added files')),
6246 ('r', 'removed', None, _('show only removed files')),
6242 ('r', 'removed', None, _('show only removed files')),
6247 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6243 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6248 ('c', 'clean', None, _('show only files without changes')),
6244 ('c', 'clean', None, _('show only files without changes')),
6249 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6245 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6250 ('i', 'ignored', None, _('show only ignored files')),
6246 ('i', 'ignored', None, _('show only ignored files')),
6251 ('n', 'no-status', None, _('hide status prefix')),
6247 ('n', 'no-status', None, _('hide status prefix')),
6252 ('C', 'copies', None, _('show source of copied files')),
6248 ('C', 'copies', None, _('show source of copied files')),
6253 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6249 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6254 ('', 'rev', [], _('show difference from revision'), _('REV')),
6250 ('', 'rev', [], _('show difference from revision'), _('REV')),
6255 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6251 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6256 ] + walkopts + subrepoopts + formatteropts,
6252 ] + walkopts + subrepoopts + formatteropts,
6257 _('[OPTION]... [FILE]...'),
6253 _('[OPTION]... [FILE]...'),
6258 inferrepo=True)
6254 inferrepo=True)
6259 def status(ui, repo, *pats, **opts):
6255 def status(ui, repo, *pats, **opts):
6260 """show changed files in the working directory
6256 """show changed files in the working directory
6261
6257
6262 Show status of files in the repository. If names are given, only
6258 Show status of files in the repository. If names are given, only
6263 files that match are shown. Files that are clean or ignored or
6259 files that match are shown. Files that are clean or ignored or
6264 the source of a copy/move operation, are not listed unless
6260 the source of a copy/move operation, are not listed unless
6265 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6261 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6266 Unless options described with "show only ..." are given, the
6262 Unless options described with "show only ..." are given, the
6267 options -mardu are used.
6263 options -mardu are used.
6268
6264
6269 Option -q/--quiet hides untracked (unknown and ignored) files
6265 Option -q/--quiet hides untracked (unknown and ignored) files
6270 unless explicitly requested with -u/--unknown or -i/--ignored.
6266 unless explicitly requested with -u/--unknown or -i/--ignored.
6271
6267
6272 .. note::
6268 .. note::
6273
6269
6274 :hg:`status` may appear to disagree with diff if permissions have
6270 :hg:`status` may appear to disagree with diff if permissions have
6275 changed or a merge has occurred. The standard diff format does
6271 changed or a merge has occurred. The standard diff format does
6276 not report permission changes and diff only reports changes
6272 not report permission changes and diff only reports changes
6277 relative to one merge parent.
6273 relative to one merge parent.
6278
6274
6279 If one revision is given, it is used as the base revision.
6275 If one revision is given, it is used as the base revision.
6280 If two revisions are given, the differences between them are
6276 If two revisions are given, the differences between them are
6281 shown. The --change option can also be used as a shortcut to list
6277 shown. The --change option can also be used as a shortcut to list
6282 the changed files of a revision from its first parent.
6278 the changed files of a revision from its first parent.
6283
6279
6284 The codes used to show the status of files are::
6280 The codes used to show the status of files are::
6285
6281
6286 M = modified
6282 M = modified
6287 A = added
6283 A = added
6288 R = removed
6284 R = removed
6289 C = clean
6285 C = clean
6290 ! = missing (deleted by non-hg command, but still tracked)
6286 ! = missing (deleted by non-hg command, but still tracked)
6291 ? = not tracked
6287 ? = not tracked
6292 I = ignored
6288 I = ignored
6293 = origin of the previous file (with --copies)
6289 = origin of the previous file (with --copies)
6294
6290
6295 .. container:: verbose
6291 .. container:: verbose
6296
6292
6297 Examples:
6293 Examples:
6298
6294
6299 - show changes in the working directory relative to a
6295 - show changes in the working directory relative to a
6300 changeset::
6296 changeset::
6301
6297
6302 hg status --rev 9353
6298 hg status --rev 9353
6303
6299
6304 - show changes in the working directory relative to the
6300 - show changes in the working directory relative to the
6305 current directory (see :hg:`help patterns` for more information)::
6301 current directory (see :hg:`help patterns` for more information)::
6306
6302
6307 hg status re:
6303 hg status re:
6308
6304
6309 - show all changes including copies in an existing changeset::
6305 - show all changes including copies in an existing changeset::
6310
6306
6311 hg status --copies --change 9353
6307 hg status --copies --change 9353
6312
6308
6313 - get a NUL separated list of added files, suitable for xargs::
6309 - get a NUL separated list of added files, suitable for xargs::
6314
6310
6315 hg status -an0
6311 hg status -an0
6316
6312
6317 Returns 0 on success.
6313 Returns 0 on success.
6318 """
6314 """
6319
6315
6320 revs = opts.get('rev')
6316 revs = opts.get('rev')
6321 change = opts.get('change')
6317 change = opts.get('change')
6322
6318
6323 if revs and change:
6319 if revs and change:
6324 msg = _('cannot specify --rev and --change at the same time')
6320 msg = _('cannot specify --rev and --change at the same time')
6325 raise error.Abort(msg)
6321 raise error.Abort(msg)
6326 elif change:
6322 elif change:
6327 node2 = scmutil.revsingle(repo, change, None).node()
6323 node2 = scmutil.revsingle(repo, change, None).node()
6328 node1 = repo[node2].p1().node()
6324 node1 = repo[node2].p1().node()
6329 else:
6325 else:
6330 node1, node2 = scmutil.revpair(repo, revs)
6326 node1, node2 = scmutil.revpair(repo, revs)
6331
6327
6332 if pats:
6328 if pats:
6333 cwd = repo.getcwd()
6329 cwd = repo.getcwd()
6334 else:
6330 else:
6335 cwd = ''
6331 cwd = ''
6336
6332
6337 if opts.get('print0'):
6333 if opts.get('print0'):
6338 end = '\0'
6334 end = '\0'
6339 else:
6335 else:
6340 end = '\n'
6336 end = '\n'
6341 copy = {}
6337 copy = {}
6342 states = 'modified added removed deleted unknown ignored clean'.split()
6338 states = 'modified added removed deleted unknown ignored clean'.split()
6343 show = [k for k in states if opts.get(k)]
6339 show = [k for k in states if opts.get(k)]
6344 if opts.get('all'):
6340 if opts.get('all'):
6345 show += ui.quiet and (states[:4] + ['clean']) or states
6341 show += ui.quiet and (states[:4] + ['clean']) or states
6346 if not show:
6342 if not show:
6347 if ui.quiet:
6343 if ui.quiet:
6348 show = states[:4]
6344 show = states[:4]
6349 else:
6345 else:
6350 show = states[:5]
6346 show = states[:5]
6351
6347
6352 m = scmutil.match(repo[node2], pats, opts)
6348 m = scmutil.match(repo[node2], pats, opts)
6353 stat = repo.status(node1, node2, m,
6349 stat = repo.status(node1, node2, m,
6354 'ignored' in show, 'clean' in show, 'unknown' in show,
6350 'ignored' in show, 'clean' in show, 'unknown' in show,
6355 opts.get('subrepos'))
6351 opts.get('subrepos'))
6356 changestates = zip(states, 'MAR!?IC', stat)
6352 changestates = zip(states, 'MAR!?IC', stat)
6357
6353
6358 if (opts.get('all') or opts.get('copies')
6354 if (opts.get('all') or opts.get('copies')
6359 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6355 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6360 copy = copies.pathcopies(repo[node1], repo[node2], m)
6356 copy = copies.pathcopies(repo[node1], repo[node2], m)
6361
6357
6362 fm = ui.formatter('status', opts)
6358 fm = ui.formatter('status', opts)
6363 fmt = '%s' + end
6359 fmt = '%s' + end
6364 showchar = not opts.get('no_status')
6360 showchar = not opts.get('no_status')
6365
6361
6366 for state, char, files in changestates:
6362 for state, char, files in changestates:
6367 if state in show:
6363 if state in show:
6368 label = 'status.' + state
6364 label = 'status.' + state
6369 for f in files:
6365 for f in files:
6370 fm.startitem()
6366 fm.startitem()
6371 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6367 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6372 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6368 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6373 if f in copy:
6369 if f in copy:
6374 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6370 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6375 label='status.copied')
6371 label='status.copied')
6376 fm.end()
6372 fm.end()
6377
6373
6378 @command('^summary|sum',
6374 @command('^summary|sum',
6379 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6375 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6380 def summary(ui, repo, **opts):
6376 def summary(ui, repo, **opts):
6381 """summarize working directory state
6377 """summarize working directory state
6382
6378
6383 This generates a brief summary of the working directory state,
6379 This generates a brief summary of the working directory state,
6384 including parents, branch, commit status, phase and available updates.
6380 including parents, branch, commit status, phase and available updates.
6385
6381
6386 With the --remote option, this will check the default paths for
6382 With the --remote option, this will check the default paths for
6387 incoming and outgoing changes. This can be time-consuming.
6383 incoming and outgoing changes. This can be time-consuming.
6388
6384
6389 Returns 0 on success.
6385 Returns 0 on success.
6390 """
6386 """
6391
6387
6392 ctx = repo[None]
6388 ctx = repo[None]
6393 parents = ctx.parents()
6389 parents = ctx.parents()
6394 pnode = parents[0].node()
6390 pnode = parents[0].node()
6395 marks = []
6391 marks = []
6396
6392
6397 for p in parents:
6393 for p in parents:
6398 # label with log.changeset (instead of log.parent) since this
6394 # label with log.changeset (instead of log.parent) since this
6399 # shows a working directory parent *changeset*:
6395 # shows a working directory parent *changeset*:
6400 # i18n: column positioning for "hg summary"
6396 # i18n: column positioning for "hg summary"
6401 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6397 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6402 label='log.changeset changeset.%s' % p.phasestr())
6398 label='log.changeset changeset.%s' % p.phasestr())
6403 ui.write(' '.join(p.tags()), label='log.tag')
6399 ui.write(' '.join(p.tags()), label='log.tag')
6404 if p.bookmarks():
6400 if p.bookmarks():
6405 marks.extend(p.bookmarks())
6401 marks.extend(p.bookmarks())
6406 if p.rev() == -1:
6402 if p.rev() == -1:
6407 if not len(repo):
6403 if not len(repo):
6408 ui.write(_(' (empty repository)'))
6404 ui.write(_(' (empty repository)'))
6409 else:
6405 else:
6410 ui.write(_(' (no revision checked out)'))
6406 ui.write(_(' (no revision checked out)'))
6411 ui.write('\n')
6407 ui.write('\n')
6412 if p.description():
6408 if p.description():
6413 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6409 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6414 label='log.summary')
6410 label='log.summary')
6415
6411
6416 branch = ctx.branch()
6412 branch = ctx.branch()
6417 bheads = repo.branchheads(branch)
6413 bheads = repo.branchheads(branch)
6418 # i18n: column positioning for "hg summary"
6414 # i18n: column positioning for "hg summary"
6419 m = _('branch: %s\n') % branch
6415 m = _('branch: %s\n') % branch
6420 if branch != 'default':
6416 if branch != 'default':
6421 ui.write(m, label='log.branch')
6417 ui.write(m, label='log.branch')
6422 else:
6418 else:
6423 ui.status(m, label='log.branch')
6419 ui.status(m, label='log.branch')
6424
6420
6425 if marks:
6421 if marks:
6426 active = repo._activebookmark
6422 active = repo._activebookmark
6427 # i18n: column positioning for "hg summary"
6423 # i18n: column positioning for "hg summary"
6428 ui.write(_('bookmarks:'), label='log.bookmark')
6424 ui.write(_('bookmarks:'), label='log.bookmark')
6429 if active is not None:
6425 if active is not None:
6430 if active in marks:
6426 if active in marks:
6431 ui.write(' *' + active, label=activebookmarklabel)
6427 ui.write(' *' + active, label=activebookmarklabel)
6432 marks.remove(active)
6428 marks.remove(active)
6433 else:
6429 else:
6434 ui.write(' [%s]' % active, label=activebookmarklabel)
6430 ui.write(' [%s]' % active, label=activebookmarklabel)
6435 for m in marks:
6431 for m in marks:
6436 ui.write(' ' + m, label='log.bookmark')
6432 ui.write(' ' + m, label='log.bookmark')
6437 ui.write('\n', label='log.bookmark')
6433 ui.write('\n', label='log.bookmark')
6438
6434
6439 status = repo.status(unknown=True)
6435 status = repo.status(unknown=True)
6440
6436
6441 c = repo.dirstate.copies()
6437 c = repo.dirstate.copies()
6442 copied, renamed = [], []
6438 copied, renamed = [], []
6443 for d, s in c.iteritems():
6439 for d, s in c.iteritems():
6444 if s in status.removed:
6440 if s in status.removed:
6445 status.removed.remove(s)
6441 status.removed.remove(s)
6446 renamed.append(d)
6442 renamed.append(d)
6447 else:
6443 else:
6448 copied.append(d)
6444 copied.append(d)
6449 if d in status.added:
6445 if d in status.added:
6450 status.added.remove(d)
6446 status.added.remove(d)
6451
6447
6452 try:
6448 try:
6453 ms = mergemod.mergestate.read(repo)
6449 ms = mergemod.mergestate.read(repo)
6454 except error.UnsupportedMergeRecords as e:
6450 except error.UnsupportedMergeRecords as e:
6455 s = ' '.join(e.recordtypes)
6451 s = ' '.join(e.recordtypes)
6456 ui.warn(
6452 ui.warn(
6457 _('warning: merge state has unsupported record types: %s\n') % s)
6453 _('warning: merge state has unsupported record types: %s\n') % s)
6458 unresolved = 0
6454 unresolved = 0
6459 else:
6455 else:
6460 unresolved = [f for f in ms if ms[f] == 'u']
6456 unresolved = [f for f in ms if ms[f] == 'u']
6461
6457
6462 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6458 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6463
6459
6464 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6460 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6465 (ui.label(_('%d added'), 'status.added'), status.added),
6461 (ui.label(_('%d added'), 'status.added'), status.added),
6466 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6462 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6467 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6463 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6468 (ui.label(_('%d copied'), 'status.copied'), copied),
6464 (ui.label(_('%d copied'), 'status.copied'), copied),
6469 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6465 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6470 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6466 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6471 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6467 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6472 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6468 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6473 t = []
6469 t = []
6474 for l, s in labels:
6470 for l, s in labels:
6475 if s:
6471 if s:
6476 t.append(l % len(s))
6472 t.append(l % len(s))
6477
6473
6478 t = ', '.join(t)
6474 t = ', '.join(t)
6479 cleanworkdir = False
6475 cleanworkdir = False
6480
6476
6481 if repo.vfs.exists('graftstate'):
6477 if repo.vfs.exists('graftstate'):
6482 t += _(' (graft in progress)')
6478 t += _(' (graft in progress)')
6483 if repo.vfs.exists('updatestate'):
6479 if repo.vfs.exists('updatestate'):
6484 t += _(' (interrupted update)')
6480 t += _(' (interrupted update)')
6485 elif len(parents) > 1:
6481 elif len(parents) > 1:
6486 t += _(' (merge)')
6482 t += _(' (merge)')
6487 elif branch != parents[0].branch():
6483 elif branch != parents[0].branch():
6488 t += _(' (new branch)')
6484 t += _(' (new branch)')
6489 elif (parents[0].closesbranch() and
6485 elif (parents[0].closesbranch() and
6490 pnode in repo.branchheads(branch, closed=True)):
6486 pnode in repo.branchheads(branch, closed=True)):
6491 t += _(' (head closed)')
6487 t += _(' (head closed)')
6492 elif not (status.modified or status.added or status.removed or renamed or
6488 elif not (status.modified or status.added or status.removed or renamed or
6493 copied or subs):
6489 copied or subs):
6494 t += _(' (clean)')
6490 t += _(' (clean)')
6495 cleanworkdir = True
6491 cleanworkdir = True
6496 elif pnode not in bheads:
6492 elif pnode not in bheads:
6497 t += _(' (new branch head)')
6493 t += _(' (new branch head)')
6498
6494
6499 if parents:
6495 if parents:
6500 pendingphase = max(p.phase() for p in parents)
6496 pendingphase = max(p.phase() for p in parents)
6501 else:
6497 else:
6502 pendingphase = phases.public
6498 pendingphase = phases.public
6503
6499
6504 if pendingphase > phases.newcommitphase(ui):
6500 if pendingphase > phases.newcommitphase(ui):
6505 t += ' (%s)' % phases.phasenames[pendingphase]
6501 t += ' (%s)' % phases.phasenames[pendingphase]
6506
6502
6507 if cleanworkdir:
6503 if cleanworkdir:
6508 # i18n: column positioning for "hg summary"
6504 # i18n: column positioning for "hg summary"
6509 ui.status(_('commit: %s\n') % t.strip())
6505 ui.status(_('commit: %s\n') % t.strip())
6510 else:
6506 else:
6511 # i18n: column positioning for "hg summary"
6507 # i18n: column positioning for "hg summary"
6512 ui.write(_('commit: %s\n') % t.strip())
6508 ui.write(_('commit: %s\n') % t.strip())
6513
6509
6514 # all ancestors of branch heads - all ancestors of parent = new csets
6510 # all ancestors of branch heads - all ancestors of parent = new csets
6515 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6511 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6516 bheads))
6512 bheads))
6517
6513
6518 if new == 0:
6514 if new == 0:
6519 # i18n: column positioning for "hg summary"
6515 # i18n: column positioning for "hg summary"
6520 ui.status(_('update: (current)\n'))
6516 ui.status(_('update: (current)\n'))
6521 elif pnode not in bheads:
6517 elif pnode not in bheads:
6522 # i18n: column positioning for "hg summary"
6518 # i18n: column positioning for "hg summary"
6523 ui.write(_('update: %d new changesets (update)\n') % new)
6519 ui.write(_('update: %d new changesets (update)\n') % new)
6524 else:
6520 else:
6525 # i18n: column positioning for "hg summary"
6521 # i18n: column positioning for "hg summary"
6526 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6522 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6527 (new, len(bheads)))
6523 (new, len(bheads)))
6528
6524
6529 t = []
6525 t = []
6530 draft = len(repo.revs('draft()'))
6526 draft = len(repo.revs('draft()'))
6531 if draft:
6527 if draft:
6532 t.append(_('%d draft') % draft)
6528 t.append(_('%d draft') % draft)
6533 secret = len(repo.revs('secret()'))
6529 secret = len(repo.revs('secret()'))
6534 if secret:
6530 if secret:
6535 t.append(_('%d secret') % secret)
6531 t.append(_('%d secret') % secret)
6536
6532
6537 if draft or secret:
6533 if draft or secret:
6538 ui.status(_('phases: %s\n') % ', '.join(t))
6534 ui.status(_('phases: %s\n') % ', '.join(t))
6539
6535
6540 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6536 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6541 for trouble in ("unstable", "divergent", "bumped"):
6537 for trouble in ("unstable", "divergent", "bumped"):
6542 numtrouble = len(repo.revs(trouble + "()"))
6538 numtrouble = len(repo.revs(trouble + "()"))
6543 # We write all the possibilities to ease translation
6539 # We write all the possibilities to ease translation
6544 troublemsg = {
6540 troublemsg = {
6545 "unstable": _("unstable: %d changesets"),
6541 "unstable": _("unstable: %d changesets"),
6546 "divergent": _("divergent: %d changesets"),
6542 "divergent": _("divergent: %d changesets"),
6547 "bumped": _("bumped: %d changesets"),
6543 "bumped": _("bumped: %d changesets"),
6548 }
6544 }
6549 if numtrouble > 0:
6545 if numtrouble > 0:
6550 ui.status(troublemsg[trouble] % numtrouble + "\n")
6546 ui.status(troublemsg[trouble] % numtrouble + "\n")
6551
6547
6552 cmdutil.summaryhooks(ui, repo)
6548 cmdutil.summaryhooks(ui, repo)
6553
6549
6554 if opts.get('remote'):
6550 if opts.get('remote'):
6555 needsincoming, needsoutgoing = True, True
6551 needsincoming, needsoutgoing = True, True
6556 else:
6552 else:
6557 needsincoming, needsoutgoing = False, False
6553 needsincoming, needsoutgoing = False, False
6558 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6554 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6559 if i:
6555 if i:
6560 needsincoming = True
6556 needsincoming = True
6561 if o:
6557 if o:
6562 needsoutgoing = True
6558 needsoutgoing = True
6563 if not needsincoming and not needsoutgoing:
6559 if not needsincoming and not needsoutgoing:
6564 return
6560 return
6565
6561
6566 def getincoming():
6562 def getincoming():
6567 source, branches = hg.parseurl(ui.expandpath('default'))
6563 source, branches = hg.parseurl(ui.expandpath('default'))
6568 sbranch = branches[0]
6564 sbranch = branches[0]
6569 try:
6565 try:
6570 other = hg.peer(repo, {}, source)
6566 other = hg.peer(repo, {}, source)
6571 except error.RepoError:
6567 except error.RepoError:
6572 if opts.get('remote'):
6568 if opts.get('remote'):
6573 raise
6569 raise
6574 return source, sbranch, None, None, None
6570 return source, sbranch, None, None, None
6575 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6571 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6576 if revs:
6572 if revs:
6577 revs = [other.lookup(rev) for rev in revs]
6573 revs = [other.lookup(rev) for rev in revs]
6578 ui.debug('comparing with %s\n' % util.hidepassword(source))
6574 ui.debug('comparing with %s\n' % util.hidepassword(source))
6579 repo.ui.pushbuffer()
6575 repo.ui.pushbuffer()
6580 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6576 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6581 repo.ui.popbuffer()
6577 repo.ui.popbuffer()
6582 return source, sbranch, other, commoninc, commoninc[1]
6578 return source, sbranch, other, commoninc, commoninc[1]
6583
6579
6584 if needsincoming:
6580 if needsincoming:
6585 source, sbranch, sother, commoninc, incoming = getincoming()
6581 source, sbranch, sother, commoninc, incoming = getincoming()
6586 else:
6582 else:
6587 source = sbranch = sother = commoninc = incoming = None
6583 source = sbranch = sother = commoninc = incoming = None
6588
6584
6589 def getoutgoing():
6585 def getoutgoing():
6590 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6586 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6591 dbranch = branches[0]
6587 dbranch = branches[0]
6592 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6588 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6593 if source != dest:
6589 if source != dest:
6594 try:
6590 try:
6595 dother = hg.peer(repo, {}, dest)
6591 dother = hg.peer(repo, {}, dest)
6596 except error.RepoError:
6592 except error.RepoError:
6597 if opts.get('remote'):
6593 if opts.get('remote'):
6598 raise
6594 raise
6599 return dest, dbranch, None, None
6595 return dest, dbranch, None, None
6600 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6596 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6601 elif sother is None:
6597 elif sother is None:
6602 # there is no explicit destination peer, but source one is invalid
6598 # there is no explicit destination peer, but source one is invalid
6603 return dest, dbranch, None, None
6599 return dest, dbranch, None, None
6604 else:
6600 else:
6605 dother = sother
6601 dother = sother
6606 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6602 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6607 common = None
6603 common = None
6608 else:
6604 else:
6609 common = commoninc
6605 common = commoninc
6610 if revs:
6606 if revs:
6611 revs = [repo.lookup(rev) for rev in revs]
6607 revs = [repo.lookup(rev) for rev in revs]
6612 repo.ui.pushbuffer()
6608 repo.ui.pushbuffer()
6613 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6609 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6614 commoninc=common)
6610 commoninc=common)
6615 repo.ui.popbuffer()
6611 repo.ui.popbuffer()
6616 return dest, dbranch, dother, outgoing
6612 return dest, dbranch, dother, outgoing
6617
6613
6618 if needsoutgoing:
6614 if needsoutgoing:
6619 dest, dbranch, dother, outgoing = getoutgoing()
6615 dest, dbranch, dother, outgoing = getoutgoing()
6620 else:
6616 else:
6621 dest = dbranch = dother = outgoing = None
6617 dest = dbranch = dother = outgoing = None
6622
6618
6623 if opts.get('remote'):
6619 if opts.get('remote'):
6624 t = []
6620 t = []
6625 if incoming:
6621 if incoming:
6626 t.append(_('1 or more incoming'))
6622 t.append(_('1 or more incoming'))
6627 o = outgoing.missing
6623 o = outgoing.missing
6628 if o:
6624 if o:
6629 t.append(_('%d outgoing') % len(o))
6625 t.append(_('%d outgoing') % len(o))
6630 other = dother or sother
6626 other = dother or sother
6631 if 'bookmarks' in other.listkeys('namespaces'):
6627 if 'bookmarks' in other.listkeys('namespaces'):
6632 counts = bookmarks.summary(repo, other)
6628 counts = bookmarks.summary(repo, other)
6633 if counts[0] > 0:
6629 if counts[0] > 0:
6634 t.append(_('%d incoming bookmarks') % counts[0])
6630 t.append(_('%d incoming bookmarks') % counts[0])
6635 if counts[1] > 0:
6631 if counts[1] > 0:
6636 t.append(_('%d outgoing bookmarks') % counts[1])
6632 t.append(_('%d outgoing bookmarks') % counts[1])
6637
6633
6638 if t:
6634 if t:
6639 # i18n: column positioning for "hg summary"
6635 # i18n: column positioning for "hg summary"
6640 ui.write(_('remote: %s\n') % (', '.join(t)))
6636 ui.write(_('remote: %s\n') % (', '.join(t)))
6641 else:
6637 else:
6642 # i18n: column positioning for "hg summary"
6638 # i18n: column positioning for "hg summary"
6643 ui.status(_('remote: (synced)\n'))
6639 ui.status(_('remote: (synced)\n'))
6644
6640
6645 cmdutil.summaryremotehooks(ui, repo, opts,
6641 cmdutil.summaryremotehooks(ui, repo, opts,
6646 ((source, sbranch, sother, commoninc),
6642 ((source, sbranch, sother, commoninc),
6647 (dest, dbranch, dother, outgoing)))
6643 (dest, dbranch, dother, outgoing)))
6648
6644
6649 @command('tag',
6645 @command('tag',
6650 [('f', 'force', None, _('force tag')),
6646 [('f', 'force', None, _('force tag')),
6651 ('l', 'local', None, _('make the tag local')),
6647 ('l', 'local', None, _('make the tag local')),
6652 ('r', 'rev', '', _('revision to tag'), _('REV')),
6648 ('r', 'rev', '', _('revision to tag'), _('REV')),
6653 ('', 'remove', None, _('remove a tag')),
6649 ('', 'remove', None, _('remove a tag')),
6654 # -l/--local is already there, commitopts cannot be used
6650 # -l/--local is already there, commitopts cannot be used
6655 ('e', 'edit', None, _('invoke editor on commit messages')),
6651 ('e', 'edit', None, _('invoke editor on commit messages')),
6656 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6652 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6657 ] + commitopts2,
6653 ] + commitopts2,
6658 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6654 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6659 def tag(ui, repo, name1, *names, **opts):
6655 def tag(ui, repo, name1, *names, **opts):
6660 """add one or more tags for the current or given revision
6656 """add one or more tags for the current or given revision
6661
6657
6662 Name a particular revision using <name>.
6658 Name a particular revision using <name>.
6663
6659
6664 Tags are used to name particular revisions of the repository and are
6660 Tags are used to name particular revisions of the repository and are
6665 very useful to compare different revisions, to go back to significant
6661 very useful to compare different revisions, to go back to significant
6666 earlier versions or to mark branch points as releases, etc. Changing
6662 earlier versions or to mark branch points as releases, etc. Changing
6667 an existing tag is normally disallowed; use -f/--force to override.
6663 an existing tag is normally disallowed; use -f/--force to override.
6668
6664
6669 If no revision is given, the parent of the working directory is
6665 If no revision is given, the parent of the working directory is
6670 used.
6666 used.
6671
6667
6672 To facilitate version control, distribution, and merging of tags,
6668 To facilitate version control, distribution, and merging of tags,
6673 they are stored as a file named ".hgtags" which is managed similarly
6669 they are stored as a file named ".hgtags" which is managed similarly
6674 to other project files and can be hand-edited if necessary. This
6670 to other project files and can be hand-edited if necessary. This
6675 also means that tagging creates a new commit. The file
6671 also means that tagging creates a new commit. The file
6676 ".hg/localtags" is used for local tags (not shared among
6672 ".hg/localtags" is used for local tags (not shared among
6677 repositories).
6673 repositories).
6678
6674
6679 Tag commits are usually made at the head of a branch. If the parent
6675 Tag commits are usually made at the head of a branch. If the parent
6680 of the working directory is not a branch head, :hg:`tag` aborts; use
6676 of the working directory is not a branch head, :hg:`tag` aborts; use
6681 -f/--force to force the tag commit to be based on a non-head
6677 -f/--force to force the tag commit to be based on a non-head
6682 changeset.
6678 changeset.
6683
6679
6684 See :hg:`help dates` for a list of formats valid for -d/--date.
6680 See :hg:`help dates` for a list of formats valid for -d/--date.
6685
6681
6686 Since tag names have priority over branch names during revision
6682 Since tag names have priority over branch names during revision
6687 lookup, using an existing branch name as a tag name is discouraged.
6683 lookup, using an existing branch name as a tag name is discouraged.
6688
6684
6689 Returns 0 on success.
6685 Returns 0 on success.
6690 """
6686 """
6691 wlock = lock = None
6687 wlock = lock = None
6692 try:
6688 try:
6693 wlock = repo.wlock()
6689 wlock = repo.wlock()
6694 lock = repo.lock()
6690 lock = repo.lock()
6695 rev_ = "."
6691 rev_ = "."
6696 names = [t.strip() for t in (name1,) + names]
6692 names = [t.strip() for t in (name1,) + names]
6697 if len(names) != len(set(names)):
6693 if len(names) != len(set(names)):
6698 raise error.Abort(_('tag names must be unique'))
6694 raise error.Abort(_('tag names must be unique'))
6699 for n in names:
6695 for n in names:
6700 scmutil.checknewlabel(repo, n, 'tag')
6696 scmutil.checknewlabel(repo, n, 'tag')
6701 if not n:
6697 if not n:
6702 raise error.Abort(_('tag names cannot consist entirely of '
6698 raise error.Abort(_('tag names cannot consist entirely of '
6703 'whitespace'))
6699 'whitespace'))
6704 if opts.get('rev') and opts.get('remove'):
6700 if opts.get('rev') and opts.get('remove'):
6705 raise error.Abort(_("--rev and --remove are incompatible"))
6701 raise error.Abort(_("--rev and --remove are incompatible"))
6706 if opts.get('rev'):
6702 if opts.get('rev'):
6707 rev_ = opts['rev']
6703 rev_ = opts['rev']
6708 message = opts.get('message')
6704 message = opts.get('message')
6709 if opts.get('remove'):
6705 if opts.get('remove'):
6710 if opts.get('local'):
6706 if opts.get('local'):
6711 expectedtype = 'local'
6707 expectedtype = 'local'
6712 else:
6708 else:
6713 expectedtype = 'global'
6709 expectedtype = 'global'
6714
6710
6715 for n in names:
6711 for n in names:
6716 if not repo.tagtype(n):
6712 if not repo.tagtype(n):
6717 raise error.Abort(_("tag '%s' does not exist") % n)
6713 raise error.Abort(_("tag '%s' does not exist") % n)
6718 if repo.tagtype(n) != expectedtype:
6714 if repo.tagtype(n) != expectedtype:
6719 if expectedtype == 'global':
6715 if expectedtype == 'global':
6720 raise error.Abort(_("tag '%s' is not a global tag") % n)
6716 raise error.Abort(_("tag '%s' is not a global tag") % n)
6721 else:
6717 else:
6722 raise error.Abort(_("tag '%s' is not a local tag") % n)
6718 raise error.Abort(_("tag '%s' is not a local tag") % n)
6723 rev_ = 'null'
6719 rev_ = 'null'
6724 if not message:
6720 if not message:
6725 # we don't translate commit messages
6721 # we don't translate commit messages
6726 message = 'Removed tag %s' % ', '.join(names)
6722 message = 'Removed tag %s' % ', '.join(names)
6727 elif not opts.get('force'):
6723 elif not opts.get('force'):
6728 for n in names:
6724 for n in names:
6729 if n in repo.tags():
6725 if n in repo.tags():
6730 raise error.Abort(_("tag '%s' already exists "
6726 raise error.Abort(_("tag '%s' already exists "
6731 "(use -f to force)") % n)
6727 "(use -f to force)") % n)
6732 if not opts.get('local'):
6728 if not opts.get('local'):
6733 p1, p2 = repo.dirstate.parents()
6729 p1, p2 = repo.dirstate.parents()
6734 if p2 != nullid:
6730 if p2 != nullid:
6735 raise error.Abort(_('uncommitted merge'))
6731 raise error.Abort(_('uncommitted merge'))
6736 bheads = repo.branchheads()
6732 bheads = repo.branchheads()
6737 if not opts.get('force') and bheads and p1 not in bheads:
6733 if not opts.get('force') and bheads and p1 not in bheads:
6738 raise error.Abort(_('not at a branch head (use -f to force)'))
6734 raise error.Abort(_('not at a branch head (use -f to force)'))
6739 r = scmutil.revsingle(repo, rev_).node()
6735 r = scmutil.revsingle(repo, rev_).node()
6740
6736
6741 if not message:
6737 if not message:
6742 # we don't translate commit messages
6738 # we don't translate commit messages
6743 message = ('Added tag %s for changeset %s' %
6739 message = ('Added tag %s for changeset %s' %
6744 (', '.join(names), short(r)))
6740 (', '.join(names), short(r)))
6745
6741
6746 date = opts.get('date')
6742 date = opts.get('date')
6747 if date:
6743 if date:
6748 date = util.parsedate(date)
6744 date = util.parsedate(date)
6749
6745
6750 if opts.get('remove'):
6746 if opts.get('remove'):
6751 editform = 'tag.remove'
6747 editform = 'tag.remove'
6752 else:
6748 else:
6753 editform = 'tag.add'
6749 editform = 'tag.add'
6754 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6750 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6755
6751
6756 # don't allow tagging the null rev
6752 # don't allow tagging the null rev
6757 if (not opts.get('remove') and
6753 if (not opts.get('remove') and
6758 scmutil.revsingle(repo, rev_).rev() == nullrev):
6754 scmutil.revsingle(repo, rev_).rev() == nullrev):
6759 raise error.Abort(_("cannot tag null revision"))
6755 raise error.Abort(_("cannot tag null revision"))
6760
6756
6761 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6757 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6762 editor=editor)
6758 editor=editor)
6763 finally:
6759 finally:
6764 release(lock, wlock)
6760 release(lock, wlock)
6765
6761
6766 @command('tags', formatteropts, '')
6762 @command('tags', formatteropts, '')
6767 def tags(ui, repo, **opts):
6763 def tags(ui, repo, **opts):
6768 """list repository tags
6764 """list repository tags
6769
6765
6770 This lists both regular and local tags. When the -v/--verbose
6766 This lists both regular and local tags. When the -v/--verbose
6771 switch is used, a third column "local" is printed for local tags.
6767 switch is used, a third column "local" is printed for local tags.
6772 When the -q/--quiet switch is used, only the tag name is printed.
6768 When the -q/--quiet switch is used, only the tag name is printed.
6773
6769
6774 Returns 0 on success.
6770 Returns 0 on success.
6775 """
6771 """
6776
6772
6777 fm = ui.formatter('tags', opts)
6773 fm = ui.formatter('tags', opts)
6778 hexfunc = fm.hexfunc
6774 hexfunc = fm.hexfunc
6779 tagtype = ""
6775 tagtype = ""
6780
6776
6781 for t, n in reversed(repo.tagslist()):
6777 for t, n in reversed(repo.tagslist()):
6782 hn = hexfunc(n)
6778 hn = hexfunc(n)
6783 label = 'tags.normal'
6779 label = 'tags.normal'
6784 tagtype = ''
6780 tagtype = ''
6785 if repo.tagtype(t) == 'local':
6781 if repo.tagtype(t) == 'local':
6786 label = 'tags.local'
6782 label = 'tags.local'
6787 tagtype = 'local'
6783 tagtype = 'local'
6788
6784
6789 fm.startitem()
6785 fm.startitem()
6790 fm.write('tag', '%s', t, label=label)
6786 fm.write('tag', '%s', t, label=label)
6791 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6787 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6792 fm.condwrite(not ui.quiet, 'rev node', fmt,
6788 fm.condwrite(not ui.quiet, 'rev node', fmt,
6793 repo.changelog.rev(n), hn, label=label)
6789 repo.changelog.rev(n), hn, label=label)
6794 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6790 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6795 tagtype, label=label)
6791 tagtype, label=label)
6796 fm.plain('\n')
6792 fm.plain('\n')
6797 fm.end()
6793 fm.end()
6798
6794
6799 @command('tip',
6795 @command('tip',
6800 [('p', 'patch', None, _('show patch')),
6796 [('p', 'patch', None, _('show patch')),
6801 ('g', 'git', None, _('use git extended diff format')),
6797 ('g', 'git', None, _('use git extended diff format')),
6802 ] + templateopts,
6798 ] + templateopts,
6803 _('[-p] [-g]'))
6799 _('[-p] [-g]'))
6804 def tip(ui, repo, **opts):
6800 def tip(ui, repo, **opts):
6805 """show the tip revision (DEPRECATED)
6801 """show the tip revision (DEPRECATED)
6806
6802
6807 The tip revision (usually just called the tip) is the changeset
6803 The tip revision (usually just called the tip) is the changeset
6808 most recently added to the repository (and therefore the most
6804 most recently added to the repository (and therefore the most
6809 recently changed head).
6805 recently changed head).
6810
6806
6811 If you have just made a commit, that commit will be the tip. If
6807 If you have just made a commit, that commit will be the tip. If
6812 you have just pulled changes from another repository, the tip of
6808 you have just pulled changes from another repository, the tip of
6813 that repository becomes the current tip. The "tip" tag is special
6809 that repository becomes the current tip. The "tip" tag is special
6814 and cannot be renamed or assigned to a different changeset.
6810 and cannot be renamed or assigned to a different changeset.
6815
6811
6816 This command is deprecated, please use :hg:`heads` instead.
6812 This command is deprecated, please use :hg:`heads` instead.
6817
6813
6818 Returns 0 on success.
6814 Returns 0 on success.
6819 """
6815 """
6820 displayer = cmdutil.show_changeset(ui, repo, opts)
6816 displayer = cmdutil.show_changeset(ui, repo, opts)
6821 displayer.show(repo['tip'])
6817 displayer.show(repo['tip'])
6822 displayer.close()
6818 displayer.close()
6823
6819
6824 @command('unbundle',
6820 @command('unbundle',
6825 [('u', 'update', None,
6821 [('u', 'update', None,
6826 _('update to new branch head if changesets were unbundled'))],
6822 _('update to new branch head if changesets were unbundled'))],
6827 _('[-u] FILE...'))
6823 _('[-u] FILE...'))
6828 def unbundle(ui, repo, fname1, *fnames, **opts):
6824 def unbundle(ui, repo, fname1, *fnames, **opts):
6829 """apply one or more changegroup files
6825 """apply one or more changegroup files
6830
6826
6831 Apply one or more compressed changegroup files generated by the
6827 Apply one or more compressed changegroup files generated by the
6832 bundle command.
6828 bundle command.
6833
6829
6834 Returns 0 on success, 1 if an update has unresolved files.
6830 Returns 0 on success, 1 if an update has unresolved files.
6835 """
6831 """
6836 fnames = (fname1,) + fnames
6832 fnames = (fname1,) + fnames
6837
6833
6838 lock = repo.lock()
6834 lock = repo.lock()
6839 try:
6835 try:
6840 for fname in fnames:
6836 for fname in fnames:
6841 f = hg.openpath(ui, fname)
6837 f = hg.openpath(ui, fname)
6842 gen = exchange.readbundle(ui, f, fname)
6838 gen = exchange.readbundle(ui, f, fname)
6843 if isinstance(gen, bundle2.unbundle20):
6839 if isinstance(gen, bundle2.unbundle20):
6844 tr = repo.transaction('unbundle')
6840 tr = repo.transaction('unbundle')
6845 try:
6841 try:
6846 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6842 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6847 url='bundle:' + fname)
6843 url='bundle:' + fname)
6848 tr.close()
6844 tr.close()
6849 except error.BundleUnknownFeatureError as exc:
6845 except error.BundleUnknownFeatureError as exc:
6850 raise error.Abort(_('%s: unknown bundle feature, %s')
6846 raise error.Abort(_('%s: unknown bundle feature, %s')
6851 % (fname, exc),
6847 % (fname, exc),
6852 hint=_("see https://mercurial-scm.org/"
6848 hint=_("see https://mercurial-scm.org/"
6853 "wiki/BundleFeature for more "
6849 "wiki/BundleFeature for more "
6854 "information"))
6850 "information"))
6855 finally:
6851 finally:
6856 if tr:
6852 if tr:
6857 tr.release()
6853 tr.release()
6858 changes = [r.get('return', 0)
6854 changes = [r.get('return', 0)
6859 for r in op.records['changegroup']]
6855 for r in op.records['changegroup']]
6860 modheads = changegroup.combineresults(changes)
6856 modheads = changegroup.combineresults(changes)
6861 elif isinstance(gen, streamclone.streamcloneapplier):
6857 elif isinstance(gen, streamclone.streamcloneapplier):
6862 raise error.Abort(
6858 raise error.Abort(
6863 _('packed bundles cannot be applied with '
6859 _('packed bundles cannot be applied with '
6864 '"hg unbundle"'),
6860 '"hg unbundle"'),
6865 hint=_('use "hg debugapplystreamclonebundle"'))
6861 hint=_('use "hg debugapplystreamclonebundle"'))
6866 else:
6862 else:
6867 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6863 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6868 finally:
6864 finally:
6869 lock.release()
6865 lock.release()
6870
6866
6871 return postincoming(ui, repo, modheads, opts.get('update'), None)
6867 return postincoming(ui, repo, modheads, opts.get('update'), None)
6872
6868
6873 @command('^update|up|checkout|co',
6869 @command('^update|up|checkout|co',
6874 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6870 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6875 ('c', 'check', None,
6871 ('c', 'check', None,
6876 _('update across branches if no uncommitted changes')),
6872 _('update across branches if no uncommitted changes')),
6877 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6873 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6878 ('r', 'rev', '', _('revision'), _('REV'))
6874 ('r', 'rev', '', _('revision'), _('REV'))
6879 ] + mergetoolopts,
6875 ] + mergetoolopts,
6880 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6876 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6881 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6877 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6882 tool=None):
6878 tool=None):
6883 """update working directory (or switch revisions)
6879 """update working directory (or switch revisions)
6884
6880
6885 Update the repository's working directory to the specified
6881 Update the repository's working directory to the specified
6886 changeset. If no changeset is specified, update to the tip of the
6882 changeset. If no changeset is specified, update to the tip of the
6887 current named branch and move the active bookmark (see :hg:`help
6883 current named branch and move the active bookmark (see :hg:`help
6888 bookmarks`).
6884 bookmarks`).
6889
6885
6890 Update sets the working directory's parent revision to the specified
6886 Update sets the working directory's parent revision to the specified
6891 changeset (see :hg:`help parents`).
6887 changeset (see :hg:`help parents`).
6892
6888
6893 If the changeset is not a descendant or ancestor of the working
6889 If the changeset is not a descendant or ancestor of the working
6894 directory's parent, the update is aborted. With the -c/--check
6890 directory's parent, the update is aborted. With the -c/--check
6895 option, the working directory is checked for uncommitted changes; if
6891 option, the working directory is checked for uncommitted changes; if
6896 none are found, the working directory is updated to the specified
6892 none are found, the working directory is updated to the specified
6897 changeset.
6893 changeset.
6898
6894
6899 .. container:: verbose
6895 .. container:: verbose
6900
6896
6901 The following rules apply when the working directory contains
6897 The following rules apply when the working directory contains
6902 uncommitted changes:
6898 uncommitted changes:
6903
6899
6904 1. If neither -c/--check nor -C/--clean is specified, and if
6900 1. If neither -c/--check nor -C/--clean is specified, and if
6905 the requested changeset is an ancestor or descendant of
6901 the requested changeset is an ancestor or descendant of
6906 the working directory's parent, the uncommitted changes
6902 the working directory's parent, the uncommitted changes
6907 are merged into the requested changeset and the merged
6903 are merged into the requested changeset and the merged
6908 result is left uncommitted. If the requested changeset is
6904 result is left uncommitted. If the requested changeset is
6909 not an ancestor or descendant (that is, it is on another
6905 not an ancestor or descendant (that is, it is on another
6910 branch), the update is aborted and the uncommitted changes
6906 branch), the update is aborted and the uncommitted changes
6911 are preserved.
6907 are preserved.
6912
6908
6913 2. With the -c/--check option, the update is aborted and the
6909 2. With the -c/--check option, the update is aborted and the
6914 uncommitted changes are preserved.
6910 uncommitted changes are preserved.
6915
6911
6916 3. With the -C/--clean option, uncommitted changes are discarded and
6912 3. With the -C/--clean option, uncommitted changes are discarded and
6917 the working directory is updated to the requested changeset.
6913 the working directory is updated to the requested changeset.
6918
6914
6919 To cancel an uncommitted merge (and lose your changes), use
6915 To cancel an uncommitted merge (and lose your changes), use
6920 :hg:`update --clean .`.
6916 :hg:`update --clean .`.
6921
6917
6922 Use null as the changeset to remove the working directory (like
6918 Use null as the changeset to remove the working directory (like
6923 :hg:`clone -U`).
6919 :hg:`clone -U`).
6924
6920
6925 If you want to revert just one file to an older revision, use
6921 If you want to revert just one file to an older revision, use
6926 :hg:`revert [-r REV] NAME`.
6922 :hg:`revert [-r REV] NAME`.
6927
6923
6928 See :hg:`help dates` for a list of formats valid for -d/--date.
6924 See :hg:`help dates` for a list of formats valid for -d/--date.
6929
6925
6930 Returns 0 on success, 1 if there are unresolved files.
6926 Returns 0 on success, 1 if there are unresolved files.
6931 """
6927 """
6932 movemarkfrom = None
6928 movemarkfrom = None
6933 if rev and node:
6929 if rev and node:
6934 raise error.Abort(_("please specify just one revision"))
6930 raise error.Abort(_("please specify just one revision"))
6935
6931
6936 if rev is None or rev == '':
6932 if rev is None or rev == '':
6937 rev = node
6933 rev = node
6938
6934
6939 wlock = repo.wlock()
6935 wlock = repo.wlock()
6940 try:
6936 try:
6941 cmdutil.clearunfinished(repo)
6937 cmdutil.clearunfinished(repo)
6942
6938
6943 if date:
6939 if date:
6944 if rev is not None:
6940 if rev is not None:
6945 raise error.Abort(_("you can't specify a revision and a date"))
6941 raise error.Abort(_("you can't specify a revision and a date"))
6946 rev = cmdutil.finddate(ui, repo, date)
6942 rev = cmdutil.finddate(ui, repo, date)
6947
6943
6948 # if we defined a bookmark, we have to remember the original name
6944 # if we defined a bookmark, we have to remember the original name
6949 brev = rev
6945 brev = rev
6950 rev = scmutil.revsingle(repo, rev, rev).rev()
6946 rev = scmutil.revsingle(repo, rev, rev).rev()
6951
6947
6952 if check and clean:
6948 if check and clean:
6953 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6949 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6954 )
6950 )
6955
6951
6956 if check:
6952 if check:
6957 cmdutil.bailifchanged(repo, merge=False)
6953 cmdutil.bailifchanged(repo, merge=False)
6958 if rev is None:
6954 if rev is None:
6959 updata = destutil.destupdate(repo, clean=clean, check=check)
6955 updata = destutil.destupdate(repo, clean=clean, check=check)
6960 rev, movemarkfrom, brev = updata
6956 rev, movemarkfrom, brev = updata
6961
6957
6962 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6958 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6963
6959
6964 if clean:
6960 if clean:
6965 ret = hg.clean(repo, rev)
6961 ret = hg.clean(repo, rev)
6966 else:
6962 else:
6967 ret = hg.update(repo, rev)
6963 ret = hg.update(repo, rev)
6968
6964
6969 if not ret and movemarkfrom:
6965 if not ret and movemarkfrom:
6970 if movemarkfrom == repo['.'].node():
6966 if movemarkfrom == repo['.'].node():
6971 pass # no-op update
6967 pass # no-op update
6972 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6968 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6973 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6969 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6974 else:
6970 else:
6975 # this can happen with a non-linear update
6971 # this can happen with a non-linear update
6976 ui.status(_("(leaving bookmark %s)\n") %
6972 ui.status(_("(leaving bookmark %s)\n") %
6977 repo._activebookmark)
6973 repo._activebookmark)
6978 bookmarks.deactivate(repo)
6974 bookmarks.deactivate(repo)
6979 elif brev in repo._bookmarks:
6975 elif brev in repo._bookmarks:
6980 bookmarks.activate(repo, brev)
6976 bookmarks.activate(repo, brev)
6981 ui.status(_("(activating bookmark %s)\n") % brev)
6977 ui.status(_("(activating bookmark %s)\n") % brev)
6982 elif brev:
6978 elif brev:
6983 if repo._activebookmark:
6979 if repo._activebookmark:
6984 ui.status(_("(leaving bookmark %s)\n") %
6980 ui.status(_("(leaving bookmark %s)\n") %
6985 repo._activebookmark)
6981 repo._activebookmark)
6986 bookmarks.deactivate(repo)
6982 bookmarks.deactivate(repo)
6987 finally:
6983 finally:
6988 wlock.release()
6984 wlock.release()
6989
6985
6990 return ret
6986 return ret
6991
6987
6992 @command('verify', [])
6988 @command('verify', [])
6993 def verify(ui, repo):
6989 def verify(ui, repo):
6994 """verify the integrity of the repository
6990 """verify the integrity of the repository
6995
6991
6996 Verify the integrity of the current repository.
6992 Verify the integrity of the current repository.
6997
6993
6998 This will perform an extensive check of the repository's
6994 This will perform an extensive check of the repository's
6999 integrity, validating the hashes and checksums of each entry in
6995 integrity, validating the hashes and checksums of each entry in
7000 the changelog, manifest, and tracked files, as well as the
6996 the changelog, manifest, and tracked files, as well as the
7001 integrity of their crosslinks and indices.
6997 integrity of their crosslinks and indices.
7002
6998
7003 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
6999 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7004 for more information about recovery from corruption of the
7000 for more information about recovery from corruption of the
7005 repository.
7001 repository.
7006
7002
7007 Returns 0 on success, 1 if errors are encountered.
7003 Returns 0 on success, 1 if errors are encountered.
7008 """
7004 """
7009 return hg.verify(repo)
7005 return hg.verify(repo)
7010
7006
7011 @command('version', [], norepo=True)
7007 @command('version', [], norepo=True)
7012 def version_(ui):
7008 def version_(ui):
7013 """output version and copyright information"""
7009 """output version and copyright information"""
7014 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7010 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7015 % util.version())
7011 % util.version())
7016 ui.status(_(
7012 ui.status(_(
7017 "(see https://mercurial-scm.org for more information)\n"
7013 "(see https://mercurial-scm.org for more information)\n"
7018 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7014 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7019 "This is free software; see the source for copying conditions. "
7015 "This is free software; see the source for copying conditions. "
7020 "There is NO\nwarranty; "
7016 "There is NO\nwarranty; "
7021 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7017 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7022 ))
7018 ))
7023
7019
7024 ui.note(_("\nEnabled extensions:\n\n"))
7020 ui.note(_("\nEnabled extensions:\n\n"))
7025 if ui.verbose:
7021 if ui.verbose:
7026 # format names and versions into columns
7022 # format names and versions into columns
7027 names = []
7023 names = []
7028 vers = []
7024 vers = []
7029 for name, module in extensions.extensions():
7025 for name, module in extensions.extensions():
7030 names.append(name)
7026 names.append(name)
7031 vers.append(extensions.moduleversion(module))
7027 vers.append(extensions.moduleversion(module))
7032 if names:
7028 if names:
7033 maxnamelen = max(len(n) for n in names)
7029 maxnamelen = max(len(n) for n in names)
7034 for i, name in enumerate(names):
7030 for i, name in enumerate(names):
7035 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7031 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now