##// END OF EJS Templates
with: use context manager for wlock in debugrebuilddirstate
Bryan O'Sullivan -
r27806:a5eae47a default
parent child Browse files
Show More
@@ -1,7041 +1,7038
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 wlock = repo.wlock()
3127 with repo.wlock():
3128 try:
3129 dirstate = repo.dirstate
3128 dirstate = repo.dirstate
3130 changedfiles = None
3129 changedfiles = None
3131 # See command doc for what minimal does.
3130 # See command doc for what minimal does.
3132 if opts.get('minimal'):
3131 if opts.get('minimal'):
3133 manifestfiles = set(ctx.manifest().keys())
3132 manifestfiles = set(ctx.manifest().keys())
3134 dirstatefiles = set(dirstate)
3133 dirstatefiles = set(dirstate)
3135 manifestonly = manifestfiles - dirstatefiles
3134 manifestonly = manifestfiles - dirstatefiles
3136 dsonly = dirstatefiles - manifestfiles
3135 dsonly = dirstatefiles - manifestfiles
3137 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3136 dsnotadded = set(f for f in dsonly if dirstate[f] != 'a')
3138 changedfiles = manifestonly | dsnotadded
3137 changedfiles = manifestonly | dsnotadded
3139
3138
3140 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3139 dirstate.rebuild(ctx.node(), ctx.manifest(), changedfiles)
3141 finally:
3142 wlock.release()
3143
3140
3144 @command('debugrebuildfncache', [], '')
3141 @command('debugrebuildfncache', [], '')
3145 def debugrebuildfncache(ui, repo):
3142 def debugrebuildfncache(ui, repo):
3146 """rebuild the fncache file"""
3143 """rebuild the fncache file"""
3147 repair.rebuildfncache(ui, repo)
3144 repair.rebuildfncache(ui, repo)
3148
3145
3149 @command('debugrename',
3146 @command('debugrename',
3150 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3147 [('r', 'rev', '', _('revision to debug'), _('REV'))],
3151 _('[-r REV] FILE'))
3148 _('[-r REV] FILE'))
3152 def debugrename(ui, repo, file1, *pats, **opts):
3149 def debugrename(ui, repo, file1, *pats, **opts):
3153 """dump rename information"""
3150 """dump rename information"""
3154
3151
3155 ctx = scmutil.revsingle(repo, opts.get('rev'))
3152 ctx = scmutil.revsingle(repo, opts.get('rev'))
3156 m = scmutil.match(ctx, (file1,) + pats, opts)
3153 m = scmutil.match(ctx, (file1,) + pats, opts)
3157 for abs in ctx.walk(m):
3154 for abs in ctx.walk(m):
3158 fctx = ctx[abs]
3155 fctx = ctx[abs]
3159 o = fctx.filelog().renamed(fctx.filenode())
3156 o = fctx.filelog().renamed(fctx.filenode())
3160 rel = m.rel(abs)
3157 rel = m.rel(abs)
3161 if o:
3158 if o:
3162 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])))
3163 else:
3160 else:
3164 ui.write(_("%s not renamed\n") % rel)
3161 ui.write(_("%s not renamed\n") % rel)
3165
3162
3166 @command('debugrevlog', debugrevlogopts +
3163 @command('debugrevlog', debugrevlogopts +
3167 [('d', 'dump', False, _('dump index data'))],
3164 [('d', 'dump', False, _('dump index data'))],
3168 _('-c|-m|FILE'),
3165 _('-c|-m|FILE'),
3169 optionalrepo=True)
3166 optionalrepo=True)
3170 def debugrevlog(ui, repo, file_=None, **opts):
3167 def debugrevlog(ui, repo, file_=None, **opts):
3171 """show data and statistics about a revlog"""
3168 """show data and statistics about a revlog"""
3172 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3169 r = cmdutil.openrevlog(repo, 'debugrevlog', file_, opts)
3173
3170
3174 if opts.get("dump"):
3171 if opts.get("dump"):
3175 numrevs = len(r)
3172 numrevs = len(r)
3176 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3173 ui.write("# rev p1rev p2rev start end deltastart base p1 p2"
3177 " rawsize totalsize compression heads chainlen\n")
3174 " rawsize totalsize compression heads chainlen\n")
3178 ts = 0
3175 ts = 0
3179 heads = set()
3176 heads = set()
3180
3177
3181 for rev in xrange(numrevs):
3178 for rev in xrange(numrevs):
3182 dbase = r.deltaparent(rev)
3179 dbase = r.deltaparent(rev)
3183 if dbase == -1:
3180 if dbase == -1:
3184 dbase = rev
3181 dbase = rev
3185 cbase = r.chainbase(rev)
3182 cbase = r.chainbase(rev)
3186 clen = r.chainlen(rev)
3183 clen = r.chainlen(rev)
3187 p1, p2 = r.parentrevs(rev)
3184 p1, p2 = r.parentrevs(rev)
3188 rs = r.rawsize(rev)
3185 rs = r.rawsize(rev)
3189 ts = ts + rs
3186 ts = ts + rs
3190 heads -= set(r.parentrevs(rev))
3187 heads -= set(r.parentrevs(rev))
3191 heads.add(rev)
3188 heads.add(rev)
3192 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 "
3193 "%11d %5d %8d\n" %
3190 "%11d %5d %8d\n" %
3194 (rev, p1, p2, r.start(rev), r.end(rev),
3191 (rev, p1, p2, r.start(rev), r.end(rev),
3195 r.start(dbase), r.start(cbase),
3192 r.start(dbase), r.start(cbase),
3196 r.start(p1), r.start(p2),
3193 r.start(p1), r.start(p2),
3197 rs, ts, ts / r.end(rev), len(heads), clen))
3194 rs, ts, ts / r.end(rev), len(heads), clen))
3198 return 0
3195 return 0
3199
3196
3200 v = r.version
3197 v = r.version
3201 format = v & 0xFFFF
3198 format = v & 0xFFFF
3202 flags = []
3199 flags = []
3203 gdelta = False
3200 gdelta = False
3204 if v & revlog.REVLOGNGINLINEDATA:
3201 if v & revlog.REVLOGNGINLINEDATA:
3205 flags.append('inline')
3202 flags.append('inline')
3206 if v & revlog.REVLOGGENERALDELTA:
3203 if v & revlog.REVLOGGENERALDELTA:
3207 gdelta = True
3204 gdelta = True
3208 flags.append('generaldelta')
3205 flags.append('generaldelta')
3209 if not flags:
3206 if not flags:
3210 flags = ['(none)']
3207 flags = ['(none)']
3211
3208
3212 nummerges = 0
3209 nummerges = 0
3213 numfull = 0
3210 numfull = 0
3214 numprev = 0
3211 numprev = 0
3215 nump1 = 0
3212 nump1 = 0
3216 nump2 = 0
3213 nump2 = 0
3217 numother = 0
3214 numother = 0
3218 nump1prev = 0
3215 nump1prev = 0
3219 nump2prev = 0
3216 nump2prev = 0
3220 chainlengths = []
3217 chainlengths = []
3221
3218
3222 datasize = [None, 0, 0L]
3219 datasize = [None, 0, 0L]
3223 fullsize = [None, 0, 0L]
3220 fullsize = [None, 0, 0L]
3224 deltasize = [None, 0, 0L]
3221 deltasize = [None, 0, 0L]
3225
3222
3226 def addsize(size, l):
3223 def addsize(size, l):
3227 if l[0] is None or size < l[0]:
3224 if l[0] is None or size < l[0]:
3228 l[0] = size
3225 l[0] = size
3229 if size > l[1]:
3226 if size > l[1]:
3230 l[1] = size
3227 l[1] = size
3231 l[2] += size
3228 l[2] += size
3232
3229
3233 numrevs = len(r)
3230 numrevs = len(r)
3234 for rev in xrange(numrevs):
3231 for rev in xrange(numrevs):
3235 p1, p2 = r.parentrevs(rev)
3232 p1, p2 = r.parentrevs(rev)
3236 delta = r.deltaparent(rev)
3233 delta = r.deltaparent(rev)
3237 if format > 0:
3234 if format > 0:
3238 addsize(r.rawsize(rev), datasize)
3235 addsize(r.rawsize(rev), datasize)
3239 if p2 != nullrev:
3236 if p2 != nullrev:
3240 nummerges += 1
3237 nummerges += 1
3241 size = r.length(rev)
3238 size = r.length(rev)
3242 if delta == nullrev:
3239 if delta == nullrev:
3243 chainlengths.append(0)
3240 chainlengths.append(0)
3244 numfull += 1
3241 numfull += 1
3245 addsize(size, fullsize)
3242 addsize(size, fullsize)
3246 else:
3243 else:
3247 chainlengths.append(chainlengths[delta] + 1)
3244 chainlengths.append(chainlengths[delta] + 1)
3248 addsize(size, deltasize)
3245 addsize(size, deltasize)
3249 if delta == rev - 1:
3246 if delta == rev - 1:
3250 numprev += 1
3247 numprev += 1
3251 if delta == p1:
3248 if delta == p1:
3252 nump1prev += 1
3249 nump1prev += 1
3253 elif delta == p2:
3250 elif delta == p2:
3254 nump2prev += 1
3251 nump2prev += 1
3255 elif delta == p1:
3252 elif delta == p1:
3256 nump1 += 1
3253 nump1 += 1
3257 elif delta == p2:
3254 elif delta == p2:
3258 nump2 += 1
3255 nump2 += 1
3259 elif delta != nullrev:
3256 elif delta != nullrev:
3260 numother += 1
3257 numother += 1
3261
3258
3262 # Adjust size min value for empty cases
3259 # Adjust size min value for empty cases
3263 for size in (datasize, fullsize, deltasize):
3260 for size in (datasize, fullsize, deltasize):
3264 if size[0] is None:
3261 if size[0] is None:
3265 size[0] = 0
3262 size[0] = 0
3266
3263
3267 numdeltas = numrevs - numfull
3264 numdeltas = numrevs - numfull
3268 numoprev = numprev - nump1prev - nump2prev
3265 numoprev = numprev - nump1prev - nump2prev
3269 totalrawsize = datasize[2]
3266 totalrawsize = datasize[2]
3270 datasize[2] /= numrevs
3267 datasize[2] /= numrevs
3271 fulltotal = fullsize[2]
3268 fulltotal = fullsize[2]
3272 fullsize[2] /= numfull
3269 fullsize[2] /= numfull
3273 deltatotal = deltasize[2]
3270 deltatotal = deltasize[2]
3274 if numrevs - numfull > 0:
3271 if numrevs - numfull > 0:
3275 deltasize[2] /= numrevs - numfull
3272 deltasize[2] /= numrevs - numfull
3276 totalsize = fulltotal + deltatotal
3273 totalsize = fulltotal + deltatotal
3277 avgchainlen = sum(chainlengths) / numrevs
3274 avgchainlen = sum(chainlengths) / numrevs
3278 maxchainlen = max(chainlengths)
3275 maxchainlen = max(chainlengths)
3279 compratio = 1
3276 compratio = 1
3280 if totalsize:
3277 if totalsize:
3281 compratio = totalrawsize / totalsize
3278 compratio = totalrawsize / totalsize
3282
3279
3283 basedfmtstr = '%%%dd\n'
3280 basedfmtstr = '%%%dd\n'
3284 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3281 basepcfmtstr = '%%%dd %s(%%5.2f%%%%)\n'
3285
3282
3286 def dfmtstr(max):
3283 def dfmtstr(max):
3287 return basedfmtstr % len(str(max))
3284 return basedfmtstr % len(str(max))
3288 def pcfmtstr(max, padding=0):
3285 def pcfmtstr(max, padding=0):
3289 return basepcfmtstr % (len(str(max)), ' ' * padding)
3286 return basepcfmtstr % (len(str(max)), ' ' * padding)
3290
3287
3291 def pcfmt(value, total):
3288 def pcfmt(value, total):
3292 if total:
3289 if total:
3293 return (value, 100 * float(value) / total)
3290 return (value, 100 * float(value) / total)
3294 else:
3291 else:
3295 return value, 100.0
3292 return value, 100.0
3296
3293
3297 ui.write(('format : %d\n') % format)
3294 ui.write(('format : %d\n') % format)
3298 ui.write(('flags : %s\n') % ', '.join(flags))
3295 ui.write(('flags : %s\n') % ', '.join(flags))
3299
3296
3300 ui.write('\n')
3297 ui.write('\n')
3301 fmt = pcfmtstr(totalsize)
3298 fmt = pcfmtstr(totalsize)
3302 fmt2 = dfmtstr(totalsize)
3299 fmt2 = dfmtstr(totalsize)
3303 ui.write(('revisions : ') + fmt2 % numrevs)
3300 ui.write(('revisions : ') + fmt2 % numrevs)
3304 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3301 ui.write((' merges : ') + fmt % pcfmt(nummerges, numrevs))
3305 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3302 ui.write((' normal : ') + fmt % pcfmt(numrevs - nummerges, numrevs))
3306 ui.write(('revisions : ') + fmt2 % numrevs)
3303 ui.write(('revisions : ') + fmt2 % numrevs)
3307 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3304 ui.write((' full : ') + fmt % pcfmt(numfull, numrevs))
3308 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3305 ui.write((' deltas : ') + fmt % pcfmt(numdeltas, numrevs))
3309 ui.write(('revision size : ') + fmt2 % totalsize)
3306 ui.write(('revision size : ') + fmt2 % totalsize)
3310 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3307 ui.write((' full : ') + fmt % pcfmt(fulltotal, totalsize))
3311 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3308 ui.write((' deltas : ') + fmt % pcfmt(deltatotal, totalsize))
3312
3309
3313 ui.write('\n')
3310 ui.write('\n')
3314 fmt = dfmtstr(max(avgchainlen, compratio))
3311 fmt = dfmtstr(max(avgchainlen, compratio))
3315 ui.write(('avg chain length : ') + fmt % avgchainlen)
3312 ui.write(('avg chain length : ') + fmt % avgchainlen)
3316 ui.write(('max chain length : ') + fmt % maxchainlen)
3313 ui.write(('max chain length : ') + fmt % maxchainlen)
3317 ui.write(('compression ratio : ') + fmt % compratio)
3314 ui.write(('compression ratio : ') + fmt % compratio)
3318
3315
3319 if format > 0:
3316 if format > 0:
3320 ui.write('\n')
3317 ui.write('\n')
3321 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')
3322 % tuple(datasize))
3319 % tuple(datasize))
3323 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')
3324 % tuple(fullsize))
3321 % tuple(fullsize))
3325 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3322 ui.write(('delta size (min/max/avg) : %d / %d / %d\n')
3326 % tuple(deltasize))
3323 % tuple(deltasize))
3327
3324
3328 if numdeltas > 0:
3325 if numdeltas > 0:
3329 ui.write('\n')
3326 ui.write('\n')
3330 fmt = pcfmtstr(numdeltas)
3327 fmt = pcfmtstr(numdeltas)
3331 fmt2 = pcfmtstr(numdeltas, 4)
3328 fmt2 = pcfmtstr(numdeltas, 4)
3332 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3329 ui.write(('deltas against prev : ') + fmt % pcfmt(numprev, numdeltas))
3333 if numprev > 0:
3330 if numprev > 0:
3334 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3331 ui.write((' where prev = p1 : ') + fmt2 % pcfmt(nump1prev,
3335 numprev))
3332 numprev))
3336 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3333 ui.write((' where prev = p2 : ') + fmt2 % pcfmt(nump2prev,
3337 numprev))
3334 numprev))
3338 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3335 ui.write((' other : ') + fmt2 % pcfmt(numoprev,
3339 numprev))
3336 numprev))
3340 if gdelta:
3337 if gdelta:
3341 ui.write(('deltas against p1 : ')
3338 ui.write(('deltas against p1 : ')
3342 + fmt % pcfmt(nump1, numdeltas))
3339 + fmt % pcfmt(nump1, numdeltas))
3343 ui.write(('deltas against p2 : ')
3340 ui.write(('deltas against p2 : ')
3344 + fmt % pcfmt(nump2, numdeltas))
3341 + fmt % pcfmt(nump2, numdeltas))
3345 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3342 ui.write(('deltas against other : ') + fmt % pcfmt(numother,
3346 numdeltas))
3343 numdeltas))
3347
3344
3348 @command('debugrevspec',
3345 @command('debugrevspec',
3349 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3346 [('', 'optimize', None, _('print parsed tree after optimizing'))],
3350 ('REVSPEC'))
3347 ('REVSPEC'))
3351 def debugrevspec(ui, repo, expr, **opts):
3348 def debugrevspec(ui, repo, expr, **opts):
3352 """parse and apply a revision specification
3349 """parse and apply a revision specification
3353
3350
3354 Use --verbose to print the parsed tree before and after aliases
3351 Use --verbose to print the parsed tree before and after aliases
3355 expansion.
3352 expansion.
3356 """
3353 """
3357 if ui.verbose:
3354 if ui.verbose:
3358 tree = revset.parse(expr, lookup=repo.__contains__)
3355 tree = revset.parse(expr, lookup=repo.__contains__)
3359 ui.note(revset.prettyformat(tree), "\n")
3356 ui.note(revset.prettyformat(tree), "\n")
3360 newtree = revset.findaliases(ui, tree)
3357 newtree = revset.findaliases(ui, tree)
3361 if newtree != tree:
3358 if newtree != tree:
3362 ui.note(revset.prettyformat(newtree), "\n")
3359 ui.note(revset.prettyformat(newtree), "\n")
3363 tree = newtree
3360 tree = newtree
3364 newtree = revset.foldconcat(tree)
3361 newtree = revset.foldconcat(tree)
3365 if newtree != tree:
3362 if newtree != tree:
3366 ui.note(revset.prettyformat(newtree), "\n")
3363 ui.note(revset.prettyformat(newtree), "\n")
3367 if opts["optimize"]:
3364 if opts["optimize"]:
3368 weight, optimizedtree = revset.optimize(newtree, True)
3365 weight, optimizedtree = revset.optimize(newtree, True)
3369 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3366 ui.note("* optimized:\n", revset.prettyformat(optimizedtree), "\n")
3370 func = revset.match(ui, expr, repo)
3367 func = revset.match(ui, expr, repo)
3371 revs = func(repo)
3368 revs = func(repo)
3372 if ui.verbose:
3369 if ui.verbose:
3373 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3370 ui.note("* set:\n", revset.prettyformatset(revs), "\n")
3374 for c in revs:
3371 for c in revs:
3375 ui.write("%s\n" % c)
3372 ui.write("%s\n" % c)
3376
3373
3377 @command('debugsetparents', [], _('REV1 [REV2]'))
3374 @command('debugsetparents', [], _('REV1 [REV2]'))
3378 def debugsetparents(ui, repo, rev1, rev2=None):
3375 def debugsetparents(ui, repo, rev1, rev2=None):
3379 """manually set the parents of the current working directory
3376 """manually set the parents of the current working directory
3380
3377
3381 This is useful for writing repository conversion tools, but should
3378 This is useful for writing repository conversion tools, but should
3382 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
3383 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
3384 command.
3381 command.
3385
3382
3386 Returns 0 on success.
3383 Returns 0 on success.
3387 """
3384 """
3388
3385
3389 r1 = scmutil.revsingle(repo, rev1).node()
3386 r1 = scmutil.revsingle(repo, rev1).node()
3390 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3387 r2 = scmutil.revsingle(repo, rev2, 'null').node()
3391
3388
3392 wlock = repo.wlock()
3389 wlock = repo.wlock()
3393 try:
3390 try:
3394 repo.dirstate.beginparentchange()
3391 repo.dirstate.beginparentchange()
3395 repo.setparents(r1, r2)
3392 repo.setparents(r1, r2)
3396 repo.dirstate.endparentchange()
3393 repo.dirstate.endparentchange()
3397 finally:
3394 finally:
3398 wlock.release()
3395 wlock.release()
3399
3396
3400 @command('debugdirstate|debugstate',
3397 @command('debugdirstate|debugstate',
3401 [('', 'nodates', None, _('do not display the saved mtime')),
3398 [('', 'nodates', None, _('do not display the saved mtime')),
3402 ('', 'datesort', None, _('sort by saved mtime'))],
3399 ('', 'datesort', None, _('sort by saved mtime'))],
3403 _('[OPTION]...'))
3400 _('[OPTION]...'))
3404 def debugstate(ui, repo, **opts):
3401 def debugstate(ui, repo, **opts):
3405 """show the contents of the current dirstate"""
3402 """show the contents of the current dirstate"""
3406
3403
3407 nodates = opts.get('nodates')
3404 nodates = opts.get('nodates')
3408 datesort = opts.get('datesort')
3405 datesort = opts.get('datesort')
3409
3406
3410 timestr = ""
3407 timestr = ""
3411 if datesort:
3408 if datesort:
3412 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3409 keyfunc = lambda x: (x[1][3], x[0]) # sort by mtime, then by filename
3413 else:
3410 else:
3414 keyfunc = None # sort by filename
3411 keyfunc = None # sort by filename
3415 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3412 for file_, ent in sorted(repo.dirstate._map.iteritems(), key=keyfunc):
3416 if ent[3] == -1:
3413 if ent[3] == -1:
3417 timestr = 'unset '
3414 timestr = 'unset '
3418 elif nodates:
3415 elif nodates:
3419 timestr = 'set '
3416 timestr = 'set '
3420 else:
3417 else:
3421 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3418 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
3422 time.localtime(ent[3]))
3419 time.localtime(ent[3]))
3423 if ent[1] & 0o20000:
3420 if ent[1] & 0o20000:
3424 mode = 'lnk'
3421 mode = 'lnk'
3425 else:
3422 else:
3426 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3423 mode = '%3o' % (ent[1] & 0o777 & ~util.umask)
3427 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3424 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
3428 for f in repo.dirstate.copies():
3425 for f in repo.dirstate.copies():
3429 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3426 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
3430
3427
3431 @command('debugsub',
3428 @command('debugsub',
3432 [('r', 'rev', '',
3429 [('r', 'rev', '',
3433 _('revision to check'), _('REV'))],
3430 _('revision to check'), _('REV'))],
3434 _('[-r REV] [REV]'))
3431 _('[-r REV] [REV]'))
3435 def debugsub(ui, repo, rev=None):
3432 def debugsub(ui, repo, rev=None):
3436 ctx = scmutil.revsingle(repo, rev, None)
3433 ctx = scmutil.revsingle(repo, rev, None)
3437 for k, v in sorted(ctx.substate.items()):
3434 for k, v in sorted(ctx.substate.items()):
3438 ui.write(('path %s\n') % k)
3435 ui.write(('path %s\n') % k)
3439 ui.write((' source %s\n') % v[0])
3436 ui.write((' source %s\n') % v[0])
3440 ui.write((' revision %s\n') % v[1])
3437 ui.write((' revision %s\n') % v[1])
3441
3438
3442 @command('debugsuccessorssets',
3439 @command('debugsuccessorssets',
3443 [],
3440 [],
3444 _('[REV]'))
3441 _('[REV]'))
3445 def debugsuccessorssets(ui, repo, *revs):
3442 def debugsuccessorssets(ui, repo, *revs):
3446 """show set of successors for revision
3443 """show set of successors for revision
3447
3444
3448 A successors set of changeset A is a consistent group of revisions that
3445 A successors set of changeset A is a consistent group of revisions that
3449 succeed A. It contains non-obsolete changesets only.
3446 succeed A. It contains non-obsolete changesets only.
3450
3447
3451 In most cases a changeset A has a single successors set containing a single
3448 In most cases a changeset A has a single successors set containing a single
3452 successor (changeset A replaced by A').
3449 successor (changeset A replaced by A').
3453
3450
3454 A changeset that is made obsolete with no successors are called "pruned".
3451 A changeset that is made obsolete with no successors are called "pruned".
3455 Such changesets have no successors sets at all.
3452 Such changesets have no successors sets at all.
3456
3453
3457 A changeset that has been "split" will have a successors set containing
3454 A changeset that has been "split" will have a successors set containing
3458 more than one successor.
3455 more than one successor.
3459
3456
3460 A changeset that has been rewritten in multiple different ways is called
3457 A changeset that has been rewritten in multiple different ways is called
3461 "divergent". Such changesets have multiple successor sets (each of which
3458 "divergent". Such changesets have multiple successor sets (each of which
3462 may also be split, i.e. have multiple successors).
3459 may also be split, i.e. have multiple successors).
3463
3460
3464 Results are displayed as follows::
3461 Results are displayed as follows::
3465
3462
3466 <rev1>
3463 <rev1>
3467 <successors-1A>
3464 <successors-1A>
3468 <rev2>
3465 <rev2>
3469 <successors-2A>
3466 <successors-2A>
3470 <successors-2B1> <successors-2B2> <successors-2B3>
3467 <successors-2B1> <successors-2B2> <successors-2B3>
3471
3468
3472 Here rev2 has two possible (i.e. divergent) successors sets. The first
3469 Here rev2 has two possible (i.e. divergent) successors sets. The first
3473 holds one element, whereas the second holds three (i.e. the changeset has
3470 holds one element, whereas the second holds three (i.e. the changeset has
3474 been split).
3471 been split).
3475 """
3472 """
3476 # passed to successorssets caching computation from one call to another
3473 # passed to successorssets caching computation from one call to another
3477 cache = {}
3474 cache = {}
3478 ctx2str = str
3475 ctx2str = str
3479 node2str = short
3476 node2str = short
3480 if ui.debug():
3477 if ui.debug():
3481 def ctx2str(ctx):
3478 def ctx2str(ctx):
3482 return ctx.hex()
3479 return ctx.hex()
3483 node2str = hex
3480 node2str = hex
3484 for rev in scmutil.revrange(repo, revs):
3481 for rev in scmutil.revrange(repo, revs):
3485 ctx = repo[rev]
3482 ctx = repo[rev]
3486 ui.write('%s\n'% ctx2str(ctx))
3483 ui.write('%s\n'% ctx2str(ctx))
3487 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3484 for succsset in obsolete.successorssets(repo, ctx.node(), cache):
3488 if succsset:
3485 if succsset:
3489 ui.write(' ')
3486 ui.write(' ')
3490 ui.write(node2str(succsset[0]))
3487 ui.write(node2str(succsset[0]))
3491 for node in succsset[1:]:
3488 for node in succsset[1:]:
3492 ui.write(' ')
3489 ui.write(' ')
3493 ui.write(node2str(node))
3490 ui.write(node2str(node))
3494 ui.write('\n')
3491 ui.write('\n')
3495
3492
3496 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3493 @command('debugwalk', walkopts, _('[OPTION]... [FILE]...'), inferrepo=True)
3497 def debugwalk(ui, repo, *pats, **opts):
3494 def debugwalk(ui, repo, *pats, **opts):
3498 """show how files match on given patterns"""
3495 """show how files match on given patterns"""
3499 m = scmutil.match(repo[None], pats, opts)
3496 m = scmutil.match(repo[None], pats, opts)
3500 items = list(repo.walk(m))
3497 items = list(repo.walk(m))
3501 if not items:
3498 if not items:
3502 return
3499 return
3503 f = lambda fn: fn
3500 f = lambda fn: fn
3504 if ui.configbool('ui', 'slash') and os.sep != '/':
3501 if ui.configbool('ui', 'slash') and os.sep != '/':
3505 f = lambda fn: util.normpath(fn)
3502 f = lambda fn: util.normpath(fn)
3506 fmt = 'f %%-%ds %%-%ds %%s' % (
3503 fmt = 'f %%-%ds %%-%ds %%s' % (
3507 max([len(abs) for abs in items]),
3504 max([len(abs) for abs in items]),
3508 max([len(m.rel(abs)) for abs in items]))
3505 max([len(m.rel(abs)) for abs in items]))
3509 for abs in items:
3506 for abs in items:
3510 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3507 line = fmt % (abs, f(m.rel(abs)), m.exact(abs) and 'exact' or '')
3511 ui.write("%s\n" % line.rstrip())
3508 ui.write("%s\n" % line.rstrip())
3512
3509
3513 @command('debugwireargs',
3510 @command('debugwireargs',
3514 [('', 'three', '', 'three'),
3511 [('', 'three', '', 'three'),
3515 ('', 'four', '', 'four'),
3512 ('', 'four', '', 'four'),
3516 ('', 'five', '', 'five'),
3513 ('', 'five', '', 'five'),
3517 ] + remoteopts,
3514 ] + remoteopts,
3518 _('REPO [OPTIONS]... [ONE [TWO]]'),
3515 _('REPO [OPTIONS]... [ONE [TWO]]'),
3519 norepo=True)
3516 norepo=True)
3520 def debugwireargs(ui, repopath, *vals, **opts):
3517 def debugwireargs(ui, repopath, *vals, **opts):
3521 repo = hg.peer(ui, opts, repopath)
3518 repo = hg.peer(ui, opts, repopath)
3522 for opt in remoteopts:
3519 for opt in remoteopts:
3523 del opts[opt[1]]
3520 del opts[opt[1]]
3524 args = {}
3521 args = {}
3525 for k, v in opts.iteritems():
3522 for k, v in opts.iteritems():
3526 if v:
3523 if v:
3527 args[k] = v
3524 args[k] = v
3528 # run twice to check that we don't mess up the stream for the next command
3525 # run twice to check that we don't mess up the stream for the next command
3529 res1 = repo.debugwireargs(*vals, **args)
3526 res1 = repo.debugwireargs(*vals, **args)
3530 res2 = repo.debugwireargs(*vals, **args)
3527 res2 = repo.debugwireargs(*vals, **args)
3531 ui.write("%s\n" % res1)
3528 ui.write("%s\n" % res1)
3532 if res1 != res2:
3529 if res1 != res2:
3533 ui.warn("%s\n" % res2)
3530 ui.warn("%s\n" % res2)
3534
3531
3535 @command('^diff',
3532 @command('^diff',
3536 [('r', 'rev', [], _('revision'), _('REV')),
3533 [('r', 'rev', [], _('revision'), _('REV')),
3537 ('c', 'change', '', _('change made by revision'), _('REV'))
3534 ('c', 'change', '', _('change made by revision'), _('REV'))
3538 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3535 ] + diffopts + diffopts2 + walkopts + subrepoopts,
3539 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3536 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...'),
3540 inferrepo=True)
3537 inferrepo=True)
3541 def diff(ui, repo, *pats, **opts):
3538 def diff(ui, repo, *pats, **opts):
3542 """diff repository (or selected files)
3539 """diff repository (or selected files)
3543
3540
3544 Show differences between revisions for the specified files.
3541 Show differences between revisions for the specified files.
3545
3542
3546 Differences between files are shown using the unified diff format.
3543 Differences between files are shown using the unified diff format.
3547
3544
3548 .. note::
3545 .. note::
3549
3546
3550 :hg:`diff` may generate unexpected results for merges, as it will
3547 :hg:`diff` may generate unexpected results for merges, as it will
3551 default to comparing against the working directory's first
3548 default to comparing against the working directory's first
3552 parent changeset if no revisions are specified.
3549 parent changeset if no revisions are specified.
3553
3550
3554 When two revision arguments are given, then changes are shown
3551 When two revision arguments are given, then changes are shown
3555 between those revisions. If only one revision is specified then
3552 between those revisions. If only one revision is specified then
3556 that revision is compared to the working directory, and, when no
3553 that revision is compared to the working directory, and, when no
3557 revisions are specified, the working directory files are compared
3554 revisions are specified, the working directory files are compared
3558 to its first parent.
3555 to its first parent.
3559
3556
3560 Alternatively you can specify -c/--change with a revision to see
3557 Alternatively you can specify -c/--change with a revision to see
3561 the changes in that changeset relative to its first parent.
3558 the changes in that changeset relative to its first parent.
3562
3559
3563 Without the -a/--text option, diff will avoid generating diffs of
3560 Without the -a/--text option, diff will avoid generating diffs of
3564 files it detects as binary. With -a, diff will generate a diff
3561 files it detects as binary. With -a, diff will generate a diff
3565 anyway, probably with undesirable results.
3562 anyway, probably with undesirable results.
3566
3563
3567 Use the -g/--git option to generate diffs in the git extended diff
3564 Use the -g/--git option to generate diffs in the git extended diff
3568 format. For more information, read :hg:`help diffs`.
3565 format. For more information, read :hg:`help diffs`.
3569
3566
3570 .. container:: verbose
3567 .. container:: verbose
3571
3568
3572 Examples:
3569 Examples:
3573
3570
3574 - compare a file in the current working directory to its parent::
3571 - compare a file in the current working directory to its parent::
3575
3572
3576 hg diff foo.c
3573 hg diff foo.c
3577
3574
3578 - compare two historical versions of a directory, with rename info::
3575 - compare two historical versions of a directory, with rename info::
3579
3576
3580 hg diff --git -r 1.0:1.2 lib/
3577 hg diff --git -r 1.0:1.2 lib/
3581
3578
3582 - get change stats relative to the last change on some date::
3579 - get change stats relative to the last change on some date::
3583
3580
3584 hg diff --stat -r "date('may 2')"
3581 hg diff --stat -r "date('may 2')"
3585
3582
3586 - diff all newly-added files that contain a keyword::
3583 - diff all newly-added files that contain a keyword::
3587
3584
3588 hg diff "set:added() and grep(GNU)"
3585 hg diff "set:added() and grep(GNU)"
3589
3586
3590 - compare a revision and its parents::
3587 - compare a revision and its parents::
3591
3588
3592 hg diff -c 9353 # compare against first parent
3589 hg diff -c 9353 # compare against first parent
3593 hg diff -r 9353^:9353 # same using revset syntax
3590 hg diff -r 9353^:9353 # same using revset syntax
3594 hg diff -r 9353^2:9353 # compare against the second parent
3591 hg diff -r 9353^2:9353 # compare against the second parent
3595
3592
3596 Returns 0 on success.
3593 Returns 0 on success.
3597 """
3594 """
3598
3595
3599 revs = opts.get('rev')
3596 revs = opts.get('rev')
3600 change = opts.get('change')
3597 change = opts.get('change')
3601 stat = opts.get('stat')
3598 stat = opts.get('stat')
3602 reverse = opts.get('reverse')
3599 reverse = opts.get('reverse')
3603
3600
3604 if revs and change:
3601 if revs and change:
3605 msg = _('cannot specify --rev and --change at the same time')
3602 msg = _('cannot specify --rev and --change at the same time')
3606 raise error.Abort(msg)
3603 raise error.Abort(msg)
3607 elif change:
3604 elif change:
3608 node2 = scmutil.revsingle(repo, change, None).node()
3605 node2 = scmutil.revsingle(repo, change, None).node()
3609 node1 = repo[node2].p1().node()
3606 node1 = repo[node2].p1().node()
3610 else:
3607 else:
3611 node1, node2 = scmutil.revpair(repo, revs)
3608 node1, node2 = scmutil.revpair(repo, revs)
3612
3609
3613 if reverse:
3610 if reverse:
3614 node1, node2 = node2, node1
3611 node1, node2 = node2, node1
3615
3612
3616 diffopts = patch.diffallopts(ui, opts)
3613 diffopts = patch.diffallopts(ui, opts)
3617 m = scmutil.match(repo[node2], pats, opts)
3614 m = scmutil.match(repo[node2], pats, opts)
3618 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3615 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
3619 listsubrepos=opts.get('subrepos'),
3616 listsubrepos=opts.get('subrepos'),
3620 root=opts.get('root'))
3617 root=opts.get('root'))
3621
3618
3622 @command('^export',
3619 @command('^export',
3623 [('o', 'output', '',
3620 [('o', 'output', '',
3624 _('print output to file with formatted name'), _('FORMAT')),
3621 _('print output to file with formatted name'), _('FORMAT')),
3625 ('', 'switch-parent', None, _('diff against the second parent')),
3622 ('', 'switch-parent', None, _('diff against the second parent')),
3626 ('r', 'rev', [], _('revisions to export'), _('REV')),
3623 ('r', 'rev', [], _('revisions to export'), _('REV')),
3627 ] + diffopts,
3624 ] + diffopts,
3628 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3625 _('[OPTION]... [-o OUTFILESPEC] [-r] [REV]...'))
3629 def export(ui, repo, *changesets, **opts):
3626 def export(ui, repo, *changesets, **opts):
3630 """dump the header and diffs for one or more changesets
3627 """dump the header and diffs for one or more changesets
3631
3628
3632 Print the changeset header and diffs for one or more revisions.
3629 Print the changeset header and diffs for one or more revisions.
3633 If no revision is given, the parent of the working directory is used.
3630 If no revision is given, the parent of the working directory is used.
3634
3631
3635 The information shown in the changeset header is: author, date,
3632 The information shown in the changeset header is: author, date,
3636 branch name (if non-default), changeset hash, parent(s) and commit
3633 branch name (if non-default), changeset hash, parent(s) and commit
3637 comment.
3634 comment.
3638
3635
3639 .. note::
3636 .. note::
3640
3637
3641 :hg:`export` may generate unexpected diff output for merge
3638 :hg:`export` may generate unexpected diff output for merge
3642 changesets, as it will compare the merge changeset against its
3639 changesets, as it will compare the merge changeset against its
3643 first parent only.
3640 first parent only.
3644
3641
3645 Output may be to a file, in which case the name of the file is
3642 Output may be to a file, in which case the name of the file is
3646 given using a format string. The formatting rules are as follows:
3643 given using a format string. The formatting rules are as follows:
3647
3644
3648 :``%%``: literal "%" character
3645 :``%%``: literal "%" character
3649 :``%H``: changeset hash (40 hexadecimal digits)
3646 :``%H``: changeset hash (40 hexadecimal digits)
3650 :``%N``: number of patches being generated
3647 :``%N``: number of patches being generated
3651 :``%R``: changeset revision number
3648 :``%R``: changeset revision number
3652 :``%b``: basename of the exporting repository
3649 :``%b``: basename of the exporting repository
3653 :``%h``: short-form changeset hash (12 hexadecimal digits)
3650 :``%h``: short-form changeset hash (12 hexadecimal digits)
3654 :``%m``: first line of the commit message (only alphanumeric characters)
3651 :``%m``: first line of the commit message (only alphanumeric characters)
3655 :``%n``: zero-padded sequence number, starting at 1
3652 :``%n``: zero-padded sequence number, starting at 1
3656 :``%r``: zero-padded changeset revision number
3653 :``%r``: zero-padded changeset revision number
3657
3654
3658 Without the -a/--text option, export will avoid generating diffs
3655 Without the -a/--text option, export will avoid generating diffs
3659 of files it detects as binary. With -a, export will generate a
3656 of files it detects as binary. With -a, export will generate a
3660 diff anyway, probably with undesirable results.
3657 diff anyway, probably with undesirable results.
3661
3658
3662 Use the -g/--git option to generate diffs in the git extended diff
3659 Use the -g/--git option to generate diffs in the git extended diff
3663 format. See :hg:`help diffs` for more information.
3660 format. See :hg:`help diffs` for more information.
3664
3661
3665 With the --switch-parent option, the diff will be against the
3662 With the --switch-parent option, the diff will be against the
3666 second parent. It can be useful to review a merge.
3663 second parent. It can be useful to review a merge.
3667
3664
3668 .. container:: verbose
3665 .. container:: verbose
3669
3666
3670 Examples:
3667 Examples:
3671
3668
3672 - use export and import to transplant a bugfix to the current
3669 - use export and import to transplant a bugfix to the current
3673 branch::
3670 branch::
3674
3671
3675 hg export -r 9353 | hg import -
3672 hg export -r 9353 | hg import -
3676
3673
3677 - export all the changesets between two revisions to a file with
3674 - export all the changesets between two revisions to a file with
3678 rename information::
3675 rename information::
3679
3676
3680 hg export --git -r 123:150 > changes.txt
3677 hg export --git -r 123:150 > changes.txt
3681
3678
3682 - split outgoing changes into a series of patches with
3679 - split outgoing changes into a series of patches with
3683 descriptive names::
3680 descriptive names::
3684
3681
3685 hg export -r "outgoing()" -o "%n-%m.patch"
3682 hg export -r "outgoing()" -o "%n-%m.patch"
3686
3683
3687 Returns 0 on success.
3684 Returns 0 on success.
3688 """
3685 """
3689 changesets += tuple(opts.get('rev', []))
3686 changesets += tuple(opts.get('rev', []))
3690 if not changesets:
3687 if not changesets:
3691 changesets = ['.']
3688 changesets = ['.']
3692 revs = scmutil.revrange(repo, changesets)
3689 revs = scmutil.revrange(repo, changesets)
3693 if not revs:
3690 if not revs:
3694 raise error.Abort(_("export requires at least one changeset"))
3691 raise error.Abort(_("export requires at least one changeset"))
3695 if len(revs) > 1:
3692 if len(revs) > 1:
3696 ui.note(_('exporting patches:\n'))
3693 ui.note(_('exporting patches:\n'))
3697 else:
3694 else:
3698 ui.note(_('exporting patch:\n'))
3695 ui.note(_('exporting patch:\n'))
3699 cmdutil.export(repo, revs, template=opts.get('output'),
3696 cmdutil.export(repo, revs, template=opts.get('output'),
3700 switch_parent=opts.get('switch_parent'),
3697 switch_parent=opts.get('switch_parent'),
3701 opts=patch.diffallopts(ui, opts))
3698 opts=patch.diffallopts(ui, opts))
3702
3699
3703 @command('files',
3700 @command('files',
3704 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3701 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
3705 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3702 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
3706 ] + walkopts + formatteropts + subrepoopts,
3703 ] + walkopts + formatteropts + subrepoopts,
3707 _('[OPTION]... [PATTERN]...'))
3704 _('[OPTION]... [PATTERN]...'))
3708 def files(ui, repo, *pats, **opts):
3705 def files(ui, repo, *pats, **opts):
3709 """list tracked files
3706 """list tracked files
3710
3707
3711 Print files under Mercurial control in the working directory or
3708 Print files under Mercurial control in the working directory or
3712 specified revision whose names match the given patterns (excluding
3709 specified revision whose names match the given patterns (excluding
3713 removed files).
3710 removed files).
3714
3711
3715 If no patterns are given to match, this command prints the names
3712 If no patterns are given to match, this command prints the names
3716 of all files under Mercurial control in the working directory.
3713 of all files under Mercurial control in the working directory.
3717
3714
3718 .. container:: verbose
3715 .. container:: verbose
3719
3716
3720 Examples:
3717 Examples:
3721
3718
3722 - list all files under the current directory::
3719 - list all files under the current directory::
3723
3720
3724 hg files .
3721 hg files .
3725
3722
3726 - shows sizes and flags for current revision::
3723 - shows sizes and flags for current revision::
3727
3724
3728 hg files -vr .
3725 hg files -vr .
3729
3726
3730 - list all files named README::
3727 - list all files named README::
3731
3728
3732 hg files -I "**/README"
3729 hg files -I "**/README"
3733
3730
3734 - list all binary files::
3731 - list all binary files::
3735
3732
3736 hg files "set:binary()"
3733 hg files "set:binary()"
3737
3734
3738 - find files containing a regular expression::
3735 - find files containing a regular expression::
3739
3736
3740 hg files "set:grep('bob')"
3737 hg files "set:grep('bob')"
3741
3738
3742 - search tracked file contents with xargs and grep::
3739 - search tracked file contents with xargs and grep::
3743
3740
3744 hg files -0 | xargs -0 grep foo
3741 hg files -0 | xargs -0 grep foo
3745
3742
3746 See :hg:`help patterns` and :hg:`help filesets` for more information
3743 See :hg:`help patterns` and :hg:`help filesets` for more information
3747 on specifying file patterns.
3744 on specifying file patterns.
3748
3745
3749 Returns 0 if a match is found, 1 otherwise.
3746 Returns 0 if a match is found, 1 otherwise.
3750
3747
3751 """
3748 """
3752 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3749 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
3753
3750
3754 end = '\n'
3751 end = '\n'
3755 if opts.get('print0'):
3752 if opts.get('print0'):
3756 end = '\0'
3753 end = '\0'
3757 fm = ui.formatter('files', opts)
3754 fm = ui.formatter('files', opts)
3758 fmt = '%s' + end
3755 fmt = '%s' + end
3759
3756
3760 m = scmutil.match(ctx, pats, opts)
3757 m = scmutil.match(ctx, pats, opts)
3761 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3758 ret = cmdutil.files(ui, ctx, m, fm, fmt, opts.get('subrepos'))
3762
3759
3763 fm.end()
3760 fm.end()
3764
3761
3765 return ret
3762 return ret
3766
3763
3767 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3764 @command('^forget', walkopts, _('[OPTION]... FILE...'), inferrepo=True)
3768 def forget(ui, repo, *pats, **opts):
3765 def forget(ui, repo, *pats, **opts):
3769 """forget the specified files on the next commit
3766 """forget the specified files on the next commit
3770
3767
3771 Mark the specified files so they will no longer be tracked
3768 Mark the specified files so they will no longer be tracked
3772 after the next commit.
3769 after the next commit.
3773
3770
3774 This only removes files from the current branch, not from the
3771 This only removes files from the current branch, not from the
3775 entire project history, and it does not delete them from the
3772 entire project history, and it does not delete them from the
3776 working directory.
3773 working directory.
3777
3774
3778 To delete the file from the working directory, see :hg:`remove`.
3775 To delete the file from the working directory, see :hg:`remove`.
3779
3776
3780 To undo a forget before the next commit, see :hg:`add`.
3777 To undo a forget before the next commit, see :hg:`add`.
3781
3778
3782 .. container:: verbose
3779 .. container:: verbose
3783
3780
3784 Examples:
3781 Examples:
3785
3782
3786 - forget newly-added binary files::
3783 - forget newly-added binary files::
3787
3784
3788 hg forget "set:added() and binary()"
3785 hg forget "set:added() and binary()"
3789
3786
3790 - forget files that would be excluded by .hgignore::
3787 - forget files that would be excluded by .hgignore::
3791
3788
3792 hg forget "set:hgignore()"
3789 hg forget "set:hgignore()"
3793
3790
3794 Returns 0 on success.
3791 Returns 0 on success.
3795 """
3792 """
3796
3793
3797 if not pats:
3794 if not pats:
3798 raise error.Abort(_('no files specified'))
3795 raise error.Abort(_('no files specified'))
3799
3796
3800 m = scmutil.match(repo[None], pats, opts)
3797 m = scmutil.match(repo[None], pats, opts)
3801 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3798 rejected = cmdutil.forget(ui, repo, m, prefix="", explicitonly=False)[0]
3802 return rejected and 1 or 0
3799 return rejected and 1 or 0
3803
3800
3804 @command(
3801 @command(
3805 'graft',
3802 'graft',
3806 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3803 [('r', 'rev', [], _('revisions to graft'), _('REV')),
3807 ('c', 'continue', False, _('resume interrupted graft')),
3804 ('c', 'continue', False, _('resume interrupted graft')),
3808 ('e', 'edit', False, _('invoke editor on commit messages')),
3805 ('e', 'edit', False, _('invoke editor on commit messages')),
3809 ('', 'log', None, _('append graft info to log message')),
3806 ('', 'log', None, _('append graft info to log message')),
3810 ('f', 'force', False, _('force graft')),
3807 ('f', 'force', False, _('force graft')),
3811 ('D', 'currentdate', False,
3808 ('D', 'currentdate', False,
3812 _('record the current date as commit date')),
3809 _('record the current date as commit date')),
3813 ('U', 'currentuser', False,
3810 ('U', 'currentuser', False,
3814 _('record the current user as committer'), _('DATE'))]
3811 _('record the current user as committer'), _('DATE'))]
3815 + commitopts2 + mergetoolopts + dryrunopts,
3812 + commitopts2 + mergetoolopts + dryrunopts,
3816 _('[OPTION]... [-r] REV...'))
3813 _('[OPTION]... [-r] REV...'))
3817 def graft(ui, repo, *revs, **opts):
3814 def graft(ui, repo, *revs, **opts):
3818 '''copy changes from other branches onto the current branch
3815 '''copy changes from other branches onto the current branch
3819
3816
3820 This command uses Mercurial's merge logic to copy individual
3817 This command uses Mercurial's merge logic to copy individual
3821 changes from other branches without merging branches in the
3818 changes from other branches without merging branches in the
3822 history graph. This is sometimes known as 'backporting' or
3819 history graph. This is sometimes known as 'backporting' or
3823 'cherry-picking'. By default, graft will copy user, date, and
3820 'cherry-picking'. By default, graft will copy user, date, and
3824 description from the source changesets.
3821 description from the source changesets.
3825
3822
3826 Changesets that are ancestors of the current revision, that have
3823 Changesets that are ancestors of the current revision, that have
3827 already been grafted, or that are merges will be skipped.
3824 already been grafted, or that are merges will be skipped.
3828
3825
3829 If --log is specified, log messages will have a comment appended
3826 If --log is specified, log messages will have a comment appended
3830 of the form::
3827 of the form::
3831
3828
3832 (grafted from CHANGESETHASH)
3829 (grafted from CHANGESETHASH)
3833
3830
3834 If --force is specified, revisions will be grafted even if they
3831 If --force is specified, revisions will be grafted even if they
3835 are already ancestors of or have been grafted to the destination.
3832 are already ancestors of or have been grafted to the destination.
3836 This is useful when the revisions have since been backed out.
3833 This is useful when the revisions have since been backed out.
3837
3834
3838 If a graft merge results in conflicts, the graft process is
3835 If a graft merge results in conflicts, the graft process is
3839 interrupted so that the current merge can be manually resolved.
3836 interrupted so that the current merge can be manually resolved.
3840 Once all conflicts are addressed, the graft process can be
3837 Once all conflicts are addressed, the graft process can be
3841 continued with the -c/--continue option.
3838 continued with the -c/--continue option.
3842
3839
3843 .. note::
3840 .. note::
3844
3841
3845 The -c/--continue option does not reapply earlier options, except
3842 The -c/--continue option does not reapply earlier options, except
3846 for --force.
3843 for --force.
3847
3844
3848 .. container:: verbose
3845 .. container:: verbose
3849
3846
3850 Examples:
3847 Examples:
3851
3848
3852 - copy a single change to the stable branch and edit its description::
3849 - copy a single change to the stable branch and edit its description::
3853
3850
3854 hg update stable
3851 hg update stable
3855 hg graft --edit 9393
3852 hg graft --edit 9393
3856
3853
3857 - graft a range of changesets with one exception, updating dates::
3854 - graft a range of changesets with one exception, updating dates::
3858
3855
3859 hg graft -D "2085::2093 and not 2091"
3856 hg graft -D "2085::2093 and not 2091"
3860
3857
3861 - continue a graft after resolving conflicts::
3858 - continue a graft after resolving conflicts::
3862
3859
3863 hg graft -c
3860 hg graft -c
3864
3861
3865 - show the source of a grafted changeset::
3862 - show the source of a grafted changeset::
3866
3863
3867 hg log --debug -r .
3864 hg log --debug -r .
3868
3865
3869 - show revisions sorted by date::
3866 - show revisions sorted by date::
3870
3867
3871 hg log -r 'sort(all(), date)'
3868 hg log -r 'sort(all(), date)'
3872
3869
3873 See :hg:`help revisions` and :hg:`help revsets` for more about
3870 See :hg:`help revisions` and :hg:`help revsets` for more about
3874 specifying revisions.
3871 specifying revisions.
3875
3872
3876 Returns 0 on successful completion.
3873 Returns 0 on successful completion.
3877 '''
3874 '''
3878 wlock = None
3875 wlock = None
3879 try:
3876 try:
3880 wlock = repo.wlock()
3877 wlock = repo.wlock()
3881 return _dograft(ui, repo, *revs, **opts)
3878 return _dograft(ui, repo, *revs, **opts)
3882 finally:
3879 finally:
3883 release(wlock)
3880 release(wlock)
3884
3881
3885 def _dograft(ui, repo, *revs, **opts):
3882 def _dograft(ui, repo, *revs, **opts):
3886 revs = list(revs)
3883 revs = list(revs)
3887 revs.extend(opts['rev'])
3884 revs.extend(opts['rev'])
3888
3885
3889 if not opts.get('user') and opts.get('currentuser'):
3886 if not opts.get('user') and opts.get('currentuser'):
3890 opts['user'] = ui.username()
3887 opts['user'] = ui.username()
3891 if not opts.get('date') and opts.get('currentdate'):
3888 if not opts.get('date') and opts.get('currentdate'):
3892 opts['date'] = "%d %d" % util.makedate()
3889 opts['date'] = "%d %d" % util.makedate()
3893
3890
3894 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3891 editor = cmdutil.getcommiteditor(editform='graft', **opts)
3895
3892
3896 cont = False
3893 cont = False
3897 if opts['continue']:
3894 if opts['continue']:
3898 cont = True
3895 cont = True
3899 if revs:
3896 if revs:
3900 raise error.Abort(_("can't specify --continue and revisions"))
3897 raise error.Abort(_("can't specify --continue and revisions"))
3901 # read in unfinished revisions
3898 # read in unfinished revisions
3902 try:
3899 try:
3903 nodes = repo.vfs.read('graftstate').splitlines()
3900 nodes = repo.vfs.read('graftstate').splitlines()
3904 revs = [repo[node].rev() for node in nodes]
3901 revs = [repo[node].rev() for node in nodes]
3905 except IOError as inst:
3902 except IOError as inst:
3906 if inst.errno != errno.ENOENT:
3903 if inst.errno != errno.ENOENT:
3907 raise
3904 raise
3908 raise error.Abort(_("no graft state found, can't continue"))
3905 raise error.Abort(_("no graft state found, can't continue"))
3909 else:
3906 else:
3910 cmdutil.checkunfinished(repo)
3907 cmdutil.checkunfinished(repo)
3911 cmdutil.bailifchanged(repo)
3908 cmdutil.bailifchanged(repo)
3912 if not revs:
3909 if not revs:
3913 raise error.Abort(_('no revisions specified'))
3910 raise error.Abort(_('no revisions specified'))
3914 revs = scmutil.revrange(repo, revs)
3911 revs = scmutil.revrange(repo, revs)
3915
3912
3916 skipped = set()
3913 skipped = set()
3917 # check for merges
3914 # check for merges
3918 for rev in repo.revs('%ld and merge()', revs):
3915 for rev in repo.revs('%ld and merge()', revs):
3919 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3916 ui.warn(_('skipping ungraftable merge revision %s\n') % rev)
3920 skipped.add(rev)
3917 skipped.add(rev)
3921 revs = [r for r in revs if r not in skipped]
3918 revs = [r for r in revs if r not in skipped]
3922 if not revs:
3919 if not revs:
3923 return -1
3920 return -1
3924
3921
3925 # Don't check in the --continue case, in effect retaining --force across
3922 # Don't check in the --continue case, in effect retaining --force across
3926 # --continues. That's because without --force, any revisions we decided to
3923 # --continues. That's because without --force, any revisions we decided to
3927 # skip would have been filtered out here, so they wouldn't have made their
3924 # skip would have been filtered out here, so they wouldn't have made their
3928 # way to the graftstate. With --force, any revisions we would have otherwise
3925 # way to the graftstate. With --force, any revisions we would have otherwise
3929 # skipped would not have been filtered out, and if they hadn't been applied
3926 # skipped would not have been filtered out, and if they hadn't been applied
3930 # already, they'd have been in the graftstate.
3927 # already, they'd have been in the graftstate.
3931 if not (cont or opts.get('force')):
3928 if not (cont or opts.get('force')):
3932 # check for ancestors of dest branch
3929 # check for ancestors of dest branch
3933 crev = repo['.'].rev()
3930 crev = repo['.'].rev()
3934 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3931 ancestors = repo.changelog.ancestors([crev], inclusive=True)
3935 # Cannot use x.remove(y) on smart set, this has to be a list.
3932 # Cannot use x.remove(y) on smart set, this has to be a list.
3936 # XXX make this lazy in the future
3933 # XXX make this lazy in the future
3937 revs = list(revs)
3934 revs = list(revs)
3938 # don't mutate while iterating, create a copy
3935 # don't mutate while iterating, create a copy
3939 for rev in list(revs):
3936 for rev in list(revs):
3940 if rev in ancestors:
3937 if rev in ancestors:
3941 ui.warn(_('skipping ancestor revision %d:%s\n') %
3938 ui.warn(_('skipping ancestor revision %d:%s\n') %
3942 (rev, repo[rev]))
3939 (rev, repo[rev]))
3943 # XXX remove on list is slow
3940 # XXX remove on list is slow
3944 revs.remove(rev)
3941 revs.remove(rev)
3945 if not revs:
3942 if not revs:
3946 return -1
3943 return -1
3947
3944
3948 # analyze revs for earlier grafts
3945 # analyze revs for earlier grafts
3949 ids = {}
3946 ids = {}
3950 for ctx in repo.set("%ld", revs):
3947 for ctx in repo.set("%ld", revs):
3951 ids[ctx.hex()] = ctx.rev()
3948 ids[ctx.hex()] = ctx.rev()
3952 n = ctx.extra().get('source')
3949 n = ctx.extra().get('source')
3953 if n:
3950 if n:
3954 ids[n] = ctx.rev()
3951 ids[n] = ctx.rev()
3955
3952
3956 # check ancestors for earlier grafts
3953 # check ancestors for earlier grafts
3957 ui.debug('scanning for duplicate grafts\n')
3954 ui.debug('scanning for duplicate grafts\n')
3958
3955
3959 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3956 for rev in repo.changelog.findmissingrevs(revs, [crev]):
3960 ctx = repo[rev]
3957 ctx = repo[rev]
3961 n = ctx.extra().get('source')
3958 n = ctx.extra().get('source')
3962 if n in ids:
3959 if n in ids:
3963 try:
3960 try:
3964 r = repo[n].rev()
3961 r = repo[n].rev()
3965 except error.RepoLookupError:
3962 except error.RepoLookupError:
3966 r = None
3963 r = None
3967 if r in revs:
3964 if r in revs:
3968 ui.warn(_('skipping revision %d:%s '
3965 ui.warn(_('skipping revision %d:%s '
3969 '(already grafted to %d:%s)\n')
3966 '(already grafted to %d:%s)\n')
3970 % (r, repo[r], rev, ctx))
3967 % (r, repo[r], rev, ctx))
3971 revs.remove(r)
3968 revs.remove(r)
3972 elif ids[n] in revs:
3969 elif ids[n] in revs:
3973 if r is None:
3970 if r is None:
3974 ui.warn(_('skipping already grafted revision %d:%s '
3971 ui.warn(_('skipping already grafted revision %d:%s '
3975 '(%d:%s also has unknown origin %s)\n')
3972 '(%d:%s also has unknown origin %s)\n')
3976 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3973 % (ids[n], repo[ids[n]], rev, ctx, n[:12]))
3977 else:
3974 else:
3978 ui.warn(_('skipping already grafted revision %d:%s '
3975 ui.warn(_('skipping already grafted revision %d:%s '
3979 '(%d:%s also has origin %d:%s)\n')
3976 '(%d:%s also has origin %d:%s)\n')
3980 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3977 % (ids[n], repo[ids[n]], rev, ctx, r, n[:12]))
3981 revs.remove(ids[n])
3978 revs.remove(ids[n])
3982 elif ctx.hex() in ids:
3979 elif ctx.hex() in ids:
3983 r = ids[ctx.hex()]
3980 r = ids[ctx.hex()]
3984 ui.warn(_('skipping already grafted revision %d:%s '
3981 ui.warn(_('skipping already grafted revision %d:%s '
3985 '(was grafted from %d:%s)\n') %
3982 '(was grafted from %d:%s)\n') %
3986 (r, repo[r], rev, ctx))
3983 (r, repo[r], rev, ctx))
3987 revs.remove(r)
3984 revs.remove(r)
3988 if not revs:
3985 if not revs:
3989 return -1
3986 return -1
3990
3987
3991 for pos, ctx in enumerate(repo.set("%ld", revs)):
3988 for pos, ctx in enumerate(repo.set("%ld", revs)):
3992 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3989 desc = '%d:%s "%s"' % (ctx.rev(), ctx,
3993 ctx.description().split('\n', 1)[0])
3990 ctx.description().split('\n', 1)[0])
3994 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3991 names = repo.nodetags(ctx.node()) + repo.nodebookmarks(ctx.node())
3995 if names:
3992 if names:
3996 desc += ' (%s)' % ' '.join(names)
3993 desc += ' (%s)' % ' '.join(names)
3997 ui.status(_('grafting %s\n') % desc)
3994 ui.status(_('grafting %s\n') % desc)
3998 if opts.get('dry_run'):
3995 if opts.get('dry_run'):
3999 continue
3996 continue
4000
3997
4001 extra = ctx.extra().copy()
3998 extra = ctx.extra().copy()
4002 del extra['branch']
3999 del extra['branch']
4003 source = extra.get('source')
4000 source = extra.get('source')
4004 if source:
4001 if source:
4005 extra['intermediate-source'] = ctx.hex()
4002 extra['intermediate-source'] = ctx.hex()
4006 else:
4003 else:
4007 extra['source'] = ctx.hex()
4004 extra['source'] = ctx.hex()
4008 user = ctx.user()
4005 user = ctx.user()
4009 if opts.get('user'):
4006 if opts.get('user'):
4010 user = opts['user']
4007 user = opts['user']
4011 date = ctx.date()
4008 date = ctx.date()
4012 if opts.get('date'):
4009 if opts.get('date'):
4013 date = opts['date']
4010 date = opts['date']
4014 message = ctx.description()
4011 message = ctx.description()
4015 if opts.get('log'):
4012 if opts.get('log'):
4016 message += '\n(grafted from %s)' % ctx.hex()
4013 message += '\n(grafted from %s)' % ctx.hex()
4017
4014
4018 # we don't merge the first commit when continuing
4015 # we don't merge the first commit when continuing
4019 if not cont:
4016 if not cont:
4020 # perform the graft merge with p1(rev) as 'ancestor'
4017 # perform the graft merge with p1(rev) as 'ancestor'
4021 try:
4018 try:
4022 # ui.forcemerge is an internal variable, do not document
4019 # ui.forcemerge is an internal variable, do not document
4023 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4020 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
4024 'graft')
4021 'graft')
4025 stats = mergemod.graft(repo, ctx, ctx.p1(),
4022 stats = mergemod.graft(repo, ctx, ctx.p1(),
4026 ['local', 'graft'])
4023 ['local', 'graft'])
4027 finally:
4024 finally:
4028 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4025 repo.ui.setconfig('ui', 'forcemerge', '', 'graft')
4029 # report any conflicts
4026 # report any conflicts
4030 if stats and stats[3] > 0:
4027 if stats and stats[3] > 0:
4031 # write out state for --continue
4028 # write out state for --continue
4032 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4029 nodelines = [repo[rev].hex() + "\n" for rev in revs[pos:]]
4033 repo.vfs.write('graftstate', ''.join(nodelines))
4030 repo.vfs.write('graftstate', ''.join(nodelines))
4034 extra = ''
4031 extra = ''
4035 if opts.get('user'):
4032 if opts.get('user'):
4036 extra += ' --user %s' % opts['user']
4033 extra += ' --user %s' % opts['user']
4037 if opts.get('date'):
4034 if opts.get('date'):
4038 extra += ' --date %s' % opts['date']
4035 extra += ' --date %s' % opts['date']
4039 if opts.get('log'):
4036 if opts.get('log'):
4040 extra += ' --log'
4037 extra += ' --log'
4041 hint=_('use hg resolve and hg graft --continue%s') % extra
4038 hint=_('use hg resolve and hg graft --continue%s') % extra
4042 raise error.Abort(
4039 raise error.Abort(
4043 _("unresolved conflicts, can't continue"),
4040 _("unresolved conflicts, can't continue"),
4044 hint=hint)
4041 hint=hint)
4045 else:
4042 else:
4046 cont = False
4043 cont = False
4047
4044
4048 # commit
4045 # commit
4049 node = repo.commit(text=message, user=user,
4046 node = repo.commit(text=message, user=user,
4050 date=date, extra=extra, editor=editor)
4047 date=date, extra=extra, editor=editor)
4051 if node is None:
4048 if node is None:
4052 ui.warn(
4049 ui.warn(
4053 _('note: graft of %d:%s created no changes to commit\n') %
4050 _('note: graft of %d:%s created no changes to commit\n') %
4054 (ctx.rev(), ctx))
4051 (ctx.rev(), ctx))
4055
4052
4056 # remove state when we complete successfully
4053 # remove state when we complete successfully
4057 if not opts.get('dry_run'):
4054 if not opts.get('dry_run'):
4058 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4055 util.unlinkpath(repo.join('graftstate'), ignoremissing=True)
4059
4056
4060 return 0
4057 return 0
4061
4058
4062 @command('grep',
4059 @command('grep',
4063 [('0', 'print0', None, _('end fields with NUL')),
4060 [('0', 'print0', None, _('end fields with NUL')),
4064 ('', 'all', None, _('print all revisions that match')),
4061 ('', 'all', None, _('print all revisions that match')),
4065 ('a', 'text', None, _('treat all files as text')),
4062 ('a', 'text', None, _('treat all files as text')),
4066 ('f', 'follow', None,
4063 ('f', 'follow', None,
4067 _('follow changeset history,'
4064 _('follow changeset history,'
4068 ' or file history across copies and renames')),
4065 ' or file history across copies and renames')),
4069 ('i', 'ignore-case', None, _('ignore case when matching')),
4066 ('i', 'ignore-case', None, _('ignore case when matching')),
4070 ('l', 'files-with-matches', None,
4067 ('l', 'files-with-matches', None,
4071 _('print only filenames and revisions that match')),
4068 _('print only filenames and revisions that match')),
4072 ('n', 'line-number', None, _('print matching line numbers')),
4069 ('n', 'line-number', None, _('print matching line numbers')),
4073 ('r', 'rev', [],
4070 ('r', 'rev', [],
4074 _('only search files changed within revision range'), _('REV')),
4071 _('only search files changed within revision range'), _('REV')),
4075 ('u', 'user', None, _('list the author (long with -v)')),
4072 ('u', 'user', None, _('list the author (long with -v)')),
4076 ('d', 'date', None, _('list the date (short with -q)')),
4073 ('d', 'date', None, _('list the date (short with -q)')),
4077 ] + walkopts,
4074 ] + walkopts,
4078 _('[OPTION]... PATTERN [FILE]...'),
4075 _('[OPTION]... PATTERN [FILE]...'),
4079 inferrepo=True)
4076 inferrepo=True)
4080 def grep(ui, repo, pattern, *pats, **opts):
4077 def grep(ui, repo, pattern, *pats, **opts):
4081 """search for a pattern in specified files and revisions
4078 """search for a pattern in specified files and revisions
4082
4079
4083 Search revisions of files for a regular expression.
4080 Search revisions of files for a regular expression.
4084
4081
4085 This command behaves differently than Unix grep. It only accepts
4082 This command behaves differently than Unix grep. It only accepts
4086 Python/Perl regexps. It searches repository history, not the
4083 Python/Perl regexps. It searches repository history, not the
4087 working directory. It always prints the revision number in which a
4084 working directory. It always prints the revision number in which a
4088 match appears.
4085 match appears.
4089
4086
4090 By default, grep only prints output for the first revision of a
4087 By default, grep only prints output for the first revision of a
4091 file in which it finds a match. To get it to print every revision
4088 file in which it finds a match. To get it to print every revision
4092 that contains a change in match status ("-" for a match that
4089 that contains a change in match status ("-" for a match that
4093 becomes a non-match, or "+" for a non-match that becomes a match),
4090 becomes a non-match, or "+" for a non-match that becomes a match),
4094 use the --all flag.
4091 use the --all flag.
4095
4092
4096 Returns 0 if a match is found, 1 otherwise.
4093 Returns 0 if a match is found, 1 otherwise.
4097 """
4094 """
4098 reflags = re.M
4095 reflags = re.M
4099 if opts.get('ignore_case'):
4096 if opts.get('ignore_case'):
4100 reflags |= re.I
4097 reflags |= re.I
4101 try:
4098 try:
4102 regexp = util.re.compile(pattern, reflags)
4099 regexp = util.re.compile(pattern, reflags)
4103 except re.error as inst:
4100 except re.error as inst:
4104 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4101 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
4105 return 1
4102 return 1
4106 sep, eol = ':', '\n'
4103 sep, eol = ':', '\n'
4107 if opts.get('print0'):
4104 if opts.get('print0'):
4108 sep = eol = '\0'
4105 sep = eol = '\0'
4109
4106
4110 getfile = util.lrucachefunc(repo.file)
4107 getfile = util.lrucachefunc(repo.file)
4111
4108
4112 def matchlines(body):
4109 def matchlines(body):
4113 begin = 0
4110 begin = 0
4114 linenum = 0
4111 linenum = 0
4115 while begin < len(body):
4112 while begin < len(body):
4116 match = regexp.search(body, begin)
4113 match = regexp.search(body, begin)
4117 if not match:
4114 if not match:
4118 break
4115 break
4119 mstart, mend = match.span()
4116 mstart, mend = match.span()
4120 linenum += body.count('\n', begin, mstart) + 1
4117 linenum += body.count('\n', begin, mstart) + 1
4121 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4118 lstart = body.rfind('\n', begin, mstart) + 1 or begin
4122 begin = body.find('\n', mend) + 1 or len(body) + 1
4119 begin = body.find('\n', mend) + 1 or len(body) + 1
4123 lend = begin - 1
4120 lend = begin - 1
4124 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4121 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
4125
4122
4126 class linestate(object):
4123 class linestate(object):
4127 def __init__(self, line, linenum, colstart, colend):
4124 def __init__(self, line, linenum, colstart, colend):
4128 self.line = line
4125 self.line = line
4129 self.linenum = linenum
4126 self.linenum = linenum
4130 self.colstart = colstart
4127 self.colstart = colstart
4131 self.colend = colend
4128 self.colend = colend
4132
4129
4133 def __hash__(self):
4130 def __hash__(self):
4134 return hash((self.linenum, self.line))
4131 return hash((self.linenum, self.line))
4135
4132
4136 def __eq__(self, other):
4133 def __eq__(self, other):
4137 return self.line == other.line
4134 return self.line == other.line
4138
4135
4139 def __iter__(self):
4136 def __iter__(self):
4140 yield (self.line[:self.colstart], '')
4137 yield (self.line[:self.colstart], '')
4141 yield (self.line[self.colstart:self.colend], 'grep.match')
4138 yield (self.line[self.colstart:self.colend], 'grep.match')
4142 rest = self.line[self.colend:]
4139 rest = self.line[self.colend:]
4143 while rest != '':
4140 while rest != '':
4144 match = regexp.search(rest)
4141 match = regexp.search(rest)
4145 if not match:
4142 if not match:
4146 yield (rest, '')
4143 yield (rest, '')
4147 break
4144 break
4148 mstart, mend = match.span()
4145 mstart, mend = match.span()
4149 yield (rest[:mstart], '')
4146 yield (rest[:mstart], '')
4150 yield (rest[mstart:mend], 'grep.match')
4147 yield (rest[mstart:mend], 'grep.match')
4151 rest = rest[mend:]
4148 rest = rest[mend:]
4152
4149
4153 matches = {}
4150 matches = {}
4154 copies = {}
4151 copies = {}
4155 def grepbody(fn, rev, body):
4152 def grepbody(fn, rev, body):
4156 matches[rev].setdefault(fn, [])
4153 matches[rev].setdefault(fn, [])
4157 m = matches[rev][fn]
4154 m = matches[rev][fn]
4158 for lnum, cstart, cend, line in matchlines(body):
4155 for lnum, cstart, cend, line in matchlines(body):
4159 s = linestate(line, lnum, cstart, cend)
4156 s = linestate(line, lnum, cstart, cend)
4160 m.append(s)
4157 m.append(s)
4161
4158
4162 def difflinestates(a, b):
4159 def difflinestates(a, b):
4163 sm = difflib.SequenceMatcher(None, a, b)
4160 sm = difflib.SequenceMatcher(None, a, b)
4164 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4161 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
4165 if tag == 'insert':
4162 if tag == 'insert':
4166 for i in xrange(blo, bhi):
4163 for i in xrange(blo, bhi):
4167 yield ('+', b[i])
4164 yield ('+', b[i])
4168 elif tag == 'delete':
4165 elif tag == 'delete':
4169 for i in xrange(alo, ahi):
4166 for i in xrange(alo, ahi):
4170 yield ('-', a[i])
4167 yield ('-', a[i])
4171 elif tag == 'replace':
4168 elif tag == 'replace':
4172 for i in xrange(alo, ahi):
4169 for i in xrange(alo, ahi):
4173 yield ('-', a[i])
4170 yield ('-', a[i])
4174 for i in xrange(blo, bhi):
4171 for i in xrange(blo, bhi):
4175 yield ('+', b[i])
4172 yield ('+', b[i])
4176
4173
4177 def display(fn, ctx, pstates, states):
4174 def display(fn, ctx, pstates, states):
4178 rev = ctx.rev()
4175 rev = ctx.rev()
4179 if ui.quiet:
4176 if ui.quiet:
4180 datefunc = util.shortdate
4177 datefunc = util.shortdate
4181 else:
4178 else:
4182 datefunc = util.datestr
4179 datefunc = util.datestr
4183 found = False
4180 found = False
4184 @util.cachefunc
4181 @util.cachefunc
4185 def binary():
4182 def binary():
4186 flog = getfile(fn)
4183 flog = getfile(fn)
4187 return util.binary(flog.read(ctx.filenode(fn)))
4184 return util.binary(flog.read(ctx.filenode(fn)))
4188
4185
4189 if opts.get('all'):
4186 if opts.get('all'):
4190 iter = difflinestates(pstates, states)
4187 iter = difflinestates(pstates, states)
4191 else:
4188 else:
4192 iter = [('', l) for l in states]
4189 iter = [('', l) for l in states]
4193 for change, l in iter:
4190 for change, l in iter:
4194 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4191 cols = [(fn, 'grep.filename'), (str(rev), 'grep.rev')]
4195
4192
4196 if opts.get('line_number'):
4193 if opts.get('line_number'):
4197 cols.append((str(l.linenum), 'grep.linenumber'))
4194 cols.append((str(l.linenum), 'grep.linenumber'))
4198 if opts.get('all'):
4195 if opts.get('all'):
4199 cols.append((change, 'grep.change'))
4196 cols.append((change, 'grep.change'))
4200 if opts.get('user'):
4197 if opts.get('user'):
4201 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4198 cols.append((ui.shortuser(ctx.user()), 'grep.user'))
4202 if opts.get('date'):
4199 if opts.get('date'):
4203 cols.append((datefunc(ctx.date()), 'grep.date'))
4200 cols.append((datefunc(ctx.date()), 'grep.date'))
4204 for col, label in cols[:-1]:
4201 for col, label in cols[:-1]:
4205 ui.write(col, label=label)
4202 ui.write(col, label=label)
4206 ui.write(sep, label='grep.sep')
4203 ui.write(sep, label='grep.sep')
4207 ui.write(cols[-1][0], label=cols[-1][1])
4204 ui.write(cols[-1][0], label=cols[-1][1])
4208 if not opts.get('files_with_matches'):
4205 if not opts.get('files_with_matches'):
4209 ui.write(sep, label='grep.sep')
4206 ui.write(sep, label='grep.sep')
4210 if not opts.get('text') and binary():
4207 if not opts.get('text') and binary():
4211 ui.write(" Binary file matches")
4208 ui.write(" Binary file matches")
4212 else:
4209 else:
4213 for s, label in l:
4210 for s, label in l:
4214 ui.write(s, label=label)
4211 ui.write(s, label=label)
4215 ui.write(eol)
4212 ui.write(eol)
4216 found = True
4213 found = True
4217 if opts.get('files_with_matches'):
4214 if opts.get('files_with_matches'):
4218 break
4215 break
4219 return found
4216 return found
4220
4217
4221 skip = {}
4218 skip = {}
4222 revfiles = {}
4219 revfiles = {}
4223 matchfn = scmutil.match(repo[None], pats, opts)
4220 matchfn = scmutil.match(repo[None], pats, opts)
4224 found = False
4221 found = False
4225 follow = opts.get('follow')
4222 follow = opts.get('follow')
4226
4223
4227 def prep(ctx, fns):
4224 def prep(ctx, fns):
4228 rev = ctx.rev()
4225 rev = ctx.rev()
4229 pctx = ctx.p1()
4226 pctx = ctx.p1()
4230 parent = pctx.rev()
4227 parent = pctx.rev()
4231 matches.setdefault(rev, {})
4228 matches.setdefault(rev, {})
4232 matches.setdefault(parent, {})
4229 matches.setdefault(parent, {})
4233 files = revfiles.setdefault(rev, [])
4230 files = revfiles.setdefault(rev, [])
4234 for fn in fns:
4231 for fn in fns:
4235 flog = getfile(fn)
4232 flog = getfile(fn)
4236 try:
4233 try:
4237 fnode = ctx.filenode(fn)
4234 fnode = ctx.filenode(fn)
4238 except error.LookupError:
4235 except error.LookupError:
4239 continue
4236 continue
4240
4237
4241 copied = flog.renamed(fnode)
4238 copied = flog.renamed(fnode)
4242 copy = follow and copied and copied[0]
4239 copy = follow and copied and copied[0]
4243 if copy:
4240 if copy:
4244 copies.setdefault(rev, {})[fn] = copy
4241 copies.setdefault(rev, {})[fn] = copy
4245 if fn in skip:
4242 if fn in skip:
4246 if copy:
4243 if copy:
4247 skip[copy] = True
4244 skip[copy] = True
4248 continue
4245 continue
4249 files.append(fn)
4246 files.append(fn)
4250
4247
4251 if fn not in matches[rev]:
4248 if fn not in matches[rev]:
4252 grepbody(fn, rev, flog.read(fnode))
4249 grepbody(fn, rev, flog.read(fnode))
4253
4250
4254 pfn = copy or fn
4251 pfn = copy or fn
4255 if pfn not in matches[parent]:
4252 if pfn not in matches[parent]:
4256 try:
4253 try:
4257 fnode = pctx.filenode(pfn)
4254 fnode = pctx.filenode(pfn)
4258 grepbody(pfn, parent, flog.read(fnode))
4255 grepbody(pfn, parent, flog.read(fnode))
4259 except error.LookupError:
4256 except error.LookupError:
4260 pass
4257 pass
4261
4258
4262 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4259 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
4263 rev = ctx.rev()
4260 rev = ctx.rev()
4264 parent = ctx.p1().rev()
4261 parent = ctx.p1().rev()
4265 for fn in sorted(revfiles.get(rev, [])):
4262 for fn in sorted(revfiles.get(rev, [])):
4266 states = matches[rev][fn]
4263 states = matches[rev][fn]
4267 copy = copies.get(rev, {}).get(fn)
4264 copy = copies.get(rev, {}).get(fn)
4268 if fn in skip:
4265 if fn in skip:
4269 if copy:
4266 if copy:
4270 skip[copy] = True
4267 skip[copy] = True
4271 continue
4268 continue
4272 pstates = matches.get(parent, {}).get(copy or fn, [])
4269 pstates = matches.get(parent, {}).get(copy or fn, [])
4273 if pstates or states:
4270 if pstates or states:
4274 r = display(fn, ctx, pstates, states)
4271 r = display(fn, ctx, pstates, states)
4275 found = found or r
4272 found = found or r
4276 if r and not opts.get('all'):
4273 if r and not opts.get('all'):
4277 skip[fn] = True
4274 skip[fn] = True
4278 if copy:
4275 if copy:
4279 skip[copy] = True
4276 skip[copy] = True
4280 del matches[rev]
4277 del matches[rev]
4281 del revfiles[rev]
4278 del revfiles[rev]
4282
4279
4283 return not found
4280 return not found
4284
4281
4285 @command('heads',
4282 @command('heads',
4286 [('r', 'rev', '',
4283 [('r', 'rev', '',
4287 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4284 _('show only heads which are descendants of STARTREV'), _('STARTREV')),
4288 ('t', 'topo', False, _('show topological heads only')),
4285 ('t', 'topo', False, _('show topological heads only')),
4289 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4286 ('a', 'active', False, _('show active branchheads only (DEPRECATED)')),
4290 ('c', 'closed', False, _('show normal and closed branch heads')),
4287 ('c', 'closed', False, _('show normal and closed branch heads')),
4291 ] + templateopts,
4288 ] + templateopts,
4292 _('[-ct] [-r STARTREV] [REV]...'))
4289 _('[-ct] [-r STARTREV] [REV]...'))
4293 def heads(ui, repo, *branchrevs, **opts):
4290 def heads(ui, repo, *branchrevs, **opts):
4294 """show branch heads
4291 """show branch heads
4295
4292
4296 With no arguments, show all open branch heads in the repository.
4293 With no arguments, show all open branch heads in the repository.
4297 Branch heads are changesets that have no descendants on the
4294 Branch heads are changesets that have no descendants on the
4298 same branch. They are where development generally takes place and
4295 same branch. They are where development generally takes place and
4299 are the usual targets for update and merge operations.
4296 are the usual targets for update and merge operations.
4300
4297
4301 If one or more REVs are given, only open branch heads on the
4298 If one or more REVs are given, only open branch heads on the
4302 branches associated with the specified changesets are shown. This
4299 branches associated with the specified changesets are shown. This
4303 means that you can use :hg:`heads .` to see the heads on the
4300 means that you can use :hg:`heads .` to see the heads on the
4304 currently checked-out branch.
4301 currently checked-out branch.
4305
4302
4306 If -c/--closed is specified, also show branch heads marked closed
4303 If -c/--closed is specified, also show branch heads marked closed
4307 (see :hg:`commit --close-branch`).
4304 (see :hg:`commit --close-branch`).
4308
4305
4309 If STARTREV is specified, only those heads that are descendants of
4306 If STARTREV is specified, only those heads that are descendants of
4310 STARTREV will be displayed.
4307 STARTREV will be displayed.
4311
4308
4312 If -t/--topo is specified, named branch mechanics will be ignored and only
4309 If -t/--topo is specified, named branch mechanics will be ignored and only
4313 topological heads (changesets with no children) will be shown.
4310 topological heads (changesets with no children) will be shown.
4314
4311
4315 Returns 0 if matching heads are found, 1 if not.
4312 Returns 0 if matching heads are found, 1 if not.
4316 """
4313 """
4317
4314
4318 start = None
4315 start = None
4319 if 'rev' in opts:
4316 if 'rev' in opts:
4320 start = scmutil.revsingle(repo, opts['rev'], None).node()
4317 start = scmutil.revsingle(repo, opts['rev'], None).node()
4321
4318
4322 if opts.get('topo'):
4319 if opts.get('topo'):
4323 heads = [repo[h] for h in repo.heads(start)]
4320 heads = [repo[h] for h in repo.heads(start)]
4324 else:
4321 else:
4325 heads = []
4322 heads = []
4326 for branch in repo.branchmap():
4323 for branch in repo.branchmap():
4327 heads += repo.branchheads(branch, start, opts.get('closed'))
4324 heads += repo.branchheads(branch, start, opts.get('closed'))
4328 heads = [repo[h] for h in heads]
4325 heads = [repo[h] for h in heads]
4329
4326
4330 if branchrevs:
4327 if branchrevs:
4331 branches = set(repo[br].branch() for br in branchrevs)
4328 branches = set(repo[br].branch() for br in branchrevs)
4332 heads = [h for h in heads if h.branch() in branches]
4329 heads = [h for h in heads if h.branch() in branches]
4333
4330
4334 if opts.get('active') and branchrevs:
4331 if opts.get('active') and branchrevs:
4335 dagheads = repo.heads(start)
4332 dagheads = repo.heads(start)
4336 heads = [h for h in heads if h.node() in dagheads]
4333 heads = [h for h in heads if h.node() in dagheads]
4337
4334
4338 if branchrevs:
4335 if branchrevs:
4339 haveheads = set(h.branch() for h in heads)
4336 haveheads = set(h.branch() for h in heads)
4340 if branches - haveheads:
4337 if branches - haveheads:
4341 headless = ', '.join(b for b in branches - haveheads)
4338 headless = ', '.join(b for b in branches - haveheads)
4342 msg = _('no open branch heads found on branches %s')
4339 msg = _('no open branch heads found on branches %s')
4343 if opts.get('rev'):
4340 if opts.get('rev'):
4344 msg += _(' (started at %s)') % opts['rev']
4341 msg += _(' (started at %s)') % opts['rev']
4345 ui.warn((msg + '\n') % headless)
4342 ui.warn((msg + '\n') % headless)
4346
4343
4347 if not heads:
4344 if not heads:
4348 return 1
4345 return 1
4349
4346
4350 heads = sorted(heads, key=lambda x: -x.rev())
4347 heads = sorted(heads, key=lambda x: -x.rev())
4351 displayer = cmdutil.show_changeset(ui, repo, opts)
4348 displayer = cmdutil.show_changeset(ui, repo, opts)
4352 for ctx in heads:
4349 for ctx in heads:
4353 displayer.show(ctx)
4350 displayer.show(ctx)
4354 displayer.close()
4351 displayer.close()
4355
4352
4356 @command('help',
4353 @command('help',
4357 [('e', 'extension', None, _('show only help for extensions')),
4354 [('e', 'extension', None, _('show only help for extensions')),
4358 ('c', 'command', None, _('show only help for commands')),
4355 ('c', 'command', None, _('show only help for commands')),
4359 ('k', 'keyword', None, _('show topics matching keyword')),
4356 ('k', 'keyword', None, _('show topics matching keyword')),
4360 ('s', 'system', [], _('show help for specific platform(s)')),
4357 ('s', 'system', [], _('show help for specific platform(s)')),
4361 ],
4358 ],
4362 _('[-ecks] [TOPIC]'),
4359 _('[-ecks] [TOPIC]'),
4363 norepo=True)
4360 norepo=True)
4364 def help_(ui, name=None, **opts):
4361 def help_(ui, name=None, **opts):
4365 """show help for a given topic or a help overview
4362 """show help for a given topic or a help overview
4366
4363
4367 With no arguments, print a list of commands with short help messages.
4364 With no arguments, print a list of commands with short help messages.
4368
4365
4369 Given a topic, extension, or command name, print help for that
4366 Given a topic, extension, or command name, print help for that
4370 topic.
4367 topic.
4371
4368
4372 Returns 0 if successful.
4369 Returns 0 if successful.
4373 """
4370 """
4374
4371
4375 textwidth = min(ui.termwidth(), 80) - 2
4372 textwidth = min(ui.termwidth(), 80) - 2
4376
4373
4377 keep = opts.get('system') or []
4374 keep = opts.get('system') or []
4378 if len(keep) == 0:
4375 if len(keep) == 0:
4379 if sys.platform.startswith('win'):
4376 if sys.platform.startswith('win'):
4380 keep.append('windows')
4377 keep.append('windows')
4381 elif sys.platform == 'OpenVMS':
4378 elif sys.platform == 'OpenVMS':
4382 keep.append('vms')
4379 keep.append('vms')
4383 elif sys.platform == 'plan9':
4380 elif sys.platform == 'plan9':
4384 keep.append('plan9')
4381 keep.append('plan9')
4385 else:
4382 else:
4386 keep.append('unix')
4383 keep.append('unix')
4387 keep.append(sys.platform.lower())
4384 keep.append(sys.platform.lower())
4388 if ui.verbose:
4385 if ui.verbose:
4389 keep.append('verbose')
4386 keep.append('verbose')
4390
4387
4391 section = None
4388 section = None
4392 subtopic = None
4389 subtopic = None
4393 if name and '.' in name:
4390 if name and '.' in name:
4394 name, section = name.split('.', 1)
4391 name, section = name.split('.', 1)
4395 section = section.lower()
4392 section = section.lower()
4396 if '.' in section:
4393 if '.' in section:
4397 subtopic, section = section.split('.', 1)
4394 subtopic, section = section.split('.', 1)
4398 else:
4395 else:
4399 subtopic = section
4396 subtopic = section
4400
4397
4401 text = help.help_(ui, name, subtopic=subtopic, **opts)
4398 text = help.help_(ui, name, subtopic=subtopic, **opts)
4402
4399
4403 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4400 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4404 section=section)
4401 section=section)
4405
4402
4406 # We could have been given a weird ".foo" section without a name
4403 # We could have been given a weird ".foo" section without a name
4407 # to look for, or we could have simply failed to found "foo.bar"
4404 # to look for, or we could have simply failed to found "foo.bar"
4408 # because bar isn't a section of foo
4405 # because bar isn't a section of foo
4409 if section and not (formatted and name):
4406 if section and not (formatted and name):
4410 raise error.Abort(_("help section not found"))
4407 raise error.Abort(_("help section not found"))
4411
4408
4412 if 'verbose' in pruned:
4409 if 'verbose' in pruned:
4413 keep.append('omitted')
4410 keep.append('omitted')
4414 else:
4411 else:
4415 keep.append('notomitted')
4412 keep.append('notomitted')
4416 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4413 formatted, pruned = minirst.format(text, textwidth, keep=keep,
4417 section=section)
4414 section=section)
4418 ui.write(formatted)
4415 ui.write(formatted)
4419
4416
4420
4417
4421 @command('identify|id',
4418 @command('identify|id',
4422 [('r', 'rev', '',
4419 [('r', 'rev', '',
4423 _('identify the specified revision'), _('REV')),
4420 _('identify the specified revision'), _('REV')),
4424 ('n', 'num', None, _('show local revision number')),
4421 ('n', 'num', None, _('show local revision number')),
4425 ('i', 'id', None, _('show global revision id')),
4422 ('i', 'id', None, _('show global revision id')),
4426 ('b', 'branch', None, _('show branch')),
4423 ('b', 'branch', None, _('show branch')),
4427 ('t', 'tags', None, _('show tags')),
4424 ('t', 'tags', None, _('show tags')),
4428 ('B', 'bookmarks', None, _('show bookmarks')),
4425 ('B', 'bookmarks', None, _('show bookmarks')),
4429 ] + remoteopts,
4426 ] + remoteopts,
4430 _('[-nibtB] [-r REV] [SOURCE]'),
4427 _('[-nibtB] [-r REV] [SOURCE]'),
4431 optionalrepo=True)
4428 optionalrepo=True)
4432 def identify(ui, repo, source=None, rev=None,
4429 def identify(ui, repo, source=None, rev=None,
4433 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4430 num=None, id=None, branch=None, tags=None, bookmarks=None, **opts):
4434 """identify the working directory or specified revision
4431 """identify the working directory or specified revision
4435
4432
4436 Print a summary identifying the repository state at REV using one or
4433 Print a summary identifying the repository state at REV using one or
4437 two parent hash identifiers, followed by a "+" if the working
4434 two parent hash identifiers, followed by a "+" if the working
4438 directory has uncommitted changes, the branch name (if not default),
4435 directory has uncommitted changes, the branch name (if not default),
4439 a list of tags, and a list of bookmarks.
4436 a list of tags, and a list of bookmarks.
4440
4437
4441 When REV is not given, print a summary of the current state of the
4438 When REV is not given, print a summary of the current state of the
4442 repository.
4439 repository.
4443
4440
4444 Specifying a path to a repository root or Mercurial bundle will
4441 Specifying a path to a repository root or Mercurial bundle will
4445 cause lookup to operate on that repository/bundle.
4442 cause lookup to operate on that repository/bundle.
4446
4443
4447 .. container:: verbose
4444 .. container:: verbose
4448
4445
4449 Examples:
4446 Examples:
4450
4447
4451 - generate a build identifier for the working directory::
4448 - generate a build identifier for the working directory::
4452
4449
4453 hg id --id > build-id.dat
4450 hg id --id > build-id.dat
4454
4451
4455 - find the revision corresponding to a tag::
4452 - find the revision corresponding to a tag::
4456
4453
4457 hg id -n -r 1.3
4454 hg id -n -r 1.3
4458
4455
4459 - check the most recent revision of a remote repository::
4456 - check the most recent revision of a remote repository::
4460
4457
4461 hg id -r tip http://selenic.com/hg/
4458 hg id -r tip http://selenic.com/hg/
4462
4459
4463 See :hg:`log` for generating more information about specific revisions,
4460 See :hg:`log` for generating more information about specific revisions,
4464 including full hash identifiers.
4461 including full hash identifiers.
4465
4462
4466 Returns 0 if successful.
4463 Returns 0 if successful.
4467 """
4464 """
4468
4465
4469 if not repo and not source:
4466 if not repo and not source:
4470 raise error.Abort(_("there is no Mercurial repository here "
4467 raise error.Abort(_("there is no Mercurial repository here "
4471 "(.hg not found)"))
4468 "(.hg not found)"))
4472
4469
4473 if ui.debugflag:
4470 if ui.debugflag:
4474 hexfunc = hex
4471 hexfunc = hex
4475 else:
4472 else:
4476 hexfunc = short
4473 hexfunc = short
4477 default = not (num or id or branch or tags or bookmarks)
4474 default = not (num or id or branch or tags or bookmarks)
4478 output = []
4475 output = []
4479 revs = []
4476 revs = []
4480
4477
4481 if source:
4478 if source:
4482 source, branches = hg.parseurl(ui.expandpath(source))
4479 source, branches = hg.parseurl(ui.expandpath(source))
4483 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4480 peer = hg.peer(repo or ui, opts, source) # only pass ui when no repo
4484 repo = peer.local()
4481 repo = peer.local()
4485 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4482 revs, checkout = hg.addbranchrevs(repo, peer, branches, None)
4486
4483
4487 if not repo:
4484 if not repo:
4488 if num or branch or tags:
4485 if num or branch or tags:
4489 raise error.Abort(
4486 raise error.Abort(
4490 _("can't query remote revision number, branch, or tags"))
4487 _("can't query remote revision number, branch, or tags"))
4491 if not rev and revs:
4488 if not rev and revs:
4492 rev = revs[0]
4489 rev = revs[0]
4493 if not rev:
4490 if not rev:
4494 rev = "tip"
4491 rev = "tip"
4495
4492
4496 remoterev = peer.lookup(rev)
4493 remoterev = peer.lookup(rev)
4497 if default or id:
4494 if default or id:
4498 output = [hexfunc(remoterev)]
4495 output = [hexfunc(remoterev)]
4499
4496
4500 def getbms():
4497 def getbms():
4501 bms = []
4498 bms = []
4502
4499
4503 if 'bookmarks' in peer.listkeys('namespaces'):
4500 if 'bookmarks' in peer.listkeys('namespaces'):
4504 hexremoterev = hex(remoterev)
4501 hexremoterev = hex(remoterev)
4505 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4502 bms = [bm for bm, bmr in peer.listkeys('bookmarks').iteritems()
4506 if bmr == hexremoterev]
4503 if bmr == hexremoterev]
4507
4504
4508 return sorted(bms)
4505 return sorted(bms)
4509
4506
4510 if bookmarks:
4507 if bookmarks:
4511 output.extend(getbms())
4508 output.extend(getbms())
4512 elif default and not ui.quiet:
4509 elif default and not ui.quiet:
4513 # multiple bookmarks for a single parent separated by '/'
4510 # multiple bookmarks for a single parent separated by '/'
4514 bm = '/'.join(getbms())
4511 bm = '/'.join(getbms())
4515 if bm:
4512 if bm:
4516 output.append(bm)
4513 output.append(bm)
4517 else:
4514 else:
4518 ctx = scmutil.revsingle(repo, rev, None)
4515 ctx = scmutil.revsingle(repo, rev, None)
4519
4516
4520 if ctx.rev() is None:
4517 if ctx.rev() is None:
4521 ctx = repo[None]
4518 ctx = repo[None]
4522 parents = ctx.parents()
4519 parents = ctx.parents()
4523 taglist = []
4520 taglist = []
4524 for p in parents:
4521 for p in parents:
4525 taglist.extend(p.tags())
4522 taglist.extend(p.tags())
4526
4523
4527 changed = ""
4524 changed = ""
4528 if default or id or num:
4525 if default or id or num:
4529 if (any(repo.status())
4526 if (any(repo.status())
4530 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4527 or any(ctx.sub(s).dirty() for s in ctx.substate)):
4531 changed = '+'
4528 changed = '+'
4532 if default or id:
4529 if default or id:
4533 output = ["%s%s" %
4530 output = ["%s%s" %
4534 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4531 ('+'.join([hexfunc(p.node()) for p in parents]), changed)]
4535 if num:
4532 if num:
4536 output.append("%s%s" %
4533 output.append("%s%s" %
4537 ('+'.join([str(p.rev()) for p in parents]), changed))
4534 ('+'.join([str(p.rev()) for p in parents]), changed))
4538 else:
4535 else:
4539 if default or id:
4536 if default or id:
4540 output = [hexfunc(ctx.node())]
4537 output = [hexfunc(ctx.node())]
4541 if num:
4538 if num:
4542 output.append(str(ctx.rev()))
4539 output.append(str(ctx.rev()))
4543 taglist = ctx.tags()
4540 taglist = ctx.tags()
4544
4541
4545 if default and not ui.quiet:
4542 if default and not ui.quiet:
4546 b = ctx.branch()
4543 b = ctx.branch()
4547 if b != 'default':
4544 if b != 'default':
4548 output.append("(%s)" % b)
4545 output.append("(%s)" % b)
4549
4546
4550 # multiple tags for a single parent separated by '/'
4547 # multiple tags for a single parent separated by '/'
4551 t = '/'.join(taglist)
4548 t = '/'.join(taglist)
4552 if t:
4549 if t:
4553 output.append(t)
4550 output.append(t)
4554
4551
4555 # multiple bookmarks for a single parent separated by '/'
4552 # multiple bookmarks for a single parent separated by '/'
4556 bm = '/'.join(ctx.bookmarks())
4553 bm = '/'.join(ctx.bookmarks())
4557 if bm:
4554 if bm:
4558 output.append(bm)
4555 output.append(bm)
4559 else:
4556 else:
4560 if branch:
4557 if branch:
4561 output.append(ctx.branch())
4558 output.append(ctx.branch())
4562
4559
4563 if tags:
4560 if tags:
4564 output.extend(taglist)
4561 output.extend(taglist)
4565
4562
4566 if bookmarks:
4563 if bookmarks:
4567 output.extend(ctx.bookmarks())
4564 output.extend(ctx.bookmarks())
4568
4565
4569 ui.write("%s\n" % ' '.join(output))
4566 ui.write("%s\n" % ' '.join(output))
4570
4567
4571 @command('import|patch',
4568 @command('import|patch',
4572 [('p', 'strip', 1,
4569 [('p', 'strip', 1,
4573 _('directory strip option for patch. This has the same '
4570 _('directory strip option for patch. This has the same '
4574 'meaning as the corresponding patch option'), _('NUM')),
4571 'meaning as the corresponding patch option'), _('NUM')),
4575 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4572 ('b', 'base', '', _('base path (DEPRECATED)'), _('PATH')),
4576 ('e', 'edit', False, _('invoke editor on commit messages')),
4573 ('e', 'edit', False, _('invoke editor on commit messages')),
4577 ('f', 'force', None,
4574 ('f', 'force', None,
4578 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4575 _('skip check for outstanding uncommitted changes (DEPRECATED)')),
4579 ('', 'no-commit', None,
4576 ('', 'no-commit', None,
4580 _("don't commit, just update the working directory")),
4577 _("don't commit, just update the working directory")),
4581 ('', 'bypass', None,
4578 ('', 'bypass', None,
4582 _("apply patch without touching the working directory")),
4579 _("apply patch without touching the working directory")),
4583 ('', 'partial', None,
4580 ('', 'partial', None,
4584 _('commit even if some hunks fail')),
4581 _('commit even if some hunks fail')),
4585 ('', 'exact', None,
4582 ('', 'exact', None,
4586 _('apply patch to the nodes from which it was generated')),
4583 _('apply patch to the nodes from which it was generated')),
4587 ('', 'prefix', '',
4584 ('', 'prefix', '',
4588 _('apply patch to subdirectory'), _('DIR')),
4585 _('apply patch to subdirectory'), _('DIR')),
4589 ('', 'import-branch', None,
4586 ('', 'import-branch', None,
4590 _('use any branch information in patch (implied by --exact)'))] +
4587 _('use any branch information in patch (implied by --exact)'))] +
4591 commitopts + commitopts2 + similarityopts,
4588 commitopts + commitopts2 + similarityopts,
4592 _('[OPTION]... PATCH...'))
4589 _('[OPTION]... PATCH...'))
4593 def import_(ui, repo, patch1=None, *patches, **opts):
4590 def import_(ui, repo, patch1=None, *patches, **opts):
4594 """import an ordered set of patches
4591 """import an ordered set of patches
4595
4592
4596 Import a list of patches and commit them individually (unless
4593 Import a list of patches and commit them individually (unless
4597 --no-commit is specified).
4594 --no-commit is specified).
4598
4595
4599 To read a patch from standard input, use "-" as the patch name. If
4596 To read a patch from standard input, use "-" as the patch name. If
4600 a URL is specified, the patch will be downloaded from there.
4597 a URL is specified, the patch will be downloaded from there.
4601
4598
4602 Import first applies changes to the working directory (unless
4599 Import first applies changes to the working directory (unless
4603 --bypass is specified), import will abort if there are outstanding
4600 --bypass is specified), import will abort if there are outstanding
4604 changes.
4601 changes.
4605
4602
4606 Use --bypass to apply and commit patches directly to the
4603 Use --bypass to apply and commit patches directly to the
4607 repository, without affecting the working directory. Without
4604 repository, without affecting the working directory. Without
4608 --exact, patches will be applied on top of the working directory
4605 --exact, patches will be applied on top of the working directory
4609 parent revision.
4606 parent revision.
4610
4607
4611 You can import a patch straight from a mail message. Even patches
4608 You can import a patch straight from a mail message. Even patches
4612 as attachments work (to use the body part, it must have type
4609 as attachments work (to use the body part, it must have type
4613 text/plain or text/x-patch). From and Subject headers of email
4610 text/plain or text/x-patch). From and Subject headers of email
4614 message are used as default committer and commit message. All
4611 message are used as default committer and commit message. All
4615 text/plain body parts before first diff are added to the commit
4612 text/plain body parts before first diff are added to the commit
4616 message.
4613 message.
4617
4614
4618 If the imported patch was generated by :hg:`export`, user and
4615 If the imported patch was generated by :hg:`export`, user and
4619 description from patch override values from message headers and
4616 description from patch override values from message headers and
4620 body. Values given on command line with -m/--message and -u/--user
4617 body. Values given on command line with -m/--message and -u/--user
4621 override these.
4618 override these.
4622
4619
4623 If --exact is specified, import will set the working directory to
4620 If --exact is specified, import will set the working directory to
4624 the parent of each patch before applying it, and will abort if the
4621 the parent of each patch before applying it, and will abort if the
4625 resulting changeset has a different ID than the one recorded in
4622 resulting changeset has a different ID than the one recorded in
4626 the patch. This may happen due to character set problems or other
4623 the patch. This may happen due to character set problems or other
4627 deficiencies in the text patch format.
4624 deficiencies in the text patch format.
4628
4625
4629 Use --partial to ensure a changeset will be created from the patch
4626 Use --partial to ensure a changeset will be created from the patch
4630 even if some hunks fail to apply. Hunks that fail to apply will be
4627 even if some hunks fail to apply. Hunks that fail to apply will be
4631 written to a <target-file>.rej file. Conflicts can then be resolved
4628 written to a <target-file>.rej file. Conflicts can then be resolved
4632 by hand before :hg:`commit --amend` is run to update the created
4629 by hand before :hg:`commit --amend` is run to update the created
4633 changeset. This flag exists to let people import patches that
4630 changeset. This flag exists to let people import patches that
4634 partially apply without losing the associated metadata (author,
4631 partially apply without losing the associated metadata (author,
4635 date, description, ...).
4632 date, description, ...).
4636
4633
4637 .. note::
4634 .. note::
4638
4635
4639 When no hunks apply cleanly, :hg:`import --partial` will create
4636 When no hunks apply cleanly, :hg:`import --partial` will create
4640 an empty changeset, importing only the patch metadata.
4637 an empty changeset, importing only the patch metadata.
4641
4638
4642 With -s/--similarity, hg will attempt to discover renames and
4639 With -s/--similarity, hg will attempt to discover renames and
4643 copies in the patch in the same way as :hg:`addremove`.
4640 copies in the patch in the same way as :hg:`addremove`.
4644
4641
4645 It is possible to use external patch programs to perform the patch
4642 It is possible to use external patch programs to perform the patch
4646 by setting the ``ui.patch`` configuration option. For the default
4643 by setting the ``ui.patch`` configuration option. For the default
4647 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4644 internal tool, the fuzz can also be configured via ``patch.fuzz``.
4648 See :hg:`help config` for more information about configuration
4645 See :hg:`help config` for more information about configuration
4649 files and how to use these options.
4646 files and how to use these options.
4650
4647
4651 See :hg:`help dates` for a list of formats valid for -d/--date.
4648 See :hg:`help dates` for a list of formats valid for -d/--date.
4652
4649
4653 .. container:: verbose
4650 .. container:: verbose
4654
4651
4655 Examples:
4652 Examples:
4656
4653
4657 - import a traditional patch from a website and detect renames::
4654 - import a traditional patch from a website and detect renames::
4658
4655
4659 hg import -s 80 http://example.com/bugfix.patch
4656 hg import -s 80 http://example.com/bugfix.patch
4660
4657
4661 - import a changeset from an hgweb server::
4658 - import a changeset from an hgweb server::
4662
4659
4663 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4660 hg import http://www.selenic.com/hg/rev/5ca8c111e9aa
4664
4661
4665 - import all the patches in an Unix-style mbox::
4662 - import all the patches in an Unix-style mbox::
4666
4663
4667 hg import incoming-patches.mbox
4664 hg import incoming-patches.mbox
4668
4665
4669 - attempt to exactly restore an exported changeset (not always
4666 - attempt to exactly restore an exported changeset (not always
4670 possible)::
4667 possible)::
4671
4668
4672 hg import --exact proposed-fix.patch
4669 hg import --exact proposed-fix.patch
4673
4670
4674 - use an external tool to apply a patch which is too fuzzy for
4671 - use an external tool to apply a patch which is too fuzzy for
4675 the default internal tool.
4672 the default internal tool.
4676
4673
4677 hg import --config ui.patch="patch --merge" fuzzy.patch
4674 hg import --config ui.patch="patch --merge" fuzzy.patch
4678
4675
4679 - change the default fuzzing from 2 to a less strict 7
4676 - change the default fuzzing from 2 to a less strict 7
4680
4677
4681 hg import --config ui.fuzz=7 fuzz.patch
4678 hg import --config ui.fuzz=7 fuzz.patch
4682
4679
4683 Returns 0 on success, 1 on partial success (see --partial).
4680 Returns 0 on success, 1 on partial success (see --partial).
4684 """
4681 """
4685
4682
4686 if not patch1:
4683 if not patch1:
4687 raise error.Abort(_('need at least one patch to import'))
4684 raise error.Abort(_('need at least one patch to import'))
4688
4685
4689 patches = (patch1,) + patches
4686 patches = (patch1,) + patches
4690
4687
4691 date = opts.get('date')
4688 date = opts.get('date')
4692 if date:
4689 if date:
4693 opts['date'] = util.parsedate(date)
4690 opts['date'] = util.parsedate(date)
4694
4691
4695 exact = opts.get('exact')
4692 exact = opts.get('exact')
4696 update = not opts.get('bypass')
4693 update = not opts.get('bypass')
4697 if not update and opts.get('no_commit'):
4694 if not update and opts.get('no_commit'):
4698 raise error.Abort(_('cannot use --no-commit with --bypass'))
4695 raise error.Abort(_('cannot use --no-commit with --bypass'))
4699 try:
4696 try:
4700 sim = float(opts.get('similarity') or 0)
4697 sim = float(opts.get('similarity') or 0)
4701 except ValueError:
4698 except ValueError:
4702 raise error.Abort(_('similarity must be a number'))
4699 raise error.Abort(_('similarity must be a number'))
4703 if sim < 0 or sim > 100:
4700 if sim < 0 or sim > 100:
4704 raise error.Abort(_('similarity must be between 0 and 100'))
4701 raise error.Abort(_('similarity must be between 0 and 100'))
4705 if sim and not update:
4702 if sim and not update:
4706 raise error.Abort(_('cannot use --similarity with --bypass'))
4703 raise error.Abort(_('cannot use --similarity with --bypass'))
4707 if exact:
4704 if exact:
4708 if opts.get('edit'):
4705 if opts.get('edit'):
4709 raise error.Abort(_('cannot use --exact with --edit'))
4706 raise error.Abort(_('cannot use --exact with --edit'))
4710 if opts.get('prefix'):
4707 if opts.get('prefix'):
4711 raise error.Abort(_('cannot use --exact with --prefix'))
4708 raise error.Abort(_('cannot use --exact with --prefix'))
4712
4709
4713 base = opts["base"]
4710 base = opts["base"]
4714 wlock = dsguard = lock = tr = None
4711 wlock = dsguard = lock = tr = None
4715 msgs = []
4712 msgs = []
4716 ret = 0
4713 ret = 0
4717
4714
4718
4715
4719 try:
4716 try:
4720 wlock = repo.wlock()
4717 wlock = repo.wlock()
4721
4718
4722 if update:
4719 if update:
4723 cmdutil.checkunfinished(repo)
4720 cmdutil.checkunfinished(repo)
4724 if (exact or not opts.get('force')):
4721 if (exact or not opts.get('force')):
4725 cmdutil.bailifchanged(repo)
4722 cmdutil.bailifchanged(repo)
4726
4723
4727 if not opts.get('no_commit'):
4724 if not opts.get('no_commit'):
4728 lock = repo.lock()
4725 lock = repo.lock()
4729 tr = repo.transaction('import')
4726 tr = repo.transaction('import')
4730 else:
4727 else:
4731 dsguard = cmdutil.dirstateguard(repo, 'import')
4728 dsguard = cmdutil.dirstateguard(repo, 'import')
4732 parents = repo[None].parents()
4729 parents = repo[None].parents()
4733 for patchurl in patches:
4730 for patchurl in patches:
4734 if patchurl == '-':
4731 if patchurl == '-':
4735 ui.status(_('applying patch from stdin\n'))
4732 ui.status(_('applying patch from stdin\n'))
4736 patchfile = ui.fin
4733 patchfile = ui.fin
4737 patchurl = 'stdin' # for error message
4734 patchurl = 'stdin' # for error message
4738 else:
4735 else:
4739 patchurl = os.path.join(base, patchurl)
4736 patchurl = os.path.join(base, patchurl)
4740 ui.status(_('applying %s\n') % patchurl)
4737 ui.status(_('applying %s\n') % patchurl)
4741 patchfile = hg.openpath(ui, patchurl)
4738 patchfile = hg.openpath(ui, patchurl)
4742
4739
4743 haspatch = False
4740 haspatch = False
4744 for hunk in patch.split(patchfile):
4741 for hunk in patch.split(patchfile):
4745 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4742 (msg, node, rej) = cmdutil.tryimportone(ui, repo, hunk,
4746 parents, opts,
4743 parents, opts,
4747 msgs, hg.clean)
4744 msgs, hg.clean)
4748 if msg:
4745 if msg:
4749 haspatch = True
4746 haspatch = True
4750 ui.note(msg + '\n')
4747 ui.note(msg + '\n')
4751 if update or exact:
4748 if update or exact:
4752 parents = repo[None].parents()
4749 parents = repo[None].parents()
4753 else:
4750 else:
4754 parents = [repo[node]]
4751 parents = [repo[node]]
4755 if rej:
4752 if rej:
4756 ui.write_err(_("patch applied partially\n"))
4753 ui.write_err(_("patch applied partially\n"))
4757 ui.write_err(_("(fix the .rej files and run "
4754 ui.write_err(_("(fix the .rej files and run "
4758 "`hg commit --amend`)\n"))
4755 "`hg commit --amend`)\n"))
4759 ret = 1
4756 ret = 1
4760 break
4757 break
4761
4758
4762 if not haspatch:
4759 if not haspatch:
4763 raise error.Abort(_('%s: no diffs found') % patchurl)
4760 raise error.Abort(_('%s: no diffs found') % patchurl)
4764
4761
4765 if tr:
4762 if tr:
4766 tr.close()
4763 tr.close()
4767 if msgs:
4764 if msgs:
4768 repo.savecommitmessage('\n* * *\n'.join(msgs))
4765 repo.savecommitmessage('\n* * *\n'.join(msgs))
4769 if dsguard:
4766 if dsguard:
4770 dsguard.close()
4767 dsguard.close()
4771 return ret
4768 return ret
4772 finally:
4769 finally:
4773 if tr:
4770 if tr:
4774 tr.release()
4771 tr.release()
4775 release(lock, dsguard, wlock)
4772 release(lock, dsguard, wlock)
4776
4773
4777 @command('incoming|in',
4774 @command('incoming|in',
4778 [('f', 'force', None,
4775 [('f', 'force', None,
4779 _('run even if remote repository is unrelated')),
4776 _('run even if remote repository is unrelated')),
4780 ('n', 'newest-first', None, _('show newest record first')),
4777 ('n', 'newest-first', None, _('show newest record first')),
4781 ('', 'bundle', '',
4778 ('', 'bundle', '',
4782 _('file to store the bundles into'), _('FILE')),
4779 _('file to store the bundles into'), _('FILE')),
4783 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4780 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
4784 ('B', 'bookmarks', False, _("compare bookmarks")),
4781 ('B', 'bookmarks', False, _("compare bookmarks")),
4785 ('b', 'branch', [],
4782 ('b', 'branch', [],
4786 _('a specific branch you would like to pull'), _('BRANCH')),
4783 _('a specific branch you would like to pull'), _('BRANCH')),
4787 ] + logopts + remoteopts + subrepoopts,
4784 ] + logopts + remoteopts + subrepoopts,
4788 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4785 _('[-p] [-n] [-M] [-f] [-r REV]... [--bundle FILENAME] [SOURCE]'))
4789 def incoming(ui, repo, source="default", **opts):
4786 def incoming(ui, repo, source="default", **opts):
4790 """show new changesets found in source
4787 """show new changesets found in source
4791
4788
4792 Show new changesets found in the specified path/URL or the default
4789 Show new changesets found in the specified path/URL or the default
4793 pull location. These are the changesets that would have been pulled
4790 pull location. These are the changesets that would have been pulled
4794 if a pull at the time you issued this command.
4791 if a pull at the time you issued this command.
4795
4792
4796 See pull for valid source format details.
4793 See pull for valid source format details.
4797
4794
4798 .. container:: verbose
4795 .. container:: verbose
4799
4796
4800 With -B/--bookmarks, the result of bookmark comparison between
4797 With -B/--bookmarks, the result of bookmark comparison between
4801 local and remote repositories is displayed. With -v/--verbose,
4798 local and remote repositories is displayed. With -v/--verbose,
4802 status is also displayed for each bookmark like below::
4799 status is also displayed for each bookmark like below::
4803
4800
4804 BM1 01234567890a added
4801 BM1 01234567890a added
4805 BM2 1234567890ab advanced
4802 BM2 1234567890ab advanced
4806 BM3 234567890abc diverged
4803 BM3 234567890abc diverged
4807 BM4 34567890abcd changed
4804 BM4 34567890abcd changed
4808
4805
4809 The action taken locally when pulling depends on the
4806 The action taken locally when pulling depends on the
4810 status of each bookmark:
4807 status of each bookmark:
4811
4808
4812 :``added``: pull will create it
4809 :``added``: pull will create it
4813 :``advanced``: pull will update it
4810 :``advanced``: pull will update it
4814 :``diverged``: pull will create a divergent bookmark
4811 :``diverged``: pull will create a divergent bookmark
4815 :``changed``: result depends on remote changesets
4812 :``changed``: result depends on remote changesets
4816
4813
4817 From the point of view of pulling behavior, bookmark
4814 From the point of view of pulling behavior, bookmark
4818 existing only in the remote repository are treated as ``added``,
4815 existing only in the remote repository are treated as ``added``,
4819 even if it is in fact locally deleted.
4816 even if it is in fact locally deleted.
4820
4817
4821 .. container:: verbose
4818 .. container:: verbose
4822
4819
4823 For remote repository, using --bundle avoids downloading the
4820 For remote repository, using --bundle avoids downloading the
4824 changesets twice if the incoming is followed by a pull.
4821 changesets twice if the incoming is followed by a pull.
4825
4822
4826 Examples:
4823 Examples:
4827
4824
4828 - show incoming changes with patches and full description::
4825 - show incoming changes with patches and full description::
4829
4826
4830 hg incoming -vp
4827 hg incoming -vp
4831
4828
4832 - show incoming changes excluding merges, store a bundle::
4829 - show incoming changes excluding merges, store a bundle::
4833
4830
4834 hg in -vpM --bundle incoming.hg
4831 hg in -vpM --bundle incoming.hg
4835 hg pull incoming.hg
4832 hg pull incoming.hg
4836
4833
4837 - briefly list changes inside a bundle::
4834 - briefly list changes inside a bundle::
4838
4835
4839 hg in changes.hg -T "{desc|firstline}\\n"
4836 hg in changes.hg -T "{desc|firstline}\\n"
4840
4837
4841 Returns 0 if there are incoming changes, 1 otherwise.
4838 Returns 0 if there are incoming changes, 1 otherwise.
4842 """
4839 """
4843 if opts.get('graph'):
4840 if opts.get('graph'):
4844 cmdutil.checkunsupportedgraphflags([], opts)
4841 cmdutil.checkunsupportedgraphflags([], opts)
4845 def display(other, chlist, displayer):
4842 def display(other, chlist, displayer):
4846 revdag = cmdutil.graphrevs(other, chlist, opts)
4843 revdag = cmdutil.graphrevs(other, chlist, opts)
4847 cmdutil.displaygraph(ui, repo, revdag, displayer,
4844 cmdutil.displaygraph(ui, repo, revdag, displayer,
4848 graphmod.asciiedges)
4845 graphmod.asciiedges)
4849
4846
4850 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4847 hg._incoming(display, lambda: 1, ui, repo, source, opts, buffered=True)
4851 return 0
4848 return 0
4852
4849
4853 if opts.get('bundle') and opts.get('subrepos'):
4850 if opts.get('bundle') and opts.get('subrepos'):
4854 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4851 raise error.Abort(_('cannot combine --bundle and --subrepos'))
4855
4852
4856 if opts.get('bookmarks'):
4853 if opts.get('bookmarks'):
4857 source, branches = hg.parseurl(ui.expandpath(source),
4854 source, branches = hg.parseurl(ui.expandpath(source),
4858 opts.get('branch'))
4855 opts.get('branch'))
4859 other = hg.peer(repo, opts, source)
4856 other = hg.peer(repo, opts, source)
4860 if 'bookmarks' not in other.listkeys('namespaces'):
4857 if 'bookmarks' not in other.listkeys('namespaces'):
4861 ui.warn(_("remote doesn't support bookmarks\n"))
4858 ui.warn(_("remote doesn't support bookmarks\n"))
4862 return 0
4859 return 0
4863 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4860 ui.status(_('comparing with %s\n') % util.hidepassword(source))
4864 return bookmarks.incoming(ui, repo, other)
4861 return bookmarks.incoming(ui, repo, other)
4865
4862
4866 repo._subtoppath = ui.expandpath(source)
4863 repo._subtoppath = ui.expandpath(source)
4867 try:
4864 try:
4868 return hg.incoming(ui, repo, source, opts)
4865 return hg.incoming(ui, repo, source, opts)
4869 finally:
4866 finally:
4870 del repo._subtoppath
4867 del repo._subtoppath
4871
4868
4872
4869
4873 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4870 @command('^init', remoteopts, _('[-e CMD] [--remotecmd CMD] [DEST]'),
4874 norepo=True)
4871 norepo=True)
4875 def init(ui, dest=".", **opts):
4872 def init(ui, dest=".", **opts):
4876 """create a new repository in the given directory
4873 """create a new repository in the given directory
4877
4874
4878 Initialize a new repository in the given directory. If the given
4875 Initialize a new repository in the given directory. If the given
4879 directory does not exist, it will be created.
4876 directory does not exist, it will be created.
4880
4877
4881 If no directory is given, the current directory is used.
4878 If no directory is given, the current directory is used.
4882
4879
4883 It is possible to specify an ``ssh://`` URL as the destination.
4880 It is possible to specify an ``ssh://`` URL as the destination.
4884 See :hg:`help urls` for more information.
4881 See :hg:`help urls` for more information.
4885
4882
4886 Returns 0 on success.
4883 Returns 0 on success.
4887 """
4884 """
4888 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4885 hg.peer(ui, opts, ui.expandpath(dest), create=True)
4889
4886
4890 @command('locate',
4887 @command('locate',
4891 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4888 [('r', 'rev', '', _('search the repository as it is in REV'), _('REV')),
4892 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4889 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
4893 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4890 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
4894 ] + walkopts,
4891 ] + walkopts,
4895 _('[OPTION]... [PATTERN]...'))
4892 _('[OPTION]... [PATTERN]...'))
4896 def locate(ui, repo, *pats, **opts):
4893 def locate(ui, repo, *pats, **opts):
4897 """locate files matching specific patterns (DEPRECATED)
4894 """locate files matching specific patterns (DEPRECATED)
4898
4895
4899 Print files under Mercurial control in the working directory whose
4896 Print files under Mercurial control in the working directory whose
4900 names match the given patterns.
4897 names match the given patterns.
4901
4898
4902 By default, this command searches all directories in the working
4899 By default, this command searches all directories in the working
4903 directory. To search just the current directory and its
4900 directory. To search just the current directory and its
4904 subdirectories, use "--include .".
4901 subdirectories, use "--include .".
4905
4902
4906 If no patterns are given to match, this command prints the names
4903 If no patterns are given to match, this command prints the names
4907 of all files under Mercurial control in the working directory.
4904 of all files under Mercurial control in the working directory.
4908
4905
4909 If you want to feed the output of this command into the "xargs"
4906 If you want to feed the output of this command into the "xargs"
4910 command, use the -0 option to both this command and "xargs". This
4907 command, use the -0 option to both this command and "xargs". This
4911 will avoid the problem of "xargs" treating single filenames that
4908 will avoid the problem of "xargs" treating single filenames that
4912 contain whitespace as multiple filenames.
4909 contain whitespace as multiple filenames.
4913
4910
4914 See :hg:`help files` for a more versatile command.
4911 See :hg:`help files` for a more versatile command.
4915
4912
4916 Returns 0 if a match is found, 1 otherwise.
4913 Returns 0 if a match is found, 1 otherwise.
4917 """
4914 """
4918 if opts.get('print0'):
4915 if opts.get('print0'):
4919 end = '\0'
4916 end = '\0'
4920 else:
4917 else:
4921 end = '\n'
4918 end = '\n'
4922 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4919 rev = scmutil.revsingle(repo, opts.get('rev'), None).node()
4923
4920
4924 ret = 1
4921 ret = 1
4925 ctx = repo[rev]
4922 ctx = repo[rev]
4926 m = scmutil.match(ctx, pats, opts, default='relglob',
4923 m = scmutil.match(ctx, pats, opts, default='relglob',
4927 badfn=lambda x, y: False)
4924 badfn=lambda x, y: False)
4928
4925
4929 for abs in ctx.matches(m):
4926 for abs in ctx.matches(m):
4930 if opts.get('fullpath'):
4927 if opts.get('fullpath'):
4931 ui.write(repo.wjoin(abs), end)
4928 ui.write(repo.wjoin(abs), end)
4932 else:
4929 else:
4933 ui.write(((pats and m.rel(abs)) or abs), end)
4930 ui.write(((pats and m.rel(abs)) or abs), end)
4934 ret = 0
4931 ret = 0
4935
4932
4936 return ret
4933 return ret
4937
4934
4938 @command('^log|history',
4935 @command('^log|history',
4939 [('f', 'follow', None,
4936 [('f', 'follow', None,
4940 _('follow changeset history, or file history across copies and renames')),
4937 _('follow changeset history, or file history across copies and renames')),
4941 ('', 'follow-first', None,
4938 ('', 'follow-first', None,
4942 _('only follow the first parent of merge changesets (DEPRECATED)')),
4939 _('only follow the first parent of merge changesets (DEPRECATED)')),
4943 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4940 ('d', 'date', '', _('show revisions matching date spec'), _('DATE')),
4944 ('C', 'copies', None, _('show copied files')),
4941 ('C', 'copies', None, _('show copied files')),
4945 ('k', 'keyword', [],
4942 ('k', 'keyword', [],
4946 _('do case-insensitive search for a given text'), _('TEXT')),
4943 _('do case-insensitive search for a given text'), _('TEXT')),
4947 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4944 ('r', 'rev', [], _('show the specified revision or revset'), _('REV')),
4948 ('', 'removed', None, _('include revisions where files were removed')),
4945 ('', 'removed', None, _('include revisions where files were removed')),
4949 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4946 ('m', 'only-merges', None, _('show only merges (DEPRECATED)')),
4950 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4947 ('u', 'user', [], _('revisions committed by user'), _('USER')),
4951 ('', 'only-branch', [],
4948 ('', 'only-branch', [],
4952 _('show only changesets within the given named branch (DEPRECATED)'),
4949 _('show only changesets within the given named branch (DEPRECATED)'),
4953 _('BRANCH')),
4950 _('BRANCH')),
4954 ('b', 'branch', [],
4951 ('b', 'branch', [],
4955 _('show changesets within the given named branch'), _('BRANCH')),
4952 _('show changesets within the given named branch'), _('BRANCH')),
4956 ('P', 'prune', [],
4953 ('P', 'prune', [],
4957 _('do not display revision or any of its ancestors'), _('REV')),
4954 _('do not display revision or any of its ancestors'), _('REV')),
4958 ] + logopts + walkopts,
4955 ] + logopts + walkopts,
4959 _('[OPTION]... [FILE]'),
4956 _('[OPTION]... [FILE]'),
4960 inferrepo=True)
4957 inferrepo=True)
4961 def log(ui, repo, *pats, **opts):
4958 def log(ui, repo, *pats, **opts):
4962 """show revision history of entire repository or files
4959 """show revision history of entire repository or files
4963
4960
4964 Print the revision history of the specified files or the entire
4961 Print the revision history of the specified files or the entire
4965 project.
4962 project.
4966
4963
4967 If no revision range is specified, the default is ``tip:0`` unless
4964 If no revision range is specified, the default is ``tip:0`` unless
4968 --follow is set, in which case the working directory parent is
4965 --follow is set, in which case the working directory parent is
4969 used as the starting revision.
4966 used as the starting revision.
4970
4967
4971 File history is shown without following rename or copy history of
4968 File history is shown without following rename or copy history of
4972 files. Use -f/--follow with a filename to follow history across
4969 files. Use -f/--follow with a filename to follow history across
4973 renames and copies. --follow without a filename will only show
4970 renames and copies. --follow without a filename will only show
4974 ancestors or descendants of the starting revision.
4971 ancestors or descendants of the starting revision.
4975
4972
4976 By default this command prints revision number and changeset id,
4973 By default this command prints revision number and changeset id,
4977 tags, non-trivial parents, user, date and time, and a summary for
4974 tags, non-trivial parents, user, date and time, and a summary for
4978 each commit. When the -v/--verbose switch is used, the list of
4975 each commit. When the -v/--verbose switch is used, the list of
4979 changed files and full commit message are shown.
4976 changed files and full commit message are shown.
4980
4977
4981 With --graph the revisions are shown as an ASCII art DAG with the most
4978 With --graph the revisions are shown as an ASCII art DAG with the most
4982 recent changeset at the top.
4979 recent changeset at the top.
4983 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4980 'o' is a changeset, '@' is a working directory parent, 'x' is obsolete,
4984 and '+' represents a fork where the changeset from the lines below is a
4981 and '+' represents a fork where the changeset from the lines below is a
4985 parent of the 'o' merge on the same line.
4982 parent of the 'o' merge on the same line.
4986
4983
4987 .. note::
4984 .. note::
4988
4985
4989 :hg:`log --patch` may generate unexpected diff output for merge
4986 :hg:`log --patch` may generate unexpected diff output for merge
4990 changesets, as it will only compare the merge changeset against
4987 changesets, as it will only compare the merge changeset against
4991 its first parent. Also, only files different from BOTH parents
4988 its first parent. Also, only files different from BOTH parents
4992 will appear in files:.
4989 will appear in files:.
4993
4990
4994 .. note::
4991 .. note::
4995
4992
4996 For performance reasons, :hg:`log FILE` may omit duplicate changes
4993 For performance reasons, :hg:`log FILE` may omit duplicate changes
4997 made on branches and will not show removals or mode changes. To
4994 made on branches and will not show removals or mode changes. To
4998 see all such changes, use the --removed switch.
4995 see all such changes, use the --removed switch.
4999
4996
5000 .. container:: verbose
4997 .. container:: verbose
5001
4998
5002 Some examples:
4999 Some examples:
5003
5000
5004 - changesets with full descriptions and file lists::
5001 - changesets with full descriptions and file lists::
5005
5002
5006 hg log -v
5003 hg log -v
5007
5004
5008 - changesets ancestral to the working directory::
5005 - changesets ancestral to the working directory::
5009
5006
5010 hg log -f
5007 hg log -f
5011
5008
5012 - last 10 commits on the current branch::
5009 - last 10 commits on the current branch::
5013
5010
5014 hg log -l 10 -b .
5011 hg log -l 10 -b .
5015
5012
5016 - changesets showing all modifications of a file, including removals::
5013 - changesets showing all modifications of a file, including removals::
5017
5014
5018 hg log --removed file.c
5015 hg log --removed file.c
5019
5016
5020 - all changesets that touch a directory, with diffs, excluding merges::
5017 - all changesets that touch a directory, with diffs, excluding merges::
5021
5018
5022 hg log -Mp lib/
5019 hg log -Mp lib/
5023
5020
5024 - all revision numbers that match a keyword::
5021 - all revision numbers that match a keyword::
5025
5022
5026 hg log -k bug --template "{rev}\\n"
5023 hg log -k bug --template "{rev}\\n"
5027
5024
5028 - the full hash identifier of the working directory parent::
5025 - the full hash identifier of the working directory parent::
5029
5026
5030 hg log -r . --template "{node}\\n"
5027 hg log -r . --template "{node}\\n"
5031
5028
5032 - list available log templates::
5029 - list available log templates::
5033
5030
5034 hg log -T list
5031 hg log -T list
5035
5032
5036 - check if a given changeset is included in a tagged release::
5033 - check if a given changeset is included in a tagged release::
5037
5034
5038 hg log -r "a21ccf and ancestor(1.9)"
5035 hg log -r "a21ccf and ancestor(1.9)"
5039
5036
5040 - find all changesets by some user in a date range::
5037 - find all changesets by some user in a date range::
5041
5038
5042 hg log -k alice -d "may 2008 to jul 2008"
5039 hg log -k alice -d "may 2008 to jul 2008"
5043
5040
5044 - summary of all changesets after the last tag::
5041 - summary of all changesets after the last tag::
5045
5042
5046 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5043 hg log -r "last(tagged())::" --template "{desc|firstline}\\n"
5047
5044
5048 See :hg:`help dates` for a list of formats valid for -d/--date.
5045 See :hg:`help dates` for a list of formats valid for -d/--date.
5049
5046
5050 See :hg:`help revisions` and :hg:`help revsets` for more about
5047 See :hg:`help revisions` and :hg:`help revsets` for more about
5051 specifying and ordering revisions.
5048 specifying and ordering revisions.
5052
5049
5053 See :hg:`help templates` for more about pre-packaged styles and
5050 See :hg:`help templates` for more about pre-packaged styles and
5054 specifying custom templates.
5051 specifying custom templates.
5055
5052
5056 Returns 0 on success.
5053 Returns 0 on success.
5057
5054
5058 """
5055 """
5059 if opts.get('follow') and opts.get('rev'):
5056 if opts.get('follow') and opts.get('rev'):
5060 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5057 opts['rev'] = [revset.formatspec('reverse(::%lr)', opts.get('rev'))]
5061 del opts['follow']
5058 del opts['follow']
5062
5059
5063 if opts.get('graph'):
5060 if opts.get('graph'):
5064 return cmdutil.graphlog(ui, repo, *pats, **opts)
5061 return cmdutil.graphlog(ui, repo, *pats, **opts)
5065
5062
5066 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5063 revs, expr, filematcher = cmdutil.getlogrevs(repo, pats, opts)
5067 limit = cmdutil.loglimit(opts)
5064 limit = cmdutil.loglimit(opts)
5068 count = 0
5065 count = 0
5069
5066
5070 getrenamed = None
5067 getrenamed = None
5071 if opts.get('copies'):
5068 if opts.get('copies'):
5072 endrev = None
5069 endrev = None
5073 if opts.get('rev'):
5070 if opts.get('rev'):
5074 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5071 endrev = scmutil.revrange(repo, opts.get('rev')).max() + 1
5075 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5072 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
5076
5073
5077 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5074 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5078 for rev in revs:
5075 for rev in revs:
5079 if count == limit:
5076 if count == limit:
5080 break
5077 break
5081 ctx = repo[rev]
5078 ctx = repo[rev]
5082 copies = None
5079 copies = None
5083 if getrenamed is not None and rev:
5080 if getrenamed is not None and rev:
5084 copies = []
5081 copies = []
5085 for fn in ctx.files():
5082 for fn in ctx.files():
5086 rename = getrenamed(fn, rev)
5083 rename = getrenamed(fn, rev)
5087 if rename:
5084 if rename:
5088 copies.append((fn, rename[0]))
5085 copies.append((fn, rename[0]))
5089 if filematcher:
5086 if filematcher:
5090 revmatchfn = filematcher(ctx.rev())
5087 revmatchfn = filematcher(ctx.rev())
5091 else:
5088 else:
5092 revmatchfn = None
5089 revmatchfn = None
5093 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5090 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
5094 if displayer.flush(ctx):
5091 if displayer.flush(ctx):
5095 count += 1
5092 count += 1
5096
5093
5097 displayer.close()
5094 displayer.close()
5098
5095
5099 @command('manifest',
5096 @command('manifest',
5100 [('r', 'rev', '', _('revision to display'), _('REV')),
5097 [('r', 'rev', '', _('revision to display'), _('REV')),
5101 ('', 'all', False, _("list files from all revisions"))]
5098 ('', 'all', False, _("list files from all revisions"))]
5102 + formatteropts,
5099 + formatteropts,
5103 _('[-r REV]'))
5100 _('[-r REV]'))
5104 def manifest(ui, repo, node=None, rev=None, **opts):
5101 def manifest(ui, repo, node=None, rev=None, **opts):
5105 """output the current or given revision of the project manifest
5102 """output the current or given revision of the project manifest
5106
5103
5107 Print a list of version controlled files for the given revision.
5104 Print a list of version controlled files for the given revision.
5108 If no revision is given, the first parent of the working directory
5105 If no revision is given, the first parent of the working directory
5109 is used, or the null revision if no revision is checked out.
5106 is used, or the null revision if no revision is checked out.
5110
5107
5111 With -v, print file permissions, symlink and executable bits.
5108 With -v, print file permissions, symlink and executable bits.
5112 With --debug, print file revision hashes.
5109 With --debug, print file revision hashes.
5113
5110
5114 If option --all is specified, the list of all files from all revisions
5111 If option --all is specified, the list of all files from all revisions
5115 is printed. This includes deleted and renamed files.
5112 is printed. This includes deleted and renamed files.
5116
5113
5117 Returns 0 on success.
5114 Returns 0 on success.
5118 """
5115 """
5119
5116
5120 fm = ui.formatter('manifest', opts)
5117 fm = ui.formatter('manifest', opts)
5121
5118
5122 if opts.get('all'):
5119 if opts.get('all'):
5123 if rev or node:
5120 if rev or node:
5124 raise error.Abort(_("can't specify a revision with --all"))
5121 raise error.Abort(_("can't specify a revision with --all"))
5125
5122
5126 res = []
5123 res = []
5127 prefix = "data/"
5124 prefix = "data/"
5128 suffix = ".i"
5125 suffix = ".i"
5129 plen = len(prefix)
5126 plen = len(prefix)
5130 slen = len(suffix)
5127 slen = len(suffix)
5131 lock = repo.lock()
5128 lock = repo.lock()
5132 try:
5129 try:
5133 for fn, b, size in repo.store.datafiles():
5130 for fn, b, size in repo.store.datafiles():
5134 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5131 if size != 0 and fn[-slen:] == suffix and fn[:plen] == prefix:
5135 res.append(fn[plen:-slen])
5132 res.append(fn[plen:-slen])
5136 finally:
5133 finally:
5137 lock.release()
5134 lock.release()
5138 for f in res:
5135 for f in res:
5139 fm.startitem()
5136 fm.startitem()
5140 fm.write("path", '%s\n', f)
5137 fm.write("path", '%s\n', f)
5141 fm.end()
5138 fm.end()
5142 return
5139 return
5143
5140
5144 if rev and node:
5141 if rev and node:
5145 raise error.Abort(_("please specify just one revision"))
5142 raise error.Abort(_("please specify just one revision"))
5146
5143
5147 if not node:
5144 if not node:
5148 node = rev
5145 node = rev
5149
5146
5150 char = {'l': '@', 'x': '*', '': ''}
5147 char = {'l': '@', 'x': '*', '': ''}
5151 mode = {'l': '644', 'x': '755', '': '644'}
5148 mode = {'l': '644', 'x': '755', '': '644'}
5152 ctx = scmutil.revsingle(repo, node)
5149 ctx = scmutil.revsingle(repo, node)
5153 mf = ctx.manifest()
5150 mf = ctx.manifest()
5154 for f in ctx:
5151 for f in ctx:
5155 fm.startitem()
5152 fm.startitem()
5156 fl = ctx[f].flags()
5153 fl = ctx[f].flags()
5157 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5154 fm.condwrite(ui.debugflag, 'hash', '%s ', hex(mf[f]))
5158 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5155 fm.condwrite(ui.verbose, 'mode type', '%s %1s ', mode[fl], char[fl])
5159 fm.write('path', '%s\n', f)
5156 fm.write('path', '%s\n', f)
5160 fm.end()
5157 fm.end()
5161
5158
5162 @command('^merge',
5159 @command('^merge',
5163 [('f', 'force', None,
5160 [('f', 'force', None,
5164 _('force a merge including outstanding changes (DEPRECATED)')),
5161 _('force a merge including outstanding changes (DEPRECATED)')),
5165 ('r', 'rev', '', _('revision to merge'), _('REV')),
5162 ('r', 'rev', '', _('revision to merge'), _('REV')),
5166 ('P', 'preview', None,
5163 ('P', 'preview', None,
5167 _('review revisions to merge (no merge is performed)'))
5164 _('review revisions to merge (no merge is performed)'))
5168 ] + mergetoolopts,
5165 ] + mergetoolopts,
5169 _('[-P] [-f] [[-r] REV]'))
5166 _('[-P] [-f] [[-r] REV]'))
5170 def merge(ui, repo, node=None, **opts):
5167 def merge(ui, repo, node=None, **opts):
5171 """merge another revision into working directory
5168 """merge another revision into working directory
5172
5169
5173 The current working directory is updated with all changes made in
5170 The current working directory is updated with all changes made in
5174 the requested revision since the last common predecessor revision.
5171 the requested revision since the last common predecessor revision.
5175
5172
5176 Files that changed between either parent are marked as changed for
5173 Files that changed between either parent are marked as changed for
5177 the next commit and a commit must be performed before any further
5174 the next commit and a commit must be performed before any further
5178 updates to the repository are allowed. The next commit will have
5175 updates to the repository are allowed. The next commit will have
5179 two parents.
5176 two parents.
5180
5177
5181 ``--tool`` can be used to specify the merge tool used for file
5178 ``--tool`` can be used to specify the merge tool used for file
5182 merges. It overrides the HGMERGE environment variable and your
5179 merges. It overrides the HGMERGE environment variable and your
5183 configuration files. See :hg:`help merge-tools` for options.
5180 configuration files. See :hg:`help merge-tools` for options.
5184
5181
5185 If no revision is specified, the working directory's parent is a
5182 If no revision is specified, the working directory's parent is a
5186 head revision, and the current branch contains exactly one other
5183 head revision, and the current branch contains exactly one other
5187 head, the other head is merged with by default. Otherwise, an
5184 head, the other head is merged with by default. Otherwise, an
5188 explicit revision with which to merge with must be provided.
5185 explicit revision with which to merge with must be provided.
5189
5186
5190 See :hg:`help resolve` for information on handling file conflicts.
5187 See :hg:`help resolve` for information on handling file conflicts.
5191
5188
5192 To undo an uncommitted merge, use :hg:`update --clean .` which
5189 To undo an uncommitted merge, use :hg:`update --clean .` which
5193 will check out a clean copy of the original merge parent, losing
5190 will check out a clean copy of the original merge parent, losing
5194 all changes.
5191 all changes.
5195
5192
5196 Returns 0 on success, 1 if there are unresolved files.
5193 Returns 0 on success, 1 if there are unresolved files.
5197 """
5194 """
5198
5195
5199 if opts.get('rev') and node:
5196 if opts.get('rev') and node:
5200 raise error.Abort(_("please specify just one revision"))
5197 raise error.Abort(_("please specify just one revision"))
5201 if not node:
5198 if not node:
5202 node = opts.get('rev')
5199 node = opts.get('rev')
5203
5200
5204 if node:
5201 if node:
5205 node = scmutil.revsingle(repo, node).node()
5202 node = scmutil.revsingle(repo, node).node()
5206
5203
5207 if not node:
5204 if not node:
5208 node = repo[destutil.destmerge(repo)].node()
5205 node = repo[destutil.destmerge(repo)].node()
5209
5206
5210 if opts.get('preview'):
5207 if opts.get('preview'):
5211 # find nodes that are ancestors of p2 but not of p1
5208 # find nodes that are ancestors of p2 but not of p1
5212 p1 = repo.lookup('.')
5209 p1 = repo.lookup('.')
5213 p2 = repo.lookup(node)
5210 p2 = repo.lookup(node)
5214 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5211 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
5215
5212
5216 displayer = cmdutil.show_changeset(ui, repo, opts)
5213 displayer = cmdutil.show_changeset(ui, repo, opts)
5217 for node in nodes:
5214 for node in nodes:
5218 displayer.show(repo[node])
5215 displayer.show(repo[node])
5219 displayer.close()
5216 displayer.close()
5220 return 0
5217 return 0
5221
5218
5222 try:
5219 try:
5223 # ui.forcemerge is an internal variable, do not document
5220 # ui.forcemerge is an internal variable, do not document
5224 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5221 repo.ui.setconfig('ui', 'forcemerge', opts.get('tool', ''), 'merge')
5225 return hg.merge(repo, node, force=opts.get('force'))
5222 return hg.merge(repo, node, force=opts.get('force'))
5226 finally:
5223 finally:
5227 ui.setconfig('ui', 'forcemerge', '', 'merge')
5224 ui.setconfig('ui', 'forcemerge', '', 'merge')
5228
5225
5229 @command('outgoing|out',
5226 @command('outgoing|out',
5230 [('f', 'force', None, _('run even when the destination is unrelated')),
5227 [('f', 'force', None, _('run even when the destination is unrelated')),
5231 ('r', 'rev', [],
5228 ('r', 'rev', [],
5232 _('a changeset intended to be included in the destination'), _('REV')),
5229 _('a changeset intended to be included in the destination'), _('REV')),
5233 ('n', 'newest-first', None, _('show newest record first')),
5230 ('n', 'newest-first', None, _('show newest record first')),
5234 ('B', 'bookmarks', False, _('compare bookmarks')),
5231 ('B', 'bookmarks', False, _('compare bookmarks')),
5235 ('b', 'branch', [], _('a specific branch you would like to push'),
5232 ('b', 'branch', [], _('a specific branch you would like to push'),
5236 _('BRANCH')),
5233 _('BRANCH')),
5237 ] + logopts + remoteopts + subrepoopts,
5234 ] + logopts + remoteopts + subrepoopts,
5238 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5235 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]'))
5239 def outgoing(ui, repo, dest=None, **opts):
5236 def outgoing(ui, repo, dest=None, **opts):
5240 """show changesets not found in the destination
5237 """show changesets not found in the destination
5241
5238
5242 Show changesets not found in the specified destination repository
5239 Show changesets not found in the specified destination repository
5243 or the default push location. These are the changesets that would
5240 or the default push location. These are the changesets that would
5244 be pushed if a push was requested.
5241 be pushed if a push was requested.
5245
5242
5246 See pull for details of valid destination formats.
5243 See pull for details of valid destination formats.
5247
5244
5248 .. container:: verbose
5245 .. container:: verbose
5249
5246
5250 With -B/--bookmarks, the result of bookmark comparison between
5247 With -B/--bookmarks, the result of bookmark comparison between
5251 local and remote repositories is displayed. With -v/--verbose,
5248 local and remote repositories is displayed. With -v/--verbose,
5252 status is also displayed for each bookmark like below::
5249 status is also displayed for each bookmark like below::
5253
5250
5254 BM1 01234567890a added
5251 BM1 01234567890a added
5255 BM2 deleted
5252 BM2 deleted
5256 BM3 234567890abc advanced
5253 BM3 234567890abc advanced
5257 BM4 34567890abcd diverged
5254 BM4 34567890abcd diverged
5258 BM5 4567890abcde changed
5255 BM5 4567890abcde changed
5259
5256
5260 The action taken when pushing depends on the
5257 The action taken when pushing depends on the
5261 status of each bookmark:
5258 status of each bookmark:
5262
5259
5263 :``added``: push with ``-B`` will create it
5260 :``added``: push with ``-B`` will create it
5264 :``deleted``: push with ``-B`` will delete it
5261 :``deleted``: push with ``-B`` will delete it
5265 :``advanced``: push will update it
5262 :``advanced``: push will update it
5266 :``diverged``: push with ``-B`` will update it
5263 :``diverged``: push with ``-B`` will update it
5267 :``changed``: push with ``-B`` will update it
5264 :``changed``: push with ``-B`` will update it
5268
5265
5269 From the point of view of pushing behavior, bookmarks
5266 From the point of view of pushing behavior, bookmarks
5270 existing only in the remote repository are treated as
5267 existing only in the remote repository are treated as
5271 ``deleted``, even if it is in fact added remotely.
5268 ``deleted``, even if it is in fact added remotely.
5272
5269
5273 Returns 0 if there are outgoing changes, 1 otherwise.
5270 Returns 0 if there are outgoing changes, 1 otherwise.
5274 """
5271 """
5275 if opts.get('graph'):
5272 if opts.get('graph'):
5276 cmdutil.checkunsupportedgraphflags([], opts)
5273 cmdutil.checkunsupportedgraphflags([], opts)
5277 o, other = hg._outgoing(ui, repo, dest, opts)
5274 o, other = hg._outgoing(ui, repo, dest, opts)
5278 if not o:
5275 if not o:
5279 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5276 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5280 return
5277 return
5281
5278
5282 revdag = cmdutil.graphrevs(repo, o, opts)
5279 revdag = cmdutil.graphrevs(repo, o, opts)
5283 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5280 displayer = cmdutil.show_changeset(ui, repo, opts, buffered=True)
5284 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5281 cmdutil.displaygraph(ui, repo, revdag, displayer, graphmod.asciiedges)
5285 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5282 cmdutil.outgoinghooks(ui, repo, other, opts, o)
5286 return 0
5283 return 0
5287
5284
5288 if opts.get('bookmarks'):
5285 if opts.get('bookmarks'):
5289 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5286 dest = ui.expandpath(dest or 'default-push', dest or 'default')
5290 dest, branches = hg.parseurl(dest, opts.get('branch'))
5287 dest, branches = hg.parseurl(dest, opts.get('branch'))
5291 other = hg.peer(repo, opts, dest)
5288 other = hg.peer(repo, opts, dest)
5292 if 'bookmarks' not in other.listkeys('namespaces'):
5289 if 'bookmarks' not in other.listkeys('namespaces'):
5293 ui.warn(_("remote doesn't support bookmarks\n"))
5290 ui.warn(_("remote doesn't support bookmarks\n"))
5294 return 0
5291 return 0
5295 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5292 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
5296 return bookmarks.outgoing(ui, repo, other)
5293 return bookmarks.outgoing(ui, repo, other)
5297
5294
5298 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5295 repo._subtoppath = ui.expandpath(dest or 'default-push', dest or 'default')
5299 try:
5296 try:
5300 return hg.outgoing(ui, repo, dest, opts)
5297 return hg.outgoing(ui, repo, dest, opts)
5301 finally:
5298 finally:
5302 del repo._subtoppath
5299 del repo._subtoppath
5303
5300
5304 @command('parents',
5301 @command('parents',
5305 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5302 [('r', 'rev', '', _('show parents of the specified revision'), _('REV')),
5306 ] + templateopts,
5303 ] + templateopts,
5307 _('[-r REV] [FILE]'),
5304 _('[-r REV] [FILE]'),
5308 inferrepo=True)
5305 inferrepo=True)
5309 def parents(ui, repo, file_=None, **opts):
5306 def parents(ui, repo, file_=None, **opts):
5310 """show the parents of the working directory or revision (DEPRECATED)
5307 """show the parents of the working directory or revision (DEPRECATED)
5311
5308
5312 Print the working directory's parent revisions. If a revision is
5309 Print the working directory's parent revisions. If a revision is
5313 given via -r/--rev, the parent of that revision will be printed.
5310 given via -r/--rev, the parent of that revision will be printed.
5314 If a file argument is given, the revision in which the file was
5311 If a file argument is given, the revision in which the file was
5315 last changed (before the working directory revision or the
5312 last changed (before the working directory revision or the
5316 argument to --rev if given) is printed.
5313 argument to --rev if given) is printed.
5317
5314
5318 This command is equivalent to::
5315 This command is equivalent to::
5319
5316
5320 hg log -r "p1()+p2()" or
5317 hg log -r "p1()+p2()" or
5321 hg log -r "p1(REV)+p2(REV)" or
5318 hg log -r "p1(REV)+p2(REV)" or
5322 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5319 hg log -r "max(::p1() and file(FILE))+max(::p2() and file(FILE))" or
5323 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5320 hg log -r "max(::p1(REV) and file(FILE))+max(::p2(REV) and file(FILE))"
5324
5321
5325 See :hg:`summary` and :hg:`help revsets` for related information.
5322 See :hg:`summary` and :hg:`help revsets` for related information.
5326
5323
5327 Returns 0 on success.
5324 Returns 0 on success.
5328 """
5325 """
5329
5326
5330 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5327 ctx = scmutil.revsingle(repo, opts.get('rev'), None)
5331
5328
5332 if file_:
5329 if file_:
5333 m = scmutil.match(ctx, (file_,), opts)
5330 m = scmutil.match(ctx, (file_,), opts)
5334 if m.anypats() or len(m.files()) != 1:
5331 if m.anypats() or len(m.files()) != 1:
5335 raise error.Abort(_('can only specify an explicit filename'))
5332 raise error.Abort(_('can only specify an explicit filename'))
5336 file_ = m.files()[0]
5333 file_ = m.files()[0]
5337 filenodes = []
5334 filenodes = []
5338 for cp in ctx.parents():
5335 for cp in ctx.parents():
5339 if not cp:
5336 if not cp:
5340 continue
5337 continue
5341 try:
5338 try:
5342 filenodes.append(cp.filenode(file_))
5339 filenodes.append(cp.filenode(file_))
5343 except error.LookupError:
5340 except error.LookupError:
5344 pass
5341 pass
5345 if not filenodes:
5342 if not filenodes:
5346 raise error.Abort(_("'%s' not found in manifest!") % file_)
5343 raise error.Abort(_("'%s' not found in manifest!") % file_)
5347 p = []
5344 p = []
5348 for fn in filenodes:
5345 for fn in filenodes:
5349 fctx = repo.filectx(file_, fileid=fn)
5346 fctx = repo.filectx(file_, fileid=fn)
5350 p.append(fctx.node())
5347 p.append(fctx.node())
5351 else:
5348 else:
5352 p = [cp.node() for cp in ctx.parents()]
5349 p = [cp.node() for cp in ctx.parents()]
5353
5350
5354 displayer = cmdutil.show_changeset(ui, repo, opts)
5351 displayer = cmdutil.show_changeset(ui, repo, opts)
5355 for n in p:
5352 for n in p:
5356 if n != nullid:
5353 if n != nullid:
5357 displayer.show(repo[n])
5354 displayer.show(repo[n])
5358 displayer.close()
5355 displayer.close()
5359
5356
5360 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5357 @command('paths', formatteropts, _('[NAME]'), optionalrepo=True)
5361 def paths(ui, repo, search=None, **opts):
5358 def paths(ui, repo, search=None, **opts):
5362 """show aliases for remote repositories
5359 """show aliases for remote repositories
5363
5360
5364 Show definition of symbolic path name NAME. If no name is given,
5361 Show definition of symbolic path name NAME. If no name is given,
5365 show definition of all available names.
5362 show definition of all available names.
5366
5363
5367 Option -q/--quiet suppresses all output when searching for NAME
5364 Option -q/--quiet suppresses all output when searching for NAME
5368 and shows only the path names when listing all definitions.
5365 and shows only the path names when listing all definitions.
5369
5366
5370 Path names are defined in the [paths] section of your
5367 Path names are defined in the [paths] section of your
5371 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5368 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
5372 repository, ``.hg/hgrc`` is used, too.
5369 repository, ``.hg/hgrc`` is used, too.
5373
5370
5374 The path names ``default`` and ``default-push`` have a special
5371 The path names ``default`` and ``default-push`` have a special
5375 meaning. When performing a push or pull operation, they are used
5372 meaning. When performing a push or pull operation, they are used
5376 as fallbacks if no location is specified on the command-line.
5373 as fallbacks if no location is specified on the command-line.
5377 When ``default-push`` is set, it will be used for push and
5374 When ``default-push`` is set, it will be used for push and
5378 ``default`` will be used for pull; otherwise ``default`` is used
5375 ``default`` will be used for pull; otherwise ``default`` is used
5379 as the fallback for both. When cloning a repository, the clone
5376 as the fallback for both. When cloning a repository, the clone
5380 source is written as ``default`` in ``.hg/hgrc``.
5377 source is written as ``default`` in ``.hg/hgrc``.
5381
5378
5382 .. note::
5379 .. note::
5383
5380
5384 ``default`` and ``default-push`` apply to all inbound (e.g.
5381 ``default`` and ``default-push`` apply to all inbound (e.g.
5385 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5382 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email`
5386 and :hg:`bundle`) operations.
5383 and :hg:`bundle`) operations.
5387
5384
5388 See :hg:`help urls` for more information.
5385 See :hg:`help urls` for more information.
5389
5386
5390 Returns 0 on success.
5387 Returns 0 on success.
5391 """
5388 """
5392 if search:
5389 if search:
5393 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5390 pathitems = [(name, path) for name, path in ui.paths.iteritems()
5394 if name == search]
5391 if name == search]
5395 else:
5392 else:
5396 pathitems = sorted(ui.paths.iteritems())
5393 pathitems = sorted(ui.paths.iteritems())
5397
5394
5398 fm = ui.formatter('paths', opts)
5395 fm = ui.formatter('paths', opts)
5399 if fm:
5396 if fm:
5400 hidepassword = str
5397 hidepassword = str
5401 else:
5398 else:
5402 hidepassword = util.hidepassword
5399 hidepassword = util.hidepassword
5403 if ui.quiet:
5400 if ui.quiet:
5404 namefmt = '%s\n'
5401 namefmt = '%s\n'
5405 else:
5402 else:
5406 namefmt = '%s = '
5403 namefmt = '%s = '
5407 showsubopts = not search and not ui.quiet
5404 showsubopts = not search and not ui.quiet
5408
5405
5409 for name, path in pathitems:
5406 for name, path in pathitems:
5410 fm.startitem()
5407 fm.startitem()
5411 fm.condwrite(not search, 'name', namefmt, name)
5408 fm.condwrite(not search, 'name', namefmt, name)
5412 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5409 fm.condwrite(not ui.quiet, 'url', '%s\n', hidepassword(path.rawloc))
5413 for subopt, value in sorted(path.suboptions.items()):
5410 for subopt, value in sorted(path.suboptions.items()):
5414 assert subopt not in ('name', 'url')
5411 assert subopt not in ('name', 'url')
5415 if showsubopts:
5412 if showsubopts:
5416 fm.plain('%s:%s = ' % (name, subopt))
5413 fm.plain('%s:%s = ' % (name, subopt))
5417 fm.condwrite(showsubopts, subopt, '%s\n', value)
5414 fm.condwrite(showsubopts, subopt, '%s\n', value)
5418
5415
5419 fm.end()
5416 fm.end()
5420
5417
5421 if search and not pathitems:
5418 if search and not pathitems:
5422 if not ui.quiet:
5419 if not ui.quiet:
5423 ui.warn(_("not found!\n"))
5420 ui.warn(_("not found!\n"))
5424 return 1
5421 return 1
5425 else:
5422 else:
5426 return 0
5423 return 0
5427
5424
5428 @command('phase',
5425 @command('phase',
5429 [('p', 'public', False, _('set changeset phase to public')),
5426 [('p', 'public', False, _('set changeset phase to public')),
5430 ('d', 'draft', False, _('set changeset phase to draft')),
5427 ('d', 'draft', False, _('set changeset phase to draft')),
5431 ('s', 'secret', False, _('set changeset phase to secret')),
5428 ('s', 'secret', False, _('set changeset phase to secret')),
5432 ('f', 'force', False, _('allow to move boundary backward')),
5429 ('f', 'force', False, _('allow to move boundary backward')),
5433 ('r', 'rev', [], _('target revision'), _('REV')),
5430 ('r', 'rev', [], _('target revision'), _('REV')),
5434 ],
5431 ],
5435 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5432 _('[-p|-d|-s] [-f] [-r] [REV...]'))
5436 def phase(ui, repo, *revs, **opts):
5433 def phase(ui, repo, *revs, **opts):
5437 """set or show the current phase name
5434 """set or show the current phase name
5438
5435
5439 With no argument, show the phase name of the current revision(s).
5436 With no argument, show the phase name of the current revision(s).
5440
5437
5441 With one of -p/--public, -d/--draft or -s/--secret, change the
5438 With one of -p/--public, -d/--draft or -s/--secret, change the
5442 phase value of the specified revisions.
5439 phase value of the specified revisions.
5443
5440
5444 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5441 Unless -f/--force is specified, :hg:`phase` won't move changeset from a
5445 lower phase to an higher phase. Phases are ordered as follows::
5442 lower phase to an higher phase. Phases are ordered as follows::
5446
5443
5447 public < draft < secret
5444 public < draft < secret
5448
5445
5449 Returns 0 on success, 1 if some phases could not be changed.
5446 Returns 0 on success, 1 if some phases could not be changed.
5450
5447
5451 (For more information about the phases concept, see :hg:`help phases`.)
5448 (For more information about the phases concept, see :hg:`help phases`.)
5452 """
5449 """
5453 # search for a unique phase argument
5450 # search for a unique phase argument
5454 targetphase = None
5451 targetphase = None
5455 for idx, name in enumerate(phases.phasenames):
5452 for idx, name in enumerate(phases.phasenames):
5456 if opts[name]:
5453 if opts[name]:
5457 if targetphase is not None:
5454 if targetphase is not None:
5458 raise error.Abort(_('only one phase can be specified'))
5455 raise error.Abort(_('only one phase can be specified'))
5459 targetphase = idx
5456 targetphase = idx
5460
5457
5461 # look for specified revision
5458 # look for specified revision
5462 revs = list(revs)
5459 revs = list(revs)
5463 revs.extend(opts['rev'])
5460 revs.extend(opts['rev'])
5464 if not revs:
5461 if not revs:
5465 # display both parents as the second parent phase can influence
5462 # display both parents as the second parent phase can influence
5466 # the phase of a merge commit
5463 # the phase of a merge commit
5467 revs = [c.rev() for c in repo[None].parents()]
5464 revs = [c.rev() for c in repo[None].parents()]
5468
5465
5469 revs = scmutil.revrange(repo, revs)
5466 revs = scmutil.revrange(repo, revs)
5470
5467
5471 lock = None
5468 lock = None
5472 ret = 0
5469 ret = 0
5473 if targetphase is None:
5470 if targetphase is None:
5474 # display
5471 # display
5475 for r in revs:
5472 for r in revs:
5476 ctx = repo[r]
5473 ctx = repo[r]
5477 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5474 ui.write('%i: %s\n' % (ctx.rev(), ctx.phasestr()))
5478 else:
5475 else:
5479 tr = None
5476 tr = None
5480 lock = repo.lock()
5477 lock = repo.lock()
5481 try:
5478 try:
5482 tr = repo.transaction("phase")
5479 tr = repo.transaction("phase")
5483 # set phase
5480 # set phase
5484 if not revs:
5481 if not revs:
5485 raise error.Abort(_('empty revision set'))
5482 raise error.Abort(_('empty revision set'))
5486 nodes = [repo[r].node() for r in revs]
5483 nodes = [repo[r].node() for r in revs]
5487 # moving revision from public to draft may hide them
5484 # moving revision from public to draft may hide them
5488 # We have to check result on an unfiltered repository
5485 # We have to check result on an unfiltered repository
5489 unfi = repo.unfiltered()
5486 unfi = repo.unfiltered()
5490 getphase = unfi._phasecache.phase
5487 getphase = unfi._phasecache.phase
5491 olddata = [getphase(unfi, r) for r in unfi]
5488 olddata = [getphase(unfi, r) for r in unfi]
5492 phases.advanceboundary(repo, tr, targetphase, nodes)
5489 phases.advanceboundary(repo, tr, targetphase, nodes)
5493 if opts['force']:
5490 if opts['force']:
5494 phases.retractboundary(repo, tr, targetphase, nodes)
5491 phases.retractboundary(repo, tr, targetphase, nodes)
5495 tr.close()
5492 tr.close()
5496 finally:
5493 finally:
5497 if tr is not None:
5494 if tr is not None:
5498 tr.release()
5495 tr.release()
5499 lock.release()
5496 lock.release()
5500 getphase = unfi._phasecache.phase
5497 getphase = unfi._phasecache.phase
5501 newdata = [getphase(unfi, r) for r in unfi]
5498 newdata = [getphase(unfi, r) for r in unfi]
5502 changes = sum(newdata[r] != olddata[r] for r in unfi)
5499 changes = sum(newdata[r] != olddata[r] for r in unfi)
5503 cl = unfi.changelog
5500 cl = unfi.changelog
5504 rejected = [n for n in nodes
5501 rejected = [n for n in nodes
5505 if newdata[cl.rev(n)] < targetphase]
5502 if newdata[cl.rev(n)] < targetphase]
5506 if rejected:
5503 if rejected:
5507 ui.warn(_('cannot move %i changesets to a higher '
5504 ui.warn(_('cannot move %i changesets to a higher '
5508 'phase, use --force\n') % len(rejected))
5505 'phase, use --force\n') % len(rejected))
5509 ret = 1
5506 ret = 1
5510 if changes:
5507 if changes:
5511 msg = _('phase changed for %i changesets\n') % changes
5508 msg = _('phase changed for %i changesets\n') % changes
5512 if ret:
5509 if ret:
5513 ui.status(msg)
5510 ui.status(msg)
5514 else:
5511 else:
5515 ui.note(msg)
5512 ui.note(msg)
5516 else:
5513 else:
5517 ui.warn(_('no phases changed\n'))
5514 ui.warn(_('no phases changed\n'))
5518 return ret
5515 return ret
5519
5516
5520 def postincoming(ui, repo, modheads, optupdate, checkout):
5517 def postincoming(ui, repo, modheads, optupdate, checkout):
5521 if modheads == 0:
5518 if modheads == 0:
5522 return
5519 return
5523 if optupdate:
5520 if optupdate:
5524 try:
5521 try:
5525 brev = checkout
5522 brev = checkout
5526 movemarkfrom = None
5523 movemarkfrom = None
5527 if not checkout:
5524 if not checkout:
5528 updata = destutil.destupdate(repo)
5525 updata = destutil.destupdate(repo)
5529 checkout, movemarkfrom, brev = updata
5526 checkout, movemarkfrom, brev = updata
5530 ret = hg.update(repo, checkout)
5527 ret = hg.update(repo, checkout)
5531 except error.UpdateAbort as inst:
5528 except error.UpdateAbort as inst:
5532 msg = _("not updating: %s") % str(inst)
5529 msg = _("not updating: %s") % str(inst)
5533 hint = inst.hint
5530 hint = inst.hint
5534 raise error.UpdateAbort(msg, hint=hint)
5531 raise error.UpdateAbort(msg, hint=hint)
5535 if not ret and not checkout:
5532 if not ret and not checkout:
5536 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5533 if bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
5537 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5534 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
5538 return ret
5535 return ret
5539 if modheads > 1:
5536 if modheads > 1:
5540 currentbranchheads = len(repo.branchheads())
5537 currentbranchheads = len(repo.branchheads())
5541 if currentbranchheads == modheads:
5538 if currentbranchheads == modheads:
5542 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5539 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
5543 elif currentbranchheads > 1:
5540 elif currentbranchheads > 1:
5544 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5541 ui.status(_("(run 'hg heads .' to see heads, 'hg merge' to "
5545 "merge)\n"))
5542 "merge)\n"))
5546 else:
5543 else:
5547 ui.status(_("(run 'hg heads' to see heads)\n"))
5544 ui.status(_("(run 'hg heads' to see heads)\n"))
5548 else:
5545 else:
5549 ui.status(_("(run 'hg update' to get a working copy)\n"))
5546 ui.status(_("(run 'hg update' to get a working copy)\n"))
5550
5547
5551 @command('^pull',
5548 @command('^pull',
5552 [('u', 'update', None,
5549 [('u', 'update', None,
5553 _('update to new branch head if changesets were pulled')),
5550 _('update to new branch head if changesets were pulled')),
5554 ('f', 'force', None, _('run even when remote repository is unrelated')),
5551 ('f', 'force', None, _('run even when remote repository is unrelated')),
5555 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5552 ('r', 'rev', [], _('a remote changeset intended to be added'), _('REV')),
5556 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5553 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
5557 ('b', 'branch', [], _('a specific branch you would like to pull'),
5554 ('b', 'branch', [], _('a specific branch you would like to pull'),
5558 _('BRANCH')),
5555 _('BRANCH')),
5559 ] + remoteopts,
5556 ] + remoteopts,
5560 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5557 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]'))
5561 def pull(ui, repo, source="default", **opts):
5558 def pull(ui, repo, source="default", **opts):
5562 """pull changes from the specified source
5559 """pull changes from the specified source
5563
5560
5564 Pull changes from a remote repository to a local one.
5561 Pull changes from a remote repository to a local one.
5565
5562
5566 This finds all changes from the repository at the specified path
5563 This finds all changes from the repository at the specified path
5567 or URL and adds them to a local repository (the current one unless
5564 or URL and adds them to a local repository (the current one unless
5568 -R is specified). By default, this does not update the copy of the
5565 -R is specified). By default, this does not update the copy of the
5569 project in the working directory.
5566 project in the working directory.
5570
5567
5571 Use :hg:`incoming` if you want to see what would have been added
5568 Use :hg:`incoming` if you want to see what would have been added
5572 by a pull at the time you issued this command. If you then decide
5569 by a pull at the time you issued this command. If you then decide
5573 to add those changes to the repository, you should use :hg:`pull
5570 to add those changes to the repository, you should use :hg:`pull
5574 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5571 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
5575
5572
5576 If SOURCE is omitted, the 'default' path will be used.
5573 If SOURCE is omitted, the 'default' path will be used.
5577 See :hg:`help urls` for more information.
5574 See :hg:`help urls` for more information.
5578
5575
5579 Returns 0 on success, 1 if an update had unresolved files.
5576 Returns 0 on success, 1 if an update had unresolved files.
5580 """
5577 """
5581 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5578 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
5582 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5579 ui.status(_('pulling from %s\n') % util.hidepassword(source))
5583 other = hg.peer(repo, opts, source)
5580 other = hg.peer(repo, opts, source)
5584 try:
5581 try:
5585 revs, checkout = hg.addbranchrevs(repo, other, branches,
5582 revs, checkout = hg.addbranchrevs(repo, other, branches,
5586 opts.get('rev'))
5583 opts.get('rev'))
5587
5584
5588
5585
5589 pullopargs = {}
5586 pullopargs = {}
5590 if opts.get('bookmark'):
5587 if opts.get('bookmark'):
5591 if not revs:
5588 if not revs:
5592 revs = []
5589 revs = []
5593 # The list of bookmark used here is not the one used to actually
5590 # The list of bookmark used here is not the one used to actually
5594 # update the bookmark name. This can result in the revision pulled
5591 # update the bookmark name. This can result in the revision pulled
5595 # not ending up with the name of the bookmark because of a race
5592 # not ending up with the name of the bookmark because of a race
5596 # condition on the server. (See issue 4689 for details)
5593 # condition on the server. (See issue 4689 for details)
5597 remotebookmarks = other.listkeys('bookmarks')
5594 remotebookmarks = other.listkeys('bookmarks')
5598 pullopargs['remotebookmarks'] = remotebookmarks
5595 pullopargs['remotebookmarks'] = remotebookmarks
5599 for b in opts['bookmark']:
5596 for b in opts['bookmark']:
5600 if b not in remotebookmarks:
5597 if b not in remotebookmarks:
5601 raise error.Abort(_('remote bookmark %s not found!') % b)
5598 raise error.Abort(_('remote bookmark %s not found!') % b)
5602 revs.append(remotebookmarks[b])
5599 revs.append(remotebookmarks[b])
5603
5600
5604 if revs:
5601 if revs:
5605 try:
5602 try:
5606 # When 'rev' is a bookmark name, we cannot guarantee that it
5603 # When 'rev' is a bookmark name, we cannot guarantee that it
5607 # will be updated with that name because of a race condition
5604 # will be updated with that name because of a race condition
5608 # server side. (See issue 4689 for details)
5605 # server side. (See issue 4689 for details)
5609 oldrevs = revs
5606 oldrevs = revs
5610 revs = [] # actually, nodes
5607 revs = [] # actually, nodes
5611 for r in oldrevs:
5608 for r in oldrevs:
5612 node = other.lookup(r)
5609 node = other.lookup(r)
5613 revs.append(node)
5610 revs.append(node)
5614 if r == checkout:
5611 if r == checkout:
5615 checkout = node
5612 checkout = node
5616 except error.CapabilityError:
5613 except error.CapabilityError:
5617 err = _("other repository doesn't support revision lookup, "
5614 err = _("other repository doesn't support revision lookup, "
5618 "so a rev cannot be specified.")
5615 "so a rev cannot be specified.")
5619 raise error.Abort(err)
5616 raise error.Abort(err)
5620
5617
5621 pullopargs.update(opts.get('opargs', {}))
5618 pullopargs.update(opts.get('opargs', {}))
5622 modheads = exchange.pull(repo, other, heads=revs,
5619 modheads = exchange.pull(repo, other, heads=revs,
5623 force=opts.get('force'),
5620 force=opts.get('force'),
5624 bookmarks=opts.get('bookmark', ()),
5621 bookmarks=opts.get('bookmark', ()),
5625 opargs=pullopargs).cgresult
5622 opargs=pullopargs).cgresult
5626 if checkout:
5623 if checkout:
5627 checkout = str(repo.changelog.rev(checkout))
5624 checkout = str(repo.changelog.rev(checkout))
5628 repo._subtoppath = source
5625 repo._subtoppath = source
5629 try:
5626 try:
5630 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5627 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
5631
5628
5632 finally:
5629 finally:
5633 del repo._subtoppath
5630 del repo._subtoppath
5634
5631
5635 finally:
5632 finally:
5636 other.close()
5633 other.close()
5637 return ret
5634 return ret
5638
5635
5639 @command('^push',
5636 @command('^push',
5640 [('f', 'force', None, _('force push')),
5637 [('f', 'force', None, _('force push')),
5641 ('r', 'rev', [],
5638 ('r', 'rev', [],
5642 _('a changeset intended to be included in the destination'),
5639 _('a changeset intended to be included in the destination'),
5643 _('REV')),
5640 _('REV')),
5644 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5641 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
5645 ('b', 'branch', [],
5642 ('b', 'branch', [],
5646 _('a specific branch you would like to push'), _('BRANCH')),
5643 _('a specific branch you would like to push'), _('BRANCH')),
5647 ('', 'new-branch', False, _('allow pushing a new branch')),
5644 ('', 'new-branch', False, _('allow pushing a new branch')),
5648 ] + remoteopts,
5645 ] + remoteopts,
5649 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5646 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]'))
5650 def push(ui, repo, dest=None, **opts):
5647 def push(ui, repo, dest=None, **opts):
5651 """push changes to the specified destination
5648 """push changes to the specified destination
5652
5649
5653 Push changesets from the local repository to the specified
5650 Push changesets from the local repository to the specified
5654 destination.
5651 destination.
5655
5652
5656 This operation is symmetrical to pull: it is identical to a pull
5653 This operation is symmetrical to pull: it is identical to a pull
5657 in the destination repository from the current one.
5654 in the destination repository from the current one.
5658
5655
5659 By default, push will not allow creation of new heads at the
5656 By default, push will not allow creation of new heads at the
5660 destination, since multiple heads would make it unclear which head
5657 destination, since multiple heads would make it unclear which head
5661 to use. In this situation, it is recommended to pull and merge
5658 to use. In this situation, it is recommended to pull and merge
5662 before pushing.
5659 before pushing.
5663
5660
5664 Use --new-branch if you want to allow push to create a new named
5661 Use --new-branch if you want to allow push to create a new named
5665 branch that is not present at the destination. This allows you to
5662 branch that is not present at the destination. This allows you to
5666 only create a new branch without forcing other changes.
5663 only create a new branch without forcing other changes.
5667
5664
5668 .. note::
5665 .. note::
5669
5666
5670 Extra care should be taken with the -f/--force option,
5667 Extra care should be taken with the -f/--force option,
5671 which will push all new heads on all branches, an action which will
5668 which will push all new heads on all branches, an action which will
5672 almost always cause confusion for collaborators.
5669 almost always cause confusion for collaborators.
5673
5670
5674 If -r/--rev is used, the specified revision and all its ancestors
5671 If -r/--rev is used, the specified revision and all its ancestors
5675 will be pushed to the remote repository.
5672 will be pushed to the remote repository.
5676
5673
5677 If -B/--bookmark is used, the specified bookmarked revision, its
5674 If -B/--bookmark is used, the specified bookmarked revision, its
5678 ancestors, and the bookmark will be pushed to the remote
5675 ancestors, and the bookmark will be pushed to the remote
5679 repository.
5676 repository.
5680
5677
5681 Please see :hg:`help urls` for important details about ``ssh://``
5678 Please see :hg:`help urls` for important details about ``ssh://``
5682 URLs. If DESTINATION is omitted, a default path will be used.
5679 URLs. If DESTINATION is omitted, a default path will be used.
5683
5680
5684 Returns 0 if push was successful, 1 if nothing to push.
5681 Returns 0 if push was successful, 1 if nothing to push.
5685 """
5682 """
5686
5683
5687 if opts.get('bookmark'):
5684 if opts.get('bookmark'):
5688 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5685 ui.setconfig('bookmarks', 'pushing', opts['bookmark'], 'push')
5689 for b in opts['bookmark']:
5686 for b in opts['bookmark']:
5690 # translate -B options to -r so changesets get pushed
5687 # translate -B options to -r so changesets get pushed
5691 if b in repo._bookmarks:
5688 if b in repo._bookmarks:
5692 opts.setdefault('rev', []).append(b)
5689 opts.setdefault('rev', []).append(b)
5693 else:
5690 else:
5694 # if we try to push a deleted bookmark, translate it to null
5691 # if we try to push a deleted bookmark, translate it to null
5695 # this lets simultaneous -r, -b options continue working
5692 # this lets simultaneous -r, -b options continue working
5696 opts.setdefault('rev', []).append("null")
5693 opts.setdefault('rev', []).append("null")
5697
5694
5698 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5695 path = ui.paths.getpath(dest, default=('default-push', 'default'))
5699 if not path:
5696 if not path:
5700 raise error.Abort(_('default repository not configured!'),
5697 raise error.Abort(_('default repository not configured!'),
5701 hint=_('see the "path" section in "hg help config"'))
5698 hint=_('see the "path" section in "hg help config"'))
5702 dest = path.pushloc or path.loc
5699 dest = path.pushloc or path.loc
5703 branches = (path.branch, opts.get('branch') or [])
5700 branches = (path.branch, opts.get('branch') or [])
5704 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5701 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
5705 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5702 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
5706 other = hg.peer(repo, opts, dest)
5703 other = hg.peer(repo, opts, dest)
5707
5704
5708 if revs:
5705 if revs:
5709 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5706 revs = [repo.lookup(r) for r in scmutil.revrange(repo, revs)]
5710 if not revs:
5707 if not revs:
5711 raise error.Abort(_("specified revisions evaluate to an empty set"),
5708 raise error.Abort(_("specified revisions evaluate to an empty set"),
5712 hint=_("use different revision arguments"))
5709 hint=_("use different revision arguments"))
5713
5710
5714 repo._subtoppath = dest
5711 repo._subtoppath = dest
5715 try:
5712 try:
5716 # push subrepos depth-first for coherent ordering
5713 # push subrepos depth-first for coherent ordering
5717 c = repo['']
5714 c = repo['']
5718 subs = c.substate # only repos that are committed
5715 subs = c.substate # only repos that are committed
5719 for s in sorted(subs):
5716 for s in sorted(subs):
5720 result = c.sub(s).push(opts)
5717 result = c.sub(s).push(opts)
5721 if result == 0:
5718 if result == 0:
5722 return not result
5719 return not result
5723 finally:
5720 finally:
5724 del repo._subtoppath
5721 del repo._subtoppath
5725 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5722 pushop = exchange.push(repo, other, opts.get('force'), revs=revs,
5726 newbranch=opts.get('new_branch'),
5723 newbranch=opts.get('new_branch'),
5727 bookmarks=opts.get('bookmark', ()),
5724 bookmarks=opts.get('bookmark', ()),
5728 opargs=opts.get('opargs'))
5725 opargs=opts.get('opargs'))
5729
5726
5730 result = not pushop.cgresult
5727 result = not pushop.cgresult
5731
5728
5732 if pushop.bkresult is not None:
5729 if pushop.bkresult is not None:
5733 if pushop.bkresult == 2:
5730 if pushop.bkresult == 2:
5734 result = 2
5731 result = 2
5735 elif not result and pushop.bkresult:
5732 elif not result and pushop.bkresult:
5736 result = 2
5733 result = 2
5737
5734
5738 return result
5735 return result
5739
5736
5740 @command('recover', [])
5737 @command('recover', [])
5741 def recover(ui, repo):
5738 def recover(ui, repo):
5742 """roll back an interrupted transaction
5739 """roll back an interrupted transaction
5743
5740
5744 Recover from an interrupted commit or pull.
5741 Recover from an interrupted commit or pull.
5745
5742
5746 This command tries to fix the repository status after an
5743 This command tries to fix the repository status after an
5747 interrupted operation. It should only be necessary when Mercurial
5744 interrupted operation. It should only be necessary when Mercurial
5748 suggests it.
5745 suggests it.
5749
5746
5750 Returns 0 if successful, 1 if nothing to recover or verify fails.
5747 Returns 0 if successful, 1 if nothing to recover or verify fails.
5751 """
5748 """
5752 if repo.recover():
5749 if repo.recover():
5753 return hg.verify(repo)
5750 return hg.verify(repo)
5754 return 1
5751 return 1
5755
5752
5756 @command('^remove|rm',
5753 @command('^remove|rm',
5757 [('A', 'after', None, _('record delete for missing files')),
5754 [('A', 'after', None, _('record delete for missing files')),
5758 ('f', 'force', None,
5755 ('f', 'force', None,
5759 _('remove (and delete) file even if added or modified')),
5756 _('remove (and delete) file even if added or modified')),
5760 ] + subrepoopts + walkopts,
5757 ] + subrepoopts + walkopts,
5761 _('[OPTION]... FILE...'),
5758 _('[OPTION]... FILE...'),
5762 inferrepo=True)
5759 inferrepo=True)
5763 def remove(ui, repo, *pats, **opts):
5760 def remove(ui, repo, *pats, **opts):
5764 """remove the specified files on the next commit
5761 """remove the specified files on the next commit
5765
5762
5766 Schedule the indicated files for removal from the current branch.
5763 Schedule the indicated files for removal from the current branch.
5767
5764
5768 This command schedules the files to be removed at the next commit.
5765 This command schedules the files to be removed at the next commit.
5769 To undo a remove before that, see :hg:`revert`. To undo added
5766 To undo a remove before that, see :hg:`revert`. To undo added
5770 files, see :hg:`forget`.
5767 files, see :hg:`forget`.
5771
5768
5772 .. container:: verbose
5769 .. container:: verbose
5773
5770
5774 -A/--after can be used to remove only files that have already
5771 -A/--after can be used to remove only files that have already
5775 been deleted, -f/--force can be used to force deletion, and -Af
5772 been deleted, -f/--force can be used to force deletion, and -Af
5776 can be used to remove files from the next revision without
5773 can be used to remove files from the next revision without
5777 deleting them from the working directory.
5774 deleting them from the working directory.
5778
5775
5779 The following table details the behavior of remove for different
5776 The following table details the behavior of remove for different
5780 file states (columns) and option combinations (rows). The file
5777 file states (columns) and option combinations (rows). The file
5781 states are Added [A], Clean [C], Modified [M] and Missing [!]
5778 states are Added [A], Clean [C], Modified [M] and Missing [!]
5782 (as reported by :hg:`status`). The actions are Warn, Remove
5779 (as reported by :hg:`status`). The actions are Warn, Remove
5783 (from branch) and Delete (from disk):
5780 (from branch) and Delete (from disk):
5784
5781
5785 ========= == == == ==
5782 ========= == == == ==
5786 opt/state A C M !
5783 opt/state A C M !
5787 ========= == == == ==
5784 ========= == == == ==
5788 none W RD W R
5785 none W RD W R
5789 -f R RD RD R
5786 -f R RD RD R
5790 -A W W W R
5787 -A W W W R
5791 -Af R R R R
5788 -Af R R R R
5792 ========= == == == ==
5789 ========= == == == ==
5793
5790
5794 .. note::
5791 .. note::
5795
5792
5796 :hg:`remove` never deletes files in Added [A] state from the
5793 :hg:`remove` never deletes files in Added [A] state from the
5797 working directory, not even if ``--force`` is specified.
5794 working directory, not even if ``--force`` is specified.
5798
5795
5799 Returns 0 on success, 1 if any warnings encountered.
5796 Returns 0 on success, 1 if any warnings encountered.
5800 """
5797 """
5801
5798
5802 after, force = opts.get('after'), opts.get('force')
5799 after, force = opts.get('after'), opts.get('force')
5803 if not pats and not after:
5800 if not pats and not after:
5804 raise error.Abort(_('no files specified'))
5801 raise error.Abort(_('no files specified'))
5805
5802
5806 m = scmutil.match(repo[None], pats, opts)
5803 m = scmutil.match(repo[None], pats, opts)
5807 subrepos = opts.get('subrepos')
5804 subrepos = opts.get('subrepos')
5808 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5805 return cmdutil.remove(ui, repo, m, "", after, force, subrepos)
5809
5806
5810 @command('rename|move|mv',
5807 @command('rename|move|mv',
5811 [('A', 'after', None, _('record a rename that has already occurred')),
5808 [('A', 'after', None, _('record a rename that has already occurred')),
5812 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5809 ('f', 'force', None, _('forcibly copy over an existing managed file')),
5813 ] + walkopts + dryrunopts,
5810 ] + walkopts + dryrunopts,
5814 _('[OPTION]... SOURCE... DEST'))
5811 _('[OPTION]... SOURCE... DEST'))
5815 def rename(ui, repo, *pats, **opts):
5812 def rename(ui, repo, *pats, **opts):
5816 """rename files; equivalent of copy + remove
5813 """rename files; equivalent of copy + remove
5817
5814
5818 Mark dest as copies of sources; mark sources for deletion. If dest
5815 Mark dest as copies of sources; mark sources for deletion. If dest
5819 is a directory, copies are put in that directory. If dest is a
5816 is a directory, copies are put in that directory. If dest is a
5820 file, there can only be one source.
5817 file, there can only be one source.
5821
5818
5822 By default, this command copies the contents of files as they
5819 By default, this command copies the contents of files as they
5823 exist in the working directory. If invoked with -A/--after, the
5820 exist in the working directory. If invoked with -A/--after, the
5824 operation is recorded, but no copying is performed.
5821 operation is recorded, but no copying is performed.
5825
5822
5826 This command takes effect at the next commit. To undo a rename
5823 This command takes effect at the next commit. To undo a rename
5827 before that, see :hg:`revert`.
5824 before that, see :hg:`revert`.
5828
5825
5829 Returns 0 on success, 1 if errors are encountered.
5826 Returns 0 on success, 1 if errors are encountered.
5830 """
5827 """
5831 wlock = repo.wlock(False)
5828 wlock = repo.wlock(False)
5832 try:
5829 try:
5833 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5830 return cmdutil.copy(ui, repo, pats, opts, rename=True)
5834 finally:
5831 finally:
5835 wlock.release()
5832 wlock.release()
5836
5833
5837 @command('resolve',
5834 @command('resolve',
5838 [('a', 'all', None, _('select all unresolved files')),
5835 [('a', 'all', None, _('select all unresolved files')),
5839 ('l', 'list', None, _('list state of files needing merge')),
5836 ('l', 'list', None, _('list state of files needing merge')),
5840 ('m', 'mark', None, _('mark files as resolved')),
5837 ('m', 'mark', None, _('mark files as resolved')),
5841 ('u', 'unmark', None, _('mark files as unresolved')),
5838 ('u', 'unmark', None, _('mark files as unresolved')),
5842 ('n', 'no-status', None, _('hide status prefix'))]
5839 ('n', 'no-status', None, _('hide status prefix'))]
5843 + mergetoolopts + walkopts + formatteropts,
5840 + mergetoolopts + walkopts + formatteropts,
5844 _('[OPTION]... [FILE]...'),
5841 _('[OPTION]... [FILE]...'),
5845 inferrepo=True)
5842 inferrepo=True)
5846 def resolve(ui, repo, *pats, **opts):
5843 def resolve(ui, repo, *pats, **opts):
5847 """redo merges or set/view the merge status of files
5844 """redo merges or set/view the merge status of files
5848
5845
5849 Merges with unresolved conflicts are often the result of
5846 Merges with unresolved conflicts are often the result of
5850 non-interactive merging using the ``internal:merge`` configuration
5847 non-interactive merging using the ``internal:merge`` configuration
5851 setting, or a command-line merge tool like ``diff3``. The resolve
5848 setting, or a command-line merge tool like ``diff3``. The resolve
5852 command is used to manage the files involved in a merge, after
5849 command is used to manage the files involved in a merge, after
5853 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5850 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
5854 working directory must have two parents). See :hg:`help
5851 working directory must have two parents). See :hg:`help
5855 merge-tools` for information on configuring merge tools.
5852 merge-tools` for information on configuring merge tools.
5856
5853
5857 The resolve command can be used in the following ways:
5854 The resolve command can be used in the following ways:
5858
5855
5859 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5856 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
5860 files, discarding any previous merge attempts. Re-merging is not
5857 files, discarding any previous merge attempts. Re-merging is not
5861 performed for files already marked as resolved. Use ``--all/-a``
5858 performed for files already marked as resolved. Use ``--all/-a``
5862 to select all unresolved files. ``--tool`` can be used to specify
5859 to select all unresolved files. ``--tool`` can be used to specify
5863 the merge tool used for the given files. It overrides the HGMERGE
5860 the merge tool used for the given files. It overrides the HGMERGE
5864 environment variable and your configuration files. Previous file
5861 environment variable and your configuration files. Previous file
5865 contents are saved with a ``.orig`` suffix.
5862 contents are saved with a ``.orig`` suffix.
5866
5863
5867 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5864 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
5868 (e.g. after having manually fixed-up the files). The default is
5865 (e.g. after having manually fixed-up the files). The default is
5869 to mark all unresolved files.
5866 to mark all unresolved files.
5870
5867
5871 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5868 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
5872 default is to mark all resolved files.
5869 default is to mark all resolved files.
5873
5870
5874 - :hg:`resolve -l`: list files which had or still have conflicts.
5871 - :hg:`resolve -l`: list files which had or still have conflicts.
5875 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5872 In the printed list, ``U`` = unresolved and ``R`` = resolved.
5876
5873
5877 .. note::
5874 .. note::
5878
5875
5879 Mercurial will not let you commit files with unresolved merge
5876 Mercurial will not let you commit files with unresolved merge
5880 conflicts. You must use :hg:`resolve -m ...` before you can
5877 conflicts. You must use :hg:`resolve -m ...` before you can
5881 commit after a conflicting merge.
5878 commit after a conflicting merge.
5882
5879
5883 Returns 0 on success, 1 if any files fail a resolve attempt.
5880 Returns 0 on success, 1 if any files fail a resolve attempt.
5884 """
5881 """
5885
5882
5886 all, mark, unmark, show, nostatus = \
5883 all, mark, unmark, show, nostatus = \
5887 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5884 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
5888
5885
5889 if (show and (mark or unmark)) or (mark and unmark):
5886 if (show and (mark or unmark)) or (mark and unmark):
5890 raise error.Abort(_("too many options specified"))
5887 raise error.Abort(_("too many options specified"))
5891 if pats and all:
5888 if pats and all:
5892 raise error.Abort(_("can't specify --all and patterns"))
5889 raise error.Abort(_("can't specify --all and patterns"))
5893 if not (all or pats or show or mark or unmark):
5890 if not (all or pats or show or mark or unmark):
5894 raise error.Abort(_('no files or directories specified'),
5891 raise error.Abort(_('no files or directories specified'),
5895 hint=('use --all to re-merge all unresolved files'))
5892 hint=('use --all to re-merge all unresolved files'))
5896
5893
5897 if show:
5894 if show:
5898 fm = ui.formatter('resolve', opts)
5895 fm = ui.formatter('resolve', opts)
5899 ms = mergemod.mergestate.read(repo)
5896 ms = mergemod.mergestate.read(repo)
5900 m = scmutil.match(repo[None], pats, opts)
5897 m = scmutil.match(repo[None], pats, opts)
5901 for f in ms:
5898 for f in ms:
5902 if not m(f):
5899 if not m(f):
5903 continue
5900 continue
5904 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5901 l = 'resolve.' + {'u': 'unresolved', 'r': 'resolved',
5905 'd': 'driverresolved'}[ms[f]]
5902 'd': 'driverresolved'}[ms[f]]
5906 fm.startitem()
5903 fm.startitem()
5907 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5904 fm.condwrite(not nostatus, 'status', '%s ', ms[f].upper(), label=l)
5908 fm.write('path', '%s\n', f, label=l)
5905 fm.write('path', '%s\n', f, label=l)
5909 fm.end()
5906 fm.end()
5910 return 0
5907 return 0
5911
5908
5912 wlock = repo.wlock()
5909 wlock = repo.wlock()
5913 try:
5910 try:
5914 ms = mergemod.mergestate.read(repo)
5911 ms = mergemod.mergestate.read(repo)
5915
5912
5916 if not (ms.active() or repo.dirstate.p2() != nullid):
5913 if not (ms.active() or repo.dirstate.p2() != nullid):
5917 raise error.Abort(
5914 raise error.Abort(
5918 _('resolve command not applicable when not merging'))
5915 _('resolve command not applicable when not merging'))
5919
5916
5920 wctx = repo[None]
5917 wctx = repo[None]
5921
5918
5922 if ms.mergedriver and ms.mdstate() == 'u':
5919 if ms.mergedriver and ms.mdstate() == 'u':
5923 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5920 proceed = mergemod.driverpreprocess(repo, ms, wctx)
5924 ms.commit()
5921 ms.commit()
5925 # allow mark and unmark to go through
5922 # allow mark and unmark to go through
5926 if not mark and not unmark and not proceed:
5923 if not mark and not unmark and not proceed:
5927 return 1
5924 return 1
5928
5925
5929 m = scmutil.match(wctx, pats, opts)
5926 m = scmutil.match(wctx, pats, opts)
5930 ret = 0
5927 ret = 0
5931 didwork = False
5928 didwork = False
5932 runconclude = False
5929 runconclude = False
5933
5930
5934 tocomplete = []
5931 tocomplete = []
5935 for f in ms:
5932 for f in ms:
5936 if not m(f):
5933 if not m(f):
5937 continue
5934 continue
5938
5935
5939 didwork = True
5936 didwork = True
5940
5937
5941 # don't let driver-resolved files be marked, and run the conclude
5938 # don't let driver-resolved files be marked, and run the conclude
5942 # step if asked to resolve
5939 # step if asked to resolve
5943 if ms[f] == "d":
5940 if ms[f] == "d":
5944 exact = m.exact(f)
5941 exact = m.exact(f)
5945 if mark:
5942 if mark:
5946 if exact:
5943 if exact:
5947 ui.warn(_('not marking %s as it is driver-resolved\n')
5944 ui.warn(_('not marking %s as it is driver-resolved\n')
5948 % f)
5945 % f)
5949 elif unmark:
5946 elif unmark:
5950 if exact:
5947 if exact:
5951 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5948 ui.warn(_('not unmarking %s as it is driver-resolved\n')
5952 % f)
5949 % f)
5953 else:
5950 else:
5954 runconclude = True
5951 runconclude = True
5955 continue
5952 continue
5956
5953
5957 if mark:
5954 if mark:
5958 ms.mark(f, "r")
5955 ms.mark(f, "r")
5959 elif unmark:
5956 elif unmark:
5960 ms.mark(f, "u")
5957 ms.mark(f, "u")
5961 else:
5958 else:
5962 # backup pre-resolve (merge uses .orig for its own purposes)
5959 # backup pre-resolve (merge uses .orig for its own purposes)
5963 a = repo.wjoin(f)
5960 a = repo.wjoin(f)
5964 try:
5961 try:
5965 util.copyfile(a, a + ".resolve")
5962 util.copyfile(a, a + ".resolve")
5966 except (IOError, OSError) as inst:
5963 except (IOError, OSError) as inst:
5967 if inst.errno != errno.ENOENT:
5964 if inst.errno != errno.ENOENT:
5968 raise
5965 raise
5969
5966
5970 try:
5967 try:
5971 # preresolve file
5968 # preresolve file
5972 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5969 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5973 'resolve')
5970 'resolve')
5974 complete, r = ms.preresolve(f, wctx)
5971 complete, r = ms.preresolve(f, wctx)
5975 if not complete:
5972 if not complete:
5976 tocomplete.append(f)
5973 tocomplete.append(f)
5977 elif r:
5974 elif r:
5978 ret = 1
5975 ret = 1
5979 finally:
5976 finally:
5980 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5977 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5981 ms.commit()
5978 ms.commit()
5982
5979
5983 # replace filemerge's .orig file with our resolve file, but only
5980 # replace filemerge's .orig file with our resolve file, but only
5984 # for merges that are complete
5981 # for merges that are complete
5985 if complete:
5982 if complete:
5986 try:
5983 try:
5987 util.rename(a + ".resolve",
5984 util.rename(a + ".resolve",
5988 scmutil.origpath(ui, repo, a))
5985 scmutil.origpath(ui, repo, a))
5989 except OSError as inst:
5986 except OSError as inst:
5990 if inst.errno != errno.ENOENT:
5987 if inst.errno != errno.ENOENT:
5991 raise
5988 raise
5992
5989
5993 for f in tocomplete:
5990 for f in tocomplete:
5994 try:
5991 try:
5995 # resolve file
5992 # resolve file
5996 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5993 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''),
5997 'resolve')
5994 'resolve')
5998 r = ms.resolve(f, wctx)
5995 r = ms.resolve(f, wctx)
5999 if r:
5996 if r:
6000 ret = 1
5997 ret = 1
6001 finally:
5998 finally:
6002 ui.setconfig('ui', 'forcemerge', '', 'resolve')
5999 ui.setconfig('ui', 'forcemerge', '', 'resolve')
6003 ms.commit()
6000 ms.commit()
6004
6001
6005 # replace filemerge's .orig file with our resolve file
6002 # replace filemerge's .orig file with our resolve file
6006 a = repo.wjoin(f)
6003 a = repo.wjoin(f)
6007 try:
6004 try:
6008 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6005 util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
6009 except OSError as inst:
6006 except OSError as inst:
6010 if inst.errno != errno.ENOENT:
6007 if inst.errno != errno.ENOENT:
6011 raise
6008 raise
6012
6009
6013 ms.commit()
6010 ms.commit()
6014 ms.recordactions()
6011 ms.recordactions()
6015
6012
6016 if not didwork and pats:
6013 if not didwork and pats:
6017 ui.warn(_("arguments do not match paths that need resolving\n"))
6014 ui.warn(_("arguments do not match paths that need resolving\n"))
6018 elif ms.mergedriver and ms.mdstate() != 's':
6015 elif ms.mergedriver and ms.mdstate() != 's':
6019 # run conclude step when either a driver-resolved file is requested
6016 # run conclude step when either a driver-resolved file is requested
6020 # or there are no driver-resolved files
6017 # or there are no driver-resolved files
6021 # we can't use 'ret' to determine whether any files are unresolved
6018 # we can't use 'ret' to determine whether any files are unresolved
6022 # because we might not have tried to resolve some
6019 # because we might not have tried to resolve some
6023 if ((runconclude or not list(ms.driverresolved()))
6020 if ((runconclude or not list(ms.driverresolved()))
6024 and not list(ms.unresolved())):
6021 and not list(ms.unresolved())):
6025 proceed = mergemod.driverconclude(repo, ms, wctx)
6022 proceed = mergemod.driverconclude(repo, ms, wctx)
6026 ms.commit()
6023 ms.commit()
6027 if not proceed:
6024 if not proceed:
6028 return 1
6025 return 1
6029
6026
6030 finally:
6027 finally:
6031 wlock.release()
6028 wlock.release()
6032
6029
6033 # Nudge users into finishing an unfinished operation
6030 # Nudge users into finishing an unfinished operation
6034 unresolvedf = list(ms.unresolved())
6031 unresolvedf = list(ms.unresolved())
6035 driverresolvedf = list(ms.driverresolved())
6032 driverresolvedf = list(ms.driverresolved())
6036 if not unresolvedf and not driverresolvedf:
6033 if not unresolvedf and not driverresolvedf:
6037 ui.status(_('(no more unresolved files)\n'))
6034 ui.status(_('(no more unresolved files)\n'))
6038 cmdutil.checkafterresolved(repo)
6035 cmdutil.checkafterresolved(repo)
6039 elif not unresolvedf:
6036 elif not unresolvedf:
6040 ui.status(_('(no more unresolved files -- '
6037 ui.status(_('(no more unresolved files -- '
6041 'run "hg resolve --all" to conclude)\n'))
6038 'run "hg resolve --all" to conclude)\n'))
6042
6039
6043 return ret
6040 return ret
6044
6041
6045 @command('revert',
6042 @command('revert',
6046 [('a', 'all', None, _('revert all changes when no arguments given')),
6043 [('a', 'all', None, _('revert all changes when no arguments given')),
6047 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6044 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6048 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6045 ('r', 'rev', '', _('revert to the specified revision'), _('REV')),
6049 ('C', 'no-backup', None, _('do not save backup copies of files')),
6046 ('C', 'no-backup', None, _('do not save backup copies of files')),
6050 ('i', 'interactive', None,
6047 ('i', 'interactive', None,
6051 _('interactively select the changes (EXPERIMENTAL)')),
6048 _('interactively select the changes (EXPERIMENTAL)')),
6052 ] + walkopts + dryrunopts,
6049 ] + walkopts + dryrunopts,
6053 _('[OPTION]... [-r REV] [NAME]...'))
6050 _('[OPTION]... [-r REV] [NAME]...'))
6054 def revert(ui, repo, *pats, **opts):
6051 def revert(ui, repo, *pats, **opts):
6055 """restore files to their checkout state
6052 """restore files to their checkout state
6056
6053
6057 .. note::
6054 .. note::
6058
6055
6059 To check out earlier revisions, you should use :hg:`update REV`.
6056 To check out earlier revisions, you should use :hg:`update REV`.
6060 To cancel an uncommitted merge (and lose your changes),
6057 To cancel an uncommitted merge (and lose your changes),
6061 use :hg:`update --clean .`.
6058 use :hg:`update --clean .`.
6062
6059
6063 With no revision specified, revert the specified files or directories
6060 With no revision specified, revert the specified files or directories
6064 to the contents they had in the parent of the working directory.
6061 to the contents they had in the parent of the working directory.
6065 This restores the contents of files to an unmodified
6062 This restores the contents of files to an unmodified
6066 state and unschedules adds, removes, copies, and renames. If the
6063 state and unschedules adds, removes, copies, and renames. If the
6067 working directory has two parents, you must explicitly specify a
6064 working directory has two parents, you must explicitly specify a
6068 revision.
6065 revision.
6069
6066
6070 Using the -r/--rev or -d/--date options, revert the given files or
6067 Using the -r/--rev or -d/--date options, revert the given files or
6071 directories to their states as of a specific revision. Because
6068 directories to their states as of a specific revision. Because
6072 revert does not change the working directory parents, this will
6069 revert does not change the working directory parents, this will
6073 cause these files to appear modified. This can be helpful to "back
6070 cause these files to appear modified. This can be helpful to "back
6074 out" some or all of an earlier change. See :hg:`backout` for a
6071 out" some or all of an earlier change. See :hg:`backout` for a
6075 related method.
6072 related method.
6076
6073
6077 Modified files are saved with a .orig suffix before reverting.
6074 Modified files are saved with a .orig suffix before reverting.
6078 To disable these backups, use --no-backup.
6075 To disable these backups, use --no-backup.
6079
6076
6080 See :hg:`help dates` for a list of formats valid for -d/--date.
6077 See :hg:`help dates` for a list of formats valid for -d/--date.
6081
6078
6082 See :hg:`help backout` for a way to reverse the effect of an
6079 See :hg:`help backout` for a way to reverse the effect of an
6083 earlier changeset.
6080 earlier changeset.
6084
6081
6085 Returns 0 on success.
6082 Returns 0 on success.
6086 """
6083 """
6087
6084
6088 if opts.get("date"):
6085 if opts.get("date"):
6089 if opts.get("rev"):
6086 if opts.get("rev"):
6090 raise error.Abort(_("you can't specify a revision and a date"))
6087 raise error.Abort(_("you can't specify a revision and a date"))
6091 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6088 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
6092
6089
6093 parent, p2 = repo.dirstate.parents()
6090 parent, p2 = repo.dirstate.parents()
6094 if not opts.get('rev') and p2 != nullid:
6091 if not opts.get('rev') and p2 != nullid:
6095 # revert after merge is a trap for new users (issue2915)
6092 # revert after merge is a trap for new users (issue2915)
6096 raise error.Abort(_('uncommitted merge with no revision specified'),
6093 raise error.Abort(_('uncommitted merge with no revision specified'),
6097 hint=_('use "hg update" or see "hg help revert"'))
6094 hint=_('use "hg update" or see "hg help revert"'))
6098
6095
6099 ctx = scmutil.revsingle(repo, opts.get('rev'))
6096 ctx = scmutil.revsingle(repo, opts.get('rev'))
6100
6097
6101 if (not (pats or opts.get('include') or opts.get('exclude') or
6098 if (not (pats or opts.get('include') or opts.get('exclude') or
6102 opts.get('all') or opts.get('interactive'))):
6099 opts.get('all') or opts.get('interactive'))):
6103 msg = _("no files or directories specified")
6100 msg = _("no files or directories specified")
6104 if p2 != nullid:
6101 if p2 != nullid:
6105 hint = _("uncommitted merge, use --all to discard all changes,"
6102 hint = _("uncommitted merge, use --all to discard all changes,"
6106 " or 'hg update -C .' to abort the merge")
6103 " or 'hg update -C .' to abort the merge")
6107 raise error.Abort(msg, hint=hint)
6104 raise error.Abort(msg, hint=hint)
6108 dirty = any(repo.status())
6105 dirty = any(repo.status())
6109 node = ctx.node()
6106 node = ctx.node()
6110 if node != parent:
6107 if node != parent:
6111 if dirty:
6108 if dirty:
6112 hint = _("uncommitted changes, use --all to discard all"
6109 hint = _("uncommitted changes, use --all to discard all"
6113 " changes, or 'hg update %s' to update") % ctx.rev()
6110 " changes, or 'hg update %s' to update") % ctx.rev()
6114 else:
6111 else:
6115 hint = _("use --all to revert all files,"
6112 hint = _("use --all to revert all files,"
6116 " or 'hg update %s' to update") % ctx.rev()
6113 " or 'hg update %s' to update") % ctx.rev()
6117 elif dirty:
6114 elif dirty:
6118 hint = _("uncommitted changes, use --all to discard all changes")
6115 hint = _("uncommitted changes, use --all to discard all changes")
6119 else:
6116 else:
6120 hint = _("use --all to revert all files")
6117 hint = _("use --all to revert all files")
6121 raise error.Abort(msg, hint=hint)
6118 raise error.Abort(msg, hint=hint)
6122
6119
6123 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6120 return cmdutil.revert(ui, repo, ctx, (parent, p2), *pats, **opts)
6124
6121
6125 @command('rollback', dryrunopts +
6122 @command('rollback', dryrunopts +
6126 [('f', 'force', False, _('ignore safety measures'))])
6123 [('f', 'force', False, _('ignore safety measures'))])
6127 def rollback(ui, repo, **opts):
6124 def rollback(ui, repo, **opts):
6128 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6125 """roll back the last transaction (DANGEROUS) (DEPRECATED)
6129
6126
6130 Please use :hg:`commit --amend` instead of rollback to correct
6127 Please use :hg:`commit --amend` instead of rollback to correct
6131 mistakes in the last commit.
6128 mistakes in the last commit.
6132
6129
6133 This command should be used with care. There is only one level of
6130 This command should be used with care. There is only one level of
6134 rollback, and there is no way to undo a rollback. It will also
6131 rollback, and there is no way to undo a rollback. It will also
6135 restore the dirstate at the time of the last transaction, losing
6132 restore the dirstate at the time of the last transaction, losing
6136 any dirstate changes since that time. This command does not alter
6133 any dirstate changes since that time. This command does not alter
6137 the working directory.
6134 the working directory.
6138
6135
6139 Transactions are used to encapsulate the effects of all commands
6136 Transactions are used to encapsulate the effects of all commands
6140 that create new changesets or propagate existing changesets into a
6137 that create new changesets or propagate existing changesets into a
6141 repository.
6138 repository.
6142
6139
6143 .. container:: verbose
6140 .. container:: verbose
6144
6141
6145 For example, the following commands are transactional, and their
6142 For example, the following commands are transactional, and their
6146 effects can be rolled back:
6143 effects can be rolled back:
6147
6144
6148 - commit
6145 - commit
6149 - import
6146 - import
6150 - pull
6147 - pull
6151 - push (with this repository as the destination)
6148 - push (with this repository as the destination)
6152 - unbundle
6149 - unbundle
6153
6150
6154 To avoid permanent data loss, rollback will refuse to rollback a
6151 To avoid permanent data loss, rollback will refuse to rollback a
6155 commit transaction if it isn't checked out. Use --force to
6152 commit transaction if it isn't checked out. Use --force to
6156 override this protection.
6153 override this protection.
6157
6154
6158 This command is not intended for use on public repositories. Once
6155 This command is not intended for use on public repositories. Once
6159 changes are visible for pull by other users, rolling a transaction
6156 changes are visible for pull by other users, rolling a transaction
6160 back locally is ineffective (someone else may already have pulled
6157 back locally is ineffective (someone else may already have pulled
6161 the changes). Furthermore, a race is possible with readers of the
6158 the changes). Furthermore, a race is possible with readers of the
6162 repository; for example an in-progress pull from the repository
6159 repository; for example an in-progress pull from the repository
6163 may fail if a rollback is performed.
6160 may fail if a rollback is performed.
6164
6161
6165 Returns 0 on success, 1 if no rollback data is available.
6162 Returns 0 on success, 1 if no rollback data is available.
6166 """
6163 """
6167 return repo.rollback(dryrun=opts.get('dry_run'),
6164 return repo.rollback(dryrun=opts.get('dry_run'),
6168 force=opts.get('force'))
6165 force=opts.get('force'))
6169
6166
6170 @command('root', [])
6167 @command('root', [])
6171 def root(ui, repo):
6168 def root(ui, repo):
6172 """print the root (top) of the current working directory
6169 """print the root (top) of the current working directory
6173
6170
6174 Print the root directory of the current repository.
6171 Print the root directory of the current repository.
6175
6172
6176 Returns 0 on success.
6173 Returns 0 on success.
6177 """
6174 """
6178 ui.write(repo.root + "\n")
6175 ui.write(repo.root + "\n")
6179
6176
6180 @command('^serve',
6177 @command('^serve',
6181 [('A', 'accesslog', '', _('name of access log file to write to'),
6178 [('A', 'accesslog', '', _('name of access log file to write to'),
6182 _('FILE')),
6179 _('FILE')),
6183 ('d', 'daemon', None, _('run server in background')),
6180 ('d', 'daemon', None, _('run server in background')),
6184 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6181 ('', 'daemon-pipefds', '', _('used internally by daemon mode'), _('FILE')),
6185 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6182 ('E', 'errorlog', '', _('name of error log file to write to'), _('FILE')),
6186 # use string type, then we can check if something was passed
6183 # use string type, then we can check if something was passed
6187 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6184 ('p', 'port', '', _('port to listen on (default: 8000)'), _('PORT')),
6188 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6185 ('a', 'address', '', _('address to listen on (default: all interfaces)'),
6189 _('ADDR')),
6186 _('ADDR')),
6190 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6187 ('', 'prefix', '', _('prefix path to serve from (default: server root)'),
6191 _('PREFIX')),
6188 _('PREFIX')),
6192 ('n', 'name', '',
6189 ('n', 'name', '',
6193 _('name to show in web pages (default: working directory)'), _('NAME')),
6190 _('name to show in web pages (default: working directory)'), _('NAME')),
6194 ('', 'web-conf', '',
6191 ('', 'web-conf', '',
6195 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6192 _('name of the hgweb config file (see "hg help hgweb")'), _('FILE')),
6196 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6193 ('', 'webdir-conf', '', _('name of the hgweb config file (DEPRECATED)'),
6197 _('FILE')),
6194 _('FILE')),
6198 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6195 ('', 'pid-file', '', _('name of file to write process ID to'), _('FILE')),
6199 ('', 'stdio', None, _('for remote clients')),
6196 ('', 'stdio', None, _('for remote clients')),
6200 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6197 ('', 'cmdserver', '', _('for remote clients'), _('MODE')),
6201 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6198 ('t', 'templates', '', _('web templates to use'), _('TEMPLATE')),
6202 ('', 'style', '', _('template style to use'), _('STYLE')),
6199 ('', 'style', '', _('template style to use'), _('STYLE')),
6203 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6200 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
6204 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6201 ('', 'certificate', '', _('SSL certificate file'), _('FILE'))],
6205 _('[OPTION]...'),
6202 _('[OPTION]...'),
6206 optionalrepo=True)
6203 optionalrepo=True)
6207 def serve(ui, repo, **opts):
6204 def serve(ui, repo, **opts):
6208 """start stand-alone webserver
6205 """start stand-alone webserver
6209
6206
6210 Start a local HTTP repository browser and pull server. You can use
6207 Start a local HTTP repository browser and pull server. You can use
6211 this for ad-hoc sharing and browsing of repositories. It is
6208 this for ad-hoc sharing and browsing of repositories. It is
6212 recommended to use a real web server to serve a repository for
6209 recommended to use a real web server to serve a repository for
6213 longer periods of time.
6210 longer periods of time.
6214
6211
6215 Please note that the server does not implement access control.
6212 Please note that the server does not implement access control.
6216 This means that, by default, anybody can read from the server and
6213 This means that, by default, anybody can read from the server and
6217 nobody can write to it by default. Set the ``web.allow_push``
6214 nobody can write to it by default. Set the ``web.allow_push``
6218 option to ``*`` to allow everybody to push to the server. You
6215 option to ``*`` to allow everybody to push to the server. You
6219 should use a real web server if you need to authenticate users.
6216 should use a real web server if you need to authenticate users.
6220
6217
6221 By default, the server logs accesses to stdout and errors to
6218 By default, the server logs accesses to stdout and errors to
6222 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6219 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
6223 files.
6220 files.
6224
6221
6225 To have the server choose a free port number to listen on, specify
6222 To have the server choose a free port number to listen on, specify
6226 a port number of 0; in this case, the server will print the port
6223 a port number of 0; in this case, the server will print the port
6227 number it uses.
6224 number it uses.
6228
6225
6229 Returns 0 on success.
6226 Returns 0 on success.
6230 """
6227 """
6231
6228
6232 if opts["stdio"] and opts["cmdserver"]:
6229 if opts["stdio"] and opts["cmdserver"]:
6233 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6230 raise error.Abort(_("cannot use --stdio with --cmdserver"))
6234
6231
6235 if opts["stdio"]:
6232 if opts["stdio"]:
6236 if repo is None:
6233 if repo is None:
6237 raise error.RepoError(_("there is no Mercurial repository here"
6234 raise error.RepoError(_("there is no Mercurial repository here"
6238 " (.hg not found)"))
6235 " (.hg not found)"))
6239 s = sshserver.sshserver(ui, repo)
6236 s = sshserver.sshserver(ui, repo)
6240 s.serve_forever()
6237 s.serve_forever()
6241
6238
6242 if opts["cmdserver"]:
6239 if opts["cmdserver"]:
6243 service = commandserver.createservice(ui, repo, opts)
6240 service = commandserver.createservice(ui, repo, opts)
6244 else:
6241 else:
6245 service = hgweb.createservice(ui, repo, opts)
6242 service = hgweb.createservice(ui, repo, opts)
6246 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6243 return cmdutil.service(opts, initfn=service.init, runfn=service.run)
6247
6244
6248 @command('^status|st',
6245 @command('^status|st',
6249 [('A', 'all', None, _('show status of all files')),
6246 [('A', 'all', None, _('show status of all files')),
6250 ('m', 'modified', None, _('show only modified files')),
6247 ('m', 'modified', None, _('show only modified files')),
6251 ('a', 'added', None, _('show only added files')),
6248 ('a', 'added', None, _('show only added files')),
6252 ('r', 'removed', None, _('show only removed files')),
6249 ('r', 'removed', None, _('show only removed files')),
6253 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6250 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
6254 ('c', 'clean', None, _('show only files without changes')),
6251 ('c', 'clean', None, _('show only files without changes')),
6255 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6252 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
6256 ('i', 'ignored', None, _('show only ignored files')),
6253 ('i', 'ignored', None, _('show only ignored files')),
6257 ('n', 'no-status', None, _('hide status prefix')),
6254 ('n', 'no-status', None, _('hide status prefix')),
6258 ('C', 'copies', None, _('show source of copied files')),
6255 ('C', 'copies', None, _('show source of copied files')),
6259 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6256 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
6260 ('', 'rev', [], _('show difference from revision'), _('REV')),
6257 ('', 'rev', [], _('show difference from revision'), _('REV')),
6261 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6258 ('', 'change', '', _('list the changed files of a revision'), _('REV')),
6262 ] + walkopts + subrepoopts + formatteropts,
6259 ] + walkopts + subrepoopts + formatteropts,
6263 _('[OPTION]... [FILE]...'),
6260 _('[OPTION]... [FILE]...'),
6264 inferrepo=True)
6261 inferrepo=True)
6265 def status(ui, repo, *pats, **opts):
6262 def status(ui, repo, *pats, **opts):
6266 """show changed files in the working directory
6263 """show changed files in the working directory
6267
6264
6268 Show status of files in the repository. If names are given, only
6265 Show status of files in the repository. If names are given, only
6269 files that match are shown. Files that are clean or ignored or
6266 files that match are shown. Files that are clean or ignored or
6270 the source of a copy/move operation, are not listed unless
6267 the source of a copy/move operation, are not listed unless
6271 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6268 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
6272 Unless options described with "show only ..." are given, the
6269 Unless options described with "show only ..." are given, the
6273 options -mardu are used.
6270 options -mardu are used.
6274
6271
6275 Option -q/--quiet hides untracked (unknown and ignored) files
6272 Option -q/--quiet hides untracked (unknown and ignored) files
6276 unless explicitly requested with -u/--unknown or -i/--ignored.
6273 unless explicitly requested with -u/--unknown or -i/--ignored.
6277
6274
6278 .. note::
6275 .. note::
6279
6276
6280 :hg:`status` may appear to disagree with diff if permissions have
6277 :hg:`status` may appear to disagree with diff if permissions have
6281 changed or a merge has occurred. The standard diff format does
6278 changed or a merge has occurred. The standard diff format does
6282 not report permission changes and diff only reports changes
6279 not report permission changes and diff only reports changes
6283 relative to one merge parent.
6280 relative to one merge parent.
6284
6281
6285 If one revision is given, it is used as the base revision.
6282 If one revision is given, it is used as the base revision.
6286 If two revisions are given, the differences between them are
6283 If two revisions are given, the differences between them are
6287 shown. The --change option can also be used as a shortcut to list
6284 shown. The --change option can also be used as a shortcut to list
6288 the changed files of a revision from its first parent.
6285 the changed files of a revision from its first parent.
6289
6286
6290 The codes used to show the status of files are::
6287 The codes used to show the status of files are::
6291
6288
6292 M = modified
6289 M = modified
6293 A = added
6290 A = added
6294 R = removed
6291 R = removed
6295 C = clean
6292 C = clean
6296 ! = missing (deleted by non-hg command, but still tracked)
6293 ! = missing (deleted by non-hg command, but still tracked)
6297 ? = not tracked
6294 ? = not tracked
6298 I = ignored
6295 I = ignored
6299 = origin of the previous file (with --copies)
6296 = origin of the previous file (with --copies)
6300
6297
6301 .. container:: verbose
6298 .. container:: verbose
6302
6299
6303 Examples:
6300 Examples:
6304
6301
6305 - show changes in the working directory relative to a
6302 - show changes in the working directory relative to a
6306 changeset::
6303 changeset::
6307
6304
6308 hg status --rev 9353
6305 hg status --rev 9353
6309
6306
6310 - show changes in the working directory relative to the
6307 - show changes in the working directory relative to the
6311 current directory (see :hg:`help patterns` for more information)::
6308 current directory (see :hg:`help patterns` for more information)::
6312
6309
6313 hg status re:
6310 hg status re:
6314
6311
6315 - show all changes including copies in an existing changeset::
6312 - show all changes including copies in an existing changeset::
6316
6313
6317 hg status --copies --change 9353
6314 hg status --copies --change 9353
6318
6315
6319 - get a NUL separated list of added files, suitable for xargs::
6316 - get a NUL separated list of added files, suitable for xargs::
6320
6317
6321 hg status -an0
6318 hg status -an0
6322
6319
6323 Returns 0 on success.
6320 Returns 0 on success.
6324 """
6321 """
6325
6322
6326 revs = opts.get('rev')
6323 revs = opts.get('rev')
6327 change = opts.get('change')
6324 change = opts.get('change')
6328
6325
6329 if revs and change:
6326 if revs and change:
6330 msg = _('cannot specify --rev and --change at the same time')
6327 msg = _('cannot specify --rev and --change at the same time')
6331 raise error.Abort(msg)
6328 raise error.Abort(msg)
6332 elif change:
6329 elif change:
6333 node2 = scmutil.revsingle(repo, change, None).node()
6330 node2 = scmutil.revsingle(repo, change, None).node()
6334 node1 = repo[node2].p1().node()
6331 node1 = repo[node2].p1().node()
6335 else:
6332 else:
6336 node1, node2 = scmutil.revpair(repo, revs)
6333 node1, node2 = scmutil.revpair(repo, revs)
6337
6334
6338 if pats:
6335 if pats:
6339 cwd = repo.getcwd()
6336 cwd = repo.getcwd()
6340 else:
6337 else:
6341 cwd = ''
6338 cwd = ''
6342
6339
6343 if opts.get('print0'):
6340 if opts.get('print0'):
6344 end = '\0'
6341 end = '\0'
6345 else:
6342 else:
6346 end = '\n'
6343 end = '\n'
6347 copy = {}
6344 copy = {}
6348 states = 'modified added removed deleted unknown ignored clean'.split()
6345 states = 'modified added removed deleted unknown ignored clean'.split()
6349 show = [k for k in states if opts.get(k)]
6346 show = [k for k in states if opts.get(k)]
6350 if opts.get('all'):
6347 if opts.get('all'):
6351 show += ui.quiet and (states[:4] + ['clean']) or states
6348 show += ui.quiet and (states[:4] + ['clean']) or states
6352 if not show:
6349 if not show:
6353 if ui.quiet:
6350 if ui.quiet:
6354 show = states[:4]
6351 show = states[:4]
6355 else:
6352 else:
6356 show = states[:5]
6353 show = states[:5]
6357
6354
6358 m = scmutil.match(repo[node2], pats, opts)
6355 m = scmutil.match(repo[node2], pats, opts)
6359 stat = repo.status(node1, node2, m,
6356 stat = repo.status(node1, node2, m,
6360 'ignored' in show, 'clean' in show, 'unknown' in show,
6357 'ignored' in show, 'clean' in show, 'unknown' in show,
6361 opts.get('subrepos'))
6358 opts.get('subrepos'))
6362 changestates = zip(states, 'MAR!?IC', stat)
6359 changestates = zip(states, 'MAR!?IC', stat)
6363
6360
6364 if (opts.get('all') or opts.get('copies')
6361 if (opts.get('all') or opts.get('copies')
6365 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6362 or ui.configbool('ui', 'statuscopies')) and not opts.get('no_status'):
6366 copy = copies.pathcopies(repo[node1], repo[node2], m)
6363 copy = copies.pathcopies(repo[node1], repo[node2], m)
6367
6364
6368 fm = ui.formatter('status', opts)
6365 fm = ui.formatter('status', opts)
6369 fmt = '%s' + end
6366 fmt = '%s' + end
6370 showchar = not opts.get('no_status')
6367 showchar = not opts.get('no_status')
6371
6368
6372 for state, char, files in changestates:
6369 for state, char, files in changestates:
6373 if state in show:
6370 if state in show:
6374 label = 'status.' + state
6371 label = 'status.' + state
6375 for f in files:
6372 for f in files:
6376 fm.startitem()
6373 fm.startitem()
6377 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6374 fm.condwrite(showchar, 'status', '%s ', char, label=label)
6378 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6375 fm.write('path', fmt, repo.pathto(f, cwd), label=label)
6379 if f in copy:
6376 if f in copy:
6380 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6377 fm.write("copy", ' %s' + end, repo.pathto(copy[f], cwd),
6381 label='status.copied')
6378 label='status.copied')
6382 fm.end()
6379 fm.end()
6383
6380
6384 @command('^summary|sum',
6381 @command('^summary|sum',
6385 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6382 [('', 'remote', None, _('check for push and pull'))], '[--remote]')
6386 def summary(ui, repo, **opts):
6383 def summary(ui, repo, **opts):
6387 """summarize working directory state
6384 """summarize working directory state
6388
6385
6389 This generates a brief summary of the working directory state,
6386 This generates a brief summary of the working directory state,
6390 including parents, branch, commit status, phase and available updates.
6387 including parents, branch, commit status, phase and available updates.
6391
6388
6392 With the --remote option, this will check the default paths for
6389 With the --remote option, this will check the default paths for
6393 incoming and outgoing changes. This can be time-consuming.
6390 incoming and outgoing changes. This can be time-consuming.
6394
6391
6395 Returns 0 on success.
6392 Returns 0 on success.
6396 """
6393 """
6397
6394
6398 ctx = repo[None]
6395 ctx = repo[None]
6399 parents = ctx.parents()
6396 parents = ctx.parents()
6400 pnode = parents[0].node()
6397 pnode = parents[0].node()
6401 marks = []
6398 marks = []
6402
6399
6403 for p in parents:
6400 for p in parents:
6404 # label with log.changeset (instead of log.parent) since this
6401 # label with log.changeset (instead of log.parent) since this
6405 # shows a working directory parent *changeset*:
6402 # shows a working directory parent *changeset*:
6406 # i18n: column positioning for "hg summary"
6403 # i18n: column positioning for "hg summary"
6407 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6404 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
6408 label='log.changeset changeset.%s' % p.phasestr())
6405 label='log.changeset changeset.%s' % p.phasestr())
6409 ui.write(' '.join(p.tags()), label='log.tag')
6406 ui.write(' '.join(p.tags()), label='log.tag')
6410 if p.bookmarks():
6407 if p.bookmarks():
6411 marks.extend(p.bookmarks())
6408 marks.extend(p.bookmarks())
6412 if p.rev() == -1:
6409 if p.rev() == -1:
6413 if not len(repo):
6410 if not len(repo):
6414 ui.write(_(' (empty repository)'))
6411 ui.write(_(' (empty repository)'))
6415 else:
6412 else:
6416 ui.write(_(' (no revision checked out)'))
6413 ui.write(_(' (no revision checked out)'))
6417 ui.write('\n')
6414 ui.write('\n')
6418 if p.description():
6415 if p.description():
6419 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6416 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
6420 label='log.summary')
6417 label='log.summary')
6421
6418
6422 branch = ctx.branch()
6419 branch = ctx.branch()
6423 bheads = repo.branchheads(branch)
6420 bheads = repo.branchheads(branch)
6424 # i18n: column positioning for "hg summary"
6421 # i18n: column positioning for "hg summary"
6425 m = _('branch: %s\n') % branch
6422 m = _('branch: %s\n') % branch
6426 if branch != 'default':
6423 if branch != 'default':
6427 ui.write(m, label='log.branch')
6424 ui.write(m, label='log.branch')
6428 else:
6425 else:
6429 ui.status(m, label='log.branch')
6426 ui.status(m, label='log.branch')
6430
6427
6431 if marks:
6428 if marks:
6432 active = repo._activebookmark
6429 active = repo._activebookmark
6433 # i18n: column positioning for "hg summary"
6430 # i18n: column positioning for "hg summary"
6434 ui.write(_('bookmarks:'), label='log.bookmark')
6431 ui.write(_('bookmarks:'), label='log.bookmark')
6435 if active is not None:
6432 if active is not None:
6436 if active in marks:
6433 if active in marks:
6437 ui.write(' *' + active, label=activebookmarklabel)
6434 ui.write(' *' + active, label=activebookmarklabel)
6438 marks.remove(active)
6435 marks.remove(active)
6439 else:
6436 else:
6440 ui.write(' [%s]' % active, label=activebookmarklabel)
6437 ui.write(' [%s]' % active, label=activebookmarklabel)
6441 for m in marks:
6438 for m in marks:
6442 ui.write(' ' + m, label='log.bookmark')
6439 ui.write(' ' + m, label='log.bookmark')
6443 ui.write('\n', label='log.bookmark')
6440 ui.write('\n', label='log.bookmark')
6444
6441
6445 status = repo.status(unknown=True)
6442 status = repo.status(unknown=True)
6446
6443
6447 c = repo.dirstate.copies()
6444 c = repo.dirstate.copies()
6448 copied, renamed = [], []
6445 copied, renamed = [], []
6449 for d, s in c.iteritems():
6446 for d, s in c.iteritems():
6450 if s in status.removed:
6447 if s in status.removed:
6451 status.removed.remove(s)
6448 status.removed.remove(s)
6452 renamed.append(d)
6449 renamed.append(d)
6453 else:
6450 else:
6454 copied.append(d)
6451 copied.append(d)
6455 if d in status.added:
6452 if d in status.added:
6456 status.added.remove(d)
6453 status.added.remove(d)
6457
6454
6458 try:
6455 try:
6459 ms = mergemod.mergestate.read(repo)
6456 ms = mergemod.mergestate.read(repo)
6460 except error.UnsupportedMergeRecords as e:
6457 except error.UnsupportedMergeRecords as e:
6461 s = ' '.join(e.recordtypes)
6458 s = ' '.join(e.recordtypes)
6462 ui.warn(
6459 ui.warn(
6463 _('warning: merge state has unsupported record types: %s\n') % s)
6460 _('warning: merge state has unsupported record types: %s\n') % s)
6464 unresolved = 0
6461 unresolved = 0
6465 else:
6462 else:
6466 unresolved = [f for f in ms if ms[f] == 'u']
6463 unresolved = [f for f in ms if ms[f] == 'u']
6467
6464
6468 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6465 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
6469
6466
6470 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6467 labels = [(ui.label(_('%d modified'), 'status.modified'), status.modified),
6471 (ui.label(_('%d added'), 'status.added'), status.added),
6468 (ui.label(_('%d added'), 'status.added'), status.added),
6472 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6469 (ui.label(_('%d removed'), 'status.removed'), status.removed),
6473 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6470 (ui.label(_('%d renamed'), 'status.copied'), renamed),
6474 (ui.label(_('%d copied'), 'status.copied'), copied),
6471 (ui.label(_('%d copied'), 'status.copied'), copied),
6475 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6472 (ui.label(_('%d deleted'), 'status.deleted'), status.deleted),
6476 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6473 (ui.label(_('%d unknown'), 'status.unknown'), status.unknown),
6477 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6474 (ui.label(_('%d unresolved'), 'resolve.unresolved'), unresolved),
6478 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6475 (ui.label(_('%d subrepos'), 'status.modified'), subs)]
6479 t = []
6476 t = []
6480 for l, s in labels:
6477 for l, s in labels:
6481 if s:
6478 if s:
6482 t.append(l % len(s))
6479 t.append(l % len(s))
6483
6480
6484 t = ', '.join(t)
6481 t = ', '.join(t)
6485 cleanworkdir = False
6482 cleanworkdir = False
6486
6483
6487 if repo.vfs.exists('graftstate'):
6484 if repo.vfs.exists('graftstate'):
6488 t += _(' (graft in progress)')
6485 t += _(' (graft in progress)')
6489 if repo.vfs.exists('updatestate'):
6486 if repo.vfs.exists('updatestate'):
6490 t += _(' (interrupted update)')
6487 t += _(' (interrupted update)')
6491 elif len(parents) > 1:
6488 elif len(parents) > 1:
6492 t += _(' (merge)')
6489 t += _(' (merge)')
6493 elif branch != parents[0].branch():
6490 elif branch != parents[0].branch():
6494 t += _(' (new branch)')
6491 t += _(' (new branch)')
6495 elif (parents[0].closesbranch() and
6492 elif (parents[0].closesbranch() and
6496 pnode in repo.branchheads(branch, closed=True)):
6493 pnode in repo.branchheads(branch, closed=True)):
6497 t += _(' (head closed)')
6494 t += _(' (head closed)')
6498 elif not (status.modified or status.added or status.removed or renamed or
6495 elif not (status.modified or status.added or status.removed or renamed or
6499 copied or subs):
6496 copied or subs):
6500 t += _(' (clean)')
6497 t += _(' (clean)')
6501 cleanworkdir = True
6498 cleanworkdir = True
6502 elif pnode not in bheads:
6499 elif pnode not in bheads:
6503 t += _(' (new branch head)')
6500 t += _(' (new branch head)')
6504
6501
6505 if parents:
6502 if parents:
6506 pendingphase = max(p.phase() for p in parents)
6503 pendingphase = max(p.phase() for p in parents)
6507 else:
6504 else:
6508 pendingphase = phases.public
6505 pendingphase = phases.public
6509
6506
6510 if pendingphase > phases.newcommitphase(ui):
6507 if pendingphase > phases.newcommitphase(ui):
6511 t += ' (%s)' % phases.phasenames[pendingphase]
6508 t += ' (%s)' % phases.phasenames[pendingphase]
6512
6509
6513 if cleanworkdir:
6510 if cleanworkdir:
6514 # i18n: column positioning for "hg summary"
6511 # i18n: column positioning for "hg summary"
6515 ui.status(_('commit: %s\n') % t.strip())
6512 ui.status(_('commit: %s\n') % t.strip())
6516 else:
6513 else:
6517 # i18n: column positioning for "hg summary"
6514 # i18n: column positioning for "hg summary"
6518 ui.write(_('commit: %s\n') % t.strip())
6515 ui.write(_('commit: %s\n') % t.strip())
6519
6516
6520 # all ancestors of branch heads - all ancestors of parent = new csets
6517 # all ancestors of branch heads - all ancestors of parent = new csets
6521 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6518 new = len(repo.changelog.findmissing([pctx.node() for pctx in parents],
6522 bheads))
6519 bheads))
6523
6520
6524 if new == 0:
6521 if new == 0:
6525 # i18n: column positioning for "hg summary"
6522 # i18n: column positioning for "hg summary"
6526 ui.status(_('update: (current)\n'))
6523 ui.status(_('update: (current)\n'))
6527 elif pnode not in bheads:
6524 elif pnode not in bheads:
6528 # i18n: column positioning for "hg summary"
6525 # i18n: column positioning for "hg summary"
6529 ui.write(_('update: %d new changesets (update)\n') % new)
6526 ui.write(_('update: %d new changesets (update)\n') % new)
6530 else:
6527 else:
6531 # i18n: column positioning for "hg summary"
6528 # i18n: column positioning for "hg summary"
6532 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6529 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
6533 (new, len(bheads)))
6530 (new, len(bheads)))
6534
6531
6535 t = []
6532 t = []
6536 draft = len(repo.revs('draft()'))
6533 draft = len(repo.revs('draft()'))
6537 if draft:
6534 if draft:
6538 t.append(_('%d draft') % draft)
6535 t.append(_('%d draft') % draft)
6539 secret = len(repo.revs('secret()'))
6536 secret = len(repo.revs('secret()'))
6540 if secret:
6537 if secret:
6541 t.append(_('%d secret') % secret)
6538 t.append(_('%d secret') % secret)
6542
6539
6543 if draft or secret:
6540 if draft or secret:
6544 ui.status(_('phases: %s\n') % ', '.join(t))
6541 ui.status(_('phases: %s\n') % ', '.join(t))
6545
6542
6546 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6543 if obsolete.isenabled(repo, obsolete.createmarkersopt):
6547 for trouble in ("unstable", "divergent", "bumped"):
6544 for trouble in ("unstable", "divergent", "bumped"):
6548 numtrouble = len(repo.revs(trouble + "()"))
6545 numtrouble = len(repo.revs(trouble + "()"))
6549 # We write all the possibilities to ease translation
6546 # We write all the possibilities to ease translation
6550 troublemsg = {
6547 troublemsg = {
6551 "unstable": _("unstable: %d changesets"),
6548 "unstable": _("unstable: %d changesets"),
6552 "divergent": _("divergent: %d changesets"),
6549 "divergent": _("divergent: %d changesets"),
6553 "bumped": _("bumped: %d changesets"),
6550 "bumped": _("bumped: %d changesets"),
6554 }
6551 }
6555 if numtrouble > 0:
6552 if numtrouble > 0:
6556 ui.status(troublemsg[trouble] % numtrouble + "\n")
6553 ui.status(troublemsg[trouble] % numtrouble + "\n")
6557
6554
6558 cmdutil.summaryhooks(ui, repo)
6555 cmdutil.summaryhooks(ui, repo)
6559
6556
6560 if opts.get('remote'):
6557 if opts.get('remote'):
6561 needsincoming, needsoutgoing = True, True
6558 needsincoming, needsoutgoing = True, True
6562 else:
6559 else:
6563 needsincoming, needsoutgoing = False, False
6560 needsincoming, needsoutgoing = False, False
6564 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6561 for i, o in cmdutil.summaryremotehooks(ui, repo, opts, None):
6565 if i:
6562 if i:
6566 needsincoming = True
6563 needsincoming = True
6567 if o:
6564 if o:
6568 needsoutgoing = True
6565 needsoutgoing = True
6569 if not needsincoming and not needsoutgoing:
6566 if not needsincoming and not needsoutgoing:
6570 return
6567 return
6571
6568
6572 def getincoming():
6569 def getincoming():
6573 source, branches = hg.parseurl(ui.expandpath('default'))
6570 source, branches = hg.parseurl(ui.expandpath('default'))
6574 sbranch = branches[0]
6571 sbranch = branches[0]
6575 try:
6572 try:
6576 other = hg.peer(repo, {}, source)
6573 other = hg.peer(repo, {}, source)
6577 except error.RepoError:
6574 except error.RepoError:
6578 if opts.get('remote'):
6575 if opts.get('remote'):
6579 raise
6576 raise
6580 return source, sbranch, None, None, None
6577 return source, sbranch, None, None, None
6581 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6578 revs, checkout = hg.addbranchrevs(repo, other, branches, None)
6582 if revs:
6579 if revs:
6583 revs = [other.lookup(rev) for rev in revs]
6580 revs = [other.lookup(rev) for rev in revs]
6584 ui.debug('comparing with %s\n' % util.hidepassword(source))
6581 ui.debug('comparing with %s\n' % util.hidepassword(source))
6585 repo.ui.pushbuffer()
6582 repo.ui.pushbuffer()
6586 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6583 commoninc = discovery.findcommonincoming(repo, other, heads=revs)
6587 repo.ui.popbuffer()
6584 repo.ui.popbuffer()
6588 return source, sbranch, other, commoninc, commoninc[1]
6585 return source, sbranch, other, commoninc, commoninc[1]
6589
6586
6590 if needsincoming:
6587 if needsincoming:
6591 source, sbranch, sother, commoninc, incoming = getincoming()
6588 source, sbranch, sother, commoninc, incoming = getincoming()
6592 else:
6589 else:
6593 source = sbranch = sother = commoninc = incoming = None
6590 source = sbranch = sother = commoninc = incoming = None
6594
6591
6595 def getoutgoing():
6592 def getoutgoing():
6596 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6593 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
6597 dbranch = branches[0]
6594 dbranch = branches[0]
6598 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6595 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
6599 if source != dest:
6596 if source != dest:
6600 try:
6597 try:
6601 dother = hg.peer(repo, {}, dest)
6598 dother = hg.peer(repo, {}, dest)
6602 except error.RepoError:
6599 except error.RepoError:
6603 if opts.get('remote'):
6600 if opts.get('remote'):
6604 raise
6601 raise
6605 return dest, dbranch, None, None
6602 return dest, dbranch, None, None
6606 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6603 ui.debug('comparing with %s\n' % util.hidepassword(dest))
6607 elif sother is None:
6604 elif sother is None:
6608 # there is no explicit destination peer, but source one is invalid
6605 # there is no explicit destination peer, but source one is invalid
6609 return dest, dbranch, None, None
6606 return dest, dbranch, None, None
6610 else:
6607 else:
6611 dother = sother
6608 dother = sother
6612 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6609 if (source != dest or (sbranch is not None and sbranch != dbranch)):
6613 common = None
6610 common = None
6614 else:
6611 else:
6615 common = commoninc
6612 common = commoninc
6616 if revs:
6613 if revs:
6617 revs = [repo.lookup(rev) for rev in revs]
6614 revs = [repo.lookup(rev) for rev in revs]
6618 repo.ui.pushbuffer()
6615 repo.ui.pushbuffer()
6619 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6616 outgoing = discovery.findcommonoutgoing(repo, dother, onlyheads=revs,
6620 commoninc=common)
6617 commoninc=common)
6621 repo.ui.popbuffer()
6618 repo.ui.popbuffer()
6622 return dest, dbranch, dother, outgoing
6619 return dest, dbranch, dother, outgoing
6623
6620
6624 if needsoutgoing:
6621 if needsoutgoing:
6625 dest, dbranch, dother, outgoing = getoutgoing()
6622 dest, dbranch, dother, outgoing = getoutgoing()
6626 else:
6623 else:
6627 dest = dbranch = dother = outgoing = None
6624 dest = dbranch = dother = outgoing = None
6628
6625
6629 if opts.get('remote'):
6626 if opts.get('remote'):
6630 t = []
6627 t = []
6631 if incoming:
6628 if incoming:
6632 t.append(_('1 or more incoming'))
6629 t.append(_('1 or more incoming'))
6633 o = outgoing.missing
6630 o = outgoing.missing
6634 if o:
6631 if o:
6635 t.append(_('%d outgoing') % len(o))
6632 t.append(_('%d outgoing') % len(o))
6636 other = dother or sother
6633 other = dother or sother
6637 if 'bookmarks' in other.listkeys('namespaces'):
6634 if 'bookmarks' in other.listkeys('namespaces'):
6638 counts = bookmarks.summary(repo, other)
6635 counts = bookmarks.summary(repo, other)
6639 if counts[0] > 0:
6636 if counts[0] > 0:
6640 t.append(_('%d incoming bookmarks') % counts[0])
6637 t.append(_('%d incoming bookmarks') % counts[0])
6641 if counts[1] > 0:
6638 if counts[1] > 0:
6642 t.append(_('%d outgoing bookmarks') % counts[1])
6639 t.append(_('%d outgoing bookmarks') % counts[1])
6643
6640
6644 if t:
6641 if t:
6645 # i18n: column positioning for "hg summary"
6642 # i18n: column positioning for "hg summary"
6646 ui.write(_('remote: %s\n') % (', '.join(t)))
6643 ui.write(_('remote: %s\n') % (', '.join(t)))
6647 else:
6644 else:
6648 # i18n: column positioning for "hg summary"
6645 # i18n: column positioning for "hg summary"
6649 ui.status(_('remote: (synced)\n'))
6646 ui.status(_('remote: (synced)\n'))
6650
6647
6651 cmdutil.summaryremotehooks(ui, repo, opts,
6648 cmdutil.summaryremotehooks(ui, repo, opts,
6652 ((source, sbranch, sother, commoninc),
6649 ((source, sbranch, sother, commoninc),
6653 (dest, dbranch, dother, outgoing)))
6650 (dest, dbranch, dother, outgoing)))
6654
6651
6655 @command('tag',
6652 @command('tag',
6656 [('f', 'force', None, _('force tag')),
6653 [('f', 'force', None, _('force tag')),
6657 ('l', 'local', None, _('make the tag local')),
6654 ('l', 'local', None, _('make the tag local')),
6658 ('r', 'rev', '', _('revision to tag'), _('REV')),
6655 ('r', 'rev', '', _('revision to tag'), _('REV')),
6659 ('', 'remove', None, _('remove a tag')),
6656 ('', 'remove', None, _('remove a tag')),
6660 # -l/--local is already there, commitopts cannot be used
6657 # -l/--local is already there, commitopts cannot be used
6661 ('e', 'edit', None, _('invoke editor on commit messages')),
6658 ('e', 'edit', None, _('invoke editor on commit messages')),
6662 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6659 ('m', 'message', '', _('use text as commit message'), _('TEXT')),
6663 ] + commitopts2,
6660 ] + commitopts2,
6664 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6661 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...'))
6665 def tag(ui, repo, name1, *names, **opts):
6662 def tag(ui, repo, name1, *names, **opts):
6666 """add one or more tags for the current or given revision
6663 """add one or more tags for the current or given revision
6667
6664
6668 Name a particular revision using <name>.
6665 Name a particular revision using <name>.
6669
6666
6670 Tags are used to name particular revisions of the repository and are
6667 Tags are used to name particular revisions of the repository and are
6671 very useful to compare different revisions, to go back to significant
6668 very useful to compare different revisions, to go back to significant
6672 earlier versions or to mark branch points as releases, etc. Changing
6669 earlier versions or to mark branch points as releases, etc. Changing
6673 an existing tag is normally disallowed; use -f/--force to override.
6670 an existing tag is normally disallowed; use -f/--force to override.
6674
6671
6675 If no revision is given, the parent of the working directory is
6672 If no revision is given, the parent of the working directory is
6676 used.
6673 used.
6677
6674
6678 To facilitate version control, distribution, and merging of tags,
6675 To facilitate version control, distribution, and merging of tags,
6679 they are stored as a file named ".hgtags" which is managed similarly
6676 they are stored as a file named ".hgtags" which is managed similarly
6680 to other project files and can be hand-edited if necessary. This
6677 to other project files and can be hand-edited if necessary. This
6681 also means that tagging creates a new commit. The file
6678 also means that tagging creates a new commit. The file
6682 ".hg/localtags" is used for local tags (not shared among
6679 ".hg/localtags" is used for local tags (not shared among
6683 repositories).
6680 repositories).
6684
6681
6685 Tag commits are usually made at the head of a branch. If the parent
6682 Tag commits are usually made at the head of a branch. If the parent
6686 of the working directory is not a branch head, :hg:`tag` aborts; use
6683 of the working directory is not a branch head, :hg:`tag` aborts; use
6687 -f/--force to force the tag commit to be based on a non-head
6684 -f/--force to force the tag commit to be based on a non-head
6688 changeset.
6685 changeset.
6689
6686
6690 See :hg:`help dates` for a list of formats valid for -d/--date.
6687 See :hg:`help dates` for a list of formats valid for -d/--date.
6691
6688
6692 Since tag names have priority over branch names during revision
6689 Since tag names have priority over branch names during revision
6693 lookup, using an existing branch name as a tag name is discouraged.
6690 lookup, using an existing branch name as a tag name is discouraged.
6694
6691
6695 Returns 0 on success.
6692 Returns 0 on success.
6696 """
6693 """
6697 wlock = lock = None
6694 wlock = lock = None
6698 try:
6695 try:
6699 wlock = repo.wlock()
6696 wlock = repo.wlock()
6700 lock = repo.lock()
6697 lock = repo.lock()
6701 rev_ = "."
6698 rev_ = "."
6702 names = [t.strip() for t in (name1,) + names]
6699 names = [t.strip() for t in (name1,) + names]
6703 if len(names) != len(set(names)):
6700 if len(names) != len(set(names)):
6704 raise error.Abort(_('tag names must be unique'))
6701 raise error.Abort(_('tag names must be unique'))
6705 for n in names:
6702 for n in names:
6706 scmutil.checknewlabel(repo, n, 'tag')
6703 scmutil.checknewlabel(repo, n, 'tag')
6707 if not n:
6704 if not n:
6708 raise error.Abort(_('tag names cannot consist entirely of '
6705 raise error.Abort(_('tag names cannot consist entirely of '
6709 'whitespace'))
6706 'whitespace'))
6710 if opts.get('rev') and opts.get('remove'):
6707 if opts.get('rev') and opts.get('remove'):
6711 raise error.Abort(_("--rev and --remove are incompatible"))
6708 raise error.Abort(_("--rev and --remove are incompatible"))
6712 if opts.get('rev'):
6709 if opts.get('rev'):
6713 rev_ = opts['rev']
6710 rev_ = opts['rev']
6714 message = opts.get('message')
6711 message = opts.get('message')
6715 if opts.get('remove'):
6712 if opts.get('remove'):
6716 if opts.get('local'):
6713 if opts.get('local'):
6717 expectedtype = 'local'
6714 expectedtype = 'local'
6718 else:
6715 else:
6719 expectedtype = 'global'
6716 expectedtype = 'global'
6720
6717
6721 for n in names:
6718 for n in names:
6722 if not repo.tagtype(n):
6719 if not repo.tagtype(n):
6723 raise error.Abort(_("tag '%s' does not exist") % n)
6720 raise error.Abort(_("tag '%s' does not exist") % n)
6724 if repo.tagtype(n) != expectedtype:
6721 if repo.tagtype(n) != expectedtype:
6725 if expectedtype == 'global':
6722 if expectedtype == 'global':
6726 raise error.Abort(_("tag '%s' is not a global tag") % n)
6723 raise error.Abort(_("tag '%s' is not a global tag") % n)
6727 else:
6724 else:
6728 raise error.Abort(_("tag '%s' is not a local tag") % n)
6725 raise error.Abort(_("tag '%s' is not a local tag") % n)
6729 rev_ = 'null'
6726 rev_ = 'null'
6730 if not message:
6727 if not message:
6731 # we don't translate commit messages
6728 # we don't translate commit messages
6732 message = 'Removed tag %s' % ', '.join(names)
6729 message = 'Removed tag %s' % ', '.join(names)
6733 elif not opts.get('force'):
6730 elif not opts.get('force'):
6734 for n in names:
6731 for n in names:
6735 if n in repo.tags():
6732 if n in repo.tags():
6736 raise error.Abort(_("tag '%s' already exists "
6733 raise error.Abort(_("tag '%s' already exists "
6737 "(use -f to force)") % n)
6734 "(use -f to force)") % n)
6738 if not opts.get('local'):
6735 if not opts.get('local'):
6739 p1, p2 = repo.dirstate.parents()
6736 p1, p2 = repo.dirstate.parents()
6740 if p2 != nullid:
6737 if p2 != nullid:
6741 raise error.Abort(_('uncommitted merge'))
6738 raise error.Abort(_('uncommitted merge'))
6742 bheads = repo.branchheads()
6739 bheads = repo.branchheads()
6743 if not opts.get('force') and bheads and p1 not in bheads:
6740 if not opts.get('force') and bheads and p1 not in bheads:
6744 raise error.Abort(_('not at a branch head (use -f to force)'))
6741 raise error.Abort(_('not at a branch head (use -f to force)'))
6745 r = scmutil.revsingle(repo, rev_).node()
6742 r = scmutil.revsingle(repo, rev_).node()
6746
6743
6747 if not message:
6744 if not message:
6748 # we don't translate commit messages
6745 # we don't translate commit messages
6749 message = ('Added tag %s for changeset %s' %
6746 message = ('Added tag %s for changeset %s' %
6750 (', '.join(names), short(r)))
6747 (', '.join(names), short(r)))
6751
6748
6752 date = opts.get('date')
6749 date = opts.get('date')
6753 if date:
6750 if date:
6754 date = util.parsedate(date)
6751 date = util.parsedate(date)
6755
6752
6756 if opts.get('remove'):
6753 if opts.get('remove'):
6757 editform = 'tag.remove'
6754 editform = 'tag.remove'
6758 else:
6755 else:
6759 editform = 'tag.add'
6756 editform = 'tag.add'
6760 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6757 editor = cmdutil.getcommiteditor(editform=editform, **opts)
6761
6758
6762 # don't allow tagging the null rev
6759 # don't allow tagging the null rev
6763 if (not opts.get('remove') and
6760 if (not opts.get('remove') and
6764 scmutil.revsingle(repo, rev_).rev() == nullrev):
6761 scmutil.revsingle(repo, rev_).rev() == nullrev):
6765 raise error.Abort(_("cannot tag null revision"))
6762 raise error.Abort(_("cannot tag null revision"))
6766
6763
6767 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6764 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date,
6768 editor=editor)
6765 editor=editor)
6769 finally:
6766 finally:
6770 release(lock, wlock)
6767 release(lock, wlock)
6771
6768
6772 @command('tags', formatteropts, '')
6769 @command('tags', formatteropts, '')
6773 def tags(ui, repo, **opts):
6770 def tags(ui, repo, **opts):
6774 """list repository tags
6771 """list repository tags
6775
6772
6776 This lists both regular and local tags. When the -v/--verbose
6773 This lists both regular and local tags. When the -v/--verbose
6777 switch is used, a third column "local" is printed for local tags.
6774 switch is used, a third column "local" is printed for local tags.
6778 When the -q/--quiet switch is used, only the tag name is printed.
6775 When the -q/--quiet switch is used, only the tag name is printed.
6779
6776
6780 Returns 0 on success.
6777 Returns 0 on success.
6781 """
6778 """
6782
6779
6783 fm = ui.formatter('tags', opts)
6780 fm = ui.formatter('tags', opts)
6784 hexfunc = fm.hexfunc
6781 hexfunc = fm.hexfunc
6785 tagtype = ""
6782 tagtype = ""
6786
6783
6787 for t, n in reversed(repo.tagslist()):
6784 for t, n in reversed(repo.tagslist()):
6788 hn = hexfunc(n)
6785 hn = hexfunc(n)
6789 label = 'tags.normal'
6786 label = 'tags.normal'
6790 tagtype = ''
6787 tagtype = ''
6791 if repo.tagtype(t) == 'local':
6788 if repo.tagtype(t) == 'local':
6792 label = 'tags.local'
6789 label = 'tags.local'
6793 tagtype = 'local'
6790 tagtype = 'local'
6794
6791
6795 fm.startitem()
6792 fm.startitem()
6796 fm.write('tag', '%s', t, label=label)
6793 fm.write('tag', '%s', t, label=label)
6797 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6794 fmt = " " * (30 - encoding.colwidth(t)) + ' %5d:%s'
6798 fm.condwrite(not ui.quiet, 'rev node', fmt,
6795 fm.condwrite(not ui.quiet, 'rev node', fmt,
6799 repo.changelog.rev(n), hn, label=label)
6796 repo.changelog.rev(n), hn, label=label)
6800 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6797 fm.condwrite(ui.verbose and tagtype, 'type', ' %s',
6801 tagtype, label=label)
6798 tagtype, label=label)
6802 fm.plain('\n')
6799 fm.plain('\n')
6803 fm.end()
6800 fm.end()
6804
6801
6805 @command('tip',
6802 @command('tip',
6806 [('p', 'patch', None, _('show patch')),
6803 [('p', 'patch', None, _('show patch')),
6807 ('g', 'git', None, _('use git extended diff format')),
6804 ('g', 'git', None, _('use git extended diff format')),
6808 ] + templateopts,
6805 ] + templateopts,
6809 _('[-p] [-g]'))
6806 _('[-p] [-g]'))
6810 def tip(ui, repo, **opts):
6807 def tip(ui, repo, **opts):
6811 """show the tip revision (DEPRECATED)
6808 """show the tip revision (DEPRECATED)
6812
6809
6813 The tip revision (usually just called the tip) is the changeset
6810 The tip revision (usually just called the tip) is the changeset
6814 most recently added to the repository (and therefore the most
6811 most recently added to the repository (and therefore the most
6815 recently changed head).
6812 recently changed head).
6816
6813
6817 If you have just made a commit, that commit will be the tip. If
6814 If you have just made a commit, that commit will be the tip. If
6818 you have just pulled changes from another repository, the tip of
6815 you have just pulled changes from another repository, the tip of
6819 that repository becomes the current tip. The "tip" tag is special
6816 that repository becomes the current tip. The "tip" tag is special
6820 and cannot be renamed or assigned to a different changeset.
6817 and cannot be renamed or assigned to a different changeset.
6821
6818
6822 This command is deprecated, please use :hg:`heads` instead.
6819 This command is deprecated, please use :hg:`heads` instead.
6823
6820
6824 Returns 0 on success.
6821 Returns 0 on success.
6825 """
6822 """
6826 displayer = cmdutil.show_changeset(ui, repo, opts)
6823 displayer = cmdutil.show_changeset(ui, repo, opts)
6827 displayer.show(repo['tip'])
6824 displayer.show(repo['tip'])
6828 displayer.close()
6825 displayer.close()
6829
6826
6830 @command('unbundle',
6827 @command('unbundle',
6831 [('u', 'update', None,
6828 [('u', 'update', None,
6832 _('update to new branch head if changesets were unbundled'))],
6829 _('update to new branch head if changesets were unbundled'))],
6833 _('[-u] FILE...'))
6830 _('[-u] FILE...'))
6834 def unbundle(ui, repo, fname1, *fnames, **opts):
6831 def unbundle(ui, repo, fname1, *fnames, **opts):
6835 """apply one or more changegroup files
6832 """apply one or more changegroup files
6836
6833
6837 Apply one or more compressed changegroup files generated by the
6834 Apply one or more compressed changegroup files generated by the
6838 bundle command.
6835 bundle command.
6839
6836
6840 Returns 0 on success, 1 if an update has unresolved files.
6837 Returns 0 on success, 1 if an update has unresolved files.
6841 """
6838 """
6842 fnames = (fname1,) + fnames
6839 fnames = (fname1,) + fnames
6843
6840
6844 lock = repo.lock()
6841 lock = repo.lock()
6845 try:
6842 try:
6846 for fname in fnames:
6843 for fname in fnames:
6847 f = hg.openpath(ui, fname)
6844 f = hg.openpath(ui, fname)
6848 gen = exchange.readbundle(ui, f, fname)
6845 gen = exchange.readbundle(ui, f, fname)
6849 if isinstance(gen, bundle2.unbundle20):
6846 if isinstance(gen, bundle2.unbundle20):
6850 tr = repo.transaction('unbundle')
6847 tr = repo.transaction('unbundle')
6851 try:
6848 try:
6852 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6849 op = bundle2.applybundle(repo, gen, tr, source='unbundle',
6853 url='bundle:' + fname)
6850 url='bundle:' + fname)
6854 tr.close()
6851 tr.close()
6855 except error.BundleUnknownFeatureError as exc:
6852 except error.BundleUnknownFeatureError as exc:
6856 raise error.Abort(_('%s: unknown bundle feature, %s')
6853 raise error.Abort(_('%s: unknown bundle feature, %s')
6857 % (fname, exc),
6854 % (fname, exc),
6858 hint=_("see https://mercurial-scm.org/"
6855 hint=_("see https://mercurial-scm.org/"
6859 "wiki/BundleFeature for more "
6856 "wiki/BundleFeature for more "
6860 "information"))
6857 "information"))
6861 finally:
6858 finally:
6862 if tr:
6859 if tr:
6863 tr.release()
6860 tr.release()
6864 changes = [r.get('return', 0)
6861 changes = [r.get('return', 0)
6865 for r in op.records['changegroup']]
6862 for r in op.records['changegroup']]
6866 modheads = changegroup.combineresults(changes)
6863 modheads = changegroup.combineresults(changes)
6867 elif isinstance(gen, streamclone.streamcloneapplier):
6864 elif isinstance(gen, streamclone.streamcloneapplier):
6868 raise error.Abort(
6865 raise error.Abort(
6869 _('packed bundles cannot be applied with '
6866 _('packed bundles cannot be applied with '
6870 '"hg unbundle"'),
6867 '"hg unbundle"'),
6871 hint=_('use "hg debugapplystreamclonebundle"'))
6868 hint=_('use "hg debugapplystreamclonebundle"'))
6872 else:
6869 else:
6873 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6870 modheads = gen.apply(repo, 'unbundle', 'bundle:' + fname)
6874 finally:
6871 finally:
6875 lock.release()
6872 lock.release()
6876
6873
6877 return postincoming(ui, repo, modheads, opts.get('update'), None)
6874 return postincoming(ui, repo, modheads, opts.get('update'), None)
6878
6875
6879 @command('^update|up|checkout|co',
6876 @command('^update|up|checkout|co',
6880 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6877 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
6881 ('c', 'check', None,
6878 ('c', 'check', None,
6882 _('update across branches if no uncommitted changes')),
6879 _('update across branches if no uncommitted changes')),
6883 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6880 ('d', 'date', '', _('tipmost revision matching date'), _('DATE')),
6884 ('r', 'rev', '', _('revision'), _('REV'))
6881 ('r', 'rev', '', _('revision'), _('REV'))
6885 ] + mergetoolopts,
6882 ] + mergetoolopts,
6886 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6883 _('[-c] [-C] [-d DATE] [[-r] REV]'))
6887 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6884 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False,
6888 tool=None):
6885 tool=None):
6889 """update working directory (or switch revisions)
6886 """update working directory (or switch revisions)
6890
6887
6891 Update the repository's working directory to the specified
6888 Update the repository's working directory to the specified
6892 changeset. If no changeset is specified, update to the tip of the
6889 changeset. If no changeset is specified, update to the tip of the
6893 current named branch and move the active bookmark (see :hg:`help
6890 current named branch and move the active bookmark (see :hg:`help
6894 bookmarks`).
6891 bookmarks`).
6895
6892
6896 Update sets the working directory's parent revision to the specified
6893 Update sets the working directory's parent revision to the specified
6897 changeset (see :hg:`help parents`).
6894 changeset (see :hg:`help parents`).
6898
6895
6899 If the changeset is not a descendant or ancestor of the working
6896 If the changeset is not a descendant or ancestor of the working
6900 directory's parent, the update is aborted. With the -c/--check
6897 directory's parent, the update is aborted. With the -c/--check
6901 option, the working directory is checked for uncommitted changes; if
6898 option, the working directory is checked for uncommitted changes; if
6902 none are found, the working directory is updated to the specified
6899 none are found, the working directory is updated to the specified
6903 changeset.
6900 changeset.
6904
6901
6905 .. container:: verbose
6902 .. container:: verbose
6906
6903
6907 The following rules apply when the working directory contains
6904 The following rules apply when the working directory contains
6908 uncommitted changes:
6905 uncommitted changes:
6909
6906
6910 1. If neither -c/--check nor -C/--clean is specified, and if
6907 1. If neither -c/--check nor -C/--clean is specified, and if
6911 the requested changeset is an ancestor or descendant of
6908 the requested changeset is an ancestor or descendant of
6912 the working directory's parent, the uncommitted changes
6909 the working directory's parent, the uncommitted changes
6913 are merged into the requested changeset and the merged
6910 are merged into the requested changeset and the merged
6914 result is left uncommitted. If the requested changeset is
6911 result is left uncommitted. If the requested changeset is
6915 not an ancestor or descendant (that is, it is on another
6912 not an ancestor or descendant (that is, it is on another
6916 branch), the update is aborted and the uncommitted changes
6913 branch), the update is aborted and the uncommitted changes
6917 are preserved.
6914 are preserved.
6918
6915
6919 2. With the -c/--check option, the update is aborted and the
6916 2. With the -c/--check option, the update is aborted and the
6920 uncommitted changes are preserved.
6917 uncommitted changes are preserved.
6921
6918
6922 3. With the -C/--clean option, uncommitted changes are discarded and
6919 3. With the -C/--clean option, uncommitted changes are discarded and
6923 the working directory is updated to the requested changeset.
6920 the working directory is updated to the requested changeset.
6924
6921
6925 To cancel an uncommitted merge (and lose your changes), use
6922 To cancel an uncommitted merge (and lose your changes), use
6926 :hg:`update --clean .`.
6923 :hg:`update --clean .`.
6927
6924
6928 Use null as the changeset to remove the working directory (like
6925 Use null as the changeset to remove the working directory (like
6929 :hg:`clone -U`).
6926 :hg:`clone -U`).
6930
6927
6931 If you want to revert just one file to an older revision, use
6928 If you want to revert just one file to an older revision, use
6932 :hg:`revert [-r REV] NAME`.
6929 :hg:`revert [-r REV] NAME`.
6933
6930
6934 See :hg:`help dates` for a list of formats valid for -d/--date.
6931 See :hg:`help dates` for a list of formats valid for -d/--date.
6935
6932
6936 Returns 0 on success, 1 if there are unresolved files.
6933 Returns 0 on success, 1 if there are unresolved files.
6937 """
6934 """
6938 movemarkfrom = None
6935 movemarkfrom = None
6939 if rev and node:
6936 if rev and node:
6940 raise error.Abort(_("please specify just one revision"))
6937 raise error.Abort(_("please specify just one revision"))
6941
6938
6942 if rev is None or rev == '':
6939 if rev is None or rev == '':
6943 rev = node
6940 rev = node
6944
6941
6945 wlock = repo.wlock()
6942 wlock = repo.wlock()
6946 try:
6943 try:
6947 cmdutil.clearunfinished(repo)
6944 cmdutil.clearunfinished(repo)
6948
6945
6949 if date:
6946 if date:
6950 if rev is not None:
6947 if rev is not None:
6951 raise error.Abort(_("you can't specify a revision and a date"))
6948 raise error.Abort(_("you can't specify a revision and a date"))
6952 rev = cmdutil.finddate(ui, repo, date)
6949 rev = cmdutil.finddate(ui, repo, date)
6953
6950
6954 # if we defined a bookmark, we have to remember the original name
6951 # if we defined a bookmark, we have to remember the original name
6955 brev = rev
6952 brev = rev
6956 rev = scmutil.revsingle(repo, rev, rev).rev()
6953 rev = scmutil.revsingle(repo, rev, rev).rev()
6957
6954
6958 if check and clean:
6955 if check and clean:
6959 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6956 raise error.Abort(_("cannot specify both -c/--check and -C/--clean")
6960 )
6957 )
6961
6958
6962 if check:
6959 if check:
6963 cmdutil.bailifchanged(repo, merge=False)
6960 cmdutil.bailifchanged(repo, merge=False)
6964 if rev is None:
6961 if rev is None:
6965 updata = destutil.destupdate(repo, clean=clean, check=check)
6962 updata = destutil.destupdate(repo, clean=clean, check=check)
6966 rev, movemarkfrom, brev = updata
6963 rev, movemarkfrom, brev = updata
6967
6964
6968 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6965 repo.ui.setconfig('ui', 'forcemerge', tool, 'update')
6969
6966
6970 if clean:
6967 if clean:
6971 ret = hg.clean(repo, rev)
6968 ret = hg.clean(repo, rev)
6972 else:
6969 else:
6973 ret = hg.update(repo, rev)
6970 ret = hg.update(repo, rev)
6974
6971
6975 if not ret and movemarkfrom:
6972 if not ret and movemarkfrom:
6976 if movemarkfrom == repo['.'].node():
6973 if movemarkfrom == repo['.'].node():
6977 pass # no-op update
6974 pass # no-op update
6978 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6975 elif bookmarks.update(repo, [movemarkfrom], repo['.'].node()):
6979 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6976 ui.status(_("updating bookmark %s\n") % repo._activebookmark)
6980 else:
6977 else:
6981 # this can happen with a non-linear update
6978 # this can happen with a non-linear update
6982 ui.status(_("(leaving bookmark %s)\n") %
6979 ui.status(_("(leaving bookmark %s)\n") %
6983 repo._activebookmark)
6980 repo._activebookmark)
6984 bookmarks.deactivate(repo)
6981 bookmarks.deactivate(repo)
6985 elif brev in repo._bookmarks:
6982 elif brev in repo._bookmarks:
6986 bookmarks.activate(repo, brev)
6983 bookmarks.activate(repo, brev)
6987 ui.status(_("(activating bookmark %s)\n") % brev)
6984 ui.status(_("(activating bookmark %s)\n") % brev)
6988 elif brev:
6985 elif brev:
6989 if repo._activebookmark:
6986 if repo._activebookmark:
6990 ui.status(_("(leaving bookmark %s)\n") %
6987 ui.status(_("(leaving bookmark %s)\n") %
6991 repo._activebookmark)
6988 repo._activebookmark)
6992 bookmarks.deactivate(repo)
6989 bookmarks.deactivate(repo)
6993 finally:
6990 finally:
6994 wlock.release()
6991 wlock.release()
6995
6992
6996 return ret
6993 return ret
6997
6994
6998 @command('verify', [])
6995 @command('verify', [])
6999 def verify(ui, repo):
6996 def verify(ui, repo):
7000 """verify the integrity of the repository
6997 """verify the integrity of the repository
7001
6998
7002 Verify the integrity of the current repository.
6999 Verify the integrity of the current repository.
7003
7000
7004 This will perform an extensive check of the repository's
7001 This will perform an extensive check of the repository's
7005 integrity, validating the hashes and checksums of each entry in
7002 integrity, validating the hashes and checksums of each entry in
7006 the changelog, manifest, and tracked files, as well as the
7003 the changelog, manifest, and tracked files, as well as the
7007 integrity of their crosslinks and indices.
7004 integrity of their crosslinks and indices.
7008
7005
7009 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7006 Please see https://mercurial-scm.org/wiki/RepositoryCorruption
7010 for more information about recovery from corruption of the
7007 for more information about recovery from corruption of the
7011 repository.
7008 repository.
7012
7009
7013 Returns 0 on success, 1 if errors are encountered.
7010 Returns 0 on success, 1 if errors are encountered.
7014 """
7011 """
7015 return hg.verify(repo)
7012 return hg.verify(repo)
7016
7013
7017 @command('version', [], norepo=True)
7014 @command('version', [], norepo=True)
7018 def version_(ui):
7015 def version_(ui):
7019 """output version and copyright information"""
7016 """output version and copyright information"""
7020 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7017 ui.write(_("Mercurial Distributed SCM (version %s)\n")
7021 % util.version())
7018 % util.version())
7022 ui.status(_(
7019 ui.status(_(
7023 "(see https://mercurial-scm.org for more information)\n"
7020 "(see https://mercurial-scm.org for more information)\n"
7024 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7021 "\nCopyright (C) 2005-2015 Matt Mackall and others\n"
7025 "This is free software; see the source for copying conditions. "
7022 "This is free software; see the source for copying conditions. "
7026 "There is NO\nwarranty; "
7023 "There is NO\nwarranty; "
7027 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7024 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
7028 ))
7025 ))
7029
7026
7030 ui.note(_("\nEnabled extensions:\n\n"))
7027 ui.note(_("\nEnabled extensions:\n\n"))
7031 if ui.verbose:
7028 if ui.verbose:
7032 # format names and versions into columns
7029 # format names and versions into columns
7033 names = []
7030 names = []
7034 vers = []
7031 vers = []
7035 for name, module in extensions.extensions():
7032 for name, module in extensions.extensions():
7036 names.append(name)
7033 names.append(name)
7037 vers.append(extensions.moduleversion(module))
7034 vers.append(extensions.moduleversion(module))
7038 if names:
7035 if names:
7039 maxnamelen = max(len(n) for n in names)
7036 maxnamelen = max(len(n) for n in names)
7040 for i, name in enumerate(names):
7037 for i, name in enumerate(names):
7041 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
7038 ui.write(" %-*s %s\n" % (maxnamelen, name, vers[i]))
General Comments 0
You need to be logged in to leave comments. Login now